Модульное тестирование React с помощью Jest

модульный тест React.js Jest тестовое задание
Модульное тестирование React с помощью Jest

Решение для модульного тестирования React

Предварительное знание

Зачем тестировать

  1. Тестирование гарантирует ожидаемые результаты
  2. как описание поведения существующего кода
  3. Поощряйте разработчиков писать тестируемый код, обычно тестируемый код будет более читабельным.
  4. Если зависимый компонент изменен, затронутый компонент может найти ошибку в тесте.

тип теста

  • Модульное тестирование: относится к тестированию программного обеспечения в единицах оригинала. Блок может быть функцией, модулем или компонентом.Основная особенность заключается в том, что пока вход остается неизменным, он должен возвращать тот же результат. Чем проще программное обеспечение для модульного тестирования, тем лучше его модульная структура и тем слабее связь между модулями. Компонентизация React и функциональное программирование, естественное для модульного тестирования
  • Функциональное тестирование: Эквивалентно тестированию методом "черного ящика". Тестировщик не знает внутренней ситуации программы и не нуждается в специальных знаниях языков программирования. Он знает только ввод, вывод и функции программы. независимо от внутренней логики
  • Интеграционное тестирование: на основе модульного тестирования все модули собираются в подсистемы или системы в соответствии с проектными требованиями и тестируются.
  • Дымовой тест: перед формальным и всеобъемлющим тестом основные функции проверяются, чтобы подтвердить, соответствуют ли основные функции потребностям и может ли программное обеспечение работать нормально.

режим разработки

  • TDD: Test-driven development, на английском языке Testing Driven Development, что подчеркивает метод разработки, который управляет всем проектом с помощью тестов, то есть сначала завершает написание теста в соответствии с интерфейсом, а затем непрерывно проходит тест, когда функция завершена, и конечная цель пройти все испытания
  • BDD: Behavior-driven testing, Behavior Driven Development на английском языке, делает акцент на стиле написания тестов, то есть тесты должны быть написаны как на естественном языке, чтобы каждый участник проекта и даже продукта мог понять тест, и даже написать тест. тестовое задание

TDD и BDD имеют свои сценарии использования, BDD в целом ориентирован на автоматизированное тестирование системных функций и бизнес-логики, тогда как TDD более эффективен в процессе быстрой разработки и тестирования функциональных модулей с целью быстрого завершения разработки.

Выбор технологии: Jest + Enzyme

Jest

Jest — это среда тестирования интерфейса с открытым исходным кодом Facebook, которая в основном используется для модульного тестирования React и React Native и интегрирована в приложение create-react-app. Особенности шутки:

  1. Простота использования: основанный на Jasmine, он предоставляет библиотеку утверждений и поддерживает несколько стилей тестирования.
  2. Адаптивность: Jest является модульным, расширяемым и настраиваемым.
  3. Песочница и снимок: Jest имеет встроенный JSDOM, который может имитировать среду браузера и выполнять ее параллельно.
  4. Тестирование моментальных снимков: Jest может сериализовать дерево компонентов React, создавать соответствующие моментальные снимки строк и обеспечивать высокопроизводительное обнаружение пользовательского интерфейса путем сравнения строк.
  5. Система Mock: Jest реализует мощную систему Mock, которая поддерживает автоматическое и ручное создание макетов.
  6. Поддержка асинхронного тестирования кода: поддержка Promise и async/await.
  7. Автоматически генерировать результаты статического анализа: встроенный Стамбул, тестовое покрытие кода и генерировать соответствующие отчеты.

Enzyme

Enzyme – это библиотека инструментов тестирования React с открытым исходным кодом от Airbnb. Она функционирует как вторичная инкапсуляция официальной библиотеки инструментов тестирования ReactTestUtils, предоставляет набор кратких и мощных API и имеет встроенный Cheerio.

Обработка DOM реализована в стиле jQuery, и опыт разработки очень удобен. Он очень популярен в сообществе с открытым исходным кодом, а также официально рекомендован React.

Настройка тестовой среды

Установите Jest, Enzyme и babel-jest. Если версия React 15 или 16, вам необходимо установить и настроить соответствующий энзим-адаптер-реагировать-15 и энзим-адаптер-реагировать-16.

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new Adapter() });

Добавьте «test: jest --config .jest.js» в скрипт в package.json.

.jest.js文件

