diff --git a/app/assets/javascripts/discourse/lib/bootstrap-json/index.js b/app/assets/javascripts/discourse/lib/bootstrap-json/index.js
index b2b243fdc56..1c778d80a02 100644
--- a/app/assets/javascripts/discourse/lib/bootstrap-json/index.js
+++ b/app/assets/javascripts/discourse/lib/bootstrap-json/index.js
@@ -429,6 +429,8 @@ module.exports = {
``
)
.join("\n");
+ } else if (shouldLoadPluginTestJs() && type === "test-plugin-css") {
+ return ``;
}
},
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
index fc0237c6225..8041b5141bd 100644
--- 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
@@ -3,26 +3,32 @@ 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;
+(async function setup() {
+ 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);
+
+ if (clone.tagName === "LINK" && clone["rel"] === "stylesheet") {
+ await new Promise((resolve) => (clone.onload = resolve));
+ }
}
-
- 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/testem.js b/app/assets/javascripts/discourse/testem.js
index fbc39514183..1bcc31d2cda 100644
--- a/app/assets/javascripts/discourse/testem.js
+++ b/app/assets/javascripts/discourse/testem.js
@@ -105,5 +105,11 @@ if (process.argv.includes("-t")) {
"/plugins/": {
target,
},
+ "/bootstrap/plugin-css-for-tests.css": {
+ target,
+ },
+ "/stylesheets/": {
+ target,
+ },
};
}
diff --git a/app/assets/javascripts/discourse/tests/index.html b/app/assets/javascripts/discourse/tests/index.html
index 3277f0b1cc6..c286633609f 100644
--- a/app/assets/javascripts/discourse/tests/index.html
+++ b/app/assets/javascripts/discourse/tests/index.html
@@ -52,6 +52,7 @@
+ {{content-for "test-plugin-css"}}
{{content-for "test-plugin-js"}}
diff --git a/app/controllers/bootstrap_controller.rb b/app/controllers/bootstrap_controller.rb
index 235308de3ff..8f7c4b4f62b 100644
--- a/app/controllers/bootstrap_controller.rb
+++ b/app/controllers/bootstrap_controller.rb
@@ -3,7 +3,7 @@
class BootstrapController < ApplicationController
include ApplicationHelper
- skip_before_action :redirect_to_login_if_required
+ skip_before_action :redirect_to_login_if_required, :check_xhr
# This endpoint allows us to produce the data required to start up Discourse via JSON API,
# so that you don't have to scrape the HTML for `data-*` payloads
@@ -98,6 +98,23 @@ class BootstrapController < ApplicationController
render_json_dump(bootstrap: bootstrap)
end
+ def plugin_css_for_tests
+ urls = Discourse.find_plugin_css_assets(
+ include_disabled: true,
+ desktop_view: true,
+ ).map do |target|
+ details = Stylesheet::Manager.new().stylesheet_details(target, 'all')
+ details[0][:new_href]
+ end
+
+ stylesheet = <<~CSS
+ /* For use in tests only - `@import`s all plugin stylesheets */
+ #{urls.map { |url| "@import \"#{url}\";" }.join("\n") }
+ CSS
+
+ render plain: stylesheet, content_type: 'text/css'
+ end
+
private
def add_scheme(scheme_id, media, css_class)
return if scheme_id.to_i == -1
diff --git a/config/routes.rb b/config/routes.rb
index cbb1ee51977..0092fec3f01 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -17,6 +17,9 @@ Discourse::Application.routes.draw do
get "/404-body" => "exceptions#not_found_body"
get "/bootstrap" => "bootstrap#index"
+ if Rails.env.test? || Rails.env.development?
+ get "/bootstrap/plugin-css-for-tests.css" => "bootstrap#plugin_css_for_tests"
+ end
post "webhooks/aws" => "webhooks#aws"
post "webhooks/mailgun" => "webhooks#mailgun"
diff --git a/plugins/poll/test/javascripts/widgets/discourse-poll-test.js b/plugins/poll/test/javascripts/widgets/discourse-poll-test.js
index b75ada49602..546392129a1 100644
--- a/plugins/poll/test/javascripts/widgets/discourse-poll-test.js
+++ b/plugins/poll/test/javascripts/widgets/discourse-poll-test.js
@@ -1,7 +1,12 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { click, render } from "@ember/test-helpers";
-import { count, exists, query } from "discourse/tests/helpers/qunit-helpers";
+import {
+ count,
+ exists,
+ query,
+ queryAll,
+} from "discourse/tests/helpers/qunit-helpers";
import hbs from "htmlbars-inline-precompile";
import pretender, { response } from "discourse/tests/helpers/create-pretender";
import EmberObject from "@ember/object";
@@ -85,7 +90,10 @@ module("Integration | Component | Widget | discourse-poll", function (hooks) {
await click("li[data-poll-option-id='1f972d1df351de3ce35a787c89faad29']");
assert.strictEqual(requests, 1);
assert.strictEqual(count(".chosen"), 1);
- assert.strictEqual(query(".chosen").innerText, "100%yes");
+ assert.deepEqual(
+ Array.from(queryAll(".chosen span")).map((span) => span.innerText),
+ ["100%", "yes"]
+ );
await click(".toggle-results");
assert.strictEqual(