Support Sapho ordering for shared arrivals
Verify and publish checkpoint container / container (push) Canceled after 0s
Verify and publish checkpoint container / container (push) Canceled after 0s
This commit is contained in:
1 parent
b18a767470
commit
e457478f7d
18 files changed
+808
-23
No files matched your search
@@ -0,0 +1,66 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { createElement } from 'react';
|
||||
import { renderToStaticMarkup } from 'react-dom/server';
|
||||
import type { Action } from '../game/engine';
|
||||
import { SaphoArrivalOrder, SaphoArrivalOrderChoiceButton, SaphoArrivalOrderPass,
|
||||
type SaphoArrivalOrderProps } from '../components/sapho-arrival-order';
|
||||
|
||||
function props(choices: SaphoArrivalOrderProps['view']['choices'] = []): SaphoArrivalOrderProps & { sent: Action[] } {
|
||||
const sent: Action[] = [];
|
||||
const names: Record<string, string> = { ecaz: 'Ecaz', moritani: 'Moritani' };
|
||||
return { view: { event: 'arrival-order-event', revision: 2, order: ['ecaz', 'moritani'], passed: [], choices },
|
||||
me: 'ecaz', busy: false, name: id => names[id] ?? id,
|
||||
sent, act(action) { sent.push(action); } };
|
||||
}
|
||||
const render = (input: SaphoArrivalOrderProps) => renderToStaticMarkup(createElement(SaphoArrivalOrder, input));
|
||||
|
||||
void test('both reaction owners see a public ordering opportunity without needing Sapho', () => {
|
||||
const input = props(), html = render(input);
|
||||
assert.match(html, /Ambassador and Terror reaction order/);
|
||||
assert.match(html, /Ecaz.*→.*Moritani/);
|
||||
assert.match(html, /provisional interpretation/);
|
||||
assert.match(html, /Continue without changing reaction order/);
|
||||
assert.doesNotMatch(html, /Use Juice of Sapho/);
|
||||
SaphoArrivalOrderPass(input).props.onClick();
|
||||
assert.deepEqual(input.sent, [{ type: 'arrivalOrderPass', event: 'arrival-order-event', revision: 2 }]);
|
||||
});
|
||||
|
||||
void test('quoted private options dispatch the exact event-bound Sapho actions', () => {
|
||||
const input = props([{ card: 'private-card-id', mode: 'first' }, { card: 'private-card-id', mode: 'last' }]);
|
||||
const html = render(input);
|
||||
assert.match(html, /Use Juice of Sapho to react first/);
|
||||
assert.match(html, /Use Juice of Sapho to react last/);
|
||||
assert.doesNotMatch(html, /private-card-id/);
|
||||
for (const choice of input.view.choices) SaphoArrivalOrderChoiceButton({ ...input, choice }).props.onClick();
|
||||
assert.deepEqual(input.sent, input.view.choices.map(choice => ({ type: 'saphoArrivalOrder',
|
||||
event: 'arrival-order-event', revision: 2, ...choice })));
|
||||
});
|
||||
|
||||
void test('busy, already-passed and other viewers cannot issue ordering actions', () => {
|
||||
for (const variant of ['busy', 'passed', 'other'] as const) {
|
||||
const input = props([{ card: 'sapho-card', mode: 'first' }]);
|
||||
if (variant === 'busy') input.busy = true;
|
||||
if (variant === 'passed') input.view.passed.push(input.me);
|
||||
if (variant === 'other') input.me = 'other';
|
||||
SaphoArrivalOrderPass(input).props.onClick();
|
||||
SaphoArrivalOrderChoiceButton({ ...input, choice: input.view.choices[0] }).props.onClick();
|
||||
assert.deepEqual(input.sent, []);
|
||||
if (variant !== 'busy') assert.doesNotMatch(render(input), /data-testid="sapho-arrival-order-pass"/);
|
||||
else assert.match(render(input), /disabled=""/);
|
||||
}
|
||||
});
|
||||
|
||||
void test('callbacks captured before an event, revision, pass or quoted choice changes do not send', () => {
|
||||
for (const change of ['event', 'revision', 'pass', 'choice'] as const) {
|
||||
const input = props([{ card: 'sapho-card', mode: 'first' }]);
|
||||
const pass = SaphoArrivalOrderPass(input), choice = SaphoArrivalOrderChoiceButton({ ...input, choice: input.view.choices[0] });
|
||||
if (change === 'event') input.view.event = 'new-event';
|
||||
if (change === 'revision') input.view.revision++;
|
||||
if (change === 'pass') input.view.passed.push(input.me);
|
||||
if (change === 'choice') input.view.choices.splice(0);
|
||||
if (change !== 'choice') pass.props.onClick();
|
||||
choice.props.onClick();
|
||||
assert.deepEqual(input.sent, []);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user