Skip to content

Add end-to-end testing with Playwright and TypeScript and developer CLI command #749

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 165 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
165 commits
Select commit Hold shift + click to select a range
97012dd
Update background colors for dark mode to match Figma design
tjementum May 13, 2025
45a59d4
Update background colors for input fields in dark mode to match Figma…
tjementum May 13, 2025
27b8c1e
Table hover dark mode - light mode broken
tjementum May 13, 2025
6a76b44
Fix bug preventing dark mode activation when OS is in light mode
tjementum May 22, 2025
6a9fb6e
Change name of local storage variable for "preferred-theme" to kebab-…
tjementum May 22, 2025
b4642e7
Introduce 3-state theme button switching between system, dark, and li…
tjementum May 22, 2025
6b7413e
Show correct tooltip when toggling through the tristate theme selector
tjementum Jun 18, 2025
3df2818
Adjust styling of colors in dark mode for delete and toasts messages
tjementum Jun 19, 2025
5b6f6c3
Remove transition form badges on home page dashboard
tjementum Jun 19, 2025
c061ce6
Fix colors on landing page
tjementum Jun 24, 2025
b6ebfcf
Update styling for light mode to match Figma design
tjementum Jun 20, 2025
89dc705
Create Tailwind styles for H1 and subheadings
tjementum Jun 22, 2025
ee1d7e7
Format dialogs
tjementum Jun 14, 2025
2e0b56c
Make side menu overlay on medium screens and fix top and side menus d…
tjementum Jun 18, 2025
c7da7e9
Fix a lot of issue with the overlay and new side menu
tjementum Jun 18, 2025
e213d34
Fix mobile menu
tjementum Jun 18, 2025
c3f6d0c
Change icon for local switcher and add tooltip to top menu
tjementum Jun 20, 2025
d65ab5e
Make modal dialogs scrollable when content exceeds viewport height
tjementum Jun 20, 2025
7b112d5
Add responsive ContentLayout with centered content that adapts to Sid…
tjementum Jun 20, 2025
0625095
Show custom placeholder text in date range picker when no dates are s…
tjementum Jun 21, 2025
022d096
Update Account page to use ContentLayout for centering on large scree…
tjementum Jun 20, 2025
8d26761
Delete ContentLayout and update AppLayout to allow centered content
tjementum Jun 22, 2025
72976a5
Move togglebar and home icon slightly up after changing AppLayout
tjementum Jun 22, 2025
0e722ea
Show user filters in dialog on small screens
tjementum Jun 22, 2025
badb248
Add visual indicators for active menu items in SideMenu
tjementum Jun 22, 2025
25daa3a
Fix animation of side menu
tjementum Jun 22, 2025
da47c10
Fix padding between sidemenu and content to use margin of side menu i…
tjementum Jun 22, 2025
12799c0
Fix frontend build
tjementum Jun 22, 2025
62e1298
Fix position of side menu icons and focus border
tjementum Jun 22, 2025
ecc3c99
Fix size and responsive layout of cards on dashboard
tjementum Jun 23, 2025
66a76e9
Add personalized welcome message to admin home page
tjementum Jun 21, 2025
6e24464
Reduce padding in mobile device dialogs
tjementum Jun 23, 2025
b659ed4
Make mobile side menu full screen and close when clicking active menu…
tjementum Jun 23, 2025
a367512
Make logo mark for activating side menu larger on mobile devices
tjementum Jun 23, 2025
e354c1d
Create mobile menu for improved navigation
tjementum Jun 24, 2025
987709e
Make pagination on user table stick to the bottom of the screen
tjementum Jun 22, 2025
d51af97
Update user-related error messages for clarity and consistency across…
tjementum Jun 14, 2025
f80c1a0
Move check for unique email from validation to command handler to fol…
tjementum Jun 13, 2025
5d60695
Remove FormErrorMessage now handled by toast
tjementum Jun 13, 2025
109602d
Streamline input validation messages and avoid using built-in validat…
tjementum Jun 13, 2025
79391ba
Fix description in invitation dialog to match behavior
tjementum Jun 13, 2025
e7a96bd
Add option for icon in Input and TextFields and include isDisable and…
tjementum Jun 20, 2025
5bb4d28
Remove email from UpdateCurrentUserCommand and disable email TextFiel…
tjementum Jun 20, 2025
d37d32f
Remove comma after e.g. in placeholder text
tjementum Jun 22, 2025
5b9d479
Show toast when changing user role
tjementum Jun 10, 2025
5e26098
Show toast notification when deleting user(s)
tjementum Jun 10, 2025
fb0ba70
Move toasts to the upper right corner to improve visibility and ensur…
tjementum Jun 14, 2025
34d1f41
Add toasts for user invitations, profile updates, and account informa…
tjementum Jun 6, 2025
55970ed
Add toasts for user invitations, profile updates, and account informa…
tjementum Jun 6, 2025
c123730
Enable submit of user search by pressing Enter
tjementum Jun 8, 2025
da65ae3
Rename label of user actions in user row from "Menu“ to "User actions"
tjementum Jun 10, 2025
1f7ed8b
Ensure UI state updates on user management when deleting users
tjementum Jun 15, 2025
c94edad
Change filter icon to list filter for improved user list filtering
tjementum Jun 22, 2025
2dd4a74
Rename Invite users button to Invite user
tjementum Jun 24, 2025
1dadb69
Improve login/signup state management by adding clear/has state funct…
tjementum May 29, 2025
d230d5b
Update login to return 400 bad request instead of 404 not found for u…
tjementum Jun 4, 2025
aef26dd
Disable one-time password until filled out and auto-focus on failed a…
tjementum Jun 8, 2025
2bb99c3
Add toast message when one time password is resend
tjementum Jun 10, 2025
562c016
Auto-submit one-time verification code on signup and login
tjementum Jun 11, 2025
3556cf1
Streamline resend and code expiration in signup flow
tjementum Jun 12, 2025
2bb3642
Streamline resend and code expiration in login flow
tjementum Jun 13, 2025
4b370e6
Change locked out time for too many login attempts from 1 day to 15 m…
tjementum Jun 13, 2025
8d2274b
Change login attempt limit from daily to 15 minutes
tjementum Jun 13, 2025
826c6ab
Change email confirmation attempts for signup from 15 to 60 minutes
tjementum Jun 13, 2025
e71e312
Remove check disallowing multiple active email confirmations and rely…
tjementum Jun 13, 2025
88d21db
Update Powered By logo on signup and login pages and optimize Danish …
tjementum Jun 15, 2025
784a475
Prefill email address when navigating between signin and signup pages
tjementum Jun 23, 2025
1f58aec
Create end-to-end developer CLI command for running Playwright tests …
tjementum Jun 27, 2025
1a4b7dd
Add AI rules for using e2e developer CLI command test regression duri…
tjementum Jun 27, 2025
e0e3946
Fix bug in GitHelper.GetChangedFiles() in Developer CLI for deleted f…
tjementum Jun 12, 2025
550e5d9
Fix flaky AvatarButton loading issues with module federation
tjementum May 29, 2025
f714ca3
Add CLAUDE.md files
tjementum Jun 6, 2025
a102904
Create End2EndTests project structure and add to solution
tjementum May 26, 2025
58c61b2
Add Playwright End2EndTests project with complete configuration
tjementum May 26, 2025
0a4f633
Add VS Code IDE integration for Playwright End2EndTests
tjementum May 26, 2025
19497cd
Add test utilities for E2E testing with centralized base URL and moni…
tjementum May 26, 2025
d2335ca
Create comprehensive E2E tests for signup flow including edge cases l…
tjementum May 27, 2025
9e0355a
Add comprehensive AI workflow for creating end-to-end tests
tjementum May 26, 2025
b18106b
Add AI rule for creating end-to-end tests
tjementum May 28, 2025
57c1fa2
Create comprehensive E2E tests for login flow including edge cases li…
tjementum May 29, 2025
ed1f388
Add test for back office
tjementum May 29, 2025
d2777dc
Move e2e test utilities to shared-webapp with failing tests
tjementum May 31, 2025
2be3249
Move e2e tests into self-contained systems and delete End2EndTests pr…
tjementum May 31, 2025
7910ec4
Configure separate build for e2e tests to avoid hot reload and WebApp…
tjementum Jun 1, 2025
f4350d8
Change Windows to use max 4 workers for end-to-end tests
tjementum Jun 6, 2025
931739b
Disable SSL certificate check for webkit on Windows
tjementum Jun 6, 2025
a6e6f13
Add guidelines for reviewing End-to-End Tests and Developer CLI comma…
tjementum Jun 4, 2025
a3901a2
Add authentication types and utilities for e2e test fixtures
tjementum Jun 4, 2025
13fad44
Add worker-scoped authentication fixtures for parallel e2e testing
tjementum Jun 5, 2025
1c8ea34
Implement worker-scoped authentication fixtures and tenant management…
tjementum Jun 5, 2025
1f0d449
Change e2e tests to use new shared infrastructure to reuse existing t…
tjementum Jun 5, 2025
4507b23
Add new unauthenticatedPageWithTenant page
tjementum Jun 5, 2025
13ac835
Update
tjementum Jun 5, 2025
c50b374
Implement ensureTenantUsersExist to enable clean test setup with tena…
tjementum Jun 6, 2025
6bbdc8a
Update e2e foundation with owner, admin, and member user for each ten…
tjementum Jun 6, 2025
384eba1
Update login tests to use owner, admin, member objects
tjementum Jun 6, 2025
5981117
Refactor E2E tests to utilize shared authentication and utility paths…
tjementum Jun 6, 2025
703fa6c
Remove unused e2e test infrastructure to simplify codebase
tjementum Jun 6, 2025
5eee178
Change email addresses to follow conventions
tjementum Jun 6, 2025
24a34d0
More cleanup
tjementum Jun 6, 2025
93e4f40
Change location of end-2-end tests results
tjementum Jun 6, 2025
775e5c7
Update e2e rules files to reflect separate smoke.spec.ts file per sel…
tjementum Jun 6, 2025
96aa099
Create smoke tests for account management
tjementum Jun 6, 2025
7485e46
Update smoke tests
tjementum Jun 7, 2025
75d38a2
Optimize tests
tjementum Jun 7, 2025
6721dd9
Clean up tests
tjementum Jun 7, 2025
1200046
More cleanup
tjementum Jun 7, 2025
9c00717
More fixing tests
tjementum Jun 7, 2025
3694edf
Set correct configuration for play-wright configuration output
tjementum Jun 7, 2025
19b8c93
Fix WebKit issue
tjementum Jun 7, 2025
7dd7062
Optimize test and let them pass
tjementum Jun 7, 2025
d91ec92
Make smoke tests and selection of one-time password field stable
tjementum Jun 8, 2025
64728e3
Change timeout for big smoke tests to accommodate comprehensive testing
tjementum Jun 8, 2025
c2e1b8e
Add default timeout of 5 seconds for page operations in authenticatio…
tjementum Jun 8, 2025
a61e3f1
Integrate smoke tests from login and signup into main smoke test to i…
tjementum Jun 8, 2025
e397b76
Update rules files with new // Act & Assert commetns
tjementum Jun 8, 2025
8d913dd
Cleanup duplicated tests in comprehensive that are already covered in…
tjementum Jun 8, 2025
f7395cb
Move assertNoUnexpectedErrors to global afterEach test to ensure unex…
tjementum Jun 8, 2025
0122221
Clean up tests
tjementum Jun 8, 2025
f4ad14d
Update user search tests
tjementum Jun 8, 2025
7bec3d2
Stream line e2e tests
tjementum Jun 8, 2025
cac3646
Update Playwright configuration to run smoke tests first and set acti…
tjementum Jun 10, 2025
f33160a
Update e2e tests
tjementum Jun 10, 2025
0ab858e
Move logic for installing Playwright browsers from npm to e2e CLI
tjementum Jun 10, 2025
458251e
Add toast message when one time password is resend
tjementum Jun 10, 2025
0035844
Remove logic to filter tracking errors and hardcoded localhost HTTP a…
tjementum Jun 10, 2025
c5eb5ce
Fix any type in tests
tjementum Jun 10, 2025
6a1dcf0
Extract localization flows form big smoke test to separate e2e tests
tjementum Jun 11, 2025
ad93ac9
Update e2e-tests AI rules
tjementum Jun 11, 2025
d4e2c30
Split smoke tests into focused and dedicated e2e test flows
tjementum Jun 11, 2025
6ba1919
Update shared Playwright.config.ts and e2e CLI to allow filtering of …
tjementum Jun 11, 2025
1788832
Update to login and signup flows... maybe not working
tjementum Jun 11, 2025
2b5bccf
Update e2e to account for auto-submit of one-time verification code
tjementum Jun 11, 2025
7be7844
Change signup e2e tests
tjementum Jun 12, 2025
9b74b23
Change login e2e tests
tjementum Jun 13, 2025
15f5609
Fix back-office tests
tjementum Jun 13, 2025
84c97ed
Update e2e tests for new validation rules
tjementum Jun 13, 2025
79ead17
Change test-assertion to avoid hardcoded HTTP status codes
tjementum Jun 13, 2025
5b739e4
Update end-to-end tests to use http error codes instead of titels
tjementum Jun 13, 2025
a50b3aa
Add e2e test for bulk deletion in comprehensive test and include test…
tjementum Jun 14, 2025
addbef9
Double timeout for slow-mo tests
tjementum Jun 14, 2025
9cc30ba
Fix bug with double assertion in signup and login flow
tjementum Jun 14, 2025
c097c6a
Clean up test assertion and auto-close toast to remove overlay blocki…
tjementum Jun 14, 2025
8b232d1
Add step decorators for Playwright E2E test maintainability
tjementum Jun 14, 2025
28d26c5
Enhance step decorator timing thresholds and CLI integration
tjementum Jun 14, 2025
475af29
Add sample test using new infrastructure
tjementum Jun 14, 2025
47bc71f
Remove background polling for toasts to improve test speed and enhanc…
tjementum Jun 14, 2025
31e142f
Change all e2e test to use new step decorator
tjementum Jun 14, 2025
5ac06fd
Rename all tests and add line breaks between act and assert statements
tjementum Jun 14, 2025
403d74b
Remove names of e2e test flows to elevate @smoke, @comprehensive, and…
tjementum Jun 14, 2025
08d410c
Update e2e-tests AI rules to match new infrastructure and conventions
tjementum Jun 15, 2025
df6c409
Update user flow test to include single and bulk deletion of users
tjementum Jun 15, 2025
b5bbb0c
Update test assertion to fail when toast are hanging
tjementum Jun 15, 2025
014a255
Add end-to-end flows for deleting users
tjementum Jun 15, 2025
8589c9b
Rename assertToastMessage/assertValidationError/assertNetworkErrors t…
tjementum Jun 15, 2025
0b71882
Update e2e-tests with new naming of expect utilities
tjementum Jun 15, 2025
6b34c61
Add guidance to e2e-test about location
tjementum Jun 15, 2025
2b71887
Add tests for bulk eletion
tjementum Jun 15, 2025
b6c4f72
Update step-decorated to prevent failure on slow test when running wi…
tjementum Jun 15, 2025
06bfbc9
Update user management test to click on invited user filter
tjementum Jun 15, 2025
2c0ccf3
Add e2e tests for filtering users by date, state, and role
tjementum Jun 15, 2025
1124633
Rename back-office tests
tjementum Jun 18, 2025
607bdb0
Simplify user management flows to reduce menu clicks and focus on the…
tjementum Jun 19, 2025
849a68c
Rename Invite users button to Invite user
tjementum Jun 24, 2025
f45071b
Fix end-to-end tests
tjementum Jun 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .cursor/rules/backend/commands.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ public sealed class CreateUserValidator : AbstractValidator<CreateUserCommand>
public CreateUserValidator()
{
// ✅ DO: Use the same message for better user experience and easier localization
RuleFor(x => x.Name)
.NotEmpty().WithMessage("Name must be between 1 and 50 characters.")
.MaximumLength(50).WithMessage("Name must be between 1 and 50 characters.");
RuleFor(x => x.Name).Length(1, 50).WithMessage("Name must be between 1 and 50 characters.");
}
}

