Cursor rule
.cursor/rules/e2e-rules.mdcCursor rules
Quality
89/100
Scores the file, not the repository.Length
888 words
22 headings · 7 code blocksRepository
949
— · pushed 0 days agoLast changed
3 days ago
First indexed 3 days ago.123456# Page Object Model (POM) Conventions for dotCMS E2E Tests78## Overview910This project follows the **Page Object Model (POM)** pattern for all E2E tests. This ensures maintainability, reusability, and clear separation of concerns.1112## Directory Structure1314```15src/16├── pages/ # Page Objects (one class per page)17│ ├── login.page.ts18│ ├── dashboard.page.ts19│ └── content.page.ts20├── components/ # Reusable UI components21│ ├── sideMenu.component.ts22│ ├── header.component.ts23│ └── modal.component.ts24├── tests/ # Test files that use Page Objects25│ ├── login/26│ ├── content/27│ └── navigation/28├── utils/ # Shared utilities and helpers29│ └── utils.ts30└── config/ # Configuration files31 └── environments.ts32```3334## POM Rules3536### 1. Page Objects3738- **One class per page** - Each page has its own Page Object class39- **Encapsulate all page interactions** - All `page.fill()`, `page.click()`, etc. should be in Page Objects40- **Return meaningful data** - Methods should return relevant information when needed41- **Handle environment differences** - Page Objects should adapt to different environments (dev/ci)42- **ALWAYS use data-testid selectors** - Use `page.getByTestId()` instead of `page.locator()` with CSS selectors4344### 2. Components4546- **Reusable UI elements** - Components that appear across multiple pages47- **Self-contained logic** - Each component manages its own state and interactions48- **Composable** - Components can be used within Page Objects49- **ALWAYS use data-testid selectors** - Use `page.getByTestId()` for all element interactions5051### 3. Tests5253- **Use Page Objects only** - Never interact directly with the DOM in tests54- **Descriptive test names** - Clear, readable test descriptions55- **One test per scenario** - Each test should verify one specific behavior56- **Use test data files** - Centralize test data in separate files5758## Selector Rules5960### ✅ ALWAYS Use data-testid6162```typescript63// CORRECT - Use data-testid selectors64await this.page.getByTestId("userNameInput").click();65await this.page.getByTestId("userNameInput").fill(username);66await this.page.getByTestId("password").fill(password);67await this.page.getByTestId("submitButton").click();68```6970### ❌ NEVER Use CSS selectors7172```typescript73// WRONG - Don't use CSS selectors74await this.page.locator('input[id="userId"]').fill(username);75await this.page.locator('button[id="loginButton"]').click();76await this.page.locator(".login-form input").fill(username);77```7879### Why data-testid?80811. **More stable** - Not affected by CSS class changes or styling updates822. **More specific** - Designed specifically for testing833. **Better performance** - Playwright's `getByTestId()` is optimized844. **Clearer intent** - Makes it obvious the element is for testing8586## Code Examples8788### ✅ Correct POM Implementation8990```typescript91// pages/login.page.ts92export class LoginPage {93 constructor(private page: Page) {}9495 async login(username: string, password: string): Promise<void> {96 const currentEnv = process.env["CURRENT_ENV"] || "dev";97 const loginUrl =98 currentEnv === "ci" ? "/login/" : "/dotAdmin/#/public/login";99100 await this.page.goto(loginUrl);101 await this.page.waitForLoadState();102103 // Use data-testid selectors104 await this.page.getByTestId("userNameInput").click();105 await this.page.getByTestId("userNameInput").fill(username);106 await this.page.getByTestId("userNameInput").press("Tab");107 await this.page.getByTestId("password").fill(password);108 await this.page.getByTestId("submitButton").click();109 }110111 async isLoggedIn(): Promise<boolean> {112 const currentUrl = this.page.url();113 return (114 !currentUrl.includes("/login/") && !currentUrl.includes("/public/login")115 );116 }117}118119// tests/login/login.spec.ts120test("User can login with valid credentials", async ({ page }) => {121 const loginPage = new LoginPage(page);122123 await loginPage.login("admin@dotcms.com", "admin");124125 expect(await loginPage.isLoggedIn()).toBe(true);126});127```128129### ❌ Incorrect Implementation130131```typescript132// DON'T DO THIS - Direct DOM interaction in tests133test("User can login", async ({ page }) => {134 await page.goto("/login/");135 await page.fill('input[id="userId"]', "admin@dotcms.com");136 await page.fill('input[id="password"]', "admin");137 await page.click('button[id="loginButton"]');138});139140// DON'T DO THIS - Using CSS selectors in Page Objects141export class LoginPage {142 async login(username: string, password: string) {143 await this.page.locator('input[id="userId"]').fill(username);144 await this.page.locator('input[id="password"]').fill(password);145 await this.page.locator('button[id="loginButton"]').click();146 }147}148```149150## Environment Handling151152### Page Objects should handle environment differences:153154```typescript155export class LoginPage {156 private getLoginUrl(): string {157 const currentEnv = process.env["CURRENT_ENV"] || "dev";158 return currentEnv === "ci" ? "/login/" : "/dotAdmin/#/public/login";159 }160}161```162163## Test Data Management164165### Centralize test data:166167```typescript168// tests/login/credentialsData.ts169export const validCredentials = [170 { username: "admin@dotcms.com", password: "admin" },171 { username: "test@dotcms.com", password: "test" },172];173174export const invalidCredentials = [175 { username: "wrong@dotcms.com", password: "wrong" },176];177```178179## Naming Conventions180181- **Page Objects**: `[PageName].page.ts` (e.g., `login.page.ts`)182- **Components**: `[ComponentName].component.ts` (e.g., `sideMenu.component.ts`)183- **Test Files**: `[FeatureName].spec.ts` (e.g., `login.spec.ts`)184- **Test Data**: `[FeatureName]Data.ts` (e.g., `credentialsData.ts`)185186## Best Practices1871881. **Keep Page Objects focused** - Each Page Object should handle one page only1892. **Use meaningful method names** - `login()`, `navigateToContent()`, `verifyUserIsLoggedIn()`1903. **Handle waits properly** - Use appropriate waits in Page Objects1914. **Return useful data** - Methods should return information that tests need1925. **Keep tests simple** - Tests should be easy to read and understand1936. **Use TypeScript** - Leverage type safety for better maintainability1947. **ALWAYS use data-testid** - Never use CSS selectors, always use `page.getByTestId()`195196## Migration Guidelines197198When migrating tests from Maven E2E:1992001. **Identify pages** - Create Page Objects for each page2012. **Extract components** - Identify reusable UI components2023. **Centralize data** - Move test data to dedicated files2034. **Update tests** - Refactor tests to use Page Objects2045. **Handle environments** - Ensure Page Objects work in both dev and ci modes2056. **Convert selectors** - Replace all CSS selectors with data-testid selectors206207## Using Playwright Codegen208209When using Playwright's codegen to generate tests:2102111. **Run codegen**: `npx playwright codegen http://localhost:8080/dotAdmin/#/public/login`2122. **Copy the generated selectors** - Use the `getByTestId()` calls from codegen2133. **Update Page Objects** - Replace old selectors with the new data-testid selectors2144. **Test the changes** - Verify the new selectors work correctly215216---217218**Remember**:219220- Always use Page Objects for E2E tests221- Never interact directly with the DOM in test files222- ALWAYS use `data-testid` selectors with `page.getByTestId()`223- Never use CSS selectors like `page.locator('input[id="..."]')`224
Also in dotCMS/core
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| dotCMS/core.github/copilot-instructions.md · 949 | Copilot instructions | setupbuildtestlint-format+11 | 84/100 | today | |
| dotCMS/corecore-web/apps/dotcms-ui-e2e/AGENTS.md · 949 | AGENTS.md | setupstylearchtesting-strategy+2 | 78/100 | 3 days ago | |
| dotCMS/corecore-web/apps/mcp-server/CLAUDE.md · 949 | CLAUDE.md | setupbuildtestlint-format+5 | 89/100 | 3 days ago | |
| dotCMS/core.cursor/rules/doc-updates.mdc · 949 | Cursor rules | docs | 30/100 | 3 days ago | |
| dotCMS/core.cursor/rules/dotcms-guide.mdc · 949 | Cursor rules | archdo-notdocs | 69/100 | 3 days ago | |
| dotCMS/core.cursor/rules/frontend-context.mdc · 949 | Cursor rules | teststyledocs | 78/100 | 3 days ago | |
| dotCMS/core.cursor/rules/java-context.mdc · 949 | Cursor rules | buildstyle | 44/100 | 3 days ago | |
| dotCMS/core.cursor/rules/test-context.mdc · 949 | Cursor rules | testtesting-strategy | 54/100 | 3 days ago | |
| dotCMS/core.github/instructions/frontend.instructions.md · 949 | Copilot instructions | testlint-formatstylearch+3 | 69/100 | 3 days ago | |
| dotCMS/coreCLAUDE.md · 949 | CLAUDE.md | setupbuildteststyle+7 | 99/100 | today | |
| dotCMS/corecore-web/AGENTS.md · 949 | AGENTS.md | style | 63/100 | 3 days ago | |
| dotCMS/corecore-web/CLAUDE.md · 949 | CLAUDE.md | teststylearchtesting-strategy+3 | 100/100 | 3 days ago | |
| dotCMS/corecore-web/apps/dotcms-ui/AGENTS.md · 949 | AGENTS.md | buildteststyledependencies+3 | 94/100 | 3 days ago | |
| dotCMS/corecore-web/libs/block-editor/CLAUDE.md · 949 | CLAUDE.md | archdo-not | 69/100 | 3 days ago | |
| dotCMS/corecore-web/libs/new-block-editor/CLAUDE.md · 949 | CLAUDE.md | lint-formatstyledo-notagent-behaviour | 61/100 | 3 days ago | |
| dotCMS/corecore-web/libs/portlets/CLAUDE.md · 949 | CLAUDE.md | setupteststyleui+1 | 77/100 | 3 days ago | |
| dotCMS/corecore-web/libs/portlets/edit-ema/portlet/src/lib/store/CLAUDE.md · 949 | CLAUDE.md | teststylearchtypes+2 | 65/100 | 3 days ago | |
| dotCMS/corecore-web/libs/sdk/client/CLAUDE.md · 949 | CLAUDE.md | setupbuildtestlint-format+9 | 97/100 | 3 days ago | |
| dotCMS/corecore-web/libs/sdk/react/CLAUDE.md · 949 | CLAUDE.md | setupbuildtestlint-format+9 | 97/100 | 3 days ago | |
| dotCMS/coredotCMS/src/main/java/com/dotcms/rest/CLAUDE.md · 949 | CLAUDE.md | typesdatabaseapido-not+1 | 57/100 | 3 days ago |
Diff against .github/copilot-instructions.md Diff against core-web/apps/dotcms-ui-e2e/AGENTS.md Diff against core-web/apps/mcp-server/CLAUDE.md Diff against .cursor/rules/doc-updates.mdc Diff against .cursor/rules/dotcms-guide.mdc Diff against .cursor/rules/frontend-context.mdc Diff against .cursor/rules/java-context.mdc Diff against .cursor/rules/test-context.mdc Diff against .github/instructions/frontend.instructions.md Diff against CLAUDE.md Diff against core-web/AGENTS.md Diff against core-web/CLAUDE.md Diff against core-web/apps/dotcms-ui/AGENTS.md Diff against core-web/libs/block-editor/CLAUDE.md Diff against core-web/libs/new-block-editor/CLAUDE.md Diff against core-web/libs/portlets/CLAUDE.md Diff against core-web/libs/portlets/edit-ema/portlet/src/lib/store/CLAUDE.md Diff against core-web/libs/sdk/client/CLAUDE.md Diff against core-web/libs/sdk/react/CLAUDE.md Diff against dotCMS/src/main/java/com/dotcms/rest/CLAUDE.md
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 3 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 3 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 3 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 3 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 3 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 3 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 3 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 3 days ago |
