-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path.cursorrules
More file actions
123 lines (102 loc) 路 4.21 KB
/
Copy path.cursorrules
File metadata and controls
123 lines (102 loc) 路 4.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
---
description: Testing and Component Development Patterns
globs: *.tsx, *.ts, *.test.ts
alwaysApply: true
---
# Testing and Component Development Patterns
## Class Name Composition
- ALWAYS use the `cn()` utility function instead of template literals for className composition
- Import from `@/lib/utils`
- Example: `className={cn("base-class", condition && "conditional-class", variant)}`
- Never use: `className={\`base-class ${condition ? "conditional" : ""}\`}`
## Component Testing Pattern
- Components that need testing MUST accept an optional `recordingKey?: string` prop
- Apply the recordingKey as `data-recording-key={recordingKey}` on the main component element
- This enables precise test targeting even with multiple component instances
### Example Component Implementation:
```tsx
interface MyComponentProps {
data: SomeType
recordingKey?: string
}
export default function MyComponent({ data, recordingKey }: MyComponentProps) {
return (
<div className={cn("component-styles")} data-recording-key={recordingKey}>
{/* component content */}
</div>
)
}
```
## Test Page Development
- Create test pages in `src/app/tests/`
- ALWAYS wrap test page content with `<TestPageWrapper>` to prevent production deployment
- Use descriptive recordingKey values like "component-name-scenario"
### Example Test Page:
```tsx
import TestPageWrapper from "@/lib/components/TestPageWrapper"
import MyComponent from "@/lib/components/MyComponent"
export default function MyComponentTestPage() {
return (
<TestPageWrapper>
<div className="test-page-container">
<MyComponent data={testData} recordingKey="my-component-max-values" />
</div>
</TestPageWrapper>
)
}
```
## Page Object Model for Tests
- Create element classes in `tests/utils/` for reusable component testing
- Use the recordingKey pattern for element targeting
- Encapsulate all component-specific test operations in the element class
### Example Element Class:
```typescript
import { expect, type Page, type Locator } from "@playwright/test"
export class MyComponentElement {
private page: Page
private recordingKey: string
private element: Locator
constructor(page: Page, recordingKey: string) {
this.page = page
this.recordingKey = recordingKey
this.element = page.locator(`[data-recording-key="${recordingKey}"]`)
}
async waitForLoad() {
await this.page.waitForSelector(`[data-recording-key="${this.recordingKey}"]`)
}
async expectToBeVisible() {
await expect(this.element).toBeVisible()
}
async takeScreenshot(filename: string) {
await expect(this.element).toHaveScreenshot(filename)
}
}
```
## Test Implementation Guidelines
- Import element classes: `import { MyComponentElement } from "./utils/my-component-element"`
- Create element instances: `const component = new MyComponentElement(page, "recording-key")`
- Always call `waitForLoad()` before assertions
- Use descriptive test scenarios that demonstrate component behavior
- Include visual regression testing with screenshots for UI components
### Example Test:
```typescript
test("renders correctly with maximum values", async ({ page }) => {
await page.goto("/tests/my-component-max")
const component = new MyComponentElement(page, "my-component-max-values")
await component.waitForLoad()
await component.expectToBeVisible()
await component.takeScreenshot("my-component-max-values.png")
})
```
## Production Safety
- TestPageWrapper automatically prevents test pages from rendering in production
- Test pages show 404 message when NODE_ENV === "production"
- Never deploy test pages or test utilities to production builds
## Benefits of This Pattern
1. **Durable Testing**: recordingKey ensures tests target specific component instances
2. **Maintainable**: Page Object Model separates test logic from test implementation
3. **Reusable**: Element classes can be used across multiple test files
4. **Production Safe**: Test pages are automatically excluded from production
5. **Multi-instance Support**: Multiple components can be tested on the same page
6. **Consistent Styling**: cn() utility ensures proper class name merging
Always follow these patterns when creating new components and tests to maintain consistency and reliability across the codebase.