## Быстрый старт - `yarn test` — запускает все unit-тесты; - `yarn test:e2e` — запускает в Docker-контейнере скриншотные тесты; - `yarn test:e2e-update` — запускает в Docker-контейнере обновление скриншотных тестов. ## Виды тестов ### Unit-тесты Используем: - [vitest](https://vitest.dev/) - [react-testing-library](https://testing-library.com/docs/react-testing-library/example-intro) - [vitest-axe](https://github.com/chaance/vitest-axe) Описываем в файлах: - Если это обычная функция, то `moduleName.test.ts`, (например, [`packages/vkui/src/lib/adaptivity/functions.test.ts`](../packages/vkui/src/lib/adaptivity/functions.test.ts)) - Если это React-компонент, то `ComponentName.test.ts` (например, [`Checkbox.test.tsx`](../packages/vkui/src/components/Checkbox/Checkbox.test.tsx)) ### Скриншотные тесты Используем: - [@playwright/experimental-ct-react](https://playwright.dev/docs/test-components) - [git-lfs](https://git-lfs.github.com) – помогает от раздувания репозитория из-за эталонных скриншотов. - [Docker](https://www.docker.com/products/docker-desktop) – запускаем тесты в докере, чтобы для тестов было одинаковое окружение, что в CI, что локально. Этим достигается одинаковый рендер страницы. Для примера, шрифты рендерятся по разному в зависимости от ОС. Описываем в файлах: - Тест-кейсы и вызов API Playwright в `ComponentName.e2e.tsx` (например, [Accordion.e2e.tsx](../packages/vkui/src/components/Accordion/Accordion.e2e.tsx)) - Примеры компонента в `ComponentName.e2e-playground.tsx` (например, [Accordion.e2e-playground.tsx](../packages/vkui/src/components/Accordion/Accordion.e2e-playgrgound.tsx)) > Выносим в отдельный файл из-за особенностей Playwright. > > Ссылки по теме: > > - [Why can't I pass a variable to mount?](https://playwright.dev/docs/test-components#q-why-cant-i-pass-a-variable-to-mount) > - [playwright issue #18481](https://github.com/microsoft/playwright/issues/18481) Настраиваем: - В папке [packages/vkui/src/testing/e2e](../packages/vkui/src/testing/e2e) задаём кастомные свойства, создаём утилитарные функции уменьшающие бойлерплейт. Вот основные помощники: - [constants.ts](../packages/vkui/src/testing/e2e/constants.ts) – стоит обратить внимание на `TEST_CLASS_NAMES` (ищи примеры использования в коде). - [ComponentPlayground](../packages/vkui/src/testing/e2e/ComponentPlayground.tsx) – помогает создавать песочницу компонентов с разными вариациями его параметров. - [screenshotWithClipToContent](../packages/vkui/src/testing/e2e/screenshotWithClipToContent.ts) – обрезает скриншот до контентной части. > Напрямую её использовать не придётся. Она используется в `expectScreenshotClippedToContent()`, которая доступна через аргументы `test`. > > ```ts > test('base', ({ expectScreenshotClippedToContent }) => { > // ... > await expectScreenshotClippedToContent(); > }); > ``` - В папке [packages/vkui/playwright](../packages/vkui/playwright) подключаем шрифты, подключаем CSS, подготавливаем HTML файл. - В файле [packages/vkui/playwright-сt.config.ts](../packages/vkui/playwright-сt.config.ts) конфигурируем Playwright. - В файле `env.development.local` определяем переменные окружения для удобства локального тестирования. #### Как формируются названия скриншотов? За это отвечает функцию [generateCustomScreenshotName](../packages/vkui/src/testing/e2e/utils.ts), которая используется внутри `expectScreenshotClippedToContent()`. Далее примеры того как отработает функция. Как входные данные возьмём: - platform: 'android' - browserName: 'chromium' - colorScheme: 'light' ```tsx test('Example', async ({ expectScreenshotClippedToContent }) => { // ... await expectScreenshotClippedToContent(); // => мы получим скриншот с названием 'example-android-chromium-light-1-snap.png' await expectScreenshotClippedToContent(); // => мы получим скриншот с названием 'example-android-chromium-light-2-snap.png' }); test.describe('Example', () => { test('My AWESOME case description', async ({ expectScreenshotClippedToContent }) => { // ... await expectScreenshotClippedToContent(); // => мы получим скриншот с названием 'example-android-chromium-light-my-awesome-case-description-1-snap.png' }); }); ``` #### Запускаем тесты только для конкретных платформ 1. Используем `test.use({ onlyForPlatforms: [] })`, которая через `test.skip` будет пропускать тест если платформа `platform` не удовлетворяет условию. 2. Если в тестовом файле есть другие тесты, то оборачиваем в `test.describe`, иначе `test.use` будет применять и на них. Пример ```tsx // Accordion.e2e.tsx import { test } from '@vkui-e2e/test'; import { AccordionPlayground } from './Accordion.e2e-playground'; test.describe(() => { // Будет применяться для всех тестов внутри `test.describe('Accordion')` test.use({ onlyForPlatforms: ['vkcom'] }); test('Accordion', async ({ mount expectScreenshotClippedToContent componentPlaygroundProps }) => { await mount(); await expectScreenshotClippedToContent(); }); }); // На эти тесты не влияет test('Accordion', () => {}); test.describe(() => { test('Accordion', () => {}); }); ``` #### Зашиваем параметры адаптивности 1. Используем `test.use({ adaptivityProviderProps: {} })`; 2. Если в тестовом файле есть другие тесты, то оборачиваем в `test.describe`, иначе `test.use` будет применять и на них. Пример ```tsx // Accordion.e2e.tsx import { test } from '@vkui-e2e/test'; import { ViewWidth } from '../../lib/adaptivity'; import { AccordionPlayground } from './Accordion.e2e-playground'; test.describe(() => { // Будет применяться для всех тестов внутри `test.describe('Accordion')` test.use({ adaptivityProviderProps: { viewWidth: ViewWidth.TABLET } }); test('Accordion', async ({ mount expectScreenshotClippedToContent componentPlaygroundProps }) => { await mount(); await expectScreenshotClippedToContent(); }); }); // На эти тесты не влияет test('Accordion', () => {}); test.describe(() => { test('Accordion', () => {}); }); ``` #### Debug Для начала надо будет скачать браузеры, делаем это следующей командой: ``` yarn run playwright:install ``` Далее копируем `.env.development.local` файл: ```sh cp packages/vkui/.env.development.local packages/vkui/.env ``` И читаем комментарии к константам в файле `.env`. Там будут сразу примеры. ##### Live Debugging 1. В `.env` задаём желаемый проект и тест файл. 2. Запускаем команду ``` yarn test:e2e:ci --debug ``` 3. Запустится Playwright DevTools и указанный браузер. > Подробнее см. https://playwright.dev/docs/debug#live-debugging #### Troubleshooting ##### Q) Почему при запуске `test:e2e`/`test:e2e-update` падает команда `playwright test --config ...`? В первую очередь смотрим лог ошибки. Если команда падает не успев пройтись по тест файлу, то скорей всего дело может быть в кэше Playwright. Например, был вот такой кейс, что в файле `Accordion.e2e-playground.tsx` переименовали экспортируемый компонент с `AccordionE2EPlayground` на `AccordionPlayground` и команда упала со следующей ошибкой: ```sh vkui-package_vkui-1 | $ playwright test --config playwright-ct.config.ts -u vkui-package_vkui-1 | vkui-package_vkui-1 | Running 10 tests using 2 workers vkui-package_vkui-1 | vkui-package_vkui-1 | vite v4.2.1 building for production... vkui-package_vkui-1 | transforming... vkui-package_vkui-1 | Error when using sourcemap for reporting an error: Can't resolve original location of error. vkui-package_vkui-1 | ✓ 2616 modules transformed. vkui-package_vkui-1 | ✓ built in 3.67s vkui-package_vkui-1 | "AccordionE2EPlayground" is not exported by "src/components/Accordion/Accordion.e2e-playground.tsx", imported by "playwright/index.tsx". ``` Очистили кэш, запустили заново тесты и ошибка пропала. Чтобы очистить кэш выполните: ```sh yarn workspace @vkontakte/vkui run docker:clear-playwright-cache ``` ## Покрытие Чтобы сгенерировать карту покрытия для `coverage/lcov/index.html`: > Note: карта покрытия будет создана только для пакета `@vkontakte/vkui` ```sh yarn test:ci && yarn test:coverage ```