-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathhterm_vt_canned_tests.js
198 lines (167 loc) · 5.99 KB
/
hterm_vt_canned_tests.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// Copyright 2012 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview VT canned data test suite.
*
* This suite plays back pre-recorded VT sessions. The recorded data is
* expected to define checkpoints where we should stop and compare the current
* terminal screen to expected results.
*
* See ../test_data/vttest-01.log for an example of a recorded session that
* includes the required checkpoints.
*
* The ../bin/vtscope.py script can be used to replay canned data to one
* or more terminals at the same time. It understands how to ignore the header
* information contained in the pre-recorded sessions.
*/
import {lib} from '../../libdot/index.js';
import {hterm} from '../index.js';
/*
* (This documentation moved out of JSDoc block due to use of '@@')
*
* Pre-recorded sessions look like this...
*
* @@ HEADER_START
*
* @@ OFFSET:xxx LINES:yyy CURSOR:row,column
* PLACE yyy LINES
* OF EXPECTED RESULTS HERE
*
* @@ OFFSET:xxx1 LINES:yyy1 CURSOR:row,column
* PLACE yyy1 LINES
* OF EXPECTED RESULTS HERE
*
* ... repeat as necessary ...
*
* @@ HEADER_END
* Place the recorded VT session here. You can record it with the
* `script.py` command that comes with the pexpect Python package, or
* just turn on logging on your standard terminal application, if it
* has the option.
*
* Everything between '@@ HEADER_START' and '@@ HEADER_END' is considered
* part of the header information. The vtscope.py script will skip over it
* entirely. All offsets in the OFFSET lines of the header (and in the
* vtscope.py `seek` command) assume that OFFSET 0 is starts on the line after
* '@@ HEADER_END'.
*
* This test suite will stop at each defined OFFSET. The LINES setting tells
* the suite how many of the lines in the terminal are significant, and will
* compare those lines to the expected results. The CURSOR position tells
* the test suite where the cursor is expected to be found.
*
* If there is any mismatch in the expected lines, or the cursor is left in
* the wrong position, the test case will fail.
*
* All OFFSET lines must include a LINES and CURSOR setting in the correct
* order.
*
* Blank lines and lines starting with a "#" between header definitions are
* ignored.
*/
describe('hterm_vt_canned_tests.js', () => {
before(function() {
this.visibleColumnCount = 80;
this.visibleRowCount = 25;
});
/**
* Clear out the current document and create a new hterm.Terminal object for
* testing.
*
* Called before each test case in this suite.
*/
beforeEach(function(done) {
const document = globalThis.document;
const div = document.createElement('div');
div.style.position = 'absolute';
document.body.appendChild(div);
this.div = div;
this.terminal = new hterm.Terminal({storage: new lib.Storage.Memory()});
// Allow column width changes by default so the canned data can request a
// known terminal width.
this.terminal.vt.allowColumnWidthChanges_ = true;
this.terminal.decorate(div);
this.terminal.setWidth(this.visibleColumnCount);
this.terminal.setHeight(this.visibleRowCount);
this.terminal.onTerminalReady = () => {
// The canned tests want access to graphics charsets, so make sure the
// encoding is not utf-8 (as we might default to).
this.terminal.vt.setEncoding('iso-2022');
this.terminal.setCursorPosition(0, 0);
this.terminal.setCursorVisible(true);
done();
};
});
/**
* Ensure that blink is off after the test so we don't have runaway timeouts.
*
* Called after each test case in this suite.
*/
afterEach(function() {
this.terminal.setCursorBlink(false);
document.body.removeChild(this.div);
});
/**
* Test a can of data.
*
* @param {!hterm.Terminal} terminal The terminal to run canned tests against.
* @param {string} name The name of canned test.
*/
const testData = async function(terminal, name) {
const td = new TextDecoder();
const response = await fetch(`../test_data/${name}.log`);
let data = td.decode(await response.arrayBuffer());
let m = data.match(/^(#[^\n]*\n)*@@ HEADER_START/);
// And that it has optional lead-in comments followed by a header.
assert.isTrue(!!m, 'data has a header');
const headerStart = m[0].length;
// And that the header has an ending.
m = data.match(/^@@ HEADER_END\r?\n/m);
assert.isTrue(!!m, 'header ends');
const header = data.substring(headerStart, m.index);
data = data.substr(headerStart + header.length + m[0].length);
let startOffset = 0;
const headerLines = header.split(/\r?\n/);
// Make sure the terminal has the exact dimensions now since we rely on this
// below with our final asserts.
terminal.setWidth(80);
terminal.setHeight(25);
for (let headerIndex = 0; headerIndex < headerLines.length; headerIndex++) {
const line = headerLines[headerIndex];
if (!line || /^(#.*|\s*)$/.test(line)) {
// Skip blank lines and comment lines.
continue;
}
const ary = line.match(
/^@@\s+OFFSET:(\d+)\s+LINES:(\d+)\s+CURSOR:(\d+),(\d+)\s*$/);
assert.isTrue(!!ary, 'header line: ' + line);
const endOffset = Number(ary[1]);
// console.log(`Playing to offset: ${endOffset}`);
terminal.interpret(data.substring(startOffset, endOffset));
const lineCount = Number(ary[2]);
for (let rowIndex = 0; rowIndex < lineCount; rowIndex++) {
headerIndex++;
assert.equal(terminal.getRowText(rowIndex),
headerLines[headerIndex],
'row:' + rowIndex);
}
assert.equal(terminal.getCursorRow(), Number(ary[3]), 'cursor row');
assert.equal(terminal.getCursorColumn(), Number(ary[4]),
'cursor column');
startOffset = endOffset;
}
terminal.setWidth(null);
terminal.setHeight(null);
};
[
// A pre-recorded session of vttest menu option 1, 'Test of cursor movements'.
'vttest-01',
'vttest-02',
'charsets',
].forEach((name) => {
it(name, async function() {
await testData(this.terminal, name);
}).timeout(5000);
});
});