test: 补充 platform-style 和 listSubscriptions 单元测试
- platform-style: getPlatformStyle/PlatformBadge/PlatformIcon 共 17 个测试 - listSubscriptions: URL 拼接、响应解析、错误处理共 4 个测试
This commit is contained in:
70
src/__tests__/lib/platform-style.test.ts
Normal file
70
src/__tests__/lib/platform-style.test.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { renderToStaticMarkup } from 'react-dom/server';
|
||||
|
||||
import { getPlatformStyle, PlatformBadge, PlatformIcon } from '@/lib/platform-style';
|
||||
|
||||
describe('getPlatformStyle', () => {
|
||||
const knownPlatforms = ['claude', 'anthropic', 'openai', 'codex', 'gemini', 'google', 'sora', 'antigravity'];
|
||||
|
||||
it.each(knownPlatforms)('should return correct label and non-empty icon for "%s"', (platform) => {
|
||||
const style = getPlatformStyle(platform);
|
||||
// label should be the capitalised form, not empty
|
||||
expect(style.label).toBeTruthy();
|
||||
expect(style.icon).toBeTruthy();
|
||||
});
|
||||
|
||||
it('anthropic and claude should share the same badge style', () => {
|
||||
const claude = getPlatformStyle('claude');
|
||||
const anthropic = getPlatformStyle('anthropic');
|
||||
expect(claude.badge).toBe(anthropic.badge);
|
||||
});
|
||||
|
||||
it('openai and codex should share the same badge style', () => {
|
||||
const openai = getPlatformStyle('openai');
|
||||
const codex = getPlatformStyle('codex');
|
||||
expect(openai.badge).toBe(codex.badge);
|
||||
});
|
||||
|
||||
it('gemini and google should share the same badge style', () => {
|
||||
const gemini = getPlatformStyle('gemini');
|
||||
const google = getPlatformStyle('google');
|
||||
expect(gemini.badge).toBe(google.badge);
|
||||
});
|
||||
|
||||
it('should be case-insensitive ("OpenAI" and "openai" return same result)', () => {
|
||||
const upper = getPlatformStyle('OpenAI');
|
||||
const lower = getPlatformStyle('openai');
|
||||
expect(upper).toEqual(lower);
|
||||
});
|
||||
|
||||
it('should return fallback grey style for unknown platform', () => {
|
||||
const style = getPlatformStyle('unknownService');
|
||||
expect(style.badge).toContain('slate');
|
||||
expect(style.label).toBe('unknownService');
|
||||
expect(style.icon).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('PlatformBadge', () => {
|
||||
it('should render output containing the correct label text', () => {
|
||||
const html = renderToStaticMarkup(PlatformBadge({ platform: 'claude' }));
|
||||
expect(html).toContain('Claude');
|
||||
});
|
||||
|
||||
it('should render fallback label for unknown platform', () => {
|
||||
const html = renderToStaticMarkup(PlatformBadge({ platform: 'myPlatform' }));
|
||||
expect(html).toContain('myPlatform');
|
||||
});
|
||||
});
|
||||
|
||||
describe('PlatformIcon', () => {
|
||||
it('should return non-null for known platforms', () => {
|
||||
const icon = PlatformIcon({ platform: 'openai' });
|
||||
expect(icon).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should return null for unknown platform (empty icon)', () => {
|
||||
const icon = PlatformIcon({ platform: 'unknownPlatform' });
|
||||
expect(icon).toBeNull();
|
||||
});
|
||||
});
|
||||
79
src/__tests__/lib/sub2api/client-listSubscriptions.test.ts
Normal file
79
src/__tests__/lib/sub2api/client-listSubscriptions.test.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
vi.mock('@/lib/config', () => ({
|
||||
getEnv: () => ({
|
||||
SUB2API_BASE_URL: 'https://test.sub2api.com',
|
||||
SUB2API_ADMIN_API_KEY: 'admin-testkey123',
|
||||
}),
|
||||
}));
|
||||
|
||||
import { listSubscriptions } from '@/lib/sub2api/client';
|
||||
|
||||
describe('listSubscriptions', () => {
|
||||
beforeEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should call correct URL with no query params when no params provided', async () => {
|
||||
global.fetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
json: () => Promise.resolve({ data: [], total: 0, page: 1, page_size: 50 }),
|
||||
}) as typeof fetch;
|
||||
|
||||
await listSubscriptions();
|
||||
|
||||
const [url] = (fetch as ReturnType<typeof vi.fn>).mock.calls[0];
|
||||
// URL should end with "subscriptions?" and have no params after the ?
|
||||
expect(url).toBe('https://test.sub2api.com/api/v1/admin/subscriptions?');
|
||||
});
|
||||
|
||||
it('should build correct query params when all params provided', async () => {
|
||||
global.fetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
json: () => Promise.resolve({ data: [], total: 0, page: 2, page_size: 10 }),
|
||||
}) as typeof fetch;
|
||||
|
||||
await listSubscriptions({
|
||||
user_id: 42,
|
||||
group_id: 5,
|
||||
status: 'active',
|
||||
page: 2,
|
||||
page_size: 10,
|
||||
});
|
||||
|
||||
const [url] = (fetch as ReturnType<typeof vi.fn>).mock.calls[0];
|
||||
const parsedUrl = new URL(url);
|
||||
expect(parsedUrl.searchParams.get('user_id')).toBe('42');
|
||||
expect(parsedUrl.searchParams.get('group_id')).toBe('5');
|
||||
expect(parsedUrl.searchParams.get('status')).toBe('active');
|
||||
expect(parsedUrl.searchParams.get('page')).toBe('2');
|
||||
expect(parsedUrl.searchParams.get('page_size')).toBe('10');
|
||||
});
|
||||
|
||||
it('should parse normal response correctly', async () => {
|
||||
const mockSubs = [
|
||||
{ id: 1, user_id: 42, group_id: 5, status: 'active', expires_at: '2026-12-31' },
|
||||
];
|
||||
|
||||
global.fetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
json: () => Promise.resolve({ data: mockSubs, total: 1, page: 1, page_size: 50 }),
|
||||
}) as typeof fetch;
|
||||
|
||||
const result = await listSubscriptions({ user_id: 42 });
|
||||
|
||||
expect(result.subscriptions).toEqual(mockSubs);
|
||||
expect(result.total).toBe(1);
|
||||
expect(result.page).toBe(1);
|
||||
expect(result.page_size).toBe(50);
|
||||
});
|
||||
|
||||
it('should throw on HTTP error', async () => {
|
||||
global.fetch = vi.fn().mockResolvedValue({
|
||||
ok: false,
|
||||
status: 500,
|
||||
}) as typeof fetch;
|
||||
|
||||
await expect(listSubscriptions()).rejects.toThrow('Failed to list subscriptions: 500');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user