import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { describe, it } from 'node:test'; import { classifyPackage, parseProfile, type ScrapedPackage } from '../src/lib/gextension.js'; import { looksLikeSteamId, normalizeSteamId, toLegacySteamId } from '../src/lib/steamid.js'; const here = dirname(fileURLToPath(import.meta.url)); const FIXTURE = readFileSync(join(here, 'fixtures', 'profil.html'), 'utf8'); function pkg(overrides: Partial): ScrapedPackage { return { packageBoughtId: 1, packageName: 'Custom Character', serverBundle: 'SCP-RP', purchasedAt: null, amount: '0.00 EUR', gateway: '', revoked: false, ...overrides, }; } describe('Profil auslesen', () => { const profile = parseProfile(FIXTURE, '76561198000000999'); it('findet alle Pakete', () => { assert.equal(profile.packages.length, 8); }); it('liest Titel, Bereich und Kaufdatum', () => { const cc = profile.packages.find((p) => p.packageBoughtId === 9001); assert.ok(cc); assert.equal(cc.packageName, 'Custom Character'); assert.equal(cc.serverBundle, 'SCP-RP'); assert.equal(cc.purchasedAt?.getFullYear(), 2025); assert.equal(cc.purchasedAt?.getMonth(), 9, 'Oktober'); assert.equal(cc.purchasedAt?.getDate(), 6); }); it('erkennt stornierte Kaeufe', () => { const revoked = profile.packages.find((p) => p.packageBoughtId === 9007); assert.equal(revoked?.revoked, true); }); it('liest den Nicknamen aus der Allgemein-Box', () => { assert.equal(profile.nickname, 'Testspieler'); }); it('kommt mit kaputtem HTML klar, ohne alles zu verlieren', () => { const broken = FIXTURE.replace( 'donations_data[9004] = {"id"', 'donations_data[9004] = {kaputt"id"', ); const result = parseProfile(broken, '76561198000000999'); assert.equal(result.packages.length, 7, 'nur die kaputte Zeile faellt weg'); }); }); describe('Pakete zuordnen', () => { it('erkennt ein CC-Paket', () => { assert.deepEqual(classifyPackage(pkg({ packageName: 'Custom Character' })), { kind: 'package', target: 'CC_PACKAGE', }); }); it('erkennt die Schreibweise mit K', () => { assert.deepEqual(classifyPackage(pkg({ packageName: 'Custom Charakter-Beantragung' })), { kind: 'package', target: 'CC_PACKAGE', }); }); it('zaehlt "Custom Character Redesign" als Redesign, nicht als CC', () => { assert.deepEqual(classifyPackage(pkg({ packageName: 'Custom Character Redesign' })), { kind: 'package', target: 'REDESIGN_PACKAGE', }); }); it('liest den Verbrauchszaehler samt Anzahl', () => { const result = classifyPackage( pkg({ packageName: 'CC-Paket oder Redesign genutzt | 3 Mal' }), ); assert.deepEqual(result, { kind: 'usage_counter', times: 3 }); }); it('ignoriert Merch und Raenge trotz SCP-RP-Tag', () => { assert.equal(classifyPackage(pkg({ packageName: 'FG-Tasse | Merch' })).kind, 'ignore'); assert.equal(classifyPackage(pkg({ packageName: '25 Ingame-Level' })).kind, 'ignore'); assert.equal(classifyPackage(pkg({ packageName: 'VIP (12 Monate)' })).kind, 'ignore'); }); it('ignoriert alles aus dem Web-Bereich', () => { const result = classifyPackage( pkg({ packageName: 'Ablassbrief (01.04.2026)', serverBundle: 'Web' }), ); assert.equal(result.kind, 'ignore'); }); it('bucht ein storniertes Paket nicht', () => { const result = classifyPackage(pkg({ packageName: 'Custom Character', revoked: true })); assert.equal(result.kind, 'ignore'); }); it('schiebt unklare CC-Titel in die Handpruefung statt zu raten', () => { assert.equal(classifyPackage(pkg({ packageName: 'CC Sonderaktion Winter' })).kind, 'unclear'); }); }); describe('SteamID-Schreibweisen', () => { // Dieselbe (erfundene) Kennung in drei Formaten. const legacy = 'STEAM_0:1:19867635'; const modern = '[U:1:39735271]'; const sixtyFour = '76561198000000999'; it('fuehrt alle drei Formate auf dieselbe ID zusammen', () => { assert.equal(normalizeSteamId(legacy), sixtyFour); assert.equal(normalizeSteamId(modern), sixtyFour); assert.equal(normalizeSteamId(sixtyFour), sixtyFour); }); it('rechnet zurueck in die Legacy-Form', () => { assert.equal(toLegacySteamId(sixtyFour), legacy); }); it('beherrscht auch das ungerade Bit', () => { const odd = 'STEAM_0:1:12345678'; const asNumber = normalizeSteamId(odd); assert.ok(asNumber); assert.equal(toLegacySteamId(asNumber), odd); }); it('weist Unsinn ab', () => { assert.equal(normalizeSteamId('Darkbrine44'), null); assert.equal(normalizeSteamId(''), null); assert.equal(normalizeSteamId('12345'), null); assert.equal(looksLikeSteamId('Darkbrine44'), false); }); });