Vitest — Next.js bilan sozlash

~15 daq · Next.js · Testing

Muammodan boshlaylik

Narx hisoblash funksiyasini o'zgartirdingiz — chegirma endi foiz emas, so'mda. Savat jami to'g'ri, lekin "bepul yetkazish" sharti buzildi va bir hafta davomida hamma bepul yetkazib berildi.

Har bir o'zgarishdan keyin butun saytni qo'lda sinab chiqish — imkonsiz. Kerak: kodni avtomatik tekshiradigan testlar.


Test turlari

        ▲  E2E (Playwright, 63-dars)     — kam, sekin, butun ilova brauzerda
       ▲▲  Integratsiya / komponent       — o'rtacha
     ▲▲▲▲  Unit (Vitest)                  — ko'p, tez, alohida funksiyalar
Tur Nima Vosita
Unit Funksiya, hook Vitest
Komponent Komponent render va o'zaro ta'sir Vitest + React Testing Library (62-dars)
E2E Haqiqiy brauzer, butun oqim Playwright (63-dars)

Hayotiy o'xshatma

Avtomobil zavodi. Har bir detal — alohida tekshiriladi (unit): bolt mustahkammi, chiroq yonadimi. Yig'ilgan dvigatel — stendda (integratsiya). Tayyor mashina — sinov poligonida (E2E). Detal tekshiruvlari tez va arzon — ular ko'p; poligon sinovlari qimmat — ular kam.


O'rnatish

npm install -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom @testing-library/user-event vite-tsconfig-paths
// vitest.config.mts
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
import tsconfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
  plugins: [tsconfigPaths(), react()],
  test: {
    environment: 'jsdom',
    setupFiles: ['./vitest.setup.ts'],
    include: ['**/*.test.{ts,tsx}'],
    exclude: ['node_modules', 'e2e/**'],
  },
})
// vitest.setup.ts
import '@testing-library/jest-dom/vitest'
{
  "scripts": {
    "test": "vitest",
    "test:run": "vitest run",
    "test:coverage": "vitest run --coverage"
  }
}
  • tsconfigPaths — @/lib/... import lari ishlashi uchun
  • jsdom — brauzer DOM ning simulyatsiyasi (komponent testlari uchun)
  • include/exclude — Playwright testlari Vitest ga aralashmasin

[!INFO] Nega Jest emas? Vitest Vite asosida: sozlash kam, ESM va TypeScript tabiiy ishlaydi, juda tez va API si Jest bilan deyarli bir xil (describe, it, expect, vi.fn). Next.js hujjatlarida ham Vitest va Jest ikkalasi uchun yo'riqnoma bor.


Birinchi test

// lib/narx.ts
export function savatJami(qatorlar: { narx: number; soni: number }[]) {
  return qatorlar.reduce((s, q) => s + q.narx * q.soni, 0)
}

export function yetkazishNarxi(jami: number) {
  return jami >= 500_000 ? 0 : 25_000
}
// lib/narx.test.ts
import { describe, it, expect } from 'vitest'
import { savatJami, yetkazishNarxi } from './narx'

describe('savatJami', () => {
  it('qatorlar yig\'indisini hisoblaydi', () => {
    expect(savatJami([{ narx: 100_000, soni: 2 }, { narx: 50_000, soni: 1 }])).toBe(250_000)
  })

  it("bo'sh savat — 0", () => {
    expect(savatJami([])).toBe(0)
  })
})

describe('yetkazishNarxi', () => {
  it('500 000 dan — bepul', () => {
    expect(yetkazishNarxi(500_000)).toBe(0)
  })

  it('500 000 dan kam — 25 000', () => {
    expect(yetkazishNarxi(499_999)).toBe(25_000)
  })
})
npm test
 ✓ lib/narx.test.ts (4 tests) 3ms
 Test Files  1 passed (1)
      Tests  4 passed (4)

vitest — watch rejimida: faylni saqlaganingizda bog'liq testlar avtomatik qayta ishlaydi.


Zod sxemalarini test qilish

import { describe, it, expect } from 'vitest'
import { postSchema } from './schemas'

describe('postSchema', () => {
  it("qisqa sarlavhani rad etadi", () => {
    const natija = postSchema.safeParse({ sarlavha: 'ab', matn: 'yetarlicha uzun matn' })
    expect(natija.success).toBe(false)
  })
})

Mock — tashqi bog'liqliklar

import { describe, it, expect, vi, beforeEach } from 'vitest'

vi.mock('@/lib/prisma', () => ({
  prisma: { mahsulot: { findUnique: vi.fn() } },
}))

import { prisma } from '@/lib/prisma'
import { mahsulotNarxi } from './mahsulot'

beforeEach(() => vi.clearAllMocks())

it("mahsulot topilmasa null qaytaradi", async () => {
  vi.mocked(prisma.mahsulot.findUnique).mockResolvedValue(null)
  expect(await mahsulotNarxi('yoq')).toBeNull()
})

Next.js modullarini mock qilish

vi.mock('next/navigation', () => ({
  useRouter: () => ({ push: vi.fn(), replace: vi.fn(), refresh: vi.fn() }),
  usePathname: () => '/katalog',
  useSearchParams: () => new URLSearchParams('kategoriya=telefon'),
}))

[!WARNING] Vitest async Server Component larni to'g'ridan-to'g'ri render qilishni hali to'liq qo'llab-quvvatlamaydi. Ular uchun: ichidagi mantiqni alohida funksiyalarga ajratib unit test qiling, render ni esa E2E (Playwright) bilan tekshiring (62-dars).


Tez-tez uchraydigan xatolar

1. @/ import lari ishlamaydi

vite-tsconfig-paths plagini yo'q.

2. toBeInTheDocument is not a function

vitest.setup.ts da @testing-library/jest-dom/vitest import qilinmagan yoki setupFiles da yo'q.

3. Mock lar testlar orasida "sizib chiqadi"

beforeEach(() => vi.clearAllMocks()) yoki konfiguratsiyada clearMocks: true.


Xulosa

Test piramidasi: ko'p unit, o'rtacha komponent, kam E2E
Vitest + @vitejs/plugin-react + jsdom + vite-tsconfig-paths
vitest.config.mts, vitest.setup.ts (jest-dom)
describe / it / expect; vitest — watch, vitest run — CI
vi.mock — prisma, next/navigation; vi.mocked; clearAllMocks
Async Server Component — mantiqni ajrating, render ni E2E bilan

Keyingi dars

62-dars: React Testing Library — Server Component testlash

Komponentlarni foydalanuvchi ko'zi bilan test qilish.