summaryrefslogtreecommitdiff
path: root/test/web-snapshots/touch.mjs
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-06 18:11:36 -0300
committerGabriel Schneider <[email protected]>2026-09-07 13:59:12 -0300
commit60367d8fe23f6af98ec28e3cf6c2094dfe332df0 (patch)
tree310fc734173cf771881f4691c71909135fadde97 /test/web-snapshots/touch.mjs
parentfa82cac885cb4738fe36d1e49b4749b5a3e31a4a (diff)
downloadpardes-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.mjs99
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");
+}