Fix code quality issues in E2E Cypress infrastructure

- Fix specPattern in cypress.config.ts: change from '*.cy.ts' to '*.spec.ts' to match actual test file naming convention
- Fix forbidGeolocation command: use callsFake() instead of rejects() which is not a valid Cypress stub method
- Remove redundant localStorage cleanup: keep only afterEach hook, remove beforeEach hook to avoid duplication
- Remove unused @cypress/schematic dependency from e2e/package.json
- Add comprehensive README.md with E2E testing documentation covering test structure, setup, running tests, custom commands, and best practices
This commit is contained in:
gnezim
2026-04-05 19:09:43 +03:00
parent 6ed2a3e65a
commit e0c989755e
5 changed files with 231 additions and 11 deletions
+226
View File
@@ -0,0 +1,226 @@
# E2E Testing Infrastructure
This directory contains end-to-end testing infrastructure for the Aeroflot Flights web application, including Cypress tests and visual regression testing with BackstopJS.
## Directory Structure
```
e2e/
├── cypress/
│ ├── integration/ # E2E test files organized by feature
│ │ ├── accessibility/ # Accessibility tests
│ │ ├── components/ # Component-level tests
│ │ ├── error-handling/ # Error handling tests
│ │ ├── flight-details/ # Flight details page tests
│ │ ├── flights-map/ # Flight map tests
│ │ ├── i18n/ # Internationalization tests
│ │ ├── integration/ # Cross-feature integration tests
│ │ ├── navigation/ # Navigation flow tests
│ │ ├── online-board/ # Online board tests
│ │ ├── performance/ # Performance tests
│ │ ├── responsive/ # Responsive design tests
│ │ ├── schedule/ # Schedule tests
│ │ └── search-history/ # Search history tests
│ └── support/
│ ├── index.ts # Global test setup and hooks
│ └── commands.ts # Custom Cypress commands
├── backstop/ # Visual regression testing config
├── cypress.config.ts # Cypress configuration
├── package.json # E2E dependencies
├── tsconfig.json # TypeScript configuration
└── scripts/ # Test utility scripts
```
## Test File Naming
All test files must follow the naming pattern: `*.spec.ts`
Example test files:
- `cypress/integration/search-history/search-history-filtering.spec.ts`
- `cypress/integration/flight-details/flight-details-display.spec.ts`
## Setup
### Install Dependencies
```bash
npm install
```
### Environment Configuration
The test suite uses the following configuration from `cypress.config.ts`:
- **Base URL**: `http://localhost:3000` (React development server)
- **Viewport**: 1440x900 (desktop)
- **Timeouts**: 10 seconds for requests, responses, and commands
- **Screenshots**: Enabled on test failure
- **Videos**: Disabled (can be enabled in cypress.config.ts if needed)
## Running Tests
### Open Cypress Test Runner (Interactive Mode)
```bash
npm run cypress:open
```
This opens the Cypress test runner UI where you can:
- View and run individual tests
- Debug with browser DevTools
- See real-time test execution
- Inspect elements and network calls
### Run Tests Headlessly
```bash
npm run cypress:run
```
This runs all tests in headless mode and generates a test report.
### Run Specific Test Suite
```bash
npx cypress run --spec "cypress/integration/search-history/*.spec.ts"
```
### Run Tests with Specific Browser
```bash
npx cypress run --browser chrome
npx cypress run --browser firefox
npx cypress run --browser edge
```
## Custom Commands
### getByTestId(id: string, timeout?: number)
Select elements by test ID attribute for more reliable element selection.
```typescript
cy.getByTestId('search-button').click()
cy.getByTestId('flight-results', 5000).should('exist')
```
### forbidGeolocation()
Mock the geolocation API to return an error, useful for testing geolocation-denied scenarios.
```typescript
cy.forbidGeolocation()
// Now geolocation calls will fail
```
## Test Hooks
### afterEach Hook
Automatically clears browser localStorage after each test to ensure test isolation and prevent state leakage between tests.
```typescript
// Automatically runs after every test
afterEach(() => {
cy.window().then(win => {
win.localStorage.clear()
})
})
```
## Visual Regression Testing (BackstopJS)
The e2e folder includes BackstopJS for visual regression testing.
### Create Reference Screenshots
```bash
npm run backstop:reference
```
This creates baseline screenshots using the Angular version (`backstop/backstop-angular.json`).
### Run Visual Tests
```bash
npm run backstop:test
```
This compares current React version screenshots against the Angular baseline (`backstop/backstop-react.json`).
## Test Best Practices
1. **Use data-testid attributes**: Always add `data-testid` to elements you want to test
```html
<button data-testid="search-button">Search</button>
```
2. **Avoid brittle selectors**: Don't rely on class names or IDs that change frequently
3. **Use meaningful test names**: Describe what the test verifies
```typescript
it('should filter search results when filter is applied', () => {
// test code
})
```
4. **Test user workflows**: Write tests that simulate real user interactions
```typescript
cy.getByTestId('destination-input').type('Moscow')
cy.getByTestId('search-button').click()
cy.getByTestId('flight-results').should('be.visible')
```
5. **Keep tests independent**: Each test should be able to run in any order
- Use `afterEach` to clean up state (already configured)
- Don't depend on data from other tests
6. **Handle async operations**: Use proper timeouts and waits
```typescript
cy.getByTestId('loading-spinner', 10000).should('not.exist')
cy.getByTestId('results-list').should('have.length.greaterThan', 0)
```
7. **Mock API responses when appropriate**: Use Cypress intercept for predictable tests
```typescript
cy.intercept('GET', '/api/flights/*', { fixture: 'flights.json' })
```
## Validation Script
Run the full validation suite (includes e2e tests):
```bash
npm run validate
```
## Troubleshooting
### Tests timing out
- Increase timeout values in `cypress.config.ts`
- Check if the application is running on http://localhost:3000
- Verify network connectivity to backend API
### Element not found errors
- Ensure `data-testid` attributes exist in the React components
- Wait for elements to be visible: `cy.getByTestId('element').should('be.visible')`
- Check browser console for JavaScript errors
### localStorage not clearing between tests
- The `afterEach` hook should handle this automatically
- Verify the hook is not being overridden in individual test files
## CI/CD Integration
For CI/CD pipelines, use:
```bash
npm run cypress:run # Headless test execution
```
Ensure the React development server is running on port 3000 before executing tests.
## Additional Resources
- [Cypress Documentation](https://docs.cypress.io)
- [BackstopJS Documentation](https://garris.github.io/BackstopJS/)
- [Testing Best Practices](https://docs.cypress.io/guides/references/best-practices)
+1 -1
View File
@@ -4,7 +4,7 @@ export default defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
supportFile: 'cypress/support/index.ts',
specPattern: 'cypress/integration/**/*.cy.ts',
specPattern: 'cypress/integration/**/*.spec.ts',
viewportWidth: 1440,
viewportHeight: 900,
video: false,
+4 -2
View File
@@ -6,8 +6,10 @@ Cypress.Commands.add('getByTestId', (id: string, timeout = 8000) => {
Cypress.Commands.add('forbidGeolocation', () => {
cy.window().then(win => {
cy.stub(win.navigator.geolocation, 'getCurrentPosition').rejects(
new Error('Geolocation forbidden')
cy.stub(win.navigator.geolocation, 'getCurrentPosition').callsFake(
(success, error) => {
error(new GeolocationPositionError())
}
)
})
})
-7
View File
@@ -1,12 +1,5 @@
import './commands'
beforeEach(() => {
// Clear localStorage before each test
cy.window().then(win => {
win.localStorage.clear()
})
})
afterEach(() => {
// Clean up after each test
cy.window().then(win => {
-1
View File
@@ -12,7 +12,6 @@
"devDependencies": {
"cypress": "^13.6.0",
"backstopjs": "^6.3.0",
"@cypress/schematic": "^2.5.0",
"typescript": "^5.3.0"
}
}