module.exports = {
  setupFiles: [
    './test/setup.js',
  ],
  moduleFileExtensions: [
    'js',
    'jsx',
  ],
  testPathIgnorePatterns: [
    '/node_modules/',
  ],
  testRegex: '.*\\.test\\.js$',
  collectCoverage: false,
  collectCoverageFrom: [
    'src/components/**/*.{js}',
  ],
  moduleNameMapper: {
    "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
    "\\.(css|less|scss)$": "<rootDir>/__mocks__/styleMock.js"
  },
  transform: {
    "^.+\\.js$": "babel-jest"
  },
};
  • setupFiles: файл конфигурации, перед запуском кода тестового примера Jest запустит здесь файл конфигурации, чтобы инициализировать указанную тестовую среду.
  • moduleFileExtensions: представляет имена файлов, которые поддерживают загрузку
  • testPathIgnorePatterns: используйте регулярные выражения для поиска непроверенных файлов.
  • testRegex: тестовый файл в обычном представлении, формат тестового файла xxx.test.js
  • collectCoverage: следует ли генерировать отчет о тестовом покрытии, если он включен, это увеличит время тестирования.
  • collectCoverageFrom: создайте отчет о тестовом покрытии, который обнаруживает файлы покрытия.
  • moduleNameMapper: представляет имя ресурса, который необходимо имитировать.
  • преобразование: используйте babel-jest для компиляции файлов для генерации синтаксиса ES6/7.

Jest

globals API

  • описать(имя, фн): описать блок, в котором рассказывается о группе функционально связанных тестовых случаев, сгруппированных вместе
  • it(name, fn, timeout): псевдоним test, используется для размещения тестовых случаев
  • afterAll(fn, timeout): метод, который будет выполняться после выполнения всех тестовых случаев.
  • beforeAll(fn, timeout): метод, который должен быть выполнен до того, как будут выполнены все тестовые примеры
  • afterEach(fn): метод, который будет выполняться после выполнения каждого теста.
  • dobedeach (Fn): метод, который должен быть выполнен до выполнения каждого тестового корпуса

Global и Describe могут иметь указанные выше четыре функции цикла.Приоритет функции AFTER в Describe выше, чем у общей функции AFTER, а приоритет функции Before в Describe ниже, чем у глобальной функции Before.

beforeAll(() => {
  console.log('global before all');
});

afterAll(() => {
  console.log('global after all');
});

beforeEach(() =>{
  console.log('global before each');
});

afterEach(() => {
  console.log('global after each');
});

describe('test1', () => {
  beforeAll(() => {
    console.log('test1 before all');
  });
  
  afterAll(() => {
    console.log('test1 after all');
  });
  
  beforeEach(() => {
    console.log('test1 before each');
  });
  
  afterEach(() => {
    console.log('test1 after each');
  });
  
  it('test sum', () => {
    expect(sum(2, 3)).toEqual(5);
  });
  
  it('test mutil', () => {
    expect(sum(2, 3)).toEqual(7);
  });
  
});

config

Jest имеет множество элементов конфигурации, которые можно записать в package.json, чтобы добавить поля jest для настройки, или указать файл конфигурации через командную строку --config.

объект шутки

  • jest.fn(реализация): возвращает совершенно новую фиктивную функцию, которая не использовалась.При вызове этой функции будет записано много информации, связанной с вызовом функции.
  • jest.mock(moduleName, factory, options): используется для имитации некоторых модулей или файлов.
  • jest.spyOn(object, methodName): возвращает фиктивную функцию, похожую на jest.fn, но способную отслеживать информацию о вызове объекта [methodName], аналогичную Sinon.

Mock Functions

С помощью mock-функции можно легко смоделировать зависимости между кодами: с помощью fn или spyOn смоделировать конкретную функцию, с помощью mocking смоделировать модуль. Конкретный API можно увидетьmock-function-api.

снимок

Моментальный снимок создаст структуру пользовательского интерфейса компонента и сохранит ее в файле __snapshots__ в виде строки.Сравнивая две строки, чтобы определить, изменился ли пользовательский интерфейс, поскольку это сравнение строк, производительность очень высока.

Чтобы использовать функцию моментального снимка, вам необходимо внедрить библиотеку react-test-renderer и использовать в ней метод renderer.Если jest обнаружит метод toMatchSnapshot во время выполнения, в том же каталоге будет сгенерирована папка __snapshots для хранения файлов моментальных снимков. Каждый тест сравнивается со снимком, созданным в первый раз. Файлы снимков можно обновить с помощью jest --updateSnapshot.

