Files
HexaHost-GameCloud/apps/api/test/phase3.test.js
smueller 9b061c3ee7
Some checks failed
CI / Node — lint, typecheck, test, build (push) Failing after 9s
CI / Go — node-agent tests (push) Failing after 9s
CI / Go — edge-gateway build (push) Successful in 13s
Phase3
2026-06-26 12:17:26 +02:00

112 lines
3.5 KiB
JavaScript

import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import {
parsePropertiesFile,
serializePropertiesFile,
} from '../dist/servers/properties/server-properties.util.js';
import { assertSafeServerPath } from '../dist/servers/shared/server-path.util.js';
describe('phase 3 server utilities', () => {
it('parses server.properties with types', () => {
const raw = [
'# comment',
'max-players=20',
'online-mode=false',
'motd=Hello World',
'',
].join('\n');
const parsed = parsePropertiesFile(raw);
assert.equal(parsed['max-players'], 20);
assert.equal(parsed['online-mode'], false);
assert.equal(parsed['motd'], 'Hello World');
});
it('serializes server.properties while preserving comments', () => {
const raw = '# header\nmax-players=10\nonline-mode=true\n';
const updated = parsePropertiesFile(raw);
updated['max-players'] = 25;
updated['online-mode'] = false;
const serialized = serializePropertiesFile(updated, raw);
assert.match(serialized, /^# header/);
assert.match(serialized, /max-players=25/);
assert.match(serialized, /online-mode=false/);
});
it('rejects path traversal', () => {
assert.throws(
() => assertSafeServerPath('../etc/passwd'),
(error) => error.message.includes('traversal'),
);
assert.throws(() => assertSafeServerPath('foo//bar'));
});
it('normalizes safe paths', () => {
assert.equal(assertSafeServerPath(''), '.');
assert.equal(assertSafeServerPath('logs/latest.log'), 'logs/latest.log');
assert.equal(assertSafeServerPath('\\world\\level.dat'), 'world/level.dat');
});
});
describe('phase 3 api contract', () => {
it('documents console, files, properties and players routes', () => {
const files = [
'servers/console/console.controller.ts',
'servers/files/files.controller.ts',
'servers/properties/properties.controller.ts',
'servers/players/players.controller.ts',
'servers/console/console.gateway.ts',
];
for (const file of files) {
const source = readFileSync(join(process.cwd(), 'src', file), 'utf8');
assert.ok(source.length > 0, `${file} should exist`);
}
const consoleSource = readFileSync(
join(process.cwd(), 'src', 'servers/console/console.controller.ts'),
'utf8',
);
assert.ok(consoleSource.includes("@Get('token')"));
const gatewaySource = readFileSync(
join(process.cwd(), 'src', 'servers/console/console.gateway.ts'),
'utf8',
);
assert.ok(gatewaySource.includes('console/ws'));
const filesSource = readFileSync(
join(process.cwd(), 'src', 'servers/files/files.controller.ts'),
'utf8',
);
assert.ok(filesSource.includes("@Get('content')"));
const propertiesSource = readFileSync(
join(process.cwd(), 'src', 'servers/properties/properties.controller.ts'),
'utf8',
);
assert.ok(propertiesSource.includes("@Patch()"));
const playersSource = readFileSync(
join(process.cwd(), 'src', 'servers/players/players.controller.ts'),
'utf8',
);
assert.ok(playersSource.includes('whitelist'));
const combined = [
consoleSource,
gatewaySource,
filesSource,
propertiesSource,
playersSource,
].join('\n');
for (const snippet of ['files', 'properties', 'players']) {
assert.ok(combined.includes(snippet), `missing route hint ${snippet}`);
}
});
});