From 00cefaa96dc4034b5acc66ddc86065e313c9d852 Mon Sep 17 00:00:00 2001 From: beatz174-bit Date: Tue, 2 Dec 2025 18:23:12 +1000 Subject: [PATCH] Move unit tests into e2e folder --- {tests => e2e/unit}/db.index.spec.ts | 25 +++++++++---------- {tests => e2e/unit}/db.migrations.spec.ts | 8 +++--- {tests => e2e/unit}/main.spec.tsx | 14 ++++++++--- .../unit}/useBarcodeScanner.spec.tsx | 7 +++--- {tests => e2e/unit}/useServiceWorker.spec.tsx | 2 +- {tests => e2e}/utils/mockDb.ts | 0 vite.config.ts | 4 +-- 7 files changed, 33 insertions(+), 27 deletions(-) rename {tests => e2e/unit}/db.index.spec.ts (63%) rename {tests => e2e/unit}/db.migrations.spec.ts (88%) rename {tests => e2e/unit}/main.spec.tsx (52%) rename {tests => e2e/unit}/useBarcodeScanner.spec.tsx (86%) rename {tests => e2e/unit}/useServiceWorker.spec.tsx (94%) rename {tests => e2e}/utils/mockDb.ts (100%) diff --git a/tests/db.index.spec.ts b/e2e/unit/db.index.spec.ts similarity index 63% rename from tests/db.index.spec.ts rename to e2e/unit/db.index.spec.ts index 094e4d5..c35eb5d 100644 --- a/tests/db.index.spec.ts +++ b/e2e/unit/db.index.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; -const makeDexieMock = () => { +const setupDexieMock = () => { const version = vi.fn().mockReturnThis(); const stores = vi.fn().mockReturnThis(); const upgrade = vi.fn().mockReturnThis(); @@ -18,6 +18,8 @@ const makeDexieMock = () => { constructor() {} } + vi.doMock('dexie', () => ({ default: MockDexie, Dexie: MockDexie, Table: class {} })); + return { MockDexie, version }; }; @@ -28,36 +30,33 @@ describe('db/index initializeDatabase', () => { }); test('initializeDatabase calls applyMigrations with db', async () => { - const { MockDexie } = makeDexieMock(); + setupDexieMock(); const applyMigrations = vi.fn().mockResolvedValue(undefined); - vi.mock('dexie', () => ({ default: MockDexie, Dexie: MockDexie, Table: class {} })); - vi.mock('../src/db/migrations', () => ({ applyMigrations })); + vi.doMock('../../src/db/migrations', () => ({ applyMigrations })); - const { initializeDatabase, db } = await import('../src/db'); + const { initializeDatabase, db } = await import('../../src/db'); await initializeDatabase(); expect(applyMigrations).toHaveBeenCalledWith(db); }); test('initializeDatabase rejects when applyMigrations fails', async () => { - const { MockDexie } = makeDexieMock(); + setupDexieMock(); const applyMigrations = vi.fn().mockRejectedValue(new Error('fail')); - vi.mock('dexie', () => ({ default: MockDexie, Dexie: MockDexie, Table: class {} })); - vi.mock('../src/db/migrations', () => ({ applyMigrations })); + vi.doMock('../../src/db/migrations', () => ({ applyMigrations })); - const { initializeDatabase } = await import('../src/db'); + const { initializeDatabase } = await import('../../src/db'); await expect(initializeDatabase()).rejects.toThrow('fail'); }); test('StockFillDB sets up versions on construction', async () => { - const { MockDexie, version } = makeDexieMock(); - vi.mock('dexie', () => ({ default: MockDexie, Dexie: MockDexie, Table: class {} })); - vi.mock('../src/db/migrations', () => ({ applyMigrations: vi.fn() })); + const { version } = setupDexieMock(); + vi.doMock('../../src/db/migrations', () => ({ applyMigrations: vi.fn() })); - const { db } = await import('../src/db'); + const { db } = await import('../../src/db'); expect(version).toHaveBeenCalled(); expect((version as any).mock.calls.length).toBeGreaterThanOrEqual(1); diff --git a/tests/db.migrations.spec.ts b/e2e/unit/db.migrations.spec.ts similarity index 88% rename from tests/db.migrations.spec.ts rename to e2e/unit/db.migrations.spec.ts index d7d935f..8c53bc2 100644 --- a/tests/db.migrations.spec.ts +++ b/e2e/unit/db.migrations.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; -import { makeMockDb } from './utils/mockDb'; +import { makeMockDb } from '../utils/mockDb'; vi.mock('uuid', () => ({ v4: vi.fn(() => 'mock-uuid') })); @@ -18,7 +18,7 @@ describe('applyMigrations', () => { { id: 'p1', category: 'Beverages', name: 'Cola' }, ]); - const { applyMigrations } = await import('../src/db/migrations'); + const { applyMigrations } = await import('../../src/db/migrations'); await applyMigrations(db as any); expect(db.categories.add).toHaveBeenCalledWith( @@ -36,7 +36,7 @@ describe('applyMigrations', () => { { id: 'p2', category: 'cat-1', name: 'Chips' }, ]); - const { applyMigrations } = await import('../src/db/migrations'); + const { applyMigrations } = await import('../../src/db/migrations'); await applyMigrations(db as any); expect(db.categories.add).not.toHaveBeenCalled(); @@ -53,7 +53,7 @@ describe('applyMigrations', () => { { id: 'pl-1', categories: ['Fruit'] }, ]); - const { applyMigrations } = await import('../src/db/migrations'); + const { applyMigrations } = await import('../../src/db/migrations'); await applyMigrations(db as any); expect(db.pickLists.update).toHaveBeenCalledWith('pl-1', { categories: ['cat-fruit'] }); diff --git a/tests/main.spec.tsx b/e2e/unit/main.spec.tsx similarity index 52% rename from tests/main.spec.tsx rename to e2e/unit/main.spec.tsx index 568bcf5..b6575b3 100644 --- a/tests/main.spec.tsx +++ b/e2e/unit/main.spec.tsx @@ -9,17 +9,23 @@ describe('main entry point', () => { test('renders app when root element exists', async () => { const render = vi.fn(); - vi.mock('react-dom/client', () => ({ createRoot: () => ({ render }) })); + vi.doMock('react-dom/client', () => ({ + default: { createRoot: () => ({ render }) }, + createRoot: () => ({ render }), + })); - await import('../src/main'); + await import('../../src/main'); expect(render).toHaveBeenCalled(); }); test('throws when root element is missing', async () => { document.body.innerHTML = ''; - vi.mock('react-dom/client', () => ({ createRoot: () => ({ render: vi.fn() }) })); + vi.doMock('react-dom/client', () => ({ + default: { createRoot: () => ({ render: vi.fn() }) }, + createRoot: () => ({ render: vi.fn() }), + })); - await expect(import('../src/main')).rejects.toThrow('Root element not found'); + await expect(import('../../src/main')).rejects.toThrow('Root element not found'); }); }); diff --git a/tests/useBarcodeScanner.spec.tsx b/e2e/unit/useBarcodeScanner.spec.tsx similarity index 86% rename from tests/useBarcodeScanner.spec.tsx rename to e2e/unit/useBarcodeScanner.spec.tsx index f55b3d7..ee16fe9 100644 --- a/tests/useBarcodeScanner.spec.tsx +++ b/e2e/unit/useBarcodeScanner.spec.tsx @@ -23,7 +23,7 @@ describe('useBarcodeScanner', () => { }); test('falls back to ZXing reader when BarcodeDetector is unavailable', async () => { - const { useBarcodeScanner } = await import('../src/hooks/useBarcodeScanner'); + const { useBarcodeScanner } = await import('../../src/hooks/useBarcodeScanner'); const { result } = renderHook(() => useBarcodeScanner()); result.current.videoRef.current = document.createElement('video'); @@ -39,13 +39,14 @@ describe('useBarcodeScanner', () => { const play = vi.fn().mockResolvedValue(undefined); const getVideoTracks = vi.fn().mockReturnValue([{ stop: vi.fn() }]); - const stream = { getVideoTracks } as any; + const getTracks = vi.fn().mockReturnValue([{ stop: vi.fn() }]); + const stream = { getVideoTracks, getTracks } as any; navigator.mediaDevices = { getUserMedia: vi.fn().mockResolvedValue(stream), } as any; (globalThis as any).createImageBitmap = vi.fn().mockResolvedValue({}); - const { useBarcodeScanner } = await import('../src/hooks/useBarcodeScanner'); + const { useBarcodeScanner } = await import('../../src/hooks/useBarcodeScanner'); const { result } = renderHook(() => useBarcodeScanner()); const video = document.createElement('video'); Object.defineProperty(video, 'play', { value: play }); diff --git a/tests/useServiceWorker.spec.tsx b/e2e/unit/useServiceWorker.spec.tsx similarity index 94% rename from tests/useServiceWorker.spec.tsx rename to e2e/unit/useServiceWorker.spec.tsx index 92dbb4d..4d55561 100644 --- a/tests/useServiceWorker.spec.tsx +++ b/e2e/unit/useServiceWorker.spec.tsx @@ -2,7 +2,7 @@ import { renderHook, waitFor } from '@testing-library/react'; import { describe, expect, test, vi, beforeEach } from 'vitest'; const setupHook = async () => { - const module = await import('../src/hooks/useServiceWorker'); + const module = await import('../../src/hooks/useServiceWorker'); return module.useServiceWorker; }; diff --git a/tests/utils/mockDb.ts b/e2e/utils/mockDb.ts similarity index 100% rename from tests/utils/mockDb.ts rename to e2e/utils/mockDb.ts diff --git a/vite.config.ts b/vite.config.ts index 6dbb932..5beb628 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -80,10 +80,10 @@ export default defineConfig({ } }, test: { - include: ['src/**/*.{test,spec}.{ts,tsx}'], + include: ['src/**/*.{test,spec}.{ts,tsx}', 'e2e/unit/**/*.{test,spec}.{ts,tsx}'], environment: 'jsdom', setupFiles: './src/test/setup.ts', - exclude: ['e2e/**/*'], + exclude: ['e2e/*.spec.ts', 'e2e/fixtures.ts', 'e2e/test-helpers.ts'], coverage: { provider: 'v8', reporter: ['text', 'lcov'],