import {test} from 'node:test';
import assert from 'node:assert/strict';
import {render, screen, within} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Game from './main.jsx';
const squares = () => screen.getAllByRole('button').slice(0, 9).map((button) => button.textContent);
const status = () => screen.getByText(/^(Next player|Winner):/).textContent;
const play = async (user, positions) => {
for (const i of positions) await user.click(screen.getAllByRole('button')[i]);
};
const moves = () => within(screen.getByRole('list')).queryAllByRole('button').map((button) => button.textContent);
const jump = async (user, name) => user.click(within(screen.getByRole('list')).getByRole('button', {name}));
test('The list starts with Go to game start', () => {
render(<Game />);
assert.deepEqual(moves(), ['Go to game start'], 'before any move the list reads ' + JSON.stringify(moves()));
});
test('Each move adds a button', async () => {
const user = userEvent.setup();
render(<Game />);
await play(user, [0, 1]);
assert.deepEqual(moves(), ['Go to game start', 'Go to move #1', 'Go to move #2'], 'after two moves the list reads ' + JSON.stringify(moves()));
});
test('Go to game start shows the empty board', async () => {
const user = userEvent.setup();
render(<Game />);
await play(user, [0, 1]);
await jump(user, 'Go to game start');
assert.deepEqual(squares(), ['', '', '', '', '', '', '', '', ''], 'after the jump to the start the squares read ' + JSON.stringify(squares()));
assert.equal(status(), 'Next player: X', 'after the jump to the start the status reads ' + JSON.stringify(status()));
});
test('Go to move #1 shows the board after the first move', async () => {
const user = userEvent.setup();
render(<Game />);
await play(user, [0, 1, 2]);
await jump(user, 'Go to move #1');
assert.deepEqual(squares().slice(0, 3), ['X', '', ''], 'after the jump to move #1 the top row reads ' + JSON.stringify(squares().slice(0, 3)));
assert.equal(status(), 'Next player: O', 'after the jump to move #1 the status reads ' + JSON.stringify(status()));
});
test('A move after a jump replaces the later moves', async () => {
const user = userEvent.setup();
render(<Game />);
await play(user, [0, 1, 2]);
await jump(user, 'Go to move #1');
await play(user, [4]);
assert.deepEqual(moves(), ['Go to game start', 'Go to move #1', 'Go to move #2'], 'after jumping to move #1 and playing again the list reads ' + JSON.stringify(moves()));
assert.deepEqual(squares().slice(0, 5), ['X', '', '', '', 'O'], 'the board reads ' + JSON.stringify(squares().slice(0, 5)) + ' in its first five squares');
});
test('React prints no warnings', async () => {
const warnings = [];
const original = console.error;
console.error = (...args) => warnings.push(args.join(' '));
try {
const user = userEvent.setup();
render(<Game />);
await play(user, [0, 4]);
} finally {
console.error = original;
}
assert.deepEqual(warnings, [], 'console.error while rendering and playing');
});