forked from enviPath/enviPy
Current Dev State
This commit is contained in:
18
static/js/ketcher2/node_modules/tap-parser/LICENSE
generated
vendored
Normal file
18
static/js/ketcher2/node_modules/tap-parser/LICENSE
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
This software is released under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
160
static/js/ketcher2/node_modules/tap-parser/bin/cmd.js
generated
vendored
Executable file
160
static/js/ketcher2/node_modules/tap-parser/bin/cmd.js
generated
vendored
Executable file
@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var Parser = require('../')
|
||||
var etoa = require('events-to-array')
|
||||
var util = require('util')
|
||||
|
||||
var args = process.argv.slice(2)
|
||||
var json = null
|
||||
var bail = false
|
||||
var preserveWhitespace = true
|
||||
var omitVersion = false
|
||||
|
||||
function version () {
|
||||
console.log(require('../package.json').version)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
args.forEach(function (arg, i) {
|
||||
if (arg === '-j') {
|
||||
json = args[i + 1] || 2
|
||||
} else {
|
||||
var m = arg.match(/^--json(?:=([0-9]+))$/)
|
||||
if (m)
|
||||
json = +m[1] || args[i + 1] || 2
|
||||
}
|
||||
|
||||
if (arg === '-v' || arg === '--version')
|
||||
version()
|
||||
else if (arg === '-o' || arg === '--omit-version')
|
||||
omitVersion = true
|
||||
else if (arg === '-w' || arg === '--ignore-all-whitespace')
|
||||
preserveWhitespace = false
|
||||
else if (arg === '-b' || arg === '--bail')
|
||||
bail = true
|
||||
else if (arg === '-t' || arg === '--tap')
|
||||
json = 'tap'
|
||||
else if (arg === '-l' || arg === '--lines')
|
||||
json = 'lines'
|
||||
else if (arg === '-h' || arg === '--help')
|
||||
usage()
|
||||
else
|
||||
console.error('Unrecognized arg: %j', arg)
|
||||
|
||||
if (arg === '-v' || arg === '--version')
|
||||
console.log(require('../package.json').version)
|
||||
})
|
||||
|
||||
function usage () {
|
||||
console.log(function () {/*
|
||||
Usage:
|
||||
tap-parser <options>
|
||||
|
||||
Parses TAP data from stdin, and outputs the parsed result
|
||||
in the format specified by the options. Default output is
|
||||
uses node's `util.format()` method.
|
||||
|
||||
Options:
|
||||
|
||||
-j [<indent>] | --json[=indent]
|
||||
Output event data as JSON with the specified indentation (default=2)
|
||||
|
||||
-t | --tap
|
||||
Output data as reconstituted TAP based on parsed results
|
||||
|
||||
-l | --lines
|
||||
Output each parsed line as it is recognized by the parser
|
||||
|
||||
-b | --bail
|
||||
Emit a `Bail out!` at the first failed test point encountered
|
||||
|
||||
-w | --ignore-all-whitespace
|
||||
Skip over blank lines outside of YAML blocks
|
||||
|
||||
-o | --omit-version
|
||||
Ignore the `TAP version 13` line at the start of tests
|
||||
*/}.toString().split('\n').slice(1, -1).join('\n'))
|
||||
|
||||
if (!process.stdin.isTTY)
|
||||
process.stdin.resume()
|
||||
|
||||
process.exit()
|
||||
}
|
||||
|
||||
var yaml = require('js-yaml')
|
||||
function tapFormat (msg, indent) {
|
||||
return indent + msg.map(function (item) {
|
||||
switch (item[0]) {
|
||||
case 'child':
|
||||
var comment = item[1][0]
|
||||
var child = item[1].slice(1)
|
||||
return tapFormat([comment], '') + tapFormat(child, ' ')
|
||||
|
||||
case 'version':
|
||||
return 'TAP version ' + item[1] + '\n'
|
||||
|
||||
case 'plan':
|
||||
var p = item[1].start + '..' + item[1].end
|
||||
if (item[1].comment)
|
||||
p += ' # ' + item[1].comment
|
||||
return p + '\n'
|
||||
|
||||
case 'pragma':
|
||||
return 'pragma ' + (item[2] ? '+' : '-') + item[1] + '\n'
|
||||
|
||||
case 'bailout':
|
||||
var r = item[1] === true ? '' : (' ' + item[1])
|
||||
return 'Bail out!' + r + '\n'
|
||||
|
||||
case 'assert':
|
||||
var res = item[1]
|
||||
return (res.ok ? '' : 'not ') + 'ok ' + res.id +
|
||||
(res.name ? ' - ' + res.name.replace(/ \{$/, '') : '') +
|
||||
(res.skip ? ' # SKIP' +
|
||||
(res.skip === true ? '' : ' ' + res.skip) : '') +
|
||||
(res.todo ? ' # TODO' +
|
||||
(res.todo === true ? '' : ' ' + res.todo) : '') +
|
||||
(res.time ? ' # time=' + res.time + 'ms' : '') +
|
||||
'\n' +
|
||||
(res.diag ?
|
||||
' ---\n ' +
|
||||
yaml.safeDump(res.diag).split('\n').join('\n ').trim() +
|
||||
'\n ...\n'
|
||||
: '')
|
||||
|
||||
case 'extra':
|
||||
case 'comment':
|
||||
return item[1]
|
||||
}
|
||||
}).join('').split('\n').join('\n' + indent).trim() + '\n'
|
||||
}
|
||||
|
||||
function format (msg) {
|
||||
if (json === 'tap')
|
||||
return tapFormat(msg, '')
|
||||
else if (json !== null)
|
||||
return JSON.stringify(msg, null, +json)
|
||||
else
|
||||
return util.inspect(events, null, Infinity)
|
||||
}
|
||||
|
||||
var options = {
|
||||
bail: bail,
|
||||
preserveWhitespace: preserveWhitespace,
|
||||
omitVersion: omitVersion
|
||||
}
|
||||
|
||||
var parser = new Parser(options)
|
||||
var events = etoa(parser, [ 'pipe', 'unpipe', 'prefinish', 'finish', 'line' ])
|
||||
|
||||
process.stdin.pipe(parser)
|
||||
if (json === 'lines')
|
||||
parser.on('line', function (l) {
|
||||
process.stdout.write(l)
|
||||
})
|
||||
else
|
||||
process.on('exit', function () {
|
||||
console.log(format(events))
|
||||
if (!parser.ok)
|
||||
process.exit(1)
|
||||
})
|
||||
15
static/js/ketcher2/node_modules/tap-parser/bin/usage.txt
generated
vendored
Normal file
15
static/js/ketcher2/node_modules/tap-parser/bin/usage.txt
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
usage: tap-parser OPTIONS
|
||||
|
||||
Parse TAP from INPUT. If there are any failures, exits with
|
||||
a non-zero status code.
|
||||
|
||||
OPTIONS are:
|
||||
|
||||
-i, --input Read from INPUT. Default: stdin.
|
||||
-o, --output Write to OUTPUT. Default: stdout.
|
||||
-r, --results Print results as json. Otherwise pass INPUT
|
||||
through to OUTPUT.
|
||||
|
||||
-h, --help Show this help message.
|
||||
-v, --version Print the current version of tap-parser.
|
||||
|
||||
972
static/js/ketcher2/node_modules/tap-parser/index.js
generated
vendored
Normal file
972
static/js/ketcher2/node_modules/tap-parser/index.js
generated
vendored
Normal file
@ -0,0 +1,972 @@
|
||||
// Transforms a stream of TAP into a stream of result objects
|
||||
// and string comments. Emits "results" event with summary.
|
||||
var Writable = require('stream').Writable
|
||||
/* istanbul ignore if */
|
||||
if (!Writable) {
|
||||
try {
|
||||
Writable = require('readable-stream').Writable
|
||||
} catch (er) {
|
||||
throw new Error('Please install "readable-stream" to use this module ' +
|
||||
'with Node.js v0.8 and before')
|
||||
}
|
||||
}
|
||||
|
||||
var yaml = require('js-yaml')
|
||||
var util = require('util')
|
||||
var assert = require('assert')
|
||||
|
||||
util.inherits(Parser, Writable)
|
||||
|
||||
module.exports = Parser
|
||||
|
||||
// every line outside of a yaml block is one of these things, or
|
||||
// a comment, or garbage.
|
||||
var lineTypes = {
|
||||
testPoint: /^(not )?ok(?: ([0-9]+))?(?:(?: -)?( .*?))?(\{?)\n$/,
|
||||
pragma: /^pragma ([+-])([a-z]+)\n$/,
|
||||
bailout: /^bail out!(.*)\n$/i,
|
||||
version: /^TAP version ([0-9]+)\n$/i,
|
||||
childVersion: /^( )+TAP version ([0-9]+)\n$/i,
|
||||
plan: /^([0-9]+)\.\.([0-9]+)(?:\s+(?:#\s*(.*)))?\n$/,
|
||||
subtest: /^# Subtest(?:: (.*))?\n$/,
|
||||
subtestIndent: /^ # Subtest(?:: (.*))?\n$/,
|
||||
comment: /^\s*#.*\n$/
|
||||
}
|
||||
|
||||
var lineTypeNames = Object.keys(lineTypes)
|
||||
|
||||
function lineType (line) {
|
||||
for (var t in lineTypes) {
|
||||
var match = line.match(lineTypes[t])
|
||||
if (match)
|
||||
return [t, match]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function parseDirective (line) {
|
||||
if (!line.trim())
|
||||
return false
|
||||
|
||||
line = line.replace(/\{\s*$/, '').trim()
|
||||
var time = line.match(/^time=((?:[1-9][0-9]*|0)(?:\.[0-9]+)?)(ms|s)$/i)
|
||||
if (time) {
|
||||
var n = +time[1]
|
||||
if (time[2] === 's') {
|
||||
// JS does weird things with floats. Round it off a bit.
|
||||
n *= 1000000
|
||||
n = Math.round(n)
|
||||
n /= 1000
|
||||
}
|
||||
return [ 'time', n ]
|
||||
}
|
||||
|
||||
var type = line.match(/^(todo|skip)\b/i)
|
||||
if (!type)
|
||||
return false
|
||||
|
||||
return [ type[1].toLowerCase(), line.substr(type[1].length).trim() || true ]
|
||||
}
|
||||
|
||||
function Result (parsed, count) {
|
||||
var ok = !parsed[1]
|
||||
var id = +(parsed[2] || count + 1)
|
||||
var buffered = parsed[4]
|
||||
this.ok = ok
|
||||
this.id = id
|
||||
|
||||
var rest = parsed[3] || ''
|
||||
var name
|
||||
rest = rest.replace(/([^\\]|^)((?:\\\\)*)#/g, '$1\n$2').split('\n')
|
||||
name = rest.shift()
|
||||
rest = rest.filter(function (r) { return r.trim() }).join('#')
|
||||
|
||||
// now, let's see if there's a directive in there.
|
||||
var dir = parseDirective(rest.trim())
|
||||
if (!dir)
|
||||
name += (rest ? '#' + rest : '') + buffered
|
||||
else {
|
||||
// handle buffered subtests with todo/skip on them, like
|
||||
// ok 1 - bar # todo foo {\n
|
||||
var dirKey = dir[0]
|
||||
var dirValue = dir[1]
|
||||
this[dirKey] = dirValue
|
||||
}
|
||||
|
||||
if (/\{\s*$/.test(name)) {
|
||||
name = name.replace(/\{\s*$/, '')
|
||||
buffered = '{'
|
||||
}
|
||||
|
||||
if (buffered === '{')
|
||||
this.buffered = true
|
||||
|
||||
if (name)
|
||||
this.name = name.trim()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
function Parser (options, onComplete) {
|
||||
if (typeof options === 'function') {
|
||||
onComplete = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
if (!(this instanceof Parser))
|
||||
return new Parser(options, onComplete)
|
||||
|
||||
options = options || {}
|
||||
if (onComplete)
|
||||
this.on('complete', onComplete)
|
||||
|
||||
this.comments = []
|
||||
this.results = null
|
||||
this.braceLevel = null
|
||||
this.parent = options.parent || null
|
||||
this.failures = []
|
||||
if (options.passes)
|
||||
this.passes = []
|
||||
this.level = options.level || 0
|
||||
Writable.call(this)
|
||||
this.buffer = ''
|
||||
this.bail = !!options.bail
|
||||
this.bailingOut = false
|
||||
this.bailedOut = false
|
||||
this.syntheticBailout = false
|
||||
this.syntheticPlan = false
|
||||
this.omitVersion = !!options.omitVersion
|
||||
this.planStart = -1
|
||||
this.planEnd = -1
|
||||
this.planComment = ''
|
||||
this.yamlish = ''
|
||||
this.yind = ''
|
||||
this.child = null
|
||||
this.current = null
|
||||
this.maybeSubtest = null
|
||||
this.extraQueue = []
|
||||
this.buffered = options.buffered || null
|
||||
this.aborted = false
|
||||
this.preserveWhitespace = options.preserveWhitespace || false
|
||||
|
||||
this.count = 0
|
||||
this.pass = 0
|
||||
this.fail = 0
|
||||
this.todo = 0
|
||||
this.skip = 0
|
||||
this.ok = true
|
||||
|
||||
this.strict = options.strict || false
|
||||
this.pragmas = { strict: this.strict }
|
||||
|
||||
this.postPlan = false
|
||||
}
|
||||
|
||||
Parser.prototype.tapError = function (error, line) {
|
||||
if (line)
|
||||
this.emit('line', line)
|
||||
this.ok = false
|
||||
this.fail ++
|
||||
if (typeof error === 'string') {
|
||||
error = {
|
||||
tapError: error
|
||||
}
|
||||
}
|
||||
this.failures.push(error)
|
||||
}
|
||||
|
||||
Parser.prototype.parseTestPoint = function (testPoint, line) {
|
||||
this.emitResult()
|
||||
if (this.bailedOut)
|
||||
return
|
||||
|
||||
this.emit('line', line)
|
||||
var res = new Result(testPoint, this.count)
|
||||
if (this.planStart !== -1) {
|
||||
var lessThanStart = +res.id < this.planStart
|
||||
var greaterThanEnd = +res.id > this.planEnd
|
||||
if (lessThanStart || greaterThanEnd) {
|
||||
if (lessThanStart)
|
||||
res.tapError = 'id less than plan start'
|
||||
else
|
||||
res.tapError = 'id greater than plan end'
|
||||
res.plan = { start: this.planStart, end: this.planEnd }
|
||||
this.tapError(res)
|
||||
}
|
||||
}
|
||||
|
||||
if (res.id) {
|
||||
if (!this.first || res.id < this.first)
|
||||
this.first = res.id
|
||||
if (!this.last || res.id > this.last)
|
||||
this.last = res.id
|
||||
}
|
||||
|
||||
if (!res.skip && !res.todo)
|
||||
this.ok = this.ok && res.ok
|
||||
|
||||
// hold onto it, because we might get yamlish diagnostics
|
||||
this.current = res
|
||||
}
|
||||
|
||||
Parser.prototype.nonTap = function (data, didLine) {
|
||||
if (this.bailingOut && /^( {4})*\}\n$/.test(data))
|
||||
return
|
||||
|
||||
if (this.strict) {
|
||||
var err = {
|
||||
tapError: 'Non-TAP data encountered in strict mode',
|
||||
data: data
|
||||
}
|
||||
this.tapError(err)
|
||||
if (this.parent)
|
||||
this.parent.tapError(err)
|
||||
}
|
||||
|
||||
// emit each line, then the extra as a whole
|
||||
if (!didLine)
|
||||
data.split('\n').slice(0, -1).forEach(function (line) {
|
||||
line += '\n'
|
||||
if (this.current || this.extraQueue.length)
|
||||
this.extraQueue.push(['line', line])
|
||||
else
|
||||
this.emit('line', line)
|
||||
}, this)
|
||||
|
||||
if (this.current || this.extraQueue.length)
|
||||
this.extraQueue.push(['extra', data])
|
||||
else
|
||||
this.emit('extra', data)
|
||||
}
|
||||
|
||||
Parser.prototype.plan = function (start, end, comment, line) {
|
||||
// not allowed to have more than one plan
|
||||
if (this.planStart !== -1) {
|
||||
this.nonTap(line)
|
||||
return
|
||||
}
|
||||
|
||||
// can't put a plan in a child.
|
||||
if (this.child || this.yind) {
|
||||
this.nonTap(line)
|
||||
return
|
||||
}
|
||||
|
||||
this.emitResult()
|
||||
if (this.bailedOut)
|
||||
return
|
||||
|
||||
// 1..0 is a special case. Otherwise, end must be >= start
|
||||
if (end < start && end !== 0 && start !== 1) {
|
||||
if (this.strict)
|
||||
this.tapError({
|
||||
tapError: 'plan end cannot be less than plan start',
|
||||
plan: {
|
||||
start: start,
|
||||
end: end
|
||||
}
|
||||
}, line)
|
||||
else
|
||||
this.nonTap(line)
|
||||
return
|
||||
}
|
||||
|
||||
this.planStart = start
|
||||
this.planEnd = end
|
||||
var p = { start: start, end: end }
|
||||
if (comment)
|
||||
this.planComment = p.comment = comment
|
||||
|
||||
// This means that the plan is coming at the END of all the tests
|
||||
// Plans MUST be either at the beginning or the very end. We treat
|
||||
// plans like '1..0' the same, since they indicate that no tests
|
||||
// will be coming.
|
||||
if (this.count !== 0 || this.planEnd === 0)
|
||||
this.postPlan = true
|
||||
|
||||
this.emit('line', line)
|
||||
this.emit('plan', p)
|
||||
}
|
||||
|
||||
Parser.prototype.resetYamlish = function () {
|
||||
this.yind = ''
|
||||
this.yamlish = ''
|
||||
}
|
||||
|
||||
// that moment when you realize it's not what you thought it was
|
||||
Parser.prototype.yamlGarbage = function () {
|
||||
var yamlGarbage = this.yind + '---\n' + this.yamlish
|
||||
this.emitResult()
|
||||
if (this.bailedOut)
|
||||
return
|
||||
this.nonTap(yamlGarbage, true)
|
||||
}
|
||||
|
||||
Parser.prototype.yamlishLine = function (line) {
|
||||
if (line === this.yind + '...\n') {
|
||||
// end the yaml block
|
||||
this.processYamlish()
|
||||
} else {
|
||||
this.yamlish += line
|
||||
}
|
||||
}
|
||||
|
||||
Parser.prototype.processYamlish = function () {
|
||||
var yamlish = this.yamlish
|
||||
this.resetYamlish()
|
||||
|
||||
try {
|
||||
var diags = yaml.safeLoad(yamlish)
|
||||
} catch (er) {
|
||||
this.nonTap(this.yind + '---\n' + yamlish + this.yind + '...\n', true)
|
||||
return
|
||||
}
|
||||
|
||||
this.current.diag = diags
|
||||
// we still don't emit the result here yet, to support diags
|
||||
// that come ahead of buffered subtests.
|
||||
}
|
||||
|
||||
Parser.prototype.write = function (chunk, encoding, cb) {
|
||||
if (this.aborted)
|
||||
return
|
||||
|
||||
if (typeof encoding === 'string' && encoding !== 'utf8')
|
||||
chunk = new Buffer(chunk, encoding)
|
||||
|
||||
if (Buffer.isBuffer(chunk))
|
||||
chunk += ''
|
||||
|
||||
if (typeof encoding === 'function') {
|
||||
cb = encoding
|
||||
encoding = null
|
||||
}
|
||||
|
||||
this.buffer += chunk
|
||||
do {
|
||||
var match = this.buffer.match(/^.*\r?\n/)
|
||||
if (!match)
|
||||
break
|
||||
|
||||
this.buffer = this.buffer.substr(match[0].length)
|
||||
this.parse(match[0])
|
||||
} while (this.buffer.length)
|
||||
|
||||
if (cb)
|
||||
process.nextTick(cb)
|
||||
return true
|
||||
}
|
||||
|
||||
Parser.prototype.end = function (chunk, encoding, cb) {
|
||||
if (chunk) {
|
||||
if (typeof encoding === 'function') {
|
||||
cb = encoding
|
||||
encoding = null
|
||||
}
|
||||
this.write(chunk, encoding)
|
||||
}
|
||||
|
||||
if (this.buffer)
|
||||
this.write('\n')
|
||||
|
||||
// if we have yamlish, means we didn't finish with a ...
|
||||
if (this.yamlish)
|
||||
this.yamlGarbage()
|
||||
|
||||
this.emitResult()
|
||||
|
||||
if (this.syntheticBailout && this.level === 0) {
|
||||
var reason = this.bailedOut
|
||||
if (reason === true)
|
||||
reason = ''
|
||||
else
|
||||
reason = ' ' + reason
|
||||
this.emit('line', 'Bail out!' + reason + '\n')
|
||||
}
|
||||
|
||||
var skipAll
|
||||
|
||||
if (this.planEnd === 0 && this.planStart === 1) {
|
||||
skipAll = true
|
||||
if (this.count === 0) {
|
||||
this.ok = true
|
||||
} else {
|
||||
this.tapError('Plan of 1..0, but test points encountered')
|
||||
}
|
||||
} else if (!this.bailedOut && this.planStart === -1) {
|
||||
if (this.count === 0 && !this.syntheticPlan) {
|
||||
this.syntheticPlan = true
|
||||
this.plan(1, 0, 'no tests found', '1..0 # no tests found\n')
|
||||
skipAll = true
|
||||
} else {
|
||||
this.tapError('no plan')
|
||||
}
|
||||
} else if (this.ok && this.count !== (this.planEnd - this.planStart + 1)) {
|
||||
this.tapError('incorrect number of tests')
|
||||
}
|
||||
|
||||
if (this.ok && !skipAll && this.first !== this.planStart) {
|
||||
this.tapError('first test id does not match plan start')
|
||||
}
|
||||
|
||||
if (this.ok && !skipAll && this.last !== this.planEnd) {
|
||||
this.tapError('last test id does not match plan end')
|
||||
}
|
||||
|
||||
Writable.prototype.end.call(this, null, null, cb)
|
||||
this.emitComplete(skipAll)
|
||||
}
|
||||
|
||||
Parser.prototype.emitComplete = function (skipAll) {
|
||||
if (!this.results) {
|
||||
var res = this.results = new FinalResults(!!skipAll, this)
|
||||
|
||||
if (!res.bailout) {
|
||||
// comment a bit at the end so we know what happened.
|
||||
// but don't repeat these comments if they're already present.
|
||||
if (res.plan.end !== res.count)
|
||||
this.emitComment('test count(' + res.count +
|
||||
') != plan(' + res.plan.end + ')', false, true)
|
||||
|
||||
if (res.fail > 0 && !res.ok)
|
||||
this.emitComment('failed ' + res.fail +
|
||||
(res.count > 1 ? ' of ' + res.count + ' tests'
|
||||
: ' test'),
|
||||
false, true)
|
||||
|
||||
if (res.todo > 0)
|
||||
this.emitComment('todo: ' + res.todo, false, true)
|
||||
|
||||
if (res.skip > 0)
|
||||
this.emitComment('skip: ' + res.skip, false, true)
|
||||
}
|
||||
|
||||
this.emit('complete', this.results)
|
||||
}
|
||||
}
|
||||
|
||||
function FinalResults (skipAll, self) {
|
||||
this.ok = self.ok
|
||||
this.count = self.count
|
||||
this.pass = self.pass
|
||||
this.fail = self.fail || 0
|
||||
this.bailout = self.bailedOut || false
|
||||
this.todo = self.todo || 0
|
||||
this.skip = skipAll ? self.count : self.skip || 0
|
||||
this.plan = new FinalPlan(skipAll, self)
|
||||
this.failures = self.failures
|
||||
if (self.passes)
|
||||
this.passes = self.passes
|
||||
}
|
||||
|
||||
function FinalPlan (skipAll, self) {
|
||||
this.start = self.planStart === -1 ? null : self.planStart
|
||||
this.end = self.planStart === -1 ? null : self.planEnd
|
||||
this.skipAll = skipAll
|
||||
this.skipReason = skipAll ? self.planComment : ''
|
||||
this.comment = self.planComment || ''
|
||||
}
|
||||
|
||||
Parser.prototype.version = function (version, line) {
|
||||
// If version is specified, must be at the very beginning.
|
||||
if (version >= 13 &&
|
||||
this.planStart === -1 &&
|
||||
this.count === 0 &&
|
||||
!this.current) {
|
||||
this.emit('line', line)
|
||||
this.emit('version', version)
|
||||
} else
|
||||
this.nonTap(line)
|
||||
}
|
||||
|
||||
Parser.prototype.pragma = function (key, value, line) {
|
||||
// can't put a pragma in a child or yaml block
|
||||
if (this.child) {
|
||||
this.nonTap(line)
|
||||
return
|
||||
}
|
||||
|
||||
this.emitResult()
|
||||
if (this.bailedOut)
|
||||
return
|
||||
// only the 'strict' pragma is currently relevant
|
||||
if (key === 'strict') {
|
||||
this.strict = value
|
||||
}
|
||||
this.pragmas[key] = value
|
||||
this.emit('line', line)
|
||||
this.emit('pragma', key, value)
|
||||
}
|
||||
|
||||
Parser.prototype.bailout = function (reason, synthetic) {
|
||||
this.syntheticBailout = synthetic
|
||||
|
||||
if (this.bailingOut)
|
||||
return
|
||||
|
||||
// Guard because emitting a result can trigger a forced bailout
|
||||
// if the harness decides that failures should be bailouts.
|
||||
this.bailingOut = reason || true
|
||||
|
||||
if (!synthetic)
|
||||
this.emitResult()
|
||||
else
|
||||
this.current = null
|
||||
|
||||
this.bailedOut = this.bailingOut
|
||||
this.ok = false
|
||||
if (!synthetic) {
|
||||
// synthetic bailouts get emitted on end
|
||||
var line = 'Bail out!'
|
||||
if (reason)
|
||||
line += ' ' + reason
|
||||
this.emit('line', line + '\n')
|
||||
}
|
||||
this.emit('bailout', reason)
|
||||
if (this.parent) {
|
||||
this.end()
|
||||
this.parent.bailout(reason, true)
|
||||
}
|
||||
}
|
||||
|
||||
Parser.prototype.clearExtraQueue = function () {
|
||||
for (var c = 0; c < this.extraQueue.length; c++) {
|
||||
this.emit(this.extraQueue[c][0], this.extraQueue[c][1])
|
||||
}
|
||||
this.extraQueue.length = 0
|
||||
}
|
||||
|
||||
Parser.prototype.endChild = function () {
|
||||
if (this.child) {
|
||||
this.child.end()
|
||||
this.child = null
|
||||
}
|
||||
}
|
||||
|
||||
Parser.prototype.emitResult = function () {
|
||||
if (this.bailedOut)
|
||||
return
|
||||
|
||||
this.endChild()
|
||||
this.resetYamlish()
|
||||
|
||||
if (!this.current)
|
||||
return this.clearExtraQueue()
|
||||
|
||||
var res = this.current
|
||||
this.current = null
|
||||
|
||||
this.count++
|
||||
if (res.ok) {
|
||||
this.pass++
|
||||
if (this.passes)
|
||||
this.passes.push(res)
|
||||
} else {
|
||||
this.fail++
|
||||
if (!res.todo && !res.skip) {
|
||||
this.ok = false
|
||||
this.failures.push(res)
|
||||
}
|
||||
}
|
||||
|
||||
if (res.skip)
|
||||
this.skip++
|
||||
|
||||
if (res.todo)
|
||||
this.todo++
|
||||
|
||||
this.emit('assert', res)
|
||||
if (this.bail && !res.ok && !res.todo && !res.skip && !this.bailingOut) {
|
||||
this.maybeChild = null
|
||||
var ind = new Array(this.level + 1).join(' ')
|
||||
for (var p = this; p.parent; p = p.parent);
|
||||
var bailName = res.name ? ' # ' + res.name : ''
|
||||
p.parse(ind + 'Bail out!' + bailName + '\n')
|
||||
}
|
||||
this.clearExtraQueue()
|
||||
}
|
||||
|
||||
// TODO: We COULD say that any "relevant tap" line that's indented
|
||||
// by 4 spaces starts a child test, and just call it 'unnamed' if
|
||||
// it does not have a prefix comment. In that case, any number of
|
||||
// 4-space indents can be plucked off to try to find a relevant
|
||||
// TAP line type, and if so, start the unnamed child.
|
||||
Parser.prototype.startChild = function (line) {
|
||||
var maybeBuffered = this.current && this.current.buffered
|
||||
var unindentStream = !maybeBuffered && this.maybeChild
|
||||
var indentStream = !maybeBuffered && !unindentStream &&
|
||||
lineTypes.subtestIndent.test(line)
|
||||
var unnamed = !maybeBuffered && !unindentStream && !indentStream
|
||||
|
||||
// If we have any other result waiting in the wings, we need to emit
|
||||
// that now. A buffered test emits its test point at the *end* of
|
||||
// the child subtest block, so as to match streamed test semantics.
|
||||
if (!maybeBuffered)
|
||||
this.emitResult()
|
||||
|
||||
if (this.bailedOut)
|
||||
return
|
||||
|
||||
this.child = new Parser({
|
||||
bail: this.bail,
|
||||
parent: this,
|
||||
level: this.level + 1,
|
||||
buffered: maybeBuffered,
|
||||
preserveWhitespace: this.preserveWhitespace,
|
||||
omitVersion: true,
|
||||
strict: this.strict
|
||||
})
|
||||
|
||||
var self = this
|
||||
this.child.on('complete', function (results) {
|
||||
if (!results.ok)
|
||||
self.ok = false
|
||||
})
|
||||
|
||||
this.child.on('line', function (l) {
|
||||
if (this.syntheticPlan)
|
||||
return
|
||||
|
||||
if (l.trim() || self.preserveWhitespace)
|
||||
l = ' ' + l
|
||||
self.emit('line', l)
|
||||
})
|
||||
|
||||
// Canonicalize the parsing result of any kind of subtest
|
||||
// if it's a buffered subtest or a non-indented Subtest directive,
|
||||
// then synthetically emit the Subtest comment
|
||||
line = line.substr(4)
|
||||
var subtestComment
|
||||
if (indentStream) {
|
||||
subtestComment = line
|
||||
line = null
|
||||
} else if (maybeBuffered) {
|
||||
subtestComment = '# Subtest: ' + this.current.name + '\n'
|
||||
} else {
|
||||
subtestComment = this.maybeChild || '# Subtest: (anonymous)\n'
|
||||
}
|
||||
|
||||
this.maybeChild = null
|
||||
this.child.name = subtestComment.substr('# Subtest: '.length).trim()
|
||||
|
||||
// at some point, we may wish to move 100% to preferring
|
||||
// the Subtest comment on the parent level. If so, uncomment
|
||||
// this line, and remove the child.emitComment below.
|
||||
// this.emit('comment', subtestComment)
|
||||
if (!this.child.buffered)
|
||||
this.emit('line', subtestComment)
|
||||
this.emit('child', this.child)
|
||||
this.child.emitComment(subtestComment, true)
|
||||
if (line)
|
||||
this.child.parse(line)
|
||||
}
|
||||
|
||||
Parser.prototype.abort = function (message, extra) {
|
||||
if (this.child) {
|
||||
var b = this.child.buffered
|
||||
this.child.abort(message, extra)
|
||||
extra = null
|
||||
if (b)
|
||||
this.write('\n}\n')
|
||||
}
|
||||
|
||||
var dump
|
||||
if (extra && Object.keys(extra).length) {
|
||||
try {
|
||||
dump = yaml.safeDump(extra).trimRight()
|
||||
} catch (er) {}
|
||||
}
|
||||
|
||||
var y
|
||||
if (dump)
|
||||
y = ' ---\n ' + dump.split('\n').join('\n ') + '\n ...\n'
|
||||
else
|
||||
y = '\n'
|
||||
var n = (this.count || 0) + 1
|
||||
if (this.current)
|
||||
n += 1
|
||||
|
||||
if (this.planEnd !== -1 && this.planEnd < n && this.parent) {
|
||||
// skip it, let the parent do this.
|
||||
this.aborted = true
|
||||
return
|
||||
}
|
||||
|
||||
var ind = '' // new Array(this.level + 1).join(' ')
|
||||
message = message.replace(/[\n\r\s\t]/g, ' ')
|
||||
var point = '\nnot ok ' + n + ' - ' + message + '\n' + y
|
||||
|
||||
if (this.planEnd === -1)
|
||||
point += '1..' + n + '\n'
|
||||
|
||||
this.write(point)
|
||||
this.aborted = true
|
||||
this.end()
|
||||
}
|
||||
|
||||
Parser.prototype.emitComment = function (line, skipLine, noDuplicate) {
|
||||
if (line.trim().charAt(0) !== '#')
|
||||
line = '# ' + line
|
||||
|
||||
if (line.slice(-1) !== '\n')
|
||||
line += '\n'
|
||||
|
||||
if (noDuplicate && this.comments.indexOf(line) !== -1)
|
||||
return
|
||||
|
||||
this.comments.push(line)
|
||||
if (this.current || this.extraQueue.length) {
|
||||
// no way to get here with skipLine being true
|
||||
this.extraQueue.push(['line', line])
|
||||
this.extraQueue.push(['comment', line])
|
||||
} else {
|
||||
if (!skipLine)
|
||||
this.emit('line', line)
|
||||
this.emit('comment', line)
|
||||
}
|
||||
}
|
||||
|
||||
Parser.prototype.parse = function (line) {
|
||||
// normalize line endings
|
||||
line = line.replace(/\r\n$/, '\n')
|
||||
|
||||
// sometimes empty lines get trimmed, but are still part of
|
||||
// a subtest or a yaml block. Otherwise, nothing to parse!
|
||||
if (line === '\n') {
|
||||
if (this.child)
|
||||
line = ' ' + line
|
||||
else if (this.yind)
|
||||
line = this.yind + line
|
||||
}
|
||||
|
||||
// If we're bailing out, then the only thing we want to see is the
|
||||
// end of a buffered child test. Anything else should be ignored.
|
||||
// But! if we're bailing out a nested child, and ANOTHER nested child
|
||||
// comes after that one, then we don't want the second child's } to
|
||||
// also show up, or it looks weird.
|
||||
if (this.bailingOut) {
|
||||
if (!/^\s*}\n$/.test(line))
|
||||
return
|
||||
else if (!this.braceLevel || line.length < this.braceLevel)
|
||||
this.braceLevel = line.length
|
||||
else
|
||||
return
|
||||
}
|
||||
|
||||
// This allows omitting even parsing the version if the test is
|
||||
// an indented child test. Several parsers get upset when they
|
||||
// see an indented version field.
|
||||
if (this.omitVersion && lineTypes.version.test(line) && !this.yind)
|
||||
return
|
||||
|
||||
// check to see if the line is indented.
|
||||
// if it is, then it's either a subtest, yaml, or garbage.
|
||||
var indent = line.match(/^[ \t]*/)[0]
|
||||
if (indent) {
|
||||
this.parseIndent(line, indent)
|
||||
return
|
||||
}
|
||||
|
||||
// In any case where we're going to emitResult, that can trigger
|
||||
// a bailout, so we need to only emit the line once we know that
|
||||
// isn't happening, to prevent cases where there's a bailout, and
|
||||
// then one more line of output. That'll also prevent the case
|
||||
// where the test point is emitted AFTER the line that follows it.
|
||||
|
||||
// buffered subtests must end with a }
|
||||
if (this.child && this.child.buffered && line === '}\n') {
|
||||
this.endChild()
|
||||
this.emit('line', line)
|
||||
this.emitResult()
|
||||
return
|
||||
}
|
||||
|
||||
// just a \n, emit only if we care about whitespace
|
||||
var validLine = this.preserveWhitespace || line.trim() || this.yind
|
||||
if (line === '\n')
|
||||
return validLine && this.emit('line', line)
|
||||
|
||||
// buffered subtest with diagnostics
|
||||
if (this.current && line === '{\n' &&
|
||||
!this.current.buffered &&
|
||||
!this.child) {
|
||||
this.emit('line', line)
|
||||
this.current.buffered = true
|
||||
return
|
||||
}
|
||||
|
||||
// now we know it's not indented, so if it's either valid tap
|
||||
// or garbage. Get the type of line.
|
||||
var type = lineType(line)
|
||||
if (!type) {
|
||||
this.nonTap(line)
|
||||
return
|
||||
}
|
||||
|
||||
if (type[0] === 'comment') {
|
||||
this.emitComment(line)
|
||||
return
|
||||
}
|
||||
|
||||
// if we have any yamlish, it's garbage now. We tolerate non-TAP and
|
||||
// comments in the midst of yaml (though, perhaps, that's questionable
|
||||
// behavior), but any actual TAP means that the yaml block was just
|
||||
// not valid.
|
||||
if (this.yind)
|
||||
this.yamlGarbage()
|
||||
|
||||
// If it's anything other than a comment or garbage, then any
|
||||
// maybeChild is just an unsatisfied promise.
|
||||
if (this.maybeChild) {
|
||||
this.emitComment(this.maybeChild)
|
||||
this.maybeChild = null
|
||||
}
|
||||
|
||||
// nothing but comments can come after a trailing plan
|
||||
if (this.postPlan) {
|
||||
this.nonTap(line)
|
||||
return
|
||||
}
|
||||
|
||||
// ok, now it's maybe a thing
|
||||
if (type[0] === 'bailout') {
|
||||
this.bailout(type[1][1].trim(), false)
|
||||
return
|
||||
}
|
||||
|
||||
if (type[0] === 'pragma') {
|
||||
var pragma = type[1]
|
||||
this.pragma(pragma[2], pragma[1] === '+', line)
|
||||
return
|
||||
}
|
||||
|
||||
if (type[0] === 'version') {
|
||||
var version = type[1]
|
||||
this.version(parseInt(version[1], 10), line)
|
||||
return
|
||||
}
|
||||
|
||||
if (type[0] === 'plan') {
|
||||
var plan = type[1]
|
||||
this.plan(+plan[1], +plan[2], (plan[3] || '').trim(), line)
|
||||
return
|
||||
}
|
||||
|
||||
// streamed subtests will end when this test point is emitted
|
||||
if (type[0] === 'testPoint') {
|
||||
// note: it's weird, but possible, to have a testpoint ending in
|
||||
// { before a streamed subtest which ends with a test point
|
||||
// instead of a }. In this case, the parser gets confused, but
|
||||
// also, even beginning to handle that means doing a much more
|
||||
// involved multi-line parse. By that point, the subtest block
|
||||
// has already been emitted as a 'child' event, so it's too late
|
||||
// to really do the optimal thing. The only way around would be
|
||||
// to buffer up everything and do a multi-line parse. This is
|
||||
// rare and weird, and a multi-line parse would be a bigger
|
||||
// rewrite, so I'm allowing it as it currently is.
|
||||
this.parseTestPoint(type[1], line)
|
||||
return
|
||||
}
|
||||
|
||||
// We already detected nontap up above, so the only case left
|
||||
// should be a `# Subtest:` comment. Ignore for coverage, but
|
||||
// include the error here just for good measure.
|
||||
/* istanbul ignore else */
|
||||
if (type[0] === 'subtest') {
|
||||
// this is potentially a subtest. Not indented.
|
||||
// hold until later.
|
||||
this.maybeChild = line
|
||||
} else {
|
||||
throw new Error('Unhandled case: ' + type[0])
|
||||
}
|
||||
}
|
||||
|
||||
Parser.prototype.parseIndent = function (line, indent) {
|
||||
// still belongs to the child, so pass it along.
|
||||
if (this.child && line.substr(0, 4) === ' ') {
|
||||
line = line.substr(4)
|
||||
this.child.write(line)
|
||||
return
|
||||
}
|
||||
|
||||
// one of:
|
||||
// - continuing yaml block
|
||||
// - starting yaml block
|
||||
// - ending yaml block
|
||||
// - body of a new child subtest that was previously introduced
|
||||
// - An indented subtest directive
|
||||
// - A comment, or garbage
|
||||
|
||||
// continuing/ending yaml block
|
||||
if (this.yind) {
|
||||
if (line.indexOf(this.yind) === 0) {
|
||||
this.emit('line', line)
|
||||
this.yamlishLine(line)
|
||||
return
|
||||
} else {
|
||||
// oops! that was not actually yamlish, I guess.
|
||||
// this is a case where the indent is shortened mid-yamlish block
|
||||
// treat existing yaml as garbage, continue parsing this line
|
||||
this.yamlGarbage()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// start a yaml block under a test point
|
||||
if (this.current && !this.yind && line === indent + '---\n') {
|
||||
this.yind = indent
|
||||
this.emit('line', line)
|
||||
return
|
||||
}
|
||||
|
||||
// at this point, not yamlish, and not an existing child test.
|
||||
// We may have already seen an unindented Subtest directive, or
|
||||
// a test point that ended in { indicating a buffered subtest
|
||||
// Child tests are always indented 4 spaces.
|
||||
if (line.substr(0, 4) === ' ') {
|
||||
if (this.maybeChild ||
|
||||
this.current && this.current.buffered ||
|
||||
lineTypes.subtestIndent.test(line)) {
|
||||
this.startChild(line)
|
||||
return
|
||||
}
|
||||
|
||||
// It's _something_ indented, if the indentation is divisible by
|
||||
// 4 spaces, and the result is actual TAP of some sort, then do
|
||||
// a child subtest for it as well.
|
||||
//
|
||||
// This will lead to some ambiguity in cases where there are multiple
|
||||
// levels of non-signaled subtests, but a Subtest comment in the
|
||||
// middle of them, which may or may not be considered "indented"
|
||||
// See the subtest-no-comment-mid-comment fixture for an example
|
||||
// of this. As it happens, the preference is towards an indented
|
||||
// Subtest comment as the interpretation, which is the only possible
|
||||
// way to resolve this, since otherwise there's no way to distinguish
|
||||
// between an anonymous subtest with a non-indented Subtest comment,
|
||||
// and an indented Subtest comment.
|
||||
var s = line.match(/( {4})+(.*\n)$/)
|
||||
if (s[2].charAt(0) !== ' ') {
|
||||
// integer number of indentations.
|
||||
var type = lineType(s[2])
|
||||
if (type) {
|
||||
if (type[0] === 'comment') {
|
||||
this.emit('line', line)
|
||||
this.emitComment(line)
|
||||
} else {
|
||||
// it's relevant! start as an "unnamed" child subtest
|
||||
this.startChild(line)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// at this point, it's either a non-subtest comment, or garbage.
|
||||
|
||||
if (lineTypes.comment.test(line)) {
|
||||
this.emitComment(line)
|
||||
return
|
||||
}
|
||||
|
||||
this.nonTap(line)
|
||||
}
|
||||
90
static/js/ketcher2/node_modules/tap-parser/package.json
generated
vendored
Normal file
90
static/js/ketcher2/node_modules/tap-parser/package.json
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
{
|
||||
"_from": "tap-parser@^5.3.1",
|
||||
"_id": "tap-parser@5.4.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-BIsIaGqv7uTQgTW1KLTMNPSEQf4zDDPgYOBRdgOfuB+JFOLRBfEu6cLa/KvMvmqggu1FKXDfitjLwsq4827RvA==",
|
||||
"_location": "/tap-parser",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "tap-parser@^5.3.1",
|
||||
"name": "tap-parser",
|
||||
"escapedName": "tap-parser",
|
||||
"rawSpec": "^5.3.1",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^5.3.1"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/tap",
|
||||
"/tap-mocha-reporter"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-5.4.0.tgz",
|
||||
"_shasum": "6907e89725d7b7fa6ae41ee2c464c3db43188aec",
|
||||
"_spec": "tap-parser@^5.3.1",
|
||||
"_where": "/home/manfred/enviPath/ketcher2/ketcher/node_modules/tap",
|
||||
"author": {
|
||||
"name": "James Halliday",
|
||||
"email": "mail@substack.net",
|
||||
"url": "http://substack.net"
|
||||
},
|
||||
"bin": {
|
||||
"tap-parser": "bin/cmd.js"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/substack/tap-parser/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"events-to-array": "^1.0.1",
|
||||
"js-yaml": "^3.2.7",
|
||||
"readable-stream": "^2"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "parse the test anything protocol",
|
||||
"devDependencies": {
|
||||
"glob": "^7.0.5",
|
||||
"tap": "^10.3.3"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"bin/cmd.js",
|
||||
"bin/usage.txt"
|
||||
],
|
||||
"homepage": "https://github.com/substack/tap-parser",
|
||||
"keywords": [
|
||||
"tap",
|
||||
"test",
|
||||
"parser"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"name": "tap-parser",
|
||||
"optionalDependencies": {
|
||||
"readable-stream": "^2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/substack/tap-parser.git"
|
||||
},
|
||||
"scripts": {
|
||||
"postpublish": "git push origin --all; git push origin --tags",
|
||||
"postversion": "npm publish",
|
||||
"preversion": "npm test",
|
||||
"regen-fixtures": "node scripts/generate-test.js test/fixtures/*.tap",
|
||||
"test": "tap test/*.js --100 -J"
|
||||
},
|
||||
"testling": {
|
||||
"files": "test/*.js",
|
||||
"browsers": [
|
||||
"ie/6..latest",
|
||||
"chrome/10",
|
||||
"chrome/latest",
|
||||
"firefox/3.5",
|
||||
"firefox/latest",
|
||||
"opera/latest",
|
||||
"safari/latest"
|
||||
]
|
||||
},
|
||||
"version": "5.4.0"
|
||||
}
|
||||
329
static/js/ketcher2/node_modules/tap-parser/readme.markdown
generated
vendored
Normal file
329
static/js/ketcher2/node_modules/tap-parser/readme.markdown
generated
vendored
Normal file
@ -0,0 +1,329 @@
|
||||
# tap-parser
|
||||
|
||||
parse the [test anything protocol](http://testanything.org/)
|
||||
|
||||
[](http://travis-ci.org/tapjs/tap-parser)
|
||||
|
||||
[](http://ci.testling.com/substack/tap-parser)
|
||||
|
||||
[](https://coveralls.io/github/tapjs/tap-parser?branch=master)
|
||||
|
||||
# example
|
||||
|
||||
``` js
|
||||
var parser = require('tap-parser');
|
||||
var p = parser(function (results) {
|
||||
console.dir(results);
|
||||
});
|
||||
|
||||
process.stdin.pipe(p);
|
||||
```
|
||||
|
||||
given some [TAP](http://testanything.org/)-formatted input:
|
||||
|
||||
```
|
||||
$ node test.js
|
||||
TAP version 13
|
||||
# beep
|
||||
ok 1 should be equal
|
||||
ok 2 should be equivalent
|
||||
# boop
|
||||
ok 3 should be equal
|
||||
ok 4 (unnamed assert)
|
||||
|
||||
1..4
|
||||
# tests 4
|
||||
# pass 4
|
||||
|
||||
# ok
|
||||
```
|
||||
|
||||
parse the output:
|
||||
|
||||
```
|
||||
$ node test.js | node parse.js
|
||||
{ ok: true, count: 4, pass: 4, plan: { start: 1, end: 4 } }
|
||||
```
|
||||
|
||||
# usage
|
||||
|
||||
This package also has a `tap-parser` command.
|
||||
|
||||
```
|
||||
Usage:
|
||||
tap-parser <options>
|
||||
|
||||
Parses TAP data from stdin, and outputs the parsed result
|
||||
in the format specified by the options. Default output is
|
||||
uses node's `util.format()` method.
|
||||
|
||||
Options:
|
||||
|
||||
-j [<indent>] | --json[=indent]
|
||||
Output event data as JSON with the specified indentation (default=2)
|
||||
|
||||
-t | --tap
|
||||
Output data as reconstituted TAP based on parsed results
|
||||
|
||||
-l | --lines
|
||||
Output each parsed line as it is recognized by the parser
|
||||
|
||||
-b | --bail
|
||||
Emit a `Bail out!` at the first failed test point encountered
|
||||
|
||||
-w | --ignore-all-whitespace
|
||||
Skip over blank lines outside of YAML blocks
|
||||
|
||||
-o | --omit-version
|
||||
Ignore the `TAP version 13` line at the start of tests
|
||||
```
|
||||
|
||||
# methods
|
||||
|
||||
``` js
|
||||
var parser = require('tap-parser')
|
||||
```
|
||||
|
||||
## var p = parser(options, cb)
|
||||
|
||||
Return a writable stream `p` that emits parse events.
|
||||
|
||||
If `cb` is given it will listen for the `'complete'` event.
|
||||
|
||||
If `options` is given, it may contain the following flags:
|
||||
|
||||
- `preserveWhitespace` boolean which is `false` by default and will
|
||||
cause the parser to emit `line` events even for lines containing
|
||||
only whitespace. (Whitespace lines in yaml blocks are always
|
||||
emitted, because whitespace is semantically relevant for yaml.)
|
||||
|
||||
- `strict` boolean which is `false` by default and causes the parser
|
||||
to treat non-TAP input as a failure. Strictness is heritable to
|
||||
child subtests. You can also turn strictness on or off by using the
|
||||
`pragma +strict` line in the TAP data to turn strictness on, or
|
||||
`pragma -strict` to turn strictness off.
|
||||
|
||||
- `bail` boolean which is `false` by default and will cause the parser
|
||||
to bail out (including emitting a synthetic `Bail out!` line)
|
||||
whenever a failed test point is encountered.
|
||||
|
||||
- `omitVersion` boolean which is `false` by default and will cause the
|
||||
parser to ignore `TAP version 13` lines. Version lines in subtests
|
||||
cause problems with some parsers, so they are always ignored.
|
||||
|
||||
- `passes` boolean which is false by default and will add "passes" property for that contains the result of all passed tests
|
||||
|
||||
The `parent`, `level` and `buffered` options are reserved for internal
|
||||
use.
|
||||
|
||||
# events
|
||||
|
||||
## p.on('complete', function (results) {})
|
||||
|
||||
The `results` object contains a summary of the number of tests
|
||||
skipped, failed, passed, etc., as well as a boolean `ok` member which
|
||||
is true if and only if the planned test were all found, and either
|
||||
"ok" or marked as "TODO".
|
||||
|
||||
## p.on('line', function (line) {})
|
||||
|
||||
As each line of input is parsed, a `line` event is emitted.
|
||||
|
||||
"Synthetic" line events will be emitted to support the `bail`
|
||||
behavior, and to inject `1..0` plan lines in subtests that have no
|
||||
test points. They can be used as a sort of "passthrough stream" to
|
||||
sanitize and filter a TAP stream, with the caveat that, while `line`
|
||||
events will be semantically equivalent to the TAP input, they will not
|
||||
be a perfect replica of the input.
|
||||
|
||||
## p.on('assert', function (assert) {})
|
||||
|
||||
Every `/^(not )?ok\b/` line will emit an `'assert'` event.
|
||||
|
||||
Every `assert` object has these keys:
|
||||
|
||||
* `assert.ok` - true if the assertion succeeded, false if failed
|
||||
* `assert.id` - the assertion number
|
||||
* `assert.name` - optional short description of the assertion
|
||||
|
||||
and may also have
|
||||
|
||||
* `assert.todo` - optional description of why the assertion failure is
|
||||
not a problem. (Boolean `true` if no explaination provided)
|
||||
* `assert.skip` - optional description of why this assertion was
|
||||
skipped (boolean `true` if no explanation provided)
|
||||
* `assert.diag` - a diagnostic object with additional information
|
||||
about the test point.
|
||||
|
||||
## p.on('comment', function (comment) {})
|
||||
|
||||
Every `/^# (.+)/` line will emit the string contents of `comment`.
|
||||
|
||||
## p.on('plan', function (plan) {})
|
||||
|
||||
Every `/^\d+\.\.\d+/` line emits a `'plan'` event for the test numbers
|
||||
`plan.start` through `plan.end`, inclusive.
|
||||
|
||||
If the test is [completely
|
||||
skipped](http://podwiki.hexten.net/TAP/TAP.html?page=TAP#Skippingeverything)
|
||||
the result will look like
|
||||
|
||||
```
|
||||
{ ok: true,
|
||||
count: 0,
|
||||
pass: 0,
|
||||
plan:
|
||||
{ start: 1,
|
||||
end: 0,
|
||||
skipAll: true,
|
||||
skipReason: 'This code has no seat belt' } }
|
||||
```
|
||||
|
||||
## p.on('version', function (version) {})
|
||||
|
||||
A `/^TAP version (\d+)/` line emits a `'version'` event with a version
|
||||
number or string.
|
||||
|
||||
## p.on('bailout', function (reason) {})
|
||||
|
||||
A `bail out!` line will cause the parser to completely stop doing
|
||||
anything. Child parser bailouts will bail out their parents as well.
|
||||
|
||||
## p.on('child', function (childParser) {})
|
||||
|
||||
If a child test set is embedded in the stream like this:
|
||||
|
||||
```
|
||||
TAP Version 13
|
||||
1..2
|
||||
# nesting
|
||||
1..2
|
||||
ok 1 - true is ok
|
||||
ok 2 - doag is also okay
|
||||
ok 1 - nesting
|
||||
ok 2 - second
|
||||
```
|
||||
|
||||
then the child stream will be parsed and events will be raised on the
|
||||
`childParser` object.
|
||||
|
||||
Since TAP streams with child tests *must* follow child test sets
|
||||
with a pass or fail assert based on the child test's results, failing
|
||||
to handle child tests should always result in the same end result.
|
||||
However, additional information from those child tests will obviously
|
||||
be lost.
|
||||
|
||||
See `Subtests` below for more information on which sorts of subtest
|
||||
formats are supported by this parser.
|
||||
|
||||
## p.on('extra', function (extra) {})
|
||||
|
||||
All other lines will trigger an `'extra'` event with the line text.
|
||||
|
||||
# install
|
||||
|
||||
With [npm](https://npmjs.org) do:
|
||||
|
||||
```
|
||||
npm install tap-parser
|
||||
```
|
||||
|
||||
You can use [browserify](http://browserify.org) to `require('tap-parser')` in
|
||||
the browser.
|
||||
|
||||
# license
|
||||
|
||||
MIT
|
||||
|
||||
# subtests
|
||||
|
||||
5 flavors of Subtests are suppored by this parser.
|
||||
|
||||
1. Unadorned.
|
||||
Indented TAP data with no comment, followed by a test
|
||||
point at the parent level.
|
||||
|
||||
```
|
||||
ok 1
|
||||
1..1
|
||||
ok 1 - child test
|
||||
1..1
|
||||
```
|
||||
|
||||
2. Indented comment.
|
||||
An indented `# Subtest: <name>` comment, followed by indented TAP
|
||||
data, and then a not-indented test point with a matching name.
|
||||
The summary test point may have yaml diagnostics.
|
||||
|
||||
```
|
||||
# Subtest: child test
|
||||
ok 1
|
||||
1..1
|
||||
ok 1 - child test
|
||||
1..1
|
||||
```
|
||||
|
||||
3. Unindented comment.
|
||||
A not-indented `# Subtest: <name>` comment, followed by indented TAP
|
||||
content, followed by a test point with a matching name.
|
||||
The summary test point may have yaml diagnostics.
|
||||
|
||||
```
|
||||
# Subtest: child test
|
||||
ok 1
|
||||
1..1
|
||||
ok 1 - child test
|
||||
1..1
|
||||
```
|
||||
|
||||
4. Buffered, without diagnostics.
|
||||
A test point line ending in {, followed by indented TAP content, ended
|
||||
with a } to close the block. todo/skip directives may come *either*
|
||||
before or after the `{` character. Yaml diagnostics are not allowed.
|
||||
|
||||
```
|
||||
ok 1 - child test {
|
||||
ok 1
|
||||
1..1
|
||||
}
|
||||
1..1
|
||||
```
|
||||
|
||||
5. Buffered, with diagnostics.
|
||||
A test point line with yaml diagnostics, followed by `{` alone on a
|
||||
line, indented TAP data, and then a `}`.
|
||||
|
||||
```
|
||||
ok 1 - child test
|
||||
---
|
||||
some: diagnostic
|
||||
data: true
|
||||
...
|
||||
{
|
||||
ok 1
|
||||
1..1
|
||||
}
|
||||
```
|
||||
|
||||
In all cases, the parsed behavior is identical:
|
||||
|
||||
1. The parent emits a `child` event with the `childParser` as an
|
||||
argument.
|
||||
2. The `childParser` emits a `comment` with `# Subtest: <name>` (or
|
||||
`(anonymous)` for Unadorned subtests.)
|
||||
3. When the test is over, the closing test point is emitted on parent
|
||||
test.
|
||||
|
||||
That is, buffered and nonindented/indented comment subtests are parsed
|
||||
as if they are identical input, since their semantics are the same. This
|
||||
simplifies implementation of test harness and reporter modules.
|
||||
|
||||
Since unadorned subtests have no introduction, a child event is not
|
||||
emitted until the first "relevant tap" line is encountered. This can
|
||||
cause confusion if the test output contains a spurious " 1..2" line
|
||||
or something, but such cases are rare.
|
||||
|
||||
Similarly, this means that a test point ending in `{` needs to wait to
|
||||
emit *either* the 'assert' or 'child' events until an indented line is
|
||||
encountered. *Any* test point with yaml diagnostics needs to wait to
|
||||
see if it will be followed by a `{` indicating a subtest.
|
||||
Reference in New Issue
Block a user