test
Version:
Node.js 18's node:test, as an npm package
122 lines (112 loc) • 3.59 kB
JavaScript
// https://github.com/nodejs/node/blob/a1b27b25bb01aadd3fd2714e4b136db11b7eb85a/lib/internal/test_runner/yaml_parser.js
const {
codes: {
ERR_TEST_FAILURE
}
} = require('#internal/errors')
const AssertionError = require('assert').AssertionError
const {
ArrayPrototypeJoin,
ArrayPrototypePush,
Error,
Number,
NumberIsNaN,
RegExpPrototypeExec,
StringPrototypeEndsWith,
StringPrototypeRepeat,
StringPrototypeSlice,
StringPrototypeStartsWith,
StringPrototypeSubstring
} = require('#internal/per_context/primordials')
const kYamlKeyRegex = /^(\s+)?(\w+):(\s)+([>|][-+])?(.*)$/
const kStackDelimiter = ' at '
function reConstructError (parsedYaml) {
if (!('error' in parsedYaml)) {
return parsedYaml
}
const isAssertionError = parsedYaml.code === 'ERR_ASSERTION' ||
'actual' in parsedYaml || 'expected' in parsedYaml || 'operator' in parsedYaml
const isTestFailure = parsedYaml.code === 'ERR_TEST_FAILURE' || 'failureType' in parsedYaml
const stack = parsedYaml.stack ? kStackDelimiter + ArrayPrototypeJoin(parsedYaml.stack, `\n${kStackDelimiter}`) : ''
let error, cause
if (isAssertionError) {
cause = new AssertionError({
message: parsedYaml.error,
actual: parsedYaml.actual,
expected: parsedYaml.expected,
operator: parsedYaml.operator
})
} else {
// eslint-disable-next-line no-restricted-syntax
cause = new Error(parsedYaml.error)
cause.code = parsedYaml.code
}
cause.stack = stack
if (isTestFailure) {
error = new ERR_TEST_FAILURE(cause, parsedYaml.failureType)
error.stack = stack
}
parsedYaml.error = error ?? cause
delete parsedYaml.stack
delete parsedYaml.code
delete parsedYaml.failureType
delete parsedYaml.actual
delete parsedYaml.expected
delete parsedYaml.operator
return parsedYaml
}
function getYamlValue (value) {
if (StringPrototypeStartsWith(value, "'") && StringPrototypeEndsWith(value, "'")) {
return StringPrototypeSlice(value, 1, -1)
}
if (value === 'true') {
return true
}
if (value === 'false') {
return false
}
if (value !== '') {
const valueAsNumber = Number(value)
return NumberIsNaN(valueAsNumber) ? value : valueAsNumber
}
return value
}
// This parses the YAML generated by the built-in TAP reporter,
// which is a subset of the full YAML spec. There are some
// YAML features that won't be parsed here. This function should not be exposed publicly.
function YAMLToJs (lines) {
if (lines == null) {
return undefined
}
const result = { __proto__: null }
let isInYamlBlock = false
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
if (isInYamlBlock && !StringPrototypeStartsWith(line, StringPrototypeRepeat(' ', isInYamlBlock.indent))) {
result[isInYamlBlock.key] = isInYamlBlock.key === 'stack'
? result[isInYamlBlock.key]
: ArrayPrototypeJoin(result[isInYamlBlock.key], '\n')
isInYamlBlock = false
}
if (isInYamlBlock) {
const blockLine = StringPrototypeSubstring(line, isInYamlBlock.indent)
ArrayPrototypePush(result[isInYamlBlock.key], blockLine)
continue
}
const match = RegExpPrototypeExec(kYamlKeyRegex, line)
if (match !== null) {
const { 1: leadingSpaces, 2: key, 4: block, 5: value } = match
if (block) {
isInYamlBlock = { key, indent: (leadingSpaces?.length ?? 0) + 2 }
result[key] = []
} else {
result[key] = getYamlValue(value)
}
}
}
return reConstructError(result)
}
module.exports = {
YAMLToJs
}