From 3b1a46ff37683d9e3f4c04a8801278d3ee382739 Mon Sep 17 00:00:00 2001 From: David Taylor Date: Tue, 23 Aug 2022 10:25:07 +0100 Subject: [PATCH] DEV: Skip loading plugin JS when running only core tests (#18047) Plugins often change core behavior, and thereby cause core's tests to fail. In CI, we work around this problem by running core CI without any plugins loaded. In development, the only option to safely run the core tests is to uninstall all plugins, which is clearly a bad developer experience. This commit aims to improve that experience. The `qunit_skip_plugins=1` flag would previously prevent the plugin **tests** from running. This commit extends that flag to also affect the plugin's application JS. --- .prettierignore | 1 + .../discourse/lib/bootstrap-json/index.js | 18 ++++++++---- .../scripts/discourse-test-listen-boot.js | 2 +- .../scripts/discourse-test-load-dynamic-js.js | 28 +++++++++++++++++++ .../discourse-test-trigger-ember-cli-boot.js | 1 + .../javascripts/discourse/tests/index.html | 25 +++++++++++------ .../discourse/tests/test-boot-ember-cli.js | 7 +++++ 7 files changed, 66 insertions(+), 16 deletions(-) create mode 100644 app/assets/javascripts/discourse/public/assets/scripts/discourse-test-load-dynamic-js.js create mode 100644 app/assets/javascripts/discourse/public/assets/scripts/discourse-test-trigger-ember-cli-boot.js diff --git a/.prettierignore b/.prettierignore index fff97dce442..b33a5618e4d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -17,6 +17,7 @@ lib/javascripts/messageformat.js lib/highlight_js/ plugins/**/lib/javascripts/locale public/ +!/app/assets/javascripts/discourse/public vendor/ app/assets/javascripts/discourse/tests/fixtures spec/ diff --git a/app/assets/javascripts/discourse/lib/bootstrap-json/index.js b/app/assets/javascripts/discourse/lib/bootstrap-json/index.js index 0eb9ce0b3de..3249cbbc6eb 100644 --- a/app/assets/javascripts/discourse/lib/bootstrap-json/index.js +++ b/app/assets/javascripts/discourse/lib/bootstrap-json/index.js @@ -388,24 +388,30 @@ module.exports = { for (const { name, hasJs } of pluginInfos) { if (hasJs) { - scripts.push(`plugins/${name}.js`); + scripts.push({ src: `plugins/${name}.js`, name }); } if (fs.existsSync(`../plugins/${name}_extras.js.erb`)) { - scripts.push(`plugins/${name}_extras.js`); + scripts.push({ src: `plugins/${name}_extras.js`, name }); } } } else { - scripts.push("discourse/tests/active-plugins.js"); + scripts.push({ + src: "discourse/tests/active-plugins.js", + name: "_all", + }); } - scripts.push("admin-plugins.js"); + scripts.push({ src: "admin-plugins.js", name: "_admin" }); return scripts - .map((s) => ``) + .map( + ({ src, name }) => + `` + ) .join("\n"); } else if (shouldLoadPluginTestJs() && type === "test-plugin-tests-js") { - return ``; + return ``; } }, diff --git a/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-listen-boot.js b/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-listen-boot.js index 48a7c880f6b..bc903572c7b 100644 --- a/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-listen-boot.js +++ b/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-listen-boot.js @@ -27,4 +27,4 @@ document.body.insertAdjacentHTML( ` ); -require('discourse/tests/test-boot-ember-cli'); +require("discourse/tests/test-boot-ember-cli"); diff --git a/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-load-dynamic-js.js b/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-load-dynamic-js.js new file mode 100644 index 00000000000..fc0237c6225 --- /dev/null +++ b/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-load-dynamic-js.js @@ -0,0 +1,28 @@ +const dynamicJsTemplate = document.querySelector("#dynamic-test-js"); + +const params = new URLSearchParams(document.location.search); +const skipPlugins = params.get("qunit_skip_plugins"); + +for (const element of dynamicJsTemplate.content.childNodes) { + if (skipPlugins && element.dataset?.discoursePlugin) { + continue; + } + + if ( + element.tagName === "SCRIPT" && + element.innerHTML.includes("EmberENV.TESTS_FILE_LOADED") + ) { + // Inline script introduced by ember-cli. Incompatible with CSP and our custom plugin JS loading system + // https://github.com/ember-cli/ember-cli/blob/04a38fda2c/lib/utilities/ember-app-utils.js#L131 + // We re-implement in test-boot-ember-cli.js + continue; + } + + const clone = element.cloneNode(true); + + if (clone.tagName === "SCRIPT") { + clone.async = false; + } + + document.querySelector("discourse-dynamic-test-js").appendChild(clone); +} diff --git a/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-trigger-ember-cli-boot.js b/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-trigger-ember-cli-boot.js new file mode 100644 index 00000000000..65f629d8a02 --- /dev/null +++ b/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-trigger-ember-cli-boot.js @@ -0,0 +1 @@ +require("discourse/tests/test-boot-ember-cli"); diff --git a/app/assets/javascripts/discourse/tests/index.html b/app/assets/javascripts/discourse/tests/index.html index e8c2e10b163..03d82fa2db3 100644 --- a/app/assets/javascripts/discourse/tests/index.html +++ b/app/assets/javascripts/discourse/tests/index.html @@ -50,15 +50,22 @@ - {{content-for "test-plugin-js"}} - - - {{content-for "test-plugin-tests-js"}} - - - {{content-for "body-footer"}} {{content-for "test-body-footer"}} + + + + + + + + diff --git a/app/assets/javascripts/discourse/tests/test-boot-ember-cli.js b/app/assets/javascripts/discourse/tests/test-boot-ember-cli.js index c11fbcfeb57..eabbec1ef7c 100644 --- a/app/assets/javascripts/discourse/tests/test-boot-ember-cli.js +++ b/app/assets/javascripts/discourse/tests/test-boot-ember-cli.js @@ -8,6 +8,13 @@ import { setup } from "qunit-dom"; setEnvironment("testing"); document.addEventListener("discourse-booted", () => { + // eslint-disable-next-line no-undef + if (!EmberENV.TESTS_FILE_LOADED) { + throw new Error( + 'The tests file was not loaded. Make sure your tests index.html includes "assets/tests.js".' + ); + } + const script = document.getElementById("plugin-test-script"); if (script && !requirejs.entries["discourse/tests/plugin-tests"]) { throw new Error(