diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/panes.zig | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/test/panes.zig b/test/panes.zig index ded5b075..0577154f 100644 --- a/test/panes.zig +++ b/test/panes.zig @@ -12,6 +12,154 @@ const image = pardes.image; const syntax = pardes.syntax; const filesystem = pardes.filesystem; +const TtySelectionTests = struct { + fn noChildInput(p: *Pardes) !void { + while (p.nextEffect()) |effect| { + if (effect == .write) return error.UnexpectedChildInput; + if (effect == .set_clipboard) p.perform(effect); + } + } + + test "tty selection yields to a new modal cursor selection" { + if (comptime !panes.Terminal.enabled) return error.SkipZigTest; + const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 40, .rows = 12 }); + defer p.deinit(); + p.presentation.enabled = false; + const pane = p.panes[0].?; + pane.tty_filter = false; + while (p.nextEffect()) |_| {} + p.update(.{ .output = .{ .pane = 0, .bytes = "alpha" } }); + var frame = std.heap.ArenaAllocator.init(p.gpa); + defer frame.deinit(); + _ = try p.render(frame.allocator()); + const rect = p.rects[0]; + const x = rect.x + config.GUTTER; + const y = if (p.settings.tag_bottom) rect.y else rect.y + pardes.BOX_H; + JumpSelectionTests.drag(p, x + 1, y, x + 3, y); + try std.testing.expectEqualStrings("lph", p.yank orelse return error.MissingAutomaticTtyYank); + p.update(.{ .key = .{ .cp = p.opts.tty_toggle, .ctrl = true } }); + p.update(.{ .key = .{ .cp = 'l' } }); + try std.testing.expectEqual(@as(i32, 4), pane.cur_col); + p.update(.{ .key = .{ .cp = 'y' } }); + try std.testing.expectEqualStrings("a", p.yank.?); + try noChildInput(p); + } + + test "tty selection preserves exact rectangle through yank clipboard and mode changes" { + if (comptime !panes.Terminal.enabled) return error.SkipZigTest; + for ([_]bool{ false, true }) |prompt| { + const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 40, .rows = 12 }); + defer p.deinit(); + const pane = p.panes[0].?; + pane.mode = .tty; + pane.tty_filter = false; + p.presentation.enabled = false; + while (p.nextEffect()) |_| {} + p.update(.{ .output = .{ .pane = 0, .bytes = if (prompt) + "\x1b]133;A\x07$ \x1b]133;B\x07abc" + else + "alpha\r\nbravo" } }); + var frame = std.heap.ArenaAllocator.init(p.gpa); + defer frame.deinit(); + _ = try p.render(frame.allocator()); + const rect = p.rects[0]; + const x = rect.x + config.GUTTER; + const y = if (p.settings.tag_bottom) rect.y else rect.y + pardes.BOX_H; + JumpSelectionTests.drag(p, x + @as(u16, if (prompt) 0 else 1), y, x + 3, y + @as(u16, if (prompt) 0 else 1)); + const expected = if (prompt) "$ ab" else "lph\nrav"; + try std.testing.expectEqual(Pane.Mode.tty, pane.mode); + try std.testing.expectEqualStrings(expected, pardes.test_api.heldSelection(p, 0).?); + try std.testing.expectEqualStrings(expected, p.yank orelse return error.MissingAutomaticTtyYank); + try noChildInput(p); + + try std.testing.expect(p.executeBuiltinLine(0, "ClipYank")); + try noChildInput(p); + try std.testing.expectEqualStrings(expected, p.fallback.clipboard.items); + p.update(.{ .key = .{ .cp = p.opts.tty_toggle, .ctrl = true } }); + try std.testing.expectEqual(Pane.Mode.normal, pane.mode); + const normal = try p.render(frame.allocator()); + if (!prompt) { + const selection_bg: pardes.Color = .{ .rgb = p.theme().sel_bg }; + try std.testing.expect(!std.meta.eql(selection_bg, normal.at(x + 4, y).style.bg)); + try std.testing.expect(!std.meta.eql(selection_bg, normal.at(x, y + 1).style.bg)); + } + try std.testing.expectEqualStrings(expected, pardes.test_api.heldSelection(p, 0).?); + p.update(.{ .key = .{ .cp = 'y' } }); + try std.testing.expectEqualStrings(expected, p.yank.?); + try noChildInput(p); + p.update(.{ .key = .{ .cp = p.opts.tty_toggle, .ctrl = true } }); + try std.testing.expectEqual(Pane.Mode.tty, pane.mode); + try noChildInput(p); + _ = try p.render(frame.allocator()); + try std.testing.expectEqualStrings(expected, pardes.test_api.heldSelection(p, 0).?); + p.update(.{ .output = .{ .pane = 0, .bytes = "\x1b]133;C\x07" ++ "\r\nnew output" ** 30 } }); + _ = try p.render(frame.allocator()); + try std.testing.expectEqual(Pane.Mode.tty, pane.mode); + try std.testing.expectEqualStrings(expected, pardes.test_api.heldSelection(p, 0).?); + try std.testing.expectEqualStrings(expected, p.yank.?); + try noChildInput(p); + } + } + + test "tty selection pastes across panes once with existing bracket and mouse protocols" { + if (comptime !panes.Terminal.enabled) return error.SkipZigTest; + for ([_]bool{ false, true }) |bracketed| { + for ([_]bool{ false, true }) |reports_mouse| { + const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 40, .rows = 24 }); + defer p.deinit(); + p.presentation.enabled = false; + p.spawnTty(0); + for (p.panes[0..2]) |slot| { + slot.?.mode = .tty; + slot.?.tty_filter = false; + slot.?.greet = false; + slot.?.vweight = 1; + } + p.update(.tick); + while (p.nextEffect()) |_| {} + p.update(.{ .output = .{ .pane = 0, .bytes = "alpha\r\nbravo" } }); + p.update(.{ .output = .{ .pane = 1, .bytes = "target> " } }); + if (bracketed) p.update(.{ .output = .{ .pane = 1, .bytes = "\x1b[?2004h" } }); + if (reports_mouse) p.update(.{ .output = .{ .pane = 1, .bytes = "\x1b[?1000h\x1b[?1006h" } }); + var frame = std.heap.ArenaAllocator.init(p.gpa); + defer frame.deinit(); + _ = try p.render(frame.allocator()); + const source = p.rects[0]; + const sx = source.x + config.GUTTER; + const sy = if (p.settings.tag_bottom) source.y else source.y + pardes.BOX_H; + JumpSelectionTests.drag(p, sx + 1, sy, sx + 3, sy + 1); + try std.testing.expectEqualStrings("lph\nrav", p.yank orelse return error.MissingAutomaticTtyYank); + try noChildInput(p); + + const target = p.rects[1]; + const tx = target.x + config.GUTTER + 2; + const ty = if (p.settings.tag_bottom) target.y else target.y + pardes.BOX_H; + p.update(.{ .mouse = .{ .button = .left, .kind = .press, .col = tx, .row = ty } }); + p.update(.{ .mouse = .{ .button = .right, .kind = .press, .col = tx, .row = ty } }); + p.update(.{ .mouse = .{ .button = .right, .kind = .release, .col = tx, .row = ty } }); + p.update(.{ .mouse = .{ .button = .left, .kind = .release, .col = tx, .row = ty } }); + var written: std.Io.Writer.Allocating = .init(p.gpa); + defer written.deinit(); + while (p.nextEffect()) |effect| { + if (effect == .write) { + try std.testing.expectEqual(@as(u8, 1), effect.write.pane); + try written.writer.writeAll(effect.write.bytes.slice()); + } + } + const expected = try std.fmt.allocPrint(p.gpa, "{s}{s}", .{ + if (reports_mouse) "\x1b[<0;3;1M\x1b[<0;3;1m" else "", + if (bracketed) "\x1b[200~lph\nrav\x1b[201~" else "lph\rrav", + }); + defer p.gpa.free(expected); + try std.testing.expectEqualStrings(expected, written.written()); + try std.testing.expectEqual(Pane.Mode.tty, p.panes[0].?.mode); + try std.testing.expectEqual(Pane.Mode.tty, p.panes[1].?.mode); + try std.testing.expectEqualStrings("lph\nrav", pardes.test_api.heldSelection(p, 0).?); + } + } + } +}; + const ClickCursorTests = struct { fn click(p: *Pardes, button: pardes.Mouse.Button, x: u16, y: u16) void { p.update(.{ .mouse = .{ .button = button, .kind = .press, .col = x, .row = y } }); @@ -2824,6 +2972,7 @@ const TerminalTests = struct { }; test { + _ = TtySelectionTests; _ = ClickCursorTests; _ = JumpSelectionTests; _ = @import("output.zig"); |
