Antraege eingrenzen, Reaktivierung und Bestaetigungen

Sechs Ruecklaeufer aus dem ersten Praxistest:

Das Archiv reicht ueber 25 Seiten und enthaelt vieles, was kein CC-Antrag ist.
Aufgenommen werden jetzt nur Threads von Spielern, die im CC-Manager mit
passendem Forum-Namen erfasst sind. Angepinnte Ankuendigungen tragen die
Labels "Wichtig" oder "Information" und fallen darueber raus.

Der Titel wird bewusst nirgends ausgewertet - weder zum Erkennen noch zum
Aussortieren. Antraege heissen mal "CC Antrag | Name", mal "The Duke Rang
Update"; daran ist nichts abzulesen.

Eine Reaktivierung laeuft ebenfalls ueber einen Forums-Antrag und fehlte als
Entscheidung. Sie ist jetzt waehlbar und kostet nichts, solange der CC nicht
redesignt wurde - die bestehende Regel entscheidet das, nicht der Dialog.

Der Titel in der Liste verlinkt jetzt auf den Thread im Forum. Die Labels
stehen als Kontext daneben, ohne die Entscheidung vorwegzunehmen.

Wer einen Antrag von Hand eintraegt, kann beim Anlegen oder Redesignen den
Thread-Link angeben. Der Antrag gilt damit als erledigt und taucht nicht
erneut als offen auf.

Manuelle Guthaben-Buchungen fragen vorher nach: bisher buchte ein einzelner
Klick sofort, ohne zu sagen, was genau passiert. Der Dialog nennt die Wirkung
und nimmt eine Notiz entgegen.
This commit is contained in:
2026-09-18 18:06:37 +02:00
parent 751f8bfe8e
commit bebb89c10e
13 changed files with 503 additions and 59 deletions
+47 -3
View File
@@ -3,7 +3,7 @@ import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { describe, it } from 'node:test';
import { parseBoard, parsePageCount } from '../src/lib/forum.js';
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');
@@ -12,10 +12,10 @@ describe('Board-Übersicht lesen', () => {
const threads = parseBoard(BOARD);
it('liest die Threads der Liste', () => {
assert.equal(threads.length, 3);
assert.equal(threads.length, 5);
assert.deepEqual(
threads.map((t) => t.threadId),
[7001, 7002, 7003],
[7001, 7002, 7004, 7005, 7003],
);
});
@@ -49,3 +49,47 @@ describe('Board-Übersicht lesen', () => {
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);
});
});