summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-15 15:33:30 -0300
committerGabriel Schneider <[email protected]>2026-09-15 17:24:42 -0300
commit8ac4a48a2e8e66a9e72bcbc61c114be8db9215fd (patch)
tree4c48ecd42a800b12daed0712a4620639d1631f7e /test
parentc1787ff868ee723629c1d500098d36dc419f77c3 (diff)
downloadpardes-8ac4a48a2e8e66a9e72bcbc61c114be8db9215fd.tar.gz
pardes-8ac4a48a2e8e66a9e72bcbc61c114be8db9215fd.zip
Separate discontinuous pinned source context with thin borders
Diffstat (limited to 'test')
-rw-r--r--test/panes.zig30
-rw-r--r--test/web-snapshots/touch.mjs16
2 files changed, 44 insertions, 2 deletions
diff --git a/test/panes.zig b/test/panes.zig
index 8c140001..bf8a98a2 100644
--- a/test/panes.zig
+++ b/test/panes.zig
@@ -267,6 +267,36 @@ const TreeContextTests = struct {
return pane;
}
+ test "TreeContext separators mark source gaps without splitting multiline signatures" {
+ if (!syntax.enabled) return error.SkipZigTest;
+ const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 64, .rows = 18 });
+ defer p.deinit();
+ const pane = try setZigFile(p, "const Box = struct {\n\n // omitted member comment\n\n pub fn work(\n value: usize,\n ) void {\n" ++ " // body\n" ** 30 ++ " }\n};\n");
+ p.row_metrics = .{ .body_w = 10, .body_h = 20, .tagline_w = 8, .tagline_h = 10 };
+ 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.expectEqual(@as(u16, 4), layer.context_rows);
+ for ([_]i32{ 0, 4, 5, 6 }, 0..) |source_row, index| {
+ const row: u16 = @intCast(index);
+ try std.testing.expectEqual(source_row, pane.wrapAt(row).line);
+ try std.testing.expectEqual(index == 0 or index == 3, layer.hasContextBorderAfter(row));
+ const y = layer.rowTop(row, 20, 10) + 9.5;
+ const x = @as(f32, @floatFromInt(layer.viewport.x)) * 10 + 5;
+ // A one-pixel separator remains inside its existing header row.
+ try std.testing.expectEqual(row, layer.hitAt(x, y, 10, 20, 8, 10).?.row);
+ }
+ pane.scrollBy(-5);
+ _ = try p.render(frame.allocator());
+ try std.testing.expectEqual(@as(u16, 2), layer.context_rows);
+ try std.testing.expect(layer.hasContextBorderAfter(0));
+ try std.testing.expect(layer.hasContextBorderAfter(1));
+ for (2..layer.rows) |row| try std.testing.expect(!layer.hasContextBorderAfter(@intCast(row)));
+ }
+
test "TreeContext Look to an open file discards the old viewport extent" {
for ([_]bool{ false, true }) |context| {
if (context and !syntax.enabled) continue;
diff --git a/test/web-snapshots/touch.mjs b/test/web-snapshots/touch.mjs
index 4dde2fa4..ecd8a9a3 100644
--- a/test/web-snapshots/touch.mjs
+++ b/test/web-snapshots/touch.mjs
@@ -49,12 +49,12 @@ export default async function ({ grid, touch, wait, stable, delay, evaluate, mou
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++) {
+ for (const [base,count] of [[0,4],[1024,10]]) 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 values=[3,2,1,0,0,2,2,42,0,2,1,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,
@@ -70,6 +70,15 @@ export default async function ({ grid, touch, wait, stable, delay, evaluate, mou
renderer.render();
const result={bands,height:rect.height,clipped:getComputedStyle(layer).overflow,
cursor:cursor?.textContent,cached:renderer.layerRoot.firstChild===layer};
+ values[0]=5;values[2]=3;values[6]=4;values[11]=0;values[12]=1;values[13]=1;
+ renderer.render();
+ const borders=()=>[...renderer.layerRoot.querySelectorAll('[data-context-border]')].map(node=>parseFloat(node.style.top));
+ result.gapBorders=borders();
+ const withGap=renderer.layerRoot.firstChild;
+ values[12]=0;
+ renderer.render();
+ result.closedGapBorders=borders();
+ result.borderChangeInvalidates=renderer.layerRoot.firstChild!==withGap;
root.remove();return result;
})()`);
assert.deepEqual(compactGeometry.bands, [[0,10],[10,20],[30,20]], "compact headers release real height to additional body rows");
@@ -77,6 +86,9 @@ export default async function ({ grid, touch, wait, stable, delay, evaluate, mou
assert.equal(compactGeometry.clipped,"hidden");
assert.equal(compactGeometry.cursor,"E");
assert(compactGeometry.cached,"unchanged compact layers reuse their DOM nodes");
+ assert.deepEqual(compactGeometry.gapBorders,[20,30],"source gaps and final header have separators, consecutive headers do not");
+ assert.deepEqual(compactGeometry.closedGapBorders,[30]);
+ assert(compactGeometry.borderChangeInvalidates,"separator changes invalidate an otherwise unchanged layer");
let frame = await grid();
assert.equal(tags(frame).length, 1);