Files
makelore/tests/unit/works-square-ai-gateway.test.ts
2026-07-29 17:22:35 +08:00

125 lines
4.1 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import {
clearWorksSquareAIGatewayCredential,
getFreshWorksSquareAIGatewayCredential,
getWorksSquareAIGatewaySnapshot,
markWorksSquareAIGatewayCredentialExpired,
seedWorksSquareAIGatewayCredential,
} from '@electron/services/works-square-ai-gateway';
import {
clearWorksSquareSession,
storeWorksSquareSession,
} from '@electron/services/works-square-session';
describe('works-square-ai-gateway service', () => {
beforeEach(() => {
vi.useFakeTimers();
vi.setSystemTime(new Date('2026-07-06T08:00:00.000Z'));
clearWorksSquareAIGatewayCredential();
clearWorksSquareSession();
});
afterEach(() => {
vi.useRealTimers();
clearWorksSquareAIGatewayCredential();
clearWorksSquareSession();
});
it('returns a seeded credential while it is outside the refresh skew', async () => {
seedWorksSquareAIGatewayCredential({
accessToken: 'seeded-ai-token',
expiresIn: 3600,
oneApiBaseUrl: 'https://one-api.example.com/v1/',
});
await expect(getFreshWorksSquareAIGatewayCredential()).resolves.toEqual({
accessToken: 'seeded-ai-token',
expiresAt: Date.now() + 3_600_000,
oneApiBaseUrl: 'https://one-api.example.com/v1',
});
expect(getWorksSquareAIGatewaySnapshot()?.accessToken).toBe('seeded-ai-token');
});
it('fetches a new gateway credential when none is cached', async () => {
storeWorksSquareSession({
accessToken: 'works-access-token',
refreshToken: 'works-refresh-token',
expiresAt: Date.now() + 120_000,
});
const fetchImpl = vi.fn().mockResolvedValueOnce(
new Response(JSON.stringify({
access_token: 'fresh-ai-token',
expires_in: 1800,
one_api_base_url: 'https://one-api.example.com/v1/',
}), { status: 200 }),
);
await expect(getFreshWorksSquareAIGatewayCredential({ fetchImpl })).resolves.toEqual({
accessToken: 'fresh-ai-token',
expiresAt: Date.now() + 1_800_000,
oneApiBaseUrl: 'https://one-api.example.com/v1',
});
expect(fetchImpl).toHaveBeenCalledWith(
'https://square.nianxx.cn/api/ai-gateway/session',
expect.objectContaining({
method: 'POST',
headers: expect.objectContaining({
Authorization: 'Bearer works-access-token',
Accept: 'application/json',
}),
}),
);
});
it('uses a single refresh request for parallel callers', async () => {
storeWorksSquareSession({
accessToken: 'works-access-token',
refreshToken: 'works-refresh-token',
expiresAt: Date.now() + 120_000,
});
const fetchImpl = vi.fn().mockResolvedValueOnce(
new Response(JSON.stringify({
access_token: 'fresh-ai-token',
expires_in: 1800,
one_api_base_url: 'https://one-api.example.com/v1',
}), { status: 200 }),
);
const [first, second] = await Promise.all([
getFreshWorksSquareAIGatewayCredential({ fetchImpl }),
getFreshWorksSquareAIGatewayCredential({ fetchImpl }),
]);
expect(first?.accessToken).toBe('fresh-ai-token');
expect(second?.accessToken).toBe('fresh-ai-token');
expect(fetchImpl).toHaveBeenCalledOnce();
});
it('mark expired forces the next call to refresh the gateway credential', async () => {
storeWorksSquareSession({
accessToken: 'works-access-token',
refreshToken: 'works-refresh-token',
expiresAt: Date.now() + 120_000,
});
seedWorksSquareAIGatewayCredential({
accessToken: 'old-ai-token',
expiresIn: 3600,
oneApiBaseUrl: 'https://one-api.example.com/v1',
});
markWorksSquareAIGatewayCredentialExpired();
const fetchImpl = vi.fn().mockResolvedValueOnce(
new Response(JSON.stringify({
access_token: 'fresh-ai-token',
expires_in: 1800,
one_api_base_url: 'https://one-api.example.com/v1',
}), { status: 200 }),
);
await expect(getFreshWorksSquareAIGatewayCredential({ fetchImpl })).resolves.toMatchObject({
accessToken: 'fresh-ai-token',
});
expect(fetchImpl).toHaveBeenCalledOnce();
});
});