import { module, test } from "qunit"; import { setupRenderingTest } from "discourse/tests/helpers/component-test"; import { click, render, triggerKeyEvent } from "@ember/test-helpers"; import { exists, query } from "discourse/tests/helpers/qunit-helpers"; import I18n from "I18n"; import { hbs } from "ember-cli-htmlbars"; import ClassicComponent from "@ember/component"; import { withSilencedDeprecationsAsync } from "discourse-common/lib/deprecated"; module("Integration | Component | d-button", function (hooks) { setupRenderingTest(hooks); test("icon only button", async function (assert) { await render(hbs``); assert.ok(exists("button.btn.btn-icon.no-text"), "it has all the classes"); assert.ok(exists("button .d-icon.d-icon-plus"), "it has the icon"); assert.strictEqual( query("button").getAttribute("tabindex"), "3", "it has the tabindex" ); }); test("icon and text button", async function (assert) { await render(hbs``); assert.ok(exists("button.btn.btn-icon-text"), "it has all the classes"); assert.ok(exists("button .d-icon.d-icon-plus"), "it has the icon"); assert.ok(exists("button span.d-button-label"), "it has the label"); }); test("text only button", async function (assert) { await render(hbs``); assert.ok(exists("button.btn.btn-text"), "it has all the classes"); assert.ok(exists("button span.d-button-label"), "it has the label"); }); test("form attribute", async function (assert) { await render(hbs``); assert.ok(exists("button[form=login-form]"), "it has the form attribute"); }); test("link-styled button", async function (assert) { await render(hbs``); assert.ok(exists("button.btn-link:not(.btn)"), "it has the right classes"); }); test("isLoading button", async function (assert) { this.set("isLoading", true); await render(hbs``); assert.ok( exists("button.is-loading .loading-icon"), "it has a spinner showing" ); assert.ok( exists("button[disabled]"), "while loading the button is disabled" ); this.set("isLoading", false); assert.notOk( exists("button .loading-icon"), "it doesn't have a spinner showing" ); assert.ok( exists("button:not([disabled])"), "while not loading the button is enabled" ); }); test("button without isLoading attribute", async function (assert) { await render(hbs``); assert.notOk( exists("button.is-loading"), "it doesn't have class is-loading" ); assert.notOk( exists("button .loading-icon"), "it doesn't have a spinner showing" ); assert.notOk(exists("button[disabled]"), "it isn't disabled"); }); test("isLoading button explicitly set to undefined state", async function (assert) { this.set("isLoading"); await render(hbs``); assert.notOk( exists("button.is-loading"), "it doesn't have class is-loading" ); assert.notOk( exists("button .loading-icon"), "it doesn't have a spinner showing" ); assert.notOk(exists("button[disabled]"), "it isn't disabled"); }); test("disabled button", async function (assert) { this.set("disabled", true); await render(hbs``); assert.ok(exists("button[disabled]"), "the button is disabled"); this.set("disabled", false); assert.ok(exists("button:not([disabled])"), "the button is enabled"); }); test("aria-label", async function (assert) { I18n.translations[I18n.locale].js.test = { fooAriaLabel: "foo" }; await render( hbs`` ); this.set("ariaLabel", "test.fooAriaLabel"); assert.strictEqual( query("button").getAttribute("aria-label"), I18n.t("test.fooAriaLabel") ); this.setProperties({ ariaLabel: null, translatedAriaLabel: "bar", }); assert.strictEqual(query("button").getAttribute("aria-label"), "bar"); }); test("title", async function (assert) { I18n.translations[I18n.locale].js.test = { fooTitle: "foo" }; await render( hbs`` ); this.set("title", "test.fooTitle"); assert.strictEqual( query("button").getAttribute("title"), I18n.t("test.fooTitle") ); this.setProperties({ title: null, translatedTitle: "bar", }); assert.strictEqual(query("button").getAttribute("title"), "bar"); }); test("label", async function (assert) { I18n.translations[I18n.locale].js.test = { fooLabel: "foo" }; await render( hbs`` ); this.set("label", "test.fooLabel"); assert.strictEqual( query("button .d-button-label").innerText, I18n.t("test.fooLabel") ); this.setProperties({ label: null, translatedLabel: "bar", }); assert.strictEqual(query("button .d-button-label").innerText, "bar"); }); test("aria-expanded", async function (assert) { await render(hbs``); assert.strictEqual(query("button").getAttribute("aria-expanded"), null); this.set("ariaExpanded", true); assert.strictEqual(query("button").getAttribute("aria-expanded"), "true"); this.set("ariaExpanded", false); assert.strictEqual(query("button").getAttribute("aria-expanded"), "false"); this.set("ariaExpanded", "false"); assert.strictEqual(query("button").getAttribute("aria-expanded"), null); this.set("ariaExpanded", "true"); assert.strictEqual(query("button").getAttribute("aria-expanded"), null); }); test("aria-controls", async function (assert) { await render(hbs``); this.set("ariaControls", "foo-bar"); assert.strictEqual( query("button").getAttribute("aria-controls"), "foo-bar" ); }); test("onKeyDown callback", async function (assert) { this.set("foo", null); this.set("onKeyDown", () => { this.set("foo", "bar"); }); this.set("action", () => { this.set("foo", "baz"); }); await render( hbs`` ); await triggerKeyEvent(".btn", "keydown", "Space"); assert.strictEqual(this.foo, "bar"); await triggerKeyEvent(".btn", "keydown", "Enter"); assert.strictEqual(this.foo, "bar"); }); test("press Enter", async function (assert) { this.set("foo", null); this.set("action", () => { this.set("foo", "bar"); }); await render(hbs``); await triggerKeyEvent(".btn", "keydown", "Space"); assert.strictEqual(this.foo, null); await triggerKeyEvent(".btn", "keydown", "Enter"); assert.strictEqual(this.foo, "bar"); }); test("@action function is triggered on click", async function (assert) { this.set("foo", null); this.set("action", () => { this.set("foo", "bar"); }); await render(hbs``); await click(".btn"); assert.strictEqual(this.foo, "bar"); }); test("@action can sendAction when passed a string", async function (assert) { this.set("foo", null); this.set("legacyActionTriggered", () => this.set("foo", "bar")); this.classicComponent = ClassicComponent.extend({ actions: { myLegacyAction() { this.legacyActionTriggered(); }, }, layout: hbs``, }); await withSilencedDeprecationsAsync( "discourse.d-button-action-string", async () => { await render( hbs`` ); await click(".btn"); } ); assert.strictEqual(this.foo, "bar"); }); test("Uses correct target with @action string when component called with block", async function (assert) { this.set("foo", null); this.set("legacyActionTriggered", () => this.set("foo", "bar")); this.simpleWrapperComponent = ClassicComponent.extend(); this.classicComponent = ClassicComponent.extend({ actions: { myLegacyAction() { this.legacyActionTriggered(); }, }, layout: hbs`<@simpleWrapperComponent>`, }); await withSilencedDeprecationsAsync( "discourse.d-button-action-string", async () => { await render( hbs`` ); await click(".btn"); } ); assert.strictEqual(this.foo, "bar"); }); test("ellipses", async function (assert) { await render(hbs``); assert.dom(".d-button-label").hasText("test label…"); }); });