Der Forums-Abgleich las von 25 Archivseiten nur zwei. WoltLab verlinkt in der Blätterleiste nur die Nachbarseiten und führt die Gesamtzahl in einem eigenen Element; ausgewertet wurden aber die Links. Alles jenseits von Seite zwei war damit unsichtbar - etwa ein Antrag auf Seite vier, der deshalb nie ankam. Die Rollen verlaufen jetzt zwischen erfassen und gewähren statt zwischen Alltag und Verwaltung: Editoren erfassen Käufe und führen Datei-Import, GExtension- und Forums-Abgleich samt Entscheidung über Anträge durch. Kulanz zu vergeben bleibt Administratoren, ebenso das Auflösen unklarer Pakete, weil dabei Kulanz entstehen kann. Dazu lassen sich frühere Steam- und Forumskonten am Spieler hinterlegen. Abgleich und Import prüfen sie mit, sodass ein Kontowechsel die Zuordnung nicht abreißen lässt. Steam-Kennungen werden dabei auf dieselbe Form gebracht wie die Hauptangabe, und eine Kennung kann nicht zwei Spielern gehören.
102 lines
3.7 KiB
TypeScript
102 lines
3.7 KiB
TypeScript
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 { hasIgnoredLabel, parseBoard, parsePageCount, parseThreadId } from '../src/lib/forum.js';
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
const BOARD = readFileSync(join(here, 'fixtures', 'board.html'), 'utf8');
|
|
|
|
describe('Board-Übersicht lesen', () => {
|
|
const threads = parseBoard(BOARD);
|
|
|
|
it('liest die Threads der Liste', () => {
|
|
assert.equal(threads.length, 5);
|
|
assert.deepEqual(
|
|
threads.map((t) => t.threadId),
|
|
[7001, 7002, 7004, 7005, 7003],
|
|
);
|
|
});
|
|
|
|
it('nimmt den Ersteller aus der Übersicht, nicht den letzten Antwortenden', () => {
|
|
const first = threads.find((t) => t.threadId === 7001);
|
|
assert.equal(first?.authorName, 'Antragsteller');
|
|
assert.equal(first?.authorForumId, 501, 'die Forum-ID überlebt Namensänderungen');
|
|
});
|
|
|
|
it('löst Umlaut- und Anführungszeichen-Entities auf', () => {
|
|
const second = threads.find((t) => t.threadId === 7002);
|
|
assert.equal(second?.title, 'Custom Character Redesign | Alt zu Neu');
|
|
});
|
|
|
|
it('erkennt einen zurückgelassenen Verweis als solchen', () => {
|
|
const stub = threads.find((t) => t.threadId === 7003);
|
|
assert.equal(stub?.isMovedStub, true);
|
|
});
|
|
|
|
it('ignoriert Unterforen und deren letzte Beiträge', () => {
|
|
// 9999 steht im wbbBoardNode-Kasten, gehoert aber nicht in dieses Board.
|
|
assert.equal(threads.some((t) => t.threadId === 9999), false);
|
|
});
|
|
|
|
it('liest die Gesamtzahl der Seiten, nicht nur die verlinkten', () => {
|
|
// Die Blätterleiste verlinkt hier nur Seite 2 und 3, das Board hat aber 25.
|
|
// Wer die Links auswertet, liest den grössten Teil des Archivs nie.
|
|
assert.equal(parsePageCount(BOARD), 25);
|
|
});
|
|
|
|
it('fällt ohne das Element auf die Links zurück', () => {
|
|
assert.equal(parsePageCount('<a href="x&pageNo=7">7</a>'), 7);
|
|
assert.equal(parsePageCount('<html>ohne Blaetterleiste</html>'), 1);
|
|
});
|
|
|
|
it('kommt mit einer leeren Seite klar', () => {
|
|
assert.deepEqual(parseBoard('<html><body>nichts</body></html>'), []);
|
|
});
|
|
});
|
|
|
|
describe('Ankündigungen aussortieren', () => {
|
|
const threads = parseBoard(BOARD);
|
|
|
|
it('liest die Labels eines Threads', () => {
|
|
const regelwerk = threads.find((t) => t.threadId === 7004);
|
|
assert.deepEqual(regelwerk?.labels, ['Wichtig', 'Global']);
|
|
});
|
|
|
|
it('erkennt Wichtig und Information als Ausschluss', () => {
|
|
assert.equal(hasIgnoredLabel(threads.find((t) => t.threadId === 7004)!), true);
|
|
assert.equal(hasIgnoredLabel(threads.find((t) => t.threadId === 7005)!), true);
|
|
});
|
|
|
|
it('lässt echte Anträge durch, auch mit anderen Labels', () => {
|
|
assert.equal(hasIgnoredLabel(threads.find((t) => t.threadId === 7001)!), false);
|
|
});
|
|
|
|
it('wertet den Titel nicht aus', () => {
|
|
// "The Duke Rang Update" war ein echter Antrag, "Regelwerk" keiner. Am Titel
|
|
// ist das nicht zu erkennen - deshalb entscheidet allein das Label.
|
|
const ohneStichwort = parseBoard(BOARD).find((t) => t.threadId === 7005);
|
|
assert.ok(ohneStichwort, 'auch ein Thread ohne CC im Titel wird gelesen');
|
|
});
|
|
});
|
|
|
|
describe('Thread-Verweis lesen', () => {
|
|
it('nimmt den vollen Link', () => {
|
|
assert.equal(
|
|
parseThreadId('https://senseigaming.de/forum/index.php?thread/8041-cc-antrag-feldagent/'),
|
|
8041,
|
|
);
|
|
});
|
|
|
|
it('nimmt auch nur den Pfad oder die blanke Nummer', () => {
|
|
assert.equal(parseThreadId('index.php?thread/7001-irgendwas/'), 7001);
|
|
assert.equal(parseThreadId('7001'), 7001);
|
|
});
|
|
|
|
it('weist Unbrauchbares ab', () => {
|
|
assert.equal(parseThreadId(''), null);
|
|
assert.equal(parseThreadId('kein link'), null);
|
|
});
|
|
});
|