Cypress. Тестируем отдельные компоненты

В одной из предыдущих статей было описано как использовать Cypress для e2e-тестов. Однако, чтобы протестировать побольше сценариев работы приложения удобно использовать тесты отдельных компонентов. С этим типом проверок, не придется загружать полную страницу ненужных в тесте компонентов. Это будет работать быстрее и более прицельно. В этой статье рассмотрим настройку компонентных тестов.

Содержание

Базовый проект с Vuetify

Настройка компонентных тестов была сильно проще, если бы мы не использовали кроме Vue ничего дополнительного. Однако в реальные проекты включают много вещей. Это может быть и какой-то UI-фреймворк и реактивное хранилище.

Рассмотрим настойку тестов Cypress при использовании компонентов Vuetify. На этом примере будет понятно в чем основная проблема и как ее решать.

Создадим проект на базе Vuetify используя вариант с Vite.

В предыдущей статье упоминалось, что после запуска команды npx cypress open мы увидим окно с выбором типа тестов: E2E Testing и Component Testing:

Экран с выбором типа тестов Cypress
Выбор типа тестов

Если выбрать второй вариант и пройти через пару не хитрых шагов по генерированию конфигурационных файлов, то появится экран создания нового теста:

Экран создания первого компонентного теста Cypress
Создание первого компонентного теста Cypress

Первый запуск теста компонента

Здесь мы можем создать тест прямо из компонента. В стартовом наборе файлов проекта Vuetify есть компонент HelloWorld. Выбрав его мы получим простейший тест. Однако запуск такого теста приведет к ошибке:

Запуск теста компонента при настройках Cypress по-умолчанию
Запуск теста компонента при настройках Cypress по-умолчанию

Разбираемся что не так и вносим правки

Происходит это потому, что для vue в таком тесте не регистрируется плагин vuetify. Ведь теперь мы не грузим все приложение, не загружается файл src/main.js и все, что он подключает.

Тест сейчас выглядит так:

import HelloWorld from '@/components/HelloWorld.vue'

describe('<HelloWorld />', () => {
  it('renders component', () => {
    // see: https://on.cypress.io/mounting-vue
    cy.mount(HelloWorld)

    cy.contains('h2', 'Get started')
  })
})

Чтобы плагин vuetify загружался и был корректно настроен нам необходимо изменить команду mount:

import './commands'

import _ from 'lodash'

import { mount } from 'cypress/vue';
import { createVuetify } from 'vuetify';
import 'vuetify/styles'; // Подключение стилей Vuetify

Cypress.Commands.add('mount', (component, options = {}) => {
  const vuetify = createVuetify({
    theme: {
      defaultTheme: 'dark',
    },
  });

  const defaultOptions = {
    global: {
      plugins: [vuetify],
    },
  };

  const mergedOptions = _.merge({}, defaultOptions, options);

  return mount(component, mergedOptions);
});

Здесь мы видим, что через createVuetify настраивается vuetify, передаются нужные опции. Также подключаются стили vuetify/styles. И в итоге передаваемые извне опции mount объединяются с defaultOptions, в котором содержатся нужные нам глобальные настройки.

Если мы захотим также сделать доступным хранилище Pinia, к примеру, то можно будет и его добавить в global:

import { createPinia } from 'pinia'

// ....
  
const pinia = createPinia()

const defaultOptions = {
  global: {
    plugins: [vuetify, pinia],
  },
};

// ....

Если в вашем приложении используются какие-то еще опции Vuetify, то и их тоже надо будет добавить в createVuetify:

import {ru} from 'vuetify/locale'

// ....

const vuetify = createVuetify({
  // ....
  locale: {
    locale: 'ru',
    messages: { ru }
  },
})
// ....

Хотя в тестах часто вместо этого используются различного рода заглушки (mocks).

Запускаем тесты успешно

Теперь наш тест будет успешно выполняться. Можем добавить еще один тест. Проверим как передается свойство в компонент:

import HelloWorld from '@/components/HelloWorld.vue'

describe('<HelloWorld />', () => {
  it('renders component', () => {
    // see: https://on.cypress.io/mounting-vue
    cy.mount(HelloWorld)

    cy.contains('h2', 'Get started')
  })

  it('displays property\'s value', () => {
    const testValue = 'Test property text'
    cy.mount(HelloWorld, {
      props: {
        word: testValue,
      }
    })

    cy.contains('[data-test=property-value]', testValue)
  })
})

Результат запуска выгляди так:

Успешный запуск компонентного теста Cypress
Успешный запуск компонентного теста Cypress

Еще немного глобальных настроек

По-умолчанию Cypress создал файл теста компонента рядом с ним, в его директории. Но, возможно, привычнее будет держать все тесты в одном месте. Для этого в файле cypress.config.js нужно будет указать specPattern и перенести наш тест в cypress/components.

Также обратите внимание на другие опции:

import { defineConfig } from "cypress";

export default defineConfig({
  e2e: {
    specPattern: "cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}",
    baseUrl: "http://localhost:3000",
  },

  component: {
    devServer: {
      framework: "vue",
      bundler: "vite",
    },
    specPattern: 'cypress/components/**/*.cy.{js,jsx,ts,tsx}', // Путь к компонентным тестам
  },

  viewportWidth: 1000,
  viewportHeight: 900,
});

Итоги

В результате мы имеем возможность тестировать отдельные компоненты в Cypress. Мы сможем делать больше тестов и делать их быстрее. Вместе с e2e тестами, которые рассматривались в одной из прошлых статей, приложение получит лучшее покрытие тестами.

Вы можете скачать репозиторий примера из статьи и ознакомиться с кодом поближе.

В следующих статьях я продолжу знакомство с Cypress. Будет разобран параллельный запуск тестов и Cypress Dashboard.

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии