FEATURE: Allow theme tests to be run in production (#12815)

FEATURE: Allow theme tests to be run in production (#12815)

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/setup-tests.js b/app/assets/javascripts/discourse/tests/setup-tests.js
index df1c06c..0ced9c4 100644
--- a/app/assets/javascripts/discourse/tests/setup-tests.js
+++ b/app/assets/javascripts/discourse/tests/setup-tests.js
@@ -253,7 +253,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 +262,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/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
+ * https://qunitjs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2018-11-02T16:17Z
+ */
+
+/** Font Family and Sizes */
+
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult {
+	font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
+}
+
+#qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
+#qunit-tests { font-size: smaller; }
+
+
+/** Resets */
+
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
+	margin: 0;
+	padding: 0;
+}
+
+
+/** Header (excluding toolbar) */
+
+#qunit-header {
+	padding: 0.5em 0 0.5em 1em;
+
+	color: #8699A4;
+	background-color: #0D3349;
+
+	font-size: 1.5em;
+	line-height: 1em;
+	font-weight: 400;
+
+	border-radius: 5px 5px 0 0;
+}
+
+#qunit-header a {
+	text-decoration: none;
+	color: #C2CCD1;
+}
+
+#qunit-header a:hover,
+#qunit-header a:focus {
+	color: #FFF;
+}
+
+#qunit-banner {
+	height: 5px;
+}
+
+#qunit-filteredTest {
+	padding: 0.5em 1em 0.5em 1em;
+	color: #366097;
+	background-color: #F4FF77;
+}
+
+#qunit-userAgent {
+	padding: 0.5em 1em 0.5em 1em;
+	color: #FFF;
+	background-color: #2B81AF;
+	text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
+}
+
+
+/** Toolbar */
+
+#qunit-testrunner-toolbar {
+	padding: 0.5em 1em 0.5em 1em;
+	color: #5E740B;
+	background-color: #EEE;
+}
+
+#qunit-testrunner-toolbar .clearfix {
+	height: 0;
+	clear: both;
+}
+
+#qunit-testrunner-toolbar label {
+	display: inline-block;
+}
+
+#qunit-testrunner-toolbar input[type=checkbox],
+#qunit-testrunner-toolbar input[type=radio] {
+	margin: 3px;
+	vertical-align: -2px;
+}
+
+#qunit-testrunner-toolbar input[type=text] {
+	box-sizing: border-box;
+	height: 1.6em;
+}
+
+.qunit-url-config,
+.qunit-filter,
+#qunit-modulefilter {
+	display: inline-block;
+	line-height: 2.1em;
+}
+
+.qunit-filter,
+#qunit-modulefilter {
+	float: right;
+	position: relative;
+	margin-left: 1em;
+}
+
+.qunit-url-config label {
+	margin-right: 0.5em;
+}
+
+#qunit-modulefilter-search {
+	box-sizing: border-box;
+	width: 400px;
+}
+
+#qunit-modulefilter-search-container:after {
+	position: absolute;
+	right: 0.3em;
+	content: "\25bc";
+	color: black;
+}
+
+#qunit-modulefilter-dropdown {
+	/* align with #qunit-modulefilter-search */
+	box-sizing: border-box;
+	width: 400px;
+	position: absolute;
+	right: 0;
+	top: 50%;
+	margin-top: 0.8em;
+
+	border: 1px solid #D3D3D3;
+	border-top: none;
+	border-radius: 0 0 .25em .25em;
+	color: #000;
+	background-color: #F5F5F5;
+	z-index: 99;
+}
+
+#qunit-modulefilter-dropdown a {
+	color: inherit;
+	text-decoration: none;
+}
+
+#qunit-modulefilter-dropdown .clickable.checked {
+	font-weight: bold;
+	color: #000;
+	background-color: #D2E0E6;
+}
+
+#qunit-modulefilter-dropdown .clickable:hover {
+	color: #FFF;
+	background-color: #0D3349;
+}
+
+#qunit-modulefilter-actions {
+	display: block;
+	overflow: auto;
+
+	/* align with #qunit-modulefilter-dropdown-list */
+	font: smaller/1.5em sans-serif;
+}
+
+#qunit-modulefilter-dropdown #qunit-modulefilter-actions > * {
+	box-sizing: border-box;
+	max-height: 2.8em;
+	display: block;
+	padding: 0.4em;
+}
+
+#qunit-modulefilter-dropdown #qunit-modulefilter-actions > button {
+	float: right;
+	font: inherit;
+}
+
+#qunit-modulefilter-dropdown #qunit-modulefilter-actions > :last-child {
+	/* insert padding to align with checkbox margins */
+	padding-left: 3px;
+}
+

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

GitHub sha: 7217dcb6

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