-
Notifications
You must be signed in to change notification settings - Fork 1
/
conformation.ts
86 lines (72 loc) · 2.1 KB
/
conformation.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
import { generate } from 'astring'
import * as es from 'estree'
import * as fs from 'fs'
import * as path from 'path'
import { parse as acornParse } from 'acorn'
import { parse } from '../parser'
import { createContext } from '../context'
import { evaluators, createInterpreter } from '../interpreter'
const fixturesFolderPath = path.resolve(
__dirname,
'..',
'__tests__',
'fixtures',
'conformation'
)
export type ConformationTest = {
statement: es.Statement
expectedValue: any
}
/**
* Parse and extract a list of conformation tests from a file.
* @param fixtureFilePath The fixture files
*/
export const loadAndParseConformation = (
fixtureFilePath: string
): ConformationTest[] => {
const pathname = path.join(fixturesFolderPath, fixtureFilePath)
const content = fs.readFileSync(pathname, 'utf8')
const expectedValues: any[] = []
const tests: ConformationTest[] = []
acornParse(content, {
ecmaVersion: 5,
locations: true,
onComment: (isBlock, text) => {
if (!isBlock) {
// tslint:disable-next-line
expectedValues.push(eval(text.trim()))
}
}
})
const context = createContext({ week: 3 })
const ast = parse(content, context).parser.program!
for (const [idx, statement] of ast.body.entries()) {
tests.push({
statement: statement as es.Statement,
expectedValue: expectedValues[idx]
})
}
return tests
}
/**
* Run a conformation test from a fixture file
* @param fixtureFilePath the path to fixture file, relative to fixtures directory
*/
export const runConformationTests = (fixtureFilePath: string) => {
const tests = loadAndParseConformation(fixtureFilePath)
let state = createInterpreter()
tests.forEach(t => {
const generator = evaluators[t.statement.type](t.statement, state)
let isDone = false
while (!isDone) {
const g = generator.next()
isDone = g.done
state = g.value
}
if (state.value !== t.expectedValue) {
// tslint:disable-next-line
console.log(`L${t.statement.loc!.start.line}: ${generate(t.statement)}`)
}
expect(state.value).toBe(t.expectedValue)
})
}