Files
chimera-Public/test/server/headless-database.test.js
T

138 lines
6.5 KiB
JavaScript

'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('fs');
const os = require('os');
const path = require('path');
const database = require('../../src/database');
test('database initializes headlessly with the injected server logger', async () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'porkfolio-db-'));
const messages = [];
database.configure({
dataDir: root,
logger: {
info: (...args) => messages.push(args.join(' ')),
warn() {},
error() {},
},
});
try {
await database.initialize();
assert.ok(messages.some(message => message.includes('[DB] Ready')));
database.upsertGame({
game_id: 'CUSA03041', title: '', content_id: '', size: 0, version: '',
installed: 0, backed_up: 0, ftp_path: '', last_scanned: Date.now(),
});
database.updateProsperoData('CUSA03041', {
name: 'Red Dead Redemption 2',
iconUrl: '/pork-cache/game-metadata/CUSA03041/icon.webp',
coverUrl: '/pork-cache/game-metadata/CUSA03041/cover.jpg',
coverSource: 'wikipedia-portrait-v3',
coverSourceUrl: 'https://en.wikipedia.org/wiki/Red_Dead_Redemption_2',
coverFetchedAt: Date.now(),
});
const game = database.getGame('CUSA03041');
assert.equal(game.title, 'Red Dead Redemption 2');
assert.equal(game.prospero_name, 'Red Dead Redemption 2');
assert.match(game.prospero_icon_url, /icon\.webp$/);
assert.match(game.prospero_cover_url, /cover\.jpg$/);
assert.equal(game.cover_source, 'wikipedia-portrait-v3');
assert.equal(game.metadata_failure_count, 0);
assert.equal(database.getGameCatalogHealth().complete, 1);
assert.equal(database.getGameCatalogHealth().missing_artwork, 0);
assert.deepEqual(database.listGames({ search: 'Dead', limit: 1 }).map(item => item.game_id), ['CUSA03041']);
database.updateProsperoData('CUSA03041', {
name: 'Red Dead Redemption 2',
coverUrl: '/pork-cache/game-metadata/CUSA03041/cover.png',
coverSource: 'steamgriddb',
coverSourceUrl: 'https://www.steamgriddb.com/game/1',
coverFetchedAt: Date.now(),
});
database.close();
await database.initialize();
const retiredCover = database.getGame('CUSA03041');
assert.equal(retiredCover.prospero_cover_url, null);
assert.equal(retiredCover.cover_source, 'steamgriddb-retired');
assert.equal(retiredCover.cover_fetched_at, null);
database.updateProsperoData('CUSA03041', {
name: 'Red Dead Redemption 2',
iconUrl: '/pork-cache/game-metadata/CUSA03041/icon.webp',
coverUrl: '/pork-cache/game-metadata/CUSA03041/cover.jpg',
coverSource: 'wikipedia-portrait-v3',
coverSourceUrl: 'https://en.wikipedia.org/wiki/Red_Dead_Redemption_2',
coverFetchedAt: Date.now(),
});
database.upsertGame({
game_id: 'PPSA01467', title: "Marvel's Spider-Man Remastered", content_id: '', size: 0, version: '',
installed: 0, backed_up: 0, ftp_path: '', last_scanned: Date.now(),
});
database.updateProsperoData('PPSA01467', {
name: "Marvel's Spider-Man Remastered",
coverUrl: '/pork-cache/game-metadata/PPSA01467/cover.jpg',
coverSource: 'wikipedia-portrait-v2',
coverSourceUrl: 'https://en.wikipedia.org/wiki/Spider-Man_(2018_video_game)',
coverFetchedAt: Date.now(),
});
database.close();
await database.initialize();
assert.equal(database.getGame('CUSA03041').cover_source, 'wikipedia-portrait-v3');
assert.equal(database.getGame('PPSA01467').prospero_cover_url, null);
assert.equal(database.getGame('PPSA01467').cover_source, 'wikipedia-retired');
assert.equal(database.getGame('PPSA01467').cover_fetched_at, null);
database.upsertPayloadSource({
name: 'etaHEN', github_url: 'https://github.com/etaHEN/etaHEN',
category: 'homebrew', description: 'Official', homepage: 'https://github.com/etaHEN/etaHEN',
trust: 'official', built_in: 1,
});
const source = database.listPayloadSources()[0];
database.upsertPayloadFile({
source_id: source.id, asset_name: 'etaHEN.elf', asset_url: 'https://example.com/etaHEN.elf',
remote_hash: 'a'.repeat(64), version: '2.5', asset_size: 42,
});
database.updatePayloadFileLocal({
source_id: source.id, asset_name: 'etaHEN.elf', local_path: '/payloads/etaHEN.elf',
local_hash: 'b'.repeat(64), local_size: 42, version: '2.4',
});
const catalog = database.getPayloadCatalog();
assert.equal(catalog.stats.available, 1);
assert.equal(catalog.stats.updates, 1);
assert.equal(catalog.files[0].local_version, '2.4');
const runId = database.startAutomationRun({ task_id: 'library-scan', trigger: 'test' });
database.finishAutomationRun(runId, { status: 'completed', summary: '{"found":1}' });
const runs = database.listAutomationRuns();
assert.equal(runs[0].task_id, 'library-scan');
assert.equal(runs[0].status, 'completed');
const recoveryPoint = database.exportDatabaseBuffer();
database.upsertGame({
game_id: 'PPSA99999', title: 'Temporary', content_id: '', size: 0, version: '',
installed: 0, backed_up: 0, ftp_path: '', last_scanned: Date.now(),
});
assert.equal(database.getGame('PPSA99999').title, 'Temporary');
assert.deepEqual(database.listGames({ platform: 'ps4' }).map(item => item.game_id), ['CUSA03041']);
assert.deepEqual(database.listGames({ platform: 'ps5' }).map(item => item.game_id), ['PPSA01467', 'PPSA99999']);
const restored = database.restoreDatabaseBuffer(recoveryPoint);
assert.equal(restored.ok, true);
assert.equal(database.getGame('PPSA99999'), undefined);
assert.equal(database.getGame('CUSA03041').title, 'Red Dead Redemption 2');
assert.deepEqual(database.runQuery("SELECT game_id FROM games WHERE game_id = 'CUSA03041'"), [{ game_id: 'CUSA03041' }]);
assert.ok(database.runQuery('PRAGMA table_info(games)').some(column => column.name === 'game_id'));
assert.throws(() => database.runQuery('PRAGMA user_version = 123'), /read-only|niet beschikbaar/);
assert.throws(() => database.runQuery('PRAGMA user_version(123)'), /read-only|niet beschikbaar/);
assert.throws(() => database.runQuery('WITH target AS (SELECT id FROM games) DELETE FROM games WHERE id IN target'), /niet read-only/);
assert.throws(() => database.runQuery('SELECT 1; DELETE FROM games'), /één SQL-statement/);
assert.equal(database.getGame('CUSA03041').title, 'Red Dead Redemption 2');
} finally {
database.close();
fs.rmSync(root, { recursive: true, force: true });
}
});