Tests: Simplified error message format (#2056) The error messages will now only contain the actual token stream the failed test and a full path of the test file plus the line and column number of the position of the first difference between the expected token stream and the actual token stream.
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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
diff --git a/tests/helper/test-case.js b/tests/helper/test-case.js
index 4f14cee..7fe1062 100644
--- a/tests/helper/test-case.js
+++ b/tests/helper/test-case.js
@@ -64,24 +64,27 @@ module.exports = {
// the first language is the main language to highlight
const simplifiedTokenStream = this.simpleTokenize(Prism, testCase.testSource, usedLanguages.mainLanguage);
- const tzd = JSON.stringify(simplifiedTokenStream);
- const exp = JSON.stringify(testCase.expectedTokenStream);
- let i = 0;
- let j = 0;
- let diff = "";
- while (j < tzd.length) {
- if (exp[i] != tzd[j] || i == exp.length)
- diff += tzd[j];
- else
- i++;
- j++;
+ const actual = JSON.stringify(simplifiedTokenStream);
+ const expected = JSON.stringify(testCase.expectedTokenStream);
+
+ if (actual === expected) {
+ // no difference
+ return;
}
- const tokenStreamStr = pretty ? TokenStreamTransformer.prettyprint(simplifiedTokenStream) : tzd;
- const message = "\nToken Stream: \n" + tokenStreamStr +
+ // The index of the first difference between the expected token stream and the actual token stream.
+ // The index is in the raw expected token stream JSON of the test case.
+ const diffIndex = translateIndexIgnoreSpaces(testCase.expectedJson, expected, firstDiff(expected, actual));
+ const expectedJsonLines = testCase.expectedJson.substr(0, diffIndex).split(/\r\n?|\n/g);
+ const columnNumber = expectedJsonLines.pop().length + 1;
+ const lineNumber = testCase.expectedLineOffset + expectedJsonLines.length;
+
+ const tokenStreamStr = pretty ? TokenStreamTransformer.prettyprint(simplifiedTokenStream) : actual;
+ const message = "\n\nActual Token Stream:" +
+ "\n-----------------------------------------\n" +
+ tokenStreamStr +
"\n-----------------------------------------\n" +
- "Expected Token Stream: \n" + exp +
- "\n-----------------------------------------\n" + diff;
+ "File: " + filePath + ":" + lineNumber + ":" + columnNumber + "\n\n";
assert.deepEqual(simplifiedTokenStream, testCase.expectedTokenStream, testCase.comment + message);
},
@@ -158,7 +161,6 @@ module.exports = {
*
* @private
* @param {string} filePath
- * @returns {{testSource: string, expectedTokenStream: Array.<Array.<string>>, comment:string?}|null}
*/
parseTestCaseFile(filePath) {
const testCaseSource = fs.readFileSync(filePath, "utf8");
@@ -167,6 +169,8 @@ module.exports = {
try {
const testCase = {
testSource: testCaseParts[0].trim(),
+ expectedJson: testCaseParts[1],
+ expectedLineOffset: testCaseParts[0].split(/\r\n?|\n/g).length,
expectedTokenStream: JSON.parse(testCaseParts[1]),
comment: null
};
@@ -217,3 +221,54 @@ module.exports = {
}
}
};
+
+/**
+ * Returns the index at which the given expected string differs from the given actual string.
+ *
+ * This will returns `undefined` if the strings are equal.
+ *
+ * @param {string} expected
+ * @param {string} actual
+ * @returns {number | undefined}
+ */
+function firstDiff(expected, actual) {
+ let i = 0;
+ let j = 0;
+ while (i < expected.length && j < actual.length) {
+ if (expected[i] !== actual[j]) {
+ return i;
+ }
+ i++; j++;
+ }
+
+ if (i == expected.length && j == actual.length) {
+ return undefined;
+ }
+ return i;
+}
+
+/**
+ * Translates an index within a string (`withoutSpaces`) to the index of another string (`spacey`) where the only
+ * difference between the two strings is that the other string can have any number of additional white spaces at any
+ * position.
+ *
+ * In out use case, the `withoutSpaces` string is an unformatted JSON string and the `spacey` string is a formatted JSON
+ * string.
+ *
+ * @param {string} spacey
+ * @param {string} withoutSpaces
+ * @param {number} withoutSpaceIndex
+ * @returns {number | undefined}
+ */
+function translateIndexIgnoreSpaces(spacey, withoutSpaces, withoutSpaceIndex) {
+ let i = 0;
+ let j = 0;
+ while (i < spacey.length && j < withoutSpaces.length) {
+ while (spacey[i] !== withoutSpaces[j]) i++;
+ if (j === withoutSpaceIndex) {
+ return i;
+ }
+ i++; j++;
+ }
+ return undefined;
+}