diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-06 18:11:36 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-09-07 13:59:12 -0300 |
| commit | 60367d8fe23f6af98ec28e3cf6c2094dfe332df0 (patch) | |
| tree | 310fc734173cf771881f4691c71909135fadde97 /test/web-snapshots/touch.mjs | |
| parent | fa82cac885cb4738fe36d1e49b4749b5a3e31a4a (diff) | |
| download | pardes-60367d8fe23f6af98ec28e3cf6c2094dfe332df0.tar.gz pardes-60367d8fe23f6af98ec28e3cf6c2094dfe332df0.zip | |
Refactor panes and filesystem; replace FUSE with 9P
Consolidate pane, layout, memory and host code. Serve 9P by default over Unix sockets, with runtime mounts and optional TCP/QUIC transports. Remove FUSE and obsolete proof-of-concept examples.
Fix highlighting and terminal-history performance, expand differential and stress-test infrastructure, sort navigation results while preserving the next occurrence, add syntax-colored Braille minimaps, remove SPC-k, and document 9P interaction as a repository skill.
Diffstat (limited to 'test/web-snapshots/touch.mjs')
| -rw-r--r-- | test/web-snapshots/touch.mjs | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/test/web-snapshots/touch.mjs b/test/web-snapshots/touch.mjs new file mode 100644 index 00000000..1a233e68 --- /dev/null +++ b/test/web-snapshots/touch.mjs @@ -0,0 +1,99 @@ +import assert from "node:assert/strict"; + +function tags(frame) { + return frame.styleRows.flatMap((cells, y) => y > 0 && cells.some((cell) => cell[2] & 128) ? [y] : []); +} + +function pane(frame, name) { + const rows = tags(frame); + const top = rows.find((row) => frame.lines[row].includes(name)); + assert.notEqual(top, undefined, `missing pane ${name}`); + const bottom = rows.find((row) => row > top) ?? frame.rows; + return { top, bottom, lines: frame.lines.slice(top + 1, bottom) }; +} + +function styled(frame) { + const source = pane(frame, "touch-fixture.zig"); + for (const [line, word, fg, bold] of [ + ["pub fn choose", "fn", 0xcf87e8, true], + ["pub fn choose", "choose", 0xbdbdbd, false], + ["if (value", "if", 0xcf87e8, true], + ["if (value", "42", 0xe3c78a, false], + ["if (value", '"touch fixture"', 0xe3c78a, false], + ]) { + const row = source.lines.findIndex((text) => text.includes(line)); + assert(row >= 0, `missing source line ${line}`); + const col = source.lines[row].indexOf(word); + for (let x = col; x < col + word.length; x++) { + const style = frame.styleRows[source.top + 1 + row][x]; + assert.equal(style[0], fg, `${word} cell ${x - col} foreground`); + assert.equal(Boolean(style[2] & 1), bold, `${word} cell ${x - col} bold`); + } + } + for (const [row, line] of source.lines.entries()) { + const number = /\b(\d+),/.exec(line); + if (!number) continue; + for (let x = number.index; x < number.index + number[1].length; x++) { + assert.equal(frame.styleRows[source.top + 1 + row][x][0], 0xe3c78a, `row ${row} number foreground`); + } + } +} + +export default async function ({ grid, touch, wait, stable, delay }) { + await stable(100, 5000); + let frame = await grid(); + assert.equal(tags(frame).length, 1); + styled(frame); + const link = "/virtual/pane/1/body"; + const row = frame.lines.findIndex((text) => text.includes(link)); + const col = frame.lines[row].indexOf(link) + 5; + let finger = await touch("down", 1, col, row, null); + finger = await touch("move", 1, col + 0.2, row + 0.1, finger); + await touch("up", 1, col + 0.2, row + 0.1, finger); + await wait(async () => tags(await grid()).length === 2, 5000, "Look opening the reflected body"); + await stable(100, 5000); + frame = await grid(); + styled(frame); + const reflected = pane(frame, link); + assert(reflected.lines.some((text) => text.includes("pub fn choose"))); + const original = pane(frame, "touch-fixture.zig"); + const sharedRows = Math.min(reflected.lines.length, original.lines.length); + assert(sharedRows >= 6); + assert.deepEqual(reflected.lines.slice(0, sharedRows), original.lines.slice(0, sharedRows), "Look must read the source pane body"); + + const center = Math.floor(frame.cols / 2); + const separator = Math.max(original.top, reflected.top) - 1; + const distance = original.top < reflected.top ? 4 : -4; + finger = await touch("down", 2, center, separator, null); + for (let step = 1; step <= 8; step++) { + finger = await touch("move", 2, center, separator + distance * step / 8, finger); + await delay(20); + } + await touch("up", 2, center, separator + distance, finger); + await stable(100, 5000); + frame = await grid(); + assert.equal(tags(frame).length, 2); + const resized = pane(frame, "touch-fixture.zig"); + assert(resized.lines.length >= original.lines.length + 3, "separator drag must resize, not scroll the body"); + assert.equal(resized.lines[0], original.lines[0], "resizing must preserve the source viewport"); + styled(frame); + + const beforeScroll = resized.lines[0]; + const reflectedBeforeScroll = pane(frame, link).lines; + const from = resized.bottom - 3; + const to = Math.max(resized.top + 2, from - 7); + finger = await touch("down", 3, center, from, null); + for (let step = 1; step <= 12; step++) { + finger = await touch("move", 3, center, from + (to - from) * step / 12, finger); + await delay(20); + } + await touch("up", 3, center, to, finger); + await stable(100, 5000); + frame = await grid(); + assert.equal(tags(frame).length, 2, "scroll must not also Look"); + const scrolled = pane(frame, "touch-fixture.zig"); + assert.equal(scrolled.top, resized.top, "body scrolling must not resize"); + assert.notEqual(scrolled.lines[0], beforeScroll, "source must scroll"); + assert(Number(scrolled.lines[0].trim().split(/\s+/)[0]) > 1, "scroll advances source line numbers"); + assert.deepEqual(pane(frame, link).lines, reflectedBeforeScroll, "scrolling the source must leave its neighbor alone"); +} |
