Files
tickte-system/tests/unit/workersProps.test.mjs
T
ClaudeandClaude Sonnet 5.5 514469d93c Workers P2: Engine-Requisiten und Branchen-Icons
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>
2026-10-18 01:58:15 +00:00

83 lines
6.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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))
})