CSS Modules — это способ организации стилей в JavaScript-проектах, который позволяет изолировать стили каждого компонента от других. Такой подход помогает избежать конфликтов имен классов и улучшает масштабируемость проектов. Каждый класс или идентификатор, определённый в CSS-файле, автоматически становится уникальным, что позволяет избежать проблем с глобальными стилями.
CSS Modules используют систему преобразования классов, заменяя стандартные классы на уникальные идентификаторы, которые применяются только внутри соответствующего компонента. Это достигается путём обработки стилей с помощью инструмента сборки, например, Webpack.
CSS-файл, использующий CSS Modules, отличается от обычного CSS тем, что в нём используются не обычные классы, а экспорты объектов. Например, в файле стилей:
/* styles.module.css */
.button {
background-color: blue;
}
Данный файл в JavaScript будет импортироваться и использоваться как объект, в котором ключами являются имена классов, а значениями — уникальные имена:
import styles from './styles.module.css';
const Button = () => {
return <button className={styles.button}>Click me</button>;
};
При сборке Webpack или другой сборочной системы применит
трансформацию, и класс button будет заменён на что-то вроде
button_abc123, что и будет уникальным для этого
компонента.
Основная проблема, с которой сталкиваются тестировщики в проектах, использующих глобальные стили, заключается в том, что изменения в одном месте могут повлиять на другие компоненты. CSS Modules решает эту задачу, создавая изолированные стили для каждого компонента. Однако, при тестировании компонентов, необходимо учитывать несколько ключевых аспектов, чтобы гарантировать корректную работу стилей в изолированном контексте.
Тестирование с использованием CSS Modules не так отличается от тестирования обычных компонентов с глобальными стилями, но важно помнить о нюансах, связанных с тем, что классы динамически генерируются при сборке. Поэтому, тестируя компоненты с CSS Modules, нужно удостовериться, что стили действительно применяются корректно, а не зависят от глобальных классов.
При тестировании компонентов с использованием React Testing Library важно понимать несколько ключевых моментов:
Изоляция компонентов: Стили CSS Modules всегда уникальны для конкретного компонента, что помогает минимизировать влияние других стилей. Это позволяет сосредоточиться только на том, что требуется для теста, без учета глобальных изменений.
Проверка классов: Так как классы генерируются динамически, важно убедиться, что они правильно отображаются в сгенерированном HTML. Вместо того чтобы проверять конкретные имена классов, можно использовать атрибуты или проверки визуальных эффектов.
Покрытие стилей в тестах: Для тестирования
стилей можно использовать такие подходы, как проверка наличия нужных
классов, а также проверка стилей через getComputedStyle.
Это позволит точно определить, что компоненты применяют нужные
стили.
Предположим, у нас есть компонент Button, который
использует CSS Modules:
import React from 'react';
import styles from './Button.module.css';
const Button = ({ children }) => {
return (
<button className={styles.button}>
{children}
</button>
);
};
export default Button;
Для его тестирования с использованием React Testing Library нужно проверить, что компонент рендерится с правильным классом, генерируемым через CSS Modules.
import { render } from '@testing-library/react';
import Button from './Button';
import styles from './Button.module.css';
test('Button renders with correct class', () => {
const { container } = render(<Button>Click me</Button>);
const button = container.querySelector('button');
// Проверяем, что класс button применяется к элементу
expect(button).toHaveClass(styles.button);
});
Этот тест проверяет, что элемент button использует
правильный класс, сгенерированный CSS Modules. Важно, что
styles.button будет содержать уникальное имя класса, и
React Testing Library корректно найдет его.
Для тестирования визуальных эффектов, например, изменения фона при
наведении, можно использовать метод getComputedStyle:
test('Button has correct background color', () => {
const { container } = render(<Button>Click me</Button>);
const button = container.querySelector('button');
// Проверяем фоновый цвет кнопки
const style = getComputedStyle(button);
expect(style.backgroundColor).toBe('blue');
});
Такой тест позволяет убедиться, что стили корректно применяются, независимо от того, как были сгенерированы имена классов.
Иногда бывает необходимо замокать стили для тестирования, особенно если они зависят от внешних факторов или если важно тестировать компоненты без применения настоящих стилей. В таких случаях можно использовать моки для CSS Modules.
Пример мока CSS-файла с помощью библиотеки jest:
// __mocks__/styleMock.js
module.exports = {};
После этого в тестах можно будет заменять настоящие стили на пустые объекты, чтобы не зависеть от их внешнего вида:
jest.mock('./Button.module.css', () => require('__mocks__/styleMock.js'));
test('Button renders without styles', () => {
const { container } = render(<Button>Click me</Button>);
const button = container.querySelector('button');
// Проверяем, что элемент всё ещё рендерится, несмотря на отсутствие стилей
expect(button).toBeInTheDocument();
});
В случае, когда стили зависят от состояния компонента, например, при изменении цвета кнопки при наведении, можно использовать React Testing Library для симуляции этих состояний.
Пример с состоянием hover:
import { render, fireEvent } from '@testing-library/react';
import Button from './Button';
test('Button changes background on hover', () => {
const { container } = render(<Button>Click me</Button>);
const button = container.querySelector('button');
fireEvent.mouseOver(button);
const style = getComputedStyle(button);
expect(style.backgroundColor).toBe('red');
});
Этот тест проверяет, что при наведении на кнопку её цвет изменяется.
Важно использовать fireEvent для симуляции событий и
проверки изменения стилей.
getComputedStyle и
fireEvent: Эти методы позволяют тестировать
динамические изменения стилей в реактивных компонентах, что может быть
полезно при проверке анимаций или взаимодействий с пользователем.Тестирование компонентов с CSS Modules в React требует учёта особенностей работы с уникальными классами. При правильном подходе, использование React Testing Library позволяет удобно и эффективно проверять как сами компоненты, так и их визуальное поведение.