DEV: Update plugin-outlet tests (#27630)

qunit-dom, reformat hbs blocks, use `<template>` where possible
This commit is contained in:
Jarek Radosz 2024-06-27 19:36:55 +02:00 committed by GitHub
parent 57eecbef4b
commit 3ce618e57a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 181 additions and 104 deletions

View File

@ -1,16 +1,18 @@
import Component from "@glimmer/component"; import Component from "@glimmer/component";
import { getOwner } from "@ember/application";
import templateOnly from "@ember/component/template-only"; import templateOnly from "@ember/component/template-only";
import { hash } from "@ember/helper";
import { getOwner } from "@ember/owner";
import { click, render, settled } from "@ember/test-helpers"; import { click, render, settled } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars"; import hbs from "htmlbars-inline-precompile";
import { module, test } from "qunit"; import { module, test } from "qunit";
import sinon from "sinon"; import sinon from "sinon";
import PluginOutlet from "discourse/components/plugin-outlet";
import { import {
extraConnectorClass, extraConnectorClass,
extraConnectorComponent, extraConnectorComponent,
} from "discourse/lib/plugin-connectors"; } from "discourse/lib/plugin-connectors";
import { setupRenderingTest } from "discourse/tests/helpers/component-test"; import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { count, exists, query } from "discourse/tests/helpers/qunit-helpers"; import { query } from "discourse/tests/helpers/qunit-helpers";
import { registerTemporaryModule } from "discourse/tests/helpers/temporary-module-helper"; import { registerTemporaryModule } from "discourse/tests/helpers/temporary-module-helper";
import { import {
withSilencedDeprecations, withSilencedDeprecations,
@ -60,25 +62,49 @@ module("Integration | Component | plugin-outlet", function (hooks) {
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/test-name/hello`, `${TEMPLATE_PREFIX}/test-name/hello`,
hbs`<span class='hello-username'>{{this.username}}</span> hbs`
<button type="button" class='say-hello' {{on "click" (action "sayHello")}}></button> <span class="hello-username">{{this.username}}</span>
<button type="button" class='say-hello-using-this' {{on "click" this.sayHello}}></button> <button
<span class='hello-result'>{{this.hello}}</span>` type="button"
class="say-hello"
{{on "click" (action "sayHello")}}
></button>
<button
type="button"
class="say-hello-using-this"
{{on "click" this.sayHello}}
></button>
<span class="hello-result">{{this.hello}}</span>
`
); );
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/test-name/hi`, `${TEMPLATE_PREFIX}/test-name/hi`,
hbs`<button type="button" class='say-hi' {{on "click" (action "sayHi")}}></button> hbs`
<span class='hi-result'>{{this.hi}}</span>` <button
type="button"
class="say-hi"
{{on "click" (action "sayHi")}}
></button>
<span class="hi-result">{{this.hi}}</span>
`
); );
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/test-name/conditional-render`, `${TEMPLATE_PREFIX}/test-name/conditional-render`,
hbs`<span class="conditional-render">I only render sometimes</span>` hbs`
<span class="conditional-render">I only render sometimes</span>
`
); );
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/outlet-with-default/my-connector`, `${TEMPLATE_PREFIX}/outlet-with-default/my-connector`,
hbs`<span class='result'>Plugin implementation{{#if @outletArgs.yieldCore}} {{yield}}{{/if}}</span>` hbs`
<span class="result">Plugin implementation{{#if @outletArgs.yieldCore}}
{{yield}}{{/if}}</span>
`
); );
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/outlet-with-default/clashing-connector`, `${TEMPLATE_PREFIX}/outlet-with-default/clashing-connector`,
hbs`This will override my-connector and raise an error` hbs`This will override my-connector and raise an error`
@ -86,35 +112,28 @@ module("Integration | Component | plugin-outlet", function (hooks) {
}); });
test("Renders a template into the outlet", async function (assert) { test("Renders a template into the outlet", async function (assert) {
this.set("shouldDisplay", false); await render(hbs`<PluginOutlet @name="test-name" />`);
await render(
hbs`<PluginOutlet @name="test-name" @outletArgs={{hash shouldDisplay=this.shouldDisplay}} />` assert
); .dom(".hello-username")
assert.strictEqual(count(".hello-username"), 1, "renders the hello outlet"); .exists({ count: 1 }, "renders the hello outlet");
assert.false( assert
exists(".conditional-render"), .dom(".conditional-render")
"doesn't render conditional outlet" .doesNotExist("doesn't render conditional outlet");
);
await click(".say-hello"); await click(".say-hello");
assert.strictEqual( assert.dom(".hello-result").hasText("hello!", "actions delegate properly");
query(".hello-result").innerText,
"hello!",
"actions delegate properly"
);
await click(".say-hello-using-this"); await click(".say-hello-using-this");
assert.strictEqual( assert
query(".hello-result").innerText, .dom(".hello-result")
"hello!hello!", .hasText(
"actions are made available on `this` and are bound correctly" "hello!hello!",
); "actions are made available on `this` and are bound correctly"
);
await click(".say-hi"); await click(".say-hi");
assert.strictEqual( assert.dom(".hi-result").hasText("hi!", "actions delegate properly");
query(".hi-result").innerText,
"hi!",
"actions delegate properly"
);
}); });
module( module(
@ -146,10 +165,17 @@ module("Integration | Component | plugin-outlet", function (hooks) {
); );
this.template = hbs` this.template = hbs`
<PluginOutlet @name="outlet-with-default" @outletArgs={{hash shouldDisplay=this.shouldDisplay yieldCore=this.yieldCore enableClashingConnector=this.enableClashingConnector}}> <PluginOutlet
<span class='result'>Core implementation</span> @name="outlet-with-default"
</PluginOutlet> @outletArgs={{hash
`; shouldDisplay=this.shouldDisplay
yieldCore=this.yieldCore
enableClashingConnector=this.enableClashingConnector
}}
>
<span class="result">Core implementation</span>
</PluginOutlet>
`;
}); });
test("Can act as a wrapper around core implementation", async function (assert) { test("Can act as a wrapper around core implementation", async function (assert) {
@ -230,12 +256,17 @@ module("Integration | Component | plugin-outlet", function (hooks) {
test("can render content in a automatic outlet generated before the wrapped content", async function (assert) { test("can render content in a automatic outlet generated before the wrapped content", async function (assert) {
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/outlet-with-default__before/my-connector`, `${TEMPLATE_PREFIX}/outlet-with-default__before/my-connector`,
hbs`<span class='before-result'>Before wrapped content</span>` hbs`
<span class="before-result">Before wrapped content</span>
`
); );
await render(hbs` await render(hbs`
<PluginOutlet @name="outlet-with-default" @outletArgs={{hash shouldDisplay=true}}> <PluginOutlet
<span class='result'>Core implementation</span> @name="outlet-with-default"
@outletArgs={{hash shouldDisplay=true}}
>
<span class="result">Core implementation</span>
</PluginOutlet> </PluginOutlet>
`); `);
@ -246,16 +277,25 @@ module("Integration | Component | plugin-outlet", function (hooks) {
test("can render multiple connector `before` the same wrapped content", async function (assert) { test("can render multiple connector `before` the same wrapped content", async function (assert) {
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/outlet-with-default__before/my-connector`, `${TEMPLATE_PREFIX}/outlet-with-default__before/my-connector`,
hbs`<span class='before-result'>First connector before the wrapped content</span>` hbs`
<span class="before-result">First connector before the wrapped
content</span>
`
); );
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/outlet-with-default__before/my-connector2`, `${TEMPLATE_PREFIX}/outlet-with-default__before/my-connector2`,
hbs`<span class='before-result2'>Second connector before the wrapped content</span>` hbs`
<span class="before-result2">Second connector before the wrapped
content</span>
`
); );
await render(hbs` await render(hbs`
<PluginOutlet @name="outlet-with-default" @outletArgs={{hash shouldDisplay=true}}> <PluginOutlet
<span class='result'>Core implementation</span> @name="outlet-with-default"
@outletArgs={{hash shouldDisplay=true}}
>
<span class="result">Core implementation</span>
</PluginOutlet> </PluginOutlet>
`); `);
@ -271,12 +311,17 @@ module("Integration | Component | plugin-outlet", function (hooks) {
test("can render content in a automatic outlet generated after the wrapped content", async function (assert) { test("can render content in a automatic outlet generated after the wrapped content", async function (assert) {
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/outlet-with-default__after/my-connector`, `${TEMPLATE_PREFIX}/outlet-with-default__after/my-connector`,
hbs`<span class='after-result'>After wrapped content</span>` hbs`
<span class="after-result">After wrapped content</span>
`
); );
await render(hbs` await render(hbs`
<PluginOutlet @name="outlet-with-default" @outletArgs={{hash shouldDisplay=true}}> <PluginOutlet
<span class='result'>Core implementation</span> @name="outlet-with-default"
@outletArgs={{hash shouldDisplay=true}}
>
<span class="result">Core implementation</span>
</PluginOutlet> </PluginOutlet>
`); `);
@ -287,16 +332,24 @@ module("Integration | Component | plugin-outlet", function (hooks) {
test("can render multiple connector `after` the same wrapped content", async function (assert) { test("can render multiple connector `after` the same wrapped content", async function (assert) {
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/outlet-with-default__after/my-connector`, `${TEMPLATE_PREFIX}/outlet-with-default__after/my-connector`,
hbs`<span class='after-result'>First connector after the wrapped content</span>` hbs`
<span class="after-result">First connector after the wrapped content</span>
`
); );
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/outlet-with-default__after/my-connector2`, `${TEMPLATE_PREFIX}/outlet-with-default__after/my-connector2`,
hbs`<span class='after-result2'>Second connector after the wrapped content</span>` hbs`
<span class="after-result2">Second connector after the wrapped
content</span>
`
); );
await render(hbs` await render(hbs`
<PluginOutlet @name="outlet-with-default" @outletArgs={{hash shouldDisplay=true}}> <PluginOutlet
<span class='result'>Core implementation</span> @name="outlet-with-default"
@outletArgs={{hash shouldDisplay=true}}
>
<span class="result">Core implementation</span>
</PluginOutlet> </PluginOutlet>
`); `);
@ -312,59 +365,58 @@ module("Integration | Component | plugin-outlet", function (hooks) {
); );
test("Renders wrapped implementation if no connectors are registered", async function (assert) { test("Renders wrapped implementation if no connectors are registered", async function (assert) {
await render( await render(<template>
hbs` <PluginOutlet @name="outlet-with-no-registrations">
<PluginOutlet @name="outlet-with-no-registrations"> <span class="result">Core implementation</span>
<span class='result'>Core implementation</span> </PluginOutlet>
</PluginOutlet> </template>);
`
);
assert.dom(".result").hasText("Core implementation"); assert.dom(".result").hasText("Core implementation");
}); });
test("Reevaluates shouldRender for argument changes", async function (assert) { test("Reevaluates shouldRender for argument changes", async function (assert) {
this.set("shouldDisplay", false); this.set("shouldDisplay", false);
await render( await render(hbs`
hbs`<PluginOutlet @name="test-name" @outletArgs={{hash shouldDisplay=this.shouldDisplay}} />` <PluginOutlet
); @name="test-name"
assert.false( @outletArgs={{hash shouldDisplay=this.shouldDisplay}}
exists(".conditional-render"), />
"doesn't render conditional outlet" `);
); assert
.dom(".conditional-render")
.doesNotExist("doesn't render conditional outlet");
this.set("shouldDisplay", true); this.set("shouldDisplay", true);
await settled(); await settled();
assert.true(exists(".conditional-render"), "renders conditional outlet"); assert.dom(".conditional-render").exists("renders conditional outlet");
}); });
test("Reevaluates shouldRender for other autotracked changes", async function (assert) { test("Reevaluates shouldRender for other autotracked changes", async function (assert) {
this.set("shouldDisplay", false); await render(hbs`<PluginOutlet @name="test-name" />`);
await render( assert
hbs`<PluginOutlet @name="test-name" @outletArgs={{hash shouldDisplay=this.shouldDisplay}} />` .dom(".conditional-render")
); .doesNotExist("doesn't render conditional outlet");
assert.false(
exists(".conditional-render"),
"doesn't render conditional outlet"
);
getOwner(this).lookup("service:site-settings").always_display = true; getOwner(this).lookup("service:site-settings").always_display = true;
await settled(); await settled();
assert.true(exists(".conditional-render"), "renders conditional outlet"); assert.dom(".conditional-render").exists("renders conditional outlet");
}); });
test("Other outlets are not re-rendered", async function (assert) { test("Other outlets are not re-rendered", async function (assert) {
this.set("shouldDisplay", false); this.set("shouldDisplay", false);
await render( await render(hbs`
hbs`<PluginOutlet @name="test-name" @outletArgs={{hash shouldDisplay=this.shouldDisplay}} />` <PluginOutlet
); @name="test-name"
@outletArgs={{hash shouldDisplay=this.shouldDisplay}}
/>
`);
const otherOutletElement = query(".hello-username"); const otherOutletElement = query(".hello-username");
otherOutletElement.someUniqueProperty = true; otherOutletElement.someUniqueProperty = true;
this.set("shouldDisplay", true); this.set("shouldDisplay", true);
await settled(); await settled();
assert.true(exists(".conditional-render"), "renders conditional outlet"); assert.dom(".conditional-render").exists("renders conditional outlet");
assert.true( assert.true(
query(".hello-username").someUniqueProperty, query(".hello-username").someUniqueProperty,
@ -381,23 +433,31 @@ module(
hooks.beforeEach(function () { hooks.beforeEach(function () {
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/test-name/my-connector`, `${TEMPLATE_PREFIX}/test-name/my-connector`,
hbs`<span class='outletArgHelloValue'>{{@outletArgs.hello}}</span><span class='thisHelloValue'>{{this.hello}}</span>` hbs`
<span class="outletArgHelloValue">{{@outletArgs.hello}}</span><span
class="thisHelloValue"
>{{this.hello}}</span>
`
); );
}); });
test("uses classic PluginConnector by default", async function (assert) { test("uses classic PluginConnector by default", async function (assert) {
await render( await render(hbs`
hbs`<PluginOutlet @name="test-name" @outletArgs={{hash hello="world"}} />` <PluginOutlet @name="test-name" @outletArgs={{hash hello="world"}} />
); `);
assert.dom(".outletArgHelloValue").hasText("world"); assert.dom(".outletArgHelloValue").hasText("world");
assert.dom(".thisHelloValue").hasText("world"); assert.dom(".thisHelloValue").hasText("world");
}); });
test("uses templateOnly by default when @defaultGlimmer=true", async function (assert) { test("uses templateOnly by default when @defaultGlimmer=true", async function (assert) {
await render( await render(hbs`
hbs`<PluginOutlet @name="test-name" @outletArgs={{hash hello="world"}} @defaultGlimmer={{true}} />` <PluginOutlet
); @name="test-name"
@outletArgs={{hash hello="world"}}
@defaultGlimmer={{true}}
/>
`);
assert.dom(".outletArgHelloValue").hasText("world"); assert.dom(".outletArgHelloValue").hasText("world");
assert.dom(".thisHelloValue").hasText(""); // `this.` unavailable in templateOnly components assert.dom(".thisHelloValue").hasText(""); // `this.` unavailable in templateOnly components
@ -420,9 +480,12 @@ module(
}, },
}); });
await render( await render(hbs`
hbs`<PluginOutlet @name="test-name" @outletArgs={{hash hello="world" someBoolean=this.someBoolean}} />` <PluginOutlet
); @name="test-name"
@outletArgs={{hash hello="world" someBoolean=this.someBoolean}}
/>
`);
assert.dom(".outletArgHelloValue").hasText("world"); assert.dom(".outletArgHelloValue").hasText("world");
assert.dom(".thisHelloValue").hasText("world from setupComponent"); assert.dom(".thisHelloValue").hasText("world from setupComponent");
@ -447,9 +510,13 @@ module(
await withSilencedDeprecationsAsync( await withSilencedDeprecationsAsync(
"discourse.plugin-outlet-classic-hooks", "discourse.plugin-outlet-classic-hooks",
async () => { async () => {
await render( await render(<template>
hbs`<PluginOutlet @name="test-name" @outletArgs={{hash hello="world"}} @defaultGlimmer={{true}} />` <PluginOutlet
); @name="test-name"
@outletArgs={{hash hello="world"}}
@defaultGlimmer={{true}}
/>
</template>);
} }
); );
@ -473,9 +540,12 @@ module(
} }
); );
await render( await render(hbs`
hbs`<PluginOutlet @name="test-name" @outletArgs={{hash hello="world" someBoolean=this.someBoolean}} />` <PluginOutlet
); @name="test-name"
@outletArgs={{hash hello="world" someBoolean=this.someBoolean}}
/>
`);
assert.dom(".outletArgHelloValue").hasText("world"); assert.dom(".outletArgHelloValue").hasText("world");
assert.dom(".thisHelloValue").hasText("world from custom component"); assert.dom(".thisHelloValue").hasText("world from custom component");
@ -498,9 +568,12 @@ module(
}) })
); );
await render( await render(hbs`
hbs`<PluginOutlet @name="test-name" @outletArgs={{hash hello="world" someBoolean=this.someBoolean}} />` <PluginOutlet
); @name="test-name"
@outletArgs={{hash hello="world" someBoolean=this.someBoolean}}
/>
`);
assert.dom(".outletArgHelloValue").hasText("world"); assert.dom(".outletArgHelloValue").hasText("world");
assert.dom(".thisHelloValue").hasText(""); // `this.` unavailable in templateOnly components assert.dom(".thisHelloValue").hasText(""); // `this.` unavailable in templateOnly components
@ -526,7 +599,7 @@ module(
}); });
test("detects a gjs connector with no associated template file", async function (assert) { test("detects a gjs connector with no associated template file", async function (assert) {
await render(hbs`<PluginOutlet @name="test-name" />`); await render(<template><PluginOutlet @name="test-name" /></template>);
assert.dom(".gjs-test").hasText("Hello world"); assert.dom(".gjs-test").hasText("Hello world");
}); });
@ -545,7 +618,7 @@ module(
}); });
test("renders the component in the outlet", async function (assert) { test("renders the component in the outlet", async function (assert) {
await render(hbs`<PluginOutlet @name="test-name" />`); await render(<template><PluginOutlet @name="test-name" /></template>);
assert.dom(".gjs-test").hasText("Hello world from gjs"); assert.dom(".gjs-test").hasText("Hello world from gjs");
}); });
@ -574,7 +647,9 @@ module("Integration | Component | plugin-outlet | tagName", function (hooks) {
await withSilencedDeprecationsAsync( await withSilencedDeprecationsAsync(
"discourse.plugin-outlet-tag-name", "discourse.plugin-outlet-tag-name",
async () => async () =>
await render(hbs`<PluginOutlet @name="test-name" @tagName="div" />`) await render(<template>
<PluginOutlet @name="test-name" @tagName="div" />
</template>)
); );
assert.dom("div").exists(); assert.dom("div").exists();
}); });
@ -588,7 +663,9 @@ module(
hooks.beforeEach(function () { hooks.beforeEach(function () {
registerTemporaryModule( registerTemporaryModule(
`${TEMPLATE_PREFIX}/test-name/my-legacy-connector`, `${TEMPLATE_PREFIX}/test-name/my-legacy-connector`,
hbs`<span class='legacy-test'>Hello world {{this.someVar}}</span>` hbs`
<span class="legacy-test">Hello world {{this.someVar}}</span>
`
); );
withSilencedDeprecations( withSilencedDeprecations(