Files
Dune/tests/harkonnen-exchange-controls.test.tsx
T
Quintine 0f79f28ccb Complete forced Harkonnen returns with private saved inspection
Automatically return the full combined hand when it is the only legal
special-Karama return. Preserve real choices and restore the suspended
response or auction payment through the same settlement. Record the actual
blind draw as owner-only historical card faces, with a bound integrity
receipt; legacy forced saves describe held-card history truthfully.

Add readable private history and enlarged inspectors. Both manual and
forced returns publish only a faction/action completion tag. Wake idle
legacy exchanges through production recovery without writes for real
choices. Keep provisional auction funding rules and release gates.

Validation: types, lint, 5150 offline tests, build and 49 HTTP tests
passed. Independent review resolved history substitution and root review
completed idle recovery wiring. New tests cover 1-4 forced draws, real
choices, overlays, exact saved history, immutable rejection, all four legal
AI paths, production competing actions/recovery, private views and custody.
One genuine Advanced four-player sample completed 158 actions with
4 JSON restores and no rejected action; no difficulty tuning.

Browser QA QUTHVPTT used genuine Advanced setup and conserved Bidding
positions. The actual power returned four cards without a prompt; private
history/enlargement and exact refresh worked. Phone panel fit without
horizontal overflow with 44px inspector controls. Screenshot capture timed
out; complete visual acceptance and transient notice capture remain open.
Preserved every prior row across all ten tables, including 1586
rooms and 3354 seats. New QA/integration records bring totals to
1626 rooms and 3442 seats. No reset, restart or automation.
2026-09-21 16:45:20 +10:00

42 lines
1.9 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { createElement } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { HarkonnenExchangeInspection } from '../components/harkonnen-exchange-inspection';
import { createGame, joinGame, newPlayer, viewGame, type GameView } from '../game/engine';
import { baseDeck } from '../game/cards';
function view() {
const game = createGame('INSPECTION', newPlayer('h', 'Harkonnen', 'harkonnen'));
joinGame(game, newPlayer('e', 'Emperor', 'emperor'));
const result = viewGame(game, 'h');
result.harkonnenExchangeInspection = {
owner: 'h', target: 'e', turn: 3, phase: 3, kind: 'draw',
cards: baseDeck().filter(card => card.name === 'Shield').slice(0, 1),
};
return result;
}
const render = (game: GameView) => renderToStaticMarkup(createElement(HarkonnenExchangeInspection, { game }));
void test('private exchange record offers readable cards and inspection without a return confirmation', () => {
const html = render(view());
assert.match(html, /Your Harkonnen inspection · Turn 3/);
assert.match(html, /Cards you took and inspected from Emperor/);
assert.match(html, /may have changed hands since/);
assert.match(html, /Shield/);
assert.match(html, /Inspect card: Shield/);
assert.doesNotMatch(html, /Return cards|Confirm|Acknowledge/);
});
void test('legacy history describes held cards without inventing their source', () => {
const game = view(); game.harkonnenExchangeInspection!.kind = 'return';
const html = render(game);
assert.match(html, /Cards in your hand before the automatic return to Emperor/);
assert.doesNotMatch(html, /Cards you took/);
});
void test('absent and mismatched-owner records render no private card information', () => {
const game = view(); game.me = 'e'; assert.equal(render(game), '');
game.me = 'h'; game.harkonnenExchangeInspection = null; assert.equal(render(game), '');
});