import { describe, it, expect } from 'vitest'; import { lineFrom, matchWord } from './wordsearch.js'; const colinear = (cells) => { if (cells.length < 2) return true; const [r0, c0] = cells[0], [r1, c1] = cells[1]; const sr = Math.sign(r1 - r0), sc = Math.sign(c1 - c0); return cells.every(([r, c], i) => r === r0 + sr * i && c === c0 + sc * i); }; describe('lineFrom', () => { it('builds straight horizontal / vertical / diagonal runs', () => { expect(lineFrom([2, 1], [2, 4], 10)).toEqual([[2, 1], [2, 2], [2, 3], [2, 4]]); expect(lineFrom([1, 3], [4, 3], 10)).toEqual([[1, 3], [2, 3], [3, 3], [4, 3]]); expect(lineFrom([0, 0], [3, 3], 10)).toEqual([[0, 0], [1, 1], [2, 2], [3, 3]]); }); it('snaps a non-straight drag onto a straight line (never bent)', () => { // knight-ish move (dr=1, dc=3) → should snap, and stay colinear const cells = lineFrom([5, 2], [6, 8], 10); expect(colinear(cells)).toBe(true); // a near-diagonal still resolves to a straight path expect(colinear(lineFrom([0, 0], [4, 5], 10))).toBe(true); }); it('clamps to the grid and handles a single cell', () => { expect(lineFrom([0, 0], [0, 0], 10)).toEqual([[0, 0]]); const cells = lineFrom([8, 8], [20, 8], 10); // runs off the bottom edge expect(cells.every(([r, c]) => r >= 0 && r < 10 && c >= 0 && c < 10)).toBe(true); }); }); describe('matchWord', () => { const grid = ['CALM', 'XXXX', 'XXXX', 'XXXX']; // CALM across row 0 const words = ['CALM', 'PEACE']; it('matches a forward word', () => { expect(matchWord([[0, 0], [0, 1], [0, 2], [0, 3]], grid, words, [])).toBe('CALM'); }); it('matches a reversed selection to the listed word', () => { expect(matchWord([[0, 3], [0, 2], [0, 1], [0, 0]], grid, words, [])).toBe('CALM'); }); it('is harmless on an already-found word (no re-record)', () => { expect(matchWord([[0, 0], [0, 1], [0, 2], [0, 3]], grid, words, ['CALM'])).toBe(null); }); it('returns null for a non-word or too-short selection', () => { expect(matchWord([[1, 0], [1, 1], [1, 2], [1, 3]], grid, words, [])).toBe(null); // XXXX expect(matchWord([[0, 0]], grid, words, [])).toBe(null); expect(matchWord([], grid, words, [])).toBe(null); }); });