import test from 'node:test';
import assert from 'node:assert/strict';
import { createElement } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { TableTalk } from '../components/table-talk';
import { createGame, newPlayer, viewGame } from '../game/engine';
import {
validTalkDraft,
clearTalkDraft,
restoreTalkDraft,
talkDraftKey,
mergeTalkPages,
} from '../lib/table-talk';
void test('message retry validation preserves exact text and recipient, rejects injected identities and invalid payloads', () => {
const draft = {
id: crypto.randomUUID(),
recipientId: crypto.randomUUID(),
text: ' line one\n ',
};
assert.deepEqual(restoreTalkDraft(JSON.stringify(draft)), draft);
for (const value of [
null,
[],
{},
{ ...draft, senderId: 'forged' },
{ ...draft, id: 1 },
{ ...draft, text: '\u0000' },
{ ...draft, text: ' '.repeat(20) },
{ ...draft, text: 'a'.repeat(1001) },
{ ...draft, recipientId: 'table' },
])
assert.equal(validTalkDraft(value), false);
assert.equal(restoreTalkDraft('not JSON'), null);
assert.notEqual(
talkDraftKey('AAAAAAAA', 'one'),
talkDraftKey('AAAAAAAA', 'two'),
);
assert.notEqual(
talkDraftKey('AAAAAAAA', 'one'),
talkDraftKey('BBBBBBBB', 'one'),
);
});
void test('discussion entry has a named disclosure and no server-rendered private history', () => {
const game = createGame(
'ABCDEFGH',
newPlayer('one', 'Human', 'atreides'),
false,
[],
);
const html = renderToStaticMarkup(
createElement(TableTalk, { game: viewGame(game, 'one') }),
);
assert.match(html, /Table discussion/);
assert.match(html, /aria-expanded="false"/);
assert.doesNotMatch(html, /textarea|