@git.zone/tstest 1.11.5 → 2.2.1
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/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/index.js +24 -2
- package/dist_ts/tstest.classes.tap.parser.d.ts +10 -5
- package/dist_ts/tstest.classes.tap.parser.js +239 -99
- package/dist_ts/tstest.classes.tap.parser.old.d.ts +50 -0
- package/dist_ts/tstest.classes.tap.parser.old.js +332 -0
- package/dist_ts/tstest.classes.tstest.d.ts +1 -0
- package/dist_ts/tstest.classes.tstest.js +93 -4
- package/dist_ts/tstest.logging.d.ts +4 -0
- package/dist_ts/tstest.logging.js +36 -1
- package/dist_ts/tstest.plugins.d.ts +2 -1
- package/dist_ts/tstest.plugins.js +3 -2
- package/dist_ts_tapbundle/index.d.ts +1 -3
- package/dist_ts_tapbundle/index.js +3 -5
- package/dist_ts_tapbundle/tapbundle.classes.settingsmanager.d.ts +36 -0
- package/dist_ts_tapbundle/tapbundle.classes.settingsmanager.js +114 -0
- package/dist_ts_tapbundle/tapbundle.classes.tap.d.ts +26 -3
- package/dist_ts_tapbundle/tapbundle.classes.tap.js +218 -22
- package/dist_ts_tapbundle/tapbundle.classes.taptest.d.ts +5 -0
- package/dist_ts_tapbundle/tapbundle.classes.taptest.js +161 -7
- package/dist_ts_tapbundle/tapbundle.classes.taptools.d.ts +14 -0
- package/dist_ts_tapbundle/tapbundle.classes.taptools.js +24 -1
- package/dist_ts_tapbundle/tapbundle.expect.wrapper.d.ts +11 -0
- package/dist_ts_tapbundle/tapbundle.expect.wrapper.js +71 -0
- package/dist_ts_tapbundle/tapbundle.interfaces.d.ts +27 -0
- package/dist_ts_tapbundle/tapbundle.interfaces.js +2 -0
- package/dist_ts_tapbundle/tapbundle.utilities.diff.d.ts +5 -0
- package/dist_ts_tapbundle/tapbundle.utilities.diff.js +179 -0
- package/dist_ts_tapbundle_protocol/index.d.ts +6 -0
- package/dist_ts_tapbundle_protocol/index.js +11 -0
- package/dist_ts_tapbundle_protocol/protocol.emitter.d.ts +55 -0
- package/dist_ts_tapbundle_protocol/protocol.emitter.js +155 -0
- package/dist_ts_tapbundle_protocol/protocol.parser.d.ts +79 -0
- package/dist_ts_tapbundle_protocol/protocol.parser.js +359 -0
- package/dist_ts_tapbundle_protocol/protocol.types.d.ts +111 -0
- package/dist_ts_tapbundle_protocol/protocol.types.js +19 -0
- package/npmextra.json +3 -3
- package/package.json +2 -1
- package/readme.hints.md +166 -5
- package/readme.md +135 -4
- package/readme.plan.md +145 -56
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +22 -1
- package/ts/tspublish.json +1 -1
- package/ts/tstest.classes.tap.parser.ts +271 -110
- package/ts/tstest.classes.tstest.ts +112 -5
- package/ts/tstest.logging.ts +43 -0
- package/ts/tstest.plugins.ts +2 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import { PROTOCOL_MARKERS } from './protocol.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* ProtocolParser parses Protocol V2 messages
|
|
4
|
+
* This class is used by tstest to parse test results from the new protocol format
|
|
5
|
+
*/
|
|
6
|
+
export class ProtocolParser {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.protocolVersion = null;
|
|
9
|
+
this.inBlock = false;
|
|
10
|
+
this.blockType = null;
|
|
11
|
+
this.blockContent = [];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parse a single line and return protocol messages
|
|
15
|
+
*/
|
|
16
|
+
parseLine(line) {
|
|
17
|
+
const messages = [];
|
|
18
|
+
// Handle block content
|
|
19
|
+
if (this.inBlock) {
|
|
20
|
+
if (this.isBlockEnd(line)) {
|
|
21
|
+
messages.push(this.finalizeBlock());
|
|
22
|
+
this.inBlock = false;
|
|
23
|
+
this.blockType = null;
|
|
24
|
+
this.blockContent = [];
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
this.blockContent.push(line);
|
|
28
|
+
}
|
|
29
|
+
return messages;
|
|
30
|
+
}
|
|
31
|
+
// Check for block start
|
|
32
|
+
if (this.isBlockStart(line)) {
|
|
33
|
+
this.inBlock = true;
|
|
34
|
+
this.blockType = this.extractBlockType(line);
|
|
35
|
+
return messages;
|
|
36
|
+
}
|
|
37
|
+
// Check for protocol version
|
|
38
|
+
const protocolVersion = this.parseProtocolVersion(line);
|
|
39
|
+
if (protocolVersion) {
|
|
40
|
+
this.protocolVersion = protocolVersion;
|
|
41
|
+
messages.push({
|
|
42
|
+
type: 'protocol',
|
|
43
|
+
content: { version: protocolVersion }
|
|
44
|
+
});
|
|
45
|
+
return messages;
|
|
46
|
+
}
|
|
47
|
+
// Parse TAP version
|
|
48
|
+
const tapVersion = this.parseTapVersion(line);
|
|
49
|
+
if (tapVersion !== null) {
|
|
50
|
+
messages.push({
|
|
51
|
+
type: 'version',
|
|
52
|
+
content: tapVersion
|
|
53
|
+
});
|
|
54
|
+
return messages;
|
|
55
|
+
}
|
|
56
|
+
// Parse plan
|
|
57
|
+
const plan = this.parsePlan(line);
|
|
58
|
+
if (plan) {
|
|
59
|
+
messages.push({
|
|
60
|
+
type: 'plan',
|
|
61
|
+
content: plan
|
|
62
|
+
});
|
|
63
|
+
return messages;
|
|
64
|
+
}
|
|
65
|
+
// Parse bailout
|
|
66
|
+
const bailout = this.parseBailout(line);
|
|
67
|
+
if (bailout) {
|
|
68
|
+
messages.push({
|
|
69
|
+
type: 'bailout',
|
|
70
|
+
content: bailout
|
|
71
|
+
});
|
|
72
|
+
return messages;
|
|
73
|
+
}
|
|
74
|
+
// Parse comment
|
|
75
|
+
if (this.isComment(line)) {
|
|
76
|
+
messages.push({
|
|
77
|
+
type: 'comment',
|
|
78
|
+
content: line.substring(2) // Remove "# "
|
|
79
|
+
});
|
|
80
|
+
return messages;
|
|
81
|
+
}
|
|
82
|
+
// Parse test result
|
|
83
|
+
const testResult = this.parseTestResult(line);
|
|
84
|
+
if (testResult) {
|
|
85
|
+
messages.push({
|
|
86
|
+
type: 'test',
|
|
87
|
+
content: testResult
|
|
88
|
+
});
|
|
89
|
+
return messages;
|
|
90
|
+
}
|
|
91
|
+
// Parse event
|
|
92
|
+
const event = this.parseEvent(line);
|
|
93
|
+
if (event) {
|
|
94
|
+
messages.push({
|
|
95
|
+
type: 'event',
|
|
96
|
+
content: event
|
|
97
|
+
});
|
|
98
|
+
return messages;
|
|
99
|
+
}
|
|
100
|
+
return messages;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Parse protocol version header
|
|
104
|
+
*/
|
|
105
|
+
parseProtocolVersion(line) {
|
|
106
|
+
const match = this.extractProtocolData(line, PROTOCOL_MARKERS.PROTOCOL_PREFIX);
|
|
107
|
+
return match;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Parse TAP version line
|
|
111
|
+
*/
|
|
112
|
+
parseTapVersion(line) {
|
|
113
|
+
const match = line.match(/^TAP version (\d+)$/);
|
|
114
|
+
if (match) {
|
|
115
|
+
return parseInt(match[1], 10);
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Parse plan line
|
|
121
|
+
*/
|
|
122
|
+
parsePlan(line) {
|
|
123
|
+
// Skip all plan
|
|
124
|
+
const skipMatch = line.match(/^1\.\.0\s*#\s*Skipped:\s*(.*)$/);
|
|
125
|
+
if (skipMatch) {
|
|
126
|
+
return {
|
|
127
|
+
start: 1,
|
|
128
|
+
end: 0,
|
|
129
|
+
skipAll: skipMatch[1]
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// Normal plan
|
|
133
|
+
const match = line.match(/^(\d+)\.\.(\d+)$/);
|
|
134
|
+
if (match) {
|
|
135
|
+
return {
|
|
136
|
+
start: parseInt(match[1], 10),
|
|
137
|
+
end: parseInt(match[2], 10)
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Parse bailout
|
|
144
|
+
*/
|
|
145
|
+
parseBailout(line) {
|
|
146
|
+
const match = line.match(/^Bail out!\s*(.*)$/);
|
|
147
|
+
return match ? match[1] : null;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Parse event
|
|
151
|
+
*/
|
|
152
|
+
parseEvent(line) {
|
|
153
|
+
const eventData = this.extractProtocolData(line, PROTOCOL_MARKERS.EVENT_PREFIX);
|
|
154
|
+
if (eventData) {
|
|
155
|
+
try {
|
|
156
|
+
return JSON.parse(eventData);
|
|
157
|
+
}
|
|
158
|
+
catch (e) {
|
|
159
|
+
// Invalid JSON, ignore
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Check if line is a comment
|
|
167
|
+
*/
|
|
168
|
+
isComment(line) {
|
|
169
|
+
return line.startsWith('# ');
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Parse test result line
|
|
173
|
+
*/
|
|
174
|
+
parseTestResult(line) {
|
|
175
|
+
// First extract any inline metadata
|
|
176
|
+
const metadata = this.extractInlineMetadata(line);
|
|
177
|
+
const cleanLine = this.removeInlineMetadata(line);
|
|
178
|
+
// Parse the TAP part
|
|
179
|
+
const tapMatch = cleanLine.match(/^(ok|not ok)\s+(\d+)\s*-?\s*(.*)$/);
|
|
180
|
+
if (!tapMatch) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
const result = {
|
|
184
|
+
ok: tapMatch[1] === 'ok',
|
|
185
|
+
testNumber: parseInt(tapMatch[2], 10),
|
|
186
|
+
description: tapMatch[3].trim()
|
|
187
|
+
};
|
|
188
|
+
// Parse directive
|
|
189
|
+
const directiveMatch = result.description.match(/^(.*?)\s*#\s*(SKIP|TODO)\s*(.*)$/i);
|
|
190
|
+
if (directiveMatch) {
|
|
191
|
+
result.description = directiveMatch[1].trim();
|
|
192
|
+
result.directive = {
|
|
193
|
+
type: directiveMatch[2].toLowerCase(),
|
|
194
|
+
reason: directiveMatch[3] || undefined
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
// Add metadata if found
|
|
198
|
+
if (metadata) {
|
|
199
|
+
result.metadata = metadata;
|
|
200
|
+
}
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Extract inline metadata from line
|
|
205
|
+
*/
|
|
206
|
+
extractInlineMetadata(line) {
|
|
207
|
+
const metadata = {};
|
|
208
|
+
let hasData = false;
|
|
209
|
+
// Extract skip reason
|
|
210
|
+
const skipData = this.extractProtocolData(line, PROTOCOL_MARKERS.SKIP_PREFIX);
|
|
211
|
+
if (skipData) {
|
|
212
|
+
metadata.skip = skipData;
|
|
213
|
+
hasData = true;
|
|
214
|
+
}
|
|
215
|
+
// Extract todo reason
|
|
216
|
+
const todoData = this.extractProtocolData(line, PROTOCOL_MARKERS.TODO_PREFIX);
|
|
217
|
+
if (todoData) {
|
|
218
|
+
metadata.todo = todoData;
|
|
219
|
+
hasData = true;
|
|
220
|
+
}
|
|
221
|
+
// Extract META JSON
|
|
222
|
+
const metaData = this.extractProtocolData(line, PROTOCOL_MARKERS.META_PREFIX);
|
|
223
|
+
if (metaData) {
|
|
224
|
+
try {
|
|
225
|
+
Object.assign(metadata, JSON.parse(metaData));
|
|
226
|
+
hasData = true;
|
|
227
|
+
}
|
|
228
|
+
catch (e) {
|
|
229
|
+
// Invalid JSON, ignore
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// Extract simple key:value pairs
|
|
233
|
+
const simpleMatch = line.match(new RegExp(`${this.escapeRegex(PROTOCOL_MARKERS.START)}([^${this.escapeRegex(PROTOCOL_MARKERS.END)}]+)${this.escapeRegex(PROTOCOL_MARKERS.END)}`));
|
|
234
|
+
if (simpleMatch && !simpleMatch[1].includes(':')) {
|
|
235
|
+
// Not a prefixed format, might be key:value pairs
|
|
236
|
+
const pairs = simpleMatch[1].split(',');
|
|
237
|
+
for (const pair of pairs) {
|
|
238
|
+
const [key, value] = pair.split(':');
|
|
239
|
+
if (key && value) {
|
|
240
|
+
if (key === 'time') {
|
|
241
|
+
metadata.time = parseInt(value, 10);
|
|
242
|
+
hasData = true;
|
|
243
|
+
}
|
|
244
|
+
else if (key === 'retry') {
|
|
245
|
+
metadata.retry = parseInt(value, 10);
|
|
246
|
+
hasData = true;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return hasData ? metadata : null;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Remove inline metadata from line
|
|
255
|
+
*/
|
|
256
|
+
removeInlineMetadata(line) {
|
|
257
|
+
// Remove all protocol markers
|
|
258
|
+
const regex = new RegExp(`${this.escapeRegex(PROTOCOL_MARKERS.START)}[^${this.escapeRegex(PROTOCOL_MARKERS.END)}]*${this.escapeRegex(PROTOCOL_MARKERS.END)}`, 'g');
|
|
259
|
+
return line.replace(regex, '').trim();
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Extract protocol data with specific prefix
|
|
263
|
+
*/
|
|
264
|
+
extractProtocolData(line, prefix) {
|
|
265
|
+
const regex = new RegExp(`${this.escapeRegex(PROTOCOL_MARKERS.START)}${this.escapeRegex(prefix)}([^${this.escapeRegex(PROTOCOL_MARKERS.END)}]*)${this.escapeRegex(PROTOCOL_MARKERS.END)}`);
|
|
266
|
+
const match = line.match(regex);
|
|
267
|
+
return match ? match[1] : null;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Check if line starts a block
|
|
271
|
+
*/
|
|
272
|
+
isBlockStart(line) {
|
|
273
|
+
// Only match if the line is exactly the block marker (after trimming)
|
|
274
|
+
const trimmed = line.trim();
|
|
275
|
+
return trimmed === `${PROTOCOL_MARKERS.START}${PROTOCOL_MARKERS.ERROR_PREFIX}${PROTOCOL_MARKERS.END}` ||
|
|
276
|
+
(trimmed.startsWith(`${PROTOCOL_MARKERS.START}${PROTOCOL_MARKERS.SNAPSHOT_PREFIX}`) &&
|
|
277
|
+
trimmed.endsWith(PROTOCOL_MARKERS.END) &&
|
|
278
|
+
!trimmed.includes(' '));
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Check if line ends a block
|
|
282
|
+
*/
|
|
283
|
+
isBlockEnd(line) {
|
|
284
|
+
return line.includes(`${PROTOCOL_MARKERS.START}${PROTOCOL_MARKERS.ERROR_END}${PROTOCOL_MARKERS.END}`) ||
|
|
285
|
+
line.includes(`${PROTOCOL_MARKERS.START}${PROTOCOL_MARKERS.SNAPSHOT_END}${PROTOCOL_MARKERS.END}`);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Extract block type from start line
|
|
289
|
+
*/
|
|
290
|
+
extractBlockType(line) {
|
|
291
|
+
if (line.includes(PROTOCOL_MARKERS.ERROR_PREFIX)) {
|
|
292
|
+
return 'error';
|
|
293
|
+
}
|
|
294
|
+
if (line.includes(PROTOCOL_MARKERS.SNAPSHOT_PREFIX)) {
|
|
295
|
+
const match = line.match(new RegExp(`${this.escapeRegex(PROTOCOL_MARKERS.START)}${this.escapeRegex(PROTOCOL_MARKERS.SNAPSHOT_PREFIX)}([^${this.escapeRegex(PROTOCOL_MARKERS.END)}]*)${this.escapeRegex(PROTOCOL_MARKERS.END)}`));
|
|
296
|
+
return match ? `snapshot:${match[1]}` : 'snapshot';
|
|
297
|
+
}
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Finalize current block
|
|
302
|
+
*/
|
|
303
|
+
finalizeBlock() {
|
|
304
|
+
const content = this.blockContent.join('\n');
|
|
305
|
+
if (this.blockType === 'error') {
|
|
306
|
+
try {
|
|
307
|
+
const errorData = JSON.parse(content);
|
|
308
|
+
return {
|
|
309
|
+
type: 'error',
|
|
310
|
+
content: errorData
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
catch (e) {
|
|
314
|
+
return {
|
|
315
|
+
type: 'error',
|
|
316
|
+
content: { error: { message: content } }
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (this.blockType?.startsWith('snapshot:')) {
|
|
321
|
+
const name = this.blockType.substring(9);
|
|
322
|
+
let parsedContent = content;
|
|
323
|
+
let format = 'text';
|
|
324
|
+
try {
|
|
325
|
+
parsedContent = JSON.parse(content);
|
|
326
|
+
format = 'json';
|
|
327
|
+
}
|
|
328
|
+
catch (e) {
|
|
329
|
+
// Not JSON, keep as text
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
type: 'snapshot',
|
|
333
|
+
content: {
|
|
334
|
+
name,
|
|
335
|
+
content: parsedContent,
|
|
336
|
+
format
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
// Fallback
|
|
341
|
+
return {
|
|
342
|
+
type: 'comment',
|
|
343
|
+
content: content
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Escape regex special characters
|
|
348
|
+
*/
|
|
349
|
+
escapeRegex(str) {
|
|
350
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Get protocol version
|
|
354
|
+
*/
|
|
355
|
+
getProtocolVersion() {
|
|
356
|
+
return this.protocolVersion;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wucGFyc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfdGFwYnVuZGxlX3Byb3RvY29sL3Byb3RvY29sLnBhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFVQSxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2pCLE1BQU0scUJBQXFCLENBQUM7QUFFN0I7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGNBQWM7SUFBM0I7UUFDVSxvQkFBZSxHQUFrQixJQUFJLENBQUM7UUFDdEMsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUNoQixjQUFTLEdBQWtCLElBQUksQ0FBQztRQUNoQyxpQkFBWSxHQUFhLEVBQUUsQ0FBQztJQWdZdEMsQ0FBQztJQTlYQzs7T0FFRztJQUNJLFNBQVMsQ0FBQyxJQUFZO1FBQzNCLE1BQU0sUUFBUSxHQUF1QixFQUFFLENBQUM7UUFFeEMsdUJBQXVCO1FBQ3ZCLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pCLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUMxQixRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDO2dCQUNwQyxJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztnQkFDckIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7Z0JBQ3RCLElBQUksQ0FBQyxZQUFZLEdBQUcsRUFBRSxDQUFDO1lBQ3pCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMvQixDQUFDO1lBQ0QsT0FBTyxRQUFRLENBQUM7UUFDbEIsQ0FBQztRQUVELHdCQUF3QjtRQUN4QixJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUM1QixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztZQUNwQixJQUFJLENB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
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
export interface ITestMetadata {
|
|
2
|
+
time?: number;
|
|
3
|
+
startTime?: number;
|
|
4
|
+
endTime?: number;
|
|
5
|
+
skip?: string;
|
|
6
|
+
todo?: string;
|
|
7
|
+
retry?: number;
|
|
8
|
+
maxRetries?: number;
|
|
9
|
+
error?: {
|
|
10
|
+
message: string;
|
|
11
|
+
stack?: string;
|
|
12
|
+
diff?: string;
|
|
13
|
+
actual?: any;
|
|
14
|
+
expected?: any;
|
|
15
|
+
code?: string;
|
|
16
|
+
};
|
|
17
|
+
file?: string;
|
|
18
|
+
line?: number;
|
|
19
|
+
column?: number;
|
|
20
|
+
tags?: string[];
|
|
21
|
+
custom?: Record<string, any>;
|
|
22
|
+
}
|
|
23
|
+
export interface ITestResult {
|
|
24
|
+
ok: boolean;
|
|
25
|
+
testNumber: number;
|
|
26
|
+
description: string;
|
|
27
|
+
directive?: {
|
|
28
|
+
type: 'skip' | 'todo';
|
|
29
|
+
reason?: string;
|
|
30
|
+
};
|
|
31
|
+
metadata?: ITestMetadata;
|
|
32
|
+
}
|
|
33
|
+
export interface IPlanLine {
|
|
34
|
+
start: number;
|
|
35
|
+
end: number;
|
|
36
|
+
skipAll?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface IProtocolMessage {
|
|
39
|
+
type: 'test' | 'plan' | 'comment' | 'version' | 'bailout' | 'protocol' | 'snapshot' | 'error' | 'event';
|
|
40
|
+
content: any;
|
|
41
|
+
}
|
|
42
|
+
export interface IProtocolVersion {
|
|
43
|
+
version: string;
|
|
44
|
+
features?: string[];
|
|
45
|
+
}
|
|
46
|
+
export interface ISnapshotData {
|
|
47
|
+
name: string;
|
|
48
|
+
content: any;
|
|
49
|
+
format?: 'json' | 'text' | 'binary';
|
|
50
|
+
}
|
|
51
|
+
export interface IErrorBlock {
|
|
52
|
+
testNumber?: number;
|
|
53
|
+
error: {
|
|
54
|
+
message: string;
|
|
55
|
+
stack?: string;
|
|
56
|
+
diff?: string;
|
|
57
|
+
actual?: any;
|
|
58
|
+
expected?: any;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export type EventType = 'test:queued' | 'test:started' | 'test:progress' | 'test:completed' | 'suite:started' | 'suite:completed' | 'hook:started' | 'hook:completed' | 'assertion:failed';
|
|
62
|
+
export interface ITestEvent {
|
|
63
|
+
eventType: EventType;
|
|
64
|
+
timestamp: number;
|
|
65
|
+
data: {
|
|
66
|
+
testNumber?: number;
|
|
67
|
+
description?: string;
|
|
68
|
+
suiteName?: string;
|
|
69
|
+
hookName?: string;
|
|
70
|
+
progress?: number;
|
|
71
|
+
duration?: number;
|
|
72
|
+
error?: IEnhancedError;
|
|
73
|
+
[key: string]: any;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export interface IEnhancedError {
|
|
77
|
+
message: string;
|
|
78
|
+
stack?: string;
|
|
79
|
+
diff?: IDiffResult;
|
|
80
|
+
actual?: any;
|
|
81
|
+
expected?: any;
|
|
82
|
+
code?: string;
|
|
83
|
+
type?: 'assertion' | 'timeout' | 'uncaught' | 'syntax' | 'runtime';
|
|
84
|
+
}
|
|
85
|
+
export interface IDiffResult {
|
|
86
|
+
type: 'string' | 'object' | 'array' | 'primitive';
|
|
87
|
+
changes: IDiffChange[];
|
|
88
|
+
context?: number;
|
|
89
|
+
}
|
|
90
|
+
export interface IDiffChange {
|
|
91
|
+
type: 'add' | 'remove' | 'modify';
|
|
92
|
+
path?: string[];
|
|
93
|
+
oldValue?: any;
|
|
94
|
+
newValue?: any;
|
|
95
|
+
line?: number;
|
|
96
|
+
content?: string;
|
|
97
|
+
}
|
|
98
|
+
export declare const PROTOCOL_MARKERS: {
|
|
99
|
+
readonly START: "⟦TSTEST:";
|
|
100
|
+
readonly END: "⟧";
|
|
101
|
+
readonly META_PREFIX: "META:";
|
|
102
|
+
readonly ERROR_PREFIX: "ERROR";
|
|
103
|
+
readonly ERROR_END: "/ERROR";
|
|
104
|
+
readonly SNAPSHOT_PREFIX: "SNAPSHOT:";
|
|
105
|
+
readonly SNAPSHOT_END: "/SNAPSHOT";
|
|
106
|
+
readonly PROTOCOL_PREFIX: "PROTOCOL:";
|
|
107
|
+
readonly SKIP_PREFIX: "SKIP:";
|
|
108
|
+
readonly TODO_PREFIX: "TODO:";
|
|
109
|
+
readonly EVENT_PREFIX: "EVENT:";
|
|
110
|
+
};
|
|
111
|
+
export declare const PROTOCOL_VERSION = "2.0.0";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Protocol V2 Types and Interfaces
|
|
2
|
+
// This file contains all type definitions for the improved TAP protocol
|
|
3
|
+
// Protocol markers
|
|
4
|
+
export const PROTOCOL_MARKERS = {
|
|
5
|
+
START: '⟦TSTEST:',
|
|
6
|
+
END: '⟧',
|
|
7
|
+
META_PREFIX: 'META:',
|
|
8
|
+
ERROR_PREFIX: 'ERROR',
|
|
9
|
+
ERROR_END: '/ERROR',
|
|
10
|
+
SNAPSHOT_PREFIX: 'SNAPSHOT:',
|
|
11
|
+
SNAPSHOT_END: '/SNAPSHOT',
|
|
12
|
+
PROTOCOL_PREFIX: 'PROTOCOL:',
|
|
13
|
+
SKIP_PREFIX: 'SKIP:',
|
|
14
|
+
TODO_PREFIX: 'TODO:',
|
|
15
|
+
EVENT_PREFIX: 'EVENT:',
|
|
16
|
+
};
|
|
17
|
+
// Protocol version
|
|
18
|
+
export const PROTOCOL_VERSION = '2.0.0';
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wudHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c190YXBidW5kbGVfcHJvdG9jb2wvcHJvdG9jb2wudHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsbUNBQW1DO0FBQ25DLHdFQUF3RTtBQWtJeEUsbUJBQW1CO0FBQ25CLE1BQU0sQ0FBQyxNQUFNLGdCQUFnQixHQUFHO0lBQzlCLEtBQUssRUFBRSxVQUFVO0lBQ2pCLEdBQUcsRUFBRSxHQUFHO0lBQ1IsV0FBVyxFQUFFLE9BQU87SUFDcEIsWUFBWSxFQUFFLE9BQU87SUFDckIsU0FBUyxFQUFFLFFBQVE7SUFDbkIsZUFBZSxFQUFFLFdBQVc7SUFDNUIsWUFBWSxFQUFFLFdBQVc7SUFDekIsZUFBZSxFQUFFLFdBQVc7SUFDNUIsV0FBVyxFQUFFLE9BQU87SUFDcEIsV0FBVyxFQUFFLE9BQU87SUFDcEIsWUFBWSxFQUFFLFFBQVE7Q0FDZCxDQUFDO0FBRVgsbUJBQW1CO0FBQ25CLE1BQU0sQ0FBQyxNQUFNLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyJ9
|
package/npmextra.json
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
"gitzone": {
|
|
7
7
|
"projectType": "npm",
|
|
8
8
|
"module": {
|
|
9
|
-
"githost": "
|
|
10
|
-
"gitscope": "
|
|
9
|
+
"githost": "code.foss.global",
|
|
10
|
+
"gitscope": "git.zone",
|
|
11
11
|
"gitrepo": "tstest",
|
|
12
12
|
"description": "a test utility to run tests that match test/**/*.ts",
|
|
13
|
-
"npmPackagename": "@
|
|
13
|
+
"npmPackagename": "@git.zone/tstest",
|
|
14
14
|
"license": "MIT"
|
|
15
15
|
}
|
|
16
16
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@git.zone/tstest",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "a test utility to run tests that match test/**/*.ts",
|
|
6
6
|
"exports": {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"@push.rocks/consolecolor": "^2.0.2",
|
|
26
26
|
"@push.rocks/qenv": "^6.1.0",
|
|
27
27
|
"@push.rocks/smartbrowser": "^2.0.8",
|
|
28
|
+
"@push.rocks/smartchok": "^1.0.34",
|
|
28
29
|
"@push.rocks/smartcrypto": "^2.0.4",
|
|
29
30
|
"@push.rocks/smartdelay": "^3.0.5",
|
|
30
31
|
"@push.rocks/smartenv": "^5.0.12",
|