Expand Down Expand Up @@ -98,7 +96,7 @@ public sealed class CreateUserValidator : AbstractValidator<CreateUserCommand>
{
public CreateUserValidator()
{
// ❌ DON'T: Use different validation messages for the same property
// ❌ DON'T: Use different validation messages for the same property and redundant validation rules
RuleFor(x => x.Name)
.NotEmpty().WithMessage("Name must not be empty.")
.MaximumLength(50).WithMessage("Name must not be more than 50 characters.");
Expand Down
262 changes: 262 additions & 0 deletions .cursor/rules/end-to-end-tests/e2e-tests.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
---
description: Rules for end-to-end tests
globs: */tests/e2e/**
alwaysApply: false
---
# End-to-End Tests

These rules outline the structure, patterns, and best practices for writing end-to-end tests.

## Implementation

1. Use `[CLI_ALIAS] e2e` with these option categories to optimize test execution:
- Test filtering: `--smoke`, `--include-slow`, search terms (e.g., `"@smoke"`, `"smoke"`, `"user"`, `"localization"`), `--browser`
- Change scoping: `--last-failed`, `--only-changed`
- Flaky test detection: `--repeat-each`, `--retries`, `--stop-on-first-failure`
- Performance: `--debug-timings` shows step execution times with color coding

2. Test Search and Filtering:
- Search by test tags: `[CLI_ALIAS] e2e "@smoke"` or `[CLI_ALIAS] e2e "smoke"` (both work the same)
- Search by test content: `[CLI_ALIAS] e2e "user"` (finds tests with "user" in title or content)
- Search by filename: `[CLI_ALIAS] e2e "localization"` (finds localization-flows.spec.ts)
- Search by specific file: `[CLI_ALIAS] e2e "user-management-flows.spec.ts"`
- Multiple search terms: `[CLI_ALIAS] e2e "user" "management"`
- The CLI automatically detects which self-contained systems contain matching tests and only runs those

3. Test-Driven Debugging Process:
- Focus on one failing test at a time and make it pass before moving to the next.
- Ensure tests use Playwright's built-in auto-waiting assertions: `toHaveURL()`, `toBeVisible()`, `toBeEnabled()`, `toHaveValue()`, `toContainText()`.
- Consider if root causes can be fixed in the application code, and fix application bugs rather than masking them with test workarounds.

4. Organize tests in a consistent file structure:
- All e2e test files must be located in `[self-contained-system]/WebApp/tests/e2e/` folder (e.g., `application/account-management/WebApp/tests/e2e/`).
- All test files use the `*-flows.spec.ts` naming convention (e.g., `login-flows.spec.ts`, `signup-flows.spec.ts`, `user-management-flows.spec.ts`).
- Top-level describe blocks must use only these 3 approved tags: `test.describe("@smoke", () => {})`, `test.describe("@comprehensive", () => {})`, `test.describe("@slow", () => {})`.
- `@smoke` tests:
- Critical tests run on deployment of any self-contained system.
- Should be comprehensive scenarios that test core user journeys.
- Keep tests focused on specific flows to reduce fragility while maintaining coverage.
- Focus on must-work functionality with extensive validation steps.
- Include boundary cases and error handling within the same test scenario.
- Avoid testing the same functionality multiple times across different tests.

- `@comprehensive` tests:
- Thorough tests run when a specific self-contained system is deployed.
- Focus on edge cases, error conditions, and less common scenarios.
- Test specific features in depth with various input combinations.
- Include tests for concurrency, validation rules, accessibility, etc.
- Group related edge cases together to reduce test count while maintaining coverage.

- `@slow` tests:
- Optional and run only ad-hoc using `--include-slow` flag.
- Any tests that require waiting like `waitForTimeout` (e.g., for OTP timeouts) must be marked as `@slow`.
- Include tests for rate limiting with actual wait times, session timeouts, etc.
- Use `test.setTimeout()` at the individual test level based on actual wait times needed.

5. Write clear test descriptions and documentation:
- Test descriptions must accurately reflect what the test covers and be kept in sync with test implementation.
- Use descriptive test names that clearly indicate the functionality being tested (e.g., "should handle single and bulk user deletion workflows with dashboard integration").
- Include JSDoc comments above complex tests listing all major features/scenarios covered.
- When adding new functionality to existing tests, update both the test description and JSDoc comments to reflect changes.

6. Structure each test with step decorators and proper monitoring:
- All tests must start with `const context = createTestContext(page);` for proper error monitoring.
- Use step decorators: `await step("Complete signup & verify account creation")(async () => { /* test logic */ })();`
- Step naming conventions:
- Always follow "[Business action + details] & [expected outcome]" pattern.
- Use business action verbs like "Sign up", "Login", "Invite", "Rename", "Update", "Delete", "Create", "Submit".
- Never use test/assertion prefixes like "Test", "Verify", "Check", "Validate", "Ensure"; use descriptive business actions instead.
- Every step must include an action (arrange/act) followed by assertions, not pure assertion steps.
- Step structure:
- Use blank lines to separate arrange/act/assert sections within steps.
- Keep shared variable declarations outside steps when used across multiple steps.
- Use section headers with `// === SECTION NAME ===` to group related steps.
- Add JSDoc comments for complex test workflows.
- Use semantic selectors: `page.getByRole("button", { name: "Submit" })`, `page.getByText("Welcome")`, `page.getByLabel("Email")`.
- Assert side effects immediately after actions using `expectToastMessage`, `expectValidationError`, `expectNetworkErrors`.
- Form validation pattern: Use `await blurActiveElement(page);` when updating a textbox the second time before submitting a form to trigger validation.

