Files
Genarrative/apps/preview-deployer-web/src/api.test.ts
T
kdletters abb3912530
Project CI / Frontend tests (push) Successful in 2m54s
Project CI / Native shell tests (push) Successful in 14m0s
Project CI / Repository checks (push) Successful in 1m6s
Project CI / Backend tests (push) Successful in 3m54s
增加分支与提交搜索校验
增加分支和 commit 的输入搜索下拉构建前复核固定仓库中的分支与 commit 归属补充预览控制面接口合同、配置和测试
2026-08-17 12:04:31 +08:00

159 lines
4.4 KiB
TypeScript

import { afterEach, expect, test, vi } from 'vitest';
import {
createDeployment,
createSession,
deleteSession,
getSession,
listDeployments,
searchBranches,
searchCommits,
uninstallDeployment,
} from './api';
afterEach(() => {
vi.unstubAllGlobals();
});
test('lists deployments from the same-origin control plane', async () => {
const fetchMock = vi.fn().mockResolvedValue(
new Response(
JSON.stringify({
deployments: [
{
id: 'preview-1',
branch: 'feature/demo',
status: 'running',
health: 'healthy',
createdAt: '2026-08-15T00:00:00Z',
updatedAt: '2026-08-15T00:01:00Z',
},
],
}),
{ status: 200, headers: { 'Content-Type': 'application/json' } },
),
);
vi.stubGlobal('fetch', fetchMock);
const deployments = await listDeployments();
expect(deployments).toHaveLength(1);
expect(fetchMock).toHaveBeenCalledWith(
'/api/preview-deployer/deployments',
expect.objectContaining({ credentials: 'same-origin' }),
);
});
test('uses an http-only session without browser token persistence', async () => {
const fetchMock = vi
.fn()
.mockImplementation((_url: string, init: RequestInit) =>
Promise.resolve(
new Response(
init.method === 'DELETE'
? null
: JSON.stringify({ authenticated: true }),
{ status: 200, headers: { 'Content-Type': 'application/json' } },
),
),
);
vi.stubGlobal('fetch', fetchMock);
expect(await getSession()).toEqual({ authenticated: true });
await createSession('team-access-token');
await deleteSession();
expect(fetchMock).toHaveBeenNthCalledWith(
2,
'/api/preview-deployer/session',
expect.objectContaining({
method: 'POST',
credentials: 'same-origin',
body: JSON.stringify({ accessToken: 'team-access-token' }),
}),
);
expect(fetchMock).toHaveBeenNthCalledWith(
3,
'/api/preview-deployer/session',
expect.objectContaining({ method: 'DELETE' }),
);
});
test('submits only branch and optional commit to fixed endpoints', async () => {
const buildResponse = () =>
new Response(
JSON.stringify({
id: 'preview-2',
branch: 'master',
status: 'queued',
health: 'pending',
createdAt: '2026-08-15T00:00:00Z',
updatedAt: '2026-08-15T00:00:00Z',
}),
{ status: 200, headers: { 'Content-Type': 'application/json' } },
);
const fetchMock = vi
.fn()
.mockImplementation(() => Promise.resolve(buildResponse()));
vi.stubGlobal('fetch', fetchMock);
await createDeployment({ branch: 'master', commitHash: 'aa5221abc' });
await uninstallDeployment('preview/2');
expect(fetchMock).toHaveBeenNthCalledWith(
1,
'/api/preview-deployer/deployments',
expect.objectContaining({
method: 'POST',
body: JSON.stringify({ branch: 'master', commitHash: 'aa5221abc' }),
}),
);
expect(fetchMock).toHaveBeenNthCalledWith(
2,
'/api/preview-deployer/deployments/preview%2F2/uninstall',
expect.objectContaining({ method: 'POST' }),
);
});
test('searches branches and branch-scoped commits with encoded queries', async () => {
const fetchMock = vi
.fn()
.mockResolvedValueOnce(
new Response(
JSON.stringify({
items: [{ name: 'feature/search', commitHash: 'abcdef123456' }],
}),
{ status: 200, headers: { 'Content-Type': 'application/json' } },
),
)
.mockResolvedValueOnce(
new Response(
JSON.stringify({
items: [
{
commitHash: 'abcdef123456',
shortHash: 'abcdef1',
subject: '搜索提交',
},
],
}),
{ status: 200, headers: { 'Content-Type': 'application/json' } },
),
);
vi.stubGlobal('fetch', fetchMock);
expect(await searchBranches('feature/search')).toHaveLength(1);
expect(await searchCommits('feature/search', 'abc def')).toHaveLength(1);
expect(fetchMock).toHaveBeenNthCalledWith(
1,
'/api/preview-deployer/refs/branches?q=feature%2Fsearch',
expect.objectContaining({ credentials: 'same-origin' }),
);
expect(fetchMock).toHaveBeenNthCalledWith(
2,
'/api/preview-deployer/refs/commits?branch=feature%2Fsearch&q=abc%20def',
expect.objectContaining({ credentials: 'same-origin' }),
);
});