kt-template-online-api/test/modules/admin/environment-dashboard/environment-readonly-http.client.spec.ts

66 lines
2.0 KiB
TypeScript

import axios from 'axios';
import { EnvironmentReadonlyHttpClient } from '../../../../src/modules/admin/platform-config/environment-dashboard/infrastructure/adapters/environment-readonly-http.client';
jest.mock('axios');
const requestMock = axios.request as jest.Mock;
describe('environment readonly http client', () => {
beforeEach(() => {
requestMock.mockReset();
});
it('allows GET requests and truncates large response bodies', async () => {
requestMock.mockResolvedValue({
data: 'x'.repeat(128),
headers: { 'content-type': 'text/plain' },
status: 200,
statusText: 'OK',
});
const client = new EnvironmentReadonlyHttpClient({
bodyPreviewLimit: 16,
timeoutMs: 3000,
});
const result = await client.get('https://example.test/health', {
headers: { Authorization: 'Bearer secret-token' },
});
expect(requestMock).toHaveBeenCalledWith(
expect.objectContaining({
method: 'GET',
timeout: 3000,
url: 'https://example.test/health',
}),
);
expect(result.bodyPreview).toBe('xxxxxxxxxxxxxxxx...');
expect(JSON.stringify(result)).not.toContain('secret-token');
});
it('allows HEAD requests without storing a body preview', async () => {
requestMock.mockResolvedValue({
data: '',
headers: { server: 'caddy' },
status: 200,
statusText: 'OK',
});
const client = new EnvironmentReadonlyHttpClient({ timeoutMs: 3000 });
const result = await client.head('https://example.test');
expect(requestMock).toHaveBeenCalledWith(
expect.objectContaining({ method: 'HEAD' }),
);
expect(result.bodyPreview).toBe('');
});
it('rejects write methods at the client boundary', async () => {
const client = new EnvironmentReadonlyHttpClient({ timeoutMs: 3000 });
await expect(
client.request('POST', 'https://example.test/mutate'),
).rejects.toThrow('只允许 GET/HEAD');
expect(requestMock).not.toHaveBeenCalled();
});
});