Stage 7 (wip): tests + UI CI
- Vitest units: board replay, placement machine, premium parity, i18n key parity, FlatBuffers codec round-trips (19 tests) - Playwright smoke (mock transport): guest -> lobby -> board -> place tile -> preview - ui-test.yaml workflow: check/unit/build + bundle-size budget (67.5KB gzip < 100KB) + chromium e2e - gateway transcode tests for games.list (seat display_name), pass, hint - backend integration test for game.ListForAccount
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import {
|
||||
BLANK,
|
||||
direction,
|
||||
newPlacement,
|
||||
place,
|
||||
rackView,
|
||||
recallAt,
|
||||
reset,
|
||||
toSubmit,
|
||||
} from './placement';
|
||||
|
||||
const rack = ['A', 'Q', BLANK, 'N', 'I', 'W', 'E'];
|
||||
|
||||
describe('placement state machine', () => {
|
||||
it('places a tile and marks the rack slot used', () => {
|
||||
const p = place(newPlacement(rack), 0, 7, 7);
|
||||
expect(p.pending).toHaveLength(1);
|
||||
expect(rackView(p)[0].used).toBe(true);
|
||||
expect(rackView(p)[1].used).toBe(false);
|
||||
});
|
||||
|
||||
it('rejects reusing a slot or an occupied cell', () => {
|
||||
let p = place(newPlacement(rack), 0, 7, 7);
|
||||
p = place(p, 0, 7, 8); // same slot -> no-op
|
||||
expect(p.pending).toHaveLength(1);
|
||||
p = place(p, 1, 7, 7); // occupied cell -> no-op
|
||||
expect(p.pending).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('requires a letter for a blank slot', () => {
|
||||
const noLetter = place(newPlacement(rack), 2, 7, 7);
|
||||
expect(noLetter.pending).toHaveLength(0);
|
||||
const withLetter = place(newPlacement(rack), 2, 7, 7, 'x');
|
||||
expect(withLetter.pending[0]).toMatchObject({ letter: 'X', blank: true });
|
||||
});
|
||||
|
||||
it('recalls a tile by cell', () => {
|
||||
let p = place(newPlacement(rack), 0, 7, 7);
|
||||
p = recallAt(p, 7, 7);
|
||||
expect(p.pending).toHaveLength(0);
|
||||
expect(reset(place(p, 0, 7, 7)).pending).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('infers direction H for a row, V for a column, null for a single tile', () => {
|
||||
let h = place(newPlacement(rack), 0, 7, 7);
|
||||
h = place(h, 1, 7, 8);
|
||||
expect(direction(h)).toBe('H');
|
||||
let v = place(newPlacement(rack), 0, 7, 7);
|
||||
v = place(v, 1, 8, 7);
|
||||
expect(direction(v)).toBe('V');
|
||||
expect(direction(place(newPlacement(rack), 0, 7, 7))).toBeNull();
|
||||
});
|
||||
|
||||
it('builds a sorted submit payload and honours a direction override', () => {
|
||||
let p = place(newPlacement(rack), 1, 7, 9);
|
||||
p = place(p, 0, 7, 7);
|
||||
const sub = toSubmit(p);
|
||||
expect(sub?.dir).toBe('H');
|
||||
expect(sub?.tiles.map((t) => t.col)).toEqual([7, 9]);
|
||||
expect(toSubmit(place(newPlacement(rack), 0, 7, 7), 'V')?.dir).toBe('V');
|
||||
expect(toSubmit(newPlacement(rack))).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user