DEV: Convert tests using the gjs codemod (#31625)

```sh
pnpm dlx @embroider/template-tag-codemod@alpha --relativeLocalPaths=false --nativeRouteTemplates=false --nativeLexicalThis=false --templateInsertion="end"
```
This commit is contained in:
Jarek Radosz 2025-03-05 01:37:30 +01:00 committed by GitHub
parent 28e00d9bfe
commit 72ba574d6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
83 changed files with 3169 additions and 1339 deletions

View File

@ -5,6 +5,10 @@
"description": "A platform for community discussion. Free, open, simple.",
"license": "GPL-2.0-only",
"author": "Discourse",
"exports": {
"./tests/*": "./tests/*",
"./*": "./app/*"
},
"directories": {
"doc": "doc",
"test": "tests"

View File

@ -1,40 +1,52 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import includes from "truth-helpers/helpers/includes";
module("Addons | truth-helpers | Integration | includes", function (hooks) {
setupRenderingTest(hooks);
test("when using an array", async function (assert) {
const self = this;
this.foo = [1];
this.bar = 1;
await render(
hbs`{{#if (includes this.foo this.bar)}}<span class="test"></span>{{/if}}`
<template>
{{#if (includes self.foo self.bar)}}<span class="test"></span>{{/if}}
</template>
);
assert.dom(".test").exists("is true when element is found");
this.bar = 2;
await render(
hbs`{{#if (includes this.foo this.bar)}}<span class="test"></span>{{/if}}`
<template>
{{#if (includes self.foo self.bar)}}<span class="test"></span>{{/if}}
</template>
);
assert.dom(".test").doesNotExist("is false when element is not found");
});
test("when using a string", async function (assert) {
const self = this;
this.foo = "foo";
this.bar = "f";
await render(
hbs`{{#if (includes this.foo this.bar)}}<span class="test"></span>{{/if}}`
<template>
{{#if (includes self.foo self.bar)}}<span class="test"></span>{{/if}}
</template>
);
assert.dom(".test").exists("is true when element is found");
this.bar = "b";
await render(
hbs`{{#if (includes this.foo this.bar)}}<span class="test"></span>{{/if}}`
<template>
{{#if (includes self.foo self.bar)}}<span class="test"></span>{{/if}}
</template>
);
assert.dom(".test").doesNotExist("is false when element is not found");

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import ActivationControls from "discourse/components/activation-controls";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | activation-controls", function (hooks) {
@ -10,7 +10,7 @@ module("Integration | Component | activation-controls", function (hooks) {
this.siteSettings.enable_local_logins = false;
this.siteSettings.email_editable = false;
await render(hbs`<ActivationControls />`);
await render(<template><ActivationControls /></template>);
assert.dom("button.edit-email").doesNotExist();
});

View File

@ -1,39 +1,47 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import BadgeButton from "discourse/components/badge-button";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | badge-button", function (hooks) {
setupRenderingTest(hooks);
test("disabled badge", async function (assert) {
const self = this;
this.set("badge", { enabled: false });
await render(hbs`<BadgeButton @badge={{this.badge}} />`);
await render(<template><BadgeButton @badge={{self.badge}} /></template>);
assert.dom(".user-badge.disabled").exists();
});
test("enabled badge", async function (assert) {
const self = this;
this.set("badge", { enabled: true });
await render(hbs`<BadgeButton @badge={{this.badge}} />`);
await render(<template><BadgeButton @badge={{self.badge}} /></template>);
assert.dom(".user-badge.disabled").doesNotExist();
});
test("data-badge-name", async function (assert) {
const self = this;
this.set("badge", { name: "foo" });
await render(hbs`<BadgeButton @badge={{this.badge}} />`);
await render(<template><BadgeButton @badge={{self.badge}} /></template>);
assert.dom('.user-badge[data-badge-name="foo"]').exists();
});
test("title", async function (assert) {
const self = this;
this.set("badge", { description: "a <a href>good</a> run" });
await render(hbs`<BadgeButton @badge={{this.badge}} />`);
await render(<template><BadgeButton @badge={{self.badge}} /></template>);
assert
.dom(".user-badge")
@ -51,47 +59,61 @@ module("Integration | Component | badge-button", function (hooks) {
});
test("icon", async function (assert) {
const self = this;
this.set("badge", { icon: "xmark" });
await render(hbs`<BadgeButton @badge={{this.badge}} />`);
await render(<template><BadgeButton @badge={{self.badge}} /></template>);
assert.dom(".d-icon.d-icon-xmark").exists();
});
test("accepts block", async function (assert) {
const self = this;
this.set("badge", {});
await render(hbs`
<BadgeButton @badge={{this.badge}}>
<span class="test"></span>
</BadgeButton>
`);
await render(
<template>
<BadgeButton @badge={{self.badge}}>
<span class="test"></span>
</BadgeButton>
</template>
);
assert.dom(".test").exists();
});
test("badgeTypeClassName", async function (assert) {
const self = this;
this.set("badge", { badgeTypeClassName: "foo" });
await render(hbs`<BadgeButton @badge={{this.badge}} />`);
await render(<template><BadgeButton @badge={{self.badge}} /></template>);
assert.dom(".user-badge.foo").exists();
});
test("setting showName to false hides the name", async function (assert) {
const self = this;
this.set("badge", { name: "foo" });
await render(
hbs`<BadgeButton @badge={{this.badge}} @showName={{false}} />`
<template>
<BadgeButton @badge={{self.badge}} @showName={{false}} />
</template>
);
assert.dom(".badge-display-name").doesNotExist();
});
test("showName defaults to true", async function (assert) {
const self = this;
this.set("badge", { name: "foo" });
await render(hbs`<BadgeButton @badge={{this.badge}} />`);
await render(<template><BadgeButton @badge={{self.badge}} /></template>);
assert.dom(".badge-display-name").exists();
});

View File

@ -1,7 +1,7 @@
import EmberObject from "@ember/object";
import { click, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import BadgeTitle from "discourse/components/badge-title";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import pretender, { response } from "discourse/tests/helpers/create-pretender";
import selectKit from "discourse/tests/helpers/select-kit-helper";
@ -10,6 +10,8 @@ module("Integration | Component | badge-title", function (hooks) {
setupRenderingTest(hooks);
test("badge title", async function (assert) {
const self = this;
this.set("subject", selectKit());
this.set("selectableUserBadges", [
EmberObject.create({
@ -25,9 +27,11 @@ module("Integration | Component | badge-title", function (hooks) {
pretender.put("/u/eviltrout/preferences/badge_title", () => response({}));
await render(hbs`
<BadgeTitle @selectableUserBadges={{this.selectableUserBadges}} />
`);
await render(
<template>
<BadgeTitle @selectableUserBadges={{self.selectableUserBadges}} />
</template>
);
await this.subject.expand();
await this.subject.selectRowByValue(42);

View File

@ -1,7 +1,7 @@
import { getOwner } from "@ember/owner";
import { click, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import BulkSelectTopicsDropdown from "discourse/components/bulk-select-topics-dropdown";
import BulkSelectHelper from "discourse/lib/bulk-select-helper";
import { TOPIC_VISIBILITY_REASONS } from "discourse/lib/constants";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
@ -45,11 +45,15 @@ module("Integration | Component | BulkSelectTopicsDropdown", function (hooks) {
setupRenderingTest(hooks);
test("actions all topics can perform", async function (assert) {
const self = this;
this.currentUser.admin = true;
this.bulkSelectHelper = createBulkSelectHelper(this);
await render(
hbs`<BulkSelectTopicsDropdown @bulkSelectHelper={{this.bulkSelectHelper}} />`
<template>
<BulkSelectTopicsDropdown @bulkSelectHelper={{self.bulkSelectHelper}} />
</template>
);
await click(".bulk-select-topics-dropdown-trigger");
@ -73,13 +77,17 @@ module("Integration | Component | BulkSelectTopicsDropdown", function (hooks) {
});
test("does not allow unlisting topics that are already unlisted", async function (assert) {
const self = this;
this.currentUser.admin = true;
this.bulkSelectHelper = createBulkSelectHelper(this, {
topicIds: [UNLISTED_TOPIC_ID],
});
await render(
hbs`<BulkSelectTopicsDropdown @bulkSelectHelper={{this.bulkSelectHelper}} />`
<template>
<BulkSelectTopicsDropdown @bulkSelectHelper={{self.bulkSelectHelper}} />
</template>
);
await click(".bulk-select-topics-dropdown-trigger");
@ -89,13 +97,17 @@ module("Integration | Component | BulkSelectTopicsDropdown", function (hooks) {
});
test("does not allow relisting topics that are already visible", async function (assert) {
const self = this;
this.currentUser.admin = true;
this.bulkSelectHelper = createBulkSelectHelper(this, {
topicIds: [REGULAR_TOPIC_ID],
});
await render(
hbs`<BulkSelectTopicsDropdown @bulkSelectHelper={{this.bulkSelectHelper}} />`
<template>
<BulkSelectTopicsDropdown @bulkSelectHelper={{self.bulkSelectHelper}} />
</template>
);
await click(".bulk-select-topics-dropdown-trigger");
@ -105,12 +117,16 @@ module("Integration | Component | BulkSelectTopicsDropdown", function (hooks) {
});
test("allows deferring topics if the user has the preference enabled", async function (assert) {
const self = this;
this.currentUser.admin = true;
this.currentUser.user_option.enable_defer = true;
this.bulkSelectHelper = createBulkSelectHelper(this);
await render(
hbs`<BulkSelectTopicsDropdown @bulkSelectHelper={{this.bulkSelectHelper}} />`
<template>
<BulkSelectTopicsDropdown @bulkSelectHelper={{self.bulkSelectHelper}} />
</template>
);
await click(".bulk-select-topics-dropdown-trigger");
@ -120,12 +136,16 @@ module("Integration | Component | BulkSelectTopicsDropdown", function (hooks) {
});
test("does not allow tagging actions if tagging_enabled is false", async function (assert) {
const self = this;
this.currentUser.admin = true;
this.siteSettings.tagging_enabled = false;
this.bulkSelectHelper = createBulkSelectHelper(this);
await render(
hbs`<BulkSelectTopicsDropdown @bulkSelectHelper={{this.bulkSelectHelper}} />`
<template>
<BulkSelectTopicsDropdown @bulkSelectHelper={{self.bulkSelectHelper}} />
</template>
);
await click(".bulk-select-topics-dropdown-trigger");
@ -137,10 +157,14 @@ module("Integration | Component | BulkSelectTopicsDropdown", function (hooks) {
});
test("does not allow tagging actions if user cannot manage topic", async function (assert) {
const self = this;
this.bulkSelectHelper = createBulkSelectHelper(this);
await render(
hbs`<BulkSelectTopicsDropdown @bulkSelectHelper={{this.bulkSelectHelper}} />`
<template>
<BulkSelectTopicsDropdown @bulkSelectHelper={{self.bulkSelectHelper}} />
</template>
);
await click(".bulk-select-topics-dropdown-trigger");
@ -152,10 +176,14 @@ module("Integration | Component | BulkSelectTopicsDropdown", function (hooks) {
});
test("does not allow deleting topics if user is not staff", async function (assert) {
const self = this;
this.bulkSelectHelper = createBulkSelectHelper(this);
await render(
hbs`<BulkSelectTopicsDropdown @bulkSelectHelper={{this.bulkSelectHelper}} />`
<template>
<BulkSelectTopicsDropdown @bulkSelectHelper={{self.bulkSelectHelper}} />
</template>
);
await click(".bulk-select-topics-dropdown-trigger");
@ -165,13 +193,17 @@ module("Integration | Component | BulkSelectTopicsDropdown", function (hooks) {
});
test("does not allow unlisting or relisting PM topics", async function (assert) {
const self = this;
this.currentUser.admin = true;
this.bulkSelectHelper = createBulkSelectHelper(this, {
topicIds: [PM_TOPIC_ID],
});
await render(
hbs`<BulkSelectTopicsDropdown @bulkSelectHelper={{this.bulkSelectHelper}} />`
<template>
<BulkSelectTopicsDropdown @bulkSelectHelper={{self.bulkSelectHelper}} />
</template>
);
await click(".bulk-select-topics-dropdown-trigger");
@ -184,13 +216,17 @@ module("Integration | Component | BulkSelectTopicsDropdown", function (hooks) {
});
test("does not allow updating category for PMs", async function (assert) {
const self = this;
this.currentUser.admin = true;
this.bulkSelectHelper = createBulkSelectHelper(this, {
topicIds: [PM_TOPIC_ID],
});
await render(
hbs`<BulkSelectTopicsDropdown @bulkSelectHelper={{this.bulkSelectHelper}} />`
<template>
<BulkSelectTopicsDropdown @bulkSelectHelper={{self.bulkSelectHelper}} />
</template>
);
await click(".bulk-select-topics-dropdown-trigger");
@ -200,13 +236,17 @@ module("Integration | Component | BulkSelectTopicsDropdown", function (hooks) {
});
test("allows moving to archive and moving to inbox for PMs", async function (assert) {
const self = this;
this.currentUser.admin = true;
this.bulkSelectHelper = createBulkSelectHelper(this, {
topicIds: [PM_TOPIC_ID],
});
await render(
hbs`<BulkSelectTopicsDropdown @bulkSelectHelper={{this.bulkSelectHelper}} />`
<template>
<BulkSelectTopicsDropdown @bulkSelectHelper={{self.bulkSelectHelper}} />
</template>
);
await click(".bulk-select-topics-dropdown-trigger");

View File

@ -1,33 +1,43 @@
import { fn } from "@ember/helper";
import { on } from "@ember/modifier";
import { fillIn, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import CharCounter from "discourse/components/char-counter";
import withEventValue from "discourse/helpers/with-event-value";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | char-counter", function (hooks) {
setupRenderingTest(hooks);
test("shows the number of characters", async function (assert) {
const self = this;
this.value = "Hello World";
this.max = 12;
await render(
hbs`<CharCounter @value={{this.value}} @max={{this.max}}></CharCounter>`
<template>
<CharCounter @value={{self.value}} @max={{self.max}} />
</template>
);
assert.dom(this.element).includesText("11/12");
});
test("updating value updates counter", async function (assert) {
const self = this;
this.max = 50;
await render(hbs`
<CharCounter
@value={{this.charCounterContent}}
@max={{this.max}}
>
<textarea {{on "input" (with-event-value (fn (mut this.charCounterContent)))}}></textarea>
</CharCounter>
`);
await render(
<template>
<CharCounter @value={{self.charCounterContent}} @max={{self.max}}>
<textarea
{{on "input" (withEventValue (fn (mut self.charCounterContent)))}}
></textarea>
</CharCounter>
</template>
);
assert
.dom(this.element)
@ -41,11 +51,15 @@ module("Integration | Component | char-counter", function (hooks) {
});
test("exceeding max length", async function (assert) {
const self = this;
this.max = 10;
this.value = "Hello World";
await render(
hbs`<CharCounter @value={{this.value}} @max={{this.max}}></CharCounter>`
<template>
<CharCounter @value={{self.value}} @max={{self.max}} />
</template>
);
assert.dom(".char-counter.exceeded").exists("exceeded class is applied");

View File

@ -1,7 +1,7 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { resetCache } from "pretty-text/upload-short-url";
import { module, test } from "qunit";
import CookText from "discourse/components/cook-text";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import pretender, { response } from "discourse/tests/helpers/create-pretender";
@ -13,7 +13,9 @@ module("Integration | Component | cook-text", function (hooks) {
});
test("renders markdown", async function (assert) {
await render(hbs`<CookText @rawText="_foo_" class="post-body" />`);
await render(
<template><CookText @rawText="_foo_" class="post-body" /></template>
);
assert.dom(".post-body").hasHtml("<p><em>foo</em></p>");
});
@ -30,7 +32,9 @@ module("Integration | Component | cook-text", function (hooks) {
);
await render(
hbs`<CookText @rawText="![an image](upload://a.png)" class="post-body" />`
<template>
<CookText @rawText="![an image](upload://a.png)" class="post-body" />
</template>
);
assert

View File

@ -1,6 +1,6 @@
import { click, render, triggerKeyEvent } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import DButton from "discourse/components/d-button";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import I18n, { i18n } from "discourse-i18n";
@ -8,7 +8,7 @@ module("Integration | Component | d-button", function (hooks) {
setupRenderingTest(hooks);
test("icon only button", async function (assert) {
await render(hbs`<DButton @icon="plus" tabindex="3" />`);
await render(<template><DButton @icon="plus" tabindex="3" /></template>);
assert.dom("button.btn.btn-icon.no-text").exists("has all the classes");
assert.dom("button .d-icon.d-icon-plus").exists("has the icon");
@ -16,7 +16,9 @@ module("Integration | Component | d-button", function (hooks) {
});
test("icon and text button", async function (assert) {
await render(hbs`<DButton @icon="plus" @label="topic.create" />`);
await render(
<template><DButton @icon="plus" @label="topic.create" /></template>
);
assert.dom("button.btn.btn-icon-text").exists("has all the classes");
assert.dom("button .d-icon.d-icon-plus").exists("has the icon");
@ -24,28 +26,32 @@ module("Integration | Component | d-button", function (hooks) {
});
test("text only button", async function (assert) {
await render(hbs`<DButton @label="topic.create" />`);
await render(<template><DButton @label="topic.create" /></template>);
assert.dom("button.btn.btn-text").exists("has all the classes");
assert.dom("button span.d-button-label").exists("has the label");
});
test("form attribute", async function (assert) {
await render(hbs`<DButton @form="login-form" />`);
await render(<template><DButton @form="login-form" /></template>);
assert.dom("button[form=login-form]").exists("has the form attribute");
});
test("link-styled button", async function (assert) {
await render(hbs`<DButton @display="link" />`);
await render(<template><DButton @display="link" /></template>);
assert.dom("button.btn-link:not(.btn)").exists("has the right classes");
});
test("isLoading button", async function (assert) {
const self = this;
this.set("isLoading", true);
await render(hbs`<DButton @isLoading={{this.isLoading}} />`);
await render(
<template><DButton @isLoading={{self.isLoading}} /></template>
);
assert
.dom("button.is-loading .loading-icon")
@ -61,7 +67,7 @@ module("Integration | Component | d-button", function (hooks) {
});
test("button without isLoading attribute", async function (assert) {
await render(hbs`<DButton />`);
await render(<template><DButton /></template>);
assert
.dom("button.is-loading")
@ -73,9 +79,13 @@ module("Integration | Component | d-button", function (hooks) {
});
test("isLoading button explicitly set to undefined state", async function (assert) {
const self = this;
this.set("isLoading");
await render(hbs`<DButton @isLoading={{this.isLoading}} />`);
await render(
<template><DButton @isLoading={{self.isLoading}} /></template>
);
assert
.dom("button.is-loading")
@ -87,9 +97,11 @@ module("Integration | Component | d-button", function (hooks) {
});
test("disabled button", async function (assert) {
const self = this;
this.set("disabled", true);
await render(hbs`<DButton @disabled={{this.disabled}} />`);
await render(<template><DButton @disabled={{self.disabled}} /></template>);
assert.dom("button").isDisabled();
@ -98,10 +110,17 @@ module("Integration | Component | d-button", function (hooks) {
});
test("aria-label", async function (assert) {
const self = this;
I18n.translations[I18n.locale].js.test = { fooAriaLabel: "foo" };
await render(
hbs`<DButton @ariaLabel={{this.ariaLabel}} @translatedAriaLabel={{this.translatedAriaLabel}} />`
<template>
<DButton
@ariaLabel={{self.ariaLabel}}
@translatedAriaLabel={{self.translatedAriaLabel}}
/>
</template>
);
this.set("ariaLabel", "test.fooAriaLabel");
@ -117,10 +136,17 @@ module("Integration | Component | d-button", function (hooks) {
});
test("title", async function (assert) {
const self = this;
I18n.translations[I18n.locale].js.test = { fooTitle: "foo" };
await render(
hbs`<DButton @title={{this.title}} @translatedTitle={{this.translatedTitle}} />`
<template>
<DButton
@title={{self.title}}
@translatedTitle={{self.translatedTitle}}
/>
</template>
);
this.set("title", "test.fooTitle");
@ -135,10 +161,17 @@ module("Integration | Component | d-button", function (hooks) {
});
test("label", async function (assert) {
const self = this;
I18n.translations[I18n.locale].js.test = { fooLabel: "foo" };
await render(
hbs`<DButton @label={{this.label}} @translatedLabel={{this.translatedLabel}} />`
<template>
<DButton
@label={{self.label}}
@translatedLabel={{self.translatedLabel}}
/>
</template>
);
this.set("label", "test.fooLabel");
@ -154,7 +187,11 @@ module("Integration | Component | d-button", function (hooks) {
});
test("aria-expanded", async function (assert) {
await render(hbs`<DButton @ariaExpanded={{this.ariaExpanded}} />`);
const self = this;
await render(
<template><DButton @ariaExpanded={{self.ariaExpanded}} /></template>
);
assert.dom("button").doesNotHaveAria("expanded");
@ -172,13 +209,19 @@ module("Integration | Component | d-button", function (hooks) {
});
test("aria-controls", async function (assert) {
await render(hbs`<DButton @ariaControls={{this.ariaControls}} />`);
const self = this;
await render(
<template><DButton @ariaControls={{self.ariaControls}} /></template>
);
this.set("ariaControls", "foo-bar");
assert.dom("button").hasAria("controls", "foo-bar");
});
test("onKeyDown callback", async function (assert) {
const self = this;
this.set("foo", null);
this.set("onKeyDown", () => {
this.set("foo", "bar");
@ -188,7 +231,9 @@ module("Integration | Component | d-button", function (hooks) {
});
await render(
hbs`<DButton @action={{this.action}} @onKeyDown={{this.onKeyDown}} />`
<template>
<DButton @action={{self.action}} @onKeyDown={{self.onKeyDown}} />
</template>
);
await triggerKeyEvent(".btn", "keydown", "Space");
@ -199,12 +244,14 @@ module("Integration | Component | d-button", function (hooks) {
});
test("press Enter", async function (assert) {
const self = this;
this.set("foo", null);
this.set("action", () => {
this.set("foo", "bar");
});
await render(hbs`<DButton @action={{this.action}} />`);
await render(<template><DButton @action={{self.action}} /></template>);
await triggerKeyEvent(".btn", "keydown", "Space");
assert.strictEqual(this.foo, null);
@ -214,12 +261,14 @@ module("Integration | Component | d-button", function (hooks) {
});
test("@action function is triggered on click", async function (assert) {
const self = this;
this.set("foo", null);
this.set("action", () => {
this.set("foo", "bar");
});
await render(hbs`<DButton @action={{this.action}} />`);
await render(<template><DButton @action={{self.action}} /></template>);
await click(".btn");
@ -228,7 +277,9 @@ module("Integration | Component | d-button", function (hooks) {
test("ellipses", async function (assert) {
await render(
hbs`<DButton @translatedLabel="test label" @ellipsis={{true}} />`
<template>
<DButton @translatedLabel="test label" @ellipsis={{true}} />
</template>
);
assert.dom(".d-button-label").hasText("test label…");

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import DDocument from "discourse/components/d-document";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
function getTitleCount() {
@ -23,7 +23,7 @@ module("Integration | Component | d-document", function (hooks) {
const titleBefore = document.title;
try {
this.currentUser.user_option.title_count_mode = "notifications";
await render(hbs`<DDocument />`);
await render(<template><DDocument /></template>);
assert.strictEqual(
getTitleCount(),
null,

View File

@ -9,8 +9,8 @@ import {
triggerEvent,
triggerKeyEvent,
} from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import DEditor from "discourse/components/d-editor";
import { withPluginApi } from "discourse/lib/plugin-api";
import { setCaretPosition } from "discourse/lib/utilities";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
@ -23,6 +23,7 @@ import {
setTextareaSelection,
} from "discourse/tests/helpers/textarea-selection-helper";
import { i18n } from "discourse-i18n";
import DMenus from "float-kit/components/d-menus";
module("Integration | Component | d-editor", function (hooks) {
setupRenderingTest(hooks);
@ -34,7 +35,9 @@ module("Integration | Component | d-editor", function (hooks) {
});
test("preview updates with markdown", async function (assert) {
await render(hbs`<DEditor @value={{this.value}} />`);
const self = this;
await render(<template><DEditor @value={{self.value}} /></template>);
assert.dom(".d-editor-button-bar").exists();
await fillIn(".d-editor-input", "hello **world**");
@ -46,7 +49,9 @@ module("Integration | Component | d-editor", function (hooks) {
});
test("links in preview are not tabbable", async function (assert) {
await render(hbs`<DEditor @value={{this.value}} />`);
const self = this;
await render(<template><DEditor @value={{self.value}} /></template>);
await fillIn(".d-editor-input", "[discourse](https://www.discourse.org)");
@ -58,9 +63,11 @@ module("Integration | Component | d-editor", function (hooks) {
});
test("updating the value refreshes the preview", async function (assert) {
const self = this;
this.set("value", "evil trout");
await render(hbs`<DEditor @value={{this.value}} />`);
await render(<template><DEditor @value={{self.value}} /></template>);
assert.dom(".d-editor-preview").hasHtml("<p>evil trout</p>");
@ -82,6 +89,8 @@ module("Integration | Component | d-editor", function (hooks) {
function testCase(title, testFunc, userOptions = {}) {
test(title, async function (assert) {
const self = this;
this.currentUser.user_option = Object.assign(
{},
this.currentUser.user_option,
@ -89,7 +98,7 @@ module("Integration | Component | d-editor", function (hooks) {
);
this.set("value", "hello world.");
await render(hbs`<DEditor @value={{this.value}} />`);
await render(<template><DEditor @value={{self.value}} /></template>);
const textarea = jumpEnd("textarea.d-editor-input");
await testFunc.call(this, assert, textarea);
@ -98,10 +107,14 @@ module("Integration | Component | d-editor", function (hooks) {
function composerTestCase(title, testFunc) {
test(title, async function (assert) {
const self = this;
this.set("value", "hello world.");
await render(
hbs`<DEditor @value={{this.value}} @composerEvents={{true}} />`
<template>
<DEditor @value={{self.value}} @composerEvents={{true}} />
</template>
);
const textarea = jumpEnd("textarea.d-editor-input");
@ -245,6 +258,8 @@ module("Integration | Component | d-editor", function (hooks) {
);
test("advanced code", async function (assert) {
const self = this;
this.siteSettings.code_formatting_style = "4-spaces-indent";
this.set(
"value",
@ -257,7 +272,7 @@ function xyz(x, y, z) {
`
);
await render(hbs`<DEditor @value={{this.value}} />`);
await render(<template><DEditor @value={{self.value}} /></template>);
const textarea = find("textarea.d-editor-input");
textarea.selectionStart = 0;
@ -277,9 +292,11 @@ function xyz(x, y, z) {
});
test("code button", async function (assert) {
const self = this;
this.siteSettings.code_formatting_style = "4-spaces-indent";
await render(hbs`<DEditor @value={{this.value}} />`);
await render(<template><DEditor @value={{self.value}} /></template>);
const textarea = jumpEnd("textarea.d-editor-input");
@ -359,9 +376,11 @@ third line`
});
test("code button does not reset undo history", async function (assert) {
const self = this;
this.set("value", "existing");
await render(hbs`<DEditor @value={{this.value}} />`);
await render(<template><DEditor @value={{self.value}} /></template>);
const textarea = find("textarea.d-editor-input");
textarea.selectionStart = 0;
textarea.selectionEnd = 8;
@ -379,9 +398,11 @@ third line`
});
test("code fences", async function (assert) {
const self = this;
this.set("value", "");
await render(hbs`<DEditor @value={{this.value}} />`);
await render(<template><DEditor @value={{self.value}} /></template>);
const textarea = jumpEnd("textarea.d-editor-input");
@ -492,10 +513,14 @@ third line`
});
test("quote button - empty lines", async function (assert) {
const self = this;
this.set("value", "one\n\ntwo\n\nthree");
await render(
hbs`<DEditor @value={{this.value}} @composerEvents={{true}} />`
<template>
<DEditor @value={{self.value}} @composerEvents={{true}} />
</template>
);
const textarea = jumpEnd("textarea.d-editor-input");
@ -513,10 +538,14 @@ third line`
});
test("quote button - selecting empty lines", async function (assert) {
const self = this;
this.set("value", "one\n\n\n\ntwo");
await render(
hbs`<DEditor @value={{this.value}} @composerEvents={{true}} />`
<template>
<DEditor @value={{self.value}} @composerEvents={{true}} />
</template>
);
const textarea = jumpEnd("textarea.d-editor-input");
@ -666,10 +695,12 @@ third line`
);
test("clicking the toggle-direction changes dir from ltr to rtl and back", async function (assert) {
const self = this;
this.siteSettings.support_mixed_text_direction = true;
this.siteSettings.default_locale = "en";
await render(hbs`<DEditor @value={{this.value}} />`);
await render(<template><DEditor @value={{self.value}} /></template>);
await click("button.toggle-direction");
assert.dom("textarea.d-editor-input").hasAttribute("dir", "rtl");
@ -679,6 +710,8 @@ third line`
});
test("toolbar event supports replaceText", async function (assert) {
const self = this;
withPluginApi("0.1", (api) => {
api.onToolbarCreate((toolbar) => {
toolbar.addButton({
@ -695,7 +728,7 @@ third line`
this.value = "hello";
await render(hbs`<DEditor @value={{this.value}} />`);
await render(<template><DEditor @value={{self.value}} /></template>);
await click("button.replace-text");
assert.strictEqual(this.value, "goodbye");
@ -716,10 +749,14 @@ third line`
);
test("emoji", async function (assert) {
const self = this;
this.set("value", "hello world.");
// we need DMenus here, as we are testing the d-editor which is not renderining
// the in-element outlet container necessary for DMenu to work
await render(hbs`<DMenus /><DEditor @value={{this.value}} />`);
await render(
<template><DMenus /><DEditor @value={{self.value}} /></template>
);
const picker = emojiPicker();
jumpEnd("textarea.d-editor-input");
await click(".d-editor-button-bar .emoji");
@ -766,14 +803,14 @@ third line`
});
});
await render(hbs`<DEditor/>`);
await render(<template><DEditor /></template>);
assert.dom(".d-editor-button-bar button.shown").exists();
assert.dom(".d-editor-button-bar button.not-shown").doesNotExist();
});
test("toolbar buttons tabindex", async function (assert) {
await render(hbs`<DEditor />`);
await render(<template><DEditor /></template>);
const buttons = queryAll(".d-editor-button-bar .btn");
assert
@ -897,11 +934,15 @@ third line`
);
test("paste table", async function (assert) {
const self = this;
this.set("value", "");
this.siteSettings.enable_rich_text_paste = true;
await render(
hbs`<DEditor @value={{this.value}} @composerEvents={{true}} />`
<template>
<DEditor @value={{self.value}} @composerEvents={{true}} />
</template>
);
await paste(".d-editor", "\ta\tb\n1\t2\t3");
@ -912,11 +953,15 @@ third line`
});
test("paste a different table", async function (assert) {
const self = this;
this.set("value", "");
this.siteSettings.enable_rich_text_paste = true;
await render(
hbs`<DEditor @value={{this.value}} @composerEvents={{true}} />`
<template>
<DEditor @value={{self.value}} @composerEvents={{true}} />
</template>
);
await paste(".d-editor", '\ta\tb\n1\t"2\n2.5"\t3');

View File

@ -1,6 +1,6 @@
import { click, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import DNavigation from "discourse/components/d-navigation";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | d-navigation", function (hooks) {
@ -19,7 +19,7 @@ module("Integration | Component | d-navigation", function (hooks) {
});
test("filters indirectly muted categories", async function (assert) {
await render(hbs`<DNavigation @filterMode="categories" />`);
await render(<template><DNavigation @filterMode="categories" /></template>);
await click(".category-drop .select-kit-header-wrapper");
assert

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import DToggleSwitch from "discourse/components/d-toggle-switch";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import I18n, { i18n } from "discourse-i18n";
@ -8,35 +8,49 @@ module("Integration | Component | d-toggle-switch", function (hooks) {
setupRenderingTest(hooks);
test("it renders a toggle button in a disabled state", async function (assert) {
const self = this;
this.set("state", false);
await render(hbs`<DToggleSwitch @state={{this.state}}/>`);
await render(<template><DToggleSwitch @state={{self.state}} /></template>);
assert.dom(".d-toggle-switch").exists("renders a toggle switch");
assert.dom(".d-toggle-switch__checkbox").hasAria("checked", "false");
});
test("it renders a toggle button in a enabled state", async function (assert) {
const self = this;
this.set("state", true);
await render(hbs`<DToggleSwitch @state={{this.state}}/>`);
await render(<template><DToggleSwitch @state={{self.state}} /></template>);
assert.dom(".d-toggle-switch").exists("renders a toggle switch");
assert.dom(".d-toggle-switch__checkbox").hasAria("checked", "true");
});
test("it renders a checkmark icon when enabled", async function (assert) {
const self = this;
this.set("state", true);
await render(hbs`<DToggleSwitch @state={{this.state}}/>`);
await render(<template><DToggleSwitch @state={{self.state}} /></template>);
assert.dom(".d-toggle-switch__checkbox-slider .d-icon-check").exists();
});
test("it renders a label for the button", async function (assert) {
const self = this;
I18n.translations[I18n.locale].js.test = { fooLabel: "foo" };
this.set("state", true);
await render(
hbs`<DToggleSwitch @state={{this.state}}/ @label={{this.label}} @translatedLabel={{this.translatedLabel}} />`
<template>
<DToggleSwitch
@state={{self.state}}
@label={{self.label}}
@translatedLabel={{self.translatedLabel}}
/>
</template>
);
this.set("label", "test.fooLabel");

View File

@ -1,6 +1,6 @@
import { fillIn, render, triggerEvent } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import DateInput from "discourse/components/date-input";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
const DEFAULT_DATE = moment("2019-01-29");
@ -9,19 +9,25 @@ module("Integration | Component | date-input", function (hooks) {
setupRenderingTest(hooks);
test("default", async function (assert) {
const self = this;
this.setProperties({ date: DEFAULT_DATE });
await render(hbs`<DateInput @date={{this.date}} />`);
await render(<template><DateInput @date={{self.date}} /></template>);
assert.dom(".date-picker").hasValue("2019-01-29");
});
test("prevents mutations", async function (assert) {
const self = this;
this.setProperties({ date: DEFAULT_DATE });
this.set("onChange", () => {});
await render(
hbs`<DateInput @date={{this.date}} @onChange={{this.onChange}} />`
<template>
<DateInput @date={{self.date}} @onChange={{self.onChange}} />
</template>
);
await fillIn(".date-picker", "2019-01-02");
@ -31,11 +37,15 @@ module("Integration | Component | date-input", function (hooks) {
});
test("allows mutations through actions", async function (assert) {
const self = this;
this.setProperties({ date: DEFAULT_DATE });
this.set("onChange", (date) => this.set("date", date));
await render(
hbs`<DateInput @date={{this.date}} @onChange={{this.onChange}} />`
<template>
<DateInput @date={{self.date}} @onChange={{self.onChange}} />
</template>
);
await fillIn(".date-picker", "2019-02-02");
@ -45,12 +55,16 @@ module("Integration | Component | date-input", function (hooks) {
});
test("always shows date in timezone of input timestamp", async function (assert) {
const self = this;
this.setProperties({
date: moment.tz("2023-05-05T10:00:00", "ETC/GMT-12"),
});
await render(
hbs`<DateInput @date={{this.date}} @onChange={{this.onChange}} />`
<template>
<DateInput @date={{self.date}} @onChange={{self.onChange}} />
</template>
);
assert.dom(".date-picker").hasValue("2023-05-05");

View File

@ -1,6 +1,7 @@
import { fn } from "@ember/helper";
import { fillIn, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import DateTimeInputRange from "discourse/components/date-time-input-range";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import selectKit from "discourse/tests/helpers/select-kit-helper";
@ -11,10 +12,18 @@ module("Integration | Component | date-time-input-range", function (hooks) {
setupRenderingTest(hooks);
test("default", async function (assert) {
const self = this;
this.setProperties({ state: { from: DEFAULT_DATE_TIME, to: null } });
await render(
hbs`<DateTimeInputRange @from={{this.state.from}} @to={{this.state.to}} @onChange={{fn (mut this.state)}} />`
<template>
<DateTimeInputRange
@from={{self.state.from}}
@to={{self.state.to}}
@onChange={{fn (mut self.state)}}
/>
</template>
);
assert.dom(".from.d-date-time-input .date-picker").hasValue("2019-01-29");
@ -44,10 +53,19 @@ module("Integration | Component | date-time-input-range", function (hooks) {
});
test("setting relativeDate results in correct intervals (4x 15m then 30m)", async function (assert) {
const self = this;
this.setProperties({ state: { from: DEFAULT_DATE_TIME, to: null } });
await render(
hbs`<DateTimeInputRange @from={{this.state.from}} @to={{this.state.to}} @relativeDate={{this.state.from}} @onChange={{fn (mut this.state)}} />`
<template>
<DateTimeInputRange
@from={{self.state.from}}
@to={{self.state.to}}
@relativeDate={{self.state.from}}
@onChange={{fn (mut self.state)}}
/>
</template>
);
await fillIn(".to.d-date-time-input .date-picker", "2019-01-29");
@ -60,6 +78,8 @@ module("Integration | Component | date-time-input-range", function (hooks) {
});
test("timezone support", async function (assert) {
const self = this;
this.setProperties({
state: {
from: moment.tz(DEFAULT_DATE_TIME_STRING, "Europe/Paris"),
@ -68,7 +88,14 @@ module("Integration | Component | date-time-input-range", function (hooks) {
});
await render(
hbs`<DateTimeInputRange @from={{this.state.from}} @to={{this.state.to}} @onChange={{fn (mut this.state)}} @timezone="Europe/Paris" />`
<template>
<DateTimeInputRange
@from={{self.state.from}}
@to={{self.state.to}}
@onChange={{fn (mut self.state)}}
@timezone="Europe/Paris"
/>
</template>
);
assert.dom(".from.d-date-time-input .date-picker").hasValue("2019-01-29");

View File

@ -1,6 +1,6 @@
import { fillIn, render, triggerEvent } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import DateTimeInput from "discourse/components/date-time-input";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
function setDate(date) {
@ -13,9 +13,11 @@ module("Integration | Component | date-time-input", function (hooks) {
setupRenderingTest(hooks);
test("default", async function (assert) {
const self = this;
this.setProperties({ date: DEFAULT_DATE_TIME });
await render(hbs`<DateTimeInput @date={{this.date}} />`);
await render(<template><DateTimeInput @date={{self.date}} /></template>);
assert.dom(".date-picker").hasValue("2019-01-29");
assert
@ -24,9 +26,11 @@ module("Integration | Component | date-time-input", function (hooks) {
});
test("prevents mutations", async function (assert) {
const self = this;
this.setProperties({ date: DEFAULT_DATE_TIME });
await render(hbs`<DateTimeInput @date={{this.date}} />`);
await render(<template><DateTimeInput @date={{self.date}} /></template>);
await fillIn(".date-picker", "2019-01-02");
@ -34,11 +38,15 @@ module("Integration | Component | date-time-input", function (hooks) {
});
test("allows mutations through actions", async function (assert) {
const self = this;
this.setProperties({ date: DEFAULT_DATE_TIME });
this.set("onChange", setDate);
await render(
hbs`<DateTimeInput @date={{this.date}} @onChange={{this.onChange}} />`
<template>
<DateTimeInput @date={{self.date}} @onChange={{self.onChange}} />
</template>
);
await fillIn(".date-picker", "2019-01-02");
@ -48,16 +56,22 @@ module("Integration | Component | date-time-input", function (hooks) {
});
test("can hide time", async function (assert) {
const self = this;
this.setProperties({ date: DEFAULT_DATE_TIME });
await render(
hbs`<DateTimeInput @date={{this.date}} @showTime={{false}} />`
<template>
<DateTimeInput @date={{self.date}} @showTime={{false}} />
</template>
);
assert.dom(".d-time-input .combo-box-header").doesNotExist();
});
test("supports swapping timezone without changing visible date/time", async function (assert) {
const self = this;
this.setProperties({
date: moment.tz("2023-05-05T12:00:00", "Europe/London"),
timezone: "Europe/London",
@ -65,7 +79,13 @@ module("Integration | Component | date-time-input", function (hooks) {
});
await render(
hbs`<DateTimeInput @date={{this.date}} @timezone={{this.timezone}} @onChange={{this.onChange}} />`
<template>
<DateTimeInput
@date={{self.date}}
@timezone={{self.timezone}}
@onChange={{self.onChange}}
/>
</template>
);
await triggerEvent(".date-picker", "change");
assert.strictEqual(this.date.format(), "2023-05-05T12:00:00+01:00");

View File

@ -6,7 +6,7 @@ import {
settled,
triggerKeyEvent,
} from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import DialogHolder from "dialog-holder/components/dialog-holder";
import { module, test } from "qunit";
import GroupDeleteDialogMessage from "discourse/components/dialog-messages/group-delete";
import SecondFactorConfirmPhrase from "discourse/components/dialog-messages/second-factor-confirm-phrase";
@ -21,7 +21,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
});
test("basics", async function (assert) {
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
assert.dom("#dialog-holder").exists("element is in DOM");
assert.dom("#dialog-holder").hasNoText("dialog is empty by default");
@ -47,7 +47,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
test("basics - dismiss using Esc", async function (assert) {
let cancelCallbackCalled = false;
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
assert.dom("#dialog-holder").exists("element is in DOM");
assert.dom("#dialog-holder").hasNoText("dialog is empty by default");
@ -78,7 +78,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
});
test("alert with title", async function (assert) {
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
this.dialog.alert({
message: "This is a note.",
@ -109,7 +109,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
});
test("alert with a string parameter", async function (assert) {
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
this.dialog.alert("An alert message");
await settled();
@ -122,7 +122,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
test("confirm", async function (assert) {
let confirmCallbackCalled = false;
let cancelCallbackCalled = false;
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
this.dialog.confirm({
message: "A confirm message",
@ -162,7 +162,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
let confirmCallbackCalled = false;
let cancelCallbackCalled = false;
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
this.dialog.confirm({
message: "A confirm message",
@ -187,7 +187,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
});
test("yes/no confirm", async function (assert) {
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
this.dialog.yesNoConfirm({ message: "A yes/no confirm message" });
await settled();
@ -207,7 +207,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
test("alert with custom buttons", async function (assert) {
let customCallbackTriggered = false;
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
this.dialog.alert({
message: "An alert with custom buttons",
@ -249,7 +249,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
});
test("alert with custom classes", async function (assert) {
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
this.dialog.alert({
message: "An alert with custom classes",
@ -283,7 +283,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
});
test("notice", async function (assert) {
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
this.dialog.notice("Noted!");
await settled();
@ -295,7 +295,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
});
test("delete confirm", async function (assert) {
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
this.dialog.deleteConfirm({ message: "A delete confirm message" });
await settled();
@ -317,7 +317,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
});
test("delete confirm with confirmation phrase component", async function (assert) {
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
this.dialog.deleteConfirm({
bodyComponent: SecondFactorConfirmPhrase,
@ -333,7 +333,7 @@ module("Integration | Component | dialog-holder", function (hooks) {
});
test("delete confirm with a component and model", async function (assert) {
await render(hbs`<DialogHolder />`);
await render(<template><DialogHolder /></template>);
const message_count = 5;
this.dialog.deleteConfirm({

View File

@ -1,6 +1,6 @@
import { click, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import DismissNew from "discourse/components/modal/dismiss-new";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { i18n } from "discourse-i18n";
@ -12,8 +12,10 @@ module("Integration | Component | modal/dismiss-new", function (hooks) {
});
test("modal title", async function (assert) {
const self = this;
await render(
hbs`<Modal::DismissNew @inline={{true}} @model={{this.model}} />`
<template><DismissNew @inline={{true}} @model={{self.model}} /></template>
);
assert
@ -22,8 +24,10 @@ module("Integration | Component | modal/dismiss-new", function (hooks) {
});
test("default state", async function (assert) {
const self = this;
await render(
hbs`<Modal::DismissNew @inline={{true}} @model={{this.model}} />`
<template><DismissNew @inline={{true}} @model={{self.model}} /></template>
);
assert.dom(".dismiss-topics input").isChecked();
@ -32,6 +36,8 @@ module("Integration | Component | modal/dismiss-new", function (hooks) {
});
test("one new selected topic", async function (assert) {
const self = this;
this.model.selectedTopics.push({
id: 1,
title: "Topic 1",
@ -39,7 +45,7 @@ module("Integration | Component | modal/dismiss-new", function (hooks) {
});
await render(
hbs`<Modal::DismissNew @inline={{true}} @model={{this.model}} />`
<template><DismissNew @inline={{true}} @model={{self.model}} /></template>
);
assert.dom(".dismiss-posts").doesNotExist();
@ -51,6 +57,8 @@ module("Integration | Component | modal/dismiss-new", function (hooks) {
});
test("one new unread in selected topic", async function (assert) {
const self = this;
this.model.selectedTopics.push({
id: 1,
title: "Topic 1",
@ -58,7 +66,7 @@ module("Integration | Component | modal/dismiss-new", function (hooks) {
});
await render(
hbs`<Modal::DismissNew @inline={{true}} @model={{this.model}} />`
<template><DismissNew @inline={{true}} @model={{self.model}} /></template>
);
assert.dom(".dismiss-topics").doesNotExist();
@ -70,10 +78,12 @@ module("Integration | Component | modal/dismiss-new", function (hooks) {
});
test("no selected topics with topics subset", async function (assert) {
const self = this;
this.model.subset = "topics";
await render(
hbs`<Modal::DismissNew @inline={{true}} @model={{this.model}} />`
<template><DismissNew @inline={{true}} @model={{self.model}} /></template>
);
assert.dom(".dismiss-posts").doesNotExist();
@ -83,10 +93,12 @@ module("Integration | Component | modal/dismiss-new", function (hooks) {
});
test("no selected topics with replies subset", async function (assert) {
const self = this;
this.model.subset = "replies";
await render(
hbs`<Modal::DismissNew @inline={{true}} @model={{this.model}} />`
<template><DismissNew @inline={{true}} @model={{self.model}} /></template>
);
assert.dom(".dismiss-topics").doesNotExist();
@ -96,6 +108,8 @@ module("Integration | Component | modal/dismiss-new", function (hooks) {
});
test("dismissed", async function (assert) {
const self = this;
let state;
this.model.dismissCallback = (newState) => {
@ -105,7 +119,13 @@ module("Integration | Component | modal/dismiss-new", function (hooks) {
this.noop = () => {};
await render(
hbs`<Modal::DismissNew @closeModal={{this.noop}} @inline={{true}} @model={{this.model}} />`
<template>
<DismissNew
@closeModal={{self.noop}}
@inline={{true}}
@model={{self.model}}
/>
</template>
);
await click(".dismiss-topics [type='checkbox']");

View File

@ -1,6 +1,6 @@
import { click, fillIn, render, triggerKeyEvent } from "@ember/test-helpers";
import hbs from "htmlbars-inline-precompile";
import { module, skip, test } from "qunit";
import Content from "discourse/components/emoji-picker/content";
import emojisFixtures from "discourse/tests/fixtures/emojis-fixtures";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import pretender, { response } from "discourse/tests/helpers/create-pretender";
@ -26,7 +26,7 @@ module("Integration | Component | emoji-picker-content", function (hooks) {
});
test("When displaying navigation", async function (assert) {
await render(hbs`<EmojiPicker::Content />`);
await render(<template><Content /></template>);
assert
.dom(`.emoji-picker__section-btn.active[data-section="favorites"]`)
@ -41,7 +41,7 @@ module("Integration | Component | emoji-picker-content", function (hooks) {
});
test("When changing tone scale", async function (assert) {
await render(hbs`<EmojiPicker::Content />`);
await render(<template><Content /></template>);
await emojiPicker(".emoji-picker").tone(6);
assert
@ -53,7 +53,7 @@ module("Integration | Component | emoji-picker-content", function (hooks) {
});
test("When requesting section", async function (assert) {
await render(hbs`<EmojiPicker::Content />`);
await render(<template><Content /></template>);
assert.strictEqual(
document.querySelector("#ember-testing-container").scrollTop,
@ -69,7 +69,7 @@ module("Integration | Component | emoji-picker-content", function (hooks) {
});
test("When filtering emojis", async function (assert) {
await render(hbs`<EmojiPicker::Content />`);
await render(<template><Content /></template>);
await fillIn(".filter-input", "grin");
assert
@ -93,10 +93,12 @@ module("Integration | Component | emoji-picker-content", function (hooks) {
});
test("When selecting an emoji", async function (assert) {
const self = this;
this.didSelectEmoji = (emoji) => assert.step(emoji);
await render(
hbs`<EmojiPicker::Content @didSelectEmoji={{this.didSelectEmoji}} />`
<template><Content @didSelectEmoji={{self.didSelectEmoji}} /></template>
);
await click('img.emoji[data-emoji="grinning"]');
@ -104,7 +106,7 @@ module("Integration | Component | emoji-picker-content", function (hooks) {
});
skip("When navigating sections", async function (assert) {
await render(hbs`<EmojiPicker::Content />`);
await render(<template><Content /></template>);
await triggerKeyEvent(document.activeElement, "keydown", "ArrowDown");
assert
@ -146,7 +148,7 @@ module("Integration | Component | emoji-picker-content", function (hooks) {
});
skip("When navigating filtered emojis", async function (assert) {
await render(hbs`<EmojiPicker::Content />`);
await render(<template><Content /></template>);
await fillIn(".filter-input", "man");
await triggerKeyEvent(document.activeElement, "keydown", "ArrowDown");
@ -178,10 +180,12 @@ module("Integration | Component | emoji-picker-content", function (hooks) {
});
test("When selecting a toned an emoji", async function (assert) {
const self = this;
this.didSelectEmoji = (emoji) => assert.step(emoji);
await render(
hbs`<EmojiPicker::Content @didSelectEmoji={{this.didSelectEmoji}} />`
<template><Content @didSelectEmoji={{self.didSelectEmoji}} /></template>
);
const picker = emojiPicker(".emoji-picker");
await picker.select("raised_hands");
@ -192,7 +196,7 @@ module("Integration | Component | emoji-picker-content", function (hooks) {
});
test("When hovering an emoji", async function (assert) {
await render(hbs`<EmojiPicker::Content />`);
await render(<template><Content /></template>);
assert
.dom(
@ -207,7 +211,7 @@ module("Integration | Component | emoji-picker-content", function (hooks) {
.hasAttribute("title", ":grinning_face:", "filtered emoji have a title");
await emojiPicker(".emoji-picker").tone(1);
await render(hbs`<EmojiPicker::Content />`);
await render(<template><Content /></template>);
assert
.dom('img.emoji[data-emoji="raised_hands"]')
@ -218,7 +222,7 @@ module("Integration | Component | emoji-picker-content", function (hooks) {
);
await emojiPicker(".emoji-picker").tone(2);
await render(hbs`<EmojiPicker::Content />`);
await render(<template><Content /></template>);
assert
.dom('img.emoji[data-emoji="raised_hands"]')

View File

@ -1,13 +1,15 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import EmptyState from "discourse/components/empty-state";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | empty-state", function (hooks) {
setupRenderingTest(hooks);
test("it renders", async function (assert) {
await render(hbs`<EmptyState @title="title" @body="body" />`);
await render(
<template><EmptyState @title="title" @body="body" /></template>
);
assert.dom("[data-test-title]").hasText("title");
assert.dom("[data-test-body]").hasText("body");

View File

@ -1,6 +1,7 @@
import { hash } from "@ember/helper";
import { fillIn, render, triggerEvent } from "@ember/test-helpers";
import hbs from "htmlbars-inline-precompile";
import { module, test } from "qunit";
import FilterInput from "discourse/components/filter-input";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { exists } from "discourse/tests/helpers/qunit-helpers";
@ -8,43 +9,57 @@ module("Integration | Component | filter-input", function (hooks) {
setupRenderingTest(hooks);
test("Left icon", async function (assert) {
await render(hbs`<FilterInput @icons={{hash left="bell"}} />`);
await render(
<template><FilterInput @icons={{hash left="bell"}} /></template>
);
assert.true(exists(".d-icon-bell.-left"));
});
test("Right icon", async function (assert) {
await render(hbs`<FilterInput @icons={{hash right="bell"}} />`);
await render(
<template><FilterInput @icons={{hash right="bell"}} /></template>
);
assert.true(exists(".d-icon-bell.-right"));
});
test("containerClass argument", async function (assert) {
await render(hbs`<FilterInput @containerClass="foo" />`);
await render(<template><FilterInput @containerClass="foo" /></template>);
assert.true(exists(".filter-input-container.foo"));
});
test("Html attributes", async function (assert) {
await render(hbs`<FilterInput data-foo="1" placeholder="bar" />`);
await render(
<template><FilterInput data-foo="1" placeholder="bar" /></template>
);
assert.true(exists('.filter-input[data-foo="1"]'));
assert.true(exists('.filter-input[placeholder="bar"]'));
});
test("Filter action", async function (assert) {
const self = this;
this.set("value", null);
this.set("action", (event) => {
this.set("value", event.target.value);
});
await render(hbs`<FilterInput @filterAction={{this.action}} />`);
await render(
<template><FilterInput @filterAction={{self.action}} /></template>
);
await fillIn(".filter-input", "foo");
assert.strictEqual(this.value, "foo");
});
test("Focused state", async function (assert) {
await render(hbs`<FilterInput @filterAction={{this.action}} />`);
const self = this;
await render(
<template><FilterInput @filterAction={{self.action}} /></template>
);
await triggerEvent(".filter-input", "focusin");
assert.true(exists(".filter-input-container.is-focused"));

View File

@ -1,18 +1,20 @@
import { click, render, triggerKeyEvent } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import FlatButton from "discourse/components/flat-button";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | flat-button", function (hooks) {
setupRenderingTest(hooks);
test("press Enter", async function (assert) {
const self = this;
this.set("foo", null);
this.set("action", () => {
this.set("foo", "bar");
});
await render(hbs`<FlatButton @action={{this.action}} />`);
await render(<template><FlatButton @action={{self.action}} /></template>);
await triggerKeyEvent(".btn-flat", "keydown", "Space");
assert.strictEqual(this.foo, null);
@ -22,12 +24,14 @@ module("Integration | Component | flat-button", function (hooks) {
});
test("click", async function (assert) {
const self = this;
this.set("foo", null);
this.set("action", () => {
this.set("foo", "bar");
});
await render(hbs`<FlatButton @action={{this.action}} />`);
await render(<template><FlatButton @action={{self.action}} /></template>);
await click(".btn-flat");
assert.strictEqual(this.foo, "bar");

View File

@ -0,0 +1,31 @@
import { render } from "@ember/test-helpers";
import { module, test } from "qunit";
import DButton from "discourse/components/d-button";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import DButtonTooltip from "float-kit/components/d-button-tooltip";
import DTooltip from "float-kit/components/d-tooltip";
module(
"Integration | Component | FloatKit | d-button-tooltip",
function (hooks) {
setupRenderingTest(hooks);
test("default", async function (assert) {
await render(
<template>
<DButtonTooltip>
<:button>
<DButton />
</:button>
<:tooltip>
<DTooltip />
</:tooltip>
</DButtonTooltip>
</template>
);
assert.dom(".btn").exists();
assert.dom("[data-trigger]").exists();
});
}
);

View File

@ -1,26 +0,0 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module(
"Integration | Component | FloatKit | d-button-tooltip",
function (hooks) {
setupRenderingTest(hooks);
test("default", async function (assert) {
await render(hbs`
<DButtonTooltip>
<:button>
<DButton />
</:button>
<:tooltip>
<DTooltip />
</:tooltip>
</DButtonTooltip>`);
assert.dom(".btn").exists();
assert.dom("[data-trigger]").exists();
});
}
);

View File

@ -1,7 +1,8 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import noop from "discourse/helpers/noop";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import DDefaultToast from "float-kit/components/d-default-toast";
import DToastInstance from "float-kit/lib/d-toast-instance";
module(
@ -10,45 +11,72 @@ module(
setupRenderingTest(hooks);
test("icon", async function (assert) {
const self = this;
this.toast = new DToastInstance(this, { data: { icon: "check" } });
await render(hbs`<DDefaultToast @data={{this.toast.options.data}} />`);
await render(
<template><DDefaultToast @data={{self.toast.options.data}} /></template>
);
assert.dom(".fk-d-default-toast__icon-container .d-icon-check").exists();
});
test("no icon", async function (assert) {
const self = this;
this.toast = new DToastInstance(this, {});
await render(hbs`<DDefaultToast @data={{this.toast.options.data}} />`);
await render(
<template><DDefaultToast @data={{self.toast.options.data}} /></template>
);
assert.dom(".fk-d-default-toast__icon-container").doesNotExist();
});
test("progress bar", async function (assert) {
const self = this;
this.toast = new DToastInstance(this, {});
await render(
hbs`<DDefaultToast @data={{this.toast.options.data}} @showProgressBar={{true}} @onRegisterProgressBar={{(noop)}} />`
<template>
<DDefaultToast
@data={{self.toast.options.data}}
@showProgressBar={{true}}
@onRegisterProgressBar={{(noop)}}
/>
</template>
);
assert.dom(".fk-d-default-toast__progress-bar").exists();
});
test("no progress bar", async function (assert) {
const self = this;
this.toast = new DToastInstance(this, {});
await render(
hbs`<DDefaultToast @data={{this.toast.options.data}} @showProgressBar={{false}} />`
<template>
<DDefaultToast
@data={{self.toast.options.data}}
@showProgressBar={{false}}
/>
</template>
);
assert.dom(".fk-d-default-toast__progress-bar").doesNotExist();
});
test("title", async function (assert) {
const self = this;
this.toast = new DToastInstance(this, { data: { title: "Title" } });
await render(hbs`<DDefaultToast @data={{this.toast.options.data}} />`);
await render(
<template><DDefaultToast @data={{self.toast.options.data}} /></template>
);
assert
.dom(".fk-d-default-toast__title")
@ -56,17 +84,25 @@ module(
});
test("no title", async function (assert) {
const self = this;
this.toast = new DToastInstance(this, {});
await render(hbs`<DDefaultToast @data={{this.toast.options.data}} />`);
await render(
<template><DDefaultToast @data={{self.toast.options.data}} /></template>
);
assert.dom(".fk-d-default-toast__title").doesNotExist();
});
test("message", async function (assert) {
const self = this;
this.toast = new DToastInstance(this, { data: { message: "Message" } });
await render(hbs`<DDefaultToast @data={{this.toast.options.data}} />`);
await render(
<template><DDefaultToast @data={{self.toast.options.data}} /></template>
);
assert
.dom(".fk-d-default-toast__message")
@ -74,14 +110,20 @@ module(
});
test("no message", async function (assert) {
const self = this;
this.toast = new DToastInstance(this, {});
await render(hbs`<DDefaultToast @data={{this.toast.options.data}} />`);
await render(
<template><DDefaultToast @data={{self.toast.options.data}} /></template>
);
assert.dom(".fk-d-default-toast__message").doesNotExist();
});
test("actions", async function (assert) {
const self = this;
this.toast = new DToastInstance(this, {
data: {
actions: [
@ -95,7 +137,9 @@ module(
},
});
await render(hbs`<DDefaultToast @data={{this.toast.options.data}} />`);
await render(
<template><DDefaultToast @data={{self.toast.options.data}} /></template>
);
assert
.dom(".fk-d-default-toast__actions .btn.btn-danger")

View File

@ -1,3 +1,4 @@
import { hash } from "@ember/helper";
import { getOwner } from "@ember/owner";
import {
click,
@ -5,10 +6,10 @@ import {
triggerEvent,
triggerKeyEvent,
} from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import DDefaultToast from "float-kit/components/d-default-toast";
import DTooltip from "float-kit/components/d-tooltip";
import DTooltipInstance from "float-kit/lib/d-tooltip-instance";
module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
@ -27,20 +28,26 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
}
test("@label", async function (assert) {
await render(hbs`<DTooltip @inline={{true}} @label="label" />`);
await render(
<template><DTooltip @inline={{true}} @label="label" /></template>
);
assert.dom(".fk-d-tooltip__label").hasText("label");
});
test("@icon", async function (assert) {
await render(hbs`<DTooltip @inline={{true}} @icon="check" />`);
await render(
<template><DTooltip @inline={{true}} @icon="check" /></template>
);
assert.dom(".fk-d-tooltip__icon .d-icon-check").exists();
});
test("@content", async function (assert) {
await render(
hbs`<DTooltip @inline={{true}} @label="label" @content="content" />`
<template>
<DTooltip @inline={{true}} @label="label" @content="content" />
</template>
);
await hover();
@ -48,21 +55,29 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
});
test("@onRegisterApi", async function (assert) {
const self = this;
this.api = null;
this.onRegisterApi = (api) => (this.api = api);
await render(
hbs`<DTooltip @inline={{true}} @onRegisterApi={{this.onRegisterApi}} />`
<template>
<DTooltip @inline={{true}} @onRegisterApi={{self.onRegisterApi}} />
</template>
);
assert.true(this.api instanceof DTooltipInstance);
});
test("@onShow", async function (assert) {
const self = this;
this.test = false;
this.onShow = () => (this.test = true);
await render(hbs`<DTooltip @inline={{true}} @onShow={{this.onShow}} />`);
await render(
<template><DTooltip @inline={{true}} @onShow={{self.onShow}} /></template>
);
await hover();
@ -70,10 +85,16 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
});
test("@onClose", async function (assert) {
const self = this;
this.test = false;
this.onClose = () => (this.test = true);
await render(hbs`<DTooltip @inline={{true}} @onClose={{this.onClose}} />`);
await render(
<template>
<DTooltip @inline={{true}} @onClose={{self.onClose}} />
</template>
);
await hover();
await close();
@ -81,7 +102,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
});
test("-expanded class", async function (assert) {
await render(hbs`<DTooltip @inline={{true}} @label="label" />`);
await render(
<template><DTooltip @inline={{true}} @label="label" /></template>
);
assert.dom(".fk-d-tooltip__trigger").doesNotHaveClass("-expanded");
@ -91,20 +114,26 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
});
test("trigger role attribute", async function (assert) {
await render(hbs`<DTooltip @inline={{true}} @label="label" />`);
await render(
<template><DTooltip @inline={{true}} @label="label" /></template>
);
assert.dom(".fk-d-tooltip__trigger").hasAttribute("role", "button");
});
test("trigger id attribute", async function (assert) {
await render(hbs`<DTooltip @inline={{true}} @label="label" />`);
await render(
<template><DTooltip @inline={{true}} @label="label" /></template>
);
assert.dom(".fk-d-tooltip__trigger").hasAttribute("id");
});
test("@identifier", async function (assert) {
await render(
hbs`<DTooltip @inline={{true}} @label="label" @identifier="tip" />`
<template>
<DTooltip @inline={{true}} @label="label" @identifier="tip" />
</template>
);
assert.dom(".fk-d-tooltip__trigger").hasAttribute("data-identifier", "tip");
@ -115,7 +144,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
});
test("aria-expanded attribute", async function (assert) {
await render(hbs`<DTooltip @inline={{true}} @label="label" />`);
await render(
<template><DTooltip @inline={{true}} @label="label" /></template>
);
assert.dom(".fk-d-tooltip__trigger").hasAttribute("aria-expanded", "false");
@ -126,7 +157,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
test("<:trigger>", async function (assert) {
await render(
hbs`<DTooltip @inline={{true}}><:trigger>label</:trigger></DTooltip>`
<template>
<DTooltip @inline={{true}}><:trigger>label</:trigger></DTooltip>
</template>
);
assert.dom(".fk-d-tooltip__trigger").hasText("label");
@ -134,7 +167,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
test("<:content>", async function (assert) {
await render(
hbs`<DTooltip @inline={{true}}><:content>content</:content></DTooltip>`
<template>
<DTooltip @inline={{true}}><:content>content</:content></DTooltip>
</template>
);
await hover();
@ -143,7 +178,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
});
test("content role attribute", async function (assert) {
await render(hbs`<DTooltip @inline={{true}} @label="label" />`);
await render(
<template><DTooltip @inline={{true}} @label="label" /></template>
);
await hover();
@ -151,10 +188,19 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
});
test("@component", async function (assert) {
const self = this;
this.component = DDefaultToast;
await render(
hbs`<DTooltip @inline={{true}} @label="test" @component={{this.component}} @data={{hash message="content"}} />`
<template>
<DTooltip
@inline={{true}}
@label="test"
@component={{self.component}}
@data={{hash message="content"}}
/>
</template>
);
await hover();
@ -167,7 +213,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
});
test("content aria-labelledby attribute", async function (assert) {
await render(hbs`<DTooltip @inline={{true}} @label="label" />`);
await render(
<template><DTooltip @inline={{true}} @label="label" /></template>
);
await hover();
@ -181,7 +229,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
test("@closeOnEscape", async function (assert) {
await render(
hbs`<DTooltip @inline={{true}} @label="label" @closeOnEscape={{true}} />`
<template>
<DTooltip @inline={{true}} @label="label" @closeOnEscape={{true}} />
</template>
);
await hover();
await close();
@ -189,7 +239,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
assert.dom(".fk-d-tooltip__content").doesNotExist();
await render(
hbs`<DTooltip @inline={{true}} @label="label" @closeOnEscape={{false}} />`
<template>
<DTooltip @inline={{true}} @label="label" @closeOnEscape={{false}} />
</template>
);
await hover();
await close();
@ -199,7 +251,13 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
test("@closeOnClickOutside", async function (assert) {
await render(
hbs`<span class="test">test</span><DTooltip @inline={{true}} @label="label" @closeOnClickOutside={{true}} />`
<template>
<span class="test">test</span><DTooltip
@inline={{true}}
@label="label"
@closeOnClickOutside={{true}}
/>
</template>
);
await hover();
await triggerEvent(".test", "pointerdown");
@ -207,7 +265,13 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
assert.dom(".fk-d-tooltip__content").doesNotExist();
await render(
hbs`<span class="test">test</span><DTooltip @inline={{true}} @label="label" @closeOnClickOutside={{false}} />`
<template>
<span class="test">test</span><DTooltip
@inline={{true}}
@label="label"
@closeOnClickOutside={{false}}
/>
</template>
);
await hover();
await triggerEvent(".test", "pointerdown");
@ -217,7 +281,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
test("@maxWidth", async function (assert) {
await render(
hbs`<DTooltip @inline={{true}} @label="label" @maxWidth={{20}} />`
<template>
<DTooltip @inline={{true}} @label="label" @maxWidth={{20}} />
</template>
);
await hover();
@ -227,7 +293,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
});
test("applies position", async function (assert) {
await render(hbs`<DTooltip @inline={{true}} @label="label" />`);
await render(
<template><DTooltip @inline={{true}} @label="label" /></template>
);
await hover();
assert.dom(".fk-d-tooltip__content").hasAttribute("style", /left: /);
@ -236,7 +304,13 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
test("a tooltip can be closed by identifier", async function (assert) {
await render(
hbs`<DTooltip @inline={{true}} @label="label" @identifier="test">test</DTooltip>`
<template>
<DTooltip
@inline={{true}}
@label="label"
@identifier="test"
>test</DTooltip>
</template>
);
await hover();
@ -248,7 +322,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
test("a tooltip is triggered/untriggered by click on mobile", async function (assert) {
this.site.mobileView = true;
await render(hbs`<DTooltip @inline={{true}} @label="label" />`);
await render(
<template><DTooltip @inline={{true}} @label="label" /></template>
);
await click(".fk-d-tooltip__trigger");
assert.dom(".fk-d-tooltip__content").exists();
@ -259,7 +335,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
});
test("a tooltip is triggered/untriggered by click on desktop", async function (assert) {
await render(hbs`<DTooltip @inline={{true}} @label="label" />`);
await render(
<template><DTooltip @inline={{true}} @label="label" /></template>
);
await click(".fk-d-tooltip__trigger");
assert.dom(".fk-d-tooltip__content").exists();
@ -270,7 +348,9 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
});
test("a tooltip is triggered/untriggered by hover on desktop", async function (assert) {
await render(hbs`<DTooltip @inline={{true}} @label="label" />`);
await render(
<template><DTooltip @inline={{true}} @label="label" /></template>
);
await hover();

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import Checkbox from "discourse/components/form-template-field/checkbox";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module(
@ -9,7 +9,7 @@ module(
setupRenderingTest(hooks);
test("renders a checkbox input", async function (assert) {
await render(hbs`<FormTemplateField::Checkbox />`);
await render(<template><Checkbox /></template>);
assert
.dom(
@ -19,13 +19,15 @@ module(
});
test("renders a checkbox with a label", async function (assert) {
const self = this;
const attributes = {
label: "Click this box",
};
this.set("attributes", attributes);
await render(
hbs`<FormTemplateField::Checkbox @attributes={{this.attributes}} />`
<template><Checkbox @attributes={{self.attributes}} /></template>
);
assert

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import Dropdown from "discourse/components/form-template-field/dropdown";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
import selectKit from "discourse/tests/helpers/select-kit-helper";
@ -15,12 +15,12 @@ module(
});
test("renders a dropdown with choices", async function (assert) {
const self = this;
const choices = ["Choice 1", "Choice 2", "Choice 3"];
this.set("choices", choices);
await render(
hbs`<FormTemplateField::Dropdown @choices={{this.choices}}/>`
);
await render(<template><Dropdown @choices={{self.choices}} /></template>);
assert
.dom(".form-template-field__dropdown")
.exists("a dropdown component exists");
@ -41,6 +41,8 @@ module(
});
test("renders a dropdown with choices and attributes", async function (assert) {
const self = this;
const choices = ["Choice 1", "Choice 2", "Choice 3"];
const attributes = {
none_label: "Select a choice",
@ -51,7 +53,9 @@ module(
this.set("attributes", attributes);
await render(
hbs`<FormTemplateField::Dropdown @choices={{this.choices}} @attributes={{this.attributes}} />`
<template>
<Dropdown @choices={{self.choices}} @attributes={{self.attributes}} />
</template>
);
assert
.dom(".form-template-field__dropdown")
@ -63,12 +67,12 @@ module(
});
test("doesn't render a label when attribute is missing", async function (assert) {
const self = this;
const choices = ["Choice 1", "Choice 2", "Choice 3"];
this.set("choices", choices);
await render(
hbs`<FormTemplateField::Dropdown @choices={{this.choices}} />`
);
await render(<template><Dropdown @choices={{self.choices}} /></template>);
assert.dom(".form-template-field__label").doesNotExist();
});

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import FormInput from "discourse/components/form-template-field/input";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module(
@ -9,7 +9,7 @@ module(
setupRenderingTest(hooks);
test("renders a text input", async function (assert) {
await render(hbs`<FormTemplateField::Input />`);
await render(<template><FormInput /></template>);
assert
.dom(".form-template-field[data-field-type='input'] input[type='text']")
@ -17,6 +17,8 @@ module(
});
test("renders a text input with attributes", async function (assert) {
const self = this;
const attributes = {
label: "My text label",
placeholder: "Enter text here",
@ -24,7 +26,7 @@ module(
this.set("attributes", attributes);
await render(
hbs`<FormTemplateField::Input @attributes={{this.attributes}} />`
<template><FormInput @attributes={{self.attributes}} /></template>
);
assert
@ -38,29 +40,50 @@ module(
});
test("doesn't render a label when attribute is missing", async function (assert) {
const self = this;
const attributes = {
placeholder: "Enter text here",
};
this.set("attributes", attributes);
await render(
hbs`<FormTemplateField::Input @attributes={{this.attributes}} />`
<template><FormInput @attributes={{self.attributes}} /></template>
);
assert.dom(".form-template-field__label").doesNotExist();
});
test("renders a description if present", async function (assert) {
const self = this;
const attributes = {
description: "Your full name",
};
this.set("attributes", attributes);
await render(
hbs`<FormTemplateField::Input @attributes={{this.attributes}} />`
<template><FormInput @attributes={{self.attributes}} /></template>
);
assert.dom(".form-template-field__description").hasText("Your full name");
});
test("renders a description if present", async function (assert) {
const self = this;
const attributes = {
description: "Write your bio here",
};
this.set("attributes", attributes);
await render(
<template><FormInput @attributes={{self.attributes}} /></template>
);
assert
.dom(".form-template-field__description")
.hasText("Write your bio here");
});
}
);

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import MultiSelect from "discourse/components/form-template-field/multi-select";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
import selectKit from "discourse/tests/helpers/select-kit-helper";
@ -15,12 +15,14 @@ module(
});
test("renders a multi-select dropdown with choices", async function (assert) {
const self = this;
const choices = ["Choice 1", "Choice 2", "Choice 3"];
this.set("choices", choices);
await render(
hbs`<FormTemplateField::MultiSelect @choices={{this.choices}}/>`
<template><MultiSelect @choices={{self.choices}} /></template>
);
assert
.dom(".form-template-field__multi-select")
@ -42,6 +44,8 @@ module(
});
test("renders a multi-select with choices and attributes", async function (assert) {
const self = this;
const choices = ["Choice 1", "Choice 2", "Choice 3"];
const attributes = {
none_label: "Select a choice",
@ -52,7 +56,12 @@ module(
this.set("attributes", attributes);
await render(
hbs`<FormTemplateField::MultiSelect @choices={{this.choices}} @attributes={{this.attributes}} />`
<template>
<MultiSelect
@choices={{self.choices}}
@attributes={{self.attributes}}
/>
</template>
);
assert
.dom(".form-template-field__multi-select")
@ -64,11 +73,13 @@ module(
});
test("doesn't render a label when attribute is missing", async function (assert) {
const self = this;
const choices = ["Choice 1", "Choice 2", "Choice 3"];
this.set("choices", choices);
await render(
hbs`<FormTemplateField::MultiSelect @choices={{this.choices}} />`
<template><MultiSelect @choices={{self.choices}} /></template>
);
assert.dom(".form-template-field__label").doesNotExist();

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import FormTextarea from "discourse/components/form-template-field/textarea";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module(
@ -9,7 +9,7 @@ module(
setupRenderingTest(hooks);
test("renders a textarea input", async function (assert) {
await render(hbs`<FormTemplateField::Textarea />`);
await render(<template><FormTextarea /></template>);
assert
.dom(".form-template-field__textarea")
@ -17,6 +17,8 @@ module(
});
test("renders a text input with attributes", async function (assert) {
const self = this;
const attributes = {
label: "My text label",
placeholder: "Enter text here",
@ -24,7 +26,7 @@ module(
this.set("attributes", attributes);
await render(
hbs`<FormTemplateField::Textarea @attributes={{this.attributes}} />`
<template><FormTextarea @attributes={{self.attributes}} /></template>
);
assert
@ -38,31 +40,18 @@ module(
});
test("doesn't render a label when attribute is missing", async function (assert) {
const self = this;
const attributes = {
placeholder: "Enter text here",
};
this.set("attributes", attributes);
await render(
hbs`<FormTemplateField::Textarea @attributes={{this.attributes}} />`
<template><FormTextarea @attributes={{self.attributes}} /></template>
);
assert.dom(".form-template-field__label").doesNotExist();
});
test("renders a description if present", async function (assert) {
const attributes = {
description: "Write your bio here",
};
this.set("attributes", attributes);
await render(
hbs`<FormTemplateField::Input @attributes={{this.attributes}} />`
);
assert
.dom(".form-template-field__description")
.hasText("Write your bio here");
});
}
);

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import Wrapper from "discourse/components/form-template-field/wrapper";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import pretender, { response } from "discourse/tests/helpers/create-pretender";
@ -10,10 +10,10 @@ module(
setupRenderingTest(hooks);
test("does not render a component when template content has invalid YAML", async function (assert) {
const self = this;
this.set("content", `- type: checkbox\n attributes;invalid`);
await render(
hbs`<FormTemplateField::Wrapper @content={{this.content}} />`
);
await render(<template><Wrapper @content={{self.content}} /></template>);
assert
.dom(".form-template-field")
@ -22,6 +22,8 @@ module(
});
test("renders a component based on the component type found in the content YAML", async function (assert) {
const self = this;
const content = `- type: checkbox\n id: checkbox\n
- type: input\n id: name
- type: textarea\n id: notes
@ -38,9 +40,7 @@ module(
];
this.set("content", content);
await render(
hbs`<FormTemplateField::Wrapper @content={{this.content}} />`
);
await render(<template><Wrapper @content={{self.content}} /></template>);
componentTypes.forEach((componentType) => {
assert
@ -50,6 +50,8 @@ module(
});
test("renders a component based on the component type found in the content YAML, with initial values", async function (assert) {
const self = this;
const content = `- type: checkbox\n id: checkbox\n
- type: input\n id: name
- type: textarea\n id: notes
@ -66,7 +68,12 @@ module(
});
await render(
hbs`<FormTemplateField::Wrapper @content={{this.content}} @initialValues={{this.initialValues}} />`
<template>
<Wrapper
@content={{self.content}}
@initialValues={{self.initialValues}}
/>
</template>
);
assert.dom("[name='checkbox']").hasValue("on");
@ -77,6 +84,8 @@ module(
});
test("renders a component based on the component type found in the content YAML when passed ids", async function (assert) {
const self = this;
pretender.get("/form-templates/1.json", () => {
return response({
form_template: {
@ -90,7 +99,7 @@ module(
this.set("formTemplateId", [1]);
await render(
hbs`<FormTemplateField::Wrapper @id={{this.formTemplateId}} />`
<template><Wrapper @id={{self.formTemplateId}} /></template>
);
assert

View File

@ -1,15 +1,19 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import GroupMembershipButton from "discourse/components/group-membership-button";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | group-membership-button", function (hooks) {
setupRenderingTest(hooks);
test("canJoinGroup", async function (assert) {
const self = this;
this.set("model", { public_admission: false, is_group_user: true });
await render(hbs`<GroupMembershipButton @model={{this.model}} />`);
await render(
<template><GroupMembershipButton @model={{self.model}} /></template>
);
assert
.dom(".group-index-join")
@ -25,9 +29,13 @@ module("Integration | Component | group-membership-button", function (hooks) {
});
test("canLeaveGroup", async function (assert) {
const self = this;
this.set("model", { public_exit: false, is_group_user: false });
await render(hbs`<GroupMembershipButton @model={{this.model}} />`);
await render(
<template><GroupMembershipButton @model={{self.model}} /></template>
);
assert
.dom(".group-index-leave")
@ -43,12 +51,16 @@ module("Integration | Component | group-membership-button", function (hooks) {
});
test("canRequestMembership", async function (assert) {
const self = this;
this.set("model", {
allow_membership_requests: true,
is_group_user: true,
});
await render(hbs`<GroupMembershipButton @model={{this.model}} />`);
await render(
<template><GroupMembershipButton @model={{self.model}} /></template>
);
assert
.dom(".group-index-request")

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import IframedHtml from "discourse/components/iframed-html";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | iframed-html", function (hooks) {
@ -8,7 +8,12 @@ module("Integration | Component | iframed-html", function (hooks) {
test("appends the html into the iframe", async function (assert) {
await render(
hbs`<IframedHtml @html="<h1 id='find-me'>hello</h1>" class="this-is-an-iframe" />`
<template>
<IframedHtml
@html="<h1 id='find-me'>hello</h1>"
class="this-is-an-iframe"
/>
</template>
);
assert

View File

@ -1,7 +1,7 @@
import { getOwner } from "@ember/owner";
import { click, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import InvitePanel from "discourse/components/invite-panel";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import pretender, { response } from "discourse/tests/helpers/create-pretender";
import selectKit from "discourse/tests/helpers/select-kit-helper";
@ -10,6 +10,8 @@ module("Integration | Component | invite-panel", function (hooks) {
setupRenderingTest(hooks);
test("shows the invite link after it is generated", async function (assert) {
const self = this;
pretender.get("/u/search/users", () => response({ users: [] }));
pretender.post("/invites", () =>
@ -24,7 +26,9 @@ module("Integration | Component | invite-panel", function (hooks) {
});
this.set("inviteModel", user);
await render(hbs`<InvitePanel @inviteModel={{this.inviteModel}} />`);
await render(
<template><InvitePanel @inviteModel={{self.inviteModel}} /></template>
);
const input = selectKit(".invite-user-input");
await input.expand();

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import LoadMore from "discourse/components/load-more";
import { configureEyeline } from "discourse/lib/eyeline";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
@ -19,13 +19,17 @@ module("Integration | Component | load-more", function (hooks) {
});
test("updates once after initialization", async function (assert) {
const self = this;
this.set("loadMore", () => this.set("loadedMore", true));
await render(hbs`
<LoadMore @selector=".numbers tr" @action={{this.loadMore}}>
<table class="numbers"><tbody><tr></tr></tbody></table>
</LoadMore>
`);
await render(
<template>
<LoadMore @selector=".numbers tr" @action={{self.loadMore}}>
<table class="numbers"><tbody><tr></tr></tbody></table>
</LoadMore>
</template>
);
assert.true(this.loadedMore);
});

View File

@ -1,6 +1,6 @@
import { fillIn, render, triggerKeyEvent } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import NumberField from "discourse/components/number-field";
import { withSilencedDeprecationsAsync } from "discourse/lib/deprecated";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
@ -11,9 +11,13 @@ module("Integration | Component | number-field", function (hooks) {
this.set("value", 123);
await withSilencedDeprecationsAsync("discourse.number-field", async () => {
await render(hbs`
<NumberField @value={{this.value}} @classNames="number-field-test" />
`);
const self = this;
await render(
<template>
<NumberField @value={{self.value}} @classNames="number-field-test" />
</template>
);
});
await fillIn(".number-field-test", "33");
@ -38,9 +42,17 @@ module("Integration | Component | number-field", function (hooks) {
this.set("value", "");
await withSilencedDeprecationsAsync("discourse.number-field", async () => {
await render(hbs`
<NumberField @value={{this.value}} @classNames="number-field-test" @min="1" />
`);
const self = this;
await render(
<template>
<NumberField
@value={{self.value}}
@classNames="number-field-test"
@min="1"
/>
</template>
);
});
await triggerKeyEvent(".number-field-test", "keydown", 189); // -
@ -53,9 +65,17 @@ module("Integration | Component | number-field", function (hooks) {
);
await withSilencedDeprecationsAsync("discourse.number-field", async () => {
await render(hbs`
<NumberField @value={{this.value}} @classNames="number-field-test" @min="-10" />
`);
const self = this;
await render(
<template>
<NumberField
@value={{self.value}}
@classNames="number-field-test"
@min="-10"
/>
</template>
);
});
await fillIn(".number-field-test", "-1");

View File

@ -1,6 +1,7 @@
import { fn, hash } from "@ember/helper";
import { fillIn, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import FutureDateInput from "discourse/components/future-date-input";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { fakeTime, queryAll } from "discourse/tests/helpers/qunit-helpers";
import selectKit from "discourse/tests/helpers/select-kit-helper";
@ -28,13 +29,13 @@ module(
});
test("rendering and expanding", async function (assert) {
await render(hbs`
<FutureDateInput
@options={{hash
none="time_shortcut.select_timeframe"
}}
/>
`);
await render(
<template>
<FutureDateInput
@options={{hash none="time_shortcut.select_timeframe"}}
/>
</template>
);
assert.dom(".future-date-input-selector").exists("selector is rendered");
@ -59,7 +60,7 @@ module(
true
);
await render(hbs`<FutureDateInput />`);
await render(<template><FutureDateInput /></template>);
await this.subject.expand();
const options = getOptions();
@ -83,7 +84,7 @@ module(
});
test("shows 'Custom date and time' by default", async function (assert) {
await render(hbs`<FutureDateInput />`);
await render(<template><FutureDateInput /></template>);
await this.subject.expand();
const options = getOptions();
@ -93,11 +94,9 @@ module(
});
test("doesn't show 'Custom date and time' if disabled", async function (assert) {
await render(hbs`
<FutureDateInput
@includeDateTime={{false}}
/>
`);
await render(
<template><FutureDateInput @includeDateTime={{false}} /></template>
);
await this.subject.expand();
const options = getOptions();
@ -107,11 +106,9 @@ module(
});
test("shows the now option if enabled", async function (assert) {
await render(hbs`
<FutureDateInput
@includeNow={{true}}
/>
`);
await render(
<template><FutureDateInput @includeNow={{true}} /></template>
);
await this.subject.expand();
const options = getOptions();
@ -121,10 +118,17 @@ module(
});
test("changing date/time updates the input correctly", async function (assert) {
const self = this;
this.set("input", moment("2032-01-01 11:10"));
await render(
hbs`<FutureDateInput @input={{this.input}} @onChangeInput={{fn (mut this.input)}} />`
<template>
<FutureDateInput
@input={{self.input}}
@onChangeInput={{fn (mut self.input)}}
/>
</template>
);
await fillIn(".time-input", "11:15");

View File

@ -1,13 +1,15 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import SectionLink from "discourse/components/sidebar/section-link";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | sidebar | section-link", function (hooks) {
setupRenderingTest(hooks);
test("default class attribute for link", async function (assert) {
const template = hbs`<Sidebar::SectionLink @linkName="Test Meta" @route="discovery.latest" />`;
const template = <template>
<SectionLink @linkName="Test Meta" @route="discovery.latest" />
</template>;
await render(template);
@ -21,7 +23,13 @@ module("Integration | Component | sidebar | section-link", function (hooks) {
});
test("custom class attribute for link", async function (assert) {
const template = hbs`<Sidebar::SectionLink @linkName="Test Meta" @route="discovery.latest" @linkClass="123 abc" />`;
const template = <template>
<SectionLink
@linkName="Test Meta"
@route="discovery.latest"
@linkClass="123 abc"
/>
</template>;
await render(template);
@ -35,7 +43,9 @@ module("Integration | Component | sidebar | section-link", function (hooks) {
});
test("target attribute for link", async function (assert) {
const template = hbs`<Sidebar::SectionLink @linkName="test" @href="https://discourse.org" />`;
const template = <template>
<SectionLink @linkName="test" @href="https://discourse.org" />
</template>;
await render(template);
assert.dom("a").hasAttribute("target", "_self");
@ -43,7 +53,9 @@ module("Integration | Component | sidebar | section-link", function (hooks) {
test("target attribute for link when user set external links in new tab", async function (assert) {
this.currentUser.user_option.external_links_in_new_tab = true;
const template = hbs`<Sidebar::SectionLink @linkName="test" @href="https://discourse.org" />`;
const template = <template>
<SectionLink @linkName="test" @href="https://discourse.org" />
</template>;
await render(template);
assert.dom("a").hasAttribute("target", "_blank");

View File

@ -1,19 +1,23 @@
import { click, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import Section from "discourse/components/sidebar/section";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | sidebar | section", function (hooks) {
setupRenderingTest(hooks);
test("default displaySection value for section", async function (assert) {
const template = hbs`
<Sidebar::Section
const self = this;
const template = <template>
<Section
@sectionName="test"
@headerLinkText="test header"
@headerLinkTitle="some title"
@headerActionsIcon="plus"
@headerActions={{this.headerActions}} />`;
@headerActions={{self.headerActions}}
/>
</template>;
this.headerActions = [];
await render(template);
@ -24,14 +28,18 @@ module("Integration | Component | sidebar | section", function (hooks) {
});
test("displaySection is dynamic based on argument", async function (assert) {
const template = hbs`
<Sidebar::Section
const self = this;
const template = <template>
<Section
@sectionName="test"
@headerLinkText="test header"
@headerLinkTitle="some title"
@headerActionsIcon="plus"
@headerActions={{this.headerActions}}
@displaySection={{this.displaySection}}/>`;
@headerActions={{self.headerActions}}
@displaySection={{self.displaySection}}
/>
</template>;
this.displaySection = false;
this.headerActions = [];
@ -46,14 +54,18 @@ module("Integration | Component | sidebar | section", function (hooks) {
});
test("can expand and collapse content when section is collapsible", async function (assert) {
const template = hbs`
<Sidebar::Section
const self = this;
const template = <template>
<Section
@sectionName="test"
@headerLinkText="test header"
@headerLinkTitle="some title"
@headerActionsIcon="plus"
@headerActions={{this.headerActions}}
@collapsable={{true}} />`;
@headerActions={{self.headerActions}}
@collapsable={{true}}
/>
</template>;
this.headerActions = [];
await render(template);

View File

@ -1,56 +1,70 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import SlowModeInfo from "discourse/components/slow-mode-info";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | slow-mode-info", function (hooks) {
setupRenderingTest(hooks);
test("doesn't render if the topic is closed", async function (assert) {
const self = this;
this.set("topic", { slow_mode_seconds: 3600, closed: true });
await render(hbs`<SlowModeInfo @topic={{this.topic}} />`);
await render(<template><SlowModeInfo @topic={{self.topic}} /></template>);
assert.dom(".slow-mode-heading").doesNotExist("doesn't render the notice");
});
test("doesn't render if the slow mode is disabled", async function (assert) {
const self = this;
this.set("topic", { slow_mode_seconds: 0, closed: false });
await render(hbs`<SlowModeInfo @topic={{this.topic}} />`);
await render(<template><SlowModeInfo @topic={{self.topic}} /></template>);
assert.dom(".slow-mode-heading").doesNotExist("doesn't render the notice");
});
test("renders if slow mode is enabled", async function (assert) {
const self = this;
this.set("topic", { slow_mode_seconds: 3600, closed: false });
await render(hbs`<SlowModeInfo @topic={{this.topic}} />`);
await render(<template><SlowModeInfo @topic={{self.topic}} /></template>);
assert.dom(".slow-mode-heading").exists();
});
test("staff and TL4 users can disable slow mode", async function (assert) {
const self = this;
this.setProperties({
topic: { slow_mode_seconds: 3600, closed: false },
user: { canManageTopic: true },
});
await render(
hbs`<SlowModeInfo @topic={{this.topic}} @user={{this.user}} />`
<template>
<SlowModeInfo @topic={{self.topic}} @user={{self.user}} />
</template>
);
assert.dom(".slow-mode-remove").exists();
});
test("regular users can't disable slow mode", async function (assert) {
const self = this;
this.setProperties({
topic: { slow_mode_seconds: 3600, closed: false },
user: { canManageTopic: false },
});
await render(
hbs`<SlowModeInfo @topic={{this.topic}} @user={{this.user}} />`
<template>
<SlowModeInfo @topic={{self.topic}} @user={{self.user}} />
</template>
);
assert

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import softwareUpdatePrompt from "discourse/components/software-update-prompt";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { publishToMessageBus } from "discourse/tests/helpers/qunit-helpers";
@ -8,7 +8,7 @@ module("Integration | Component | software-update-prompt", function (hooks) {
setupRenderingTest(hooks);
test("software-update-prompt gets correct CSS class after messageBus message", async function (assert) {
await render(hbs`{{software-update-prompt}}`);
await render(<template>{{softwareUpdatePrompt}}</template>);
assert
.dom("div.software-update-prompt")

View File

@ -1,19 +1,21 @@
import { fillIn, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import TextField from "discourse/components/text-field";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | text-field", function (hooks) {
setupRenderingTest(hooks);
test("renders correctly with no properties set", async function (assert) {
await render(hbs`<TextField />`);
await render(<template><TextField /></template>);
assert.dom("input[type=text]").exists();
});
test("support a placeholder", async function (assert) {
await render(hbs`<TextField @placeholderKey="placeholder.i18n.key" />`);
await render(
<template><TextField @placeholderKey="placeholder.i18n.key" /></template>
);
assert.dom("input[type=text]").exists();
assert
@ -24,12 +26,16 @@ module("Integration | Component | text-field", function (hooks) {
test("sets the dir attribute to auto when mixed text direction enabled", async function (assert) {
this.siteSettings.support_mixed_text_direction = true;
await render(hbs`<TextField @value="זהו שם עברי עם מקום עברי" />`);
await render(
<template><TextField @value="זהו שם עברי עם מקום עברי" /></template>
);
assert.dom("input").hasAttribute("dir", "auto");
});
test("supports onChange", async function (assert) {
const self = this;
this.called = false;
this.newValue = null;
this.set("value", "hello");
@ -39,7 +45,13 @@ module("Integration | Component | text-field", function (hooks) {
});
await render(
hbs`<TextField class="tf-test" @value={{this.value}} @onChange={{this.changed}} />`
<template>
<TextField
class="tf-test"
@value={{self.value}}
@onChange={{self.changed}}
/>
</template>
);
await fillIn(".tf-test", "hello");
@ -51,6 +63,8 @@ module("Integration | Component | text-field", function (hooks) {
});
test("supports onChangeImmediate", async function (assert) {
const self = this;
this.called = false;
this.newValue = null;
this.set("value", "old");
@ -60,7 +74,13 @@ module("Integration | Component | text-field", function (hooks) {
});
await render(
hbs`<TextField class="tf-test" @value={{this.value}} @onChangeImmediate={{this.changed}} />`
<template>
<TextField
class="tf-test"
@value={{self.value}}
@onChangeImmediate={{self.changed}}
/>
</template>
);
await fillIn(".tf-test", "old");

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import TimeGap from "discourse/components/time-gap";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { i18n } from "discourse-i18n";
@ -8,32 +8,48 @@ module("Integration | Component | time-gap", function (hooks) {
setupRenderingTest(hooks);
test("it renders days correctly", async function (assert) {
const self = this;
this.set("daysSince", 5);
await render(hbs`<TimeGap @daysSince={{this.daysSince}} />`);
await render(
<template><TimeGap @daysSince={{self.daysSince}} /></template>
);
assert
.dom(".small-action-desc.timegap")
.hasText(i18n("dates.later.x_days", { count: 5 }));
});
test("it renders months correctly", async function (assert) {
const self = this;
this.set("daysSince", 90);
await render(hbs`<TimeGap @daysSince={{this.daysSince}} />`);
await render(
<template><TimeGap @daysSince={{self.daysSince}} /></template>
);
assert
.dom(".small-action-desc.timegap")
.hasText(i18n("dates.later.x_months", { count: 3 }));
});
test("it renders years correctly", async function (assert) {
const self = this;
this.set("daysSince", 730);
await render(hbs`<TimeGap @daysSince={{this.daysSince}} />`);
await render(
<template><TimeGap @daysSince={{self.daysSince}} /></template>
);
assert
.dom(".small-action-desc.timegap")
.hasText(i18n("dates.later.x_years", { count: 2 }));
});
test("it renders the correct elements", async function (assert) {
const self = this;
this.set("daysSince", 10);
await render(hbs`<TimeGap @daysSince={{this.daysSince}} />`);
await render(
<template><TimeGap @daysSince={{self.daysSince}} /></template>
);
assert.dom(".topic-avatar").exists();
assert.dom(".small-action-desc.timegap").exists();
});

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import TimeInput from "discourse/components/time-input";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import selectKit from "discourse/tests/helpers/select-kit-helper";
@ -16,20 +16,28 @@ module("Integration | Component | time-input", function (hooks) {
});
test("default", async function (assert) {
const self = this;
this.setProperties({ hours: "14", minutes: "58" });
await render(
hbs`<TimeInput @hours={{this.hours}} @minutes={{this.minutes}} />`
<template>
<TimeInput @hours={{self.hours}} @minutes={{self.minutes}} />
</template>
);
assert.strictEqual(this.subject.header().name(), "14:58");
});
test("prevents mutations", async function (assert) {
const self = this;
this.setProperties({ hours: "14", minutes: "58" });
await render(
hbs`<TimeInput @hours={{this.hours}} @minutes={{this.minutes}} />`
<template>
<TimeInput @hours={{self.hours}} @minutes={{self.minutes}} />
</template>
);
await this.subject.expand();
@ -38,11 +46,19 @@ module("Integration | Component | time-input", function (hooks) {
});
test("allows mutations through actions", async function (assert) {
const self = this;
this.setProperties({ hours: "14", minutes: "58" });
this.set("onChange", setTime);
await render(
hbs`<TimeInput @hours={{this.hours}} @minutes={{this.minutes}} @onChange={{this.onChange}} />`
<template>
<TimeInput
@hours={{self.hours}}
@minutes={{self.minutes}}
@onChange={{self.onChange}}
/>
</template>
);
await this.subject.expand();

View File

@ -1,6 +1,6 @@
import { click, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import TimeShortcutPicker from "discourse/components/time-shortcut-picker";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { fakeTime, queryAll } from "discourse/tests/helpers/qunit-helpers";
import { i18n } from "discourse-i18n";
@ -22,11 +22,15 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
});
test("shows default options", async function (assert) {
const self = this;
this.siteSettings.suggest_weekends_in_date_pickers = true;
const tuesday = "2100-06-08T08:00:00";
this.clock = fakeTime(tuesday, this.currentUser.user_option.timezone, true);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
await render(
<template><TimeShortcutPicker @_itsatrap={{self.itsatrap}} /></template>
);
const expected = [
i18n("time_shortcut.later_today"),
@ -49,15 +53,21 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
});
test("show 'Later This Week' if today is < Thursday", async function (assert) {
const self = this;
const monday = "2100-06-07T08:00:00";
this.clock = fakeTime(monday, this.currentUser.user_option.timezone, true);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
await render(
<template><TimeShortcutPicker @_itsatrap={{self.itsatrap}} /></template>
);
assert.dom("#tap_tile_later_this_week").exists("has later this week");
});
test("does not show 'Later This Week' if today is >= Thursday", async function (assert) {
const self = this;
const thursday = "2100-06-10T08:00:00";
this.clock = fakeTime(
thursday,
@ -65,7 +75,9 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
true
);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
await render(
<template><TimeShortcutPicker @_itsatrap={{self.itsatrap}} /></template>
);
assert
.dom("#tap_tile_later_this_week")
@ -73,13 +85,17 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
});
test("does not show 'Later Today' if 'Later Today' is tomorrow", async function (assert) {
const self = this;
this.clock = fakeTime(
"2100-12-11T22:00:00", // + 3 hours is tomorrow
this.currentUser.user_option.timezone,
true
);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
await render(
<template><TimeShortcutPicker @_itsatrap={{self.itsatrap}} /></template>
);
assert
.dom("#tap_tile_later_today")
@ -87,25 +103,33 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
});
test("shows 'Later Today' if it is before 5pm", async function (assert) {
const self = this;
this.clock = fakeTime(
"2100-12-11T16:50:00",
this.currentUser.user_option.timezone,
true
);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
await render(
<template><TimeShortcutPicker @_itsatrap={{self.itsatrap}} /></template>
);
assert.dom("#tap_tile_later_today").exists("has later today");
});
test("does not show 'Later Today' if it is after 5pm", async function (assert) {
const self = this;
this.clock = fakeTime(
"2100-12-11T17:00:00",
this.currentUser.user_option.timezone,
true
);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
await render(
<template><TimeShortcutPicker @_itsatrap={{self.itsatrap}} /></template>
);
assert
.dom("#tap_tile_later_today")
@ -113,13 +137,17 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
});
test("default custom date time is in one hour from now", async function (assert) {
const self = this;
this.clock = fakeTime(
"2100-12-11T17:00:00",
this.currentUser.user_option.timezone,
true
);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
await render(
<template><TimeShortcutPicker @_itsatrap={{self.itsatrap}} /></template>
);
await click("#tap_tile_custom");
assert.dom("#custom-date > input").hasValue("2100-12-11");
@ -127,10 +155,14 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
});
test("shows 'Next Monday' instead of 'Monday' on Sundays", async function (assert) {
const self = this;
const sunday = "2100-01-24T08:00:00";
this.clock = fakeTime(sunday, this.currentUser.user_option.timezone, true);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
await render(
<template><TimeShortcutPicker @_itsatrap={{self.itsatrap}} /></template>
);
assert
.dom("#tap_tile_start_of_next_business_week .tap-tile-title")
@ -142,10 +174,14 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
});
test("shows 'Next Monday' instead of 'Monday' on Mondays", async function (assert) {
const self = this;
const monday = "2100-01-25T08:00:00";
this.clock = fakeTime(monday, this.currentUser.user_option.timezone, true);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
await render(
<template><TimeShortcutPicker @_itsatrap={{self.itsatrap}} /></template>
);
assert
.dom("#tap_tile_start_of_next_business_week .tap-tile-title")
@ -157,13 +193,17 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
});
test("the 'Next Month' option points to the first day of the next month", async function (assert) {
const self = this;
this.clock = fakeTime(
"2100-01-01T08:00:00",
this.currentUser.user_option.timezone,
true
);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
await render(
<template><TimeShortcutPicker @_itsatrap={{self.itsatrap}} /></template>
);
assert
.dom("div#tap_tile_next_month div.tap-tile-date")

View File

@ -1,19 +1,23 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import TopicParticipant from "discourse/components/topic-map/topic-participant";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | topic-participant", function (hooks) {
setupRenderingTest(hooks);
test("one post", async function (assert) {
const self = this;
this.set("args", {
username: "test",
avatar_template: "/images/avatar.png",
post_count: 1,
});
await render(hbs`<TopicMap::TopicParticipant @participant={{this.args}}/>`);
await render(
<template><TopicParticipant @participant={{self.args}} /></template>
);
assert.dom("a.poster.trigger-user-card").hasAttribute("href", "/u/test");
assert.dom("span.post-count").doesNotExist();
@ -21,6 +25,8 @@ module("Integration | Component | topic-participant", function (hooks) {
});
test("many posts, a primary group with flair", async function (assert) {
const self = this;
this.set("args", {
username: "test",
avatar_template: "/images/avatar.png",
@ -32,7 +38,9 @@ module("Integration | Component | topic-participant", function (hooks) {
flair_group_id: "41",
});
await render(hbs`<TopicMap::TopicParticipant @participant={{this.args}}/>`);
await render(
<template><TopicParticipant @participant={{self.args}} /></template>
);
assert.dom("a.poster.trigger-user-card").hasAttribute("href", "/u/test");
assert.dom("span.post-count").exists();

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import UserAvatarFlair from "discourse/components/user-avatar-flair";
import { resetFlair } from "discourse/lib/avatar-flair";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
@ -49,6 +49,8 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
});
test("avatar flair for admin user", async function (assert) {
const self = this;
this.set("args", {
admin: true,
moderator: false,
@ -57,7 +59,7 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
});
setupSiteGroups(this);
await render(hbs`<UserAvatarFlair @user={{this.args}} />`);
await render(<template><UserAvatarFlair @user={{self.args}} /></template>);
assert.dom(".avatar-flair").exists("has the tag");
assert.dom("svg.d-icon-bars").exists("has the svg icon");
@ -68,6 +70,8 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
});
test("avatar flair for moderator user with fallback to staff", async function (assert) {
const self = this;
this.set("args", {
admin: false,
moderator: true,
@ -76,7 +80,7 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
});
setupSiteGroups(this);
await render(hbs`<UserAvatarFlair @user={{this.args}} />`);
await render(<template><UserAvatarFlair @user={{self.args}} /></template>);
assert.dom(".avatar-flair").exists("has the tag");
assert.dom("svg.d-icon-bars").exists("has the svg icon");
@ -87,6 +91,8 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
});
test("avatar flair for trust level", async function (assert) {
const self = this;
this.set("args", {
admin: false,
moderator: false,
@ -95,7 +101,7 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
});
setupSiteGroups(this);
await render(hbs`<UserAvatarFlair @user={{this.args}} />`);
await render(<template><UserAvatarFlair @user={{self.args}} /></template>);
assert.dom(".avatar-flair").exists("has the tag");
assert.dom("svg.d-icon-dice-two").exists("has the svg icon");
@ -106,6 +112,8 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
});
test("avatar flair for trust level when set to none", async function (assert) {
const self = this;
this.set("args", {
admin: false,
moderator: false,
@ -114,12 +122,14 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
});
setupSiteGroups(this);
await render(hbs`<UserAvatarFlair @user={{this.args}} />`);
await render(<template><UserAvatarFlair @user={{self.args}} /></template>);
assert.dom(".avatar-flair").doesNotExist("does not render a flair");
});
test("avatar flair for trust level with fallback", async function (assert) {
const self = this;
this.set("args", {
admin: false,
moderator: false,
@ -128,7 +138,7 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
});
setupSiteGroups(this);
await render(hbs`<UserAvatarFlair @user={{this.args}} />`);
await render(<template><UserAvatarFlair @user={{self.args}} /></template>);
assert.dom(".avatar-flair").exists("has the tag");
assert.dom("svg.d-icon-dice-two").exists("has the svg icon");
@ -139,6 +149,8 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
});
test("avatar flair for login-required site, before login", async function (assert) {
const self = this;
this.set("args", {
admin: false,
moderator: false,
@ -148,12 +160,14 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
// Groups not serialized for anon on login_required
this.site.groups = undefined;
await render(hbs`<UserAvatarFlair @user={{this.args}} />`);
await render(<template><UserAvatarFlair @user={{self.args}} /></template>);
assert.dom(".avatar-flair").doesNotExist("does not render a flair");
});
test("avatar flair for primary group flair", async function (assert) {
const self = this;
this.set("args", {
admin: false,
moderator: false,
@ -167,7 +181,7 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
});
setupSiteGroups(this);
await render(hbs`<UserAvatarFlair @user={{this.args}} />`);
await render(<template><UserAvatarFlair @user={{self.args}} /></template>);
assert.dom(".avatar-flair").exists("has the tag");
assert.dom("svg.d-icon-xmark").exists("has the svg icon");
@ -178,6 +192,8 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
});
test("user-avatar-flair for user with no flairs", async function (assert) {
const self = this;
this.set("args", {
admin: false,
moderator: false,
@ -185,7 +201,7 @@ module("Integration | Component | user-avatar-flair", function (hooks) {
flair_group_id: 11,
});
await render(hbs`<UserAvatarFlair @user={{this.args}} />`);
await render(<template><UserAvatarFlair @user={{self.args}} /></template>);
assert.dom(".avatar-flair").doesNotExist("does not render a flair");
});

View File

@ -1,34 +1,46 @@
import { render, triggerEvent } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import UserInfo from "discourse/components/user-info";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import DTooltips from "float-kit/components/d-tooltips";
module("Integration | Component | user-info", function (hooks) {
setupRenderingTest(hooks);
test("prioritized name", async function (assert) {
const self = this;
this.siteSettings.prioritize_username_in_ux = false;
this.currentUser.name = "Evil Trout";
await render(hbs`<UserInfo @user={{this.currentUser}} />`);
await render(<template><UserInfo @user={{self.currentUser}} /></template>);
assert.dom(".name").hasText("Evil Trout");
assert.dom(".username").hasText("eviltrout");
});
test("prioritized username", async function (assert) {
const self = this;
this.siteSettings.prioritize_username_in_ux = true;
this.currentUser.name = "Evil Trout";
await render(hbs`<UserInfo @user={{this.currentUser}} />`);
await render(<template><UserInfo @user={{self.currentUser}} /></template>);
assert.dom(".username").hasText("eviltrout");
assert.dom(".name").hasText("Evil Trout");
});
test("includeLink", async function (assert) {
const self = this;
await render(
hbs`<UserInfo @user={{this.currentUser}} @includeLink={{this.includeLink}} />`
<template>
<UserInfo
@user={{self.currentUser}}
@includeLink={{self.includeLink}}
/>
</template>
);
this.set("includeLink", true);
@ -41,8 +53,15 @@ module("Integration | Component | user-info", function (hooks) {
});
test("includeAvatar", async function (assert) {
const self = this;
await render(
hbs`<UserInfo @user={{this.currentUser}} @includeAvatar={{this.includeAvatar}} />`
<template>
<UserInfo
@user={{self.currentUser}}
@includeAvatar={{self.includeAvatar}}
/>
</template>
);
this.set("includeAvatar", true);
@ -53,52 +72,70 @@ module("Integration | Component | user-info", function (hooks) {
});
test("shows status if enabled and user has status", async function (assert) {
const self = this;
this.currentUser.name = "Evil Trout";
this.currentUser.status = { emoji: "tooth", description: "off to dentist" };
await render(
hbs`<UserInfo @user={{this.currentUser}} @showStatus={{true}} />`
<template>
<UserInfo @user={{self.currentUser}} @showStatus={{true}} />
</template>
);
assert.dom(".user-status-message").exists();
});
test("doesn't show status if enabled but user doesn't have status", async function (assert) {
const self = this;
this.currentUser.name = "Evil Trout";
await render(
hbs`<UserInfo @user={{this.currentUser}} @showStatus={{true}} />`
<template>
<UserInfo @user={{self.currentUser}} @showStatus={{true}} />
</template>
);
assert.dom(".user-status-message").doesNotExist();
});
test("doesn't show status if disabled", async function (assert) {
const self = this;
this.currentUser.name = "Evil Trout";
this.currentUser.status = { emoji: "tooth", description: "off to dentist" };
await render(
hbs`<UserInfo @user={{this.currentUser}} @showStatus={{false}} />`
<template>
<UserInfo @user={{self.currentUser}} @showStatus={{false}} />
</template>
);
assert.dom(".user-status-message").doesNotExist();
});
test("doesn't show status by default", async function (assert) {
const self = this;
this.currentUser.name = "Evil Trout";
this.currentUser.status = { emoji: "tooth", description: "off to dentist" };
await render(hbs`<UserInfo @user={{this.currentUser}} />`);
await render(<template><UserInfo @user={{self.currentUser}} /></template>);
assert.dom(".user-status-message").doesNotExist();
});
test("doesn't show status description by default", async function (assert) {
const self = this;
this.currentUser.name = "Evil Trout";
this.currentUser.status = { emoji: "tooth", description: "off to dentist" };
await render(
hbs`<UserInfo @user={{this.currentUser}} @showStatus={{true}} />`
<template>
<UserInfo @user={{self.currentUser}} @showStatus={{true}} />
</template>
);
assert
@ -107,11 +144,19 @@ module("Integration | Component | user-info", function (hooks) {
});
test("shows status description if enabled", async function (assert) {
const self = this;
this.currentUser.name = "Evil Trout";
this.currentUser.status = { emoji: "tooth", description: "off to dentist" };
await render(
hbs`<UserInfo @user={{this.currentUser}} @showStatus={{true}} @showStatusDescription={{true}} />`
<template>
<UserInfo
@user={{self.currentUser}}
@showStatus={{true}}
@showStatusDescription={{true}}
/>
</template>
);
assert
@ -120,11 +165,16 @@ module("Integration | Component | user-info", function (hooks) {
});
test("shows status tooltip if enabled", async function (assert) {
const self = this;
this.currentUser.name = "Evil Trout";
this.currentUser.status = { emoji: "tooth", description: "off to dentist" };
await render(
hbs`<UserInfo @user={{this.currentUser}} @showStatus={{true}} /><DTooltips />`
<template>
<UserInfo @user={{self.currentUser}} @showStatus={{true}} /><DTooltips
/>
</template>
);
await triggerEvent(".user-status-message", "pointermove");

View File

@ -1,6 +1,6 @@
import { render, settled } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import BookmarksList from "discourse/components/user-menu/bookmarks-list";
import { NOTIFICATION_TYPES } from "discourse/tests/fixtures/concerns/notification-types";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import pretender, { response } from "discourse/tests/helpers/create-pretender";
@ -13,7 +13,7 @@ module(
setupRenderingTest(hooks);
test("renders notifications on top and bookmarks on bottom", async function (assert) {
await render(hbs`<UserMenu::BookmarksList/>`);
await render(<template><BookmarksList /></template>);
const items = queryAll("ul li");
assert.strictEqual(items.length, 2);
@ -26,7 +26,7 @@ module(
});
test("show all button for bookmark notifications", async function (assert) {
await render(hbs`<UserMenu::BookmarksList/>`);
await render(<template><BookmarksList /></template>);
assert
.dom(".panel-body-bottom .show-all")
.hasAttribute(
@ -40,7 +40,7 @@ module(
this.currentUser.set("grouped_unread_notifications", {
[NOTIFICATION_TYPES.bookmark_reminder]: 72,
});
await render(hbs`<UserMenu::BookmarksList/>`);
await render(<template><BookmarksList /></template>);
assert
.dom(".panel-body-bottom .notifications-dismiss")
.exists(
@ -68,7 +68,7 @@ module(
pretender.get("/u/eviltrout/user-menu-bookmarks", () => {
return response({ notifications: [], bookmarks: [] });
});
await render(hbs`<UserMenu::BookmarksList/>`);
await render(<template><BookmarksList /></template>);
assert
.dom(".empty-state-title")
.hasText(i18n("user.no_bookmarks_title"), "empty state title is shown");

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import LikesNotificationsList from "discourse/components/user-menu/likes-notifications-list";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import pretender, { response } from "discourse/tests/helpers/create-pretender";
import { i18n } from "discourse-i18n";
@ -15,7 +15,7 @@ module(
return response({ notifications: [] });
});
await render(hbs`<UserMenu::LikesNotificationsList/>`);
await render(<template><LikesNotificationsList /></template>);
assert
.dom(".empty-state-title")

View File

@ -1,6 +1,6 @@
import { render, settled } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import MenuItem from "discourse/components/user-menu/menu-item";
import { cloneJSON, deepMerge } from "discourse/lib/object";
import { withPluginApi } from "discourse/lib/plugin-api";
import UserMenuBookmarkItem from "discourse/lib/user-menu/bookmark-item";
@ -53,12 +53,14 @@ module(
setupRenderingTest(hooks);
test("pushes `read` to the classList if the notification is read and `unread` if it isn't", async function (assert) {
const self = this;
this.set(
"item",
getNotification(this.currentUser, this.siteSettings, this.site)
);
this.item.notification.read = false;
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert.dom("li.read").doesNotExist();
assert.dom("li.unread").exists();
@ -74,11 +76,13 @@ module(
});
test("pushes the notification type name to the classList", async function (assert) {
const self = this;
this.set(
"item",
getNotification(this.currentUser, this.siteSettings, this.site)
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert.dom("li").hasClass("mentioned");
this.set(
@ -95,36 +99,44 @@ module(
});
test("pushes is-warning to the classList if the notification originates from a warning PM", async function (assert) {
const self = this;
this.set(
"item",
getNotification(this.currentUser, this.siteSettings, this.site, {
is_warning: true,
})
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert.dom("li.is-warning").exists();
});
test("doesn't push is-warning to the classList if the notification doesn't originate from a warning PM", async function (assert) {
const self = this;
this.set(
"item",
getNotification(this.currentUser, this.siteSettings, this.site)
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert.dom("li.is-warning").doesNotExist();
assert.dom("li").exists();
});
test("the item's href links to the topic that the notification originates from", async function (assert) {
const self = this;
this.set(
"item",
getNotification(this.currentUser, this.siteSettings, this.site)
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert.dom("li a").hasAttribute("href", "/t/this-is-fancy-title/449/113");
});
test("the item's href links to the group messages if the notification is for a group messages", async function (assert) {
const self = this;
this.set(
"item",
getNotification(this.currentUser, this.siteSettings, this.site, {
@ -138,16 +150,18 @@ module(
},
})
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert.dom("li a").hasAttribute("href", "/u/ossaama/messages/grouperss");
});
test("the item's link has a title for accessibility", async function (assert) {
const self = this;
this.set(
"item",
getNotification(this.currentUser, this.siteSettings, this.site)
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom("li a")
@ -155,11 +169,13 @@ module(
});
test("has elements for label and description", async function (assert) {
const self = this;
this.set(
"item",
getNotification(this.currentUser, this.siteSettings, this.site)
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom("li a .item-label")
@ -174,13 +190,15 @@ module(
});
test("the description falls back to topic_title from data if fancy_title is absent", async function (assert) {
const self = this;
this.set(
"item",
getNotification(this.currentUser, this.siteSettings, this.site, {
fancy_title: null,
})
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom("li a .item-description")
@ -191,13 +209,15 @@ module(
});
test("fancy_title is emoji-unescaped", async function (assert) {
const self = this;
this.set(
"item",
getNotification(this.currentUser, this.siteSettings, this.site, {
fancy_title: "title with emoji :phone:",
})
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom("li a .item-description img.emoji")
.exists(
@ -206,6 +226,8 @@ module(
});
test("topic_title from data is emoji-unescaped safely", async function (assert) {
const self = this;
this.set(
"item",
getNotification(this.currentUser, this.siteSettings, this.site, {
@ -215,7 +237,7 @@ module(
},
})
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom("li a .item-description")
@ -229,6 +251,8 @@ module(
});
test("various aspects can be customized according to the notification's render director", async function (assert) {
const self = this;
withPluginApi("0.1", (api) => {
api.registerNotificationTypeRenderer(
"linked",
@ -277,7 +301,7 @@ module(
})
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom("li.additional.classes")
@ -318,6 +342,8 @@ module(
});
test("description can be omitted", async function (assert) {
const self = this;
withPluginApi("0.1", (api) => {
api.registerNotificationTypeRenderer(
"linked",
@ -342,7 +368,7 @@ module(
})
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom(".item-description")
.doesNotExist("description is not rendered");
@ -352,6 +378,8 @@ module(
});
test("label can be omitted", async function (assert) {
const self = this;
withPluginApi("0.1", (api) => {
api.registerNotificationTypeRenderer(
"linked",
@ -376,7 +404,7 @@ module(
})
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom("li")
.hasText(
@ -406,6 +434,8 @@ module(
setupRenderingTest(hooks);
test("item description is the fancy title of the message", async function (assert) {
const self = this;
this.set(
"item",
getMessage(
@ -414,7 +444,7 @@ module(
this.site
)
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom("li.message .item-description")
.hasText("This is a safe title!");
@ -476,14 +506,18 @@ module(
setupRenderingTest(hooks);
test("uses bookmarkable_url for the href", async function (assert) {
const self = this;
this.set("item", getBookmark({}, this.siteSettings, this.site));
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom("li.bookmark a")
.hasAttribute("href", /\/t\/this-bookmarkable-url\/227\/1$/);
});
test("item label is the bookmarked post author", async function (assert) {
const self = this;
this.set(
"item",
getBookmark(
@ -492,11 +526,13 @@ module(
this.site
)
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert.dom("li.bookmark .item-label").hasText("bookmarkPostAuthor");
});
test("item description is the bookmark title", async function (assert) {
const self = this;
this.set(
"item",
getBookmark(
@ -505,7 +541,7 @@ module(
this.site
)
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom("li.bookmark .item-description")
.hasText("Custom bookmark title");
@ -542,34 +578,40 @@ module(
setupRenderingTest(hooks);
test("doesn't push `reviewed` to the classList if the reviewable is pending", async function (assert) {
const self = this;
this.set(
"item",
getReviewable(this.currentUser, this.siteSettings, this.site, {
pending: true,
})
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert.dom("li.reviewed").doesNotExist();
assert.dom("li").exists();
});
test("pushes `reviewed` to the classList if the reviewable isn't pending", async function (assert) {
const self = this;
this.set(
"item",
getReviewable(this.currentUser, this.siteSettings, this.site, {
pending: false,
})
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert.dom("li.reviewed").exists();
});
test("has elements for label and description", async function (assert) {
const self = this;
this.set(
"item",
getReviewable(this.currentUser, this.siteSettings, this.site)
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom("li .item-label")
@ -583,13 +625,15 @@ module(
});
test("the item's label is a placeholder that indicates deleted user if flagger_username is absent", async function (assert) {
const self = this;
this.set(
"item",
getReviewable(this.currentUser, this.siteSettings, this.site, {
flagger_username: null,
})
);
await render(hbs`<UserMenu::MenuItem @item={{this.item}}/>`);
await render(<template><MenuItem @item={{self.item}} /></template>);
assert
.dom("li .item-label")
.hasText(i18n("user_menu.reviewable.deleted_user"));

View File

@ -1,6 +1,6 @@
import { click, render, settled } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import Menu from "discourse/components/user-menu/menu";
import { NOTIFICATION_TYPES } from "discourse/tests/fixtures/concerns/notification-types";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import pretender from "discourse/tests/helpers/create-pretender";
@ -10,7 +10,7 @@ module("Integration | Component | user-menu", function (hooks) {
setupRenderingTest(hooks);
test("default tab is all notifications", async function (assert) {
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
assert
.dom(".top-tabs.tabs-list .btn.active")
@ -23,13 +23,13 @@ module("Integration | Component | user-menu", function (hooks) {
});
test("active tab has a11y attributes that indicate it's active", async function (assert) {
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
assert.dom(".top-tabs.tabs-list .btn.active").hasAttribute("tabindex", "0");
assert.dom(".top-tabs.tabs-list .btn.active").hasAria("selected", "true");
});
test("inactive tab has a11y attributes that indicate it's inactive", async function (assert) {
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
assert
.dom(".top-tabs.tabs-list .btn:not(.active)")
.hasAttribute("tabindex", "-1");
@ -40,7 +40,7 @@ module("Integration | Component | user-menu", function (hooks) {
test("the menu has a group of tabs at the top", async function (assert) {
this.currentUser.set("can_send_private_messages", true);
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
const tabs = queryAll(".top-tabs.tabs-list .btn");
assert.strictEqual(tabs.length, 6);
["all-notifications", "replies", "likes", "messages", "bookmarks"].forEach(
@ -54,7 +54,7 @@ module("Integration | Component | user-menu", function (hooks) {
test("the menu has a group of tabs at the bottom", async function (assert) {
this.currentUser.set("can_send_private_messages", true);
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
const tabs = queryAll(".bottom-tabs.tabs-list .btn");
assert.strictEqual(tabs.length, 1);
const profileTab = tabs[0];
@ -66,7 +66,7 @@ module("Integration | Component | user-menu", function (hooks) {
test("likes tab is hidden if current user's like notifications frequency is 'never'", async function (assert) {
this.currentUser.set("user_option.likes_notifications_disabled", true);
this.currentUser.set("can_send_private_messages", true);
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
assert.dom("#user-menu-button-likes").doesNotExist();
const tabs = Array.from(queryAll(".tabs-list .btn")); // top and bottom tabs
@ -83,7 +83,7 @@ module("Integration | Component | user-menu", function (hooks) {
this.currentUser.set("can_review", true);
this.currentUser.set("reviewable_count", 1);
this.currentUser.set("can_send_private_messages", true);
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
assert
.dom("#user-menu-button-review-queue")
@ -102,7 +102,7 @@ module("Integration | Component | user-menu", function (hooks) {
test("reviewables tab is not shown if current user can review but there are no pending reviewables", async function (assert) {
this.currentUser.set("can_review", true);
this.currentUser.set("reviewable_count", 0);
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
assert.dom("#user-menu-button-review-queue").doesNotExist();
});
@ -112,7 +112,7 @@ module("Integration | Component | user-menu", function (hooks) {
this.currentUser.set("groups", []);
this.currentUser.set("can_send_private_messages", false);
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
assert.dom("#user-menu-button-messages").doesNotExist();
@ -132,7 +132,7 @@ module("Integration | Component | user-menu", function (hooks) {
this.currentUser.set("groups", []);
this.currentUser.set("can_send_private_messages", true);
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
assert.dom("#user-menu-button-messages").exists();
});
@ -140,7 +140,7 @@ module("Integration | Component | user-menu", function (hooks) {
test("reviewables count is shown on the reviewables tab", async function (assert) {
this.currentUser.set("can_review", true);
this.currentUser.set("reviewable_count", 4);
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
assert
.dom("#user-menu-button-review-queue .badge-notification")
.hasText("4");
@ -156,7 +156,7 @@ module("Integration | Component | user-menu", function (hooks) {
test("changing tabs", async function (assert) {
this.currentUser.set("can_review", true);
this.currentUser.set("reviewable_count", 1);
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
let queryParams;
pretender.get("/notifications", (request) => {
queryParams = request.queryParams;
@ -315,7 +315,7 @@ module("Integration | Component | user-menu", function (hooks) {
[NOTIFICATION_TYPES.reaction]: 3,
[NOTIFICATION_TYPES.bookmark_reminder]: 10,
});
await render(hbs`<UserMenu::Menu/>`);
await render(<template><Menu /></template>);
assert
.dom("#user-menu-button-likes .badge-notification")

View File

@ -1,6 +1,6 @@
import { render, settled } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import MessagesList from "discourse/components/user-menu/messages-list";
import { cloneJSON, deepMerge } from "discourse/lib/object";
import { NOTIFICATION_TYPES } from "discourse/tests/fixtures/concerns/notification-types";
import UserMenuFixtures from "discourse/tests/fixtures/user-menu";
@ -100,7 +100,7 @@ module("Integration | Component | user-menu | messages-list", function (hooks) {
copy.read_notifications = [getGroupMessageSummaryNotification()];
return response(copy);
});
await render(hbs`<UserMenu::MessagesList/>`);
await render(<template><MessagesList /></template>);
const items = queryAll("ul li");
assert.strictEqual(items.length, 3);
@ -125,7 +125,7 @@ module("Integration | Component | user-menu | messages-list", function (hooks) {
return response(copy);
});
await render(hbs`<UserMenu::MessagesList/>`);
await render(<template><MessagesList /></template>);
const items = queryAll("ul li");
assert.strictEqual(items.length, 2);
@ -147,7 +147,7 @@ module("Integration | Component | user-menu | messages-list", function (hooks) {
return response(copy);
});
await render(hbs`<UserMenu::MessagesList/>`);
await render(<template><MessagesList /></template>);
const items = queryAll("ul li");
assert.strictEqual(items.length, 2);
@ -206,7 +206,7 @@ module("Integration | Component | user-menu | messages-list", function (hooks) {
];
return response(copy);
});
await render(hbs`<UserMenu::MessagesList/>`);
await render(<template><MessagesList /></template>);
const items = queryAll("ul li");
assert.strictEqual(items.length, 6);
@ -240,7 +240,7 @@ module("Integration | Component | user-menu | messages-list", function (hooks) {
});
test("show all button for message notifications", async function (assert) {
await render(hbs`<UserMenu::MessagesList/>`);
await render(<template><MessagesList /></template>);
assert
.dom(".panel-body-bottom .show-all")
.hasAttribute(
@ -254,7 +254,7 @@ module("Integration | Component | user-menu | messages-list", function (hooks) {
this.currentUser.set("grouped_unread_notifications", {
[NOTIFICATION_TYPES.private_message]: 72,
});
await render(hbs`<UserMenu::MessagesList/>`);
await render(<template><MessagesList /></template>);
assert
.dom(".panel-body-bottom .notifications-dismiss")
@ -288,7 +288,7 @@ module("Integration | Component | user-menu | messages-list", function (hooks) {
});
});
await render(hbs`<UserMenu::MessagesList/>`);
await render(<template><MessagesList /></template>);
assert
.dom(".empty-state-title")

View File

@ -1,6 +1,6 @@
import { click, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import NotificationsList from "discourse/components/user-menu/notifications-list";
import { cloneJSON } from "discourse/lib/object";
import { NOTIFICATION_TYPES } from "discourse/tests/fixtures/concerns/notification-types";
import NotificationFixtures from "discourse/tests/fixtures/notification-fixtures";
@ -44,13 +44,13 @@ module(
test("empty state when there are no notifications", async function (assert) {
notificationsData.clear();
await render(hbs`<UserMenu::NotificationsList/>`);
await render(<template><NotificationsList /></template>);
assert.dom(".empty-state .empty-state-title").exists();
assert.dom(".empty-state .empty-state-body").exists();
});
test("doesn't set filter_by_types in the params of the request that fetches the notifications", async function (assert) {
await render(hbs`<UserMenu::NotificationsList/>`);
await render(<template><NotificationsList /></template>);
assert.strictEqual(
queryParams.filter_by_types,
undefined,
@ -59,12 +59,12 @@ module(
});
test("doesn't request the full notifications list in silent mode", async function (assert) {
await render(hbs`<UserMenu::NotificationsList/>`);
await render(<template><NotificationsList /></template>);
assert.strictEqual(queryParams.silent, undefined);
});
test("show all button for all notifications page", async function (assert) {
await render(hbs`<UserMenu::NotificationsList/>`);
await render(<template><NotificationsList /></template>);
assert
.dom(".panel-body-bottom .btn.show-all")
.hasAttribute(
@ -78,7 +78,7 @@ module(
this.currentUser.set("grouped_unread_notifications", {
[NOTIFICATION_TYPES.mentioned]: 1,
});
await render(hbs`<UserMenu::NotificationsList/>`);
await render(<template><NotificationsList /></template>);
assert
.dom(".panel-body-bottom .btn.notifications-dismiss")
.hasText(i18n("user.dismiss"), "dismiss button has a label");
@ -95,14 +95,14 @@ module(
notificationsData.forEach((notification) => {
notification.read = true;
});
await render(hbs`<UserMenu::NotificationsList/>`);
await render(<template><NotificationsList /></template>);
assert
.dom(".panel-body-bottom .btn.notifications-dismiss")
.doesNotExist();
});
test("dismiss button makes a request to the server and then refreshes the notifications list", async function (assert) {
await render(hbs`<UserMenu::NotificationsList/>`);
await render(<template><NotificationsList /></template>);
this.currentUser.set("grouped_unread_notifications", {
[NOTIFICATION_TYPES.mentioned]: 1,
});
@ -204,7 +204,7 @@ module(
],
});
});
await render(hbs`<UserMenu::NotificationsList/>`);
await render(<template><NotificationsList /></template>);
const items = queryAll("ul li");
assert
.dom(items[0])

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import OtherNotificationsList from "discourse/components/user-menu/other-notifications-list";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import pretender, { response } from "discourse/tests/helpers/create-pretender";
import { i18n } from "discourse-i18n";
@ -17,7 +17,7 @@ module(
});
test("empty state when there are no notifications", async function (assert) {
await render(hbs`<UserMenu::OtherNotificationsList/>`);
await render(<template><OtherNotificationsList /></template>);
assert.dom(".empty-state .empty-state-body").exists();
assert
.dom(".empty-state .empty-state-title")

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import RepliesNotificationsList from "discourse/components/user-menu/replies-notifications-list";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import pretender, { response } from "discourse/tests/helpers/create-pretender";
import { i18n } from "discourse-i18n";
@ -17,7 +17,7 @@ module(
});
test("empty state when there are no notifications", async function (assert) {
await render(hbs`<UserMenu::RepliesNotificationsList/>`);
await render(<template><RepliesNotificationsList /></template>);
assert.dom(".empty-state .empty-state-body").exists();
assert
.dom(".empty-state .empty-state-title")

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import ReviewablesList from "discourse/components/user-menu/reviewables-list";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
import { i18n } from "discourse-i18n";
@ -11,7 +11,7 @@ module(
setupRenderingTest(hooks);
test("show all button for reviewable notifications", async function (assert) {
await render(hbs`<UserMenu::ReviewablesList/>`);
await render(<template><ReviewablesList /></template>);
assert
.dom(".panel-body-bottom .show-all")
.hasAttribute(
@ -22,7 +22,7 @@ module(
});
test("renders a list of reviewables", async function (assert) {
await render(hbs`<UserMenu::ReviewablesList/>`);
await render(<template><ReviewablesList /></template>);
const reviewables = queryAll("ul li");
assert.strictEqual(reviewables.length, 8);
});

View File

@ -1,8 +1,9 @@
import { render, triggerEvent } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import UserStatusMessage from "discourse/components/user-status-message";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { fakeTime } from "discourse/tests/helpers/qunit-helpers";
import DTooltips from "float-kit/components/d-tooltips";
module("Integration | Component | user-status-message", function (hooks) {
setupRenderingTest(hooks);
@ -19,16 +20,22 @@ module("Integration | Component | user-status-message", function (hooks) {
});
test("it renders user status emoji", async function (assert) {
await render(hbs`<UserStatusMessage @status={{this.status}} />`);
const self = this;
await render(
<template><UserStatusMessage @status={{self.status}} /></template>
);
assert.dom("img.emoji[alt='tooth']").exists("the status emoji is shown");
});
test("it renders status description if enabled", async function (assert) {
await render(hbs`
<UserStatusMessage
@status={{this.status}}
@showDescription={{true}} />
`);
const self = this;
await render(
<template>
<UserStatusMessage @status={{self.status}} @showDescription={{true}} />
</template>
);
assert
.dom('[data-trigger][data-identifier="user-status-message-tooltip"]')
@ -36,6 +43,8 @@ module("Integration | Component | user-status-message", function (hooks) {
});
test("it shows the until TIME on the tooltip if status will expire today", async function (assert) {
const self = this;
this.clock = fakeTime(
"2100-02-01T08:00:00.000Z",
this.currentUser.user_option.timezone,
@ -44,7 +53,9 @@ module("Integration | Component | user-status-message", function (hooks) {
this.status.ends_at = "2100-02-01T12:30:00.000Z";
await render(
hbs`<UserStatusMessage @status={{this.status}} /><DTooltips />`
<template>
<UserStatusMessage @status={{self.status}} /><DTooltips />
</template>
);
await triggerEvent(".user-status-message", "pointermove");
@ -54,6 +65,8 @@ module("Integration | Component | user-status-message", function (hooks) {
});
test("it shows the until DATE on the tooltip if status will expire tomorrow", async function (assert) {
const self = this;
this.clock = fakeTime(
"2100-02-01T08:00:00.000Z",
this.currentUser.user_option.timezone,
@ -62,7 +75,9 @@ module("Integration | Component | user-status-message", function (hooks) {
this.status.ends_at = "2100-02-02T12:30:00.000Z";
await render(
hbs`<UserStatusMessage @status={{this.status}} /><DTooltips />`
<template>
<UserStatusMessage @status={{self.status}} /><DTooltips />
</template>
);
await triggerEvent(".user-status-message", "pointermove");
@ -72,6 +87,8 @@ module("Integration | Component | user-status-message", function (hooks) {
});
test("it doesn't show until datetime on the tooltip if status doesn't have expiration date", async function (assert) {
const self = this;
this.clock = fakeTime(
"2100-02-01T08:00:00.000Z",
this.currentUser.user_option.timezone,
@ -80,7 +97,9 @@ module("Integration | Component | user-status-message", function (hooks) {
this.status.ends_at = null;
await render(
hbs`<UserStatusMessage @status={{this.status}} /><DTooltips />`
<template>
<UserStatusMessage @status={{self.status}} /><DTooltips />
</template>
);
await triggerEvent(".user-status-message", "pointermove");
@ -92,8 +111,12 @@ module("Integration | Component | user-status-message", function (hooks) {
});
test("it shows tooltip by default", async function (assert) {
const self = this;
await render(
hbs`<UserStatusMessage @status={{this.status}} /><DTooltips />`
<template>
<UserStatusMessage @status={{self.status}} /><DTooltips />
</template>
);
await triggerEvent(".user-status-message", "pointermove");
@ -103,10 +126,14 @@ module("Integration | Component | user-status-message", function (hooks) {
});
test("doesn't blow up with an anonymous user", async function (assert) {
const self = this;
this.owner.unregister("service:current-user");
this.status.ends_at = "2100-02-02T12:30:00.000Z";
await render(hbs`<UserStatusMessage @status={{this.status}} />`);
await render(
<template><UserStatusMessage @status={{self.status}} /></template>
);
assert
.dom('[data-trigger][data-identifier="user-status-message-tooltip"]')
@ -114,10 +141,14 @@ module("Integration | Component | user-status-message", function (hooks) {
});
test("accepts a custom css class", async function (assert) {
const self = this;
this.set("status", { emoji: "tooth", description: "off to dentist" });
await render(
hbs`<UserStatusMessage @status={{this.status}} class="foo" />`
<template>
<UserStatusMessage @status={{self.status}} class="foo" />
</template>
);
assert

View File

@ -1,12 +1,14 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import MountWidget from "discourse/components/mount-widget";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | Widget | actions-summary", function (hooks) {
setupRenderingTest(hooks);
test("post deleted", async function (assert) {
const self = this;
this.set("args", {
deleted_at: "2016-01-01",
deletedByUsername: "eviltrout",
@ -14,7 +16,9 @@ module("Integration | Component | Widget | actions-summary", function (hooks) {
});
await render(
hbs`<MountWidget @widget="actions-summary" @args={{this.args}} />`
<template>
<MountWidget @widget="actions-summary" @args={{self.args}} />
</template>
);
assert.dom(".post-action .d-icon-trash-can").exists("has the deleted icon");

View File

@ -1,12 +1,14 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import MountWidget from "discourse/components/mount-widget";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | Widget | avatar-flair", function (hooks) {
setupRenderingTest(hooks);
test("avatar flair with an icon", async function (assert) {
const self = this;
this.set("args", {
flair_url: "bars",
flair_bg_color: "CC0000",
@ -14,7 +16,9 @@ module("Integration | Component | Widget | avatar-flair", function (hooks) {
});
await render(
hbs`<MountWidget @widget="avatar-flair" @args={{this.args}} />`
<template>
<MountWidget @widget="avatar-flair" @args={{self.args}} />
</template>
);
assert.dom(".avatar-flair").exists("has the tag");
@ -26,12 +30,16 @@ module("Integration | Component | Widget | avatar-flair", function (hooks) {
});
test("avatar flair with an image", async function (assert) {
const self = this;
this.set("args", {
flair_url: "/images/avatar.png",
});
await render(
hbs`<MountWidget @widget="avatar-flair" @args={{this.args}} />`
<template>
<MountWidget @widget="avatar-flair" @args={{self.args}} />
</template>
);
assert.dom(".avatar-flair").exists("has the tag");

View File

@ -1,24 +1,32 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import MountWidget from "discourse/components/mount-widget";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | Widget | button", function (hooks) {
setupRenderingTest(hooks);
test("icon only button", async function (assert) {
const self = this;
this.set("args", { icon: "far-face-smile" });
await render(hbs`<MountWidget @widget="button" @args={{this.args}} />`);
await render(
<template><MountWidget @widget="button" @args={{self.args}} /></template>
);
assert.dom("button.btn.btn-icon.no-text").exists("has all the classes");
assert.dom("button .d-icon.d-icon-far-face-smile").exists("has the icon");
});
test("icon and text button", async function (assert) {
const self = this;
this.set("args", { icon: "plus", label: "topic.create" });
await render(hbs`<MountWidget @widget="button" @args={{this.args}} />`);
await render(
<template><MountWidget @widget="button" @args={{self.args}} /></template>
);
assert.dom("button.btn.btn-icon-text").exists("has all the classes");
assert.dom("button .d-icon.d-icon-plus").exists("has the icon");
@ -26,9 +34,13 @@ module("Integration | Component | Widget | button", function (hooks) {
});
test("emoji and text button", async function (assert) {
const self = this;
this.set("args", { emoji: "mega", label: "topic.create" });
await render(hbs`<MountWidget @widget="button" @args={{this.args}} />`);
await render(
<template><MountWidget @widget="button" @args={{self.args}} /></template>
);
assert.dom("button.widget-button").exists("renders the widget");
assert.dom("button img.emoji").exists("it renders the emoji");
@ -36,34 +48,50 @@ module("Integration | Component | Widget | button", function (hooks) {
});
test("text only button", async function (assert) {
const self = this;
this.set("args", { label: "topic.create" });
await render(hbs`<MountWidget @widget="button" @args={{this.args}} />`);
await render(
<template><MountWidget @widget="button" @args={{self.args}} /></template>
);
assert.dom("button.btn.btn-text").exists("has all the classes");
assert.dom("button span.d-button-label").exists("has the label");
});
test("translatedLabel", async function (assert) {
const self = this;
this.set("args", { translatedLabel: "foo bar" });
await render(hbs`<MountWidget @widget="button" @args={{this.args}} />`);
await render(
<template><MountWidget @widget="button" @args={{self.args}} /></template>
);
assert.dom("button span.d-button-label").hasText("foo bar");
});
test("translatedTitle", async function (assert) {
const self = this;
this.set("args", { label: "topic.create", translatedTitle: "foo bar" });
await render(hbs`<MountWidget @widget="button" @args={{this.args}} />`);
await render(
<template><MountWidget @widget="button" @args={{self.args}} /></template>
);
assert.dom("button").hasAttribute("title", "foo bar");
});
test("translatedLabel skips no-text class in icon", async function (assert) {
const self = this;
this.set("args", { icon: "plus", translatedLabel: "foo bar" });
await render(hbs`<MountWidget @widget="button" @args={{this.args}} />`);
await render(
<template><MountWidget @widget="button" @args={{self.args}} /></template>
);
assert
.dom("button.btn.btn-icon-text")

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import MountWidget from "discourse/components/mount-widget";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import DecoratorHelper from "discourse/widgets/decorator-helper";
import PostCooked from "discourse/widgets/post-cooked";
@ -10,6 +10,8 @@ module("Integration | Component | Widget | post-cooked", function (hooks) {
setupRenderingTest(hooks);
test("quotes with no username and no valid topic", async function (assert) {
const self = this;
this.set("args", {
cooked: `<aside class=\"quote no-group quote-post-not-found\" data-post=\"1\" data-topic=\"123456\">\n<blockquote>\n<p>abcd</p>\n</blockquote>\n</aside>\n<p>Testing the issue</p>`,
});
@ -23,7 +25,9 @@ module("Integration | Component | Widget | post-cooked", function (hooks) {
});
await render(
hbs`<MountWidget @widget="test-widget" @args={{this.args}} />`
<template>
<MountWidget @widget="test-widget" @args={{self.args}} />
</template>
);
assert.dom("blockquote").hasText("abcd");

View File

@ -1,12 +1,14 @@
import { click, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import MountWidget from "discourse/components/mount-widget";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | Widget | post-links", function (hooks) {
setupRenderingTest(hooks);
test("duplicate links", async function (assert) {
const self = this;
this.set("args", {
id: 2,
links: [
@ -23,7 +25,11 @@ module("Integration | Component | Widget | post-links", function (hooks) {
],
});
await render(hbs`<MountWidget @widget="post-links" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="post-links" @args={{self.args}} />
</template>
);
assert
.dom(".post-links a.track-link")
@ -31,6 +37,8 @@ module("Integration | Component | Widget | post-links", function (hooks) {
});
test("collapsed links", async function (assert) {
const self = this;
this.set("args", {
id: 1,
links: [
@ -72,7 +80,11 @@ module("Integration | Component | Widget | post-links", function (hooks) {
],
});
await render(hbs`<MountWidget @widget="post-links" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="post-links" @args={{self.args}} />
</template>
);
assert.dom(".expand-links").exists({ count: 1 }, "collapsed by default");

View File

@ -1,7 +1,7 @@
import { click, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import { h } from "virtual-dom";
import MountWidget from "discourse/components/mount-widget";
import { withSilencedDeprecations } from "discourse/lib/deprecated";
import { withPluginApi } from "discourse/lib/plugin-api";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
@ -16,6 +16,8 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
test("add extra button", async function (assert) {
const self = this;
this.set("args", {});
withPluginApi("0.14.0", (api) => {
withSilencedDeprecations("discourse.post-menu-widget-overrides", () => {
@ -31,8 +33,11 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
});
await render(hbs`
<MountWidget @widget="post-menu" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="post-menu" @args={{self.args}} />
</template>
);
assert
.dom(".actions .extra-buttons .hot-coffee")
@ -40,6 +45,8 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
test("add extra button with feedback", async function (assert) {
const self = this;
this.set("args", {});
let testPost = null;
@ -62,10 +69,13 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
});
await render(hbs`
<article data-post-id="123">
<MountWidget @widget="post-menu" @args={{this.args}} />
</article>`);
await render(
<template>
<article data-post-id="123">
<MountWidget @widget="post-menu" @args={{self.args}} />
</article>
</template>
);
await click(".hot-coffee");
@ -78,6 +88,8 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
test("removes button based on callback", async function (assert) {
const self = this;
this.set("args", { canCreatePost: true, canRemoveReply: true });
withPluginApi("0.14.0", (api) => {
@ -88,13 +100,18 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
});
await render(hbs`
<MountWidget @widget="post-menu" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="post-menu" @args={{self.args}} />
</template>
);
assert.dom(".actions .reply").doesNotExist("removes reply button");
});
test("does not remove button", async function (assert) {
const self = this;
this.set("args", { canCreatePost: true, canRemoveReply: false });
withPluginApi("0.14.0", (api) => {
@ -105,13 +122,18 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
});
await render(hbs`
<MountWidget @widget="post-menu" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="post-menu" @args={{self.args}} />
</template>
);
assert.dom(".actions .reply").exists("does not remove reply button");
});
test("removes button", async function (assert) {
const self = this;
this.set("args", { canCreatePost: true });
withPluginApi("0.14.0", (api) => {
@ -120,13 +142,18 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
});
await render(hbs`
<MountWidget @widget="post-menu" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="post-menu" @args={{self.args}} />
</template>
);
assert.dom(".actions .reply").doesNotExist("removes reply button");
});
test("removes button when any callback evaluates to true", async function (assert) {
const self = this;
this.set("args", {});
withPluginApi("0.14.0", (api) => {
@ -136,8 +163,11 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
});
await render(hbs`
<MountWidget @widget="post-menu" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="post-menu" @args={{self.args}} />
</template>
);
assert.dom(".actions .reply").doesNotExist("removes reply button");
});
@ -149,6 +179,8 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
test("buttons are replaced when shouldRender is true", async function (assert) {
const self = this;
this.set("args", { id: 1, canCreatePost: true });
withPluginApi("0.14.0", (api) => {
@ -163,8 +195,11 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
});
await render(hbs`
<MountWidget @widget="post-menu" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="post-menu" @args={{self.args}} />
</template>
);
assert.dom("h1.post-menu-replacement").exists("replacement is rendered");
assert
@ -173,6 +208,8 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
test("buttons are not replaced when shouldRender is false", async function (assert) {
const self = this;
this.set("args", { id: 1, canCreatePost: true, canRemoveReply: false });
withPluginApi("0.14.0", (api) => {
@ -187,8 +224,11 @@ module("Integration | Component | Widget | post-menu", function (hooks) {
});
});
await render(hbs`
<MountWidget @widget="post-menu" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="post-menu" @args={{self.args}} />
</template>
);
assert
.dom("h1.post-menu-replacement")

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import MountWidget from "discourse/components/mount-widget";
import { withPluginApi } from "discourse/lib/plugin-api";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { resetPostSmallActionClassesCallbacks } from "discourse/widgets/post-small-action";
@ -11,10 +11,14 @@ module(
setupRenderingTest(hooks);
test("does not have delete/edit/recover buttons by default", async function (assert) {
const self = this;
this.set("args", { id: 123 });
await render(
hbs`<MountWidget @widget="post-small-action" @args={{this.args}} />`
<template>
<MountWidget @widget="post-small-action" @args={{self.args}} />
</template>
);
assert.dom(".small-action-desc .small-action-delete").doesNotExist();
@ -23,10 +27,14 @@ module(
});
test("shows edit button if canEdit", async function (assert) {
const self = this;
this.set("args", { id: 123, canEdit: true });
await render(
hbs`<MountWidget @widget="post-small-action" @args={{this.args}} />`
<template>
<MountWidget @widget="post-small-action" @args={{self.args}} />
</template>
);
assert
@ -35,10 +43,14 @@ module(
});
test("uses custom widget if actionDescriptionWidget", async function (assert) {
const self = this;
this.set("args", { id: 123, actionDescriptionWidget: "button" });
await render(
hbs`<MountWidget @widget="post-small-action" @args={{this.args}} />`
<template>
<MountWidget @widget="post-small-action" @args={{self.args}} />
</template>
);
assert
@ -47,10 +59,14 @@ module(
});
test("does not show edit button if canRecover even if canEdit", async function (assert) {
const self = this;
this.set("args", { id: 123, canEdit: true, canRecover: true });
await render(
hbs`<MountWidget @widget="post-small-action" @args={{this.args}} />`
<template>
<MountWidget @widget="post-small-action" @args={{self.args}} />
</template>
);
assert
@ -62,10 +78,14 @@ module(
});
test("shows delete button if canDelete", async function (assert) {
const self = this;
this.set("args", { id: 123, canDelete: true });
await render(
hbs`<MountWidget @widget="post-small-action" @args={{this.args}} />`
<template>
<MountWidget @widget="post-small-action" @args={{self.args}} />
</template>
);
assert
@ -74,10 +94,14 @@ module(
});
test("shows undo button if canRecover", async function (assert) {
const self = this;
this.set("args", { id: 123, canRecover: true });
await render(
hbs`<MountWidget @widget="post-small-action" @args={{this.args}} />`
<template>
<MountWidget @widget="post-small-action" @args={{self.args}} />
</template>
);
assert
@ -87,6 +111,8 @@ module(
test("`addPostSmallActionClassesCallback` plugin api", async function (assert) {
try {
const self = this;
withPluginApi("1.6.0", (api) => {
api.addPostSmallActionClassesCallback((postAttrs) => {
if (postAttrs.canRecover) {
@ -98,7 +124,9 @@ module(
this.set("args", { id: 123, canRecover: false });
await render(
hbs`<MountWidget @widget="post-small-action" @args={{this.args}} />`
<template>
<MountWidget @widget="post-small-action" @args={{self.args}} />
</template>
);
assert
@ -110,7 +138,9 @@ module(
this.set("args", { id: 123, canRecover: true });
await render(
hbs`<MountWidget @widget="post-small-action" @args={{this.args}} />`
<template>
<MountWidget @widget="post-small-action" @args={{self.args}} />
</template>
);
assert

View File

@ -1,11 +1,12 @@
import EmberObject from "@ember/object";
import { getOwner } from "@ember/owner";
import { click, render, triggerEvent } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import MountWidget from "discourse/components/mount-widget";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { count, queryAll } from "discourse/tests/helpers/qunit-helpers";
import { i18n } from "discourse-i18n";
import DMenus from "float-kit/components/d-menus";
module(
"Integration | Component | Widget | post with glimmer-post-menu",
@ -31,6 +32,8 @@ module(
});
test("basic elements", async function (assert) {
const self = this;
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", {
id: 123,
@ -39,16 +42,23 @@ module(
this.set("args", { shareUrl: "/example", post_number: 1, topic });
await render(hbs`
<MountWidget @widget="post"
@model={{this.post}}
@args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".names").exists("includes poster name");
assert.dom("a.post-date").exists("includes post date");
});
test("post - links", async function (assert) {
const self = this;
this.set("args", {
cooked:
"<a href='http://link1.example.com/'>first link</a> and <a href='http://link2.example.com/?some=query'>second link</a>",
@ -59,8 +69,13 @@ module(
});
await render(
hbs`
<MountWidget @widget="post-contents" @model={{this.post}} @args={{this.args}} />`
<template>
<MountWidget
@widget="post-contents"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.strictEqual(
@ -74,6 +89,8 @@ module(
});
test("post - onebox links", async function (assert) {
const self = this;
this.set("args", {
cooked: `
<p><a href="https://example.com">Other URL</a></p>
@ -94,8 +111,13 @@ module(
});
await render(
hbs`
<MountWidget @widget="post-contents" @model={{this.post}} @args={{this.args}} />`
<template>
<MountWidget
@widget="post-contents"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.strictEqual(
@ -111,13 +133,21 @@ module(
});
test("wiki", async function (assert) {
const self = this;
this.set("args", { wiki: true, version: 2, canViewEditHistory: true });
this.set("showHistory", () => (this.historyShown = true));
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}}
@showHistory={{this.showHistory}} />
`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@showHistory={{self.showHistory}}
/>
</template>
);
await click(".post-info .wiki");
assert.true(
@ -127,25 +157,41 @@ module(
});
test("wiki without revision", async function (assert) {
const self = this;
this.set("args", { wiki: true, version: 1, canViewEditHistory: true });
this.set("editPost", () => (this.editPostCalled = true));
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}}
@editPost={{this.editPost}} />
`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@editPost={{self.editPost}}
/>
</template>
);
await click(".post-info .wiki");
assert.true(this.editPostCalled, "clicking wiki icon edits the post");
});
test("via-email", async function (assert) {
const self = this;
this.set("args", { via_email: true, canViewRawEmail: true });
this.set("showRawEmail", () => (this.rawEmailShown = true));
await render(
hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} @showRawEmail={{this.showRawEmail}} />`
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@showRawEmail={{self.showRawEmail}}
/>
</template>
);
await click(".post-info.via-email");
@ -156,13 +202,21 @@ module(
});
test("via-email without permission", async function (assert) {
const self = this;
this.rawEmailShown = false;
this.set("args", { via_email: true, canViewRawEmail: false });
this.set("showRawEmail", () => (this.rawEmailShown = true));
await render(
hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} @showRawEmail={{this.showRawEmail}} />`
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@showRawEmail={{self.showRawEmail}}
/>
</template>
);
await click(".post-info.via-email");
@ -173,12 +227,20 @@ module(
});
test("history", async function (assert) {
const self = this;
this.set("args", { version: 3, canViewEditHistory: true });
this.set("showHistory", () => (this.historyShown = true));
await render(
hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} @showHistory={{this.showHistory}} />`
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@showHistory={{self.showHistory}}
/>
</template>
);
await click(".post-info.edits button");
@ -186,13 +248,21 @@ module(
});
test("history without view permission", async function (assert) {
const self = this;
this.historyShown = false;
this.set("args", { version: 3, canViewEditHistory: false });
this.set("showHistory", () => (this.historyShown = true));
await render(
hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} @showHistory={{this.showHistory}} />`
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@showHistory={{self.showHistory}}
/>
</template>
);
await click(".post-info.edits");
@ -203,62 +273,109 @@ module(
});
test("whisper", async function (assert) {
const self = this;
this.set("args", { isWhisper: true });
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.strictEqual(count(".topic-post.whisper"), 1);
assert.strictEqual(count(".post-info.whisper"), 1);
});
test(`read indicator`, async function (assert) {
const self = this;
this.set("args", { read: true });
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".read-state.read").exists();
});
test(`unread indicator`, async function (assert) {
const self = this;
this.set("args", { read: false });
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".read-state").exists();
});
test("reply directly above (suppressed)", async function (assert) {
const self = this;
this.set("args", {
replyToUsername: "eviltrout",
replyToAvatarTemplate: "/images/avatar.png",
replyDirectlyAbove: true,
});
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom("a.reply-to-tab").doesNotExist("hides the tab");
assert.dom(".avoid-tab").doesNotExist("doesn't have the avoid tab class");
});
test("reply a few posts above (suppressed)", async function (assert) {
const self = this;
this.set("args", {
replyToUsername: "eviltrout",
replyToAvatarTemplate: "/images/avatar.png",
replyDirectlyAbove: false,
});
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom("a.reply-to-tab").exists("shows the tab");
assert.strictEqual(count(".avoid-tab"), 1, "has the avoid tab class");
});
test("reply directly above", async function (assert) {
const self = this;
this.set("args", {
replyToUsername: "eviltrout",
replyToAvatarTemplate: "/images/avatar.png",
@ -266,8 +383,15 @@ module(
});
this.siteSettings.suppress_reply_directly_above = false;
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.strictEqual(count(".avoid-tab"), 1, "has the avoid tab class");
await click("a.reply-to-tab");
@ -276,12 +400,20 @@ module(
});
test("cooked content hidden", async function (assert) {
const self = this;
this.set("args", { cooked_hidden: true, canSeeHiddenPost: true });
this.set("expandHidden", () => (this.unhidden = true));
await render(
hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} @expandHidden={{this.expandHidden}} />`
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@expandHidden={{self.expandHidden}}
/>
</template>
);
await click(".topic-body .expand-hidden");
@ -289,12 +421,20 @@ module(
});
test(`cooked content hidden - can't view hidden post`, async function (assert) {
const self = this;
this.set("args", { cooked_hidden: true, canSeeHiddenPost: false });
this.set("expandHidden", () => (this.unhidden = true));
await render(
hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} @expandHidden={{this.expandHidden}} />`
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@expandHidden={{self.expandHidden}}
/>
</template>
);
assert
@ -303,11 +443,18 @@ module(
});
test("expand first post", async function (assert) {
const self = this;
this.set("args", { expandablePost: true });
await render(
hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
await click(".topic-body .expand-post");
@ -315,21 +462,37 @@ module(
});
test("can't show admin menu when you can't manage", async function (assert) {
const self = this;
this.set("args", { canManage: false });
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".post-menu-area .show-post-admin-menu").doesNotExist();
});
test("show admin menu", async function (assert) {
const self = this;
this.currentUser.admin = true;
await render(
hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />
<DMenus/>`
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
<DMenus />
</template>
);
assert
@ -346,6 +509,8 @@ module(
});
test("permanently delete topic", async function (assert) {
const self = this;
this.currentUser.set("admin", true);
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", {
@ -364,10 +529,15 @@ module(
this.set("permanentlyDeletePost", () => (this.deleted = true));
await render(
hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}}
@permanentlyDeletePost={{this.permanentlyDeletePost}} />
<DMenus/>`
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@permanentlyDeletePost={{self.permanentlyDeletePost}}
/>
<DMenus />
</template>
);
await click(".post-menu-area .show-post-admin-menu");
@ -381,6 +551,8 @@ module(
});
test("permanently delete post", async function (assert) {
const self = this;
this.currentUser.set("admin", true);
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", {
@ -398,11 +570,17 @@ module(
this.set("post", post);
this.set("permanentlyDeletePost", () => (this.deleted = true));
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}}
@permanentlyDeletePost={{this.permanentlyDeletePost}} />
<DMenus/>
`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@permanentlyDeletePost={{self.permanentlyDeletePost}}
/>
<DMenus />
</template>
);
await click(".post-menu-area .show-post-admin-menu");
@ -416,6 +594,8 @@ module(
});
test("toggle moderator post", async function (assert) {
const self = this;
this.currentUser.set("moderator", true);
const store = getOwner(this).lookup("service:store");
@ -434,10 +614,17 @@ module(
this.set("post", post);
this.set("togglePostType", () => (this.toggled = true));
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}}
@togglePostType={{this.togglePostType}} />
<DMenus/>`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@togglePostType={{self.togglePostType}}
/>
<DMenus />
</template>
);
await click(".post-menu-area .show-post-admin-menu");
await click(
@ -451,6 +638,8 @@ module(
});
test("rebake post", async function (assert) {
const self = this;
this.currentUser.moderator = true;
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", { id: 123 });
@ -464,10 +653,17 @@ module(
this.set("post", post);
this.set("rebakePost", () => (this.baked = true));
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}}
@rebakePost={{this.rebakePost}} />
<DMenus/>`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@rebakePost={{self.rebakePost}}
/>
<DMenus />
</template>
);
await click(".post-menu-area .show-post-admin-menu");
await click(
@ -480,6 +676,8 @@ module(
});
test("unhide post", async function (assert) {
const self = this;
let unhidden;
this.currentUser.admin = true;
@ -487,11 +685,17 @@ module(
this.set("args", { canManage: true });
this.set("unhidePost", () => (unhidden = true));
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}}
@unhidePost={{this.unhidePost}} />
<DMenus/>
`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@unhidePost={{self.unhidePost}}
/>
<DMenus />
</template>
);
await click(".post-menu-area .show-post-admin-menu");
@ -507,6 +711,8 @@ module(
});
test("change owner", async function (assert) {
const self = this;
this.currentUser.admin = true;
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", { id: 123 });
@ -521,11 +727,17 @@ module(
this.set("post", post);
this.set("changePostOwner", () => (this.owned = true));
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}}
@changePostOwner={{this.changePostOwner}} />
<DMenus/>
`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
@changePostOwner={{self.changePostOwner}}
/>
<DMenus />
</template>
);
await click(".post-menu-area .show-post-admin-menu");
await click(
@ -538,17 +750,28 @@ module(
});
test("shows the topic map when setting the 'topicMap' attribute", async function (assert) {
const self = this;
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", { id: 123 });
this.set("args", { topic, post_number: 1, topicMap: true });
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".topic-map").exists();
});
test("shows the topic map when no replies", async function (assert) {
const self = this;
this.siteSettings.show_topic_map_in_topics_without_replies = true;
const store = getOwner(this).lookup("service:store");
@ -558,13 +781,22 @@ module(
});
this.set("args", { topic, post_number: 1 });
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".topic-map").exists();
});
test("topic map - few participants", async function (assert) {
const self = this;
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", {
id: 123,
@ -581,13 +813,22 @@ module(
post_number: 1,
});
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".topic-map__users-trigger").doesNotExist();
assert.dom(".topic-map__users-list a.poster").exists({ count: 2 });
});
test("topic map - participants", async function (assert) {
const self = this;
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", {
id: 123,
@ -610,8 +851,15 @@ module(
post_number: 1,
});
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".topic-map__users-list a.poster").exists({ count: 5 });
await click(".topic-map__users-trigger");
@ -621,6 +869,8 @@ module(
});
test("topic map - links", async function (assert) {
const self = this;
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", {
id: 123,
@ -637,8 +887,15 @@ module(
]);
this.set("args", { topic, post_number: 1 });
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".topic-map").exists({ count: 1 });
assert.dom(".topic-map__links-content").doesNotExist();
@ -650,6 +907,8 @@ module(
});
test("topic map - no top reply summary", async function (assert) {
const self = this;
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", {
id: 123,
@ -658,14 +917,23 @@ module(
});
this.set("args", { topic, post_number: 1 });
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".topic-map").exists();
assert.dom(".summarization-button .top-replies").doesNotExist();
});
test("topic map - has top replies summary", async function (assert) {
const self = this;
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", {
id: 123,
@ -675,13 +943,22 @@ module(
});
this.set("args", { topic, post_number: 1 });
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".summarization-button .top-replies").exists({ count: 1 });
});
test("pm map", async function (assert) {
const self = this;
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", {
id: 123,
@ -695,14 +972,23 @@ module(
post_number: 1,
});
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".topic-map__private-message-map").exists({ count: 1 });
assert.dom(".topic-map__private-message-map .user").exists({ count: 1 });
});
test("post notice - with username", async function (assert) {
const self = this;
const twoDaysAgo = new Date();
twoDaysAgo.setDate(twoDaysAgo.getDate() - 2);
this.siteSettings.display_name_on_posts = false;
@ -718,8 +1004,15 @@ module(
},
});
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".post-notice.returning-user:not(.old)").hasText(
i18n("post.notice.returning_user", {
@ -730,6 +1023,8 @@ module(
});
test("post notice - with name", async function (assert) {
const self = this;
this.siteSettings.display_name_on_posts = true;
this.siteSettings.prioritize_username_in_ux = false;
this.siteSettings.old_post_notice_days = 14;
@ -740,8 +1035,15 @@ module(
notice: { type: "new_user" },
});
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert
.dom(".post-notice.old.new-user")
@ -751,13 +1053,22 @@ module(
});
test("show group request in post", async function (assert) {
const self = this;
this.set("args", {
username: "foo",
requestedGroupName: "testGroup",
});
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".group-request a").hasText(i18n("groups.requests.handle"));
assert
@ -766,6 +1077,8 @@ module(
});
test("shows user status if enabled in site settings", async function (assert) {
const self = this;
this.siteSettings.enable_user_status = true;
const status = {
emoji: "tooth",
@ -775,13 +1088,22 @@ module(
const user = store.createRecord("user", { status });
this.set("args", { user });
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".user-status-message").exists();
});
test("doesn't show user status if disabled in site settings", async function (assert) {
const self = this;
this.siteSettings.enable_user_status = false;
const status = {
emoji: "tooth",
@ -791,25 +1113,50 @@ module(
const user = store.createRecord("user", { status });
this.set("args", { user });
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".user-status-message").doesNotExist();
});
test("more actions button is displayed when multiple hidden items are configured", async function (assert) {
const self = this;
this.siteSettings.post_menu_hidden_items = "bookmark|edit|copyLink";
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".show-more-actions").exists();
});
test("hidden menu expands automatically when only one hidden item is configured", async function (assert) {
const self = this;
this.siteSettings.post_menu_hidden_items = "bookmark|edit";
await render(hbs`
<MountWidget @widget="post" @model={{this.post}} @args={{this.args}} />`);
await render(
<template>
<MountWidget
@widget="post"
@model={{self.post}}
@args={{self.args}}
/>
</template>
);
assert.dom(".show-more-actions").doesNotExist();
});
}

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import MountWidget from "discourse/components/mount-widget";
import Badge from "discourse/models/badge";
import User from "discourse/models/user";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
@ -9,6 +9,8 @@ module("Integration | Component | Widget | poster-name", function (hooks) {
setupRenderingTest(hooks);
test("basic rendering", async function (assert) {
const self = this;
this.set("args", {
username: "eviltrout",
usernameUrl: "/u/eviltrout",
@ -17,7 +19,9 @@ module("Integration | Component | Widget | poster-name", function (hooks) {
});
await render(
hbs`<MountWidget @widget="poster-name" @args={{this.args}} />`
<template>
<MountWidget @widget="poster-name" @args={{self.args}} />
</template>
);
assert.dom(".names").exists();
@ -28,6 +32,8 @@ module("Integration | Component | Widget | poster-name", function (hooks) {
});
test("extra classes and glyphs", async function (assert) {
const self = this;
this.set("args", {
username: "eviltrout",
usernameUrl: "/u/eviltrout",
@ -39,7 +45,9 @@ module("Integration | Component | Widget | poster-name", function (hooks) {
});
await render(
hbs`<MountWidget @widget="poster-name" @args={{this.args}} />`
<template>
<MountWidget @widget="poster-name" @args={{self.args}} />
</template>
);
assert.dom("span.staff").exists();
@ -51,29 +59,39 @@ module("Integration | Component | Widget | poster-name", function (hooks) {
});
test("disable display name on posts", async function (assert) {
const self = this;
this.siteSettings.display_name_on_posts = false;
this.set("args", { username: "eviltrout", name: "Robin Ward" });
await render(
hbs`<MountWidget @widget="poster-name" @args={{this.args}} />`
<template>
<MountWidget @widget="poster-name" @args={{self.args}} />
</template>
);
assert.dom(".full-name").doesNotExist();
});
test("doesn't render a name if it's similar to the username", async function (assert) {
const self = this;
this.siteSettings.prioritize_username_in_ux = true;
this.siteSettings.display_name_on_posts = true;
this.set("args", { username: "eviltrout", name: "evil-trout" });
await render(
hbs`<MountWidget @widget="poster-name" @args={{this.args}} />`
<template>
<MountWidget @widget="poster-name" @args={{self.args}} />
</template>
);
assert.dom(".second").doesNotExist();
});
test("renders badges that are passed in", async function (assert) {
const self = this;
this.set("args", {
username: "eviltrout",
usernameUrl: "/u/eviltrout",
@ -87,7 +105,9 @@ module("Integration | Component | Widget | poster-name", function (hooks) {
});
await render(
hbs`<MountWidget @widget="poster-name" @args={{this.args}} />`
<template>
<MountWidget @widget="poster-name" @args={{self.args}} />
</template>
);
// Check that the custom CSS classes are set

View File

@ -1,12 +1,14 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import MountWidget from "discourse/components/mount-widget";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Component | Widget | small-user-list", function (hooks) {
setupRenderingTest(hooks);
test("renders avatars and support for unknown", async function (assert) {
const self = this;
this.set("args", {
users: [
{ id: 456, username: "eviltrout" },
@ -16,7 +18,9 @@ module("Integration | Component | Widget | small-user-list", function (hooks) {
});
await render(
hbs`<MountWidget @widget="small-user-list" @args={{this.args}} />`
<template>
<MountWidget @widget="small-user-list" @args={{self.args}} />
</template>
);
assert.dom('[data-user-card="eviltrout"]').exists({ count: 1 });

View File

@ -0,0 +1,553 @@
import { hash } from "@ember/helper";
import { click, render } from "@ember/test-helpers";
import { module, test } from "qunit";
import MountWidget from "discourse/components/mount-widget";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import I18n from "discourse-i18n";
const DEFAULT_CONTENT = {
content: [
{ id: 1, label: "foo" },
{ id: 2, translatedLabel: "FooBar" },
"separator",
{ id: 3, translatedLabel: "With icon", icon: "xmark" },
{ id: 4, html: "<b>baz</b>" },
{ id: 5, translatedLabel: "Disabled", disabled: true },
],
label: "foo",
};
module("Integration | Component | Widget | widget-dropdown", function (hooks) {
setupRenderingTest(hooks);
let _translations = I18n.translations;
hooks.afterEach(function () {
I18n.translations = _translations;
});
test("dropdown id", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
assert.dom("#my-dropdown").exists();
});
test("label", async function (assert) {
const self = this;
I18n.translations = { en: { js: { foo: "FooBaz" } } };
this.setProperties(DEFAULT_CONTENT);
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
assert.dom("#my-dropdown .widget-dropdown-header .label").hasText("FooBaz");
});
test("translatedLabel", async function (assert) {
const self = this;
I18n.translations = { en: { js: { foo: "FooBaz" } } };
this.setProperties(DEFAULT_CONTENT);
this.set("translatedLabel", "BazFoo");
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
assert.dom("#my-dropdown .widget-dropdown-header .label").hasText("BazFoo");
});
test("content", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
await click("#my-dropdown .widget-dropdown-header");
assert
.dom("#my-dropdown .widget-dropdown-item.item-1")
.hasAttribute("data-id", "1", "creates rows");
assert
.dom("#my-dropdown .widget-dropdown-item.item-2")
.hasAttribute("data-id", "2", "creates rows");
assert
.dom("#my-dropdown .widget-dropdown-item.item-3")
.hasAttribute("data-id", "3", "creates rows");
});
test("onChange action", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
this.set("onChange", (item) => assert.step(`${item.id}`));
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
label=self.label
content=self.content
onChange=self.onChange
}}
/>
</template>
);
await click("#my-dropdown .widget-dropdown-header");
await click("#my-dropdown .widget-dropdown-item.item-2");
assert.verifySteps(["2"], "calls the onChange actions");
});
test("can be opened and closed", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
assert.dom("#my-dropdown.closed").exists();
assert.dom("#my-dropdown .widget-dropdown-body").doesNotExist();
await click("#my-dropdown .widget-dropdown-header");
assert.dom("#my-dropdown .widget-dropdown-item.item-2").hasText("FooBar");
assert.dom("#my-dropdown.opened").exists();
assert.dom("#my-dropdown .widget-dropdown-body").exists();
await click("#my-dropdown .widget-dropdown-header");
assert.dom("#my-dropdown.closed").exists();
assert.dom("#my-dropdown .widget-dropdown-body").doesNotExist();
});
test("icon", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
this.set("icon", "xmark");
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
assert.dom("#my-dropdown .widget-dropdown-header .d-icon-xmark").exists();
});
test("class", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
this.set("class", "activated");
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
assert.dom("#my-dropdown.activated").exists();
});
test("content with translatedLabel", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
await click("#my-dropdown .widget-dropdown-header");
assert.dom("#my-dropdown .widget-dropdown-item.item-2").hasText("FooBar");
});
test("content with label", async function (assert) {
const self = this;
I18n.translations = { en: { js: { foo: "FooBaz" } } };
this.setProperties(DEFAULT_CONTENT);
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
await click("#my-dropdown .widget-dropdown-header");
assert.dom("#my-dropdown .widget-dropdown-item.item-1").hasText("FooBaz");
});
test("content with icon", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
await click("#my-dropdown .widget-dropdown-header");
assert
.dom("#my-dropdown .widget-dropdown-item.item-3 .d-icon-xmark")
.exists();
});
test("content with html", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
await click("#my-dropdown .widget-dropdown-header");
assert
.dom("#my-dropdown .widget-dropdown-item.item-4")
.hasHtml("<span><b>baz</b></span>");
});
test("separator", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
await click("#my-dropdown .widget-dropdown-header");
assert
.dom("#my-dropdown .widget-dropdown-item:nth-child(3)")
.hasClass("separator");
});
test("hides widget if no content", async function (assert) {
const self = this;
this.setProperties({ content: null, label: "foo" });
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
assert.dom("#my-dropdown .widget-dropdown-header").doesNotExist();
assert.dom("#my-dropdown .widget-dropdown-body").doesNotExist();
});
test("headerClass option", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
this.set("options", { headerClass: "btn-small and-text" });
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
assert.dom("#my-dropdown .widget-dropdown-header").hasClass("btn-small");
assert.dom("#my-dropdown .widget-dropdown-header").hasClass("and-text");
});
test("bodyClass option", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
this.set("options", { bodyClass: "gigantic and-yet-small" });
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
await click("#my-dropdown .widget-dropdown-header");
assert.dom("#my-dropdown .widget-dropdown-body").hasClass("gigantic");
assert.dom("#my-dropdown .widget-dropdown-body").hasClass("and-yet-small");
});
test("caret option", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
this.set("options", { caret: true });
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
assert
.dom("#my-dropdown .widget-dropdown-header .d-icon-caret-down")
.exists();
});
test("disabled widget", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
this.set("options", { disabled: true });
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
assert.dom("#my-dropdown.disabled").exists();
await click("#my-dropdown .widget-dropdown-header");
assert
.dom("#my-dropdown .widget-dropdown-item.item-1")
.doesNotExist("does not display options");
});
test("disabled item", async function (assert) {
const self = this;
this.setProperties(DEFAULT_CONTENT);
await render(
<template>
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=self.icon
label=self.label
class=self.class
translatedLabel=self.translatedLabel
content=self.content
options=self.options
}}
/>
</template>
);
await click("#my-dropdown .widget-dropdown-header");
assert.dom(".widget-dropdown-item.item-5.disabled").exists();
});
});

View File

@ -1,476 +0,0 @@
import { click, render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import I18n from "discourse-i18n";
const DEFAULT_CONTENT = {
content: [
{ id: 1, label: "foo" },
{ id: 2, translatedLabel: "FooBar" },
"separator",
{ id: 3, translatedLabel: "With icon", icon: "xmark" },
{ id: 4, html: "<b>baz</b>" },
{ id: 5, translatedLabel: "Disabled", disabled: true },
],
label: "foo",
};
module("Integration | Component | Widget | widget-dropdown", function (hooks) {
setupRenderingTest(hooks);
let _translations = I18n.translations;
hooks.afterEach(function () {
I18n.translations = _translations;
});
test("dropdown id", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
assert.dom("#my-dropdown").exists();
});
test("label", async function (assert) {
I18n.translations = { en: { js: { foo: "FooBaz" } } };
this.setProperties(DEFAULT_CONTENT);
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
assert.dom("#my-dropdown .widget-dropdown-header .label").hasText("FooBaz");
});
test("translatedLabel", async function (assert) {
I18n.translations = { en: { js: { foo: "FooBaz" } } };
this.setProperties(DEFAULT_CONTENT);
this.set("translatedLabel", "BazFoo");
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
assert.dom("#my-dropdown .widget-dropdown-header .label").hasText("BazFoo");
});
test("content", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
await click("#my-dropdown .widget-dropdown-header");
assert
.dom("#my-dropdown .widget-dropdown-item.item-1")
.hasAttribute("data-id", "1", "creates rows");
assert
.dom("#my-dropdown .widget-dropdown-item.item-2")
.hasAttribute("data-id", "2", "creates rows");
assert
.dom("#my-dropdown .widget-dropdown-item.item-3")
.hasAttribute("data-id", "3", "creates rows");
});
test("onChange action", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
this.set("onChange", (item) => assert.step(`${item.id}`));
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
label=this.label
content=this.content
onChange=this.onChange
}}
/>
`);
await click("#my-dropdown .widget-dropdown-header");
await click("#my-dropdown .widget-dropdown-item.item-2");
assert.verifySteps(["2"], "calls the onChange actions");
});
test("can be opened and closed", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
assert.dom("#my-dropdown.closed").exists();
assert.dom("#my-dropdown .widget-dropdown-body").doesNotExist();
await click("#my-dropdown .widget-dropdown-header");
assert.dom("#my-dropdown .widget-dropdown-item.item-2").hasText("FooBar");
assert.dom("#my-dropdown.opened").exists();
assert.dom("#my-dropdown .widget-dropdown-body").exists();
await click("#my-dropdown .widget-dropdown-header");
assert.dom("#my-dropdown.closed").exists();
assert.dom("#my-dropdown .widget-dropdown-body").doesNotExist();
});
test("icon", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
this.set("icon", "xmark");
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
assert.dom("#my-dropdown .widget-dropdown-header .d-icon-xmark").exists();
});
test("class", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
this.set("class", "activated");
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
assert.dom("#my-dropdown.activated").exists();
});
test("content with translatedLabel", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
await click("#my-dropdown .widget-dropdown-header");
assert.dom("#my-dropdown .widget-dropdown-item.item-2").hasText("FooBar");
});
test("content with label", async function (assert) {
I18n.translations = { en: { js: { foo: "FooBaz" } } };
this.setProperties(DEFAULT_CONTENT);
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
await click("#my-dropdown .widget-dropdown-header");
assert.dom("#my-dropdown .widget-dropdown-item.item-1").hasText("FooBaz");
});
test("content with icon", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
await click("#my-dropdown .widget-dropdown-header");
assert
.dom("#my-dropdown .widget-dropdown-item.item-3 .d-icon-xmark")
.exists();
});
test("content with html", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
await click("#my-dropdown .widget-dropdown-header");
assert
.dom("#my-dropdown .widget-dropdown-item.item-4")
.hasHtml("<span><b>baz</b></span>");
});
test("separator", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
await click("#my-dropdown .widget-dropdown-header");
assert
.dom("#my-dropdown .widget-dropdown-item:nth-child(3)")
.hasClass("separator");
});
test("hides widget if no content", async function (assert) {
this.setProperties({ content: null, label: "foo" });
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
assert.dom("#my-dropdown .widget-dropdown-header").doesNotExist();
assert.dom("#my-dropdown .widget-dropdown-body").doesNotExist();
});
test("headerClass option", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
this.set("options", { headerClass: "btn-small and-text" });
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
assert.dom("#my-dropdown .widget-dropdown-header").hasClass("btn-small");
assert.dom("#my-dropdown .widget-dropdown-header").hasClass("and-text");
});
test("bodyClass option", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
this.set("options", { bodyClass: "gigantic and-yet-small" });
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
await click("#my-dropdown .widget-dropdown-header");
assert.dom("#my-dropdown .widget-dropdown-body").hasClass("gigantic");
assert.dom("#my-dropdown .widget-dropdown-body").hasClass("and-yet-small");
});
test("caret option", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
this.set("options", { caret: true });
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
assert
.dom("#my-dropdown .widget-dropdown-header .d-icon-caret-down")
.exists();
});
test("disabled widget", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
this.set("options", { disabled: true });
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
assert.dom("#my-dropdown.disabled").exists();
await click("#my-dropdown .widget-dropdown-header");
assert
.dom("#my-dropdown .widget-dropdown-item.item-1")
.doesNotExist("does not display options");
});
test("disabled item", async function (assert) {
this.setProperties(DEFAULT_CONTENT);
await render(hbs`
<MountWidget
@widget="widget-dropdown"
@args={{hash
id="my-dropdown"
icon=this.icon
label=this.label
class=this.class
translatedLabel=this.translatedLabel
content=this.content
options=this.options
}}
/>
`);
await click("#my-dropdown .widget-dropdown-header");
assert.dom(".widget-dropdown-item.item-5.disabled").exists();
});
});

View File

@ -1,9 +1,9 @@
import { next } from "@ember/runloop";
import { click, render, settled } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import { Promise } from "rsvp";
import { h } from "virtual-dom";
import MountWidget from "discourse/components/mount-widget";
import { withPluginApi } from "discourse/lib/plugin-api";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import widgetHbs from "discourse/widgets/hbs-compiler";
@ -20,6 +20,8 @@ module("Integration | Component | Widget | base", function (hooks) {
});
test("widget attributes are passed in via args", async function (assert) {
const self = this;
createWidget("hello-test", {
tagName: "div.test",
template: widgetHbs`Hello {{attrs.name}}`,
@ -27,12 +29,18 @@ module("Integration | Component | Widget | base", function (hooks) {
this.set("args", { name: "Robin" });
await render(hbs`<MountWidget @widget="hello-test" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="hello-test" @args={{self.args}} />
</template>
);
assert.dom(".test").hasText("Hello Robin");
});
test("widget rerenders when args change", async function (assert) {
const self = this;
createWidget("hello-test", {
tagName: "div.test",
template: widgetHbs`Hello {{attrs.name}}`,
@ -40,7 +48,11 @@ module("Integration | Component | Widget | base", function (hooks) {
this.set("args", { name: "Robin" });
await render(hbs`<MountWidget @widget="hello-test" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="hello-test" @args={{self.args}} />
</template>
);
assert.dom(".test").hasText("Hello Robin");
@ -59,24 +71,32 @@ module("Integration | Component | Widget | base", function (hooks) {
},
});
await render(hbs`<MountWidget @widget="service-test" />`);
await render(<template><MountWidget @widget="service-test" /></template>);
assert.dom(".base-url-test").hasText("/");
});
test("hbs template - no tagName", async function (assert) {
const self = this;
createWidget("hbs-test", {
template: widgetHbs`<div class='test'>Hello {{attrs.name}}</div>`,
});
this.set("args", { name: "Robin" });
await render(hbs`<MountWidget @widget="hbs-test" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="hbs-test" @args={{self.args}} />
</template>
);
assert.dom("div.test").hasText("Hello Robin");
});
test("hbs template - with tagName", async function (assert) {
const self = this;
createWidget("hbs-test", {
tagName: "div.test",
template: widgetHbs`Hello {{attrs.name}}`,
@ -84,22 +104,34 @@ module("Integration | Component | Widget | base", function (hooks) {
this.set("args", { name: "Robin" });
await render(hbs`<MountWidget @widget="hbs-test" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="hbs-test" @args={{self.args}} />
</template>
);
assert.dom("div.test").hasText("Hello Robin");
});
test("hbs template - with data attributes", async function (assert) {
const self = this;
createWidget("hbs-test", {
template: widgetHbs`<div class='my-div' data-my-test='hello world'></div>`,
});
await render(hbs`<MountWidget @widget="hbs-test" @args={{this.args}} />`);
await render(
<template>
<MountWidget @widget="hbs-test" @args={{self.args}} />
</template>
);
assert.dom("div.my-div").hasAttribute("data-my-test", "hello world");
});
test("buildClasses", async function (assert) {
const self = this;
createWidget("classname-test", {
tagName: "div.test",
@ -111,13 +143,17 @@ module("Integration | Component | Widget | base", function (hooks) {
this.set("args", { dynamic: "cool-class" });
await render(
hbs`<MountWidget @widget="classname-test" @args={{this.args}} />`
<template>
<MountWidget @widget="classname-test" @args={{self.args}} />
</template>
);
assert.dom(".test.static.cool-class").exists("has all the classes");
});
test("buildAttributes", async function (assert) {
const self = this;
createWidget("attributes-test", {
tagName: "div.test",
@ -129,7 +165,9 @@ module("Integration | Component | Widget | base", function (hooks) {
this.set("args", { label: "accessibility" });
await render(
hbs`<MountWidget @widget="attributes-test" @args={{this.args}} />`
<template>
<MountWidget @widget="attributes-test" @args={{self.args}} />
</template>
);
assert.dom('.test[data-evil="trout"]').exists();
@ -137,6 +175,8 @@ module("Integration | Component | Widget | base", function (hooks) {
});
test("buildId", async function (assert) {
const self = this;
createWidget("id-test", {
buildId(attrs) {
return `test-${attrs.id}`;
@ -145,7 +185,9 @@ module("Integration | Component | Widget | base", function (hooks) {
this.set("args", { id: 1234 });
await render(hbs`<MountWidget @widget="id-test" @args={{this.args}} />`);
await render(
<template><MountWidget @widget="id-test" @args={{self.args}} /></template>
);
assert.dom("#test-1234").exists();
});
@ -165,7 +207,7 @@ module("Integration | Component | Widget | base", function (hooks) {
},
});
await render(hbs`<MountWidget @widget="state-test" />`);
await render(<template><MountWidget @widget="state-test" /></template>);
assert.dom("button.test").exists("renders the button");
assert.dom("button.test").hasText("0 clicks");
@ -196,7 +238,7 @@ module("Integration | Component | Widget | base", function (hooks) {
},
});
await render(hbs`<MountWidget @widget="promise-test" />`);
await render(<template><MountWidget @widget="promise-test" /></template>);
assert.dom("button.test").hasText("No name");
@ -212,7 +254,7 @@ module("Integration | Component | Widget | base", function (hooks) {
template: widgetHbs`{{attach widget="test-embedded" attrs=attrs}}`,
});
await render(hbs`<MountWidget @widget="attach-test" />`);
await render(<template><MountWidget @widget="attach-test" /></template>);
assert.dom(".container").exists("renders container");
assert.dom(".container .embedded").exists("renders attached");
@ -226,7 +268,7 @@ module("Integration | Component | Widget | base", function (hooks) {
template: widgetHbs`{{test-embedded attrs=attrs}}`,
});
await render(hbs`<MountWidget @widget="attach-test" />`);
await render(<template><MountWidget @widget="attach-test" /></template>);
assert.dom(".container").exists("renders container");
assert.dom(".container .embedded").exists("renders attached");
@ -243,7 +285,7 @@ module("Integration | Component | Widget | base", function (hooks) {
template: widgetHbs`{{testing value=(concat "hello" " " "world")}}`,
});
await render(hbs`<MountWidget @widget="attach-test" />`);
await render(<template><MountWidget @widget="attach-test" /></template>);
assert.dom(".container").exists("renders container");
assert.dom(".container .value").hasText("hello world");
@ -263,25 +305,31 @@ module("Integration | Component | Widget | base", function (hooks) {
template: widgetHbs`{{testing value=(concat "hello" " " transformed.someValue)}}`,
});
await render(hbs`<MountWidget @widget="attach-test" />`);
await render(<template><MountWidget @widget="attach-test" /></template>);
assert.dom(".container").exists("renders container");
assert.dom(".container .value").hasText("hello world");
});
test("handlebars d-icon", async function (assert) {
const self = this;
createWidget("hbs-icon-test", {
template: widgetHbs`{{d-icon "arrow-down"}}`,
});
await render(
hbs`<MountWidget @widget="hbs-icon-test" @args={{this.args}} />`
<template>
<MountWidget @widget="hbs-icon-test" @args={{self.args}} />
</template>
);
assert.dom(".d-icon-arrow-down").exists();
});
test("handlebars i18n", async function (assert) {
const self = this;
createWidget("hbs-i18n-test", {
template: widgetHbs`
<span class='string'>{{i18n "hbs_test0"}}</span>
@ -300,7 +348,9 @@ module("Integration | Component | Widget | base", function (hooks) {
this.set("args", { key: "hbs_test1" });
await render(
hbs`<MountWidget @widget="hbs-i18n-test" @args={{this.args}} />`
<template>
<MountWidget @widget="hbs-i18n-test" @args={{self.args}} />
</template>
);
// coming up
@ -310,6 +360,8 @@ module("Integration | Component | Widget | base", function (hooks) {
});
test("handlebars #each", async function (assert) {
const self = this;
createWidget("hbs-each-test", {
tagName: "ul",
template: widgetHbs`
@ -324,7 +376,9 @@ module("Integration | Component | Widget | base", function (hooks) {
});
await render(
hbs`<MountWidget @widget="hbs-each-test" @args={{this.args}} />`
<template>
<MountWidget @widget="hbs-each-test" @args={{self.args}} />
</template>
);
assert.dom("ul li").exists({ count: 3 });
@ -347,7 +401,7 @@ module("Integration | Component | Widget | base", function (hooks) {
});
});
await render(hbs`<MountWidget @widget="decorate-test" />`);
await render(<template><MountWidget @widget="decorate-test" /></template>);
assert.dom(".decorate").exists();
assert.dom(".decorate b").hasText("before");
@ -361,7 +415,7 @@ module("Integration | Component | Widget | base", function (hooks) {
settings: { age: 36 },
});
await render(hbs`<MountWidget @widget="settings-test" />`);
await render(<template><MountWidget @widget="settings-test" /></template>);
assert.dom(".settings").hasText("age is 36");
});
@ -377,7 +431,9 @@ module("Integration | Component | Widget | base", function (hooks) {
api.changeWidgetSetting("ov-settings-test", "age", 37);
});
await render(hbs`<MountWidget @widget="ov-settings-test" />`);
await render(
<template><MountWidget @widget="ov-settings-test" /></template>
);
assert.dom(".settings").hasText("age is 37");
});
@ -393,7 +449,9 @@ module("Integration | Component | Widget | base", function (hooks) {
},
});
await render(hbs`<MountWidget @widget="get-accessor-test" />`);
await render(
<template><MountWidget @widget="get-accessor-test" /></template>
);
assert.dom("div.test").hasText("Hello eviltrout");
});
@ -405,7 +463,9 @@ module("Integration | Component | Widget | base", function (hooks) {
template: widgetHbs`{{attach widget="test-override" attrs=attrs otherOpts=(hash tagName="section.override")}}`,
});
await render(hbs`<MountWidget @widget="tag-name-override-test" />`);
await render(
<template><MountWidget @widget="tag-name-override-test" /></template>
);
assert
.dom("section.override")
@ -413,6 +473,8 @@ module("Integration | Component | Widget | base", function (hooks) {
});
test("avoids rerendering on prepend", async function (assert) {
const self = this;
createWidget("prepend-test", {
tagName: "div.test",
html(attrs) {
@ -439,7 +501,9 @@ module("Integration | Component | Widget | base", function (hooks) {
this.set("args", { array });
await render(
hbs`<MountWidget @widget="prepend-test" @args={{this.args}} />`
<template>
<MountWidget @widget="prepend-test" @args={{self.args}} />
</template>
);
const startElements = Array.from(document.querySelectorAll("span.val"));

View File

@ -1,20 +1,22 @@
import { render, settled } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import bodyClass from "discourse/helpers/body-class";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Helper | body-class", function (hooks) {
setupRenderingTest(hooks);
test("A single class", async function (assert) {
await render(hbs`{{body-class "foo"}}`);
await render(<template>{{bodyClass "foo"}}</template>);
assert.dom(document.body).hasClass("foo");
});
test("Multiple classes", async function (assert) {
const self = this;
this.set("bar", "bar");
await render(hbs`{{body-class "baz" this.bar}}`);
await render(<template>{{bodyClass "baz" self.bar}}</template>);
assert.dom(document.body).hasClass("baz");
assert.dom(document.body).hasClass("bar");
@ -22,13 +24,15 @@ module("Integration | Helper | body-class", function (hooks) {
test("Empty classes", async function (assert) {
const classesBefore = document.body.className;
await render(hbs`{{body-class (if false "not-really")}}`);
await render(<template>{{bodyClass (if false "not-really")}}</template>);
assert.strictEqual(document.body.className, classesBefore);
});
test("Dynamic classes", async function (assert) {
const self = this;
this.set("dynamic", "bar");
await render(hbs`{{body-class this.dynamic}}`);
await render(<template>{{bodyClass self.dynamic}}</template>);
assert.dom(document.body).hasClass("bar");
this.set("dynamic", "baz");

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import categoryBadge from "discourse/helpers/category-badge";
import Category from "discourse/models/category";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
@ -8,17 +8,23 @@ module("Integration | Helper | category-badge", function (hooks) {
setupRenderingTest(hooks);
test("displays category", async function (assert) {
const self = this;
this.set("category", Category.findById(1));
await render(hbs`{{category-badge this.category}}`);
await render(<template>{{categoryBadge self.category}}</template>);
assert.dom(".badge-category__name").hasText(this.category.displayName);
});
test("options.link", async function (assert) {
const self = this;
this.set("category", Category.findById(1));
await render(hbs`{{category-badge this.category link=true}}`);
await render(
<template>{{categoryBadge self.category link=true}}</template>
);
assert
.dom(

View File

@ -1,20 +1,23 @@
import { hash } from "@ember/helper";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import categoryLink from "discourse/helpers/category-link";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Helper | category-link", function (hooks) {
setupRenderingTest(hooks);
test("name", async function (assert) {
await render(hbs`{{category-link (hash name="foo")}}`);
await render(<template>{{categoryLink (hash name="foo")}}</template>);
assert.dom(".badge-category__name").hasText("foo");
});
test("description_text", async function (assert) {
await render(
hbs`{{category-link (hash name="foo" description_text="bar")}}`
<template>
{{categoryLink (hash name="foo" description_text="bar")}}
</template>
);
assert.dom(".badge-category").hasAttribute("title", "bar");

View File

@ -1,41 +1,56 @@
import { array } from "@ember/helper";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import concatClass from "discourse/helpers/concat-class";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Helper | concat-class", function (hooks) {
setupRenderingTest(hooks);
test("One class given", async function (assert) {
await render(hbs`<button class={{concat-class "foo"}} />`);
await render(<template><button class={{concatClass "foo"}} /></template>);
assert.dom("button").hasAttribute("class", "foo");
});
test("Multiple class given", async function (assert) {
const self = this;
this.set("bar", "bar");
await render(hbs`<button class={{concat-class "foo" this.bar}} />`);
await render(
<template><button class={{concatClass "foo" self.bar}} /></template>
);
assert.dom("button").hasAttribute("class", "foo bar");
});
test("One undefined class given", async function (assert) {
const self = this;
this.set("bar", null);
await render(hbs`<button class={{concat-class "foo" this.bar}} />`);
await render(
<template><button class={{concatClass "foo" self.bar}} /></template>
);
assert.dom("button").hasAttribute("class", "foo");
});
test("Only undefined class given", async function (assert) {
const self = this;
this.set("bar", null);
await render(hbs`<button class={{concat-class null this.bar}} />`);
await render(
<template><button class={{concatClass null self.bar}} /></template>
);
assert.dom("button").doesNotHaveAttribute("class");
});
test("Helpers used", async function (assert) {
await render(
hbs`<button class={{concat-class (if true "foo") (if true "bar")}} />`
<template>
<button class={{concatClass (if true "foo") (if true "bar")}} />
</template>
);
assert.dom("button").hasAttribute("class", "foo bar");
@ -43,7 +58,11 @@ module("Integration | Helper | concat-class", function (hooks) {
test("Arrays", async function (assert) {
await render(
hbs`<button class={{concat-class (array) (array "foo" "bar") (array null)}} />`
<template>
<button
class={{concatClass (array) (array "foo" "bar") (array null)}}
/>
</template>
);
assert.dom("button").hasAttribute("class", "foo bar");

View File

@ -1,13 +1,17 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import dIcon from "discourse/helpers/d-icon";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Helper | d-icon", function (hooks) {
setupRenderingTest(hooks);
test("default", async function (assert) {
await render(hbs`<div class="test">{{d-icon "bars"}}</div>`);
await render(
<template>
<div class="test">{{dIcon "bars"}}</div>
</template>
);
assert
.dom(".test")
@ -17,7 +21,11 @@ module("Integration | Helper | d-icon", function (hooks) {
});
test("with replacement", async function (assert) {
await render(hbs`<div class="test">{{d-icon "d-watching"}}</div>`);
await render(
<template>
<div class="test">{{dIcon "d-watching"}}</div>
</template>
);
assert
.dom(".test")

View File

@ -1,21 +1,23 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import emoji from "discourse/helpers/emoji";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Helper | emoji", function (hooks) {
setupRenderingTest(hooks);
test("it renders", async function (assert) {
await render(hbs`{{emoji "tada"}}`);
await render(<template>{{emoji "tada"}}</template>);
assert.dom(`.emoji[title="tada"]`).exists();
});
test("it renders custom title", async function (assert) {
const self = this;
const title = "custom title";
this.set("title", title);
await render(hbs`{{emoji "tada" title=this.title}}`);
await render(<template>{{emoji "tada" title=self.title}}</template>);
assert.dom(`.emoji[title="${title}"]`).exists();
});

View File

@ -1,15 +1,17 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import htmlSafe from "discourse/helpers/html-safe";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Helper | html-safe", function (hooks) {
setupRenderingTest(hooks);
test("default", async function (assert) {
const self = this;
this.set("string", "<p class='cookies'>biscuits</p>");
await render(hbs`{{html-safe this.string}}`);
await render(<template>{{htmlSafe self.string}}</template>);
assert.dom("p.cookies").exists("displays the string as html");
});

View File

@ -1,13 +1,18 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import htmlSafe from "discourse/helpers/html-safe";
import replaceEmoji from "discourse/helpers/replace-emoji";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
module("Integration | Helper | replace-emoji", function (hooks) {
setupRenderingTest(hooks);
test("it replaces the emoji", async function (assert) {
await render(hbs`<span>{{replace-emoji "some text :heart:"}}</span>`);
await render(
<template>
<span>{{replaceEmoji "some text :heart:"}}</span>
</template>
);
assert.dom(`span`).includesText("some text");
assert.dom(`.emoji[title="heart"]`).exists();
@ -15,14 +20,20 @@ module("Integration | Helper | replace-emoji", function (hooks) {
test("it escapes the text", async function (assert) {
await render(
hbs`<span>{{replace-emoji "<style>body: {background: red;}</style>"}}</span>`
<template>
<span>{{replaceEmoji "<style>body: {background: red;}</style>"}}</span>
</template>
);
assert.dom(`span`).hasText("<style>body: {background: red;}</style>");
});
test("it renders html-safe text", async function (assert) {
await render(hbs`<span>{{replace-emoji (html-safe "safe text")}}</span>`);
await render(
<template>
<span>{{replaceEmoji (htmlSafe "safe text")}}</span>
</template>
);
assert.dom(`span`).hasText("safe text");
});

View File

@ -1,39 +1,39 @@
import { run } from "@ember/runloop";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { setupRenderingTest } from "ember-qunit";
import { module, test } from "qunit";
import slice from "discourse/helpers/slice";
module("Integration | Helper | {{slice}}", function (hooks) {
setupRenderingTest(hooks);
test("it slices an array with positional params", async function (assert) {
const self = this;
this.set("array", [2, 4, 6]);
await render(hbs`
{{slice 1 3 this.array}}
`);
await render(<template>{{slice 1 3 self.array}}</template>);
assert.dom().hasText("4,6", "sliced values");
});
test("it slices when only 2 params are passed", async function (assert) {
const self = this;
this.set("array", [2, 4, 6]);
await render(hbs`
{{slice 1 this.array}}
`);
await render(<template>{{slice 1 self.array}}</template>);
assert.dom().hasText("4,6", "sliced values");
});
test("it recomputes the slice if an item in the array changes", async function (assert) {
const self = this;
let array = [2, 4, 6];
this.set("array", array);
await render(hbs`
{{slice 1 3 this.array}}
`);
await render(<template>{{slice 1 3 self.array}}</template>);
assert.dom().hasText("4,6", "sliced values");
@ -43,27 +43,35 @@ module("Integration | Helper | {{slice}}", function (hooks) {
});
test("it allows null array", async function (assert) {
const self = this;
this.set("array", null);
await render(hbs`
this is all that will render
{{#each (slice 1 2 this.array) as |value|}}
{{value}}
{{/each}}
`);
await render(
<template>
this is all that will render
{{#each (slice 1 2 self.array) as |value|}}
{{value}}
{{/each}}
</template>
);
assert.dom().hasText("this is all that will render", "no error is thrown");
});
test("it allows undefined array", async function (assert) {
const self = this;
this.set("array", undefined);
await render(hbs`
this is all that will render
{{#each (slice 1 2 this.array) as |value|}}
{{value}}
{{/each}}
`);
await render(
<template>
this is all that will render
{{#each (slice 1 2 self.array) as |value|}}
{{value}}
{{/each}}
</template>
);
assert.dom().hasText("this is all that will render", "no error is thrown");
});

View File

@ -1,6 +1,6 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import DButton from "discourse/components/d-button";
import domUtils from "discourse/lib/dom-utils";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
@ -8,7 +8,7 @@ module("Unit | Utils | dom-utils", function (hooks) {
setupRenderingTest(hooks);
test("offset", async function (assert) {
await render(hbs`<DButton @translatedLabel="baz" />`);
await render(<template><DButton @translatedLabel="baz" /></template>);
const element = document.querySelector(".btn");
const offset = domUtils.offset(element);
const rect = element.getBoundingClientRect();
@ -20,7 +20,7 @@ module("Unit | Utils | dom-utils", function (hooks) {
});
test("position", async function (assert) {
await render(hbs`<DButton @translatedLabel="baz" />`);
await render(<template><DButton @translatedLabel="baz" /></template>);
const element = document.querySelector(".btn");
const position = domUtils.position(element);