doctest-ts/src/UnitTest.ts

80 lines
2.3 KiB
TypeScript
Raw Normal View History

2022-03-25 15:47:14 +01:00
import {Context} from "./ExtractComments";
import {ScriptExtraction} from "./ScriptExtraction";
2022-03-25 15:47:14 +01:00
export type Script = (Statement | Equality)[]
export interface Equality {
2022-03-25 15:47:14 +01:00
tag: '=='
lhs: string
rhs: string,
2022-04-08 04:39:17 +02:00
// Line number in the single script
line: number
2022-03-25 15:47:14 +01:00
}
export interface Statement {
2022-03-25 15:47:14 +01:00
tag: 'Statement'
stmt: string
}
/**
* Represents a single unit test somewhere in a file.
*/
export default class UnitTest {
public body: Script;
public context: Context;
private _extraImports: string[];
private constructor(body: Script, context: Context, extraImports: string[]) {
this.body = body;
this.context = context;
this._extraImports = extraImports;
}
public static FromComment(comment: string, context: Context): UnitTest[] {
const imports = ScriptExtraction.extractImports(comment)
2022-04-08 17:56:56 +02:00
return ScriptExtraction.extractScripts(comment).map(
({script, name}, i) =>
2022-03-25 15:47:14 +01:00
new UnitTest(script, {
...context,
2022-04-08 04:39:17 +02:00
linenumber: (context.linenumber ?? 0) ,
2022-03-25 15:47:14 +01:00
testname: name ?? 'doctest ' + i
},imports))
}
public static FromComments(comms: { comment: string, context: Context }[]): UnitTest[] {
const result: UnitTest[] = []
for (const comm of comms) {
result.push(...UnitTest.FromComment(comm.comment, comm.context))
}
return result
}
public getImports(): string[] {
return [...this._extraImports, 'import "mocha"', 'import {expect as __expect} from "chai"']
}
/**
* Generates the mocha test code for this unit test.
* Will only construct the 'it('should ....') { __expect(x).deep.eq(y) } part
*/
public generateCode() {
const script = this.body
.map(s => {
if (s.tag == 'Statement') {
return s.stmt
} else {
2022-04-08 17:56:56 +02:00
return `__expect(${s.lhs}, "failed at ${this.context.functionname} (${this.context.filepath}:${1 + s.line + (this.context.linenumber ?? 0)}:1)").to.deep.equal(${s.rhs})`
2022-03-25 15:47:14 +01:00
}
})
.map(x => '\n ' + x)
.join('')
return `it(${this.getName()}, () => {${script}\n})`
}
private getName() {
return JSON.stringify(this.context.testname ?? this.context.functionname)
}
}