7. Timeout Configuration:
- Always use Playwright's built-in auto-waiting assertions: `toHaveURL()`, `toBeVisible()`, `toBeEnabled()`, `toHaveValue()`, `toContainText()`.
- Never add timeouts to `.click()`, `.waitForSelector()`, etc.
- Global timeout configuration is handled in the shared Playwright. Don't change this.

8. Write deterministic tests - This is critical for reliable testing:
- Each test should have a clear, linear flow of actions and assertions.
- Never use if statements, custom error handling, or try/catch blocks in tests.
- Never use regular expressions in tests; use simple string matching instead.

9. What to test:
- Enter invalid values, such as empty strings, only whitespace characters, long strings, negative numbers, Unicode, etc.
- Tooltips, keyboard navigation, accessibility, validation messages, translations, responsiveness, etc.

10. Test Fixtures and Page Management:
- Use appropriate fixtures: `{ page }` for basic tests, `{ anonymousPage }` for tests with existing tenant/owner but not logged in, `{ ownerPage }`, `{ adminPage }`, `{ memberPage }` for authenticated tests.
- Destructure anonymous page data: `const { page, tenant } = anonymousPage; const existingUser = tenant.owner;`
- Pre-logged in users (`ownerPage`, `adminPage`, `memberPage`) are isolated between workers and will not conflict between tests.
- When using pre-logged in users, do not put the tenant or user into an invalid state that could affect other tests.

