Migrate tests from Jest to Vitest, updating setup and test files accordingly.

- Replace Jest imports and mocks with Vitest equivalents in setup and unit tests.
- Adjust test cases to use async imports and reset modules with Vitest.
- Add Vitest configuration file for test environment setup and coverage reporting.
This commit is contained in:
Max Kowalski
2025-06-27 19:14:05 +02:00
parent 5c1ced5900
commit 49a75f5ede
7 changed files with 1094 additions and 2230 deletions

View File

@ -1,6 +1,5 @@
// Unit tests for environment management
import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
import { env, validateEnv, getSchedulerConfig } from '../../lib/env';
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
describe('Environment Management', () => {
let originalEnv: NodeJS.ProcessEnv;
@ -13,54 +12,55 @@ describe('Environment Management', () => {
afterEach(() => {
// Restore original environment
process.env = originalEnv;
vi.resetModules();
});
describe('env object', () => {
it('should have default values when environment variables are not set', () => {
it('should have default values when environment variables are not set', async () => {
// Clear relevant env vars
delete process.env.NEXTAUTH_URL;
delete process.env.SCHEDULER_ENABLED;
delete process.env.PORT;
// Re-import to get fresh env object
jest.resetModules();
const { env: freshEnv } = require('../../lib/env');
vi.resetModules();
const { env: freshEnv } = await import('../../lib/env');
expect(freshEnv.NEXTAUTH_URL).toBe('http://localhost:3000');
expect(freshEnv.SCHEDULER_ENABLED).toBe(false);
expect(freshEnv.PORT).toBe(3000);
});
it('should use environment variables when set', () => {
it('should use environment variables when set', async () => {
process.env.NEXTAUTH_URL = 'https://example.com';
process.env.SCHEDULER_ENABLED = 'true';
process.env.PORT = '8080';
jest.resetModules();
const { env: freshEnv } = require('../../lib/env');
vi.resetModules();
const { env: freshEnv } = await import('../../lib/env');
expect(freshEnv.NEXTAUTH_URL).toBe('https://example.com');
expect(freshEnv.SCHEDULER_ENABLED).toBe(true);
expect(freshEnv.PORT).toBe(8080);
});
it('should parse numeric environment variables correctly', () => {
it('should parse numeric environment variables correctly', async () => {
process.env.IMPORT_PROCESSING_BATCH_SIZE = '100';
process.env.SESSION_PROCESSING_CONCURRENCY = '10';
jest.resetModules();
const { env: freshEnv } = require('../../lib/env');
vi.resetModules();
const { env: freshEnv } = await import('../../lib/env');
expect(freshEnv.IMPORT_PROCESSING_BATCH_SIZE).toBe(100);
expect(freshEnv.SESSION_PROCESSING_CONCURRENCY).toBe(10);
});
it('should handle invalid numeric values gracefully', () => {
it('should handle invalid numeric values gracefully', async () => {
process.env.IMPORT_PROCESSING_BATCH_SIZE = 'invalid';
process.env.SESSION_PROCESSING_CONCURRENCY = '';
jest.resetModules();
const { env: freshEnv } = require('../../lib/env');
vi.resetModules();
const { env: freshEnv } = await import('../../lib/env');
expect(freshEnv.IMPORT_PROCESSING_BATCH_SIZE).toBe(50); // default
expect(freshEnv.SESSION_PROCESSING_CONCURRENCY).toBe(5); // default
@ -68,62 +68,50 @@ describe('Environment Management', () => {
});
describe('validateEnv', () => {
it('should return valid when all required variables are set', () => {
process.env.NEXTAUTH_SECRET = 'test-secret';
process.env.OPENAI_API_KEY = 'test-key';
Object.defineProperty(process.env, 'NODE_ENV', {
value: 'production',
writable: true,
configurable: true,
});
it('should return valid when all required variables are set', async () => {
vi.stubEnv('NEXTAUTH_SECRET', 'test-secret');
vi.stubEnv('OPENAI_API_KEY', 'test-key');
vi.stubEnv('NODE_ENV', 'production');
jest.resetModules();
const { validateEnv: freshValidateEnv } = require('../../lib/env');
vi.resetModules();
const { validateEnv: freshValidateEnv } = await import('../../lib/env');
const result = freshValidateEnv();
expect(result.valid).toBe(true);
expect(result.errors).toHaveLength(0);
});
it('should return invalid when NEXTAUTH_SECRET is missing', () => {
delete process.env.NEXTAUTH_SECRET;
it('should return invalid when NEXTAUTH_SECRET is missing', async () => {
vi.stubEnv('NEXTAUTH_SECRET', '');
jest.resetModules();
const { validateEnv: freshValidateEnv } = require('../../lib/env');
vi.resetModules();
const { validateEnv: freshValidateEnv } = await import('../../lib/env');
const result = freshValidateEnv();
expect(result.valid).toBe(false);
expect(result.errors).toContain('NEXTAUTH_SECRET is required');
});
it('should require OPENAI_API_KEY in production', () => {
process.env.NEXTAUTH_SECRET = 'test-secret';
delete process.env.OPENAI_API_KEY;
Object.defineProperty(process.env, 'NODE_ENV', {
value: 'production',
writable: true,
configurable: true,
});
it('should require OPENAI_API_KEY in production', async () => {
vi.stubEnv('NEXTAUTH_SECRET', 'test-secret');
vi.stubEnv('OPENAI_API_KEY', '');
vi.stubEnv('NODE_ENV', 'production');
jest.resetModules();
const { validateEnv: freshValidateEnv } = require('../../lib/env');
vi.resetModules();
const { validateEnv: freshValidateEnv } = await import('../../lib/env');
const result = freshValidateEnv();
expect(result.valid).toBe(false);
expect(result.errors).toContain('OPENAI_API_KEY is required in production');
});
it('should not require OPENAI_API_KEY in development', () => {
process.env.NEXTAUTH_SECRET = 'test-secret';
delete process.env.OPENAI_API_KEY;
Object.defineProperty(process.env, 'NODE_ENV', {
value: 'development',
writable: true,
configurable: true,
});
it('should not require OPENAI_API_KEY in development', async () => {
vi.stubEnv('NEXTAUTH_SECRET', 'test-secret');
vi.stubEnv('OPENAI_API_KEY', '');
vi.stubEnv('NODE_ENV', 'development');
jest.resetModules();
const { validateEnv: freshValidateEnv } = require('../../lib/env');
vi.resetModules();
const { validateEnv: freshValidateEnv } = await import('../../lib/env');
const result = freshValidateEnv();
expect(result.valid).toBe(true);
@ -132,7 +120,7 @@ describe('Environment Management', () => {
});
describe('getSchedulerConfig', () => {
it('should return correct scheduler configuration', () => {
it('should return correct scheduler configuration', async () => {
process.env.SCHEDULER_ENABLED = 'true';
process.env.CSV_IMPORT_INTERVAL = '*/10 * * * *';
process.env.IMPORT_PROCESSING_INTERVAL = '*/3 * * * *';
@ -141,8 +129,8 @@ describe('Environment Management', () => {
process.env.SESSION_PROCESSING_BATCH_SIZE = '100';
process.env.SESSION_PROCESSING_CONCURRENCY = '8';
jest.resetModules();
const { getSchedulerConfig: freshGetSchedulerConfig } = require('../../lib/env');
vi.resetModules();
const { getSchedulerConfig: freshGetSchedulerConfig } = await import('../../lib/env');
const config = freshGetSchedulerConfig();
@ -155,13 +143,13 @@ describe('Environment Management', () => {
expect(config.sessionProcessing.concurrency).toBe(8);
});
it('should use defaults when environment variables are not set', () => {
it('should use defaults when environment variables are not set', async () => {
delete process.env.SCHEDULER_ENABLED;
delete process.env.CSV_IMPORT_INTERVAL;
delete process.env.IMPORT_PROCESSING_INTERVAL;
jest.resetModules();
const { getSchedulerConfig: freshGetSchedulerConfig } = require('../../lib/env');
vi.resetModules();
const { getSchedulerConfig: freshGetSchedulerConfig } = await import('../../lib/env');
const config = freshGetSchedulerConfig();

View File

@ -1,5 +1,5 @@
// Unit tests for transcript fetcher
import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import fetch from 'node-fetch';
import {
fetchTranscriptContent,
@ -8,18 +8,18 @@ import {
} from '../../lib/transcriptFetcher';
// Mock node-fetch
const mockFetch = fetch as jest.MockedFunction<typeof fetch>;
const mockFetch = fetch as any;
describe('Transcript Fetcher', () => {
beforeEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
describe('fetchTranscriptContent', () => {
it('should successfully fetch transcript content', async () => {
const mockResponse = {
ok: true,
text: jest.fn().mockResolvedValue('Session transcript content'),
text: vi.fn().mockResolvedValue('Session transcript content'),
};
mockFetch.mockResolvedValue(mockResponse as any);
@ -40,7 +40,7 @@ describe('Transcript Fetcher', () => {
it('should handle authentication with username and password', async () => {
const mockResponse = {
ok: true,
text: jest.fn().mockResolvedValue('Authenticated transcript'),
text: vi.fn().mockResolvedValue('Authenticated transcript'),
};
mockFetch.mockResolvedValue(mockResponse as any);
@ -82,7 +82,7 @@ describe('Transcript Fetcher', () => {
it('should handle empty transcript content', async () => {
const mockResponse = {
ok: true,
text: jest.fn().mockResolvedValue(' '),
text: vi.fn().mockResolvedValue(' '),
};
mockFetch.mockResolvedValue(mockResponse as any);
@ -135,7 +135,7 @@ describe('Transcript Fetcher', () => {
it('should trim whitespace from content', async () => {
const mockResponse = {
ok: true,
text: jest.fn().mockResolvedValue(' \n Session content \n '),
text: vi.fn().mockResolvedValue(' \n Session content \n '),
};
mockFetch.mockResolvedValue(mockResponse as any);