Тесты: часть 1

This commit is contained in:
2025-10-28 09:58:44 +03:00
parent 21c7ddfd54
commit 6bffe6a9e1
21 changed files with 2843 additions and 3 deletions

31
tests/helpers/fixtures.ts Normal file
View File

@@ -0,0 +1,31 @@
import { join } from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
/**
* Путь к директории с фикстурами
*/
export const FIXTURES_DIR = join(__dirname, '../fixtures');
/**
* Получить путь к фикстуре
*/
export function getFixturePath(name: string): string {
return join(FIXTURES_DIR, name);
}
/**
* Доступные фикстуры
*/
export const FIXTURES = {
MINIMAL: getFixturePath('minimal.json'),
VALID: getFixturePath('valid.json'),
COMPLEX: getFixturePath('complex.json'),
WITH_AUTH: getFixturePath('with-auth.json'),
INVALID: getFixturePath('invalid.json'),
EMPTY: getFixturePath('empty.json'),
EDGE_CASES: getFixturePath('edge-cases.json'),
} as const;

View File

@@ -0,0 +1,88 @@
import { http, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';
/**
* Создание mock HTTP сервера для тестирования
*/
export function createMockServer() {
const handlers = [
// Mock для успешного GET запроса
http.get('https://api.example.com/users', () => {
return HttpResponse.json([
{ id: '1', email: 'user1@example.com', name: 'User 1' },
{ id: '2', email: 'user2@example.com', name: 'User 2' },
]);
}),
// Mock для GET с параметрами
http.get('https://api.example.com/users/:id', ({ params }) => {
const { id } = params;
if (id === '1') {
return HttpResponse.json({ id: '1', email: 'user1@example.com', name: 'User 1' });
}
return HttpResponse.json({ error: 'Not found' }, { status: 404 });
}),
// Mock для POST запроса
http.post('https://api.example.com/users', async ({ request }) => {
const body = await request.json() as Record<string, any>;
return HttpResponse.json(
{ id: '3', ...body },
{ status: 201 }
);
}),
// Mock для PATCH запроса
http.patch('https://api.example.com/users/:id', async ({ request, params }) => {
const body = await request.json() as Record<string, any>;
return HttpResponse.json({ id: params.id, ...body });
}),
// Mock для DELETE запроса
http.delete('https://api.example.com/users/:id', () => {
return new HttpResponse(null, { status: 204 });
}),
// Mock для авторизации
http.post('https://api.example.com/auth/login', async ({ request }) => {
const body = await request.json() as any;
if (body.email === 'test@example.com' && body.password === 'password') {
return HttpResponse.json({ token: 'mock-jwt-token' });
}
return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 });
}),
// Mock для защищенного endpoint
http.get('https://api.example.com/profile', ({ request }) => {
const auth = request.headers.get('Authorization');
if (auth && auth.startsWith('Bearer ')) {
return HttpResponse.json({ id: '1', email: 'test@example.com' });
}
return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 });
}),
// Mock для ошибки сервера
http.get('https://api.example.com/error', () => {
return HttpResponse.json({ error: 'Internal Server Error' }, { status: 500 });
}),
// Mock для network error
http.get('https://api.example.com/network-error', () => {
return HttpResponse.error();
}),
];
const server = setupServer(...handlers);
return {
server,
start: () => server.listen({ onUnhandledRequest: 'warn' }),
stop: () => server.close(),
reset: () => server.resetHandlers(),
};
}
/**
* Тип для mock сервера
*/
export type MockServer = ReturnType<typeof createMockServer>;

35
tests/helpers/setup.ts Normal file
View File

@@ -0,0 +1,35 @@
import { tmpdir } from 'os';
import { join } from 'path';
import { mkdtemp, rm } from 'fs/promises';
/**
* Создание временной директории для тестов
*/
export async function createTempDir(): Promise<string> {
const prefix = join(tmpdir(), 'api-codegen-test-');
return await mkdtemp(prefix);
}
/**
* Очистка временной директории
*/
export async function cleanupTempDir(dir: string): Promise<void> {
try {
await rm(dir, { recursive: true, force: true });
} catch (error) {
// Игнорируем ошибки при очистке
}
}
/**
* Setup функция для beforeEach
*/
export async function setupTest(): Promise<{ tempDir: string; cleanup: () => Promise<void> }> {
const tempDir = await createTempDir();
const cleanup = async () => {
await cleanupTempDir(tempDir);
};
return { tempDir, cleanup };
}