From 2e834c8c9d0f24f24235677a94721e3ddf213aea Mon Sep 17 00:00:00 2001 From: Michael Schmidt Date: Tue, 19 Oct 2021 14:59:04 +0200 Subject: [PATCH] Tests: Added `.html.test` files for replace `.js` language tests (#3148) --- package-lock.json | 6 + package.json | 1 + test-suite.html | 19 ++- tests/helper/test-case.js | 114 ++++++++++----- tests/helper/test-discovery.js | 4 +- .../asciidoc/entity_feature.html.test | 7 + tests/languages/asciidoc/entity_feature.js | 4 - tests/languages/groovy/issue1049.html.test | 15 ++ tests/languages/groovy/issue1049.js | 8 -- .../string-interpolation_feature.html.test | 133 ++++++++++++++++++ .../groovy/string-interpolation_feature.js | 28 ---- .../markdown/code-block_feature.html.test | 49 +++++++ .../languages/markdown/code-block_feature.js | 5 - ...block_language_detection_feature.html.test | 45 ++++++ .../code_block_language_detection_feature.js | 11 -- .../languages/markup/entity_feature.html.test | 17 +++ tests/languages/markup/entity_feature.js | 6 - tests/languages/markup/entity_feature.test | 14 -- tests/pattern-tests.js | 7 +- tests/run.js | 6 +- 20 files changed, 370 insertions(+), 129 deletions(-) create mode 100644 tests/languages/asciidoc/entity_feature.html.test delete mode 100644 tests/languages/asciidoc/entity_feature.js create mode 100644 tests/languages/groovy/issue1049.html.test delete mode 100644 tests/languages/groovy/issue1049.js create mode 100644 tests/languages/groovy/string-interpolation_feature.html.test delete mode 100644 tests/languages/groovy/string-interpolation_feature.js create mode 100644 tests/languages/markdown/code-block_feature.html.test delete mode 100644 tests/languages/markdown/code-block_feature.js create mode 100644 tests/languages/markdown/code_block_language_detection_feature.html.test delete mode 100644 tests/languages/markdown/code_block_language_detection_feature.js create mode 100644 tests/languages/markup/entity_feature.html.test delete mode 100644 tests/languages/markup/entity_feature.js delete mode 100644 tests/languages/markup/entity_feature.test diff --git a/package-lock.json b/package-lock.json index c9647b2c..949c9161 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6102,6 +6102,12 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prettier": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", + "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", + "dev": true + }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", diff --git a/package.json b/package.json index 487ccd73..19610409 100755 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "mocha": "^6.2.0", "node-fetch": "^2.6.0", "npm-run-all": "^4.1.5", + "prettier": "^2.4.1", "pump": "^3.0.0", "refa": "^0.9.1", "regexp-ast-analysis": "^0.2.4", diff --git a/test-suite.html b/test-suite.html index 0dbd5350..c4ae7821 100644 --- a/test-suite.html +++ b/test-suite.html @@ -165,14 +165,21 @@ This is a comment explaining this test case.

Writing specific tests

-

Sometimes, using the token stream tests is not powerful enough. By creating a test file with the file extension .js instead of .test, you can make Prism highlight arbitrary pieces of code and check their HTML results.

+

Sometimes, using the token stream tests is not powerful enough. By creating a test file with the file extension .html.test instead of .test, you can make Prism highlight arbitrary pieces of code and check their HTML results.

The language is determined by the folder containing the test file lies, as explained in the previous section.

The structure of your test file will look like this, for example:

-
module.exports = {
-	'&#x278a;': '<span class="token entity" title="&#x278a;">&amp;#x278a;</span>',
-	'&#182;': '<span class="token entity" title="&#182;">&amp;#182;</span>',
-};
-

The keys are the codes which will be highlighted by Prism. The values are the expected results, as HTML.

+
&amp;
+&#x41;
+
+----------------------------------------------------
+
+<span class="token entity named-entity" title="&amp;">&amp;amp;</span>
+<span class="token entity" title="&#x41;">&amp;#x41;</span>
+
+----------------------------------------------------
+
+This is a comment explaining this test case.
+
diff --git a/tests/helper/test-case.js b/tests/helper/test-case.js index e073613a..3454d77d 100644 --- a/tests/helper/test-case.js +++ b/tests/helper/test-case.js @@ -2,6 +2,7 @@ const fs = require('fs'); const { assert } = require('chai'); +const Prettier = require('prettier'); const PrismLoader = require('./prism-loader'); const TokenStreamTransformer = require('./token-stream-transformer'); @@ -217,6 +218,81 @@ class TokenizeJSONRunner { } } +/** + * @implements {Runner} + */ +class HighlightHTMLRunner { + /** + * @param {Prism} Prism + * @param {string} code + * @param {string} language + * @returns {string} + */ + run(Prism, code, language) { + const env = { + element: {}, + language, + grammar: Prism.languages[language], + code, + }; + + Prism.hooks.run('before-highlight', env); + env.highlightedCode = Prism.highlight(env.code, env.grammar, env.language); + Prism.hooks.run('before-insert', env); + env.element.innerHTML = env.highlightedCode; + Prism.hooks.run('after-highlight', env); + Prism.hooks.run('complete', env); + + return env.highlightedCode; + } + /** + * @param {string} actual + * @returns {string} + */ + print(actual) { + return Prettier.format(actual, { + printWidth: 100, + tabWidth: 4, + useTabs: true, + htmlWhitespaceSensitivity: 'ignore', + filepath: 'fake.html', + }); + } + /** + * @param {string} actual + * @param {string} expected + * @returns {boolean} + */ + isEqual(actual, expected) { + return this.normalize(actual) === this.normalize(expected); + } + /** + * @param {string} actual + * @param {string} expected + * @param {(firstDifference: number) => string} message + * @returns {void} + */ + assertEqual(actual, expected, message) { + // We don't calculate the index of the first difference because it's difficult. + assert.deepEqual(this.normalize(actual), this.normalize(expected), message(0)); + } + + /** + * Normalizes the given HTML by removing all leading spaces and trailing spaces. Line breaks will also be normalized + * to enable good diffing. + * + * @param {string} html + * @returns {string} + */ + normalize(html) { + return html + .replace(//g, '>\n') + .replace(/[ \t]*[\r\n]\s*/g, '\n') + .trim(); + } +} + module.exports = { TestCaseFile, @@ -238,7 +314,11 @@ module.exports = { * @param {"none" | "insert" | "update"} updateMode */ runTestCase(languageIdentifier, filePath, updateMode) { - this.runTestCaseWithRunner(languageIdentifier, filePath, updateMode, new TokenizeJSONRunner()); + if (/\.html\.test$/i.test(filePath)) { + this.runTestCaseWithRunner(languageIdentifier, filePath, updateMode, new HighlightHTMLRunner()); + } else { + this.runTestCaseWithRunner(languageIdentifier, filePath, updateMode, new TokenizeJSONRunner()); + } }, /** @@ -347,38 +427,6 @@ module.exports = { mainLanguage: mainLanguage }; }, - - /** - * Runs the given pieces of codes and asserts their result. - * - * Code is provided as the key and expected result as the value. - * - * @param {string} languageIdentifier - * @param {object} codes - */ - runTestsWithHooks(languageIdentifier, codes) { - const usedLanguages = this.parseLanguageNames(languageIdentifier); - const Prism = PrismLoader.createInstance(usedLanguages.languages); - // the first language is the main language to highlight - - for (const code in codes) { - if (codes.hasOwnProperty(code)) { - const env = { - element: {}, - language: usedLanguages.mainLanguage, - grammar: Prism.languages[usedLanguages.mainLanguage], - code: code - }; - Prism.hooks.run('before-highlight', env); - env.highlightedCode = Prism.highlight(env.code, env.grammar, env.language); - Prism.hooks.run('before-insert', env); - env.element.innerHTML = env.highlightedCode; - Prism.hooks.run('after-highlight', env); - Prism.hooks.run('complete', env); - assert.equal(env.highlightedCode, codes[code]); - } - } - } }; /** diff --git a/tests/helper/test-discovery.js b/tests/helper/test-discovery.js index c52fb25e..4d978739 100644 --- a/tests/helper/test-discovery.js +++ b/tests/helper/test-discovery.js @@ -3,8 +3,6 @@ const fs = require('fs'); const path = require('path'); -const SUPPORTED_TEST_FILE_EXT = new Set(['.js', '.test']); - module.exports = { /** @@ -95,7 +93,7 @@ module.exports = { getAllFiles(src) { return fs.readdirSync(src) .filter(fileName => { - return SUPPORTED_TEST_FILE_EXT.has(path.extname(fileName)) + return path.extname(fileName) === '.test' && fs.statSync(path.join(src, fileName)).isFile(); }) .map(fileName => { diff --git a/tests/languages/asciidoc/entity_feature.html.test b/tests/languages/asciidoc/entity_feature.html.test new file mode 100644 index 00000000..6d212747 --- /dev/null +++ b/tests/languages/asciidoc/entity_feature.html.test @@ -0,0 +1,7 @@ +➊ +¶ + +---------------------------------------------------- + +&#x278a; +&#182; diff --git a/tests/languages/asciidoc/entity_feature.js b/tests/languages/asciidoc/entity_feature.js deleted file mode 100644 index 22c9b3ba..00000000 --- a/tests/languages/asciidoc/entity_feature.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - '➊': '&#x278a;', - '¶': '&#182;' -}; diff --git a/tests/languages/groovy/issue1049.html.test b/tests/languages/groovy/issue1049.html.test new file mode 100644 index 00000000..0f0c6182 --- /dev/null +++ b/tests/languages/groovy/issue1049.html.test @@ -0,0 +1,15 @@ +"&" +"&&" +"<" +"<<" +"&lt;" +">" + +---------------------------------------------------- + +"&amp;" +"&amp;&amp;" +"&lt;" +"&lt;&lt;" +"&amp;lt;" +"&gt;" diff --git a/tests/languages/groovy/issue1049.js b/tests/languages/groovy/issue1049.js deleted file mode 100644 index 2ce81537..00000000 --- a/tests/languages/groovy/issue1049.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - '"&"': '"&amp;"', - '"&&"': '"&amp;&amp;"', - '"<"': '"&lt;"', - '"<<"': '"&lt;&lt;"', - '"&lt;"': '"&amp;lt;"', - '">"': '"&gt;"', -}; diff --git a/tests/languages/groovy/string-interpolation_feature.html.test b/tests/languages/groovy/string-interpolation_feature.html.test new file mode 100644 index 00000000..15541878 --- /dev/null +++ b/tests/languages/groovy/string-interpolation_feature.html.test @@ -0,0 +1,133 @@ +// Double quoted: interpolation +"$foo" +"${42}" + +// Triple double quoted: interpolation +"""$foo""" +"""${42}""" + +// Slashy string: interpolation +/$foo/ +/${42}/ + +// Dollar slashy string: interpolation +$/$foo/$ +$/${42}/$ + +// Double quoted: no interpolation (escaped) +"\$foo \${42}" + +// Triple double quoted: no interpolation (escaped) +"""\$foo \${42}""" + +// Slashy string: no interpolation (escaped) +/\$foo \${42}/ + +// Dollar slashy string: no interpolation (escaped) +$/$$foo $${42}/$ + +// Single quoted string: no interpolation +'$foo ${42}' + +// Triple single quoted string: no interpolation +'''$foo ${42}''' + +---------------------------------------------------- + +// Double quoted: interpolation + + " + + $ + foo + + " + + + " + + $ + { + 42 + } + + " + + +// Triple double quoted: interpolation + + """ + + $ + foo + + """ + + + """ + + $ + { + 42 + } + + """ + + +// Slashy string: interpolation + + / + + $ + foo + + / + + + / + + $ + { + 42 + } + + / + + +// Dollar slashy string: interpolation + + $/ + + $ + foo + + /$ + + + $/ + + $ + { + 42 + } + + /$ + + +// Double quoted: no interpolation (escaped) +"\$foo \${42}" + +// Triple double quoted: no interpolation (escaped) +"""\$foo \${42}""" + +// Slashy string: no interpolation (escaped) +/\$foo \${42}/ + +// Dollar slashy string: no interpolation (escaped) +$/$$foo $${42}/$ + +// Single quoted string: no interpolation +'$foo ${42}' + +// Triple single quoted string: no interpolation +'''$foo ${42}''' diff --git a/tests/languages/groovy/string-interpolation_feature.js b/tests/languages/groovy/string-interpolation_feature.js deleted file mode 100644 index 5cb2acf5..00000000 --- a/tests/languages/groovy/string-interpolation_feature.js +++ /dev/null @@ -1,28 +0,0 @@ -module.exports = { - // Double quoted: interpolation - '"$foo"': '"$foo"', - '"${42}"': '"${42}"', - // Triple double quoted: interpolation - '"""$foo"""': '"""$foo"""', - '"""${42}"""': '"""${42}"""', - // Slashy string: interpolation - '/$foo/': '/$foo/', - '/${42}/': '/${42}/', - // Dollar slashy string: interpolation - '$/$foo/$': '$/$foo/$', - '$/${42}/$': '$/${42}/$', - - // Double quoted: no interpolation (escaped) - '"\\$foo \\${42}"': '"\\$foo \\${42}"', - // Triple double quoted: no interpolation (escaped) - '"""\\$foo \\${42}"""': '"""\\$foo \\${42}"""', - // Slashy string: no interpolation (escaped) - '/\\$foo \\${42}/': '/\\$foo \\${42}/', - // Dollar slashy string: no interpolation (escaped) - '$/$$foo $${42}/$': '$/$$foo $${42}/$', - - // Single quoted string: no interpolation - '\'$foo ${42}\'': '\'$foo ${42}\'', - // Triple single quoted string: no interpolation - '\'\'\'$foo ${42}\'\'\'': '\'\'\'$foo ${42}\'\'\'' -}; diff --git a/tests/languages/markdown/code-block_feature.html.test b/tests/languages/markdown/code-block_feature.html.test new file mode 100644 index 00000000..7a5e8562 --- /dev/null +++ b/tests/languages/markdown/code-block_feature.html.test @@ -0,0 +1,49 @@ +```html +Click me! & +``` + +```unknownLanguage +Click me! & +``` + +---------------------------------------------------- + + + ``` + html + + + + < + a + + href + + = + " + #foo + " + + > + + Click me! + + + </ + a + + > + + &amp; + + ``` + + + + ``` + unknownLanguage + + <a href="#foo">Click me!</a> &amp; + + ``` + diff --git a/tests/languages/markdown/code-block_feature.js b/tests/languages/markdown/code-block_feature.js deleted file mode 100644 index e879cfa8..00000000 --- a/tests/languages/markdown/code-block_feature.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - '```html\nClick me! &\n```\n': '```html\n<a href="#foo">Click me!</a> &amp;\n```\n', - - '```unknownLanguage\nClick me! &\n```\n': '```unknownLanguage\n<a href="#foo">Click me!</a> &amp;\n```\n', -}; diff --git a/tests/languages/markdown/code_block_language_detection_feature.html.test b/tests/languages/markdown/code_block_language_detection_feature.html.test new file mode 100644 index 00000000..d47fcba0 --- /dev/null +++ b/tests/languages/markdown/code_block_language_detection_feature.html.test @@ -0,0 +1,45 @@ +```js +let a = 0; +``` + +``` c++ +int a = 0; +``` + +``` c# +var a = 0; +``` + +```{r pressure, echo=FALSE} +plot(pressure) +``` + +---------------------------------------------------- + + + ``` + js + let a = 0; + ``` + + + + ``` + c++ + int a = 0; + ``` + + + + ``` + c# + var a = 0; + ``` + + + + ``` + {r pressure, echo=FALSE} + plot(pressure) + ``` + diff --git a/tests/languages/markdown/code_block_language_detection_feature.js b/tests/languages/markdown/code_block_language_detection_feature.js deleted file mode 100644 index c980b6cf..00000000 --- a/tests/languages/markdown/code_block_language_detection_feature.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - - '```js\nlet a = 0;\n```': '```js\nlet a = 0;\n```', - - '``` c++\nint a = 0;\n```': '``` c++\nint a = 0;\n```', - - '``` c#\nvar a = 0;\n```': '``` c#\nvar a = 0;\n```', - - '```{r pressure, echo=FALSE}\nplot(pressure)\n```': '```{r pressure, echo=FALSE}\nplot(pressure)\n```' - -}; diff --git a/tests/languages/markup/entity_feature.html.test b/tests/languages/markup/entity_feature.html.test new file mode 100644 index 00000000..5bcf3517 --- /dev/null +++ b/tests/languages/markup/entity_feature.html.test @@ -0,0 +1,17 @@ +& +ϑ +A +A +⛵ + +---------------------------------------------------- + +&amp; +&thetasym; +&#65; +&#x41; +&#x26f5; + +---------------------------------------------------- + +Checks for HTML/XML character entity references. diff --git a/tests/languages/markup/entity_feature.js b/tests/languages/markup/entity_feature.js deleted file mode 100644 index ec74c9e3..00000000 --- a/tests/languages/markup/entity_feature.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - '&': '&amp;', - 'ϑ': '&thetasym;', - 'A': '&#65;', - 'A': '&#x41;' -}; diff --git a/tests/languages/markup/entity_feature.test b/tests/languages/markup/entity_feature.test deleted file mode 100644 index 44f0f83d..00000000 --- a/tests/languages/markup/entity_feature.test +++ /dev/null @@ -1,14 +0,0 @@ -& ϑ ⛵   - ----------------------------------------------------- - -[ - ["entity", "&"], - ["entity", "ϑ"], - ["entity", "⛵"], - ["entity", " "] -] - ----------------------------------------------------- - -Checks for HTML/XML character entity references. \ No newline at end of file diff --git a/tests/pattern-tests.js b/tests/pattern-tests.js index 7cfb2d00..2dc9ee4c 100644 --- a/tests/pattern-tests.js +++ b/tests/pattern-tests.js @@ -10,7 +10,6 @@ const { languages } = require('../components.json'); const { visitRegExpAST } = require('regexpp'); const { transform, combineTransformers, getIntersectionWordSets, JS, Words, NFA, Transformers } = require('refa'); const scslre = require('scslre'); -const path = require('path'); const { argv } = require('yargs'); const RAA = require('regexp-ast-analysis'); @@ -30,11 +29,7 @@ for (const languageIdentifier in testSuite) { } for (const file of testSuite[languageIdentifier]) { - if (path.extname(file) === '.test') { - snippets.push(TestCase.TestCaseFile.readFromFile(file).code); - } else { - snippets.push(...Object.keys(require(file))); - } + snippets.push(TestCase.TestCaseFile.readFromFile(file).code); } } diff --git a/tests/run.js b/tests/run.js index d6a38829..f030fbc3 100644 --- a/tests/run.js +++ b/tests/run.js @@ -28,11 +28,7 @@ for (const language in testSuite) { const fileName = path.basename(filePath, path.extname(filePath)); it("– should pass test case '" + fileName + "'", function () { - if (path.extname(filePath) === '.test') { - TestCase.runTestCase(language, filePath, update ? 'update' : 'insert'); - } else { - TestCase.runTestsWithHooks(language, require(filePath)); - } + TestCase.runTestCase(language, filePath, update ? 'update' : 'insert'); }); } });