Инструменты для тестирования

Выбор правильных инструментов определяет скорость написания тестов, стабильность запусков и полноту покрытия. Для timeago.js ключевые требования — поддержка jsdom, управление таймерами и работа с DOM.


Jest

Наиболее распространённый выбор для тестирования JavaScript-кода.

npm install --save-dev jest @types/jest ts-jest
// jest.config.js
module.exports = {
  preset:          'ts-jest',
  testEnvironment: 'jsdom',
  globals: {
    'ts-jest': {
      tsconfig: 'tsconfig.json',
    },
  },
};

Преимущества для timeago.js: - jest.useFakeTimers() — полный контроль над Date.now() и таймерами. - jest.setSystemTime() — заморозка системного времени. - jest.mock('timeago.js') — мок всей библиотеки. - jsdom окружение — реальный DOM в Node.js.


Vitest

Современная альтернатива Jest, интегрируется с Vite.

npm install --save-dev vitest @vitest/ui jsdom
// vite.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    environment: 'jsdom',
    globals:     true,
  },
});
// Использование в тестах
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';

beforeEach(() => {
  vi.useFakeTimers();
  vi.setSystemTime(new Date('2025-06-01T12:00:00Z'));
});

afterEach(() => {
  vi.useRealTimers();
});

@testing-library/react

Тестирование компонентов React через DOM-запросы.

npm install --save-dev @testing-library/react @testing-library/jest-dom
import { render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import { TimeAgo } from './TimeAgo';

it('рендерит время', async () => {
  render(<TimeAgo date="2025-05-31T12:00:00Z" />);
  await waitFor(() => {
    expect(screen.getByRole('time')).toHaveTextContent(/день/);
  });
});

@testing-library/vue

npm install --save-dev @testing-library/vue
import { render, screen } from '@testing-library/vue';
import TimeAgo from './TimeAgo.vue';

it('отображает время', () => {
  render(TimeAgo, {
    props: { date: '2025-05-31T12:00:00Z' },
  });
  expect(screen.getByRole('time')).toBeTruthy();
});

@testing-library/user-event

Симуляция пользовательских взаимодействий (клики, ввод) для тестирования смены локали:

npm install --save-dev @testing-library/user-event
import userEvent from '@testing-library/user-event';

it('переключает локаль при клике', async () => {
  render(<LocaleSwitcher />);
  await userEvent.click(screen.getByRole('button', { name: /English/ }));
  expect(screen.getByText(/ago/i)).toBeInTheDocument();
});

Playwright (E2E)

npm install --save-dev @playwright/test
// tests/timeago.spec.ts
import { test, expect } from '@playwright/test';

test('страница показывает относительные даты', async ({ page }) => {
  await page.goto('http://localhost:3000');
  const timeEl = page.locator('time').first();
  await expect(timeEl).toBeVisible();
  await expect(timeEl).not.toBeEmpty();
});

test('время обновляется через 60 секунд', async ({ page }) => {
  await page.goto('http://localhost:3000');

  const before = await page.locator('time').first().textContent();

  // Перемотать время браузера
  await page.evaluate(() => {
    Date.now = () => new Date('2025-06-01T13:00:00Z').getTime();
  });

  // Подождать обновления
  await page.waitForTimeout(2000);

  const after = await page.locator('time').first().textContent();
  // После перемотки текст может измениться
  console.log({ before, after });
});

Fake Timers — сравнение

Функция Jest Vitest
Включение jest.useFakeTimers() vi.useFakeTimers()
Установка времени jest.setSystemTime(d) vi.setSystemTime(d)
Перемотка на N мс jest.advanceTimersByTime(n) vi.advanceTimersByTime(n)
Запуск всех таймеров jest.runAllTimers() vi.runAllTimers()
Следующий таймер jest.runOnlyPendingTimers() vi.runOnlyPendingTimers()
Восстановление jest.useRealTimers() vi.useRealTimers()

Конфигурация покрытия

// jest.config.js
module.exports = {
  collectCoverageFrom: [
    'src/**/*.{ts,tsx}',
    '!src/**/*.d.ts',
    '!src/locales/**',   // Локали не требуют покрытия ветками
  ],
  coverageThresholds: {
    global: {
      statements: 80,
      branches:   75,
      functions:  80,
      lines:      80,
    },
  },
};

Структура директории тестов

src/
  utils/
    timeago.ts
    timeago.test.ts        # Unit тесты утилит
  components/
    TimeAgo.tsx
    TimeAgo.test.tsx       # Интеграционные тесты компонентов
  hooks/
    useTimeAgo.ts
    useTimeAgo.test.ts     # Тесты хуков
  locales/
    ru.ts
    ru.test.ts             # Тесты кастомных локалей
tests/
  integration/
    timeago.spec.ts        # E2E тесты (Playwright)

Полезные пакеты

Пакет Назначение
jest-environment-jsdom DOM среда для Jest
@testing-library/jest-dom Матчеры для DOM-утверждений
@testing-library/react Рендер React компонентов
@testing-library/user-event Симуляция взаимодействий пользователя
msw Мок HTTP запросов в тестах
@vitest/coverage-v8 Покрытие кода для Vitest