Files
test01/tests/life-demo.test.js

149 lines
3.8 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
function loadApi() {
let api;
assert.doesNotThrow(() => {
api = require('../app.js');
}, 'expected app.js to export the Conway helpers');
return api;
}
test('blinker rotates after one generation', () => {
const { createEmptyGrid, stepGrid } = loadApi();
const grid = createEmptyGrid(5, 5);
grid[2][1] = 1;
grid[2][2] = 1;
grid[2][3] = 1;
const next = stepGrid(grid);
assert.deepEqual(next, [
[0, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0],
]);
});
test('block stays stable across generations', () => {
const { createEmptyGrid, stepGrid } = loadApi();
const grid = createEmptyGrid(4, 4);
grid[1][1] = 1;
grid[1][2] = 1;
grid[2][1] = 1;
grid[2][2] = 1;
assert.deepEqual(stepGrid(grid), grid);
});
test('stampPattern places the glider cells inside the grid', () => {
const { createEmptyGrid, stampPattern, PATTERNS } = loadApi();
const grid = createEmptyGrid(6, 6);
stampPattern(grid, PATTERNS.glider, 1, 1);
assert.equal(grid[1][2], 1);
assert.equal(grid[2][3], 1);
assert.equal(grid[3][1], 1);
assert.equal(grid[3][2], 1);
assert.equal(grid[3][3], 1);
});
test('createInitialState seeds the default preset and starts paused', () => {
const { createInitialState } = loadApi();
const state = createInitialState({
rows: 20,
cols: 20,
defaultPattern: 'pulsar',
});
assert.equal(state.running, false);
assert.equal(state.selectedPattern, 'pulsar');
assert.equal(state.generation, 0);
assert.ok(state.liveCount > 0);
});
test('toggleCell flips a single cell without mutating the original grid', () => {
const { createEmptyGrid, toggleCell } = loadApi();
const grid = createEmptyGrid(3, 3);
const next = toggleCell(grid, 1, 1);
assert.equal(grid[1][1], 0);
assert.equal(next[1][1], 1);
});
test('applyPreset replaces the grid, pauses playback, and resets generation', () => {
const { applyPreset, createInitialState } = loadApi();
const state = {
...createInitialState({ rows: 30, cols: 30, defaultPattern: 'glider' }),
generation: 12,
running: true,
};
const next = applyPreset(state, 'gosperGliderGun');
assert.equal(next.running, false);
assert.equal(next.generation, 0);
assert.equal(next.selectedPattern, 'gosperGliderGun');
assert.ok(next.liveCount > 0);
});
test('advanceState steps the grid and increments generation', () => {
const { advanceState, createEmptyGrid } = loadApi();
const grid = createEmptyGrid(5, 5);
grid[2][1] = 1;
grid[2][2] = 1;
grid[2][3] = 1;
const next = advanceState({
cols: 5,
generation: 0,
grid: grid,
liveCount: 3,
rows: 5,
running: true,
selectedPattern: 'custom',
speed: 1,
});
assert.equal(next.generation, 1);
assert.equal(next.liveCount, 3);
assert.equal(next.grid[1][2], 1);
assert.equal(next.grid[2][2], 1);
assert.equal(next.grid[3][2], 1);
});
test('randomizeGrid respects probability extremes', () => {
const { createEmptyGrid, randomizeGrid } = loadApi();
const grid = createEmptyGrid(2, 3);
assert.deepEqual(randomizeGrid(grid, 0), [
[0, 0, 0],
[0, 0, 0],
]);
assert.deepEqual(randomizeGrid(grid, 1), [
[1, 1, 1],
[1, 1, 1],
]);
});
test('setSpeed returns a copied state with a readable label', () => {
const { createInitialState, getSpeedDelay, getSpeedLabel, setSpeed } = loadApi();
const state = createInitialState({ rows: 10, cols: 10, defaultPattern: 'glider' });
const next = setSpeed(state, 4);
assert.notEqual(next, state);
assert.equal(next.speed, 4);
assert.equal(getSpeedLabel(next.speed), 'Hyper');
assert.equal(getSpeedLabel(1), 'Drift');
assert.equal(getSpeedDelay(1), 520);
assert.equal(getSpeedDelay(6), 60);
});