115 lines
3.2 KiB
JavaScript
115 lines
3.2 KiB
JavaScript
import { expect } from 'chai'
|
|
import fs from 'node:fs/promises'
|
|
import { execSync } from 'node:child_process'
|
|
import { useDocument } from '@terrace-lang/js'
|
|
import { createFileReader } from '@terrace-lang/js/readers/node-readline'
|
|
|
|
export async function loadTestMap(path) {
|
|
const reader = createFileReader(path)
|
|
const doc = useDocument(reader)
|
|
|
|
const descriptions = {}
|
|
let currentSuite = null
|
|
let currentTest = null
|
|
|
|
for await (const node of doc) {
|
|
if (node.head === '#schema') {
|
|
// Skip schema declarations
|
|
continue
|
|
}
|
|
|
|
if (node.head === 'describe') {
|
|
currentSuite = node.tail
|
|
descriptions[currentSuite] = []
|
|
continue
|
|
}
|
|
|
|
if (node.head === 'it' && currentSuite) {
|
|
currentTest = {
|
|
it: node.tail,
|
|
packages: [],
|
|
key: '',
|
|
input: '',
|
|
output: ''
|
|
}
|
|
descriptions[currentSuite].push(currentTest)
|
|
|
|
// Collect test properties
|
|
let collectingInput = false
|
|
let collectingOutput = false
|
|
let inputLevel = 0
|
|
|
|
for await (const child of node.children()) {
|
|
if (child.head === 'key') {
|
|
currentTest.key = child.tail
|
|
} else if (child.head === 'packages') {
|
|
currentTest.packages = child.tail.split(' ')
|
|
} else if (child.head === 'input') {
|
|
collectingInput = true
|
|
collectingOutput = false
|
|
inputLevel = child.level
|
|
// If input has content on the same line
|
|
if (child.tail) {
|
|
currentTest.input = child.tail
|
|
}
|
|
} else if (child.head === 'output') {
|
|
collectingInput = false
|
|
collectingOutput = true
|
|
// If output has content on the same line
|
|
if (child.tail) {
|
|
currentTest.output = child.tail
|
|
}
|
|
} else if (collectingInput) {
|
|
// Collect input lines
|
|
currentTest.input += (currentTest.input ? '\n' : '') + child.raw(inputLevel + 1)
|
|
} else if (collectingOutput) {
|
|
// Collect output lines
|
|
currentTest.output += (currentTest.output ? '\n' : '') + child.content
|
|
}
|
|
}
|
|
|
|
// Process escape sequences
|
|
if (typeof currentTest.input === 'string') {
|
|
currentTest.input = currentTest.input
|
|
.replaceAll('\\n', '\n')
|
|
.replaceAll('\\t', '\t')
|
|
.replaceAll('\\s', ' ')
|
|
}
|
|
|
|
if (typeof currentTest.output === 'string') {
|
|
currentTest.output = currentTest.output.trimEnd()
|
|
}
|
|
|
|
continue
|
|
}
|
|
}
|
|
|
|
return descriptions
|
|
}
|
|
|
|
export function defineTests(testMap) {
|
|
for (const [name, tests] of Object.entries(testMap)) {
|
|
describe(name, () => {
|
|
for (const test of tests) {
|
|
test.packages.forEach(pkg => {
|
|
it(`${pkg}: ${test.it}`, async () => {
|
|
expect(await callTest(pkg, test.key, test.input)).to.equal(test.output)
|
|
})
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
function callTest(pkg, name, input) {
|
|
return new Promise((resolve, reject) => {
|
|
const stdout = execSync(`npm run --silent test ${name}`, {
|
|
cwd: `../packages/${pkg}`,
|
|
input
|
|
})
|
|
|
|
// TODO: Find a way to clean all this trimming up. Most caused by VSCode happily trimming empty spaces off the ends of lines.
|
|
resolve(stdout.toString().trim())
|
|
})
|
|
}
|