Task 10: Create test helper files and base test templates
- Create helpers directory structure - Add api-helpers.ts with authentication and API mocking functions - Add ui-helpers.ts with common UI interaction utilities - Add data-helpers.ts with test data generators - Create base.spec.ts as reusable test template - Update support/index.ts to import and expose helper modules globally
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Base test template for all feature tests
|
||||
* Copy this file and modify for each feature area
|
||||
*/
|
||||
|
||||
import { uiHelpers } from '../support/helpers/ui-helpers'
|
||||
import { apiHelpers } from '../support/helpers/api-helpers'
|
||||
import { dataHelpers } from '../support/helpers/data-helpers'
|
||||
|
||||
describe('Feature: [Feature Name]', () => {
|
||||
beforeEach(() => {
|
||||
// Navigate to app
|
||||
cy.visit('http://localhost:3001')
|
||||
|
||||
// Mock API responses
|
||||
apiHelpers.mockFlightSearch()
|
||||
|
||||
// Get test data
|
||||
const dates = dataHelpers.getTestDates()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
// Clear localStorage (handled by support/index.ts)
|
||||
})
|
||||
|
||||
describe('Scenario: User interaction', () => {
|
||||
it('should perform action and verify result', () => {
|
||||
// Arrange
|
||||
// Setup is in beforeEach
|
||||
|
||||
// Act
|
||||
uiHelpers.fillInput('test-input', 'test-value')
|
||||
uiHelpers.clickAndWait('submit-button', 'flightSearch')
|
||||
|
||||
// Assert
|
||||
uiHelpers.isVisible('results')
|
||||
uiHelpers.hasText('results', 'expected-text')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
describe('Button Component', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('http://localhost:3001')
|
||||
})
|
||||
|
||||
it('should render button with text', () => {
|
||||
cy.get('[data-testid="button"]').should('exist')
|
||||
})
|
||||
|
||||
it('should have correct styling', () => {
|
||||
cy.get('[data-testid="button"]')
|
||||
.should('have.css', 'padding')
|
||||
.should('have.css', 'border-radius')
|
||||
})
|
||||
|
||||
it('should support variant classes', () => {
|
||||
cy.get('[data-testid="button"]').should('have.class', 'button')
|
||||
})
|
||||
|
||||
it('should support size classes', () => {
|
||||
cy.get('[data-testid="button"]').should('have.class', 'button--medium')
|
||||
})
|
||||
|
||||
it('should handle disabled state', () => {
|
||||
cy.get('[data-testid="button"]').should('not.be.disabled')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* API helper functions for e2e tests
|
||||
*/
|
||||
|
||||
export const apiHelpers = {
|
||||
/**
|
||||
* Get auth token (mock for now, will be real API later)
|
||||
*/
|
||||
getAuthToken: () => {
|
||||
return cy.window().then(win => win.localStorage.getItem('auth_token'))
|
||||
},
|
||||
|
||||
/**
|
||||
* Set auth token in localStorage
|
||||
*/
|
||||
setAuthToken: (token: string) => {
|
||||
cy.window().then(win => {
|
||||
win.localStorage.setItem('auth_token', token)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Make API call via cy.request
|
||||
*/
|
||||
apiCall: (method: string, endpoint: string, body?: any) => {
|
||||
return cy.request({
|
||||
method,
|
||||
url: `http://localhost:3000/api${endpoint}`,
|
||||
body,
|
||||
failOnStatusCode: false,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Mock flight search response
|
||||
*/
|
||||
mockFlightSearch: () => {
|
||||
cy.intercept('GET', '**/api/flights/**', {
|
||||
statusCode: 200,
|
||||
body: {
|
||||
flights: [
|
||||
{
|
||||
id: '1',
|
||||
number: 'SU123',
|
||||
departureTime: '10:00',
|
||||
arrivalTime: '12:00',
|
||||
from: 'SVO',
|
||||
to: 'LED',
|
||||
},
|
||||
],
|
||||
},
|
||||
}).as('flightSearch')
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Test data helpers
|
||||
*/
|
||||
|
||||
export const dataHelpers = {
|
||||
/**
|
||||
* Generate random flight number
|
||||
*/
|
||||
generateFlightNumber: () => {
|
||||
return `SU${Math.floor(Math.random() * 9000 + 1000)}`
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate test dates (today, tomorrow, in 7 days)
|
||||
*/
|
||||
getTestDates: () => {
|
||||
const today = new Date()
|
||||
const tomorrow = new Date(today)
|
||||
tomorrow.setDate(tomorrow.getDate() + 1)
|
||||
const weekLater = new Date(today)
|
||||
weekLater.setDate(weekLater.getDate() + 7)
|
||||
|
||||
return {
|
||||
today: today.toISOString().split('T')[0],
|
||||
tomorrow: tomorrow.toISOString().split('T')[0],
|
||||
weekLater: weekLater.toISOString().split('T')[0],
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get major Russian cities for testing
|
||||
*/
|
||||
getMajorCities: () => [
|
||||
{ code: 'SVO', name: 'Moscow (Sheremetyevo)' },
|
||||
{ code: 'LED', name: 'St. Petersburg' },
|
||||
{ code: 'AER', name: 'Sochi' },
|
||||
{ code: 'VVO', name: 'Vladivostok' },
|
||||
{ code: 'SVX', name: 'Ekaterinburg' },
|
||||
],
|
||||
|
||||
/**
|
||||
* Store test data in cy.wrap for later use
|
||||
*/
|
||||
storeData: (key: string, value: any) => {
|
||||
cy.wrap({ [key]: value }).as(key)
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* UI interaction helper functions
|
||||
*/
|
||||
|
||||
export const uiHelpers = {
|
||||
/**
|
||||
* Fill input field and verify value
|
||||
*/
|
||||
fillInput: (testId: string, value: string) => {
|
||||
cy.getByTestId(testId).clear().type(value).should('have.value', value)
|
||||
},
|
||||
|
||||
/**
|
||||
* Select dropdown option
|
||||
*/
|
||||
selectDropdown: (testId: string, optionText: string) => {
|
||||
cy.getByTestId(testId).click()
|
||||
cy.contains(optionText).click()
|
||||
},
|
||||
|
||||
/**
|
||||
* Click button and wait for response
|
||||
*/
|
||||
clickAndWait: (testId: string, waitAlias?: string) => {
|
||||
cy.getByTestId(testId).click()
|
||||
if (waitAlias) {
|
||||
cy.wait(`@${waitAlias}`)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Verify element is visible
|
||||
*/
|
||||
isVisible: (testId: string) => {
|
||||
return cy.getByTestId(testId).should('be.visible')
|
||||
},
|
||||
|
||||
/**
|
||||
* Verify element has text
|
||||
*/
|
||||
hasText: (testId: string, text: string) => {
|
||||
return cy.getByTestId(testId).should('contain', text)
|
||||
},
|
||||
|
||||
/**
|
||||
* Scroll to element
|
||||
*/
|
||||
scrollTo: (testId: string) => {
|
||||
cy.getByTestId(testId).scrollIntoView()
|
||||
},
|
||||
|
||||
/**
|
||||
* Check element exists
|
||||
*/
|
||||
exists: (testId: string) => {
|
||||
return cy.getByTestId(testId).should('exist')
|
||||
},
|
||||
}
|
||||
@@ -1,4 +1,18 @@
|
||||
import './commands'
|
||||
import { apiHelpers } from './helpers/api-helpers'
|
||||
import { uiHelpers } from './helpers/ui-helpers'
|
||||
import { dataHelpers } from './helpers/data-helpers'
|
||||
|
||||
// Make helpers available globally
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
apiHelpers: typeof apiHelpers
|
||||
uiHelpers: typeof uiHelpers
|
||||
dataHelpers: typeof dataHelpers
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
// Clean up after each test
|
||||
|
||||
Reference in New Issue
Block a user