|
| 1 | +# Cypress Testing Setup |
| 2 | + |
| 3 | +This directory contains the end-to-end (E2E) and component tests for the Meet@Mensa React application using Cypress. |
| 4 | + |
| 5 | +## Structure |
| 6 | + |
| 7 | +``` |
| 8 | +cypress/ |
| 9 | +├── e2e/ # End-to-end tests |
| 10 | +│ ├── authentication.cy.ts |
| 11 | +│ ├── match-requests.cy.ts |
| 12 | +│ └── navigation.cy.ts |
| 13 | +├── component/ # Component tests |
| 14 | +│ └── MatchRequestCard.cy.tsx |
| 15 | +├── support/ # Support files |
| 16 | +│ ├── commands.ts # Custom Cypress commands |
| 17 | +│ ├── e2e.ts # E2E test configuration |
| 18 | +│ ├── component.ts # Component test configuration |
| 19 | +│ ├── component-index.html |
| 20 | +│ └── index.d.ts # TypeScript declarations |
| 21 | +├── fixtures/ # Test data (if needed) |
| 22 | +└── downloads/ # Downloaded files (if any) |
| 23 | +``` |
| 24 | + |
| 25 | +## Getting Started |
| 26 | + |
| 27 | +### Prerequisites |
| 28 | + |
| 29 | +1. Make sure your development server is running on `http://localhost:3000` |
| 30 | +2. Ensure your backend API is running on `http://localhost:8080` |
| 31 | +3. Set up test credentials in `cypress.env.json` |
| 32 | + |
| 33 | +### Running Tests |
| 34 | + |
| 35 | +#### E2E Tests |
| 36 | + |
| 37 | +```bash |
| 38 | +# Open Cypress Test Runner (interactive mode) |
| 39 | +npm run cypress:open |
| 40 | + |
| 41 | +# Run E2E tests in headless mode |
| 42 | +npm run cypress:run:e2e |
| 43 | + |
| 44 | +# Run E2E tests with dev server (recommended) |
| 45 | +npm run test:e2e |
| 46 | + |
| 47 | +# Run E2E tests with dev server in interactive mode |
| 48 | +npm run test:e2e:open |
| 49 | +``` |
| 50 | + |
| 51 | +#### Component Tests |
| 52 | + |
| 53 | +```bash |
| 54 | +# Run component tests in headless mode |
| 55 | +npm run cypress:run:component |
| 56 | + |
| 57 | +# Open Cypress Test Runner for component tests |
| 58 | +npm run cypress:open --component |
| 59 | +``` |
| 60 | + |
| 61 | +#### All Tests |
| 62 | + |
| 63 | +```bash |
| 64 | +# Run all Cypress tests |
| 65 | +npm run cypress:run |
| 66 | +``` |
| 67 | + |
| 68 | +## Configuration |
| 69 | + |
| 70 | +### Environment Variables |
| 71 | + |
| 72 | +Create a `cypress.env.json` file in the client directory with your test credentials: |
| 73 | + |
| 74 | +```json |
| 75 | +{ |
| 76 | + "TEST_USER_EMAIL": "[email protected]", |
| 77 | + "TEST_USER_PASSWORD": "your-test-password", |
| 78 | + "API_BASE_URL": "http://localhost:8080", |
| 79 | + "AUTH0_DOMAIN": "your-auth0-domain", |
| 80 | + "AUTH0_CLIENT_ID": "your-auth0-client-id" |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +### Test Data |
| 85 | + |
| 86 | +For consistent test data, you can create fixtures in `cypress/fixtures/`: |
| 87 | + |
| 88 | +```json |
| 89 | +// cypress/fixtures/match-requests.json |
| 90 | +{ |
| 91 | + "validMatchRequest": { |
| 92 | + "title": "Test Match Request", |
| 93 | + "description": "This is a test match request", |
| 94 | + "location": "Mensa Arcisstraße", |
| 95 | + "date": "2024-12-25", |
| 96 | + "time": "12:00", |
| 97 | + "maxParticipants": 4 |
| 98 | + } |
| 99 | +} |
| 100 | +``` |
| 101 | + |
| 102 | +## Custom Commands |
| 103 | + |
| 104 | +The following custom commands are available in your tests: |
| 105 | + |
| 106 | +### Authentication |
| 107 | + |
| 108 | +- `cy.login(email, password)` - Login with Auth0 |
| 109 | +- `cy.logout()` - Logout from the application |
| 110 | +- `cy.isAuthenticated()` - Check if user is authenticated |
| 111 | + |
| 112 | +### Match Requests |
| 113 | + |
| 114 | +- `cy.createMatchRequest(data)` - Create a new match request |
| 115 | +- `cy.joinMatchRequest(matchId)` - Join an existing match request |
| 116 | + |
| 117 | +### Navigation |
| 118 | + |
| 119 | +- `cy.navigateTo(page)` - Navigate to a specific page |
| 120 | + |
| 121 | +### Forms |
| 122 | + |
| 123 | +- `cy.fillForm(formData)` - Fill form fields with data |
| 124 | +- `cy.selectFromDropdown(dropdownId, option)` - Select from dropdown |
| 125 | + |
| 126 | +### Utilities |
| 127 | + |
| 128 | +- `cy.waitForApi(method, url)` - Wait for API requests to complete |
| 129 | +- `cy.checkToast(message, type)` - Check for toast notifications |
| 130 | +- `cy.uploadFile(inputId, filePath)` - Upload a file |
| 131 | + |
| 132 | +## Writing Tests |
| 133 | + |
| 134 | +### E2E Test Example |
| 135 | + |
| 136 | +```typescript |
| 137 | +describe('Match Requests', () => { |
| 138 | + beforeEach(() => { |
| 139 | + cy.login(Cypress.env('TEST_USER_EMAIL'), Cypress.env('TEST_USER_PASSWORD')); |
| 140 | + cy.visit('/dashboard'); |
| 141 | + }); |
| 142 | + |
| 143 | + it('should create a new match request', () => { |
| 144 | + const testRequest = { |
| 145 | + title: 'Test Match Request', |
| 146 | + description: 'This is a test match request', |
| 147 | + location: 'Mensa Arcisstraße', |
| 148 | + date: '2024-12-25', |
| 149 | + time: '12:00', |
| 150 | + maxParticipants: 4, |
| 151 | + }; |
| 152 | + |
| 153 | + cy.get('[data-testid="create-match-button"]').click(); |
| 154 | + cy.fillForm({ |
| 155 | + 'match-title': testRequest.title, |
| 156 | + 'match-description': testRequest.description, |
| 157 | + 'match-location': testRequest.location, |
| 158 | + 'match-date': testRequest.date, |
| 159 | + 'match-time': testRequest.time, |
| 160 | + 'match-max-participants': testRequest.maxParticipants.toString(), |
| 161 | + }); |
| 162 | + |
| 163 | + cy.get('[data-testid="submit-match-request"]').click(); |
| 164 | + cy.checkToast('Match request created successfully'); |
| 165 | + }); |
| 166 | +}); |
| 167 | +``` |
| 168 | + |
| 169 | +### Component Test Example |
| 170 | + |
| 171 | +```typescript |
| 172 | +import React from 'react' |
| 173 | +import { MatchRequestCard } from '../../src/components/MatchRequestCard' |
| 174 | + |
| 175 | +describe('MatchRequestCard.cy.tsx', () => { |
| 176 | + const mockMatchRequest = { |
| 177 | + id: '1', |
| 178 | + title: 'Test Match Request', |
| 179 | + description: 'This is a test match request', |
| 180 | + location: 'Mensa Arcisstraße', |
| 181 | + date: '2024-12-25', |
| 182 | + time: '12:00', |
| 183 | + maxParticipants: 4, |
| 184 | + currentParticipants: 2, |
| 185 | + creator: { id: 'user1', name: 'John Doe', email: '[email protected]' }, |
| 186 | + participants: [ |
| 187 | + { id: 'user1', name: 'John Doe' }, |
| 188 | + { id: 'user2', name: 'Jane Smith' } |
| 189 | + ], |
| 190 | + createdAt: '2024-12-20T10:00:00Z' |
| 191 | + } |
| 192 | + |
| 193 | + it('should render match request information correctly', () => { |
| 194 | + cy.mount(<MatchRequestCard matchRequest={mockMatchRequest} onJoin={() => {}} onDelete={() => {}} />) |
| 195 | + |
| 196 | + cy.get('[data-testid="match-title"]').should('contain', mockMatchRequest.title) |
| 197 | + cy.get('[data-testid="match-description"]').should('contain', mockMatchRequest.description) |
| 198 | + }); |
| 199 | +}); |
| 200 | +``` |
| 201 | + |
| 202 | +## Best Practices |
| 203 | + |
| 204 | +### Data Attributes |
| 205 | + |
| 206 | +Use `data-testid` attributes for reliable element selection: |
| 207 | + |
| 208 | +```tsx |
| 209 | +<button data-testid="create-match-button">Create Match</button> |
| 210 | +``` |
| 211 | + |
| 212 | +### Test Isolation |
| 213 | + |
| 214 | +- Clear localStorage and cookies before each test |
| 215 | +- Use unique test data for each test |
| 216 | +- Avoid dependencies between tests |
| 217 | + |
| 218 | +### API Mocking |
| 219 | + |
| 220 | +For faster tests, you can mock API responses: |
| 221 | + |
| 222 | +```typescript |
| 223 | +cy.intercept('GET', '/api/match-requests', { |
| 224 | + statusCode: 200, |
| 225 | + body: mockMatchRequests, |
| 226 | +}).as('getMatchRequests'); |
| 227 | +``` |
| 228 | + |
| 229 | +### Error Handling |
| 230 | + |
| 231 | +Handle uncaught exceptions gracefully: |
| 232 | + |
| 233 | +```typescript |
| 234 | +Cypress.on('uncaught:exception', (err, runnable) => { |
| 235 | + console.log('Uncaught exception:', err.message); |
| 236 | + return false; |
| 237 | +}); |
| 238 | +``` |
| 239 | + |
| 240 | +## CI/CD Integration |
| 241 | + |
| 242 | +### GitHub Actions Example |
| 243 | + |
| 244 | +```yaml |
| 245 | +name: E2E Tests |
| 246 | +on: [push, pull_request] |
| 247 | +jobs: |
| 248 | + cypress-run: |
| 249 | + runs-on: ubuntu-latest |
| 250 | + steps: |
| 251 | + - uses: actions/checkout@v3 |
| 252 | + - uses: actions/setup-node@v3 |
| 253 | + with: |
| 254 | + node-version: '18' |
| 255 | + - run: npm ci |
| 256 | + - run: npm run test:e2e |
| 257 | +``` |
| 258 | +
|
| 259 | +### Environment Variables in CI |
| 260 | +
|
| 261 | +Set these environment variables in your CI/CD platform: |
| 262 | +
|
| 263 | +- `TEST_USER_EMAIL` |
| 264 | +- `TEST_USER_PASSWORD` |
| 265 | +- `API_BASE_URL` |
| 266 | +- `AUTH0_DOMAIN` |
| 267 | +- `AUTH0_CLIENT_ID` |
| 268 | + |
| 269 | +## Troubleshooting |
| 270 | + |
| 271 | +### Common Issues |
| 272 | + |
| 273 | +1. **Tests failing due to Auth0 redirects** |
| 274 | + |
| 275 | + - Ensure test credentials are correct |
| 276 | + - Check Auth0 domain configuration |
| 277 | + |
| 278 | +2. **Element not found errors** |
| 279 | + |
| 280 | + - Verify `data-testid` attributes are present |
| 281 | + - Check if elements are conditionally rendered |
| 282 | + |
| 283 | +3. **API timeout errors** |
| 284 | + |
| 285 | + - Ensure backend server is running |
| 286 | + - Check API base URL configuration |
| 287 | + |
| 288 | +4. **Component test failures** |
| 289 | + - Verify component imports are correct |
| 290 | + - Check for missing dependencies |
| 291 | + |
| 292 | +### Debug Mode |
| 293 | + |
| 294 | +Run tests in debug mode for more detailed output: |
| 295 | + |
| 296 | +```bash |
| 297 | +DEBUG=cypress:* npm run cypress:run |
| 298 | +``` |
| 299 | + |
| 300 | +## Resources |
| 301 | + |
| 302 | +- [Cypress Documentation](https://docs.cypress.io/) |
| 303 | +- [Cypress Best Practices](https://docs.cypress.io/guides/references/best-practices) |
| 304 | +- [Cypress Component Testing](https://docs.cypress.io/guides/component-testing/introduction) |
| 305 | +- [Cypress Custom Commands](https://docs.cypress.io/api/cypress-api/custom-commands) |
0 commit comments