summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-15 14:46:38 -0300
committerGabriel Schneider <[email protected]>2026-09-15 17:24:42 -0300
commit40c19fd4f52d20df94c2dfa2d68102b89bd9d3f1 (patch)
tree642150be8703f1d9a0766ff18516f06bfdc8801a /test
parent379f4fe55c7c9c7c8cc7b97dc921c83e2c24698b (diff)
downloadpardes-40c19fd4f52d20df94c2dfa2d68102b89bd9d3f1.tar.gz
pardes-40c19fd4f52d20df94c2dfa2d68102b89bd9d3f1.zip
Add optional compact tagline styling for source context
Diffstat (limited to 'test')
-rw-r--r--test/panes.zig55
-rw-r--r--test/web-snapshots/touch.mjs39
2 files changed, 94 insertions, 0 deletions
diff --git a/test/panes.zig b/test/panes.zig
index a452bcfb..16e40ee3 100644
--- a/test/panes.zig
+++ b/test/panes.zig
@@ -190,6 +190,60 @@ const TagNavigationTests = struct {
}
};
+const BodyHitTests = struct {
+ fn mouse(layer: *const pardes.BodyLayer, row: u16, col: u16, kind: pardes.Mouse.Kind) pardes.Mouse {
+ const width: f32 = if (row < layer.context_rows) 8 else 10;
+ const x = @as(f32, @floatFromInt(layer.viewport.x)) * 10 + (@as(f32, @floatFromInt(col)) + 0.5) * width;
+ const y = layer.rowTop(row, 20, 10) + layer.rowHeight(row, 20, 10) / 2;
+ return .{ .button = .left, .kind = kind, .col = @intFromFloat(x / 10), .row = @intFromFloat(y / 20), .body_hit = layer.hitAt(x, y, 10, 20, 8, 10).? };
+ }
+
+ test "compact TreeContext mouse follows source rows in reclaimed space" {
+ if (!syntax.enabled) return error.SkipZigTest;
+ const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 64, .rows = 18 });
+ defer p.deinit();
+ p.row_metrics = .{ .body_w = 10, .body_h = 20, .tagline_w = 8, .tagline_h = 10 };
+ const pane = try TreeContextTests.setZigFile(p, "const Box = struct {\n pub fn work(\n value: usize,\n ) void {\n" ++ " // body\n" ** 60 ++ " }\n};\n");
+ try std.testing.expect(p.executeBuiltinLine(0, "TreeContext"));
+ pane.scrollBy(10);
+ var frame = std.heap.ArenaAllocator.init(p.gpa);
+ defer frame.deinit();
+ _ = try p.render(frame.allocator());
+ const layer = &p.surface.body_layers[0];
+ try std.testing.expect(layer.context_rows >= 4);
+ try std.testing.expect(layer.rows > pane.rows);
+ const first = mouse(layer, 0, 2, .press);
+ const second = mouse(layer, 1, 2, .press);
+ try std.testing.expectEqual(first.row, second.row);
+ const top = pane.scroll();
+ for ([_]u16{ 0, 1 }) |row| {
+ const expected = pane.wrapAt(row).line;
+ p.update(.{ .mouse = mouse(layer, row, 2, .press) });
+ p.update(.{ .mouse = mouse(layer, row, 2, .release) });
+ try std.testing.expectEqual(expected, pane.cur_row);
+ try std.testing.expectEqual(top, pane.scroll());
+ }
+ const last = pane.body_visible_rows - 1;
+ try std.testing.expect(last >= pane.rows);
+ const expected = pane.wrapAt(last).line;
+ const prefix = panes.File.gutterWidth(pane);
+ p.update(.{ .mouse = mouse(layer, last - 1, prefix + 11, .press) });
+ // Release at a different source row without an intermediate drag event.
+ p.update(.{ .mouse = mouse(layer, last, prefix + 14, .release) });
+ try std.testing.expectEqualStrings("body\nbody", pardes.test_api.heldSelection(p, 0).?);
+ p.update(.{ .mouse = mouse(layer, last, 10, .press) });
+ p.update(.{ .mouse = mouse(layer, last, 10, .release) });
+ try std.testing.expectEqual(expected, pane.cur_row);
+ var stale = mouse(layer, 0, 2, .press);
+ stale.body_hit.?.serial +%= 1;
+ p.update(.{ .mouse = stale });
+ try std.testing.expectEqual(expected, pane.cur_row);
+ p.update(.{ .key = .{ .cp = 'i' } });
+ p.update(.{ .key = .{ .cp = 'X', .text = "X" } });
+ try std.testing.expect(std.mem.indexOfScalar(u8, modal.lineSlice(pane.file.?.content, @intCast(expected)), 'X') != null);
+ }
+};
+
const TreeContextTests = struct {
const source = "const Box = struct {\n" ++
" pub fn work(\n" ++
@@ -3556,6 +3610,7 @@ test {
_ = TagNavigationTests;
_ = TagNameTintTests;
_ = TreeContextTests;
+ _ = BodyHitTests;
_ = TtySelectionTests;
_ = ClickCursorTests;
_ = JumpSelectionTests;
diff --git a/test/web-snapshots/touch.mjs b/test/web-snapshots/touch.mjs
index 8c34b185..4dde2fa4 100644
--- a/test/web-snapshots/touch.mjs
+++ b/test/web-snapshots/touch.mjs
@@ -42,6 +42,42 @@ function styled(frame) {
export default async function ({ grid, touch, wait, stable, delay, evaluate, mouse }) {
await stable(100, 5000);
+ const compactGeometry = await evaluate(`(() => {
+ const root = document.createElement("div");
+ root.className = "pardes";
+ root.style.cssText = "position:fixed;left:0;top:0;width:20px;height:40px";
+ document.body.append(root);
+ const memory = new WebAssembly.Memory({initial:1});
+ const bytes = new Uint8Array(memory.buffer), data = new DataView(memory.buffer);
+ for (const [base,count] of [[0,4],[1024,6]]) for(let i=0;i<count;i++) {
+ const off=base+i*20; bytes[off]=65+i; bytes[off+18]=1;
+ data.setUint32(off+8,0xffffff,true); data.setUint32(off+12,0x123456,true);
+ if(base && i<2) data.setUint16(off+16,128,true);
+ }
+ const values=[3,2,1,0,0,2,2,42,0,2,1];
+ const wasm={memory,pardes_gui_tagline_font_percent:()=>50,pardes_frame:()=>4,
+ pardes_pointer_shape:()=>0,pardes_frame_cols:()=>2,pardes_frame_rows:()=>2,
+ pardes_frame_ptr:()=>0,pardes_cursor_x:()=>65535,pardes_cursor_y:()=>65535,pardes_cursor_bar:()=>0,
+ pardes_body_layer_limit:()=>1,pardes_body_layer_value:(_,field)=>values[field],pardes_body_layer_cells:()=>1024};
+ const renderer=new pardes.runtime.renderer.constructor(root,wasm);
+ Object.assign(renderer,{cellWidth:10,cellHeight:20,taglineWidth:5,taglineHeight:10});
+ renderer.render();
+ const layer=renderer.layerRoot.firstChild, rect=layer.getBoundingClientRect();
+ const bands=[...layer.children].slice(0,3).map(node=>{
+ const box=node.getBoundingClientRect();return [box.y-rect.y,box.height];
+ });
+ const cursor=layer.querySelector('.is-cursor');
+ renderer.render();
+ const result={bands,height:rect.height,clipped:getComputedStyle(layer).overflow,
+ cursor:cursor?.textContent,cached:renderer.layerRoot.firstChild===layer};
+ root.remove();return result;
+ })()`);
+ assert.deepEqual(compactGeometry.bands, [[0,10],[10,20],[30,20]], "compact headers release real height to additional body rows");
+ assert.equal(compactGeometry.height,40);
+ assert.equal(compactGeometry.clipped,"hidden");
+ assert.equal(compactGeometry.cursor,"E");
+ assert(compactGeometry.cached,"unchanged compact layers reuse their DOM nodes");
+
let frame = await grid();
assert.equal(tags(frame).length, 1);
styled(frame);
@@ -118,6 +154,9 @@ export default async function ({ grid, touch, wait, stable, delay, evaluate, mou
runtime.wasm = { ...wasm, pardes_mouse: (...args) => {
events.push(args.slice(0, 2));
wasm.pardes_mouse(...args);
+ }, pardes_mouse_pixel: (...args) => {
+ events.push(args.slice(0, 2));
+ wasm.pardes_mouse_pixel(...args);
} };
const observe = (event) => {
if (event.type === "pointerdown") pointerDownCanceled.push(event.defaultPrevented);