linecraft 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +313 -64
- package/lib/api/color.d.ts +6 -0
- package/lib/api/color.d.ts.map +1 -0
- package/lib/api/color.js +9 -0
- package/lib/api/color.js.map +1 -0
- package/lib/api/color.test.d.ts +2 -0
- package/lib/api/color.test.d.ts.map +1 -0
- package/lib/api/color.test.js +23 -0
- package/lib/api/color.test.js.map +1 -0
- package/lib/api/flex.d.ts +55 -0
- package/lib/api/flex.d.ts.map +1 -0
- package/lib/api/flex.js +86 -0
- package/lib/api/flex.js.map +1 -0
- package/lib/api/flex.test.d.ts +2 -0
- package/lib/api/flex.test.d.ts.map +1 -0
- package/lib/api/flex.test.js +82 -0
- package/lib/api/flex.test.js.map +1 -0
- package/lib/api/grid.d.ts +22 -0
- package/lib/api/grid.d.ts.map +1 -0
- package/lib/api/grid.js +65 -0
- package/lib/api/grid.js.map +1 -0
- package/lib/api/grid.test.d.ts +2 -0
- package/lib/api/grid.test.d.ts.map +1 -0
- package/lib/api/grid.test.js +48 -0
- package/lib/api/grid.test.js.map +1 -0
- package/lib/components/base.d.ts +53 -0
- package/lib/components/base.d.ts.map +1 -0
- package/lib/components/base.js +47 -0
- package/lib/components/base.js.map +1 -0
- package/lib/components/col.d.ts +35 -0
- package/lib/components/col.d.ts.map +1 -0
- package/lib/components/col.js +168 -0
- package/lib/components/col.js.map +1 -0
- package/lib/components/col.test.d.ts +2 -0
- package/lib/components/col.test.d.ts.map +1 -0
- package/lib/components/col.test.js +96 -0
- package/lib/components/col.test.js.map +1 -0
- package/lib/components/index.d.ts +3 -0
- package/lib/components/index.d.ts.map +1 -0
- package/lib/components/index.js +5 -0
- package/lib/components/index.js.map +1 -0
- package/lib/components/progress-bar-grid.d.ts +20 -0
- package/lib/components/progress-bar-grid.d.ts.map +1 -0
- package/lib/components/progress-bar-grid.js +44 -0
- package/lib/components/progress-bar-grid.js.map +1 -0
- package/lib/components/progress-bar-grid.test.d.ts +2 -0
- package/lib/components/progress-bar-grid.test.d.ts.map +1 -0
- package/lib/components/progress-bar-grid.test.js +101 -0
- package/lib/components/progress-bar-grid.test.js.map +1 -0
- package/lib/components/progress-bar.d.ts +26 -3
- package/lib/components/progress-bar.d.ts.map +1 -1
- package/lib/components/progress-bar.js +62 -6
- package/lib/components/progress-bar.js.map +1 -1
- package/lib/components/progress-bar.test.d.ts +2 -0
- package/lib/components/progress-bar.test.d.ts.map +1 -0
- package/lib/components/progress-bar.test.js +153 -0
- package/lib/components/progress-bar.test.js.map +1 -0
- package/lib/components/prompt.d.ts +14 -0
- package/lib/components/prompt.d.ts.map +1 -0
- package/lib/components/prompt.js +77 -0
- package/lib/components/prompt.js.map +1 -0
- package/lib/components/renderable.d.ts +42 -0
- package/lib/components/renderable.d.ts.map +1 -0
- package/lib/components/renderable.js +225 -0
- package/lib/components/renderable.js.map +1 -0
- package/lib/components/spinner.d.ts +2 -2
- package/lib/components/spinner.d.ts.map +1 -1
- package/lib/components/spinner.js +3 -1
- package/lib/components/spinner.js.map +1 -1
- package/lib/components/spinner.test.d.ts +2 -0
- package/lib/components/spinner.test.d.ts.map +1 -0
- package/lib/components/spinner.test.js +168 -0
- package/lib/components/spinner.test.js.map +1 -0
- package/lib/components/style.d.ts +16 -0
- package/lib/components/style.d.ts.map +1 -0
- package/lib/components/style.js +72 -0
- package/lib/components/style.js.map +1 -0
- package/lib/components/style.test.d.ts +2 -0
- package/lib/components/style.test.d.ts.map +1 -0
- package/lib/components/style.test.js +135 -0
- package/lib/components/style.test.js.map +1 -0
- package/lib/components/text.d.ts +24 -0
- package/lib/components/text.d.ts.map +1 -0
- package/lib/components/text.js +65 -0
- package/lib/components/text.js.map +1 -0
- package/lib/drawing/boxes.d.ts +33 -0
- package/lib/drawing/boxes.d.ts.map +1 -0
- package/lib/drawing/boxes.js +76 -0
- package/lib/drawing/boxes.js.map +1 -0
- package/lib/index.d.ts +18 -11
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +21 -10
- package/lib/index.js.map +1 -1
- package/lib/index.test.d.ts +2 -0
- package/lib/index.test.d.ts.map +1 -0
- package/lib/index.test.js +80 -0
- package/lib/index.test.js.map +1 -0
- package/lib/layout/flex.d.ts +39 -0
- package/lib/layout/flex.d.ts.map +1 -0
- package/lib/layout/flex.js +300 -0
- package/lib/layout/flex.js.map +1 -0
- package/lib/layout/flex.test.d.ts +2 -0
- package/lib/layout/flex.test.d.ts.map +1 -0
- package/lib/layout/flex.test.js +206 -0
- package/lib/layout/flex.test.js.map +1 -0
- package/lib/layout/grid.d.ts +53 -0
- package/lib/layout/grid.d.ts.map +1 -0
- package/lib/layout/grid.js +421 -0
- package/lib/layout/grid.js.map +1 -0
- package/lib/layout/grid.test.d.ts +2 -0
- package/lib/layout/grid.test.d.ts.map +1 -0
- package/lib/layout/grid.test.js +139 -0
- package/lib/layout/grid.test.js.map +1 -0
- package/lib/native/ansi.d.ts +104 -0
- package/lib/native/ansi.d.ts.map +1 -0
- package/lib/native/ansi.js +120 -0
- package/lib/native/ansi.js.map +1 -0
- package/lib/native/ansi.test.d.ts +2 -0
- package/lib/native/ansi.test.d.ts.map +1 -0
- package/lib/native/ansi.test.js +57 -0
- package/lib/native/ansi.test.js.map +1 -0
- package/lib/native/buffer.d.ts +32 -0
- package/lib/native/buffer.d.ts.map +1 -0
- package/lib/native/buffer.js +49 -0
- package/lib/native/buffer.js.map +1 -0
- package/lib/native/buffer.test.d.ts +2 -0
- package/lib/native/buffer.test.d.ts.map +1 -0
- package/lib/native/buffer.test.js +64 -0
- package/lib/native/buffer.test.js.map +1 -0
- package/lib/native/diff.d.ts +20 -0
- package/lib/native/diff.d.ts.map +1 -0
- package/lib/native/diff.js +33 -0
- package/lib/native/diff.js.map +1 -0
- package/lib/native/diff.test.d.ts +2 -0
- package/lib/native/diff.test.d.ts.map +1 -0
- package/lib/native/diff.test.js +106 -0
- package/lib/native/diff.test.js.map +1 -0
- package/lib/native/region-old.d.ts +117 -0
- package/lib/native/region-old.d.ts.map +1 -0
- package/lib/native/region-old.js +539 -0
- package/lib/native/region-old.js.map +1 -0
- package/lib/native/region-renderer.d.ts +167 -0
- package/lib/native/region-renderer.d.ts.map +1 -0
- package/lib/native/region-renderer.js +1238 -0
- package/lib/native/region-renderer.js.map +1 -0
- package/lib/native/region-simple.d.ts +44 -0
- package/lib/native/region-simple.d.ts.map +1 -0
- package/lib/native/region-simple.js +290 -0
- package/lib/native/region-simple.js.map +1 -0
- package/lib/native/region.d.ts +53 -0
- package/lib/native/region.d.ts.map +1 -0
- package/lib/native/region.js +426 -0
- package/lib/native/region.js.map +1 -0
- package/lib/native/region.test.d.ts +2 -0
- package/lib/native/region.test.d.ts.map +1 -0
- package/lib/native/region.test.js +248 -0
- package/lib/native/region.test.js.map +1 -0
- package/lib/native/throttle.d.ts +29 -0
- package/lib/native/throttle.d.ts.map +1 -0
- package/lib/native/throttle.js +57 -0
- package/lib/native/throttle.js.map +1 -0
- package/lib/native/throttle.test.d.ts +2 -0
- package/lib/native/throttle.test.d.ts.map +1 -0
- package/lib/native/throttle.test.js +86 -0
- package/lib/native/throttle.test.js.map +1 -0
- package/lib/native.d.ts +5 -11
- package/lib/native.d.ts.map +1 -1
- package/lib/native.js +8 -64
- package/lib/native.js.map +1 -1
- package/lib/region.d.ts +48 -5
- package/lib/region.d.ts.map +1 -1
- package/lib/region.js +474 -36
- package/lib/region.js.map +1 -1
- package/lib/region.test.d.ts +2 -0
- package/lib/region.test.d.ts.map +1 -0
- package/lib/region.test.js +227 -0
- package/lib/region.test.js.map +1 -0
- package/lib/region.visual.test.d.ts +2 -0
- package/lib/region.visual.test.d.ts.map +1 -0
- package/lib/region.visual.test.js +55 -0
- package/lib/region.visual.test.js.map +1 -0
- package/lib/test-helpers/capturable-terminal.d.ts +61 -0
- package/lib/test-helpers/capturable-terminal.d.ts.map +1 -0
- package/lib/test-helpers/capturable-terminal.js +113 -0
- package/lib/test-helpers/capturable-terminal.js.map +1 -0
- package/lib/test-helpers/capturable-terminal.test.d.ts +2 -0
- package/lib/test-helpers/capturable-terminal.test.d.ts.map +1 -0
- package/lib/test-helpers/capturable-terminal.test.js +45 -0
- package/lib/test-helpers/capturable-terminal.test.js.map +1 -0
- package/lib/test-helpers/mock-region.d.ts +21 -0
- package/lib/test-helpers/mock-region.d.ts.map +1 -0
- package/lib/test-helpers/mock-region.js +37 -0
- package/lib/test-helpers/mock-region.js.map +1 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.d.ts +2 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.js +256 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.js.map +1 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.d.ts +2 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.js +438 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.js.map +1 -0
- package/lib/test-helpers/virtual-terminal.d.ts +176 -0
- package/lib/test-helpers/virtual-terminal.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal.js +492 -0
- package/lib/test-helpers/virtual-terminal.js.map +1 -0
- package/lib/test-helpers/virtual-terminal.test.d.ts +2 -0
- package/lib/test-helpers/virtual-terminal.test.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal.test.js +219 -0
- package/lib/test-helpers/virtual-terminal.test.js.map +1 -0
- package/lib/ts/components/spinner.test.d.ts +2 -0
- package/lib/ts/components/spinner.test.d.ts.map +1 -0
- package/lib/ts/components/spinner.test.js +168 -0
- package/lib/ts/components/spinner.test.js.map +1 -0
- package/lib/ts/utils/colors.test.d.ts +2 -0
- package/lib/ts/utils/colors.test.d.ts.map +1 -0
- package/lib/ts/utils/colors.test.js +87 -0
- package/lib/ts/utils/colors.test.js.map +1 -0
- package/lib/types.d.ts +8 -2
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js.map +1 -1
- package/lib/utils/colors-simple.d.ts +51 -0
- package/lib/utils/colors-simple.d.ts.map +1 -0
- package/lib/utils/colors-simple.js +59 -0
- package/lib/utils/colors-simple.js.map +1 -0
- package/lib/utils/colors.d.ts +1 -1
- package/lib/utils/colors.d.ts.map +1 -1
- package/lib/utils/colors.js.map +1 -1
- package/lib/utils/colors.test.d.ts +2 -0
- package/lib/utils/colors.test.d.ts.map +1 -0
- package/lib/utils/colors.test.js +87 -0
- package/lib/utils/colors.test.js.map +1 -0
- package/lib/utils/cursor-position.d.ts +22 -0
- package/lib/utils/cursor-position.d.ts.map +1 -0
- package/lib/utils/cursor-position.js +139 -0
- package/lib/utils/cursor-position.js.map +1 -0
- package/lib/utils/debug-log.d.ts +2 -0
- package/lib/utils/debug-log.d.ts.map +1 -0
- package/lib/utils/debug-log.js +36 -0
- package/lib/utils/debug-log.js.map +1 -0
- package/lib/utils/terminal.d.ts +27 -0
- package/lib/utils/terminal.d.ts.map +1 -0
- package/lib/utils/terminal.js +116 -0
- package/lib/utils/terminal.js.map +1 -0
- package/lib/utils/text.d.ts +21 -0
- package/lib/utils/text.d.ts.map +1 -0
- package/lib/utils/text.js +82 -0
- package/lib/utils/text.js.map +1 -0
- package/lib/utils/wait-for-spacebar.d.ts +10 -0
- package/lib/utils/wait-for-spacebar.d.ts.map +1 -0
- package/lib/utils/wait-for-spacebar.js +71 -0
- package/lib/utils/wait-for-spacebar.js.map +1 -0
- package/package.json +31 -28
- package/.cursor/plan.md +0 -952
- package/TESTING.md +0 -102
- package/build.zig +0 -100
- package/examples/basic-progress.ts +0 -21
- package/examples/multi-lane.ts +0 -29
- package/examples/spinner.ts +0 -20
- package/examples/test-basic.ts +0 -23
- package/src/ts/components/progress-bar.ts +0 -53
- package/src/ts/components/spinner.ts +0 -56
- package/src/ts/index.ts +0 -37
- package/src/ts/native.ts +0 -86
- package/src/ts/region.ts +0 -89
- package/src/ts/types/ffi-napi.d.ts +0 -11
- package/src/ts/types/ref-napi.d.ts +0 -5
- package/src/ts/types.ts +0 -53
- package/src/ts/utils/colors.ts +0 -72
- package/src/zig/ansi.zig +0 -21
- package/src/zig/buffer.zig +0 -37
- package/src/zig/diff.zig +0 -43
- package/src/zig/region.zig +0 -292
- package/src/zig/renderer.zig +0 -92
- package/src/zig/test_ansi.zig +0 -66
- package/src/zig/test_buffer.zig +0 -82
- package/src/zig/test_diff.zig +0 -220
- package/src/zig/test_integration.zig +0 -76
- package/src/zig/test_region.zig +0 -191
- package/src/zig/test_runner.zig +0 -27
- package/src/zig/test_throttle.zig +0 -59
- package/src/zig/throttle.zig +0 -38
- package/tsconfig.json +0 -21
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { TerminalRegion } from './region';
|
|
3
|
+
describe('TerminalRegion', () => {
|
|
4
|
+
let region;
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
region = new TerminalRegion({
|
|
7
|
+
width: 80,
|
|
8
|
+
height: 1,
|
|
9
|
+
disableRendering: true, // Prevent interference with test runner output
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
if (region) {
|
|
14
|
+
region.destroy();
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
describe('constructor', () => {
|
|
18
|
+
it('should create a region with default options', () => {
|
|
19
|
+
const defaultRegion = new TerminalRegion({
|
|
20
|
+
disableRendering: true,
|
|
21
|
+
});
|
|
22
|
+
expect(defaultRegion).toBeInstanceOf(TerminalRegion);
|
|
23
|
+
expect(defaultRegion.width).toBeGreaterThan(0);
|
|
24
|
+
expect(defaultRegion.height).toBe(1);
|
|
25
|
+
defaultRegion.destroy();
|
|
26
|
+
});
|
|
27
|
+
it('should create a region with custom options', () => {
|
|
28
|
+
const customRegion = new TerminalRegion({
|
|
29
|
+
width: 100,
|
|
30
|
+
height: 3,
|
|
31
|
+
disableRendering: true,
|
|
32
|
+
});
|
|
33
|
+
expect(customRegion.width).toBe(100);
|
|
34
|
+
expect(customRegion.height).toBe(3);
|
|
35
|
+
customRegion.destroy();
|
|
36
|
+
});
|
|
37
|
+
it('should use default values for missing options', () => {
|
|
38
|
+
const partialRegion = new TerminalRegion({
|
|
39
|
+
width: 50,
|
|
40
|
+
disableRendering: true,
|
|
41
|
+
});
|
|
42
|
+
expect(partialRegion.width).toBe(50);
|
|
43
|
+
expect(partialRegion.height).toBe(1);
|
|
44
|
+
partialRegion.destroy();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('width and height getters', () => {
|
|
48
|
+
it('should return the correct width', () => {
|
|
49
|
+
const customRegion = new TerminalRegion({
|
|
50
|
+
width: 120,
|
|
51
|
+
disableRendering: true,
|
|
52
|
+
});
|
|
53
|
+
expect(customRegion.width).toBe(120);
|
|
54
|
+
customRegion.destroy();
|
|
55
|
+
});
|
|
56
|
+
it('should return the correct height', () => {
|
|
57
|
+
const customRegion = new TerminalRegion({
|
|
58
|
+
height: 5,
|
|
59
|
+
disableRendering: true,
|
|
60
|
+
});
|
|
61
|
+
expect(customRegion.height).toBe(5);
|
|
62
|
+
customRegion.destroy();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('setLine', () => {
|
|
66
|
+
it('should set a line with string content', () => {
|
|
67
|
+
region.setLine(1, 'Hello, World!');
|
|
68
|
+
region.flush();
|
|
69
|
+
// With disableRendering, should not write to stdout
|
|
70
|
+
expect(region).toBeDefined();
|
|
71
|
+
});
|
|
72
|
+
it('should set a line with LineContent object', () => {
|
|
73
|
+
region.setLine(2, {
|
|
74
|
+
text: 'Styled text',
|
|
75
|
+
style: { bold: true, color: 'red' },
|
|
76
|
+
});
|
|
77
|
+
region.flush();
|
|
78
|
+
// With disableRendering, should not write to stdout
|
|
79
|
+
expect(region).toBeDefined();
|
|
80
|
+
});
|
|
81
|
+
it('should expand height when setting a line beyond current height', () => {
|
|
82
|
+
expect(region.height).toBe(1);
|
|
83
|
+
region.setLine(3, 'Line 3');
|
|
84
|
+
expect(region.height).toBe(3);
|
|
85
|
+
});
|
|
86
|
+
it('should throw error for line number less than 1', () => {
|
|
87
|
+
expect(() => region.setLine(0, 'Invalid')).toThrow('Line numbers start at 1');
|
|
88
|
+
expect(() => region.setLine(-1, 'Invalid')).toThrow('Line numbers start at 1');
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe('set', () => {
|
|
92
|
+
it('should set content from a string', () => {
|
|
93
|
+
const content = 'Line 1\nLine 2\nLine 3';
|
|
94
|
+
region.set(content);
|
|
95
|
+
expect(region.height).toBe(3);
|
|
96
|
+
});
|
|
97
|
+
it('should set content from an array of LineContent', () => {
|
|
98
|
+
const content = [
|
|
99
|
+
{ text: 'First', style: { bold: true } },
|
|
100
|
+
{ text: 'Second', style: { color: 'blue' } },
|
|
101
|
+
{ text: 'Third' },
|
|
102
|
+
];
|
|
103
|
+
region.set(content);
|
|
104
|
+
expect(region.height).toBe(3);
|
|
105
|
+
});
|
|
106
|
+
it('should handle empty string', () => {
|
|
107
|
+
region.set('');
|
|
108
|
+
expect(region.height).toBeGreaterThanOrEqual(1);
|
|
109
|
+
});
|
|
110
|
+
it('should handle single line without newline', () => {
|
|
111
|
+
region.set('Single line');
|
|
112
|
+
expect(region.height).toBe(1);
|
|
113
|
+
});
|
|
114
|
+
it('should do a full replace when called with same height', () => {
|
|
115
|
+
// Set initial content
|
|
116
|
+
region.set('Line 1\nLine 2\nLine 3');
|
|
117
|
+
expect(region.height).toBe(3);
|
|
118
|
+
// Set new content with same height - should overwrite, not add
|
|
119
|
+
region.set('New 1\nNew 2\nNew 3');
|
|
120
|
+
expect(region.height).toBe(3); // Should still be 3, not 6
|
|
121
|
+
// Verify content was replaced
|
|
122
|
+
region.flush();
|
|
123
|
+
expect(region.getLine(1)).toContain('New 1');
|
|
124
|
+
expect(region.getLine(2)).toContain('New 2');
|
|
125
|
+
expect(region.getLine(3)).toContain('New 3');
|
|
126
|
+
});
|
|
127
|
+
it('should do a full replace when height decreases', () => {
|
|
128
|
+
// Set initial content with 3 lines
|
|
129
|
+
region.set('Line 1\nLine 2\nLine 3');
|
|
130
|
+
expect(region.height).toBe(3);
|
|
131
|
+
// Set new content with 2 lines - should replace and shrink
|
|
132
|
+
region.set('New 1\nNew 2');
|
|
133
|
+
expect(region.height).toBe(2); // Should shrink to 2
|
|
134
|
+
// Verify content was replaced
|
|
135
|
+
region.flush();
|
|
136
|
+
expect(region.getLine(1)).toContain('New 1');
|
|
137
|
+
expect(region.getLine(2)).toContain('New 2');
|
|
138
|
+
});
|
|
139
|
+
it('should do a full replace when height increases', () => {
|
|
140
|
+
// Set initial content with 2 lines
|
|
141
|
+
region.set('Line 1\nLine 2');
|
|
142
|
+
expect(region.height).toBe(2);
|
|
143
|
+
// Set new content with 4 lines - should replace and expand
|
|
144
|
+
region.set('New 1\nNew 2\nNew 3\nNew 4');
|
|
145
|
+
expect(region.height).toBe(4); // Should expand to 4
|
|
146
|
+
// Verify content was replaced
|
|
147
|
+
region.flush();
|
|
148
|
+
expect(region.getLine(1)).toContain('New 1');
|
|
149
|
+
expect(region.getLine(2)).toContain('New 2');
|
|
150
|
+
expect(region.getLine(3)).toContain('New 3');
|
|
151
|
+
expect(region.getLine(4)).toContain('New 4');
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
describe('clearLine', () => {
|
|
155
|
+
it('should clear a specific line', () => {
|
|
156
|
+
region.setLine(2, 'test');
|
|
157
|
+
region.clearLine(2);
|
|
158
|
+
// Should not throw
|
|
159
|
+
expect(region).toBeDefined();
|
|
160
|
+
});
|
|
161
|
+
it('should throw error for line number less than 1', () => {
|
|
162
|
+
expect(() => region.clearLine(0)).toThrow('Line numbers start at 1');
|
|
163
|
+
expect(() => region.clearLine(-1)).toThrow('Line numbers start at 1');
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
describe('clear', () => {
|
|
167
|
+
it('should clear the entire region', () => {
|
|
168
|
+
region.setLine(1, 'line1');
|
|
169
|
+
region.setLine(2, 'line2');
|
|
170
|
+
region.clear();
|
|
171
|
+
// Should not throw
|
|
172
|
+
expect(region).toBeDefined();
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
describe('flush', () => {
|
|
176
|
+
it('should flush pending updates', () => {
|
|
177
|
+
region.setLine(1, 'test');
|
|
178
|
+
region.flush();
|
|
179
|
+
// With disableRendering, should not write to stdout
|
|
180
|
+
expect(region).toBeDefined();
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
describe('setThrottle', () => {
|
|
184
|
+
it('should set throttle FPS', () => {
|
|
185
|
+
region.setThrottle(30);
|
|
186
|
+
// Should not throw
|
|
187
|
+
expect(region).toBeDefined();
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
describe('add', () => {
|
|
191
|
+
it('should append content after existing content', () => {
|
|
192
|
+
// Set initial content
|
|
193
|
+
region.set('Line 1\nLine 2');
|
|
194
|
+
expect(region.height).toBe(2);
|
|
195
|
+
// Add new content - should append
|
|
196
|
+
region.add('Line 3\nLine 4');
|
|
197
|
+
expect(region.height).toBe(4); // Should expand to 4
|
|
198
|
+
// Verify both old and new content exist
|
|
199
|
+
region.flush();
|
|
200
|
+
expect(region.getLine(1)).toContain('Line 1');
|
|
201
|
+
expect(region.getLine(2)).toContain('Line 2');
|
|
202
|
+
expect(region.getLine(3)).toContain('Line 3');
|
|
203
|
+
expect(region.getLine(4)).toContain('Line 4');
|
|
204
|
+
});
|
|
205
|
+
it('should append multiple times', () => {
|
|
206
|
+
region.set('First');
|
|
207
|
+
expect(region.height).toBe(1);
|
|
208
|
+
region.add('Second');
|
|
209
|
+
expect(region.height).toBe(2);
|
|
210
|
+
region.add('Third');
|
|
211
|
+
expect(region.height).toBe(3);
|
|
212
|
+
region.flush();
|
|
213
|
+
expect(region.getLine(1)).toContain('First');
|
|
214
|
+
expect(region.getLine(2)).toContain('Second');
|
|
215
|
+
expect(region.getLine(3)).toContain('Third');
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
describe('destroy', () => {
|
|
219
|
+
it('should destroy the region', () => {
|
|
220
|
+
region.setLine(1, 'test');
|
|
221
|
+
region.destroy();
|
|
222
|
+
// Should not throw
|
|
223
|
+
expect(region).toBeDefined();
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
//# sourceMappingURL=region.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"region.test.js","sourceRoot":"","sources":["../src/region.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"region.visual.test.d.ts","sourceRoot":"","sources":["../src/region.visual.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual tests for TerminalRegion
|
|
3
|
+
*
|
|
4
|
+
* These tests actually render to stdout so you can see the output.
|
|
5
|
+
* Run with: pnpm test region.visual
|
|
6
|
+
*
|
|
7
|
+
* Note: These tests may interfere with test runner output, so they're
|
|
8
|
+
* kept separate from the main test suite.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
11
|
+
import { TerminalRegion } from './region';
|
|
12
|
+
describe('TerminalRegion (Visual)', () => {
|
|
13
|
+
let region;
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
// Region will automatically reserve space at the bottom
|
|
16
|
+
region = new TerminalRegion({
|
|
17
|
+
width: 80,
|
|
18
|
+
height: 5,
|
|
19
|
+
disableRendering: false, // Actually render!
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
if (region) {
|
|
24
|
+
region.destroy();
|
|
25
|
+
}
|
|
26
|
+
// Small delay to see the output
|
|
27
|
+
return new Promise(resolve => setTimeout(resolve, 100));
|
|
28
|
+
});
|
|
29
|
+
it('should render text to the region', () => {
|
|
30
|
+
region.setLine(1, 'Visual Test: Line 1');
|
|
31
|
+
region.setLine(2, 'Visual Test: Line 2');
|
|
32
|
+
region.setLine(3, 'Visual Test: Line 3');
|
|
33
|
+
region.flush();
|
|
34
|
+
expect(region).toBeDefined();
|
|
35
|
+
});
|
|
36
|
+
it('should render styled text', () => {
|
|
37
|
+
region.setLine(1, {
|
|
38
|
+
text: 'Styled Text',
|
|
39
|
+
style: { bold: true, color: 'red' },
|
|
40
|
+
});
|
|
41
|
+
region.flush();
|
|
42
|
+
expect(region).toBeDefined();
|
|
43
|
+
});
|
|
44
|
+
it('should show progress bar animation', () => {
|
|
45
|
+
for (let i = 0; i <= 10; i++) {
|
|
46
|
+
const bar = '█'.repeat(i) + '░'.repeat(10 - i);
|
|
47
|
+
region.setLine(1, `Progress: [${bar}] ${i * 10}%`);
|
|
48
|
+
region.flush();
|
|
49
|
+
// Small delay to see animation
|
|
50
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 50);
|
|
51
|
+
}
|
|
52
|
+
expect(region).toBeDefined();
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=region.visual.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"region.visual.test.js","sourceRoot":"","sources":["../src/region.visual.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,IAAI,MAAsB,CAAC;IAE3B,UAAU,CAAC,GAAG,EAAE;QACd,wDAAwD;QACxD,MAAM,GAAG,IAAI,cAAc,CAAC;YAC1B,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,CAAC;YACT,gBAAgB,EAAE,KAAK,EAAE,mBAAmB;SAC7C,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;QACD,gCAAgC;QAChC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC;QACzC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC;QACzC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,EAAE,CAAC;QAEf,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE;YAChB,IAAI,EAAE,aAAa;YACnB,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;SACpC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,EAAE,CAAC;QAEf,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,cAAc,GAAG,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnD,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,+BAA+B;YAC/B,OAAO,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A terminal region that captures all writes and allows reading back the final state
|
|
3
|
+
* Implements the same interface as TerminalRegion for testing
|
|
4
|
+
*/
|
|
5
|
+
export declare class CapturableTerminal {
|
|
6
|
+
private lines;
|
|
7
|
+
private setLineCalls;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
constructor(width?: number, height?: number);
|
|
11
|
+
/**
|
|
12
|
+
* Get the final content of a line (what would actually be displayed)
|
|
13
|
+
*/
|
|
14
|
+
getLine(lineNumber: number): string;
|
|
15
|
+
/**
|
|
16
|
+
* Get all lines that were written to
|
|
17
|
+
*/
|
|
18
|
+
getAllLines(): Map<number, string>;
|
|
19
|
+
/**
|
|
20
|
+
* Get all setLine calls in order
|
|
21
|
+
*/
|
|
22
|
+
getSetLineCalls(): Array<{
|
|
23
|
+
line: number;
|
|
24
|
+
content: string;
|
|
25
|
+
}>;
|
|
26
|
+
/**
|
|
27
|
+
* Clear all captured content
|
|
28
|
+
*/
|
|
29
|
+
clear(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Get a snapshot of the terminal as a string (for debugging)
|
|
32
|
+
*/
|
|
33
|
+
snapshot(): string;
|
|
34
|
+
setLine(lineNumber: number, content: string | {
|
|
35
|
+
text: string;
|
|
36
|
+
style?: any;
|
|
37
|
+
}): void;
|
|
38
|
+
set(content: string | Array<{
|
|
39
|
+
text: string;
|
|
40
|
+
style?: any;
|
|
41
|
+
}> | any): void;
|
|
42
|
+
clearLine(lineNumber: number): void;
|
|
43
|
+
flush(): void;
|
|
44
|
+
setThrottle(fps: number): void;
|
|
45
|
+
destroy(clearFirst?: boolean): void;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* A smarter capturable terminal that properly merges content when multiple columns
|
|
49
|
+
* write to the same line (simulating what should happen)
|
|
50
|
+
*/
|
|
51
|
+
export declare class MergingCapturableTerminal extends CapturableTerminal {
|
|
52
|
+
/**
|
|
53
|
+
* Override setLine to merge content instead of overwriting
|
|
54
|
+
* This simulates the correct behavior we want
|
|
55
|
+
*/
|
|
56
|
+
setLine(lineNumber: number, content: string | {
|
|
57
|
+
text: string;
|
|
58
|
+
style?: any;
|
|
59
|
+
}): void;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=capturable-terminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capturable-terminal.d.ts","sourceRoot":"","sources":["../../src/ts/test-helpers/capturable-terminal.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,YAAY,CAAgD;IAEpE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;gBAEH,KAAK,GAAE,MAAW,EAAE,MAAM,GAAE,MAAW;IAKnD;;OAEG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAInC;;OAEG;IACH,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAIlC;;OAEG;IACH,eAAe,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAI3D;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,QAAQ,IAAI,MAAM;IAUlB,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,GAAG,CAAA;KAAE,GAAG,IAAI;IAalF,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC,GAAG,GAAG,GAAG,IAAI;IASvE,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAInC,KAAK,IAAI,IAAI;IACb,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAC9B,OAAO,CAAC,UAAU,GAAE,OAAe,GAAG,IAAI;CAC3C;AAED;;;GAGG;AACH,qBAAa,yBAA0B,SAAQ,kBAAkB;IAC/D;;;OAGG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,GAAG,CAAA;KAAE,GAAG,IAAI;CA2BnF"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Test helper: A "capturable" terminal that tracks what actually gets written
|
|
2
|
+
// This allows tests to verify the final state of lines, not just individual setLine calls
|
|
3
|
+
/**
|
|
4
|
+
* A terminal region that captures all writes and allows reading back the final state
|
|
5
|
+
* Implements the same interface as TerminalRegion for testing
|
|
6
|
+
*/
|
|
7
|
+
export class CapturableTerminal {
|
|
8
|
+
lines = new Map();
|
|
9
|
+
setLineCalls = [];
|
|
10
|
+
width;
|
|
11
|
+
height;
|
|
12
|
+
constructor(width = 80, height = 24) {
|
|
13
|
+
this.width = width;
|
|
14
|
+
this.height = height;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get the final content of a line (what would actually be displayed)
|
|
18
|
+
*/
|
|
19
|
+
getLine(lineNumber) {
|
|
20
|
+
return this.lines.get(lineNumber) || '';
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get all lines that were written to
|
|
24
|
+
*/
|
|
25
|
+
getAllLines() {
|
|
26
|
+
return new Map(this.lines);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get all setLine calls in order
|
|
30
|
+
*/
|
|
31
|
+
getSetLineCalls() {
|
|
32
|
+
return [...this.setLineCalls];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Clear all captured content
|
|
36
|
+
*/
|
|
37
|
+
clear() {
|
|
38
|
+
this.lines.clear();
|
|
39
|
+
this.setLineCalls = [];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get a snapshot of the terminal as a string (for debugging)
|
|
43
|
+
*/
|
|
44
|
+
snapshot() {
|
|
45
|
+
const maxLine = Math.max(...Array.from(this.lines.keys()), 0);
|
|
46
|
+
const result = [];
|
|
47
|
+
for (let i = 1; i <= maxLine; i++) {
|
|
48
|
+
result.push(this.getLine(i));
|
|
49
|
+
}
|
|
50
|
+
return result.join('\n');
|
|
51
|
+
}
|
|
52
|
+
// TerminalRegion interface implementation
|
|
53
|
+
setLine(lineNumber, content) {
|
|
54
|
+
const text = typeof content === 'string' ? content : content.text;
|
|
55
|
+
// Record the call
|
|
56
|
+
this.setLineCalls.push({ line: lineNumber, content: text });
|
|
57
|
+
// Update the line (this simulates what actually happens - later writes overwrite earlier ones)
|
|
58
|
+
// But we need to merge, not overwrite! So we need to track the actual final state
|
|
59
|
+
// For now, just store the last write (this is the bug we're trying to catch!)
|
|
60
|
+
this.lines.set(lineNumber, text);
|
|
61
|
+
}
|
|
62
|
+
// Stub implementations for other TerminalRegion methods
|
|
63
|
+
set(content) {
|
|
64
|
+
if (typeof content === 'string') {
|
|
65
|
+
const lines = content.split('\n');
|
|
66
|
+
lines.forEach((line, i) => {
|
|
67
|
+
this.setLine(i + 1, line);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
clearLine(lineNumber) {
|
|
72
|
+
this.lines.set(lineNumber, '');
|
|
73
|
+
}
|
|
74
|
+
flush() { }
|
|
75
|
+
setThrottle(fps) { }
|
|
76
|
+
destroy(clearFirst = false) { }
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* A smarter capturable terminal that properly merges content when multiple columns
|
|
80
|
+
* write to the same line (simulating what should happen)
|
|
81
|
+
*/
|
|
82
|
+
export class MergingCapturableTerminal extends CapturableTerminal {
|
|
83
|
+
/**
|
|
84
|
+
* Override setLine to merge content instead of overwriting
|
|
85
|
+
* This simulates the correct behavior we want
|
|
86
|
+
*/
|
|
87
|
+
setLine(lineNumber, content) {
|
|
88
|
+
const text = typeof content === 'string' ? content : content.text;
|
|
89
|
+
// Get existing line
|
|
90
|
+
const existing = this.getLine(lineNumber);
|
|
91
|
+
// For now, if existing is empty, just set it
|
|
92
|
+
// If not empty, we need to merge - but we don't know the x position
|
|
93
|
+
// So we'll just append (this is a limitation of the current API)
|
|
94
|
+
// In real usage, col.render() should handle merging via getLine()
|
|
95
|
+
if (existing) {
|
|
96
|
+
// If the new content is shorter or equal, it might be overwriting
|
|
97
|
+
// If longer, it might be appending - we can't tell without x position
|
|
98
|
+
// For testing, let's assume: if new content starts with spaces or is padded,
|
|
99
|
+
// it's probably a column that should merge. Otherwise, it's a full-line replacement.
|
|
100
|
+
const existingPlain = existing.replace(/\x1b\[[0-9;]*m/g, '');
|
|
101
|
+
const newPlain = text.replace(/\x1b\[[0-9;]*m/g, '');
|
|
102
|
+
// If new content is padded to a specific width and existing has content,
|
|
103
|
+
// this is likely a column write that should merge
|
|
104
|
+
// But we can't know the x position from setLine alone
|
|
105
|
+
// So we'll just overwrite for now (this simulates the bug)
|
|
106
|
+
super.setLine(lineNumber, text);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
super.setLine(lineNumber, text);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=capturable-terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capturable-terminal.js","sourceRoot":"","sources":["../../src/ts/test-helpers/capturable-terminal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capturable-terminal.test.d.ts","sourceRoot":"","sources":["../../src/ts/test-helpers/capturable-terminal.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Test the capturable terminal itself
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { VirtualTerminal } from './virtual-terminal.js';
|
|
4
|
+
import { Col } from '../components/col.js';
|
|
5
|
+
import { Flex } from '../layout/flex.js';
|
|
6
|
+
describe('VirtualTerminal', () => {
|
|
7
|
+
it('should capture setLine calls', () => {
|
|
8
|
+
const terminal = new VirtualTerminal({ width: 80, height: 24 });
|
|
9
|
+
terminal.setLine(1, 'Hello');
|
|
10
|
+
terminal.setLine(2, 'World');
|
|
11
|
+
expect(terminal.getLine(1)).toBe('Hello');
|
|
12
|
+
expect(terminal.getLine(2)).toBe('World');
|
|
13
|
+
expect(terminal.getSetLineCalls()).toHaveLength(2);
|
|
14
|
+
});
|
|
15
|
+
it('should detect when columns overwrite each other', () => {
|
|
16
|
+
const terminal = new VirtualTerminal({ width: 80, height: 24 });
|
|
17
|
+
// Simulate two columns writing to the same line
|
|
18
|
+
// This is the bug: second write overwrites first
|
|
19
|
+
terminal.setLine(1, 'Column1'.padEnd(40, ' '));
|
|
20
|
+
terminal.setLine(1, 'Column2'.padEnd(40, ' '));
|
|
21
|
+
// With the bug, only Column2 is visible
|
|
22
|
+
const finalLine = terminal.getLine(1);
|
|
23
|
+
expect(finalLine).toContain('Column2');
|
|
24
|
+
expect(finalLine).not.toContain('Column1'); // This is the bug!
|
|
25
|
+
// We should see both columns, but we don't
|
|
26
|
+
// This test documents the bug we're trying to fix
|
|
27
|
+
});
|
|
28
|
+
it('should verify flex layout renders columns side-by-side', () => {
|
|
29
|
+
const capturable = new VirtualTerminal({ width: 80, height: 24 });
|
|
30
|
+
const terminal = capturable;
|
|
31
|
+
const flex = new Flex(terminal, { gap: 2 });
|
|
32
|
+
const col1 = new Col(terminal, 'Label', { min: 12, max: 12 });
|
|
33
|
+
const col2 = new Col(terminal, 'Value', { flex: 1 });
|
|
34
|
+
flex.addChild(col1);
|
|
35
|
+
flex.addChild(col2);
|
|
36
|
+
flex.render(0, 1, 80);
|
|
37
|
+
// Check that both columns appear on the same line
|
|
38
|
+
const line1 = capturable.getLine(1);
|
|
39
|
+
const line1Plain = line1.replace(/\x1b\[[0-9;]*m/g, '');
|
|
40
|
+
// With the fix, we should see both "Label" and "Value" on the same line
|
|
41
|
+
expect(line1Plain).toContain('Label');
|
|
42
|
+
expect(line1Plain).toContain('Value');
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=capturable-terminal.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capturable-terminal.test.js","sourceRoot":"","sources":["../../src/ts/test-helpers/capturable-terminal.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple mock TerminalRegion for unit tests
|
|
3
|
+
* Just tracks setLine calls - no actual terminal emulation
|
|
4
|
+
*/
|
|
5
|
+
import type { TerminalRegion } from '../region';
|
|
6
|
+
export declare class MockTerminalRegion implements Partial<TerminalRegion> {
|
|
7
|
+
private lines;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
constructor(width?: number, height?: number);
|
|
11
|
+
getLine(lineNumber: number): string;
|
|
12
|
+
setLine(lineNumber: number, content: string): void;
|
|
13
|
+
clearLine(lineNumber: number): void;
|
|
14
|
+
clear(): void;
|
|
15
|
+
flush(): void;
|
|
16
|
+
setThrottle(_fps: number): void;
|
|
17
|
+
destroy(_clearFirst?: boolean): void;
|
|
18
|
+
getWidth(): number;
|
|
19
|
+
getHeight(): number;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=mock-region.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-region.d.ts","sourceRoot":"","sources":["../../src/test-helpers/mock-region.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,qBAAa,kBAAmB,YAAW,OAAO,CAAC,cAAc,CAAC;IAChE,OAAO,CAAC,KAAK,CAAkC;IACxC,KAAK,EAAE,MAAM,CAAM;IACnB,MAAM,EAAE,MAAM,CAAM;gBAEf,KAAK,GAAE,MAAW,EAAE,MAAM,GAAE,MAAW;IAKnD,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAInC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAIlD,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAInC,KAAK,IAAI,IAAI;IAIb,KAAK,IAAI,IAAI;IAIb,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI/B,OAAO,CAAC,WAAW,GAAE,OAAe,GAAG,IAAI;IAI3C,QAAQ,IAAI,MAAM;IAIlB,SAAS,IAAI,MAAM;CAGpB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export class MockTerminalRegion {
|
|
2
|
+
lines = new Map();
|
|
3
|
+
width = 80;
|
|
4
|
+
height = 24;
|
|
5
|
+
constructor(width = 80, height = 24) {
|
|
6
|
+
this.width = width;
|
|
7
|
+
this.height = height;
|
|
8
|
+
}
|
|
9
|
+
getLine(lineNumber) {
|
|
10
|
+
return this.lines.get(lineNumber) || '';
|
|
11
|
+
}
|
|
12
|
+
setLine(lineNumber, content) {
|
|
13
|
+
this.lines.set(lineNumber, content);
|
|
14
|
+
}
|
|
15
|
+
clearLine(lineNumber) {
|
|
16
|
+
this.lines.delete(lineNumber);
|
|
17
|
+
}
|
|
18
|
+
clear() {
|
|
19
|
+
this.lines.clear();
|
|
20
|
+
}
|
|
21
|
+
flush() {
|
|
22
|
+
// No-op
|
|
23
|
+
}
|
|
24
|
+
setThrottle(_fps) {
|
|
25
|
+
// No-op
|
|
26
|
+
}
|
|
27
|
+
destroy(_clearFirst = false) {
|
|
28
|
+
// No-op
|
|
29
|
+
}
|
|
30
|
+
getWidth() {
|
|
31
|
+
return this.width;
|
|
32
|
+
}
|
|
33
|
+
getHeight() {
|
|
34
|
+
return this.height;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=mock-region.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-region.js","sourceRoot":"","sources":["../../src/test-helpers/mock-region.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,kBAAkB;IACrB,KAAK,GAAwB,IAAI,GAAG,EAAE,CAAC;IACxC,KAAK,GAAW,EAAE,CAAC;IACnB,MAAM,GAAW,EAAE,CAAC;IAE3B,YAAY,QAAgB,EAAE,EAAE,SAAiB,EAAE;QACjD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,OAAO,CAAC,UAAkB;QACxB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAC1C,CAAC;IAED,OAAO,CAAC,UAAkB,EAAE,OAAe;QACzC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,SAAS,CAAC,UAAkB;QAC1B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,KAAK;QACH,QAAQ;IACV,CAAC;IAED,WAAW,CAAC,IAAY;QACtB,QAAQ;IACV,CAAC;IAED,OAAO,CAAC,cAAuB,KAAK;QAClC,QAAQ;IACV,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtual-terminal-diff-reflow.test.d.ts","sourceRoot":"","sources":["../../src/ts/test-helpers/virtual-terminal-diff-reflow.test.ts"],"names":[],"mappings":""}
|