diff --git a/.cursor/rules/README.md b/.cursor/rules/README.md new file mode 100644 index 00000000..20f44b51 --- /dev/null +++ b/.cursor/rules/README.md @@ -0,0 +1,16 @@ +# Cursor Rules for QDrill Project + +This directory contains project-specific rules for AI assistants working on the QDrill codebase. + +## Rules Files + +- `development.mdc` - Core development commands and workflows + +## Key Points to Remember + +1. **ALWAYS use `vercel dev`** for development server (NOT pnpm run dev) +2. Use `pnpm` for package management (NOT npm) +3. Use `vercel build` for production builds +4. Use `psql "$NEON_DB_URL"` for database queries + +These rules help ensure consistent development practices across all AI assistant sessions. diff --git a/.cursor/rules/development.mdc b/.cursor/rules/development.mdc new file mode 100644 index 00000000..4fd15f99 --- /dev/null +++ b/.cursor/rules/development.mdc @@ -0,0 +1,33 @@ +--- +description: +globs: +alwaysApply: true +--- +# Development Rules for QDrill Project + +## IMPORTANT: Development Server +**ALWAYS use `vercel dev` to run the development server** +- DO NOT use `pnpm run dev` +- DO NOT use `npm run dev` +- The correct command is: `vercel dev` + +## Package Management +This project uses pnpm. Always use pnpm commands: +- `pnpm install` (not npm install) +- `pnpm add ` (not npm install ) +- `pnpm remove ` (not npm uninstall) + +## Build Commands +- For development server: `vercel dev` +- For production build verification: `vercel build` +- DO NOT use `pnpm run build` for verification + +## Database Access +When examining data, use: `psql "$NEON_DB_URL"` + +## Summary of Key Commands +- Start dev server: `vercel dev` +- Install dependencies: `pnpm install` +- Add package: `pnpm add ` +- Build for production: `vercel build` +- Check database: `psql "$NEON_DB_URL"` diff --git a/.cursorignore b/.cursorignore new file mode 100644 index 00000000..6f9f00ff --- /dev/null +++ b/.cursorignore @@ -0,0 +1 @@ +# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv) diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..1527f684 --- /dev/null +++ b/.env.example @@ -0,0 +1,11 @@ +# Server-side +SENTRY_DSN= +DATABASE_URL= +POSTGRES_URL= +BETTER_AUTH_SECRET= +BETTER_AUTH_URL= +GOOGLE_CLIENT_ID= +GOOGLE_CLIENT_SECRET= + +# Client-side (public) +PUBLIC_SENTRY_DSN= \ No newline at end of file diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 29c1d31b..035dca17 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,14 +1,45 @@ module.exports = { root: true, - extends: ['eslint:recommended', 'plugin:svelte/recommended', 'prettier'], + extends: [ + 'eslint:recommended', + 'plugin:svelte/recommended', + 'plugin:cypress/recommended', + 'prettier' + ], + plugins: ['vitest-globals'], parserOptions: { + parser: '@typescript-eslint/parser', sourceType: 'module', - ecmaVersion: 2020, + ecmaVersion: 2022, extraFileExtensions: ['.svelte'] }, env: { browser: true, es2017: true, - node: true - } + node: true, + 'cypress/globals': true + }, + overrides: [ + { + files: ['*.js'], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module' + } + }, + { + files: ['**/__tests__/**/*.js', '**/__mocks__/**/*.js'], + extends: ['plugin:vitest-globals/recommended'] + }, + { + files: ['.svelte'], + parser: 'svelte-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + ecmaVersion: 2022, + sourceType: 'module' + } + } + ] }; diff --git a/.gitignore b/.gitignore index 8f6c617e..dabbdb7b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ node_modules /build /.svelte-kit /package +venv +app/__pycache__ +*.pyc .env .env.* !.env.example @@ -10,3 +13,13 @@ node_modules .output vite.config.js.timestamp-* vite.config.ts.timestamp-* +.env*.local +/coverage +.nyc_output +tests/__pycache__ +tests/_pycache +cypress/downloads +cypress/screenshots + +# Sentry Config File +.env.sentry-build-plugin diff --git a/.prettierrc b/.prettierrc index a77fddea..95730232 100644 --- a/.prettierrc +++ b/.prettierrc @@ -4,6 +4,5 @@ "trailingComma": "none", "printWidth": 100, "plugins": ["prettier-plugin-svelte"], - "pluginSearchDirs": ["."], "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..31aca745 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "svelte.plugin.svelte.diagnostics.a11y": false, + "svelte.plugin.svelte.compilerWarnings": { + "a11y-click-events-have-key-events": "ignore", + "a11y-missing-attribute": "ignore", + "a11y-missing-content": "ignore", + "a11y-invalid-attribute": "ignore", + "a11y-label-has-associated-control": "ignore", + "a11y-no-static-element-interactions": "ignore", + "a11y-img-redundant-alt": "ignore", + "a11y-no-noninteractive-element-interactions": "ignore" + } +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..6e5d4c7b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,220 @@ +# QDrill Project Guide + +## Project Overview + +QDrill is a web-based application designed as a sports drill bank and practice planning tool for a niche sport. It allows users to create, manage, and share drills, as well as plan practices with timeline-based organization. + +## Technology Stack + +- **Frontend**: SvelteKit +- **Backend**: SvelteKit (API routes) +- **Database**: PostgreSQL (via Vercel Postgres) +- **Styling**: Tailwind CSS +- **Authentication**: Auth.js (Google OAuth) +- **Deployment**: Vercel +- **Diagramming**: Excalidraw +- **Testing**: Playwright, Cypress + +## Core Features + +### Drill Management + +- Create, edit, view, and search drills +- Tag drills with skill level, positions, duration +- Upload diagrams/images for drills +- Upvote/downvote and comment on drills +- Create variations of existing drills + +### Practice Plan Creation + +- Wizard-based practice plan creation +- Section organization with parallel timelines +- Drag-and-drop editing interface +- Duration tracking and management +- Timeline visualization +- Share and duplicate practice plans + +### User System + +- Google OAuth authentication +- User profiles +- Permission-based access control +- Personal drill/plan management + +## Development Commands + +- `vercel dev` - Start development server +- `pnpm run check` - Check TypeScript + SvelteKit sync + +## Package Management + +- `pnpm install` - Install dependencies +- `pnpm add ` - Add a package + +## Testing + +- `pnpm run test` - Run Playwright tests +- `pnpm test -- tests/test.js` - Run a specific test +- `pnpm run test:unit` - Run Vitest unit tests in watch mode +- `pnpm run test:unit:run` - Run Vitest unit tests once +- `pnpm run test:unit:coverage` - Run Vitest unit tests with coverage +- `pnpm run test:unit --run ` - Run specific Vitest tests once (e.g., `pnpm run test:unit --run src/lib/stores/__tests__/dragManager.test.js`) + +## Code Quality + +- `pnpm run lint` - Run linting checks +- `pnpm run format` - Fix formatting issues + +## Deployment + +- Automatic deployment from GitHub main branch to Vercel + +## Architecture + +### Frontend Components + +- Svelte components organized by feature area +- Modular design with reusable components +- Tailwind CSS for styling with custom components +- Interactive drag-and-drop interface for practice planning + +### State Management + +- Extensive use of Svelte stores +- Separate stores for different domain concerns +- Custom store implementation with methods +- History tracking with undo/redo support + +### API Design + +- RESTful API endpoints +- SvelteKit server endpoints (+server.js) +- Standardized response formats +- Parameterized database queries + +### Database + +- PostgreSQL with connection pooling +- Transaction support for complex operations +- Normalized schema design + +#### Database Connection + +- **Connection String**: Stored in ~/.zshrc as NEON_DB_URL environment variable +- **Connection Command**: `psql "$NEON_DB_URL"` +- **Project ID**: morning-mountain-82887088 +- **Database Name**: verceldb +- **Tables**: drills, practice_plans, practice_plan_sections, practice_plan_drills, users, comments, votes, etc. +- **Query Example**: `psql "$NEON_DB_URL" -c "SELECT COUNT(*) FROM drills;"` + +## Key Systems + +### Authentication + +- Auth.js (formerly NextAuth) integration +- Google OAuth provider +- Session-based authentication +- Authorization middleware + +### Drag and Drop + +- Complex drag-and-drop system for practice plan editing +- State management via Svelte stores +- Multiple drop targets and interactions +- Timeline-based organization +- Visual feedback during drag operations + +### Data Filtering + +- Client-side filtering for drills +- Multi-criteria filtering +- Performance optimization for large datasets + +## Code Style Guidelines + +- **AI-Readability**: Add clear comments to make code easily understood by future AI systems +- **Comments**: Include purpose explanations, input/output expectations, and logic clarifications +- **Imports**: Group imports by source (svelte, lib, components) +- **Components**: Use Svelte components with script/markup/style structure +- **Stores**: Use reactive declarations with $ prefix for store values +- **Error Handling**: Use try/catch with specific error messages +- **API Endpoints**: Return standardized JSON responses with proper status codes +- **Database**: Use parameterized queries to prevent SQL injection +- **Naming**: Use descriptive camelCase for variables/functions, PascalCase for components + +## Areas for Improvement + +### 1. Drag and Drop System Consolidation + +**Impact: High** + +- Currently has two parallel drag-and-drop systems +- Consolidate into a single system with consistent interface +- Implement proper state machine for drag operations +- Reduce code complexity and maintenance burden + +### 2. API Data Fetching Abstraction + +**Impact: High** + +- Direct fetch calls scattered throughout components +- Create unified API client with standard methods +- Implement consistent error handling and retry logic +- Add caching and performance optimizations + +### 3. Test Coverage Expansion + +**Impact: High** + +- Minimal testing despite complex UI interactions +- Add unit tests for store logic (especially drag-and-drop) +- Implement integration tests for key user flows +- Set up CI pipeline with automated testing + +### 4. Store Logic Separation + +**Impact: Medium** + +- Store files mix different concerns (data, filtering, etc.) +- Separate into dedicated modules with single responsibilities +- Move complex logic into utility functions +- Improve maintainability and testability + +### 5. Performance Optimization + +**Impact: Medium** + +- Filtering/sorting recalculates on every store update +- Implement memoization for expensive calculations +- Use web workers for heavy operations +- Optimize filter chains and add virtualization + +## Documentation Workflow + +- After completing any significant task, ALWAYS follow this documentation workflow: + +1. First examine `/docs/index.md` to understand the documentation structure +2. Then navigate to the appropriate subdirectory based on the nature of your changes: + - `/docs/architecture/` for architectural changes or patterns + - `/docs/implementation/` for implementation details and technical references +3. Update existing documentation files or create new ones as needed +4. Update index files to reference any new documentation + +## Documentation Requirements + +- Create/update documentation when modifying .js/.svelte files +- Document component descriptions, usage instructions, and relationships +- Maintain documentation consistency for directory structure +- Consider component interdependencies when making changes +- Follow best practices for Svelte documentation +- Add implementation notes to `/docs/implementation/` for technical patterns +- **README Updates**: Always update the README.md file after completing substantial code edits to reflect the latest changes, features, and usage instructions + +## Version Control Guidelines + +- **Commit Message Standards**: Write clear, descriptive commit messages explaining what changes were made and why +- **Atomic Commits**: Keep commits focused on a single logical change +- **Pull Request Format**: Include clear descriptions of changes, impact, and testing performed +- **Code Reviews**: Request code reviews for substantial changes +- **No Automatic Commits**: Never commit changes without explicitly being asked to do so +- **Testing Before Commit**: Always run relevant tests before creating a commit diff --git a/README.md b/README.md index 4d3b8e37..ec2428d4 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,245 @@ -# SvelteKit Demo app +# QDrill -The official demo app for SvelteKit, hosted on Vercel. +A comprehensive web-based application for sports drill management and practice planning. -## Deploy Your Own +## Overview -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fvercel%2Ftree%2Fmain%2Fexamples%2Fsveltekit-1&project-name=sveltekit-vercel&repository-name=sveltekit-vercel&demo-title=SvelteKit%20%2B%20Vercel&demo-url=https%3A%2F%2Fsveltekit-template.vercel.app%2F) +QDrill is a web-based application designed to be a sports drill bank and practice planning tool for a niche sport. The application allows users to create, manage, and share drills, as well as plan practices. The user experience (UX) is a high priority, with an emphasis on smooth, responsive interactions and a modern design. The application is expected to handle up to a few hundred concurrent users and is built with SvelteKit for both frontend and backend. -_Live Example: https://sveltekit-1-template.vercel.app_ +## Technology Stack -## Developing +- **Frontend**: Svelte with SvelteKit +- **Backend**: SvelteKit +- **Database**: Neon (PostgreSQL) +- **Authentication**: Auth.js (using Google OAuth) +- **Diagramming**: Excalidraw (via `@excalidraw/excalidraw`, note: includes React dependency) +- **Rich Text Editing**: TinyMCE +- **Deployment**: Hosted on Vercel +- **CSS**: Tailwind CSS +- **Testing**: Vitest (unit), Playwright and Cypress (end-to-end) -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: +## Security -```bash -npm run dev +- **Sentry**: Configure DSNs via environment variables `SENTRY_DSN` (server) and `PUBLIC_SENTRY_DSN` (client). Sampling is reduced in production. +- **HTML Sanitization**: All rich text HTML is sanitized server-side via DOMPurify (see `src/lib/utils/sanitizeHtml.js`). Do not render untrusted HTML without sanitizing. +- **CSP**: Basic Content Security Policy headers are applied in `src/hooks.server.js`. Adjust as needed per hosting. -# or start the server and open the app in a new browser tab -npm run dev -- --open -``` +## Core Features -## Building +### 1. Drill and Formation Management -To create a production version of your app: +- **Form-Based Drill Creation**: Users can create new drills via a form interface. Each drill will have the following attributes: + - Name (required) + - Brief description (required) + - How to teach it/detailed description + - Skill level required (required) + - Complexity to explain + - Suggested length of time (required) + - Number of people required + - Skills focused on (required) + - Positions focused on (required) + - Video link to drill + - Images of drill +- **Dynamic URL Generation**: Each drill will automatically be assigned a unique URL upon creation, allowing users to share and access drills directly. +- **Public vs. Private Drills**: Users can choose to make drills public or private. Public drills are accessible by all, while private drills require a specific link. Users can also create public versions of private drills with a different description. -```bash -npm run build -``` +### 2. Drill and Formation Filtering and Viewing -You can preview the production build with `npm run preview`. +- **Client-Side Filtering**: Drills and formations are currently fetched to the client-side, where filtering occurs. While this provides a responsive feel for smaller datasets, it has been identified as a scalability limitation for larger numbers of items (code review notes). +- **Listing Views**: The main views will display lists of drills or formations, showing their name, attributes, brief description, and indications of any media (pictures/videos). +- **Detail Pages**: Each drill and formation will have a dedicated page showing all of its details. Users can comment on drills, upvote them, or create variations. +- **Formations**: A specialized system for static player positions that can be created, shared, and viewed separately from the dynamic drills. -## Speed Insights +### 3. Practice Plan Creation and Management -Once deployed on Vercel, you can benefit from [Speed Insights](https://vercel.com/docs/concepts/speed-insights) simply by navigating to Vercel's dashboard, clicking on the 'Speed Insights' tab, and enabling the product. +- **Form-Based Practice Planning**: Users can create practice plans by selecting drills based on the number of players, skill levels, practice duration, and skills to focus on. Two primary methods exist: a cart-based approach (adding drills to a cart first) and a step-by-step wizard. +- **Plan Customization**: After selecting drills, users can define additional practice details, including: + - Practice name + - Practice goals + - Phase of the season + - Number of participants suited for + - Level of experience suited for + - Skills focused on + - Brief overview of practice flow + - Time dedicated to each drill + - Breaks between drills + - Total practice time +- **Public vs. Private Plans**: Similar to drills, practice plans can be published either privately (accessible via link) or publicly. Users can write different overviews for public/private versions if desired. -You will get data once your application will be re-deployed and will receive visitors. +### 4. User Interaction and Profiles + +- **User Accounts**: Users can create accounts via OAuth (e.g., Google). Logged-in users can create, comment on, and upvote drills or practice plans, and create variations. +- **Anonymous Interaction**: Users who are not logged in can still view and vote on drills, and create practice plans, though publishing or saving them for future editing requires logging in. +- **User Profiles**: Profiles can include optional information such as name, team played for, country, and social media links. +- **User Access**: All users will have the same level of access. Each user will have their own private drills and practice plans, and they can save public drills and plans. Users can see the drills and plans they have saved. + +### 5. Backend and Data Management + +- **Vercel Postgres Database**: Used for storing all application data, including drills, practice plans, user accounts, and comments. +- **API Integration**: The SvelteKit frontend will communicate with the SvelteKit backend via RESTful APIs to manage drill creation, filtering, user management, and more. +- **Media Management**: Images will be hosted directly on the application, while videos will be linked from external sources (e.g., YouTube, cloud storage). + +### 6. Deployment and Hosting + +- **Frontend**: Hosted on Vercel with the custom domain (e.g., qdrill.app). +- **Backend**: Hosted on Vercel's serverless functions or as a separate service if needed, handling API requests and database interactions. + +### 7. Testing and Quality Assurance + +- **Vitest**: Used for unit testing the service layer and other backend functionality. +- **Playwright**: Used for end-to-end testing. +- **Cypress**: Used for additional end-to-end testing to ensure the entire user flow, from drill creation to practice plan publishing, works smoothly. + +### 8. UX and Design + +- **Design Aesthetic**: The design will follow a style similar to Figma, with a clean, minimalist look. The color scheme and fonts will be inspired by Figma, but with an emphasis on ensuring faster loading times and responsive filtering without noticeable delays. + +## Development + +### Getting Started + +1. **Install dependencies**: + + ```bash + pnpm install + ``` + +2. **Run the development server**: + + ```bash + vercel dev + ``` + +3. **Check TypeScript + SvelteKit sync**: + ```bash + pnpm run check + ``` + +### Package Management + +- **Install dependencies**: + + ```bash + pnpm install + ``` + +- **Add a package**: + ```bash + pnpm add + ``` + +### Testing + +- **Run Playwright tests**: + + ```bash + pnpm run test + ``` + +- **Run a specific test**: + + ```bash + pnpm test -- tests/test.js + ``` + +- **Run Vitest unit tests in watch mode**: + + ```bash + pnpm run test:unit + ``` + +- **Run Vitest unit tests once**: + + ```bash + pnpm run test:unit:run + ``` + +- **Run Vitest unit tests with coverage**: + ```bash + pnpm run test:unit:coverage + ``` + +### Code Quality + +- **Run linting checks**: + + ```bash + pnpm run lint + ``` + +- **Fix formatting issues**: + ```bash + pnpm run format + ``` + +### Database Migrations + +Database schema changes are managed using `node-pg-migrate`. + +- **Create a new migration**: + + ```bash + npx node-pg-migrate create + ``` + + Replace `` with a descriptive name (e.g., `add_user_email_column`). + +- **Run migrations**: + + ```bash + npx node-pg-migrate up + ``` + + This applies all pending migrations. Make sure your `DATABASE_URL` environment variable is set correctly (e.g., in `.env.local` or your shell environment). + +- **Rollback the last migration**: + ```bash + npx node-pg-migrate down + ``` + +### Deployment + +Deployment is automatic from the GitHub main branch to Vercel. + +## Documentation + +Project documentation is organized in two main locations: + +1. **`docs/`**: Detailed technical documentation + - **`Architecture`**: System design, patterns, and architectural decisions + - **`Implementation`**: Technical details and implementation specifics + - Drag and Drop System + - Timeline Management + - Service Layer Architecture +2. **`code-review/`**: Contains detailed findings and notes from a comprehensive code review conducted to assess codebase health, identify areas for improvement, and align with professional development standards. See `code-review/holistic-summary.md` for an overview. + +### Documentation Workflow + +When making changes to the codebase: + +1. First examine `/docs/index.md` to understand the documentation structure +2. Navigate to the appropriate subdirectory based on the nature of your changes: + - `/docs/architecture/` for architectural changes or patterns + - `/docs/implementation/` for implementation details and technical references +3. Update existing documentation files or create new ones as needed +4. Update index files to reference any new documentation + +### Documentation Requirements + +- Create/update documentation when modifying .js/.svelte files +- Document component descriptions, usage instructions, and relationships +- Maintain documentation consistency for directory structure +- Consider component interdependencies when making changes +- Follow best practices for Svelte documentation + +## Code Style Guidelines + +- **AI-Readability**: Add clear comments to make code easily understood by future AI systems +- **Comments**: Include purpose explanations, input/output expectations, and logic clarifications +- **Imports**: Group imports by source (svelte, lib, components) +- **Components**: Use Svelte components with script/markup/style structure +- **Stores**: Use reactive declarations with $ prefix for store values +- **Error Handling**: Use try/catch with specific error messages +- **API Endpoints**: Return standardized JSON responses with proper status codes +- **Database**: Use parameterized queries to prevent SQL injection +- **Naming**: Use descriptive camelCase for variables/functions, PascalCase for components diff --git a/components.json b/components.json new file mode 100644 index 00000000..24d2c981 --- /dev/null +++ b/components.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://shadcn-svelte.com/schema.json", + "style": "default", + "tailwind": { + "config": "tailwind.config.js", + "css": "src/routes/styles.css", + "baseColor": "slate" + }, + "aliases": { + "components": "$lib/components", + "utils": "$lib/utils" + }, + "typescript": true +} diff --git a/cypress.config.js b/cypress.config.js new file mode 100644 index 00000000..204986e9 --- /dev/null +++ b/cypress.config.js @@ -0,0 +1,16 @@ +import { defineConfig } from 'cypress'; + +export default defineConfig({ + e2e: { + baseUrl: 'http://localhost:3000', + supportFile: 'cypress/support/e2e.js' + }, + + component: { + supportFile: 'cypress/support/component.js', + devServer: { + framework: 'svelte', + bundler: 'vite' + } + } +}); diff --git a/cypress/component/drillitem.cy.js b/cypress/component/drillitem.cy.js new file mode 100644 index 00000000..e7bfcb37 --- /dev/null +++ b/cypress/component/drillitem.cy.js @@ -0,0 +1,41 @@ +import DrillItem from '../../src/components/practice-plan/items/DrillItem.svelte'; + +describe('', () => { + beforeEach(() => { + // Intercept the API call that causes the DB connection issue + cy.intercept('GET', '/api/feedback', { statusCode: 200, body: [] }).as('getFeedback'); + }); + + it('renders the drill name, duration input, and remove button', () => { + const mockItem = { + id: 'drill-123', + name: 'Test Drill Item', + duration: 15, + selected_duration: null // or provide a value if needed + // Add other properties if the component strictly requires them for rendering + }; + const mockOnRemove = cy.spy().as('removeHandler'); // Create a Cypress spy + + cy.mount(DrillItem, { + props: { + item: mockItem, + itemIndex: 0, + sectionIndex: 0, + onRemove: mockOnRemove + } + }); + + // Assertions + cy.contains(mockItem.name).should('be.visible'); + cy.get('input[type="number"]').should('have.value', mockItem.duration.toString()); + cy.contains('button', 'Remove').should('be.visible'); + cy.get('[data-testid="drill-item"]').should('have.attr', 'data-item-id', mockItem.id); + cy.get('[data-testid="drill-item"]').should('have.attr', 'data-item-name', mockItem.name); + + // Optional: Test clicking the remove button + cy.contains('button', 'Remove').click(); + cy.get('@removeHandler').should('have.been.calledOnce'); + }); + + // Add more tests here for different props, states, or interactions +}); diff --git a/cypress/e2e/README.md b/cypress/e2e/README.md new file mode 100644 index 00000000..c97c7ffc --- /dev/null +++ b/cypress/e2e/README.md @@ -0,0 +1,59 @@ +# Cypress E2E Testing Notes & Best Practices + +This document summarizes key learnings and best practices encountered while writing E2E tests for this project, particularly regarding interactions with Svelte components. + +## 1. Use `data-testid` for Element Selection + +- **Why:** CSS classes, element structure, and text content can change frequently, making tests brittle. `data-testid` (or `data-cy`, `data-test`) attributes provide stable selectors specifically for testing. +- **How:** Add `data-testid="your-unique-identifier"` to elements you need to interact with (buttons, inputs, links) or assert against (list items, status indicators, specific text containers). +- **Example:** + ```javascript + // In component: + // In test: cy.get('[data-testid="submit-button"]').click(); + ``` + +## 2. Target the Element with the Event Handler + +- **Problem:** Sometimes, clicking a parent element or label (e.g., `