-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser-specification.test.ts
99 lines (93 loc) · 3.15 KB
/
parser-specification.test.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
87
88
89
90
91
92
93
94
95
96
97
98
99
import {
handlebarsSpec,
ParseErrorTest,
SuccessTest,
} from "@handlebars-ng/specification";
import { createDefaultParser, ParseError } from "./index";
describe("test against Handlebars spec", () => {
for (const [filename, testCase] of Object.entries(handlebarsSpec)) {
describe(filename, () => {
it(testCase.description, () => {
if (testCase.type === "success") {
expectSameAst(testCase);
}
if (testCase.type === "parseError") {
expectSameError(testCase);
}
});
});
}
});
function expectSameAst(testCase: SuccessTest) {
let ast;
try {
const parser = createDefaultParser();
ast = parser.parse(testCase.template);
} catch (error) {
// Allow console in this case since it helps adjusting test-cases in case they are wrong
// eslint-disable-next-line no-console
console.log(testCase);
throw error;
}
try {
expect(ast).toEqual(testCase.ast);
} catch (error) {
// Allow console in this case since it helps adjusting test-cases in case they are wrong
// eslint-disable-next-line no-console
console.log(testCase.template, JSON.stringify(ast));
throw error;
}
}
function expectSameError(testcase: ParseErrorTest) {
// TODO: The messages are currently different and we don't test this at the moment
// I don't know if the messages are really that important to be spec'd, the important
// thing in my view is that there IS an error an the the location is correct.
const parseError = getParseError(testcase.template);
acceptWrongLocationForUnfinishedFeatures(testcase);
try {
expect(parseError.location).toEqual({
column: testcase.expected.column,
line: testcase.expected.line,
});
} catch (error) {
// Allow console in this case since it helps adjusting test-cases in case they are wrong
// eslint-disable-next-line no-console
console.log({
template: testcase.template,
expectedLocation: testcase.expected,
actualLocation: parseError.location,
actualMessage: parseError.message,
});
throw error;
}
}
function getParseError(template: string): ParseError {
try {
const parser = createDefaultParser();
parser.parse(template);
} catch (error) {
if (error instanceof ParseError) {
return error;
}
throw error;
}
throw new Error(`No error was thrown when parsing "${template}"`);
}
/**
* Some errors are returning the wrong location.
*
* * An invalid id-char may be a valid token in the Mustache context for Handlebars 4.x, but not yet for this parser
* In this case, Handlebars 4.x reports the next token as invalid
*/
function acceptWrongLocationForUnfinishedFeatures(testcase: ParseErrorTest) {
switch (testcase.description) {
case "~ may not be used in an id":
// TODO: This test is failing because of an implementation detail
// In the original Handlebars, "{{~" is a single token,
// but in this implementation, it is two ("{{" "~")
// The "~" in "{{a~b}}" is a valid token in this implementation.
// This makes me wonder whether the exact error-locations should be part of the spec.
testcase.expected.column++;
break;
}
}