11. Test Data and Constants:
- Use underscore separators: `const timeout = 30_000; // 30 seconds`
- Generate unique data: `const email = uniqueEmail();`
- Use faker.js to generate realistic test data: `const firstName = faker.person.firstName(); const email = faker.internet.email();`
- Long string testing: `const longEmail = \`${"a".repeat(90)}@example.com\`; // 101 characters total`

12. Memory Management in E2E Tests:
- Playwright automatically handles browser context cleanup after tests
- Manual cleanup steps are unnecessary - focus on test clarity over micro-optimizations
- E2E test suites have minimal memory leak concerns due to their limited scope and duration

## Examples

### ✅ Good Step Naming Examples
```typescript
// ✅ DO: Business action + details & expected outcome
await step("Submit invalid email & verify validation error")(async () => {
await page.getByLabel("Email").fill("invalid-email");
await blurActiveElement(page);

await expectValidationError(context, "Invalid email.");
})();

await step("Sign up with valid credentials & verify account creation")(async () => {
await page.getByRole("button", { name: "Submit" }).click();

await expect(page.getByText("Welcome")).toBeVisible();
})();

await step("Update user role to admin & verify permission change")(async () => {
const userRow = page.locator("tbody tr").first();

await userRow.getByLabel("User actions").click();
await page.getByRole("menuitem", { name: "Change role" }).click();

await expect(page.getByRole("alertdialog", { name: "Change user role" })).toBeVisible();
})();
```

