1 | #!/usr/bin/env node
|
2 |
|
3 | var Parser = require('../')
|
4 | var etoa = require('events-to-array')
|
5 | var util = require('util')
|
6 |
|
7 | var args = process.argv.slice(2)
|
8 | var json = null
|
9 | var flat = false
|
10 | var bail = false
|
11 | var preserveWhitespace = true
|
12 | var omitVersion = false
|
13 | var strict = false
|
14 |
|
15 | function version () {
|
16 | console.log(require('../package.json').version)
|
17 | process.exit(0)
|
18 | }
|
19 |
|
20 | for (let i = 0; i < args.length; i++) {
|
21 | const arg = args[i]
|
22 | if (arg === '-j') {
|
23 | const val = +args[i + 1]
|
24 | if (val >= 0) {
|
25 | json = val
|
26 | i += 1
|
27 | } else
|
28 | json = 2
|
29 | continue
|
30 | } else {
|
31 | var m = arg.match(/^--json(?:=([0-9]+))?$/)
|
32 | if (m) {
|
33 | if (+m[1] >= 0)
|
34 | json = +m[1]
|
35 | else if (+args[i + 1] >= 0) {
|
36 | json = +args[i + 1]
|
37 | i += 1
|
38 | } else
|
39 | json = 2
|
40 | continue
|
41 | }
|
42 | }
|
43 |
|
44 | if (arg === '-v' || arg === '--version')
|
45 | version()
|
46 | else if (arg === '-o' || arg === '--omit-version')
|
47 | omitVersion = true
|
48 | else if (arg === '-w' || arg === '--ignore-all-whitespace')
|
49 | preserveWhitespace = false
|
50 | else if (arg === '-b' || arg === '--bail')
|
51 | bail = true
|
52 | else if (arg === '-B' || arg === '--no-bail')
|
53 | bail = false
|
54 | else if (arg === '-t' || arg === '--tap')
|
55 | json = 'tap'
|
56 | else if (arg === '-l' || arg === '--lines')
|
57 | json = 'lines'
|
58 | else if (arg === '-h' || arg === '--help')
|
59 | usage()
|
60 | else if (arg === '-f' || arg === '--flat')
|
61 | flat = true
|
62 | else if (arg === '-F' || arg === '--no-flat')
|
63 | flat = false
|
64 | else if (arg === '--strict')
|
65 | strict = true
|
66 | else if (arg === '--no-strict')
|
67 | strict = false
|
68 | else if (arg === '-s' || arg === '--silent')
|
69 | json = 'silent'
|
70 | else
|
71 | console.error('Unrecognized arg: %j', arg)
|
72 | }
|
73 |
|
74 | function usage () {
|
75 | console.log(`Usage:
|
76 | tap-parser <options>
|
77 |
|
78 | Parses TAP data from stdin, and outputs the parsed result
|
79 | in the format specified by the options. Default output is
|
80 | uses node's \`util.inspect()\` method.
|
81 |
|
82 | Options:
|
83 |
|
84 | -j [<indent>] | --json[=indent]
|
85 | Output event data as JSON with the specified indentation (default=2)
|
86 |
|
87 | -t | --tap
|
88 | Output data as reconstituted TAP based on parsed results
|
89 |
|
90 | -l | --lines
|
91 | Output each parsed line as it is recognized by the parser
|
92 |
|
93 | -b | --bail
|
94 | Emit a \`Bail out!\` at the first failed test point encountered
|
95 |
|
96 | -B | --no-bail
|
97 | Do not bail out at the first failed test point encountered
|
98 | (Default)
|
99 |
|
100 | -f | --flat
|
101 | Flatten all assertions to the top level parser
|
102 |
|
103 | -F | --no-flat
|
104 | Do not flatten all assertions to the top level parser
|
105 | (Default)
|
106 |
|
107 | -w | --ignore-all-whitespace
|
108 | Skip over blank lines outside of YAML blocks
|
109 |
|
110 | -o | --omit-version
|
111 | Ignore the \`TAP version 13\` line at the start of tests
|
112 |
|
113 | --strict
|
114 | Run the parser in strict mode
|
115 |
|
116 | --no-strict
|
117 | Do not run the parser in strict mode
|
118 |
|
119 | -s | --silent
|
120 | Do not print output, just exit success/failure based on TAP stream
|
121 | `)
|
122 |
|
123 |
|
124 |
|
125 | if (!process.stdin.isTTY)
|
126 | process.stdin.resume()
|
127 |
|
128 | process.exit()
|
129 | }
|
130 |
|
131 | var yaml = require('tap-yaml')
|
132 | let id = 1
|
133 | function tapFormat (msg, indent) {
|
134 | return indent + msg.map(function (item) {
|
135 | switch (item[0]) {
|
136 | case 'child':
|
137 | var comment = item[1][0]
|
138 | var child = item[1].slice(1)
|
139 | return tapFormat([comment], '') + tapFormat(child, ' ')
|
140 |
|
141 | case 'version':
|
142 | return 'TAP version ' + item[1] + '\n'
|
143 |
|
144 | case 'plan':
|
145 | if (flat) {
|
146 | item[1].start = 1
|
147 | item[1].end = id - 1
|
148 | }
|
149 | var p = item[1].start + '..' + item[1].end
|
150 | if (item[1].comment)
|
151 | p += ' # ' + item[1].comment
|
152 | return p + '\n'
|
153 |
|
154 | case 'pragma':
|
155 | return 'pragma ' + (item[2] ? '+' : '-') + item[1] + '\n'
|
156 |
|
157 | case 'bailout':
|
158 | var r = item[1] ? (' ' + item[1]) : ''
|
159 | return 'Bail out!' + r + '\n'
|
160 |
|
161 | case 'result':
|
162 | case 'assert':
|
163 | var res = item[1]
|
164 | if (item[0] === 'result') {
|
165 | res.id = id++
|
166 | res.name = (res.fullname + ' > ' + (res.name || '')).trim()
|
167 | }
|
168 | return (res.ok ? '' : 'not ') + 'ok ' + res.id +
|
169 | (res.name ? ' - ' + res.name.replace(/ \{$/, '') : '') +
|
170 | (res.skip ? ' # SKIP' +
|
171 | (res.skip === true ? '' : ' ' + res.skip) : '') +
|
172 | (res.todo ? ' # TODO' +
|
173 | (res.todo === true ? '' : ' ' + res.todo) : '') +
|
174 | (res.time ? ' # time=' + res.time + 'ms' : '') +
|
175 | '\n' +
|
176 | (res.diag ?
|
177 | ' ---\n ' +
|
178 | yaml.stringify(res.diag).split('\n').join('\n ').trim() +
|
179 | '\n ...\n'
|
180 | : '')
|
181 |
|
182 | case 'extra':
|
183 | case 'comment':
|
184 | return item[1]
|
185 | }
|
186 | }).join('').split('\n').join('\n' + indent).trim() + '\n'
|
187 | }
|
188 |
|
189 | function format (msg) {
|
190 | if (json === 'tap')
|
191 | return tapFormat(msg, '')
|
192 | else if (json !== null)
|
193 | return JSON.stringify(msg, null, +json)
|
194 | else
|
195 | return util.inspect(events, null, Infinity)
|
196 | }
|
197 |
|
198 | var options = {
|
199 | bail: bail,
|
200 | preserveWhitespace: preserveWhitespace,
|
201 | omitVersion: omitVersion,
|
202 | strict: strict,
|
203 | }
|
204 |
|
205 | var parser = new Parser(options)
|
206 | const ignore = [
|
207 | 'pipe',
|
208 | 'unpipe',
|
209 | 'prefinish',
|
210 | 'finish',
|
211 | 'line',
|
212 | 'pass',
|
213 | 'fail',
|
214 | 'todo',
|
215 | 'skip',
|
216 | ]
|
217 | if (flat)
|
218 | ignore.push('assert', 'child')
|
219 | else
|
220 | ignore.push('result')
|
221 |
|
222 | var events = etoa(parser, ignore)
|
223 |
|
224 | if (json === 'lines')
|
225 | parser.on('line', function (l) {
|
226 | process.stdout.write(l)
|
227 | })
|
228 |
|
229 | process.on('exit', function () {
|
230 | if (json !== 'silent' && json !== 'lines')
|
231 | console.log(format(events))
|
232 | if (!parser.ok)
|
233 | process.exit(1)
|
234 | })
|
235 |
|
236 | process.stdin.pipe(parser)
|