Асинхронное тестирование

Jest поддерживает асинхронное тестирование и поддерживает асинхронное тестирование двумя способами: Promise и Async/Await.

Общее утверждение

  1. ожидание (значение): если вы хотите проверить значение для утверждения, используйте ожидание, чтобы обернуть значение
  2. toBe(value): используйте Object.is для сравнения, если вы сравниваете числа с плавающей запятой, используйте toBeCloseTo
  3. не: используется для отрицания
  4. toEqual(value): для глубокого сравнения объектов
  5. toMatch(regexpOrString): используется для проверки соответствия строки, это может быть регулярное выражение или строка
  6. toContain(item): используется для определения того, находится ли элемент в массиве или нет, его также можно использовать для оценки строки
  7. toBeNull (значение): соответствует только нулю
  8. toBeUndefined (значение): соответствует только undefined
  9. Tobedefined (значение): в отличие от TOBEUNDEFINED
  10. toBeTruthy(value): соответствует любому значению, которое делает оператор if истинным
  11. toBeFalsy(value): соответствует любому значению, которое делает оператор if ложным
  12. toBeGreaterThan (число): больше, чем
  13. toBeGreaterThanOrEqual(число): больше или равно
  14. toBeLessThan(число): меньше чем
  15. toBeLessThanOrEqual(число): меньше или равно
  16. toBeInstanceOf (класс): определить, является ли он экземпляром класса
  17. что-либо (значение): соответствует всем значениям, кроме нулевого и неопределенного
  18. разрешает: используется для извлечения значения, обернутого при выполнении обещания, поддерживает цепные вызовы
  19. rejects: используется для извлечения значения, обернутого при отклонении промиса, поддерживает цепочку вызовов
  20. toHaveBeenCalled(): используется для определения того, была ли вызвана фиктивная функция.
  21. toHaveBeenCalledTimes(number): используется для определения количества вызовов фиктивной функции.
  22. Утверждения (число): Убедитесь, что есть утверждение числа называется тестовым случаем
  23. Расширение (Matchers): пользовательские утверждения

Enzyme

Три метода рендеринга

  1. Shallow: поверхностный рендеринг, который является инкапсуляцией официального Shallow Renderer. Рендеринг компонентов в виртуальные объекты DOM будет отображать только первый слой, а подкомпоненты не будут отображаться, что делает его очень эффективным. Не требует среды DOM и может использовать jQuery для доступа к информации о компонентах.
  2. render: статическая визуализация, которая преобразует компонент React в статическую строку HTML, а затем использует библиотеку Cheerio для анализа этой строки и возвращает объект экземпляра Cheerio, который можно использовать для анализа структуры HTML компонента.
  3. mount: полный рендеринг, который рендерит и загружает компонент в реальный DOM-узел, который используется для проверки взаимодействия DOM API и жизненного цикла компонента. jsdom используется для имитации среды браузера.

Среди этих трех методов мелкое и монтирование могут использовать симуляцию для интерактивного моделирования, поскольку они возвращают объекты DOM, а метод рендеринга — нет. Как правило, поверхностный метод может соответствовать требованиям.Если вам нужно оценить подкомпонент, вам нужно использовать метод рендеринга.Если вам нужно проверить жизненный цикл компонента, вам нужно использовать метод монтирования.

Общий метод

  1. Simulate (Event, Mock): аналоговые события, используемые для запуска событий, Event — это имя события, Mock — это объект события.
  2. instance(): возвращает экземпляр компонента
  3. find (селектор): поиск узлов в соответствии с селектором, селектор может быть селектором в CSS или конструктором компонента, отображаемым именем компонента и т. д.
  4. at(index): возвращает визуализированный объект
  5. get(index): возвращает узел реакции, чтобы протестировать его, его необходимо повторно отобразить.
  6. содержит (nodeOrNodes): содержит ли текущий объект ключевой узел параметра, тип параметра — объект реакции или массив объектов.
  7. text (): возвращает текущий текстовый компонент
  8. html(): возвращает форму HTML-кода текущего компонента.
  9. props(): возвращает все свойства корневого компонента.
  10. prop(key): возвращает указанное свойство корневого компонента.
  11. state(): возвращает состояние корневого компонента.
  12. setState(nextState): установить состояние корневого компонента
  13. setProps(nextProps): установить свойства корневого компонента

