Rollen neu geschnitten, Seitenzahl korrigiert, frühere Konten
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.
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { after, before, describe, it } from 'node:test';
|
||||
import { startTestDatabase, type TestDatabase } from './harness.js';
|
||||
|
||||
type Players = typeof import('../src/services/players.js');
|
||||
type Scraper = typeof import('../src/services/scraper.js');
|
||||
type Db = typeof import('../src/db.js');
|
||||
|
||||
let database: TestDatabase;
|
||||
let players: Players;
|
||||
let scraper: Scraper;
|
||||
let db: Db;
|
||||
let ctx: { actorId: number; actorName: string };
|
||||
|
||||
before(async () => {
|
||||
database = await startTestDatabase(54335);
|
||||
process.env.DATABASE_URL = database.url;
|
||||
process.env.SESSION_SECRET = 'test-secret-that-is-long-enough-000000';
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
db = await import('../src/db.js');
|
||||
players = await import('../src/services/players.js');
|
||||
scraper = await import('../src/services/scraper.js');
|
||||
|
||||
const user = await db.prisma.user.create({
|
||||
data: { username: 'pfleger', passwordHash: 'x', role: 'ADMIN' },
|
||||
});
|
||||
ctx = { actorId: user.id, actorName: user.username };
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await db.prisma.$disconnect();
|
||||
await database.stop();
|
||||
});
|
||||
|
||||
describe('Frühere Konten', () => {
|
||||
it('bringt eine nachgetragene SteamID auf dieselbe Form wie die Hauptangabe', async () => {
|
||||
const player = await db.prisma.player.create({
|
||||
data: { displayName: 'Umzügler', steamId: '76561198000001111' },
|
||||
});
|
||||
|
||||
// In der Legacy-Schreibweise eingegeben, gespeichert wird die 64-Bit-Form.
|
||||
await players.addAlias(player.id, 'STEAM_ID', 'STEAM_0:1:19867635', 'Alter Account', ctx);
|
||||
|
||||
const alias = await db.prisma.playerAlias.findFirstOrThrow({ where: { playerId: player.id } });
|
||||
assert.equal(alias.value, '76561198000000999');
|
||||
});
|
||||
|
||||
it('klappert beim Abgleich auch die früheren Konten ab', async () => {
|
||||
const ids = await scraper.knownSteamIds();
|
||||
const fuerUmzuegler = ids.filter((e) => e.steamId.startsWith('765611980000'));
|
||||
|
||||
assert.ok(
|
||||
fuerUmzuegler.some((e) => e.steamId === '76561198000001111'),
|
||||
'die aktuelle Kennung',
|
||||
);
|
||||
assert.ok(
|
||||
fuerUmzuegler.some((e) => e.steamId === '76561198000000999'),
|
||||
'und die frühere',
|
||||
);
|
||||
});
|
||||
|
||||
it('nimmt dieselbe Kennung nicht zweimal in den Lauf', async () => {
|
||||
const ids = await scraper.knownSteamIds();
|
||||
const eindeutig = new Set(ids.map((e) => e.steamId));
|
||||
assert.equal(ids.length, eindeutig.size);
|
||||
});
|
||||
|
||||
it('lässt ein Konto nicht zwei Spielern gehören', async () => {
|
||||
const anderer = await db.prisma.player.create({ data: { displayName: 'Fremder' } });
|
||||
|
||||
await assert.rejects(
|
||||
() => players.addAlias(anderer.id, 'STEAM_ID', '76561198000000999', undefined, ctx),
|
||||
(error: Error & { code?: string }) => error.code === 'ALIAS_TAKEN',
|
||||
);
|
||||
});
|
||||
|
||||
it('weist die eigene Hauptangabe als Alias ab', async () => {
|
||||
const player = await db.prisma.player.findFirstOrThrow({ where: { displayName: 'Umzügler' } });
|
||||
|
||||
await assert.rejects(
|
||||
() => players.addAlias(player.id, 'STEAM_ID', '76561198000001111', undefined, ctx),
|
||||
(error: Error & { code?: string }) => error.code === 'IS_PRIMARY',
|
||||
);
|
||||
});
|
||||
|
||||
it('weist Unsinn als SteamID ab', async () => {
|
||||
const player = await db.prisma.player.findFirstOrThrow({ where: { displayName: 'Umzügler' } });
|
||||
|
||||
await assert.rejects(
|
||||
() => players.addAlias(player.id, 'STEAM_ID', 'kein-account', undefined, ctx),
|
||||
(error: Error & { code?: string }) => error.code === 'INVALID_STEAMID',
|
||||
);
|
||||
});
|
||||
|
||||
it('nimmt Forum-Namen ohne Umrechnung', async () => {
|
||||
const player = await db.prisma.player.findFirstOrThrow({ where: { displayName: 'Umzügler' } });
|
||||
const alias = await players.addAlias(player.id, 'FORUM_NAME', 'AlterName2019', undefined, ctx);
|
||||
|
||||
assert.equal(alias.value, 'AlterName2019');
|
||||
});
|
||||
});
|
||||
Vendored
+1
@@ -70,6 +70,7 @@
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<woltlab-core-pagination page="1" count="25" url="https://forum.example.org/index.php?board/66-custom-characters/"></woltlab-core-pagination>
|
||||
<nav class="pagination"><ul>
|
||||
<li><a href="index.php?board/66-custom-characters/&pageNo=2" class="pageNavigationLink">2</a></li>
|
||||
<li><a href="index.php?board/66-custom-characters/&pageNo=3" class="pageNavigationLink">3</a></li>
|
||||
|
||||
@@ -40,8 +40,14 @@ describe('Board-Übersicht lesen', () => {
|
||||
assert.equal(threads.some((t) => t.threadId === 9999), false);
|
||||
});
|
||||
|
||||
it('liest die Seitenzahl aus der Blätterleiste', () => {
|
||||
assert.equal(parsePageCount(BOARD), 3);
|
||||
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);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user