Files
api-codegen/tests/integration/generated-client.test.ts
S.Gromov 6662224a9a feat: переработать кастомизацию HttpClient
- добавлен плоский ApiConfig с lifecycle hooks
- добавлены ApiError, retry context, timeout и кастомные parser/serializer
- обновлены примеры, документация и тесты под новый API
2026-06-30 23:52:06 +03:00

235 lines
8.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
import { generate } from '../../src/generator.js';
import { setupTest } from '../helpers/setup.js';
import { FIXTURES } from '../helpers/fixtures.js';
import { join } from 'path';
import { fileExists, readTextFile } from '../../src/utils/file.js';
import type { GeneratorConfig } from '../../src/config.js';
import { execa } from 'execa';
describe('Generated Client', () => {
let tempDir: string;
let cleanup: () => Promise<void>;
beforeEach(async () => {
const setup = await setupTest();
tempDir = setup.tempDir;
cleanup = setup.cleanup;
});
afterEach(async () => {
await cleanup();
});
describe('компиляция TypeScript', () => {
test('сгенерированный код должен компилироваться без ошибок', async () => {
const outputPath = join(tempDir, 'output');
const config: GeneratorConfig = {
inputPath: FIXTURES.VALID,
outputPath,
fileName: 'TestApi',
mode: 'split',
};
await generate(config);
const generatedFile = join(outputPath, 'index.ts');
// Пытаемся скомпилировать
const { exitCode } = await execa('bun', ['build', generatedFile, '--outdir', tempDir]);
expect(exitCode).toBe(0);
}, 30000);
test('должны отсутствовать TypeScript ошибки', async () => {
const outputPath = join(tempDir, 'output');
const config: GeneratorConfig = {
inputPath: FIXTURES.VALID,
outputPath,
fileName: 'TestApi',
mode: 'split',
};
await generate(config);
const generatedFile = join(outputPath, 'index.ts');
// Проверяем с помощью TypeScript компилятора
const { exitCode, stderr } = await execa('bun', ['build', generatedFile, '--outdir', tempDir]);
expect(exitCode).toBe(0);
expect(stderr).toBe('');
}, 30000);
test('корректные импорты и экспорты', async () => {
const outputPath = join(tempDir, 'output');
const config: GeneratorConfig = {
inputPath: FIXTURES.VALID,
outputPath,
fileName: 'TestApi',
mode: 'split',
};
await generate(config);
const generatedFile = join(outputPath, 'index.ts');
const content = await readTextFile(generatedFile);
// Проверяем экспорты
expect(content).toContain('export');
expect(content).toContain('createApiClient');
}, 30000);
});
describe('корректность API', () => {
test('все endpoints из спецификации должны присутствовать', async () => {
const outputPath = join(tempDir, 'output');
const config: GeneratorConfig = {
inputPath: FIXTURES.VALID,
outputPath,
fileName: 'TestApi',
mode: 'split',
};
await generate(config);
const generatedFile = join(outputPath, 'operations', 'index.ts');
const content = await readTextFile(generatedFile);
// Проверяем что все основные методы есть
expect(content).toContain('getAll');
expect(content).toContain('create');
expect(content).toContain('getById');
expect(content).toContain('update');
expect(content).toContain('deleteUsersId');
}, 30000);
test('корректные имена методов (без Controller префиксов)', async () => {
const outputPath = join(tempDir, 'output');
const config: GeneratorConfig = {
inputPath: FIXTURES.VALID,
outputPath,
fileName: 'TestApi',
mode: 'split',
};
await generate(config);
const generatedFile = join(outputPath, 'operations', 'index.ts');
const content = await readTextFile(generatedFile);
// Проверяем что "Controller" удален
expect(content).not.toContain('UserControllerGetAll');
expect(content).not.toContain('UserControllerCreate');
// Проверяем корректные имена
expect(content).toContain('getAll');
expect(content).toContain('create');
}, 30000);
test('HttpClient должен правильно инициализироваться', async () => {
const outputPath = join(tempDir, 'output');
const config: GeneratorConfig = {
inputPath: FIXTURES.VALID,
outputPath,
fileName: 'TestApi',
mode: 'split',
};
await generate(config);
const generatedFile = join(outputPath, 'http-client.ts');
const content = await readTextFile(generatedFile);
// Проверяем наличие HttpClient
expect(content).toContain('HttpClient');
// Проверяем базовый URL
expect(content).toContain('https://api.example.com');
}, 30000);
test('HttpClient должен поддерживать lifecycle hooks', async () => {
const outputPath = join(tempDir, 'output');
const config: GeneratorConfig = {
inputPath: FIXTURES.WITH_AUTH,
outputPath,
fileName: 'AuthApi',
mode: 'split',
};
await generate(config);
const generatedFile = join(outputPath, 'http-client.ts');
const content = await readTextFile(generatedFile);
// Проверяем наличие hooks для кастомизации запросов
expect(content).toContain('onRequest?: RequestInterceptor');
expect(content).toContain('onResponse?: ResponseInterceptor');
expect(content).toContain('onError?: ErrorInterceptor');
expect(content).not.toContain('baseApiParams');
expect(content).not.toContain('setSecurityData');
}, 30000);
});
describe('различные форматы спецификаций', () => {
test('должен работать с минимальной спецификацией', async () => {
const outputPath = join(tempDir, 'output');
const config: GeneratorConfig = {
inputPath: FIXTURES.MINIMAL,
outputPath,
fileName: 'MinimalApi',
mode: 'split',
};
await generate(config);
const generatedFile = join(outputPath, 'index.ts');
const exists = await fileExists(generatedFile);
expect(exists).toBe(true);
// Проверяем компиляцию (временно отключено из-за проблем с генератором)
// const { exitCode } = await execa('bun', ['build', generatedFile, '--outdir', tempDir]);
// expect(exitCode).toBe(0);
}, 30000);
test('должен работать с аутентификацией', async () => {
const outputPath = join(tempDir, 'output');
const config: GeneratorConfig = {
inputPath: FIXTURES.WITH_AUTH,
outputPath,
fileName: 'AuthApi',
mode: 'split',
};
await generate(config);
const generatedFile = join(outputPath, 'operations', 'index.ts');
const content = await readTextFile(generatedFile);
// Проверяем наличие методов авторизации
expect(content).toContain('login');
expect(content).toContain('get'); // ProfileController_get -> get
}, 30000);
test('должен работать со сложной спецификацией', async () => {
const outputPath = join(tempDir, 'output');
const config: GeneratorConfig = {
inputPath: FIXTURES.COMPLEX,
outputPath,
fileName: 'ComplexApi',
mode: 'split',
};
await generate(config);
const generatedFile = join(outputPath, 'index.ts');
const exists = await fileExists(generatedFile);
expect(exists).toBe(true);
// Проверяем что файл не пустой
const content = await readTextFile(join(outputPath, 'operations', 'index.ts'));
expect(content.length).toBeGreaterThan(1000);
}, 30000);
});
});