import { describe, it, expect, vi, beforeEach } from 'vitest';
import { VergeApiClient } from '../../src/client/api';
describe('VergeApiClient設定注入 (DI)', () => {
describe('基本設定', () => {
it('デフォルトのbaseUrlで初期化できる', () => {
const client = new VergeApiClient('https://api.example.com');
expect(client).toBeInstanceOf(VergeApiClient);
});
it('カスタム設定オブジェクトで初期化できる', () => {
const client = new VergeApiClient({
baseUrl: 'https://custom-api.example.com',
});
expect(client).toBeInstanceOf(VergeApiClient);
});
it('末尾のスラッシュを自動削除する', async () => {
// 内部実装を確認するため、モックfetchで検証
const fetchMock = vi.fn().mockResolvedValue({
ok: true,
status: 200,
json: async () => ({
token: 'test-token',
user: {
id: 1,
email: 'test@example.com',
username: 'test',
name: 'Test User',
role: 'admin' as const,
password_change_required: false,
created_at: '2025-01-01T00:00:00Z',
},
}),
});
const client = new VergeApiClient({
baseUrl: 'https://api.example.com/',
fetchFn: fetchMock,
});
await client.login('test@example.com', 'password');
// fetchが正しいURLで呼ばれることを確認 (末尾スラッシュなし)
expect(fetchMock).toHaveBeenCalledWith(
'https://api.example.com/api/auth/login',
expect.any(Object)
);
});
});
describe('カスタムfetch関数', () => {
it('カスタムfetch関数を注入できる', async () => {
const customFetch = vi.fn().mockResolvedValue({
ok: true,
status: 200,
json: async () => ({
token: 'custom-token',
user: {
id: 1,
email: 'test@example.com',
username: 'test',
name: 'Test User',
role: 'admin' as const,
password_change_required: false,
created_at: '2025-01-01T00:00:00Z',
},
}),
});
const client = new VergeApiClient({
baseUrl: 'https://api.example.com',
fetchFn: customFetch,
});
await client.login('test@example.com', 'password');
expect(customFetch).toHaveBeenCalledOnce();
expect(customFetch).toHaveBeenCalledWith(
'https://api.example.com/api/auth/login',
expect.objectContaining({
method: 'POST',
})
);
});
it('fetchFnが未指定の場合はglobal.fetchを使用する', async () => {
const fetchMock = vi.fn().mockResolvedValue({
ok: true,
status: 200,
json: async () => ({
token: 'test-token',
user: {
id: 1,
email: 'test@example.com',
username: 'test',
name: 'Test User',
role: 'admin' as const,
password_change_required: false,
created_at: '2025-01-01T00:00:00Z',
},
}),
});
global.fetch = fetchMock;
const client = new VergeApiClient('https://api.example.com');
await client.login('test@example.com', 'password');
expect(fetchMock).toHaveBeenCalledOnce();
});
});
describe('タイムアウト設定', () => {
it('デフォルトタイムアウトは未設定 (無制限)', async () => {
const client = new VergeApiClient('https://api.example.com');
const config = (client as any).config;
expect(config.timeout).toBeUndefined();
});
it('カスタムタイムアウトを設定できる', () => {
const client = new VergeApiClient({
baseUrl: 'https://api.example.com',
timeout: 5000, // 5秒
});
const config = (client as any).config;
expect(config.timeout).toBe(5000);
});
it('タイムアウト時はAbortErrorを投げる', async () => {
// タイムアウトのテストは後で実装
// fake timers を使う必要がある
expect(true).toBe(true);
});
});
describe('リトライ設定', () => {
it('デフォルトのリトライ設定を持つ', () => {
const client = new VergeApiClient('https://api.example.com');
const config = (client as any).config;
// デフォルト値
expect(config.retry).toEqual({
maxRetries: 3,
retryDelay: 200,
retryOn: [500, 502, 503, 504, 429],
backoffMultiplier: 2,
maxRetryDelay: 10000,
jitter: true,
});
});
it('カスタムリトライ設定を注入できる', () => {
const client = new VergeApiClient({
baseUrl: 'https://api.example.com',
retry: {
maxRetries: 5,
retryDelay: 500,
retryOn: [500, 503],
},
});
const config = (client as any).config;
expect(config.retry.maxRetries).toBe(5);
expect(config.retry.retryDelay).toBe(500);
expect(config.retry.retryOn).toEqual([500, 503]);
});
it('リトライを無効化できる', () => {
const client = new VergeApiClient({
baseUrl: 'https://api.example.com',
retry: {
maxRetries: 0,
},
});
const config = (client as any).config;
expect(config.retry.maxRetries).toBe(0);
});
});
describe('環境別設定', () => {
it('モックモードを有効化できる', () => {
const client = new VergeApiClient({
baseUrl: 'https://api.example.com',
mode: 'mock',
});
const config = (client as any).config;
expect(config.mode).toBe('mock');
});
it('本番モードを有効化できる', () => {
const client = new VergeApiClient({
baseUrl: 'https://api.example.com',
mode: 'production',
});
const config = (client as any).config;
expect(config.mode).toBe('production');
});
it('デフォルトモードは"production"', () => {
const client = new VergeApiClient('https://api.example.com');
const config = (client as any).config;
expect(config.mode).toBe('production');
});
});
describe('下位互換性', () => {
it('既存のstring引数コンストラクタは引き続き動作する', () => {
const client = new VergeApiClient('https://api.example.com');
expect(client).toBeInstanceOf(VergeApiClient);
});
it('既存のsetToken/getTokenメソッドは引き続き動作する', () => {
const client = new VergeApiClient('https://api.example.com');
client.setToken('test-token');
expect(client.getToken()).toBe('test-token');
});
});
});