### ❌ Bad Step Naming Examples
```typescript
// ❌ DON'T: Pure assertion steps without actions
await step("Verify button is visible")(async () => {
await expect(page.getByRole("button")).toBeVisible(); // No action, only assertion
})();

// ❌ DON'T: Using test/assertion prefixes
await step("Check user permissions")(async () => { // "Check" is assertion prefix
await expect(page.getByText("Admin")).toBeVisible();
})();

await step("Validate form state")(async () => { // "Validate" is assertion prefix
await expect(page.getByRole("textbox")).toBeEmpty();
})();

await step("Ensure user is deleted")(async () => { // "Ensure" is assertion prefix
await expect(page.getByText("[email protected]")).not.toBeVisible();
})();
```

### ✅ Complete Test Example
```typescript
import { step } from "@shared/e2e/utils/step-decorator";
import { expectValidationError, blurActiveElement, createTestContext } from "@shared/e2e/utils/test-assertions";
import { testUser } from "@shared/e2e/utils/test-data";

test.describe("@smoke", () => {
test("should complete signup with validation", async ({ page }) => {
const context = createTestContext(page);
const user = testUser();

await step("Submit invalid email & verify validation error")(async () => {
await page.goto("/signup");
await page.getByLabel("Email").fill("invalid-email");
await blurActiveElement(page); // ✅ DO: Trigger validation when updating textbox second time

await expectValidationError(context, "Invalid email.");
})();

await step("Sign up with valid email & verify verification redirect")(async () => {
await page.getByLabel("Email").fill(user.email);
await page.getByRole("button", { name: "Continue" }).click();

await expect(page).toHaveURL("/verify");
})();
});
});

test.describe("@comprehensive", () => {
test("should handle user management with pre-logged owner", async ({ ownerPage }) => {
createTestContext(ownerPage); // ✅ DO: Create context for pre-logged users

await step("Access user management & verify owner permissions")(async () => {
await ownerPage.getByRole("button", { name: "Users" }).click();

await expect(ownerPage.getByRole("heading", { name: "Users" })).toBeVisible();
})();
});
});

test.describe("@slow", () => {
const requestNewCodeTimeout = 30_000; // 30 seconds
const codeValidationTimeout = 60_000; // 5 minutes
const sessionTimeout = codeValidationTimeout + 60_000; // 6 minutes

test("should handle user logout after to many login attempts", async ({ page }) => { // ✅ DO: use new page, when testing e.g. account lockout
test.setTimeout(sessionTimeout); // ✅ DO: Set timeout based on actual wait times
const context = createTestContext(page);

// ...

await step("Wait for code expiration & verify timeout behavior")(async () => {
await page.goto("/login/verify");
await page.waitForTimeout(codeValidationTimeout); // ✅ DO: Use actual waits in @slow tests

await expect(page.getByText("Your verification code has expired")).toBeVisible();
})();
});
});
```

