FEATURE: Allow theme tests to be run in production (take 2) (#12845)

FEATURE: Allow theme tests to be run in production (take 2) (#12845)

This commit allows site admins to run theme tests in production via a new /theme-qunit route. When you visit /theme-qunit, you’ll see a list of the themes/components installed on your site that have tests, and from there you can select a theme or component that you run its tests.

We also have a new rake task themes:install_and_test that can be used to install a list of themes/components on a temporary database and run the tests of the themes/components that are installed. This rake task can be useful when upgrading/deploying a Discourse instance to make sure that the installed themes/components are compatible with the new Discourse version being deployed, and if the tests fail you can abort the build/deploy process so you don’t end up with a broken site.

diff --git a/app/assets/javascripts/discourse/tests/core_plugins_tests.js b/app/assets/javascripts/discourse/tests/core_plugins_tests.js
new file mode 100644
index 0000000..f9c99ce
--- /dev/null
+++ b/app/assets/javascripts/discourse/tests/core_plugins_tests.js
@@ -0,0 +1,4 @@
+//= require_tree ./acceptance
+//= require_tree ./integration
+//= require_tree ./unit
+//= require ./plugin_tests
diff --git a/app/assets/javascripts/discourse/tests/helpers/create-pretender.js b/app/assets/javascripts/discourse/tests/helpers/create-pretender.js
index f3ee733..7cbea9c 100644
--- a/app/assets/javascripts/discourse/tests/helpers/create-pretender.js
+++ b/app/assets/javascripts/discourse/tests/helpers/create-pretender.js
@@ -1,5 +1,6 @@
 import Pretender from "pretender";
 import User from "discourse/models/user";
+import getURL from "discourse-common/lib/get-url";
 
 export function parsePostData(query) {
   const result = {};
@@ -39,7 +40,15 @@ const helpers = { response, success, parsePostData };
 
 export let fixturesByUrl;
 
-export default new Pretender();
+const instance = new Pretender();
+
+const oldRegister = instance.register;
+instance.register = (...args) => {
+  args[1] = getURL(args[1]);
+  return oldRegister.call(instance, ...args);
+};
+
+export default instance;
 
 export function pretenderHelpers() {
   return { parsePostData, response, success };
diff --git a/app/assets/javascripts/discourse/tests/setup-tests.js b/app/assets/javascripts/discourse/tests/setup-tests.js
index df1c06c..7742a30 100644
--- a/app/assets/javascripts/discourse/tests/setup-tests.js
+++ b/app/assets/javascripts/discourse/tests/setup-tests.js
@@ -152,6 +152,12 @@ function setupTestsCommon(application, container, config) {
     },
   });
 
+  let setupData;
+  const setupDataElement = document.getElementById("data-discourse-setup");
+  if (setupDataElement) {
+    setupData = setupDataElement.dataset;
+    setupDataElement.remove();
+  }
   QUnit.testStart(function (ctx) {
     bootbox.$body = $("#ember-testing");
     let settings = resetSettings();
@@ -162,6 +168,15 @@ function setupTestsCommon(application, container, config) {
       app = createApplication(config, settings);
     }
 
+    const cdn = setupData ? setupData.cdn : null;
+    const baseUri = setupData ? setupData.baseUri : "";
+    setupURL(cdn, "http://localhost:3000", baseUri);
+    if (setupData && setupData.s3BaseUrl) {
+      setupS3CDN(setupData.s3BaseUrl, setupData.s3Cdn);
+    } else {
+      setupS3CDN(null, null);
+    }
+
     server = createPretender;
     server.handlers = [];
     applyDefaultHandlers(server);
@@ -199,10 +214,12 @@ function setupTestsCommon(application, container, config) {
 
     applyPretender(ctx.module, server, pretenderHelpers());
 
-    setupURL(null, "http://localhost:3000", "");
-    setupS3CDN(null, null);
-
     Session.resetCurrent();
+    if (setupData) {
+      const session = Session.current();
+      session.markdownItURL = setupData.markdownItUrl;
+      session.highlightJsPath = setupData.highlightJsPath;
+    }
     User.resetCurrent();
     let site = resetSite(settings);
     createHelperContext({
@@ -253,7 +270,6 @@ function setupTestsCommon(application, container, config) {
   let pluginPath = getUrlParameter("qunit_single_plugin")
     ? "/" + getUrlParameter("qunit_single_plugin") + "/"
     : "/plugins/";
-  let themeOnly = getUrlParameter("theme_name") || getUrlParameter("theme_url");
 
   if (getUrlParameter("qunit_disable_auto_start") === "1") {
     QUnit.config.autostart = false;
@@ -263,19 +279,11 @@ function setupTestsCommon(application, container, config) {
     let isTest = /\-test/.test(entry);
     let regex = new RegExp(pluginPath);
     let isPlugin = regex.test(entry);
-    let isTheme = /^discourse\/theme\-\d+\/.+/.test(entry);
 
     if (!isTest) {
       return;
     }
 
-    if (themeOnly) {
-      if (isTheme) {
-        require(entry, null, null, true);
-      }
-      return;
-    }
-
     if (!skipCore || isPlugin) {
       require(entry, null, null, true);
     }
diff --git a/app/assets/javascripts/discourse/tests/test_helper.js b/app/assets/javascripts/discourse/tests/test_helper.js
index affd1b3..9da07da 100644
--- a/app/assets/javascripts/discourse/tests/test_helper.js
+++ b/app/assets/javascripts/discourse/tests/test_helper.js
@@ -5,11 +5,11 @@
 //= require jquery.ui.widget
 //= require ember.debug
 //= require message-bus
-//= require qunit/qunit/qunit
+//= require qunit
 //= require ember-qunit
 //= require fake_xml_http_request
 //= require route-recognizer
-//= require pretender/pretender
+//= require pretender
 //= require locales/i18n
 //= require locales/en
 //= require discourse-loader
@@ -28,16 +28,12 @@
 //= require ember-template-compiler
 
 // Test helpers
-//= require sinon/pkg/sinon
+//= require sinon
 //= require_tree ./helpers
 //= require break_string
 
-// Finally, the tests themselves
 //= require_tree ./fixtures
-//= require_tree ./acceptance
-//= require_tree ./integration
-//= require_tree ./unit
-//= require plugin_tests
-//= require setup-tests
+
+//= require ./setup-tests
 //= require test-shims
 //= require jquery.magnific-popup.min.js
diff --git a/app/assets/javascripts/discourse/tests/theme_test_helper.js b/app/assets/javascripts/discourse/tests/theme_test_helper.js
new file mode 100644
index 0000000..a9c60c9
--- /dev/null
+++ b/app/assets/javascripts/discourse/tests/theme_test_helper.js
@@ -0,0 +1,6 @@
+// discourse-skip-module
+
+//= require_tree ./helpers
+//= require_tree ./fixtures
+//= require ./setup-tests
+//= require test-shims
diff --git a/app/assets/javascripts/discourse/tests/theme_test_vendor.js b/app/assets/javascripts/discourse/tests/theme_test_vendor.js
new file mode 100644
index 0000000..0582ffd
--- /dev/null
+++ b/app/assets/javascripts/discourse/tests/theme_test_vendor.js
@@ -0,0 +1,19 @@
+// discourse-skip-module
+
+//= require env
+//= require jquery.debug
+//= require ember.debug
+//= require qunit
+//= require ember-qunit
+//= require fake_xml_http_request
+//= require route-recognizer
+//= require pretender
+//= require discourse-loader
+
+// These are not loaded in prod or development
+// But we need them for testing handlebars templates in qunit
+//= require handlebars
+//= require ember-template-compiler
+
+//= require sinon
+//= require break_string
diff --git a/app/assets/javascripts/wizard/test/test_helper.js b/app/assets/javascripts/wizard/test/test_helper.js
index 3aec94d..9e9d3f9 100644
--- a/app/assets/javascripts/wizard/test/test_helper.js
+++ b/app/assets/javascripts/wizard/test/test_helper.js
@@ -6,10 +6,10 @@
 //= require ember.debug
 //= require locales/i18n
 //= require locales/en
-//= require route-recognizer/dist/route-recognizer
+//= require route-recognizer
 //= require fake_xml_http_request
-//= require pretender/pretender
-//= require qunit/qunit/qunit
+//= require pretender
+//= require qunit
 //= require ember-qunit
 //= require discourse-loader
 //= require jquery.debug
diff --git a/app/assets/stylesheets/test_helper.css b/app/assets/stylesheets/test_helper.css
deleted file mode 100644
index 4d4cef5..0000000
--- a/app/assets/stylesheets/test_helper.css
+++ /dev/null
@@ -1,10 +0,0 @@
-@import '/stylesheets/desktop.css';
-@import 'qunit/qunit/qunit.css';
-
-.modal-backdrop {
-  display: none;
-}
-
-#reply-control {
-  transition-property: none !important;
-}
diff --git a/app/assets/stylesheets/test_helper.scss b/app/assets/stylesheets/test_helper.scss
new file mode 100644
index 0000000..6666bb4
--- /dev/null
+++ b/app/assets/stylesheets/test_helper.scss
@@ -0,0 +1,9 @@
+@import "vendor/qunit";
+
+.modal-backdrop {
+  display: none;
+}
+
+#reply-control {
+  transition-property: none !important;
+}
diff --git a/app/assets/stylesheets/vendor/qunit.css b/app/assets/stylesheets/vendor/qunit.css
new file mode 100644
index 0000000..9bf0381
--- /dev/null
+++ b/app/assets/stylesheets/vendor/qunit.css
@@ -0,0 +1,436 @@
+/*!
+ * QUnit 2.8.0

[... diff too long, it was truncated ...]

GitHub sha: 4f88f2eb

This commit appears in #12845 which was approved by eviltrout. It was merged by OsamaSayegh.

This commit has been mentioned on Discourse Meta. There might be relevant details there: