141 lines
6.1 KiB
TypeScript
141 lines
6.1 KiB
TypeScript
import { createHash } from 'node:crypto';
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { newFixture, type Fixture } from '../helpers/fixture.js';
|
|
|
|
let fixture: Fixture;
|
|
beforeEach(async () => {
|
|
vi.resetModules();
|
|
fixture = await newFixture([]);
|
|
});
|
|
afterEach(async () => {
|
|
await fixture.cleanup();
|
|
});
|
|
|
|
describe('server detail data', () => {
|
|
it('filters history before the global limit and includes the matching campaign members', async () => {
|
|
const { db } = await import('../../src/lib/server/db/index.js');
|
|
const handle = db();
|
|
handle.exec("INSERT INTO servers (name) VALUES ('target'), ('other')");
|
|
handle.transaction(() => {
|
|
const deployment = handle.prepare(
|
|
"INSERT INTO deployments (id, action, started_at) VALUES (?, 'promote', ?)"
|
|
);
|
|
const member = handle.prepare(
|
|
"INSERT INTO deployment_servers (deployment_id, server, files_changed, restart_state) VALUES (?, ?, 1, 'done')"
|
|
);
|
|
deployment.run('older-target', '2026-01-01');
|
|
member.run('older-target', 'target');
|
|
member.run('older-target', 'other');
|
|
for (let n = 0; n < 501; n++) {
|
|
deployment.run('other-' + n, '2026-09-18');
|
|
member.run('other-' + n, 'other');
|
|
}
|
|
})();
|
|
const { GET } = await import('../../src/routes/api/campaigns/+server.js');
|
|
const all = await (
|
|
await GET({ url: new URL('http://localhost/api/campaigns?limit=500') })
|
|
).json();
|
|
expect(all.deployments).toHaveLength(500);
|
|
const first = await (
|
|
await GET({ url: new URL('http://localhost/api/campaigns?limit=25') })
|
|
).json();
|
|
const second = await (
|
|
await GET({ url: new URL('http://localhost/api/campaigns?limit=25&offset=25') })
|
|
).json();
|
|
expect(first.total).toBe(502);
|
|
expect(first.deployments).toHaveLength(25);
|
|
expect(
|
|
new Set([...first.deployments, ...second.deployments].map((row) => row.id)).size
|
|
).toBe(50);
|
|
const filtered = await (
|
|
await GET({ url: new URL('http://localhost/api/campaigns?server=target') })
|
|
).json();
|
|
expect(filtered.deployments.map((row: { id: string }) => row.id)).toEqual(['older-target']);
|
|
expect(filtered.deployments[0].servers).toHaveLength(2);
|
|
expect(
|
|
(
|
|
await (
|
|
await GET({ url: new URL('http://localhost/api/campaigns?server=unknown') })
|
|
).json()
|
|
).deployments
|
|
).toEqual([]);
|
|
});
|
|
it('identifies plugins, scripts, composed configs and unknown inventory files', async () => {
|
|
const { db } = await import('../../src/lib/server/db/index.js');
|
|
db().exec("INSERT INTO servers (name) VALUES ('target')");
|
|
const { createScript } = await import('../../src/lib/server/fleet/scripts.js');
|
|
const { recordScript } = await import('../../src/lib/server/fleet/inventory.js');
|
|
const { script, version } = createScript({
|
|
name: 'Plugin',
|
|
kind: 'plugin',
|
|
releaseVersion: '1.0.0',
|
|
targetRelPath: 'native.bin',
|
|
content: Buffer.from('plugin')
|
|
});
|
|
recordScript('target', 'native.bin', version.id, version.sha256, 6, 'beta');
|
|
recordScript('target', 'dedicated_zm.cfg', null, 'hash', 10, 'compose');
|
|
recordScript('target', 'main.gsc', null, 'hash', 10, 'beta');
|
|
recordScript('target', 'unknown.dat', null, 'hash', 10, 'manual');
|
|
const { GET } = await import('../../src/routes/api/servers/[name]/scripts/+server.js');
|
|
const body = await (await GET({ params: { name: 'target' } })).json();
|
|
expect(
|
|
Object.fromEntries(
|
|
body.scripts.map((file: { relPath: string; kind: string }) => [
|
|
file.relPath,
|
|
file.kind
|
|
])
|
|
)
|
|
).toEqual({
|
|
'dedicated_zm.cfg': 'config',
|
|
'main.gsc': 'script',
|
|
'native.bin': 'plugin',
|
|
'unknown.dat': 'file'
|
|
});
|
|
expect(
|
|
body.scripts.find((file: { relPath: string }) => file.relPath === 'native.bin')
|
|
).toMatchObject({
|
|
artifactId: script.id,
|
|
version: version.version,
|
|
releaseVersion: '1.0.0',
|
|
sha256: version.sha256
|
|
});
|
|
});
|
|
it.each([
|
|
['native.bin', 'file'],
|
|
['native.dll', 'plugin']
|
|
])(
|
|
'omits saved artifact metadata for modified %s and falls back to its extension',
|
|
async (path, kind) => {
|
|
const { db } = await import('../../src/lib/server/db/index.js');
|
|
db().exec("INSERT INTO servers (name) VALUES ('target')");
|
|
const { createScript } = await import('../../src/lib/server/fleet/scripts.js');
|
|
const { recordScript } = await import('../../src/lib/server/fleet/inventory.js');
|
|
const { version } = createScript({
|
|
name: 'Plugin',
|
|
kind: 'plugin',
|
|
releaseVersion: '1.0.0',
|
|
targetRelPath: path,
|
|
content: Buffer.from('plugin')
|
|
});
|
|
const content = Buffer.from('modified plugin');
|
|
const sha256 = createHash('sha256').update(content).digest('hex');
|
|
recordScript('target', path, version.id, sha256, content.length, 'manual');
|
|
const { GET } = await import('../../src/routes/api/servers/[name]/scripts/+server.js');
|
|
const body = await (await GET({ params: { name: 'target' } })).json();
|
|
expect(body.scripts).toEqual([
|
|
expect.objectContaining({
|
|
relPath: path,
|
|
kind,
|
|
artifactId: null,
|
|
version: null,
|
|
releaseVersion: null,
|
|
scriptVersionId: version.id,
|
|
sha256,
|
|
size: content.length,
|
|
source: 'manual'
|
|
})
|
|
]);
|
|
}
|
|
);
|
|
});
|