Пишите тестовые случаи

код компонента

todo-list/index.js

import React, { Component } from 'react';
import { Button } from 'antd';

export default class TodoList extends Component {
  constructor(props) {
    super(props);
    this.handleTest2 = this.handleTest2.bind(this);
  }
  handleTest = () => {
    console.log('test');
  }

  handleTest2() {
    console.log('test2');
  }

  componentDidMount() {}

  render() {
    return (
      <div className="todo-list">
        {this.props.list.map((todo, index) => (<div key={index}>
          <span className="item-text ">{todo}</span>
          <Button onClick={() => this.props.deleteTodo(index)} >done</Button>
        </div>))}
      </div>
    );
  }
}

настройка тестового файла

const props = {
  list: ['first', 'second'],
  deleteTodo: jest.fn(),
};

const setup = () => {
  const wrapper = shallow(<TodoList {...props} />);
  return {
    props,
    wrapper,
  };
};

const setupByRender = () => {
  const wrapper = render(<TodoList {...props} />);
  return {
    props,
    wrapper,
  };
};

const setupByMount = () => {
  const wrapper = mount(<TodoList {...props} />);
  return {
    props,
    wrapper,
  };
};

Тестирование пользовательского интерфейса с помощью снимка

it('renders correctly', () => {
  const tree = renderer
  .create(<TodoList {...props} />)
          .toJSON();

  expect(tree).toMatchSnapshot();
});

При использовании toMatchSnapshot будет сгенерирован снимок DOM компонента.Каждый раз, когда тестовый пример будет запускаться в будущем, будет сгенерирован снимок компонента и сравнен с снимком, сгенерированным в первый раз.Если структура компонента изменен, сгенерированный снимок не сможет сравниться. Тесты пользовательского интерфейса можно переделать, обновив снимок.

Протестируйте узел компонента

it('should has Button', () => {
  const { wrapper } = setup();
  expect(wrapper.find('Button').length).toBe(2);
});

it('should render 2 item', () => {
  const { wrapper } = setupByRender();
  expect(wrapper.find('button').length).toBe(2);
});

it('should render item equal', () => {
  const { wrapper } = setupByMount();
  wrapper.find('.item-text').forEach((node, index) => {
    expect(node.text()).toBe(wrapper.props().list[index])
  });
});

it('click item to be done', () => {
  const { wrapper } = setupByMount();
  wrapper.find('Button').at(0).simulate('click');
  expect(props.deleteTodo).toBeCalled();
});

Чтобы определить, есть ли у компонента компонент Button, поскольку нет необходимости рендерить дочерние узлы, для рендеринга компонента используется поверхностный метод.Поскольку в списке реквизитов два элемента, ожидается, что должно быть два Button компоненты.

Определите, есть ли в компоненте элемент кнопки, поскольку кнопка является элементом компонента Button, все используют метод рендеринга для рендеринга, и ожидается, что он найдет даже элемент кнопки.

Определите содержимое компонента, используйте метод монтирования для рендеринга, а затем используйте forEach, чтобы определить, равно ли содержимое .item-text входящему значению. может вызываться при использовании метода deleteTodo.Определить, запускается ли событие щелчка.

жизненный цикл тестового компонента

//使用spy替身的时候,在测试用例结束后,要对spy进行restore,不然这个spy会一直存在,并且无法对相同的方法再次进行spy。
it('calls componentDidMount', () => {
  const componentDidMountSpy = jest.spyOn(TodoList.prototype, 'componentDidMount');
  const { wrapper } = setup();
  expect(componentDidMountSpy).toHaveBeenCalled();
  componentDidMountSpy.mockRestore();
});

Используйте spyOn, чтобы имитировать componentDidMount компонента, функция замены должна быть до рендеринга компонента, все функции замены должны быть определены до выполнения установки, а функция замены должна быть восстановлена ​​после решения, в противном случае функция замены всегда будет существовать , а над имитируемой функцией нельзя снова имитировать.

Внутренняя функция тестового компонента

it('calls component handleTest', () => { // class中使用箭头函数来定义方法
  const { wrapper } = setup();
  const spyFunction = jest.spyOn(wrapper.instance(), 'handleTest');
  wrapper.instance().handleTest();
  expect(spyFunction).toHaveBeenCalled();
  spyFunction.mockRestore();
});

