105 lines
3.3 KiB
TypeScript
105 lines
3.3 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
InstanceResourceService,
|
|
parseHealth,
|
|
parseSim,
|
|
parseStats,
|
|
} from './instance-resource-service.js';
|
|
|
|
const response = (body: unknown) => ({
|
|
status: 200,
|
|
headers: {},
|
|
body: JSON.stringify(body),
|
|
});
|
|
|
|
describe('instance resource allowlist parsing', () => {
|
|
it('extracts CPU, memory and only the highest valid temperature', () => {
|
|
expect(
|
|
parseStats(
|
|
response({
|
|
data: {
|
|
cpu_load: { load_percent: 23.4, secret: 'drop' },
|
|
memory: { used_percent: 67.8, total_bytes: 123 },
|
|
temperature: [
|
|
{ label: 'a', temperature: 41.2 },
|
|
{ label: 'b', temperature: 52.6 },
|
|
{ label: 'bad', temperature: 900 },
|
|
],
|
|
},
|
|
}),
|
|
),
|
|
).toEqual({ cpuPercent: 23.4, memoryPercent: 67.8, maxTemperatureCelsius: 52.6 });
|
|
});
|
|
|
|
it('falls back to version metadata exposed by stats on older SimAdmin builds', () => {
|
|
expect(
|
|
parseStats(
|
|
response({
|
|
data: {
|
|
cpu_load: { load_percent: 10 },
|
|
system: { app_version: '1.8.7', architecture: 'aarch64' },
|
|
},
|
|
}),
|
|
),
|
|
).toMatchObject({ cpuPercent: 10, version: '1.8.7', platform: 'aarch64' });
|
|
});
|
|
|
|
it('extracts the upstream SimAdmin version from the health endpoint', () => {
|
|
expect(
|
|
parseHealth(
|
|
response({ status: 'ok', version: '1.9.4', platform: 'linux-aarch64', secret: 'drop' }),
|
|
),
|
|
).toEqual({ version: '1.9.4', platform: 'linux-aarch64' });
|
|
});
|
|
|
|
it('extracts, validates, deduplicates and bounds phone numbers only', () => {
|
|
expect(
|
|
parseSim(
|
|
response({
|
|
data: {
|
|
phone_numbers: ['+86 138-0000-0000', '+86 138-0000-0000', 'bad<script>'],
|
|
imsi: 'drop',
|
|
iccid: 'drop',
|
|
},
|
|
}),
|
|
),
|
|
).toEqual({ phoneNumbers: ['+86 138-0000-0000'] });
|
|
});
|
|
|
|
it('probes passwordless instances without manufacturing a cookie', async () => {
|
|
const requests: Array<{ headers: Readonly<Record<string, string>> }> = [];
|
|
const service = new InstanceResourceService({
|
|
instances: { get: async () => ({ origin: 'http://192.168.3.55:3000' }) } as never,
|
|
sessions: { sessionFor: () => undefined } as never,
|
|
request: async (request) => {
|
|
requests.push(request);
|
|
return response(
|
|
request.url.endsWith('/api/stats')
|
|
? { data: { cpu_load: { load_percent: 12 }, memory: { used_percent: 34 } } }
|
|
: request.url.endsWith('/api/sim')
|
|
? { data: { phone_numbers: ['13800000000'] } }
|
|
: { status: 'ok', version: '2.0.1', platform: 'linux' },
|
|
);
|
|
},
|
|
});
|
|
await expect(service.get('device-1')).resolves.toEqual({
|
|
cpuPercent: 12,
|
|
memoryPercent: 34,
|
|
phoneNumbers: ['13800000000'],
|
|
version: '2.0.1',
|
|
platform: 'linux',
|
|
});
|
|
expect(requests.map((request) => request.headers)).toEqual([
|
|
{ accept: 'application/json' },
|
|
{ accept: 'application/json' },
|
|
{ accept: 'application/json' },
|
|
]);
|
|
});
|
|
|
|
it('fails closed for malformed and oversized payloads', () => {
|
|
expect(parseStats({ status: 200, headers: {}, body: '{' })).toEqual({});
|
|
expect(parseSim({ status: 200, headers: {}, body: 'x'.repeat(40_000) })).toEqual({});
|
|
});
|
|
});
|