```typescript
test.describe("@security", () => { // ❌ DON'T: Don't invent new tags - use @smoke, @comprehensive, @slow only
test("should handle login", async ({ page }) => {
// ❌ DON'T: Skip createTestContext(page); step
page.setDefaultTimeout(5000); // ❌ DON'T: Set timeouts manually - use global config

// ❌ DON'T: Use test/assertion prefixes in step descriptions
await step("Test login functionality")(async () => { // ❌ Should be "Submit login form & verify authentication"
await step("Verify button is visible")(async () => { // ❌ Should be "Navigate to page & verify button is visible"
await step("Check user permissions")(async () => { // ❌ Should be "Click user menu & verify permissions"
if (page.url().includes("/login/verify")) { // ❌ DON'T: Add conditional logic - tests should be linear
await page.waitForTimeout(2000); // ❌ DON'T: Add manual timeouts
// Continue with verification... // ❌ DON'T: Write verbose explanatory comments
}

await page.click("#submit-btn"); // ❌ DON'T: Use CSS selectors - use semantic selectors

// ❌ DON'T: Skip assertions for side effects
})();

// ❌ DON'T: Use regular expressions - use simple string matching instead
await expect(page.getByText(/welcome.*home/i)).toBeVisible(); // ❌ Should be: page.getByText("Welcome home")
await expect(page.locator('input[name*="email"]')).toBeFocused(); // ❌ Should be: page.getByLabel("Email")
});

// ❌ DON'T: Place assertions outside test functions
expect(page.url().includes("/admin") || page.url().includes("/login")).toBeTruthy(); // ❌ DON'T: Use ambiguous assertions

// ❌ DON'T: Use try/catch to handle flaky behavior - makes tests unreliable
try {
await page.waitForLoadState("networkidle"); // ❌ DON'T: Add timeout logic in tests
await page.getByRole("button", { name: "Submit" }).click({ timeout: 1000 }); // ❌ DON'T: Add timeouts to actions
} catch (error) {
await page.waitForTimeout(1000); // ❌ DON'T: Add manual waits
console.log("Retrying..."); // ❌ DON'T: Add custom error handling
}
});

// ❌ DON'T: Create tests without proper organization
test("isolated test without describe block", async ({ page }) => {
// ❌ DON'T: Violates organization rules
});
```
27 changes: 26 additions & 1 deletion .cursor/rules/tools.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ alwaysApply: true
* BrowserMCP: Use this to troubleshoot frontend issues. The base URL is https://localhost:9000. The website is already running, so never start it manually.
* `[PRODUCT_MANAGEMENT_TOOL]`: Use this MCP tool to create and manage product backlog items.