it('calls component handleTest2', () => { //在constructor使用bind来定义方法
  const spyFunction = jest.spyOn(TodoList.prototype, 'handleTest2');
  const { wrapper } = setup();
  wrapper.instance().handleTest2();
  expect(spyFunction).toHaveBeenCalled();
  spyFunction.mockRestore();
});

Используйте функцию экземпляра, чтобы получить экземпляр компонента, и используйте метод spyOn, чтобы имитировать внутренний метод экземпляра, а затем используйте этот экземпляр для вызова этого внутреннего метода. называется. Если внутренний метод определяется стрелочной функцией, экземпляр необходимо имитировать; если внутренний метод определяется обычным методом или методом связывания, то необходимо имитировать прототип компонента. На самом деле о проверке жизненного цикла или внутренних функций можно судить по каким-то изменениям состояния, потому что вызовы этих функций вообще выполняют какие-то операции над состоянием компонента.

Manual Mocks

  1. Чтобы вручную смоделировать глобальный модуль (moduleName), вам необходимо создать новую папку __mocks__ на уровне node_modules и создать новый файл с именем модуля в папке
  2. Чтобы вручную смоделировать файл (fileName), вам необходимо создать папку __mocks__ на уровне смоделированного файла, а затем создать новый файл с именем файла в папке.
add/index.js

import { add } from 'lodash';
import { multip } from '../../utils/index';

export default function sum(a, b) {
  return add(a, b);
}

export function m(a, b) {
  return multip(a, b);
}
add/__test__/index.test.js

import sum, { m } from '../index';

jest.mock('lodash');
jest.mock('../../../utils/index');

describe('test mocks', () => {
  it('test sum', () => {
    expect(sum(2, 3)).toEqual(5);
  });
  it('test mutilp', () => {
    expect(m(2, 3)).toEqual(7);
  });
});

_mocks_:

Используйте метод mock() в тестовом файле, чтобы сослаться на файл, который нужно смоделировать, Jest автоматически найдет соответствующий файл в __mocks__ и заменит его, добавление в lodash и метод multip в utils будут смоделированы в соответствующий метод. Вы можете использовать автоматический прокси для имитации библиотек асинхронных компонентов проекта (fetch, axios) или использовать fetch-mock, jest-fetch-mock для имитации асинхронных запросов.

Тестировать асинхронные методы

async/index.js

import request from './request';

export function getUserName(userID) {
  return request(`/users/${userID}`).then(user => user.name);
}



async/request.js

const http = require('http');
export default function request(url) {
  return new Promise((resolve) => {
    // This is an example of an http request, for example to fetch
    // user data from an API.
    // This module is being mocked in __mocks__/request.js
    http.get({ path: url }, (response) => {
      let data = '';
      response.on('data', _data => (data += _data));
      response.on('end', () => resolve(data));
    });
  });
}

mock request:

const users = {
  4: {
    name: 'hehe',
  },
  5: {
    name: 'haha',
  },
};

export default function request(url) {
  return new Promise((resolve, reject) => {
    const userID = parseInt(url.substr('/users/'.length), 10);
    process.nextTick(() => {
      users[userID] ?
        resolve(users[userID]) :
        reject({
          error: `User with ${userID} not found.`,
        });
    });
  });
}

request.js можно рассматривать как модуль для запроса данных. Вручную смоделируйте этот модуль, чтобы он возвращал объект Promise для асинхронной обработки.

Тестовые обещания

// 使用'.resolves'来测试promise成功时返回的值
it('works with resolves', () => {
   // expect.assertions(1);
   expect(user.getUserName(5)).resolves.toEqual('haha')
});

// 使用'.rejects'来测试promise失败时返回的值
it('works with rejects', () => {
  expect.assertions(1);
  return expect(user.getUserName(3)).rejects.toEqual({
    error: 'User with 3 not found.',
  });
});

// 使用promise的返回值来进行测试
it('test resolve with promise', () => {
  expect.assertions(1);
  return user.getUserName(4).then((data) => {
    expect(data).toEqual('hehe');
  });
});
it('test error with promise', () => {
  expect.assertions(1);
  return user.getUserName(2).catch((e) => {
    expect(e).toEqual({
      error: 'User with 2 not found.',
    });
  });
});

При тестировании промиса обязательно добавляйте возврат перед утверждением, иначе тестовая функция завершится, не дожидаясь возврата промиса. Вы можете использовать .promises/.rejects для получения возвращаемого значения или использовать метод then/catch для оценки.

Протестировать асинхронно/ожидание

