-
-
Notifications
You must be signed in to change notification settings - Fork 269
/
statics.ts
148 lines (138 loc) · 3.76 KB
/
statics.ts
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
/**
* Static `parse()` and `stringify()` methods
*/
import etoa from 'events-to-array'
type EventLog = ReturnType<typeof etoa>
import { Parser, ParserOptions } from './index.js'
import { esc } from './escape.js'
import yaml from 'tap-yaml'
import { SPACE_OPEN_BRACE_EOL } from './brace-patterns.js'
// used in flattening mode
const getId = (): { (): number; current: number } => {
const id = () => id.current++
id.current = 1
return id
}
/**
* Parse a TAP text stream into a log of all the events encountered
*/
export const parse = (
str: string,
options: ParserOptions,
): EventLog => {
const { flat = false } = options
const ignore = ['line', 'pass', 'fail', 'todo', 'skip', 'result']
if (flat) ignore.push('assert', 'child', 'plan', 'complete')
const parser = new Parser(options)
const events = etoa(parser, ignore)
if (flat) {
const id = getId()
parser.on('result', res => {
res.name = res.fullname
res.id = id()
events.push(['assert', res])
})
parser.on('complete', res => {
if (!res.bailout)
events.push(['plan', { end: id.current - 1, start: 1 }])
events.push(['complete', res])
})
}
parser.end(str)
return events
}
/**
* Turn an EventLog from {@link tap-parser!statics.parse} into a TAP string
*/
export const stringify = (
msg: EventLog,
{ flat = false, indent = '', id = getId() },
): string => {
const ind = flat ? '' : indent
return (
ind +
msg
.map(item => {
switch (item[0]) {
case 'child':
const comment = item[1][0]
const child = item[1].slice(1)
return (
Parser.stringify([comment], {
flat,
indent: '',
id,
}) +
Parser.stringify(child, {
flat,
indent: ' ',
id,
})
)
case 'version':
return 'TAP version ' + item[1] + '\n'
case 'plan':
if (flat) {
if (indent !== '') return ''
item[1].start = 1
item[1].end = id.current - 1
}
return (
item[1].start +
'..' +
item[1].end +
(item[1].comment ? ' # ' + esc(item[1].comment) : '') +
'\n'
)
case 'pragma':
return 'pragma ' + (item[2] ? '+' : '-') + item[1] + '\n'
case 'bailout':
return (
'Bail out!' + (item[1] ? ' ' + esc(item[1]) : '') + '\n'
)
case 'assert':
const res = item[1]
if (flat) {
res.id = id()
res.name = res.fullname
}
return (
(res.ok ? '' : 'not ') +
'ok' +
(res.id ? ' ' + res.id : '') +
(res.name ?
' - ' +
esc(res.name).replace(SPACE_OPEN_BRACE_EOL, '')
: '') +
(res.skip ?
' # SKIP' +
(res.skip === true ? '' : ' ' + esc(res.skip))
: '') +
(res.todo ?
' # TODO' +
(res.todo === true ? '' : ' ' + esc(res.todo))
: '') +
(res.time ? ' # time=' + res.time + 'ms' : '') +
'\n' +
(res.diag ?
' ---\n ' +
yaml
.stringify(res.diag)
.split('\n')
.join('\n ')
.trim() +
'\n ...\n'
: '')
)
case 'extra':
case 'comment':
return item[1]
}
})
.join('')
.split('\n')
.join('\n' + ind)
.trim() +
'\n'
)
}