Fixtures в Cypress представляют собой статические файлы с тестовыми
данными, которые можно использовать для имитации ответов API, заполнения
форм или любых других сценариев, где требуется постоянный набор данных.
Они обычно хранятся в папке cypress/fixtures и поддерживают
форматы JSON, CSV, TXT и другие. Для эффективного использования fixtures
в TypeScript или с проверкой типов в JavaScript важно корректно
определять и использовать типы данных.
В Cypress существует несколько способов загрузки данных из fixture:
// Асинхронная загрузка через cy.fixture()
cy.fixture('user.json').then((user) => {
cy.log(user.name);
});
// Использование alias
cy.fixture('user.json').as('userData');
cy.get('@userData').then((user) => {
cy.log(user.email);
});
При этом user будет объектом, автоматически приведенным
к типу any в JavaScript. В TypeScript рекомендуется явно
задавать интерфейсы для повышения безопасности типов.
Если используется TypeScript, можно создать интерфейс для структуры данных fixture:
// cypress/fixtures/user.json
/*
{
"id": 1,
"name": "John Doe",
"email": "john@example.com"
}
*/
// types/user.ts
export interface User {
id: number;
name: string;
email: string;
}
// В тесте
import { User } from '../types/user';
cy.fixture('user.json').then((user: User) => {
expect(user.id).to.equal(1);
expect(user.name).to.be.a('string');
});
Использование интерфейсов позволяет избежать ошибок при доступе к полям и упрощает автодополнение в редакторах кода.
Для fixtures, содержащих массив объектов, можно определить тип как массив интерфейсов:
// cypress/fixtures/users.json
/*
[
{ "id": 1, "name": "John" },
{ "id": 2, "name": "Jane" }
]
*/
import { User } from '../types/user';
cy.fixture('users.json').then((users: User[]) => {
expect(users).to.have.length(2);
expect(users[0].name).to.equal('John');
});
Это обеспечивает строгую проверку всех элементов массива и предотвращает случайный доступ к несуществующим полям.
В сложных сценариях тестов часто требуется использовать несколько fixtures одновременно:
cy.fixture('user.json').then((user: User) => {
cy.fixture('settings.json').then((settings: any) => {
cy.log(`${user.name} - theme: ${settings.theme}`);
});
});
Для более чистого кода можно использовать
Promise.all:
Promise.all([
cy.fixture('user.json'),
cy.fixture('settings.json')
]).then(([user, settings]: [User, any]) => {
cy.log(`${user.name} - theme: ${settings.theme}`);
});
Такой подход позволяет объединять типы данных и сохранять строгую типизацию.
Alias можно типизировать для удобного доступа:
cy.fixture('user.json').as('userData');
cy.get<User>('@userData').then((user) => {
expect(user.email).to.match(/@/);
});
Типизация alias повышает читаемость кода и предотвращает ошибки при
обращении к fixture через @userData.
В некоторых случаях структура fixture может меняться в зависимости от
сценария. В таких ситуациях можно использовать объединение
типов или Partial:
interface UserPartial {
id?: number;
name?: string;
email?: string;
}
cy.fixture('user_partial.json').then((user: Partial<User>) => {
if (user.email) {
cy.log(user.email);
}
});
Partial<User> позволяет работать с частично
заполненными объектами, не вызывая ошибок TypeScript при отсутствии
полей.
Для крупных проектов целесообразно использовать генерацию типов из JSON:
npx quicktype -s json -o cypress/types/user.ts cypress/fixtures/user.json
Это позволяет автоматически создавать интерфейсы, полностью соответствующие данным в fixture, и уменьшает риск рассинхронизации между тестами и данными.
Partial или объединения для динамических
структур.Типизация fixtures в Cypress повышает стабильность тестов, снижает вероятность ошибок и улучшает поддержку кода в долгосрочной перспективе. При правильной организации интерфейсов и alias можно легко управлять как простыми, так и сложными структурами данных.