If an MCP Server is not responding, instruct the user to activate it rather than using workarounds like calling `curl` when the browser MCP is unavailable.

# Product Management Tools

> **Update this value in ONE place:**
Expand All @@ -25,7 +27,7 @@ Use the `[CLI_ALIAS]` Developer CLI to build, test, and format backend and front

Always use the Developer CLI to build, test, and format code correctly over using direct commands like `npm run format` or `dotnet test`.

**IMPORTANT:** Never fall back to using direct commands like `npm run format` or `dotnet test`. Always use the Developer CLI with the appropriate alias.
**IMPORTANT:** Never fall back to using direct commands like `npm run format`, `dotnet test`, `npx playwright test`, `npm test`, etc. Always use the Developer CLI with the appropriate alias.

## CLI Alias Configuration

Expand Down Expand Up @@ -67,6 +69,29 @@ After you have completed a backend task and want to ensure that it works as expe
[CLI_ALIAS] test --solution-name <solution-name>
```

## End-to-End Test Commands

```bash
# Run all end-to-end tests except slow tests
[CLI_ALIAS] e2e

# Run end-to-end tests for specific so lution
[CLI_ALIAS] e2e --self-contained-system <self-contained-system-name>

# Run end-to-end tests for specific browser
[CLI_ALIAS] e2e --browser <browser-name>

# Run end-to-end tests for specific search term
[CLI_ALIAS] e2e <search-term>

# Run end-to-end tests for specific test tags
[CLI_ALIAS] e2e "@smoke"
[CLI_ALIAS] e2e "smoke"
[CLI_ALIAS] e2e "@comprehensive"
```

Any combination of the above parameters is possible. There are other parameters available, but you should only use the ones mentioned above.

## Format Commands

Run these commands before you commit your changes.
Expand Down
Loading
Loading