diff --git a/app/assets/javascripts/discourse/app/components/plugin-outlet.js b/app/assets/javascripts/discourse/app/components/plugin-outlet.js
index f73fbbcd12e..11a7f28641c 100644
--- a/app/assets/javascripts/discourse/app/components/plugin-outlet.js
+++ b/app/assets/javascripts/discourse/app/components/plugin-outlet.js
@@ -56,10 +56,8 @@ export default class PluginOutletComponent extends GlimmerComponentWithDeprecate
},
};
- constructor() {
- super(...arguments);
-
- this.connectors = renderedConnectorsFor(
+ get connectors() {
+ return renderedConnectorsFor(
this.args.name,
this.outletArgsWithDeprecations,
this.context
diff --git a/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-connector-class-test.js b/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-connector-class-test.js
deleted file mode 100644
index f5186065f1b..00000000000
--- a/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-connector-class-test.js
+++ /dev/null
@@ -1,102 +0,0 @@
-import {
- acceptance,
- count,
- exists,
- query,
-} from "discourse/tests/helpers/qunit-helpers";
-import { click, visit } from "@ember/test-helpers";
-import { action } from "@ember/object";
-import { extraConnectorClass } from "discourse/lib/plugin-connectors";
-import { hbs } from "ember-cli-htmlbars";
-import { test } from "qunit";
-import { registerTemporaryModule } from "discourse/tests/helpers/temporary-module-helper";
-
-const PREFIX = "discourse/plugins/some-plugin/templates/connectors";
-
-acceptance("Plugin Outlet - Connector Class", function (needs) {
- needs.hooks.beforeEach(() => {
- extraConnectorClass("user-profile-primary/hello", {
- actions: {
- sayHello() {
- this.set("hello", `${this.hello || ""}hello!`);
- },
- },
- });
-
- extraConnectorClass("user-profile-primary/hi", {
- setupComponent() {
- this.appEvents.on("hi:sayHi", this, this.say);
- },
-
- teardownComponent() {
- this.appEvents.off("hi:sayHi", this, this.say);
- },
-
- @action
- say() {
- this.set("hi", "hi!");
- },
-
- @action
- sayHi() {
- this.appEvents.trigger("hi:sayHi");
- },
- });
-
- extraConnectorClass("user-profile-primary/dont-render", {
- shouldRender(args) {
- return args.model.get("username") !== "eviltrout";
- },
- });
-
- registerTemporaryModule(
- `${PREFIX}/user-profile-primary/hello`,
- hbs`{{model.username}}
-
-
- {{hello}}`
- );
- registerTemporaryModule(
- `${PREFIX}/user-profile-primary/hi`,
- hbs`
- {{hi}}`
- );
- registerTemporaryModule(
- `${PREFIX}/user-profile-primary/dont-render`,
- hbs`I'm not rendered!`
- );
- });
-
- test("Renders a template into the outlet", async function (assert) {
- await visit("/u/eviltrout");
- assert.strictEqual(
- count(".user-profile-primary-outlet.hello"),
- 1,
- "it has class names"
- );
- assert.ok(
- !exists(".user-profile-primary-outlet.dont-render"),
- "doesn't render"
- );
-
- await click(".say-hello");
- assert.strictEqual(
- query(".hello-result").innerText,
- "hello!",
- "actions delegate properly"
- );
- await click(".say-hello-using-this");
- assert.strictEqual(
- query(".hello-result").innerText,
- "hello!hello!",
- "actions are made available on `this` and are bound correctly"
- );
-
- await click(".say-hi");
- assert.strictEqual(
- query(".hi-result").innerText,
- "hi!",
- "actions delegate properly"
- );
- });
-});
diff --git a/app/assets/javascripts/discourse/tests/integration/components/plugin-outlet-test.js b/app/assets/javascripts/discourse/tests/integration/components/plugin-outlet-test.js
new file mode 100644
index 00000000000..fa45cfb08cc
--- /dev/null
+++ b/app/assets/javascripts/discourse/tests/integration/components/plugin-outlet-test.js
@@ -0,0 +1,149 @@
+import { module, test } from "qunit";
+import { count, exists, query } from "discourse/tests/helpers/qunit-helpers";
+import { setupRenderingTest } from "discourse/tests/helpers/component-test";
+import { click, render, settled } from "@ember/test-helpers";
+import { action } from "@ember/object";
+import { extraConnectorClass } from "discourse/lib/plugin-connectors";
+import { hbs } from "ember-cli-htmlbars";
+import { registerTemporaryModule } from "discourse/tests/helpers/temporary-module-helper";
+import { getOwner } from "discourse-common/lib/get-owner";
+
+const PREFIX = "discourse/plugins/some-plugin/templates/connectors";
+
+module("Integration | Component | plugin-outlet", function (hooks) {
+ setupRenderingTest(hooks);
+
+ hooks.beforeEach(function () {
+ extraConnectorClass("test-name/hello", {
+ actions: {
+ sayHello() {
+ this.set("hello", `${this.hello || ""}hello!`);
+ },
+ },
+ });
+
+ extraConnectorClass("test-name/hi", {
+ setupComponent() {
+ this.appEvents.on("hi:sayHi", this, this.say);
+ },
+
+ teardownComponent() {
+ this.appEvents.off("hi:sayHi", this, this.say);
+ },
+
+ @action
+ say() {
+ this.set("hi", "hi!");
+ },
+
+ @action
+ sayHi() {
+ this.appEvents.trigger("hi:sayHi");
+ },
+ });
+
+ extraConnectorClass("test-name/conditional-render", {
+ shouldRender(args, context) {
+ return args.shouldDisplay || context.siteSettings.always_display;
+ },
+ });
+
+ registerTemporaryModule(
+ `${PREFIX}/test-name/hello`,
+ hbs`{{username}}
+
+
+ {{hello}}`
+ );
+ registerTemporaryModule(
+ `${PREFIX}/test-name/hi`,
+ hbs`
+ {{hi}}`
+ );
+ registerTemporaryModule(
+ `${PREFIX}/test-name/conditional-render`,
+ hbs`I only render sometimes`
+ );
+ });
+
+ test("Renders a template into the outlet", async function (assert) {
+ this.set("shouldDisplay", false);
+ await render(
+ hbs``
+ );
+ assert.strictEqual(count(".hello-username"), 1, "renders the hello outlet");
+ assert.false(
+ exists(".conditional-render"),
+ "doesn't render conditional outlet"
+ );
+
+ await click(".say-hello");
+ assert.strictEqual(
+ query(".hello-result").innerText,
+ "hello!",
+ "actions delegate properly"
+ );
+ await click(".say-hello-using-this");
+ assert.strictEqual(
+ query(".hello-result").innerText,
+ "hello!hello!",
+ "actions are made available on `this` and are bound correctly"
+ );
+
+ await click(".say-hi");
+ assert.strictEqual(
+ query(".hi-result").innerText,
+ "hi!",
+ "actions delegate properly"
+ );
+ });
+
+ test("Reevaluates shouldRender for argument changes", async function (assert) {
+ this.set("shouldDisplay", false);
+ await render(
+ hbs``
+ );
+ assert.false(
+ exists(".conditional-render"),
+ "doesn't render conditional outlet"
+ );
+
+ this.set("shouldDisplay", true);
+ await settled();
+ assert.true(exists(".conditional-render"), "renders conditional outlet");
+ });
+
+ test("Reevaluates shouldRender for other autotracked changes", async function (assert) {
+ this.set("shouldDisplay", false);
+ await render(
+ hbs``
+ );
+ assert.false(
+ exists(".conditional-render"),
+ "doesn't render conditional outlet"
+ );
+
+ getOwner(this).lookup("service:site-settings").always_display = true;
+ await settled();
+ assert.true(exists(".conditional-render"), "renders conditional outlet");
+ });
+
+ test("Other outlets are not re-rendered", async function (assert) {
+ this.set("shouldDisplay", false);
+ await render(
+ hbs``
+ );
+
+ const otherOutletElement = query(".hello-username");
+ otherOutletElement.someUniqueProperty = true;
+
+ this.set("shouldDisplay", true);
+ await settled();
+ assert.true(exists(".conditional-render"), "renders conditional outlet");
+
+ assert.true(
+ query(".hello-username").someUniqueProperty,
+ "other outlet is left untouched"
+ );
+ });
+});