Компонентное тестирование в JavaScript направлено на проверку отдельных частей приложения — компонентов — в изоляции от остального кода. В отличие от интеграционного тестирования, где проверяется взаимодействие нескольких модулей, компонентные тесты фокусируются на функциональности, поведении и визуальном отображении одного компонента.
Изоляция Каждый тест должен проверять только конкретный компонент. Любые внешние зависимости, такие как API или глобальные состояния, должны быть замоканы или заменены стабами. Это позволяет выявлять ошибки именно в компоненте, а не в его окружении.
Предсказуемость Тесты должны работать одинаково при каждом запуске. Для этого важно контролировать входные данные, состояние компонентов и окружение браузера.
Минимализм и конкретность Каждый тест охватывает один сценарий поведения или один аспект визуального отображения. Если проверяются несколько функций одновременно, в случае ошибки будет сложно определить причину.
Cypress предоставляет отдельный режим для работы с компонентами. Основные шаги настройки включают:
npm install cypress --save-dev
npx cypress open-ct
cypress.config.js с указанием фреймворка и
файлов тестов:const { defineConfig } = require('cypress')
module.exports = defineConfig({
component: {
devServer: {
framework: 'react',
bundler: 'webpack'
},
specPattern: 'cypress/component/**/*.cy.{js,jsx,ts,tsx}'
}
})
Компонентные тесты в Cypress имеют схожую структуру с e2e-тестами, но с рядом особенностей:
import Button from '../. ./src/components/Button'
import { mount } from 'cypress/react18'
describe('Button', () => {
it('отображает текст', () => {
mount(<Button label="Нажми меня" />)
cy.contains('Нажми меня').should('be.visible')
})
})
it('вызывает обработчик клика', () => {
const onCl ick = cy.stub()
mount(<Button label="Клик" onCl ick={onClick} />)
cy.get('button').click().then(() => {
expect(onClick).to.have.been.calledOnce
})
})
it('имеет правильный класс для primary', () => {
mount(<Button label="Главная" variant="primary" />)
cy.get('button').should('have.class', 'btn-primary')
})
Для изоляции компонентов важно заменять внешние зависимости:
cy.intercept для создания заглушек API.cy.intercept('GET', '/api/data', { fixture: 'data.json' })
import { Provider } from 'react-redux'
import store from '../. ./src/store'
mount(
<Provider store={store}>
<MyComponent />
</Provider>
)
Cypress поддерживает проверку визуальной составляющей:
cy.get('button').toMatchImageSnapshot()
should('be.visible') или
should('have.text', '...').Многие компоненты используют асинхронные операции (например, загрузка данных). Cypress автоматически ждёт завершения промисов и обновления DOM. Основные методы:
cy.wait() для ожидания конкретных сетевых запросовcy.contains() или cy.get().should() для
проверки, что элемент появился после асинхронной операцииCypress легко интегрируется с системами непрерывной интеграции:
npx cypress run-ct
Компонентное тестирование с Cypress позволяет создавать надёжные, быстрые и поддерживаемые тесты, обеспечивая качественное развитие интерфейсных частей приложения.