// 使用async/await来测试resolve
it('works resolve with async/await', async () => {
  expect.assertions(1);
  const data = await user.getUserName(4);
  expect(data).toEqual('hehe');
});

// 使用async/await来测试reject
it('works reject with async/await', async () => {
  expect.assertions(1);
  try {
    await user.getUserName(1);
  } catch (e) {
    expect(e).toEqual({
      error: 'User with 1 not found.',
    });
  }
});

Используйте async без возврата и используйте try/catch для перехвата исключений.

покрытие кода

Покрытие кода — это тестовая метрика, которая описывает, выполняется ли код тестового примера. Статистическое покрытие кода обычно требует помощи инструментов покрытия кода Jest интегрирует Istanbul, инструмент покрытия кода.

Четыре измерения

  1. Покрытие строки: выполняется ли каждая строка тестового примера
  2. Покрытие функций: вызывается каждая функция основного тестового примера.
  3. Покрытие ветвления: выполняется ли каждый блок кода IF тестового примера.
  4. Покрытие операторов (покрытие операторов): выполняется ли каждый оператор тестового примера

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

  • ||, &&, ? , !
  • если заявление
  • оператор переключения

пример

function test(a, b) {
  a = a || 0;
  b = b || 0;
  if (a && b) {
    return a + b;
  } else {
    return 0;
  }
}

test(1, 2);
// test();

При выполнении test(1,2) покрытие кода равно

При выполнении test() покрытие кода равно

установить порог

stanbul может установить порог каждого коэффициента покрытия в командной строке, а затем проверить, соответствует ли тестовый пример стандарту.Каждый параметр связан со стандартом, и если один из них не соответствует стандарту, будет сообщено об ошибке.

Когда оператор и ветвь установлены на 90, обнаружение покрытия сообщит

Когда статус установлен на 80T, а ветвь установлено значение 50, обнаружение покрытия пройдет

В шуме, пороги покрытия для различных тестовых размеров могут быть установлены через элемент конфигурации CoverageThreShold. Global - это глобальная конфигурация. По умолчанию все тестовые случаи должны соответствовать этой конфигурации, чтобы пройти тест. Конфигурации подстановочных знаков или конфигурации пути. Если эти конфигурации существуют, охват соответствующих файлов будет удален из расчета глобального покрытия, а соответствующие пороговые значения будут использоваться независимо.

{
  ...
  "jest": {
    "coverageThreshold": {
      "global": {
        "branches": 50,
        "functions": 50,
        "lines": 50,
        "statements": 50
      },
      "./src/components/": {
        "branches": 40,
        "statements": 40
      },
      "./src/reducers/**/*.js": {
        "statements": 90,
      },
      "./src/api/very-important-module.js": {
        "branches": 100,
        "functions": 100,
        "lines": 100,
        "statements": 100
      }
    }
  }
}

встроенный в леса

После обращения к модульному тесту в проекте я надеюсь, что каждый раз, когда вы изменяете тестируемый файл, вы сможете автоматически запускать тестовый пример перед отправкой кода, чтобы убедиться в правильности и надежности кода.

Вы можете использовать husky и lint-staged в проекте для запуска githooks, выполните некоторую проверку перед отправкой кода.

  • husky: После того, как хаски будет установлен в проекте, скрипты типа pre-commit будут прописаны в .git/hooks для активациикрюк, вызванные, когда Git выполняет связанные операции
  • lint-staged: staged в названии представляет промежуточную область в Git, он будет отображать только содержимое, которое будет добавлено в промежуточную область.

В package.json precommit выполняет lint-staged, настраивает lint-staged, выполняет eslint-проверку всех js-файлов и тестирует js-файлы в src/components.

{
  "scripts": {
    "precommit": "lint-staged",
  },
   "lint-staged": {
    "ignore": [
      "build/*",
      "node_modules"
    ],
    "linters": {
      "src/*.js": [
        "eslint --fix",
        "git add"
      ],
      "src/components/**/*.js": [
        "jest --findRelatedTests --config .jest.js",
        "git add"
      ]
    }
  },
}

Когда файлы в контейнерах изменяются, а затем помещаются в промежуточную область, проверки eslint будут выполняться, но тесты выполняться не будут.

Измените список задач в компонентах, eslint проверит и выполнит тестовый пример компонента списка задач, поскольку структура компонента изменена, поэтому сравнение пользовательского интерфейса со снимками не удастся

Категории