Möbel und Requisiten aus der Vorlage (Schreibtisch, Monitor mit Schalter an/aus, Aktenschrank, Pflanze, Münze, Pokal, Stempel, Radar, Briefkasten, Tresor, Waage), neu Ablagekorb, Schild und die acht 7x7-Branchen-Icons mit drawIcon. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
83 lines
6.4 KiB
JavaScript
83 lines
6.4 KiB
JavaScript
import test from 'node:test'
|
||
import assert from 'node:assert/strict'
|
||
import { loadModule } from './load.mjs'
|
||
import { makeCtx } from './helpers/fakeCtx.mjs'
|
||
|
||
// Engine-Requisiten: Möbel, Briefkasten, Tresor, Waage, Schild und die 7×7-Branchen-Icons
|
||
const P = await loadModule('src/components/workers/engine/props.js')
|
||
const { PAL } = await loadModule('src/components/workers/engine/sprites.js')
|
||
const { SEARCH_ROOMS } = await loadModule('src/lib/workersRoster.js')
|
||
|
||
test('alle Requisiten zeichnen ohne Wurf und mindestens ein Rechteck', () => {
|
||
const calls = { desk: (c) => P.drawDesk(c, 0, 0, 18, '#f00'), monitor: (c) => P.drawMonitor(c, 0, 0, 1, '#7fb2ff'), cabinet: (c) => P.drawCabinet(c, 0, 0, 3), plant: (c) => P.drawPlant(c, 0, 0),
|
||
coin: (c) => P.drawCoin(c, 0, 0, 0.3), trophy: (c) => P.drawTrophy(c, 0, 0), stampOk: (c) => P.drawStamp(c, 0, 0, true), stampNo: (c) => P.drawStamp(c, 0, 0, false),
|
||
radar: (c) => P.drawRadar(c, 0, 0, 1), mailbox: (c) => P.drawMailbox(c, 0, 0, 2), vault: (c) => P.drawVault(c, 0, 0, 1), scale: (c) => P.drawScale(c, 0, 0, 2), tray: (c) => P.drawTray(c, 0, 0, true) }
|
||
for (const [name, fn] of Object.entries(calls)) { const { ctx, rects } = makeCtx(); fn(ctx); assert.ok(rects.length >= 1, name) }
|
||
})
|
||
test('Briefkasten-Abzeichen nur bei count > 0; Monitor aus zeigt keine Inhaltszeilen', () => {
|
||
const red = (n) => { const { ctx, rects } = makeCtx(); P.drawMailbox(ctx, 0, 0, n); return rects.filter((r) => r.fill === PAL.red).length }
|
||
assert.equal(red(0), 0); assert.ok(red(3) >= 1)
|
||
const lines = (on) => { const { ctx, rects } = makeCtx(); P.drawMonitor(ctx, 0, 0, 1, '#abcdef', on); return rects.filter((r) => r.fill === '#abcdef').length }
|
||
assert.ok(lines(true) >= 2); assert.equal(lines(false), 0)
|
||
})
|
||
test('ICONS: genau die 8 Suchräume, je 7 Zeilen à 7 Zeichen; drawSign schreibt den Text', () => {
|
||
assert.deepEqual(Object.keys(P.ICONS).sort(), ['aerzte', 'foren', 'handwerk', 'kleinanzeigen', 'laden', 'netz', 'portale', 'selbst'])
|
||
for (const [k, rows] of Object.entries(P.ICONS)) { assert.equal(rows.length, 7, k); for (const r of rows) assert.match(r, /^[.xa]{7}$/, k) }
|
||
const { ctx, texts, rects } = makeCtx(); P.drawSign(ctx, 0, 0, 40, 'noch nicht angeschlossen'); assert.equal(texts[0].text, 'noch nicht angeschlossen'); assert.ok(rects.length >= 2)
|
||
const t = makeCtx(); P.drawIcon(t.ctx, 'aerzte', 0, 0, '#3fb6b2'); assert.ok(t.rects.length >= 5)
|
||
})
|
||
|
||
// ---- Ergänzungen: Verhalten, das die drei Tests oben nicht berühren ----
|
||
|
||
test('ICONS: Schlüssel gleich SEARCH_ROOMS, eingefroren, jedes Icon hat Linien und die Zeichen stehen nur in .xa', () => {
|
||
assert.deepEqual([...SEARCH_ROOMS].sort(), Object.keys(P.ICONS).sort())
|
||
assert.ok(Object.isFrozen(P.ICONS))
|
||
for (const [k, rows] of Object.entries(P.ICONS)) {
|
||
assert.ok(Object.isFrozen(rows), k)
|
||
assert.ok(rows.join('').includes('x'), k)
|
||
}
|
||
})
|
||
test('drawIcon: x in der Farbe, a in Gold, nichts außerhalb von 7 × 7; unbekannter Name zeichnet nichts und wirft nicht', () => {
|
||
const { ctx, rects } = makeCtx(); P.drawIcon(ctx, 'handwerk', 10, 20, '#3fb6b2')
|
||
assert.ok(rects.some((r) => r.fill === '#3fb6b2')); assert.ok(rects.some((r) => r.fill === PAL.gold))
|
||
assert.ok(rects.every((r) => r.fill === '#3fb6b2' || r.fill === PAL.gold))
|
||
assert.ok(rects.every((r) => r.x >= 30 && r.x + r.w <= 30 + 21 && r.y >= 60 && r.y + r.h <= 60 + 21))
|
||
for (const name of ['gibt-es-nicht', 'constructor', '__proto__', 'toString', undefined, null]) {
|
||
const e = makeCtx(); assert.doesNotThrow(() => P.drawIcon(e.ctx, name, 0, 0, '#000'), String(name)); assert.equal(e.rects.length, 0, String(name))
|
||
}
|
||
})
|
||
test('drawIcon: jedes der acht Icons zeichnet sichtbar (mindestens 5 Rechtecke)', () => {
|
||
for (const name of Object.keys(P.ICONS)) { const { ctx, rects } = makeCtx(); P.drawIcon(ctx, name, 0, 0, '#123456'); assert.ok(rects.length >= 5, name) }
|
||
})
|
||
test('drawMonitor: Standard ist an; aus hat kein Blinken, an blinkt mit t', () => {
|
||
const draw = (t, on) => { const { ctx, rects } = makeCtx(); if (on === undefined) P.drawMonitor(ctx, 0, 0, t, '#abcdef'); else P.drawMonitor(ctx, 0, 0, t, '#abcdef', on); return JSON.stringify(rects) }
|
||
assert.equal(draw(0.2), draw(0.2, true))
|
||
assert.notEqual(draw(0.2, true), draw(0.7, true))
|
||
assert.equal(draw(0.2, false), draw(0.7, false))
|
||
const off = makeCtx(); P.drawMonitor(off.ctx, 0, 0, 1, '#abcdef', false); assert.ok(off.rects.length >= 2) // Rahmen und Schirm bleiben
|
||
})
|
||
test('drawTray: voll zeigt Papier über dem Rand, beide bleiben in 10 × 4', () => {
|
||
const draw = (filled) => { const { ctx, rects } = makeCtx(); P.drawTray(ctx, 5, 7, filled); return rects }
|
||
const full = draw(true); const empty = draw(false)
|
||
assert.ok(full.some((r) => r.fill === PAL.w)); assert.ok(!empty.some((r) => r.fill === PAL.w))
|
||
for (const rs of [full, empty]) assert.ok(rs.every((r) => r.x >= 15 && r.x + r.w <= 15 + 30 && r.y >= 21 && r.y + r.h <= 21 + 12))
|
||
assert.equal(Math.max(...full.map((r) => r.x + r.w)) - Math.min(...full.map((r) => r.x)), 30)
|
||
})
|
||
test('drawSign: dunkler Rand, weiße Fläche, Text mittig im Schild', () => {
|
||
const { ctx, rects, texts } = makeCtx(); P.drawSign(ctx, 4, 6, 40, 'Ablage')
|
||
assert.equal(rects[0].fill, PAL.o); assert.ok(rects.some((r) => r.fill === PAL.w))
|
||
const border = rects[0]; assert.deepEqual([border.x, border.y, border.w], [12, 18, 120])
|
||
assert.ok(rects.slice(1).every((r) => r.x > border.x && r.x + r.w < border.x + border.w && r.y > border.y && r.y + r.h < border.y + border.h))
|
||
assert.equal(texts.length, 1); assert.equal(texts[0].x, (4 + 20) * 3)
|
||
assert.ok(texts[0].y > border.y && texts[0].y < border.y + border.h)
|
||
})
|
||
test('drawStamp: ok grün, nein rot; drawCoin dreht sich mit t; drawScale kippt mit tilt', () => {
|
||
const fills = (fn) => { const { ctx, rects } = makeCtx(); fn(ctx); return new Set(rects.map((r) => r.fill)) }
|
||
assert.ok(fills((c) => P.drawStamp(c, 0, 0, true)).has(PAL.green)); assert.ok(!fills((c) => P.drawStamp(c, 0, 0, true)).has(PAL.red))
|
||
assert.ok(fills((c) => P.drawStamp(c, 0, 0, false)).has(PAL.red)); assert.ok(!fills((c) => P.drawStamp(c, 0, 0, false)).has(PAL.green))
|
||
const coinW = (t) => { const { ctx, rects } = makeCtx(); P.drawCoin(ctx, 0, 0, t); return rects[0].w }
|
||
assert.notEqual(coinW(0), coinW(1 / 6))
|
||
const pans = (tilt) => { const { ctx, rects } = makeCtx(); P.drawScale(ctx, 0, 0, tilt); return rects.filter((r) => r.w === 15 && r.h === 6).map((r) => r.y) }
|
||
assert.equal(pans(0).length, 2); assert.notDeepEqual(pans(2), pans(-2))
|
||
})
|