|
1 | | ---- |
2 | | -alwaysApply: true |
3 | | ---- |
| 1 | +# ESLint Plugin Playwright - Agent Guidelines |
4 | 2 |
|
5 | | -## Pull Requests |
| 3 | +## Project Overview |
6 | 4 |
|
7 | | -- When creating pull requests, add the `cursor` label to the pull request. |
| 5 | +This is a comprehensive ESLint plugin for Playwright testing that provides 50+ |
| 6 | +rules to enforce best practices and catch common issues in Playwright test code. |
| 7 | +The plugin is built with TypeScript, uses modern ESLint APIs, and follows strict |
| 8 | +testing practices. |
8 | 9 |
|
9 | | -## Commits |
| 10 | +## Architecture & Code Structure |
| 11 | + |
| 12 | +### Core Architecture |
| 13 | + |
| 14 | +- **Entry Point**: `src/index.ts` - Exports all rules and configurations |
| 15 | +- **Rule Structure**: Each rule follows the pattern `src/rules/{rule-name}.ts` |
| 16 | + with corresponding tests |
| 17 | +- **Utilities**: Shared utilities in `src/utils/` for AST manipulation, parsing, |
| 18 | + and common patterns |
| 19 | +- **Configurations**: Supports both flat config (ESLint 9+) and legacy config |
| 20 | + formats |
| 21 | + |
| 22 | +### Key Patterns & Conventions |
| 23 | + |
| 24 | +#### Rule Implementation Pattern |
| 25 | + |
| 26 | +```typescript |
| 27 | +import { createRule } from '../utils/createRule.js' |
| 28 | +import { parseFnCall } from '../utils/parseFnCall.js' |
| 29 | +// ... other imports |
| 30 | + |
| 31 | +export default createRule({ |
| 32 | + create(context) { |
| 33 | + // Rule logic here |
| 34 | + return { |
| 35 | + CallExpression(node) { |
| 36 | + const call = parseFnCall(context, node) |
| 37 | + if (call?.type !== 'expect') return |
| 38 | + // Rule-specific logic |
| 39 | + } |
| 40 | + } |
| 41 | + }, |
| 42 | + meta: { |
| 43 | + docs: { |
| 44 | + category: 'Best Practices', |
| 45 | + description: 'Rule description', |
| 46 | + recommended: true, |
| 47 | + url: 'https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/{rule-name}.md', |
| 48 | + }, |
| 49 | + messages: { |
| 50 | + messageId: 'Message text with {{ interpolation }}', |
| 51 | + }, |
| 52 | + schema: [/* JSON schema for options */], |
| 53 | + type: 'problem' | 'suggestion', |
| 54 | + fixable?: 'code' | 'whitespace', |
| 55 | + }, |
| 56 | +}) |
| 57 | +``` |
| 58 | + |
| 59 | +#### AST Utilities & Patterns |
| 60 | + |
| 61 | +- **`parseFnCall`**: Core utility for parsing Playwright function calls (test, |
| 62 | + expect, describe, etc.) |
| 63 | +- **`createRule`**: Wrapper that handles custom message interpolation and |
| 64 | + context modification |
| 65 | +- **AST Helpers**: `getStringValue`, `isIdentifier`, `findParent`, `dereference` |
| 66 | + for node manipulation |
| 67 | +- **Type Safety**: Extensive TypeScript types for AST nodes with parent |
| 68 | + extensions |
| 69 | + |
| 70 | +#### Testing Pattern |
| 71 | + |
| 72 | +```typescript |
| 73 | +import rule from '../../src/rules/{rule-name}.js' |
| 74 | +import { javascript, runRuleTester } from '../utils/rule-tester.js' |
| 75 | + |
| 76 | +runRuleTester('{rule-name}', rule, { |
| 77 | + invalid: [ |
| 78 | + { |
| 79 | + code: 'test("should fail", () => {});', |
| 80 | + errors: [{ messageId: 'errorMessage', type: 'Identifier' }], |
| 81 | + }, |
| 82 | + ], |
| 83 | + valid: ['test("should pass", () => expect(true).toBe(true))'], |
| 84 | +}) |
| 85 | +``` |
| 86 | + |
| 87 | +## Development Workflow |
| 88 | + |
| 89 | +### Test-Driven Development (TDD) |
| 90 | + |
| 91 | +1. **Always write tests first** - Every rule must have comprehensive test |
| 92 | + coverage |
| 93 | +2. **Test both valid and invalid cases** - Include edge cases and complex |
| 94 | + scenarios |
| 95 | +3. **Use the `runRuleTester` utility** - Provides consistent testing framework |
| 96 | +4. **Test with different configurations** - Options, settings, global aliases |
| 97 | +5. **Test with TypeScript** - Use `runTSRuleTester` for TypeScript-specific |
| 98 | + rules |
| 99 | + |
| 100 | +### Rule Development Process |
| 101 | + |
| 102 | +1. **Analyze the problem** - Understand what Playwright pattern needs |
| 103 | + enforcement |
| 104 | +2. **Write failing tests** - Define what should and shouldn't trigger the rule |
| 105 | +3. **Implement the rule** - Use existing utilities and patterns |
| 106 | +4. **Add documentation** - Create markdown file in `docs/rules/` |
| 107 | +5. **Update README** - Add rule to the rules table |
| 108 | +6. **Register the rule** - Add to `src/index.ts` exports and configurations |
| 109 | + |
| 110 | +### Code Quality Standards |
| 111 | + |
| 112 | +- **TypeScript strict mode** - All code must be properly typed |
| 113 | +- **ESLint compliance** - Code must pass the project's own linting rules |
| 114 | +- **Prettier formatting** - Consistent code formatting |
| 115 | +- **Comprehensive testing** - Aim for 100% test coverage on new rules |
| 116 | + |
| 117 | +## Key Utilities & APIs |
| 118 | + |
| 119 | +### AST Manipulation (`src/utils/ast.ts`) |
| 120 | + |
| 121 | +- `getStringValue(node)` - Extract string value from various node types |
| 122 | +- `isIdentifier(node, name?)` - Check if node is identifier with optional name |
| 123 | +- `findParent(node, type)` - Find parent node of specific type |
| 124 | +- `dereference(context, node)` - Resolve variable references |
| 125 | +- `isPageMethod(node, name)` - Check if call is page method |
| 126 | + |
| 127 | +### Function Call Parsing (`src/utils/parseFnCall.ts`) |
| 128 | + |
| 129 | +- `parseFnCall(context, node)` - Parse Playwright function calls |
| 130 | +- `isTypeOfFnCall(context, node, types)` - Check function call types |
| 131 | +- Supports: `test`, `expect`, `describe`, `hook`, `step`, `config` |
| 132 | + |
| 133 | +### Rule Creation (`src/utils/createRule.ts`) |
| 134 | + |
| 135 | +- Handles custom message interpolation via `{{ variable }}` syntax |
| 136 | +- Supports global settings for message customization |
| 137 | +- Provides consistent rule context wrapper |
| 138 | + |
| 139 | +### Fixing Utilities (`src/utils/fixer.ts`) |
| 140 | + |
| 141 | +- `replaceAccessorFixer` - Replace property accessors safely |
| 142 | +- `removePropertyFixer` - Remove object properties with cleanup |
| 143 | + |
| 144 | +## Configuration & Settings |
| 145 | + |
| 146 | +### Plugin Settings |
| 147 | + |
| 148 | +```json |
| 149 | +{ |
| 150 | + "settings": { |
| 151 | + "playwright": { |
| 152 | + "globalAliases": { |
| 153 | + "test": ["it", "spec"], |
| 154 | + "expect": ["assert"] |
| 155 | + }, |
| 156 | + "messages": { |
| 157 | + "customMessageId": "Custom error message" |
| 158 | + } |
| 159 | + } |
| 160 | + } |
| 161 | +} |
| 162 | +``` |
| 163 | + |
| 164 | +### Rule Options |
| 165 | + |
| 166 | +- Most rules support configuration options via JSON schema |
| 167 | +- Options are validated at runtime |
| 168 | +- Default values should be sensible and well-documented |
| 169 | + |
| 170 | +## Testing Strategies |
| 171 | + |
| 172 | +### Test Structure |
| 173 | + |
| 174 | +- **Invalid cases**: Code that should trigger the rule |
| 175 | +- **Valid cases**: Code that should not trigger the rule |
| 176 | +- **Edge cases**: Complex scenarios, nested structures, different syntax |
| 177 | +- **Configuration tests**: Different options and settings |
| 178 | + |
| 179 | +### Test Utilities |
| 180 | + |
| 181 | +- `javascript` template literal for multi-line code |
| 182 | +- `typescript` template literal for TypeScript code |
| 183 | +- `test()` wrapper for common test patterns |
| 184 | +- Global alias testing with settings |
| 185 | + |
| 186 | +### Test Coverage Requirements |
| 187 | + |
| 188 | +- All rule logic paths must be tested |
| 189 | +- All message variations must be tested |
| 190 | +- All configuration options must be tested |
| 191 | +- Edge cases and error conditions must be tested |
| 192 | + |
| 193 | +## Documentation Standards |
| 194 | + |
| 195 | +### Rule Documentation (`docs/rules/`) |
| 196 | + |
| 197 | +- Clear description of what the rule does |
| 198 | +- Examples of correct and incorrect usage |
| 199 | +- Configuration options with examples |
| 200 | +- Rationale for the rule's existence |
| 201 | + |
| 202 | +### README Integration |
| 203 | + |
| 204 | +- Rules table with status indicators (✅ recommended, 🔧 fixable, 💡 |
| 205 | + suggestions) |
| 206 | +- Clear categorization and descriptions |
| 207 | +- Links to detailed documentation |
| 208 | + |
| 209 | +## Issue Resolution Process |
| 210 | + |
| 211 | +### GitHub Issue Workflow |
| 212 | + |
| 213 | +1. **Get issue details**: |
| 214 | + `gh issue view <issue-number> --json 'title,body,comments'` |
| 215 | +2. **Analyze the problem**: Understand the specific Playwright pattern or issue |
| 216 | +3. **Create a plan**: Step-by-step approach to solving the issue |
| 217 | +4. **Write tests first**: Implement failing tests that demonstrate the problem |
| 218 | +5. **Implement the solution**: Write the rule or fix the bug |
| 219 | +6. **Verify with tests**: Run `pnpm test` to ensure all tests pass |
| 220 | +7. **Create branch and PR**: Use semantic commit messages and add `ai` label |
| 221 | + |
| 222 | +### Common Issue Types |
| 223 | + |
| 224 | +- **New rule requests**: Implement new Playwright best practices |
| 225 | +- **Bug fixes**: Existing rules not working correctly |
| 226 | +- **Enhancement requests**: Additional options or functionality |
| 227 | +- **Documentation updates**: Clarifying rule behavior or usage |
| 228 | + |
| 229 | +## Build & Release Process |
| 230 | + |
| 231 | +### Development Commands |
| 232 | + |
| 233 | +- `pnpm install` - Install dependencies |
| 234 | +- `pnpm test` - Run all tests |
| 235 | +- `pnpm test:watch` - Run tests in watch mode |
| 236 | +- `pnpm build` - Build the plugin |
| 237 | +- `pnpm lint` - Run ESLint |
| 238 | +- `pnpm fmt` - Format code with Prettier |
| 239 | + |
| 240 | +### Release Process |
| 241 | + |
| 242 | +- Uses semantic-release for automated versioning |
| 243 | +- Triggered via GitHub Actions workflow |
| 244 | +- Requires all tests to pass before release |
| 245 | +- Automatically publishes to npm |
| 246 | + |
| 247 | +## Best Practices for Agents |
| 248 | + |
| 249 | +### When Implementing New Rules |
| 250 | + |
| 251 | +1. **Study existing rules** - Understand patterns from similar rules |
| 252 | +2. **Use existing utilities** - Don't reinvent AST parsing logic |
| 253 | +3. **Follow naming conventions** - Rule names should be descriptive and |
| 254 | + consistent |
| 255 | +4. **Consider edge cases** - Think about complex Playwright patterns |
| 256 | +5. **Test thoroughly** - Include both obvious and subtle test cases |
| 257 | + |
| 258 | +### When Fixing Bugs |
| 259 | + |
| 260 | +1. **Reproduce the issue** - Create a minimal test case |
| 261 | +2. **Understand the root cause** - Is it AST parsing, logic, or configuration? |
| 262 | +3. **Fix the core issue** - Don't just patch symptoms |
| 263 | +4. **Add regression tests** - Ensure the bug doesn't return |
| 264 | + |
| 265 | +### When Adding Features |
| 266 | + |
| 267 | +1. **Backward compatibility** - Don't break existing configurations |
| 268 | +2. **Performance considerations** - Rules run on every file |
| 269 | +3. **User experience** - Clear error messages and helpful suggestions |
| 270 | +4. **Documentation** - Update docs and examples |
| 271 | + |
| 272 | +### Code Review Checklist |
| 273 | + |
| 274 | +- [ ] Tests cover all code paths |
| 275 | +- [ ] Error messages are clear and helpful |
| 276 | +- [ ] Configuration options are well-documented |
| 277 | +- [ ] Performance impact is reasonable |
| 278 | +- [ ] Backward compatibility is maintained |
| 279 | +- [ ] Documentation is updated |
| 280 | + |
| 281 | +## Common Patterns & Anti-patterns |
| 282 | + |
| 283 | +### Good Patterns |
| 284 | + |
| 285 | +- Use `parseFnCall` for function identification |
| 286 | +- Use `createRule` wrapper for consistency |
| 287 | +- Provide helpful error messages with context |
| 288 | +- Include auto-fix capabilities when possible |
| 289 | +- Test with both JavaScript and TypeScript |
| 290 | + |
| 291 | +### Anti-patterns to Avoid |
| 292 | + |
| 293 | +- Reinventing AST parsing logic |
| 294 | +- Hard-coding string literals instead of using utilities |
| 295 | +- Not testing edge cases and complex scenarios |
| 296 | +- Ignoring performance implications |
| 297 | +- Breaking backward compatibility without good reason |
| 298 | + |
| 299 | +## Semantic Commit Messages |
| 300 | + |
| 301 | +This project uses semantic-release, so commit messages must follow the format: |
| 302 | + |
| 303 | +- `feat: add new rule or feature` |
| 304 | +- `fix: fix bug in existing rule` |
| 305 | +- `docs: update documentation` |
| 306 | +- `refactor: refactor existing code` |
| 307 | +- `test: add or update tests` |
| 308 | +- `chore: maintenance tasks` |
| 309 | +- `style: formatting changes` |
| 310 | + |
| 311 | +## Pull Request Guidelines |
| 312 | + |
| 313 | +- Add the `ai` label to all PRs |
| 314 | +- Ensure all tests pass before submitting |
| 315 | +- Include comprehensive test coverage |
| 316 | +- Update documentation as needed |
| 317 | +- Follow the existing code style and patterns |
| 318 | +- Provide clear description of changes and rationale |
10 | 319 |
|
11 | | -- This project uses semantic-release to automatically publish new versions of |
12 | | - the package. |
13 | | -- When creating commits, use the following format: |
14 | | - - `feat: add new feature` |
15 | | - - `fix: fix bug` |
16 | | - - `chore: update dependencies` |
17 | | - - `docs: update documentation` |
18 | | - - `refactor: refactor code` |
19 | 320 | - `test: add tests` |
20 | 321 | - `style: update styles` |
0 commit comments