diff --git a/app/assets/javascripts/discourse/app/mixins/uppy-upload.js b/app/assets/javascripts/discourse/app/mixins/uppy-upload.js index 59f04690451..320f151a4c1 100644 --- a/app/assets/javascripts/discourse/app/mixins/uppy-upload.js +++ b/app/assets/javascripts/discourse/app/mixins/uppy-upload.js @@ -159,6 +159,10 @@ export default Mixin.create(UppyS3Multipart, ExtendableUploader, { }); this._uppyInstance.on("upload", (data) => { + if (this.isDestroying || this.isDestroyed) { + return; + } + this._addNeedProcessing(data.fileIDs.length); const files = data.fileIDs.map((fileId) => this._uppyInstance.getFile(fileId) @@ -257,6 +261,10 @@ export default Mixin.create(UppyS3Multipart, ExtendableUploader, { this._uppyInstance.on("complete", () => { run(() => { + if (this.isDestroying || this.isDestroyed) { + return; + } + this.appEvents.trigger(`upload-mixin:${this.id}:all-uploads-complete`); this._reset(); }); diff --git a/app/assets/javascripts/discourse/tests/helpers/component-test.js b/app/assets/javascripts/discourse/tests/helpers/component-test.js index 99396c2b618..4a4df22ee95 100644 --- a/app/assets/javascripts/discourse/tests/helpers/component-test.js +++ b/app/assets/javascripts/discourse/tests/helpers/component-test.js @@ -5,16 +5,28 @@ import TopicTrackingState from "discourse/models/topic-tracking-state"; import User from "discourse/models/user"; import { autoLoadModules } from "discourse/initializers/auto-load-modules"; import QUnit, { test } from "qunit"; - import { setupRenderingTest as emberSetupRenderingTest } from "ember-qunit"; +import { currentSettings } from "discourse/tests/helpers/site-settings"; +import { clearResolverOptions } from "discourse-common/resolver"; +import { testCleanup } from "discourse/tests/helpers/qunit-helpers"; export function setupRenderingTest(hooks) { emberSetupRenderingTest(hooks); hooks.beforeEach(function () { + if (!hooks.usingDiscourseModule) { + this.siteSettings = currentSettings(); + + if (!this.registry) { + this.registry = this.owner.__registry__; + } + + this.container = this.owner; + clearResolverOptions(); + } + this.site = Site.current(); this.session = Session.current(); - this.container = this.owner; const currentUser = User.create({ username: "eviltrout", @@ -41,9 +53,16 @@ export function setupRenderingTest(hooks) { ); autoLoadModules(this.owner, this.registry); + this.owner.lookup("service:store"); $.fn.autocomplete = function () {}; }); + + if (!hooks.usingDiscourseModule) { + hooks.afterEach(function () { + testCleanup(this.container); + }); + } } export default function (name, hooks, opts) { diff --git a/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js b/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js index 6c95e4e67cd..734118f5f94 100644 --- a/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js +++ b/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js @@ -138,7 +138,7 @@ export function applyPretender(name, server, helper) { } // Add clean up code here to run after every test -function testCleanup(container, app) { +export function testCleanup(container, app) { if (_initialized.has(QUnit.config.current.testId)) { if (!app) { app = getApplication(); @@ -223,6 +223,7 @@ export function discourseModule(name, options) { this.moduleName = name; + hooks.usingDiscourseModule = true; options.call(this, hooks); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/ace-editor-test.js b/app/assets/javascripts/discourse/tests/integration/components/ace-editor-test.js index 0e2cc1eaad1..c049c8060ea 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/ace-editor-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/ace-editor-test.js @@ -1,48 +1,37 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { count, exists } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | ace-editor", function (hooks) { +module("Integration | Component | ace-editor", function (hooks) { setupRenderingTest(hooks); - componentTest("css editor", { - template: hbs`{{ace-editor mode="css"}}`, - test(assert) { - assert.ok(exists(".ace_editor"), "it renders the ace editor"); - }, + test("css editor", async function (assert) { + await render(hbs``); + assert.ok(exists(".ace_editor"), "it renders the ace editor"); }); - componentTest("html editor", { - template: hbs`{{ace-editor mode="html" content="wat"}}`, - test(assert) { - assert.ok(exists(".ace_editor"), "it renders the ace editor"); - }, + test("html editor", async function (assert) { + await render(hbs``); + assert.ok(exists(".ace_editor"), "it renders the ace editor"); }); - componentTest("sql editor", { - template: hbs`{{ace-editor mode="sql" content="SELECT * FROM users"}}`, - test(assert) { - assert.ok(exists(".ace_editor"), "it renders the ace editor"); - }, + test("sql editor", async function (assert) { + await render(hbs``); + assert.ok(exists(".ace_editor"), "it renders the ace editor"); }); - componentTest("disabled editor", { - template: hbs` - {{ace-editor mode="sql" content="SELECT * FROM users" disabled=true}} - `, - test(assert) { - assert.ok(exists(".ace_editor"), "it renders the ace editor"); - assert.equal( - queryAll(".ace-wrapper[data-disabled]").length, - 1, - "it has a data-disabled attr" - ); - }, + test("disabled editor", async function (assert) { + await render(hbs` + + `); + + assert.ok(exists(".ace_editor"), "it renders the ace editor"); + assert.strictEqual( + count(".ace-wrapper[data-disabled]"), + 1, + "it has a data-disabled attr" + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/activation-controls-test.js b/app/assets/javascripts/discourse/tests/integration/components/activation-controls-test.js index 1c8c5ae730e..dcffc1daa58 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/activation-controls-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/activation-controls-test.js @@ -1,24 +1,18 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, exists } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule( - "Integration | Component | activation-controls", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | activation-controls", function (hooks) { + setupRenderingTest(hooks); - componentTest("hides change email button", { - template: hbs`{{activation-controls}}`, - beforeEach() { - this.siteSettings.enable_local_logins = false; - this.siteSettings.email_editable = false; - }, + test("hides change email button", async function (assert) { + this.siteSettings.enable_local_logins = false; + this.siteSettings.email_editable = false; - test(assert) { - assert.ok(!exists("button.edit-email")); - }, - }); - } -); + await render(hbs``); + + assert.ok(!exists("button.edit-email")); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/admin-report-test.js b/app/assets/javascripts/discourse/tests/integration/components/admin-report-test.js index 944330bc68e..88691761fe6 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/admin-report-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/admin-report-test.js @@ -1,190 +1,166 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import { click } from "@ember/test-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { count, exists, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import pretender from "discourse/tests/helpers/create-pretender"; -discourseModule("Integration | Component | admin-report", function (hooks) { +module("Integration | Component | admin-report", function (hooks) { setupRenderingTest(hooks); - componentTest("default", { - template: hbs`{{admin-report dataSourceName='signups'}}`, + test("default", async function (assert) { + await render(hbs``); - async test(assert) { - assert.ok(exists(".admin-report.signups")); + assert.ok(exists(".admin-report.signups")); - assert.ok(exists(".admin-report.signups", "it defaults to table mode")); + assert.ok(exists(".admin-report.signups", "it defaults to table mode")); - assert.strictEqual( - queryAll(".header .item.report").text().trim(), - "Signups", - "it has a title" - ); + assert.strictEqual( + query(".header .item.report").innerText.trim(), + "Signups", + "it has a title" + ); - assert.strictEqual( - queryAll(".header .info").attr("data-tooltip"), - "New account registrations for this period", - "it has a description" - ); + assert.strictEqual( + query(".header .info").getAttribute("data-tooltip"), + "New account registrations for this period", + "it has a description" + ); - assert.strictEqual( - queryAll(".admin-report-table thead tr th:first-child .title") - .text() - .trim(), - "Day", - "it has col headers" - ); + assert.strictEqual( + query( + ".admin-report-table thead tr th:first-child .title" + ).innerText.trim(), + "Day", + "it has col headers" + ); - assert.strictEqual( - queryAll(".admin-report-table thead tr th:nth-child(2) .title") - .text() - .trim(), - "Count", - "it has col headers" - ); + assert.strictEqual( + query( + ".admin-report-table thead tr th:nth-child(2) .title" + ).innerText.trim(), + "Count", + "it has col headers" + ); - assert.strictEqual( - queryAll(".admin-report-table tbody tr:nth-child(1) td:nth-child(1)") - .text() - .trim(), - "June 16, 2018", - "it has rows" - ); + assert.strictEqual( + query( + ".admin-report-table tbody tr:nth-child(1) td:nth-child(1)" + ).innerText.trim(), + "June 16, 2018", + "it has rows" + ); - assert.strictEqual( - queryAll(".admin-report-table tbody tr:nth-child(1) td:nth-child(2)") - .text() - .trim(), - "12", - "it has rows" - ); + assert.strictEqual( + query( + ".admin-report-table tbody tr:nth-child(1) td:nth-child(2)" + ).innerText.trim(), + "12", + "it has rows" + ); - assert.ok(exists(".total-row"), "it has totals"); + assert.ok(exists(".total-row"), "it has totals"); - await click(".admin-report-table-header.y .sort-btn"); + await click(".admin-report-table-header.y .sort-btn"); - assert.strictEqual( - queryAll(".admin-report-table tbody tr:nth-child(1) td:nth-child(2)") - .text() - .trim(), - "7", - "it can sort rows" - ); - }, + assert.strictEqual( + query( + ".admin-report-table tbody tr:nth-child(1) td:nth-child(2)" + ).innerText.trim(), + "7", + "it can sort rows" + ); }); - componentTest("options", { - template: hbs`{{admin-report dataSourceName='signups' reportOptions=options}}`, + test("options", async function (assert) { + this.set("options", { + table: { + perPage: 4, + total: false, + }, + }); - beforeEach() { - this.set("options", { - table: { - perPage: 4, - total: false, + await render( + hbs`` + ); + + assert.ok(exists(".pagination"), "it paginates the results"); + assert.strictEqual( + count(".pagination button"), + 3, + "it creates the correct number of pages" + ); + + assert.notOk(exists(".totals-sample-table"), "it hides totals"); + }); + + test("switch modes", async function (assert) { + await render( + hbs`` + ); + + await click(".mode-btn.chart"); + + assert.notOk(exists(".admin-report-table"), "it removes the table"); + assert.ok(exists(".admin-report-chart"), "it shows the chart"); + }); + + test("timeout", async function (assert) { + await render(hbs``); + + assert.ok(exists(".alert-error.timeout"), "it displays a timeout error"); + }); + + test("no data", async function (assert) { + await render(hbs``); + + assert.ok(exists(".no-data"), "it displays a no data alert"); + }); + + test("exception", async function (assert) { + await render(hbs``); + + assert.ok(exists(".alert-error.exception"), "it displays an error"); + }); + + test("rate limited", async function (assert) { + pretender.get("/admin/reports/bulk", () => { + return [ + 429, + { "Content-Type": "application/json" }, + { + errors: [ + "You’ve performed this action too many times. Please wait 10 seconds before trying again.", + ], + error_type: "rate_limit", + extras: { wait_seconds: 10 }, }, - }); - }, + ]; + }); - test(assert) { - assert.ok(exists(".pagination"), "it paginates the results"); - assert.strictEqual( - count(".pagination button"), - 3, - "it creates the correct number of pages" - ); + await render(hbs``); - assert.notOk(exists(".totals-sample-table"), "it hides totals"); - }, + assert.ok( + exists(".alert-error.rate-limited"), + "it displays a rate limited error" + ); }); - componentTest("switch modes", { - template: hbs`{{admin-report dataSourceName='signups' showFilteringUI=true}}`, + test("post edits", async function (assert) { + await render(hbs``); - async test(assert) { - await click(".mode-btn.chart"); - - assert.notOk(exists(".admin-report-table"), "it removes the table"); - assert.ok(exists(".admin-report-chart"), "it shows the chart"); - }, + assert.ok( + exists(".admin-report.post-edits"), + "it displays the post edits report" + ); }); - componentTest("timeout", { - template: hbs`{{admin-report dataSourceName='signups_timeout'}}`, + test("not found", async function (assert) { + await render(hbs``); - test(assert) { - assert.ok(exists(".alert-error.timeout"), "it displays a timeout error"); - }, - }); - - componentTest("no data", { - template: hbs`{{admin-report dataSourceName='posts'}}`, - - test(assert) { - assert.ok(exists(".no-data"), "it displays a no data alert"); - }, - }); - - componentTest("exception", { - template: hbs`{{admin-report dataSourceName='signups_exception'}}`, - - test(assert) { - assert.ok(exists(".alert-error.exception"), "it displays an error"); - }, - }); - - componentTest("rate limited", { - beforeEach() { - pretender.get("/admin/reports/bulk", () => { - return [ - 429, - { "Content-Type": "application/json" }, - { - errors: [ - "You’ve performed this action too many times. Please wait 10 seconds before trying again.", - ], - error_type: "rate_limit", - extras: { wait_seconds: 10 }, - }, - ]; - }); - }, - - template: hbs`{{admin-report dataSourceName='signups_rate_limited'}}`, - - test(assert) { - assert.ok( - exists(".alert-error.rate-limited"), - "it displays a rate limited error" - ); - }, - }); - - componentTest("post edits", { - template: hbs`{{admin-report dataSourceName='post_edits'}}`, - - test(assert) { - assert.ok( - exists(".admin-report.post-edits"), - "it displays the post edits report" - ); - }, - }); - - componentTest("not found", { - template: hbs`{{admin-report dataSourceName='not_found'}}`, - - test(assert) { - assert.ok( - exists(".alert-error.not-found"), - "it displays a not found error" - ); - }, + assert.ok( + exists(".alert-error.not-found"), + "it displays a not found error" + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/admin-user-field-item-test.js b/app/assets/javascripts/discourse/tests/integration/components/admin-user-field-item-test.js index f8501c3df1e..d642d84f021 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/admin-user-field-item-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/admin-user-field-item-test.js @@ -1,78 +1,60 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import I18n from "I18n"; -import { click } from "@ember/test-helpers"; -discourseModule( - "Integration | Component | admin-user-field-item", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | admin-user-field-item", function (hooks) { + setupRenderingTest(hooks); - componentTest("user field without an id", { - template: hbs`{{admin-user-field-item userField=userField}}`, + test("user field without an id", async function (assert) { + await render(hbs``); - async test(assert) { - assert.ok(exists(".save"), "displays editing mode"); - }, + assert.ok(exists(".save"), "displays editing mode"); + }); + + test("cancel action", async function (assert) { + this.set("userField", { id: 1, field_type: "text" }); + this.set("isEditing", true); + + await render( + hbs`` + ); + + await click(".cancel"); + assert.ok(exists(".edit")); + }); + + test("edit action", async function (assert) { + this.set("userField", { id: 1, field_type: "text" }); + + await render( + hbs`` + ); + + await click(".edit"); + assert.ok(exists(".save")); + }); + + test("user field with an id", async function (assert) { + this.set("userField", { + id: 1, + field_type: "text", + name: "foo", + description: "what is foo", }); - componentTest("cancel action", { - template: hbs`{{admin-user-field-item isEditing=isEditing destroyAction=destroyAction userField=userField}}`, + await render(hbs``); - beforeEach() { - this.set("userField", { id: 1, field_type: "text" }); - this.set("isEditing", true); - }, - - async test(assert) { - await click(".cancel"); - assert.ok(exists(".edit")); - }, - }); - - componentTest("edit action", { - template: hbs`{{admin-user-field-item destroyAction=destroyAction userField=userField}}`, - - beforeEach() { - this.set("userField", { id: 1, field_type: "text" }); - }, - - async test(assert) { - await click(".edit"); - assert.ok(exists(".save")); - }, - }); - - componentTest("user field with an id", { - template: hbs`{{admin-user-field-item userField=userField}}`, - - beforeEach() { - this.set("userField", { - id: 1, - field_type: "text", - name: "foo", - description: "what is foo", - }); - }, - - async test(assert) { - assert.equal(query(".name").innerText, this.userField.name); - assert.equal( - query(".description").innerText, - this.userField.description - ); - assert.equal( - query(".field-type").innerText, - I18n.t("admin.user_fields.field_types.text") - ); - }, - }); - } -); + assert.strictEqual(query(".name").innerText, this.userField.name); + assert.strictEqual( + query(".description").innerText, + this.userField.description + ); + assert.strictEqual( + query(".field-type").innerText, + I18n.t("admin.user_fields.field_types.text") + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/avatar-uploader-test.js b/app/assets/javascripts/discourse/tests/integration/components/avatar-uploader-test.js index a7cc40b79fb..6d1a3c2e302 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/avatar-uploader-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/avatar-uploader-test.js @@ -1,14 +1,11 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import pretender from "discourse/tests/helpers/create-pretender"; -import { - createFile, - discourseModule, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { createFile } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; +import pretender from "discourse/tests/helpers/create-pretender"; -discourseModule("Integration | Component | avatar-uploader", function (hooks) { +module("Integration | Component | avatar-uploader", function (hooks) { setupRenderingTest(hooks); hooks.beforeEach(function () { @@ -17,25 +14,24 @@ discourseModule("Integration | Component | avatar-uploader", function (hooks) { }); }); - componentTest("default", { - template: hbs`{{avatar-uploader - id="avatar-uploader" - done=done - }}`, + test("default", async function (assert) { + const done = assert.async(); + this.set("done", () => { + assert.ok(true, "action is called after avatar is uploaded"); + done(); + }); - async test(assert) { - const done = assert.async(); + await render(hbs` + + `); - this.set("done", () => { - assert.ok(true, "action is called after avatar is uploaded"); - done(); - }); - - await this.container - .lookup("service:app-events") - .trigger("upload-mixin:avatar-uploader:add-files", [ - createFile("avatar.png"), - ]); - }, + await this.container + .lookup("service:app-events") + .trigger("upload-mixin:avatar-uploader:add-files", [ + createFile("avatar.png"), + ]); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/badge-button-test.js b/app/assets/javascripts/discourse/tests/integration/components/badge-button-test.js index 975d4c1075c..532b9ad4137 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/badge-button-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/badge-button-test.js @@ -1,105 +1,81 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | badge-button", function (hooks) { +module("Integration | Component | badge-button", function (hooks) { setupRenderingTest(hooks); - componentTest("disabled badge", { - template: hbs`{{badge-button badge=badge}}`, + test("disabled badge", async function (assert) { + this.set("badge", { enabled: false }); - beforeEach() { - this.set("badge", { enabled: false }); - }, + await render(hbs``); - async test(assert) { - assert.ok(exists(".user-badge.disabled")); - }, + assert.ok(exists(".user-badge.disabled")); }); - componentTest("enabled badge", { - template: hbs`{{badge-button badge=badge}}`, + test("enabled badge", async function (assert) { + this.set("badge", { enabled: true }); - beforeEach() { - this.set("badge", { enabled: true }); - }, + await render(hbs``); - async test(assert) { - assert.notOk(exists(".user-badge.disabled")); - }, + assert.notOk(exists(".user-badge.disabled")); }); - componentTest("data-badge-name", { - template: hbs`{{badge-button badge=badge}}`, + test("data-badge-name", async function (assert) { + this.set("badge", { name: "foo" }); - beforeEach() { - this.set("badge", { name: "foo" }); - }, + await render(hbs``); - async test(assert) { - assert.ok(exists('.user-badge[data-badge-name="foo"]')); - }, + assert.ok(exists('.user-badge[data-badge-name="foo"]')); }); - componentTest("title", { - template: hbs`{{badge-button badge=badge}}`, + test("title", async function (assert) { + this.set("badge", { description: "a good run" }); - beforeEach() { - this.set("badge", { description: "a good run" }); - }, + await render(hbs``); - async test(assert) { - assert.equal(query(".user-badge").title, "a good run", "it strips html"); + assert.strictEqual( + query(".user-badge").title, + "a good run", + "it strips html" + ); - this.set("badge", { description: "a bad run" }); + this.set("badge", { description: "a bad run" }); - assert.equal( - query(".user-badge").title, - "a bad run", - "it updates title when changing description" - ); - }, + assert.strictEqual( + query(".user-badge").title, + "a bad run", + "it updates title when changing description" + ); }); - componentTest("icon", { - template: hbs`{{badge-button badge=badge}}`, + test("icon", async function (assert) { + this.set("badge", { icon: "times" }); - beforeEach() { - this.set("badge", { icon: "times" }); - }, + await render(hbs``); - async test(assert) { - assert.ok(exists(".d-icon.d-icon-times")); - }, + assert.ok(exists(".d-icon.d-icon-times")); }); - componentTest("accepts block", { - template: hbs`{{#badge-button badge=badge}}{{/badge-button}}`, + test("accepts block", async function (assert) { + this.set("badge", {}); - beforeEach() { - this.set("badge", {}); - }, + await render(hbs` + + + + `); - async test(assert) { - assert.ok(exists(".test")); - }, + assert.ok(exists(".test")); }); - componentTest("badgeTypeClassName", { - template: hbs`{{badge-button badge=badge}}`, + test("badgeTypeClassName", async function (assert) { + this.set("badge", { badgeTypeClassName: "foo" }); - beforeEach() { - this.set("badge", { badgeTypeClassName: "foo" }); - }, + await render(hbs``); - async test(assert) { - assert.ok(exists(".user-badge.foo")); - }, + assert.ok(exists(".user-badge.foo")); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/badge-title-test.js b/app/assets/javascripts/discourse/tests/integration/components/badge-title-test.js index eeb07720480..6b7d194f00c 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/badge-title-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/badge-title-test.js @@ -1,46 +1,42 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import EmberObject from "@ember/object"; -import { click } from "@ember/test-helpers"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; import hbs from "htmlbars-inline-precompile"; import pretender from "discourse/tests/helpers/create-pretender"; import selectKit from "discourse/tests/helpers/select-kit-helper"; +import EmberObject from "@ember/object"; -discourseModule("Integration | Component | badge-title", function (hooks) { +module("Integration | Component | badge-title", function (hooks) { setupRenderingTest(hooks); - componentTest("badge title", { - template: hbs` - {{badge-title selectableUserBadges=selectableUserBadges}} - `, + test("badge title", async function (assert) { + this.set("subject", selectKit()); + this.set("selectableUserBadges", [ + EmberObject.create({ + id: 0, + badge: { name: "(none)" }, + }), + EmberObject.create({ + id: 42, + badge_id: 102, + badge: { name: "Test" }, + }), + ]); - beforeEach() { - this.set("subject", selectKit()); - this.set("selectableUserBadges", [ - EmberObject.create({ - id: 0, - badge: { name: "(none)" }, - }), - EmberObject.create({ - id: 42, - badge_id: 102, - badge: { name: "Test" }, - }), - ]); - }, + pretender.put("/u/eviltrout/preferences/badge_title", () => [ + 200, + { "Content-Type": "application/json" }, + {}, + ]); - async test(assert) { - pretender.put("/u/eviltrout/preferences/badge_title", () => [ - 200, - { "Content-Type": "application/json" }, - {}, - ]); - await this.subject.expand(); - await this.subject.selectRowByValue(42); - await click(".btn"); - assert.strictEqual(this.currentUser.title, "Test"); - }, + await render(hbs` + + `); + + await this.subject.expand(); + await this.subject.selectRowByValue(42); + await click(".btn"); + + assert.strictEqual(this.currentUser.title, "Test"); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/bookmark-icon-test.js b/app/assets/javascripts/discourse/tests/integration/components/bookmark-icon-test.js index ffb9832fdac..13fac3954a1 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/bookmark-icon-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/bookmark-icon-test.js @@ -1,87 +1,71 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; import Bookmark from "discourse/models/bookmark"; import I18n from "I18n"; import { formattedReminderTime } from "discourse/lib/bookmark"; import { tomorrow } from "discourse/lib/time-utils"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import hbs from "htmlbars-inline-precompile"; -import { - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; -discourseModule("Integration | Component | bookmark-icon", function (hooks) { +module("Integration | Component | bookmark-icon", function (hooks) { setupRenderingTest(hooks); - componentTest("with reminder", { - template: hbs`{{bookmark-icon bookmark=bookmark}}`, + test("with reminder", async function (assert) { + this.setProperties({ + bookmark: Bookmark.create({ + reminder_at: tomorrow(this.currentUser.timezone), + name: "some name", + }), + }); - beforeEach() { - this.setProperties({ - bookmark: Bookmark.create({ - reminder_at: tomorrow(this.currentUser.timezone), - name: "some name", - }), - }); - }, + await render(hbs``); - async test(assert) { - assert.ok( - exists(".d-icon-discourse-bookmark-clock.bookmark-icon__bookmarked") - ); - assert.strictEqual( - query(".svg-icon-title")["title"], - I18n.t("bookmarks.created_with_reminder_generic", { - date: formattedReminderTime( - this.bookmark.reminder_at, - this.currentUser.timezone - ), - name: "some name", - }) - ); - }, + assert.ok( + exists(".d-icon-discourse-bookmark-clock.bookmark-icon__bookmarked") + ); + assert.strictEqual( + query(".svg-icon-title").title, + I18n.t("bookmarks.created_with_reminder_generic", { + date: formattedReminderTime( + this.bookmark.reminder_at, + this.currentUser.timezone + ), + name: "some name", + }) + ); }); - componentTest("no reminder", { - template: hbs`{{bookmark-icon bookmark=bookmark}}`, + test("no reminder", async function (assert) { + this.set( + "bookmark", + Bookmark.create({ + name: "some name", + }) + ); - beforeEach() { - this.set( - "bookmark", - Bookmark.create({ - name: "some name", - }) - ); - }, + await render(hbs``); - async test(assert) { - assert.ok(exists(".d-icon-bookmark.bookmark-icon__bookmarked")); - assert.strictEqual( - query(".svg-icon-title")["title"], - I18n.t("bookmarks.created_generic", { - name: "some name", - }) - ); - }, + assert.ok(exists(".d-icon-bookmark.bookmark-icon__bookmarked")); + assert.strictEqual( + query(".svg-icon-title").title, + I18n.t("bookmarks.created_generic", { + name: "some name", + }) + ); }); - componentTest("null bookmark", { - template: hbs`{{bookmark-icon bookmark=bookmark}}`, + test("null bookmark", async function (assert) { + this.setProperties({ + bookmark: null, + }); - beforeEach() { - this.setProperties({ - bookmark: null, - }); - }, + await render(hbs``); - async test(assert) { - assert.ok(exists(".d-icon-bookmark.bookmark-icon")); - assert.strictEqual( - query(".svg-icon-title")["title"], - I18n.t("bookmarks.create") - ); - }, + assert.ok(exists(".d-icon-bookmark.bookmark-icon")); + assert.strictEqual( + query(".svg-icon-title").title, + I18n.t("bookmarks.create") + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/bookmark-test.js b/app/assets/javascripts/discourse/tests/integration/components/bookmark-test.js index 36fb680dfaa..171d868f97d 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/bookmark-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/bookmark-test.js @@ -1,20 +1,12 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | bookmark", function (hooks) { +module("Integration | Component | bookmark", function (hooks) { setupRenderingTest(hooks); - const template = hbs`{{bookmark - model=model - afterSave=afterSave - afterDelete=afterDelete - onCloseWithoutSaving=onCloseWithoutSaving - registerOnCloseHandler=registerOnCloseHandler - closeModal=closeModal}}`; - hooks.beforeEach(function () { this.setProperties({ model: {}, @@ -26,22 +18,27 @@ discourseModule("Integration | Component | bookmark", function (hooks) { }); }); - componentTest("prefills the custom reminder type date and time", { - template, + test("prefills the custom reminder type date and time", async function (assert) { + let name = "test"; + let reminderAt = "2020-05-15T09:45:00"; + this.model = { id: 1, name, reminderAt }; - beforeEach() { - let name = "test"; - let reminderAt = "2020-05-15T09:45:00"; - this.model = { id: 1, name, reminderAt }; - }, + await render(hbs` + + `); - test(assert) { - assert.strictEqual(query("#bookmark-name").value, "test"); - assert.strictEqual( - query("#custom-date > .date-picker").value, - "2020-05-15" - ); - assert.strictEqual(query("#custom-time").value, "09:45"); - }, + assert.strictEqual(query("#bookmark-name").value, "test"); + assert.strictEqual( + query("#custom-date > .date-picker").value, + "2020-05-15" + ); + assert.strictEqual(query("#custom-time").value, "09:45"); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/category-badge-helper-test.js b/app/assets/javascripts/discourse/tests/integration/components/category-badge-helper-test.js new file mode 100644 index 00000000000..01949976f35 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/category-badge-helper-test.js @@ -0,0 +1,33 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import Category from "discourse/models/category"; + +module("Integration | Component | category-badge helper", function (hooks) { + setupRenderingTest(hooks); + + test("displays category", async function (assert) { + this.set("category", Category.findById(1)); + + await render(hbs`{{category-badge category}}`); + + assert.strictEqual( + query(".category-name").innerText.trim(), + this.category.name + ); + }); + + test("options.link", async function (assert) { + this.set("category", Category.findById(1)); + + await render(hbs`{{category-badge category link=true}}`); + + assert.ok( + exists( + `a.badge-wrapper[href="/c/${this.category.slug}/${this.category.id}"]` + ) + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/category-badge-test.js b/app/assets/javascripts/discourse/tests/integration/components/category-badge-test.js deleted file mode 100644 index 0dfecbf6b21..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/components/category-badge-test.js +++ /dev/null @@ -1,45 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; -import Category from "discourse/models/category"; - -discourseModule("Integration | Component | category-badge", function (hooks) { - setupRenderingTest(hooks); - - componentTest("displays category", { - template: hbs`{{category-badge category}}`, - - beforeEach() { - this.set("category", Category.findById(1)); - }, - - async test(assert) { - assert.equal( - query(".category-name").innerText.trim(), - this.category.name - ); - }, - }); - - componentTest("options.link", { - template: hbs`{{category-badge category link=true}}`, - - beforeEach() { - this.set("category", Category.findById(1)); - }, - - async test(assert) { - assert.ok( - exists( - `a.badge-wrapper[href="/c/${this.category.slug}/${this.category.id}"]` - ) - ); - }, - }); -}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/cook-text-test.js b/app/assets/javascripts/discourse/tests/integration/components/cook-text-test.js index 391a4446dec..8a434358411 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/cook-text-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/cook-text-test.js @@ -1,52 +1,48 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import pretender from "discourse/tests/helpers/create-pretender"; import { resetCache } from "pretty-text/upload-short-url"; -discourseModule("Integration | Component | cook-text", function (hooks) { +module("Integration | Component | cook-text", function (hooks) { setupRenderingTest(hooks); - componentTest("renders markdown", { - template: hbs``, - - test(assert) { - const html = query(".post-body").innerHTML.trim(); - assert.strictEqual(html, "

foo

"); - }, + hooks.afterEach(function () { + resetCache(); }); - componentTest("resolves short URLs", { - template: hbs``, + test("renders markdown", async function (assert) { + await render(hbs``); - beforeEach() { - pretender.post("/uploads/lookup-urls", () => { - return [ - 200, - { "Content-Type": "application/json" }, - [ - { - short_url: "upload://a.png", - url: "/images/avatar.png", - short_path: "/images/d-logo-sketch.png", - }, - ], - ]; - }); - }, + const html = query(".post-body").innerHTML.trim(); + assert.strictEqual(html, "

foo

"); + }); - afterEach() { - resetCache(); - }, + test("resolves short URLs", async function (assert) { + pretender.post("/uploads/lookup-urls", () => { + return [ + 200, + { "Content-Type": "application/json" }, + [ + { + short_url: "upload://a.png", + url: "/images/avatar.png", + short_path: "/images/d-logo-sketch.png", + }, + ], + ]; + }); - test(assert) { - const html = query(".post-body").innerHTML.trim(); - assert.strictEqual( - html, - '

an image

' - ); - }, + await render( + hbs`` + ); + + const html = query(".post-body").innerHTML.trim(); + assert.strictEqual( + html, + '

an image

' + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/d-button-test.js b/app/assets/javascripts/discourse/tests/integration/components/d-button-test.js index 52e687148d4..e843dcb31ea 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/d-button-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/d-button-test.js @@ -1,304 +1,244 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - query, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import { triggerKeyEvent } from "@ember/test-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render, triggerKeyEvent } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; import I18n from "I18n"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | d-button", function (hooks) { +module("Integration | Component | d-button", function (hooks) { setupRenderingTest(hooks); - componentTest("icon only button", { - template: hbs`{{d-button icon="plus" tabindex="3"}}`, + test("icon only button", async function (assert) { + await render(hbs``); - test(assert) { - 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( - queryAll("button").attr("tabindex"), - "3", - "it has the tabindex" - ); - }, + 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" + ); }); - componentTest("icon and text button", { - template: hbs`{{d-button icon="plus" label="topic.create"}}`, + test("icon and text button", async function (assert) { + await render(hbs``); - test(assert) { - 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"); - }, + 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"); }); - componentTest("text only button", { - template: hbs`{{d-button label="topic.create"}}`, + test("text only button", async function (assert) { + await render(hbs``); - test(assert) { - assert.ok(exists("button.btn.btn-text"), "it has all the classes"); - assert.ok(exists("button span.d-button-label"), "it has the label"); - }, + assert.ok(exists("button.btn.btn-text"), "it has all the classes"); + assert.ok(exists("button span.d-button-label"), "it has the label"); }); - componentTest("form attribute", { - template: hbs`{{d-button form="login-form"}}`, + test("form attribute", async function (assert) { + await render(hbs``); - test(assert) { - assert.ok(exists("button[form=login-form]"), "it has the form attribute"); - }, + assert.ok(exists("button[form=login-form]"), "it has the form attribute"); }); - componentTest("link-styled button", { - template: hbs`{{d-button display="link"}}`, + test("link-styled button", async function (assert) { + await render(hbs``); - test(assert) { - assert.ok( - exists("button.btn-link:not(.btn)"), - "it has the right classes" - ); - }, + assert.ok(exists("button.btn-link:not(.btn)"), "it has the right classes"); }); - componentTest("isLoading button", { - template: hbs`{{d-button isLoading=isLoading}}`, + test("isLoading button", async function (assert) { + this.set("isLoading", true); - beforeEach() { - this.set("isLoading", true); - }, + await render(hbs``); - test(assert) { - assert.ok( - exists("button.is-loading .loading-icon"), - "it has a spinner showing" - ); - assert.ok( - exists("button[disabled]"), - "while loading the button is disabled" - ); + 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); + 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" - ); - }, + 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" + ); }); - componentTest("button without isLoading attribute", { - template: hbs`{{d-button}}`, + test("button without isLoading attribute", async function (assert) { + await render(hbs``); - test(assert) { - 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"); - }, + 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"); }); - componentTest("isLoading button explicitly set to undefined state", { - template: hbs`{{d-button isLoading=isLoading}}`, + test("isLoading button explicitly set to undefined state", async function (assert) { + this.set("isLoading"); - beforeEach() { - this.set("isLoading"); - }, + await render(hbs``); - test(assert) { - 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"); - }, + 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"); }); - componentTest("disabled button", { - template: hbs`{{d-button disabled=disabled}}`, + test("disabled button", async function (assert) { + this.set("disabled", true); - beforeEach() { - this.set("disabled", true); - }, + await render(hbs``); - test(assert) { - assert.ok(exists("button[disabled]"), "the button is disabled"); + assert.ok(exists("button[disabled]"), "the button is disabled"); - this.set("disabled", false); - - assert.ok(exists("button:not([disabled])"), "the button is enabled"); - }, + this.set("disabled", false); + assert.ok(exists("button:not([disabled])"), "the button is enabled"); }); - componentTest("aria-label", { - template: hbs`{{d-button ariaLabel=ariaLabel translatedAriaLabel=translatedAriaLabel}}`, + test("aria-label", async function (assert) { + I18n.translations[I18n.locale].js.test = { fooAriaLabel: "foo" }; - beforeEach() { - I18n.translations[I18n.locale].js.test = { fooAriaLabel: "foo" }; - }, + await render( + hbs`` + ); - test(assert) { - this.set("ariaLabel", "test.fooAriaLabel"); + this.set("ariaLabel", "test.fooAriaLabel"); - assert.strictEqual( - query("button").getAttribute("aria-label"), - I18n.t("test.fooAriaLabel") - ); + assert.strictEqual( + query("button").getAttribute("aria-label"), + I18n.t("test.fooAriaLabel") + ); - this.setProperties({ - ariaLabel: null, - translatedAriaLabel: "bar", - }); + this.setProperties({ + ariaLabel: null, + translatedAriaLabel: "bar", + }); - assert.strictEqual(query("button").getAttribute("aria-label"), "bar"); - }, + assert.strictEqual(query("button").getAttribute("aria-label"), "bar"); }); - componentTest("title", { - template: hbs`{{d-button title=title translatedTitle=translatedTitle}}`, + test("title", async function (assert) { + I18n.translations[I18n.locale].js.test = { fooTitle: "foo" }; - beforeEach() { - I18n.translations[I18n.locale].js.test = { fooTitle: "foo" }; - }, + await render( + hbs`` + ); - test(assert) { - this.set("title", "test.fooTitle"); - assert.strictEqual( - query("button").getAttribute("title"), - I18n.t("test.fooTitle") - ); + this.set("title", "test.fooTitle"); + assert.strictEqual( + query("button").getAttribute("title"), + I18n.t("test.fooTitle") + ); - this.setProperties({ - title: null, - translatedTitle: "bar", - }); + this.setProperties({ + title: null, + translatedTitle: "bar", + }); - assert.strictEqual(query("button").getAttribute("title"), "bar"); - }, + assert.strictEqual(query("button").getAttribute("title"), "bar"); }); - componentTest("label", { - template: hbs`{{d-button label=label translatedLabel=translatedLabel}}`, + test("label", async function (assert) { + I18n.translations[I18n.locale].js.test = { fooLabel: "foo" }; - beforeEach() { - I18n.translations[I18n.locale].js.test = { fooLabel: "foo" }; - }, + await render( + hbs`` + ); - test(assert) { - this.set("label", "test.fooLabel"); + this.set("label", "test.fooLabel"); - assert.strictEqual( - queryAll("button .d-button-label").text(), - I18n.t("test.fooLabel") - ); + assert.strictEqual( + query("button .d-button-label").innerText, + I18n.t("test.fooLabel") + ); - this.setProperties({ - label: null, - translatedLabel: "bar", - }); + this.setProperties({ + label: null, + translatedLabel: "bar", + }); - assert.strictEqual(queryAll("button .d-button-label").text(), "bar"); - }, + assert.strictEqual(query("button .d-button-label").innerText, "bar"); }); - componentTest("aria-expanded", { - template: hbs`{{d-button ariaExpanded=ariaExpanded}}`, + test("aria-expanded", async function (assert) { + await render(hbs``); - test(assert) { - assert.strictEqual(query("button").getAttribute("aria-expanded"), null); + assert.strictEqual(query("button").getAttribute("aria-expanded"), null); - this.set("ariaExpanded", true); - assert.strictEqual(query("button").getAttribute("aria-expanded"), "true"); + 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"), "false"); - this.set("ariaExpanded", "false"); - assert.strictEqual(query("button").getAttribute("aria-expanded"), null); + this.set("ariaExpanded", "false"); + assert.strictEqual(query("button").getAttribute("aria-expanded"), null); - this.set("ariaExpanded", "true"); - assert.strictEqual(query("button").getAttribute("aria-expanded"), null); - }, + this.set("ariaExpanded", "true"); + assert.strictEqual(query("button").getAttribute("aria-expanded"), null); }); - componentTest("aria-controls", { - template: hbs`{{d-button ariaControls=ariaControls}}`, + test("aria-controls", async function (assert) { + await render(hbs``); - test(assert) { - this.set("ariaControls", "foo-bar"); - assert.strictEqual( - query("button").getAttribute("aria-controls"), - "foo-bar" - ); - }, + this.set("ariaControls", "foo-bar"); + assert.strictEqual( + query("button").getAttribute("aria-controls"), + "foo-bar" + ); }); - componentTest("onKeyDown callback", { - template: hbs`{{d-button action=action onKeyDown=onKeyDown}}`, + test("onKeyDown callback", async function (assert) { + this.set("foo", null); + this.set("onKeyDown", () => { + this.set("foo", "bar"); + }); + this.set("action", () => { + this.set("foo", "baz"); + }); - beforeEach() { - this.set("foo", null); - this.set("onKeyDown", () => { - this.set("foo", "bar"); - }); - this.set("action", () => { - this.set("foo", "baz"); - }); - }, + await render( + hbs`` + ); - async test(assert) { - await triggerKeyEvent(".btn", "keydown", 32); + await triggerKeyEvent(".btn", "keydown", 32); + assert.strictEqual(this.foo, "bar"); - assert.strictEqual(this.foo, "bar"); - - await triggerKeyEvent(".btn", "keydown", 13); - - assert.strictEqual(this.foo, "bar"); - }, + await triggerKeyEvent(".btn", "keydown", 13); + assert.strictEqual(this.foo, "bar"); }); - componentTest("press Enter", { - template: hbs`{{d-button action=action}}`, + test("press Enter", async function (assert) { + this.set("foo", null); + this.set("action", () => { + this.set("foo", "bar"); + }); - beforeEach() { - this.set("foo", null); - this.set("action", () => { - this.set("foo", "bar"); - }); - }, + await render(hbs``); - async test(assert) { - await triggerKeyEvent(".btn", "keydown", 32); + await triggerKeyEvent(".btn", "keydown", 32); + assert.strictEqual(this.foo, null); - assert.strictEqual(this.foo, null); - - await triggerKeyEvent(".btn", "keydown", 13); - - assert.strictEqual(this.foo, "bar"); - }, + await triggerKeyEvent(".btn", "keydown", 13); + assert.strictEqual(this.foo, "bar"); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/d-editor-test.js b/app/assets/javascripts/discourse/tests/integration/components/d-editor-test.js index 0f62df37c39..51cb3aff347 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/d-editor-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/d-editor-test.js @@ -1,89 +1,81 @@ -import { click, fillIn, settled } from "@ember/test-helpers"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, fillIn, render, settled } from "@ember/test-helpers"; import { - discourseModule, + chromeTest, exists, paste, query, - queryAll, } from "discourse/tests/helpers/qunit-helpers"; import { getTextareaSelection, setTextareaSelection, } from "discourse/tests/helpers/textarea-selection-helper"; +import hbs from "htmlbars-inline-precompile"; import I18n from "I18n"; import { clearToolbarCallbacks } from "discourse/components/d-editor"; import formatTextWithSelection from "discourse/tests/helpers/d-editor-helper"; -import hbs from "htmlbars-inline-precompile"; import { next } from "@ember/runloop"; import { withPluginApi } from "discourse/lib/plugin-api"; -discourseModule("Integration | Component | d-editor", function (hooks) { +module("Integration | Component | d-editor", function (hooks) { setupRenderingTest(hooks); - componentTest("preview updates with markdown", { - template: hbs`{{d-editor value=value}}`, - - async test(assert) { - assert.ok(exists(".d-editor-button-bar")); - await fillIn(".d-editor-input", "hello **world**"); - - assert.strictEqual(this.value, "hello **world**"); - assert.strictEqual( - queryAll(".d-editor-preview").html().trim(), - "

hello world

" - ); - }, + hooks.afterEach(function () { + clearToolbarCallbacks(); }); - componentTest("links in preview are not tabbable", { - template: hbs`{{d-editor value=value}}`, + test("preview updates with markdown", async function (assert) { + await render(hbs``); - async test(assert) { - await fillIn(".d-editor-input", "[discourse](https://www.discourse.org)"); + assert.ok(exists(".d-editor-button-bar")); + await fillIn(".d-editor-input", "hello **world**"); - assert.strictEqual( - queryAll(".d-editor-preview").html().trim(), - '

discourse

' - ); - }, + assert.strictEqual(this.value, "hello **world**"); + assert.strictEqual( + query(".d-editor-preview").innerHTML.trim(), + "

hello world

" + ); }); - componentTest("preview sanitizes HTML", { - template: hbs`{{d-editor value=value}}`, + test("links in preview are not tabbable", async function (assert) { + await render(hbs``); - async test(assert) { - await fillIn(".d-editor-input", `">`); - assert.strictEqual( - queryAll(".d-editor-preview").html().trim(), - '

">

' - ); - }, + await fillIn(".d-editor-input", "[discourse](https://www.discourse.org)"); + + assert.strictEqual( + query(".d-editor-preview").innerHTML.trim(), + '

discourse

' + ); }); - componentTest("updating the value refreshes the preview", { - template: hbs`{{d-editor value=value}}`, + test("preview sanitizes HTML", async function (assert) { + await render(hbs``); - beforeEach() { - this.set("value", "evil trout"); - }, + await fillIn(".d-editor-input", `">`); + assert.strictEqual( + query(".d-editor-preview").innerHTML.trim(), + '

">

' + ); + }); - async test(assert) { - assert.strictEqual( - queryAll(".d-editor-preview").html().trim(), - "

evil trout

" - ); + test("updating the value refreshes the preview", async function (assert) { + this.set("value", "evil trout"); - this.set("value", "zogstrip"); - await settled(); + await render(hbs``); - assert.strictEqual( - queryAll(".d-editor-preview").html().trim(), - "

zogstrip

" - ); - }, + assert.strictEqual( + query(".d-editor-preview").innerHTML.trim(), + "

evil trout

" + ); + + this.set("value", "zogstrip"); + await settled(); + + assert.strictEqual( + query(".d-editor-preview").innerHTML.trim(), + "

zogstrip

" + ); }); function jumpEnd(textarea) { @@ -93,30 +85,26 @@ discourseModule("Integration | Component | d-editor", function (hooks) { } function testCase(title, testFunc) { - componentTest(title, { - template: hbs`{{d-editor value=value}}`, - beforeEach() { - this.set("value", "hello world."); - }, - async test(assert) { - const textarea = jumpEnd(query("textarea.d-editor-input")); - await testFunc.call(this, assert, textarea); - }, - skip: !navigator.userAgent.includes("Chrome"), + chromeTest(title, async function (assert) { + this.set("value", "hello world."); + + await render(hbs``); + + const textarea = jumpEnd(query("textarea.d-editor-input")); + await testFunc.call(this, assert, textarea); }); } function composerTestCase(title, testFunc) { - componentTest(title, { - template: hbs`{{d-editor value=value composerEvents=true}}`, - beforeEach() { - this.set("value", "hello world."); - }, + test(title, async function (assert) { + this.set("value", "hello world."); - async test(assert) { - const textarea = jumpEnd(query("textarea.d-editor-input")); - await testFunc.call(this, assert, textarea); - }, + await render( + hbs`` + ); + + const textarea = jumpEnd(query("textarea.d-editor-input")); + await testFunc.call(this, assert, textarea); }); } @@ -255,283 +243,271 @@ discourseModule("Integration | Component | d-editor", function (hooks) { } ); - componentTest("advanced code", { - template: hbs`{{d-editor value=value}}`, - beforeEach() { - this.siteSettings.code_formatting_style = "4-spaces-indent"; - this.set( - "value", - ` - function xyz(x, y, z) { - if (y === z) { - return true; - } + test("advanced code", async function (assert) { + this.siteSettings.code_formatting_style = "4-spaces-indent"; + this.set( + "value", + ` +function xyz(x, y, z) { + if (y === z) { + return true; } - ` - ); - }, +} +` + ); - async test(assert) { - const textarea = query("textarea.d-editor-input"); - textarea.selectionStart = 0; - textarea.selectionEnd = textarea.value.length; + await render(hbs``); - await click("button.code"); - assert.strictEqual( - this.value, - ` - function xyz(x, y, z) { - if (y === z) { - return true; - } + const textarea = query("textarea.d-editor-input"); + textarea.selectionStart = 0; + textarea.selectionEnd = textarea.value.length; + + await click("button.code"); + assert.strictEqual( + this.value, + ` + function xyz(x, y, z) { + if (y === z) { + return true; } - ` - ); - }, + } +` + ); }); - componentTest("code button", { - template: hbs`{{d-editor value=value}}`, - beforeEach() { - this.siteSettings.code_formatting_style = "4-spaces-indent"; - }, + test("code button", async function (assert) { + this.siteSettings.code_formatting_style = "4-spaces-indent"; - async test(assert) { - const textarea = jumpEnd(query("textarea.d-editor-input")); + await render(hbs``); - await click("button.code"); - assert.strictEqual(this.value, ` ${I18n.t("composer.code_text")}`); + const textarea = jumpEnd(query("textarea.d-editor-input")); - this.set("value", "first line\n\nsecond line\n\nthird line"); + await click("button.code"); + assert.strictEqual(this.value, ` ${I18n.t("composer.code_text")}`); - textarea.selectionStart = 11; - textarea.selectionEnd = 11; + this.set("value", "first line\n\nsecond line\n\nthird line"); - await click("button.code"); - assert.strictEqual( - this.value, - `first line + textarea.selectionStart = 11; + textarea.selectionEnd = 11; + + await click("button.code"); + assert.strictEqual( + this.value, + `first line ${I18n.t("composer.code_text")} second line third line` - ); + ); - this.set("value", "first line\n\nsecond line\n\nthird line"); + this.set("value", "first line\n\nsecond line\n\nthird line"); - await click("button.code"); - assert.strictEqual( - this.value, - `first line + await click("button.code"); + assert.strictEqual( + this.value, + `first line second line third line\`${I18n.t("composer.code_title")}\`` - ); - this.set("value", "first line\n\nsecond line\n\nthird line"); + ); + this.set("value", "first line\n\nsecond line\n\nthird line"); - textarea.selectionStart = 5; - textarea.selectionEnd = 5; + textarea.selectionStart = 5; + textarea.selectionEnd = 5; - await click("button.code"); - assert.strictEqual( - this.value, - `first\`${I18n.t("composer.code_title")}\` line + await click("button.code"); + assert.strictEqual( + this.value, + `first\`${I18n.t("composer.code_title")}\` line second line third line` - ); - this.set("value", "first line\n\nsecond line\n\nthird line"); + ); + this.set("value", "first line\n\nsecond line\n\nthird line"); - textarea.selectionStart = 6; - textarea.selectionEnd = 10; + textarea.selectionStart = 6; + textarea.selectionEnd = 10; - await click("button.code"); - assert.strictEqual( - this.value, - "first `line`\n\nsecond line\n\nthird line" - ); - assert.strictEqual(textarea.selectionStart, 7); - assert.strictEqual(textarea.selectionEnd, 11); + await click("button.code"); + assert.strictEqual(this.value, "first `line`\n\nsecond line\n\nthird line"); + assert.strictEqual(textarea.selectionStart, 7); + assert.strictEqual(textarea.selectionEnd, 11); - await click("button.code"); - assert.strictEqual(this.value, "first line\n\nsecond line\n\nthird line"); - assert.strictEqual(textarea.selectionStart, 6); - assert.strictEqual(textarea.selectionEnd, 10); + await click("button.code"); + assert.strictEqual(this.value, "first line\n\nsecond line\n\nthird line"); + assert.strictEqual(textarea.selectionStart, 6); + assert.strictEqual(textarea.selectionEnd, 10); - textarea.selectionStart = 0; - textarea.selectionEnd = 23; + textarea.selectionStart = 0; + textarea.selectionEnd = 23; - await click("button.code"); - assert.strictEqual( - this.value, - " first line\n\n second line\n\nthird line" - ); - assert.strictEqual(textarea.selectionStart, 0); - assert.strictEqual(textarea.selectionEnd, 31); + await click("button.code"); + assert.strictEqual( + this.value, + " first line\n\n second line\n\nthird line" + ); + assert.strictEqual(textarea.selectionStart, 0); + assert.strictEqual(textarea.selectionEnd, 31); - await click("button.code"); - assert.strictEqual(this.value, "first line\n\nsecond line\n\nthird line"); - assert.strictEqual(textarea.selectionStart, 0); - assert.strictEqual(textarea.selectionEnd, 23); - }, + await click("button.code"); + assert.strictEqual(this.value, "first line\n\nsecond line\n\nthird line"); + assert.strictEqual(textarea.selectionStart, 0); + assert.strictEqual(textarea.selectionEnd, 23); }); - componentTest("code fences", { - template: hbs`{{d-editor value=value}}`, - beforeEach() { - this.set("value", ""); - }, + test("code fences", async function (assert) { + this.set("value", ""); - async test(assert) { - const textarea = jumpEnd(query("textarea.d-editor-input")); + await render(hbs``); - await click("button.code"); - assert.strictEqual( - this.value, - `\`\`\` + const textarea = jumpEnd(query("textarea.d-editor-input")); + + await click("button.code"); + assert.strictEqual( + this.value, + `\`\`\` ${I18n.t("composer.paste_code_text")} \`\`\`` - ); + ); - assert.strictEqual(textarea.selectionStart, 4); - assert.strictEqual(textarea.selectionEnd, 27); + assert.strictEqual(textarea.selectionStart, 4); + assert.strictEqual(textarea.selectionEnd, 27); - this.set("value", "first line\nsecond line\nthird line"); + this.set("value", "first line\nsecond line\nthird line"); - textarea.selectionStart = 0; - textarea.selectionEnd = textarea.value.length; + textarea.selectionStart = 0; + textarea.selectionEnd = textarea.value.length; - await click("button.code"); + await click("button.code"); - assert.strictEqual( - this.value, - `\`\`\` + assert.strictEqual( + this.value, + `\`\`\` first line second line third line \`\`\` ` - ); + ); - assert.strictEqual(textarea.selectionStart, textarea.value.length); - assert.strictEqual(textarea.selectionEnd, textarea.value.length); + assert.strictEqual(textarea.selectionStart, textarea.value.length); + assert.strictEqual(textarea.selectionEnd, textarea.value.length); - this.set("value", "first line\nsecond line\nthird line"); + this.set("value", "first line\nsecond line\nthird line"); - textarea.selectionStart = 0; - textarea.selectionEnd = 0; + textarea.selectionStart = 0; + textarea.selectionEnd = 0; - await click("button.code"); + await click("button.code"); - assert.strictEqual( - this.value, - `\`${I18n.t("composer.code_title")}\`first line + assert.strictEqual( + this.value, + `\`${I18n.t("composer.code_title")}\`first line second line third line` - ); + ); - assert.strictEqual(textarea.selectionStart, 1); - assert.strictEqual( - textarea.selectionEnd, - I18n.t("composer.code_title").length + 1 - ); + assert.strictEqual(textarea.selectionStart, 1); + assert.strictEqual( + textarea.selectionEnd, + I18n.t("composer.code_title").length + 1 + ); - this.set("value", "first line\nsecond line\nthird line"); + this.set("value", "first line\nsecond line\nthird line"); - textarea.selectionStart = 0; - textarea.selectionEnd = 10; + textarea.selectionStart = 0; + textarea.selectionEnd = 10; - await click("button.code"); + await click("button.code"); - assert.strictEqual( - this.value, - `\`first line\` + assert.strictEqual( + this.value, + `\`first line\` second line third line` - ); + ); - assert.strictEqual(textarea.selectionStart, 1); - assert.strictEqual(textarea.selectionEnd, 11); + assert.strictEqual(textarea.selectionStart, 1); + assert.strictEqual(textarea.selectionEnd, 11); - this.set("value", "first line\nsecond line\nthird line"); + this.set("value", "first line\nsecond line\nthird line"); - textarea.selectionStart = 0; - textarea.selectionEnd = 23; + textarea.selectionStart = 0; + textarea.selectionEnd = 23; - await click("button.code"); + await click("button.code"); - assert.strictEqual( - this.value, - `\`\`\` + assert.strictEqual( + this.value, + `\`\`\` first line second line \`\`\` third line` - ); + ); - assert.strictEqual(textarea.selectionStart, 30); - assert.strictEqual(textarea.selectionEnd, 30); + assert.strictEqual(textarea.selectionStart, 30); + assert.strictEqual(textarea.selectionEnd, 30); - this.set("value", "first line\nsecond line\nthird line"); + this.set("value", "first line\nsecond line\nthird line"); - textarea.selectionStart = 6; - textarea.selectionEnd = 17; + textarea.selectionStart = 6; + textarea.selectionEnd = 17; - await click("button.code"); + await click("button.code"); - assert.strictEqual( - this.value, - `first \n\`\`\`\nline\nsecond\n\`\`\`\n line\nthird line` - ); + assert.strictEqual( + this.value, + `first \n\`\`\`\nline\nsecond\n\`\`\`\n line\nthird line` + ); - assert.strictEqual(textarea.selectionStart, 27); - assert.strictEqual(textarea.selectionEnd, 27); + assert.strictEqual(textarea.selectionStart, 27); + assert.strictEqual(textarea.selectionEnd, 27); - document.execCommand("undo"); - assert.strictEqual(this.value, "first line\nsecond line\nthird line"); - }, + document.execCommand("undo"); + assert.strictEqual(this.value, "first line\nsecond line\nthird line"); }); - componentTest("quote button - empty lines", { - template: hbs`{{d-editor value=value composerEvents=true}}`, - beforeEach() { - this.set("value", "one\n\ntwo\n\nthree"); - }, - async test(assert) { - const textarea = jumpEnd(query("textarea.d-editor-input")); + test("quote button - empty lines", async function (assert) { + this.set("value", "one\n\ntwo\n\nthree"); - textarea.selectionStart = 0; + await render( + hbs`` + ); - await click("button.blockquote"); + const textarea = jumpEnd(query("textarea.d-editor-input")); - assert.strictEqual(this.value, "> one\n> \n> two\n> \n> three"); - assert.strictEqual(textarea.selectionStart, 0); - assert.strictEqual(textarea.selectionEnd, 25); + textarea.selectionStart = 0; - await click("button.blockquote"); - assert.strictEqual(this.value, "one\n\ntwo\n\nthree"); - }, + await click("button.blockquote"); + + assert.strictEqual(this.value, "> one\n> \n> two\n> \n> three"); + assert.strictEqual(textarea.selectionStart, 0); + assert.strictEqual(textarea.selectionEnd, 25); + + await click("button.blockquote"); + assert.strictEqual(this.value, "one\n\ntwo\n\nthree"); }); - componentTest("quote button - selecting empty lines", { - template: hbs`{{d-editor value=value composerEvents=true}}`, - beforeEach() { - this.set("value", "one\n\n\n\ntwo"); - }, - async test(assert) { - const textarea = jumpEnd(query("textarea.d-editor-input")); + test("quote button - selecting empty lines", async function (assert) { + this.set("value", "one\n\n\n\ntwo"); - textarea.selectionStart = 6; - textarea.selectionEnd = 10; + await render( + hbs`` + ); - await click("button.blockquote"); - assert.strictEqual(this.value, "one\n\n\n> \n> two"); + const textarea = jumpEnd(query("textarea.d-editor-input")); - document.execCommand("undo"); - assert.strictEqual(this.value, "one\n\n\n\ntwo"); - }, + textarea.selectionStart = 6; + textarea.selectionEnd = 10; + + await click("button.blockquote"); + assert.strictEqual(this.value, "one\n\n\n> \n> two"); + + document.execCommand("undo"); + assert.strictEqual(this.value, "one\n\n\n\ntwo"); }); testCase("quote button", async function (assert, textarea) { @@ -652,33 +628,29 @@ third line` assert.strictEqual(textarea.selectionEnd, 18); }); - componentTest("clicking the toggle-direction changes dir from ltr to rtl", { - template: hbs`{{d-editor value=value}}`, - beforeEach() { - this.siteSettings.support_mixed_text_direction = true; - this.siteSettings.default_locale = "en"; - }, + test("clicking the toggle-direction changes dir from ltr to rtl", async function (assert) { + this.siteSettings.support_mixed_text_direction = true; + this.siteSettings.default_locale = "en"; - async test(assert) { - const textarea = queryAll("textarea.d-editor-input"); - await click("button.toggle-direction"); - assert.strictEqual(textarea.attr("dir"), "rtl"); - }, + await render(hbs``); + + await click("button.toggle-direction"); + assert.strictEqual( + query("textarea.d-editor-input").getAttribute("dir"), + "rtl" + ); }); - componentTest("clicking the toggle-direction changes dir from ltr to rtl", { - template: hbs`{{d-editor value=value}}`, - beforeEach() { - this.siteSettings.support_mixed_text_direction = true; - this.siteSettings.default_locale = "en"; - }, + test("clicking the toggle-direction changes dir from ltr to rtl", async function (assert) { + this.siteSettings.support_mixed_text_direction = true; + this.siteSettings.default_locale = "en"; - async test(assert) { - const textarea = queryAll("textarea.d-editor-input"); - textarea.attr("dir", "ltr"); - await click("button.toggle-direction"); - assert.strictEqual(textarea.attr("dir"), "rtl"); - }, + await render(hbs``); + + const textarea = query("textarea.d-editor-input"); + textarea.setAttribute("dir", "ltr"); + await click("button.toggle-direction"); + assert.strictEqual(textarea.getAttribute("dir"), "rtl"); }); testCase( @@ -699,54 +671,47 @@ third line` } ); - componentTest("emoji", { - template: hbs`{{d-editor value=value}}`, - beforeEach() { - // Test adding a custom button - withPluginApi("0.1", (api) => { - api.onToolbarCreate((toolbar) => { - toolbar.addButton({ - id: "emoji", - group: "extras", - icon: "far-smile", - action: () => toolbar.context.send("emoji"), - }); + test("emoji", async function (assert) { + // Test adding a custom button + withPluginApi("0.1", (api) => { + api.onToolbarCreate((toolbar) => { + toolbar.addButton({ + id: "emoji", + group: "extras", + icon: "far-smile", + action: () => toolbar.context.send("emoji"), }); }); - this.set("value", "hello world."); - }, + }); + this.set("value", "hello world."); - afterEach() { - clearToolbarCallbacks(); - }, + await render(hbs``); - async test(assert) { - jumpEnd(query("textarea.d-editor-input")); - await click("button.emoji"); + jumpEnd(query("textarea.d-editor-input")); + await click("button.emoji"); - await click( - '.emoji-picker .section[data-section="smileys_&_emotion"] img.emoji[title="grinning"]' - ); - assert.strictEqual( - this.value, - "hello world. :grinning:", - "it works when there is no partial emoji" - ); + await click( + '.emoji-picker .section[data-section="smileys_&_emotion"] img.emoji[title="grinning"]' + ); + assert.strictEqual( + this.value, + "hello world. :grinning:", + "it works when there is no partial emoji" + ); - await click("textarea.d-editor-input"); - await fillIn(".d-editor-input", "starting to type an emoji like :gri"); - jumpEnd(query("textarea.d-editor-input")); - await click("button.emoji"); + await click("textarea.d-editor-input"); + await fillIn(".d-editor-input", "starting to type an emoji like :gri"); + jumpEnd(query("textarea.d-editor-input")); + await click("button.emoji"); - await click( - '.emoji-picker .section[data-section="smileys_&_emotion"] img.emoji[title="grinning"]' - ); - assert.strictEqual( - this.value, - "starting to type an emoji like :grinning:", - "it works when there is a partial emoji" - ); - }, + await click( + '.emoji-picker .section[data-section="smileys_&_emotion"] img.emoji[title="grinning"]' + ); + assert.strictEqual( + this.value, + "starting to type an emoji like :grinning:", + "it works when there is a partial emoji" + ); }); testCase("replace-text event by default", async function (assert) { @@ -863,35 +828,33 @@ third line` } ); - componentTest("paste table", { - template: hbs`{{d-editor value=value composerEvents=true}}`, - beforeEach() { - this.set("value", ""); - this.siteSettings.enable_rich_text_paste = true; - }, + test("paste table", async function (assert) { + this.set("value", ""); + this.siteSettings.enable_rich_text_paste = true; - async test(assert) { - let element = query(".d-editor"); - await paste(element, "\ta\tb\n1\t2\t3"); - assert.strictEqual(this.value, "||a|b|\n|---|---|---|\n|1|2|3|\n"); + await render( + hbs`` + ); - document.execCommand("undo"); - assert.strictEqual(this.value, ""); - }, + let element = query(".d-editor"); + await paste(element, "\ta\tb\n1\t2\t3"); + assert.strictEqual(this.value, "||a|b|\n|---|---|---|\n|1|2|3|\n"); + + document.execCommand("undo"); + assert.strictEqual(this.value, ""); }); - componentTest("paste a different table", { - template: hbs`{{d-editor value=value composerEvents=true}}`, - beforeEach() { - this.set("value", ""); - this.siteSettings.enable_rich_text_paste = true; - }, + test("paste a different table", async function (assert) { + this.set("value", ""); + this.siteSettings.enable_rich_text_paste = true; - async test(assert) { - let element = query(".d-editor"); - await paste(element, '\ta\tb\n1\t"2\n2.5"\t3'); - assert.strictEqual(this.value, "||a|b|\n|---|---|---|\n|1|2
2.5|3|\n"); - }, + await render( + hbs`` + ); + + let element = query(".d-editor"); + await paste(element, '\ta\tb\n1\t"2\n2.5"\t3'); + assert.strictEqual(this.value, "||a|b|\n|---|---|---|\n|1|2
2.5|3|\n"); }); testCase( @@ -1066,7 +1029,7 @@ third line` await focus(textarea); - assert.ok(textarea.value === BEFORE); + assert.strictEqual(textarea.value, BEFORE); const [start, len] = CASE.before; setTextareaSelection(textarea, start, start + len); diff --git a/app/assets/javascripts/discourse/tests/integration/components/d-icon-helper-test.js b/app/assets/javascripts/discourse/tests/integration/components/d-icon-helper-test.js new file mode 100644 index 00000000000..3f98dc9c8b0 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/d-icon-helper-test.js @@ -0,0 +1,29 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; + +module("Integration | Component | d-icon helper", function (hooks) { + setupRenderingTest(hooks); + + test("default", async function (assert) { + await render(hbs`
{{d-icon "bars"}}
`); + + const html = query(".test").innerHTML.trim(); + assert.strictEqual( + html, + '' + ); + }); + + test("with replacement", async function (assert) { + await render(hbs`
{{d-icon "d-watching"}}
`); + + const html = query(".test").innerHTML.trim(); + assert.strictEqual( + html, + '' + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/d-icon-test.js b/app/assets/javascripts/discourse/tests/integration/components/d-icon-test.js deleted file mode 100644 index 38e79c121fe..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/components/d-icon-test.js +++ /dev/null @@ -1,36 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule("Integration | Component | d-icon", function (hooks) { - setupRenderingTest(hooks); - - componentTest("default", { - template: hbs`
{{d-icon "bars"}}
`, - - test(assert) { - const html = queryAll(".test").html().trim(); - assert.strictEqual( - html, - '' - ); - }, - }); - - componentTest("with replacement", { - template: hbs`
{{d-icon "d-watching"}}
`, - - test(assert) { - const html = queryAll(".test").html().trim(); - assert.strictEqual( - html, - '' - ); - }, - }); -}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/d-navigation-test.js b/app/assets/javascripts/discourse/tests/integration/components/d-navigation-test.js index 50c748c264c..af49541be0b 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/d-navigation-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/d-navigation-test.js @@ -1,11 +1,10 @@ -import { click } from "@ember/test-helpers"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { count, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | d-navigation", function (hooks) { +module("Integration | Component | d-navigation", function (hooks) { setupRenderingTest(hooks); hooks.beforeEach(function () { @@ -13,31 +12,25 @@ discourseModule("Integration | Component | d-navigation", function (hooks) { .filter((category) => !category.parent_category_id) .slice(0, 4); this.site.setProperties({ categories }); + this.currentUser.set( "indirectly_muted_category_ids", categories.slice(0, 3).map((category) => category.id) ); }); - componentTest("filters indirectly muted categories", { - template: hbs` - {{d-navigation - filterType="categories" - }} - `, + test("filters indirectly muted categories", async function (assert) { + await render(hbs``); + await click(".category-drop .select-kit-header-wrapper"); - async test(assert) { - await click(".category-drop .select-kit-header-wrapper"); - - assert.strictEqual( - document.querySelectorAll(".category-row").length, - 1, - "displays only categories that are not muted" - ); - assert.strictEqual( - query(".category-row .badge-category span").textContent.trim(), - "dev" - ); - }, + assert.strictEqual( + count(".category-row"), + 1, + "displays only categories that are not muted" + ); + assert.strictEqual( + query(".category-row .badge-category span").textContent.trim(), + "dev" + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/d-popover-test.js b/app/assets/javascripts/discourse/tests/integration/components/d-popover-test.js index 462127e418c..0b021bf724d 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/d-popover-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/d-popover-test.js @@ -1,102 +1,102 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; +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 hbs from "htmlbars-inline-precompile"; import { showPopover } from "discourse/lib/d-popover"; -import { click, triggerKeyEvent } from "@ember/test-helpers"; -discourseModule("Integration | Component | d-popover", function (hooks) { +module("Integration | Component | d-popover", function (hooks) { setupRenderingTest(hooks); - componentTest("show/hide popover from lib", { - template: hbs`{{d-button translatedLabel="test" action=onButtonClick forwardEvent=true}}`, + test("show/hide popover from lib", async function (assert) { + this.set("onButtonClick", (_, event) => { + showPopover(event, { content: "test", trigger: "click", duration: 0 }); + }); - beforeEach() { - this.set("onButtonClick", (_, event) => { - showPopover(event, { content: "test", trigger: "click", duration: 0 }); - }); - }, + await render(hbs` + + `); - async test(assert) { - assert.notOk(document.querySelector("div[data-tippy-root]")); + assert.notOk(document.querySelector("div[data-tippy-root]")); - await click(".btn"); + await click(".btn"); + assert.strictEqual( + document.querySelector("div[data-tippy-root]").innerText.trim(), + "test" + ); - assert.equal( - document.querySelector("div[data-tippy-root]").innerText.trim(), - "test" - ); - - await click(".btn"); - - assert.notOk(document.querySelector("div[data-tippy-root]")); - }, + await click(".btn"); + assert.notOk(document.querySelector("div[data-tippy-root]")); }); - componentTest("show/hide popover from component", { - template: hbs`{{#d-popover}}{{d-button class="trigger" icon="chevron-down"}}
  • foo
  • {{d-button icon="times" class="closer"}}
{{/d-popover}}`, + test("show/hide popover from component", async function (assert) { + await render(hbs` + + +
    +
  • foo
  • +
  • +
+
+ `); - async test(assert) { - assert.notOk(exists(".d-popover.is-expanded")); - assert.notOk(exists(".test")); + assert.notOk(exists(".d-popover.is-expanded")); + assert.notOk(exists(".test")); - await click(".trigger"); + await click(".trigger"); - assert.ok(exists(".d-popover.is-expanded")); - assert.equal(query(".test").innerText.trim(), "foo"); + assert.ok(exists(".d-popover.is-expanded")); + assert.strictEqual(query(".test").innerText.trim(), "foo"); - await click(".closer"); - - assert.notOk(exists(".d-popover.is-expanded")); - }, + await click(".closer"); + assert.notOk(exists(".d-popover.is-expanded")); }); - componentTest("using options with component", { - template: hbs`{{#d-popover options=(hash content="bar")}}{{d-button icon="chevron-down"}}{{/d-popover}}`, + test("using options with component", async function (assert) { + await render(hbs` + + + + `); - async test(assert) { - await click(".btn"); - - assert.equal(query(".tippy-content").innerText.trim(), "bar"); - }, + await click(".btn"); + assert.strictEqual(query(".tippy-content").innerText.trim(), "bar"); }); - componentTest("d-popover component accepts a block", { - template: hbs`{{#d-popover as |state|}}{{d-button icon=(if state.isExpanded "chevron-up" "chevron-down")}}{{/d-popover}}`, + test("d-popover component accepts a block", async function (assert) { + await render(hbs` + + + + `); - async test(assert) { - assert.ok(exists(".d-icon-chevron-down")); + assert.ok(exists(".d-icon-chevron-down")); - await click(".btn"); - - assert.ok(exists(".d-icon-chevron-up")); - }, + await click(".btn"); + assert.ok(exists(".d-icon-chevron-up")); }); - componentTest("d-popover component accepts a class property", { - template: hbs`{{#d-popover class="foo"}}{{/d-popover}}`, + test("d-popover component accepts a class property", async function (assert) { + await render(hbs``); - async test(assert) { - assert.ok(exists(".d-popover.foo")); - }, + assert.ok(exists(".d-popover.foo")); }); - componentTest("d-popover component closes on escape key", { - template: hbs`{{#d-popover as |state|}}{{d-button icon=(if state.isExpanded "chevron-up" "chevron-down")}}{{/d-popover}}`, + test("d-popover component closes on escape key", async function (assert) { + await render(hbs` + + + + `); - async test(assert) { - await click(".btn"); + await click(".btn"); + assert.ok(exists(".d-popover.is-expanded")); - assert.ok(exists(".d-popover.is-expanded")); - - await triggerKeyEvent(document, "keydown", 27); - - assert.notOk(exists(".d-popover.is-expanded")); - }, + await triggerKeyEvent(document, "keydown", 27); + assert.notOk(exists(".d-popover.is-expanded")); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/date-input-test.js b/app/assets/javascripts/discourse/tests/integration/components/date-input-test.js index b8d31362898..1238adce988 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/date-input-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/date-input-test.js @@ -1,7 +1,7 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; function dateInput() { @@ -16,50 +16,42 @@ function noop() {} const DEFAULT_DATE = moment("2019-01-29"); -discourseModule("Integration | Component | date-input", function (hooks) { +module("Integration | Component | date-input", function (hooks) { setupRenderingTest(hooks); - componentTest("default", { - template: hbs`{{date-input date=date}}`, + test("default", async function (assert) { + this.setProperties({ date: DEFAULT_DATE }); - beforeEach() { - this.setProperties({ date: DEFAULT_DATE }); - }, + await render(hbs``); - test(assert) { - assert.strictEqual(dateInput().value, "2019-01-29"); - }, + assert.strictEqual(dateInput().value, "2019-01-29"); }); - componentTest("prevents mutations", { - template: hbs`{{date-input date=date onChange=onChange}}`, + test("prevents mutations", async function (assert) { + this.setProperties({ date: DEFAULT_DATE }); + this.set("onChange", noop); - beforeEach() { - this.setProperties({ date: DEFAULT_DATE }); - this.set("onChange", noop); - }, + await render( + hbs`` + ); - async test(assert) { - dateInput().value = "2019-01-02"; - dateInput().dispatchEvent(new Event("change")); + dateInput().value = "2019-01-02"; + dateInput().dispatchEvent(new Event("change")); - assert.ok(this.date.isSame(DEFAULT_DATE)); - }, + assert.ok(this.date.isSame(DEFAULT_DATE)); }); - componentTest("allows mutations through actions", { - template: hbs`{{date-input date=date onChange=onChange}}`, + test("allows mutations through actions", async function (assert) { + this.setProperties({ date: DEFAULT_DATE }); + this.set("onChange", setDate); - beforeEach() { - this.setProperties({ date: DEFAULT_DATE }); - this.set("onChange", setDate); - }, + await render( + hbs`` + ); - async test(assert) { - dateInput().value = "2019-02-02"; - dateInput().dispatchEvent(new Event("change")); + dateInput().value = "2019-02-02"; + dateInput().dispatchEvent(new Event("change")); - assert.ok(this.date.isSame(moment("2019-02-02"))); - }, + assert.ok(this.date.isSame(moment("2019-02-02"))); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/date-time-input-range-test.js b/app/assets/javascripts/discourse/tests/integration/components/date-time-input-range-test.js index 71e23480cf6..89c1db6a2d8 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/date-time-input-range-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/date-time-input-range-test.js @@ -1,7 +1,7 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; function fromDateInput() { @@ -22,24 +22,19 @@ function toTimeInput() { const DEFAULT_DATE_TIME = moment("2019-01-29 14:45"); -discourseModule( - "Integration | Component | date-time-input-range", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | date-time-input-range", function (hooks) { + setupRenderingTest(hooks); - componentTest("default", { - template: hbs`{{date-time-input-range from=from to=to}}`, + test("default", async function (assert) { + this.setProperties({ from: DEFAULT_DATE_TIME, to: null }); - beforeEach() { - this.setProperties({ from: DEFAULT_DATE_TIME, to: null }); - }, + await render( + hbs`` + ); - test(assert) { - assert.strictEqual(fromDateInput().value, "2019-01-29"); - assert.strictEqual(fromTimeInput().dataset.name, "14:45"); - assert.strictEqual(toDateInput().value, ""); - assert.strictEqual(toTimeInput().dataset.name, "--:--"); - }, - }); - } -); + assert.strictEqual(fromDateInput().value, "2019-01-29"); + assert.strictEqual(fromTimeInput().dataset.name, "14:45"); + assert.strictEqual(toDateInput().value, ""); + assert.strictEqual(toTimeInput().dataset.name, "--:--"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/date-time-input-test.js b/app/assets/javascripts/discourse/tests/integration/components/date-time-input-test.js index 66449bc3d40..803fc3d5db4 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/date-time-input-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/date-time-input-test.js @@ -1,11 +1,7 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; function dateInput() { @@ -22,61 +18,49 @@ function setDate(date) { const DEFAULT_DATE_TIME = moment("2019-01-29 14:45"); -discourseModule("Integration | Component | date-time-input", function (hooks) { +module("Integration | Component | date-time-input", function (hooks) { setupRenderingTest(hooks); - componentTest("default", { - template: hbs`{{date-time-input date=date}}`, + test("default", async function (assert) { + this.setProperties({ date: DEFAULT_DATE_TIME }); - beforeEach() { - this.setProperties({ date: DEFAULT_DATE_TIME }); - }, + await render(hbs``); - test(assert) { - assert.strictEqual(dateInput().value, "2019-01-29"); - assert.strictEqual(timeInput().dataset.name, "14:45"); - }, + assert.strictEqual(dateInput().value, "2019-01-29"); + assert.strictEqual(timeInput().dataset.name, "14:45"); }); - componentTest("prevents mutations", { - template: hbs`{{date-time-input date=date}}`, + test("prevents mutations", async function (assert) { + this.setProperties({ date: DEFAULT_DATE_TIME }); - beforeEach() { - this.setProperties({ date: DEFAULT_DATE_TIME }); - }, + await render(hbs``); - async test(assert) { - dateInput().value = "2019-01-02"; + dateInput().value = "2019-01-02"; - assert.ok(this.date.isSame(DEFAULT_DATE_TIME)); - }, + assert.ok(this.date.isSame(DEFAULT_DATE_TIME)); }); - componentTest("allows mutations through actions", { - template: hbs`{{date-time-input date=date onChange=onChange}}`, + test("allows mutations through actions", async function (assert) { + this.setProperties({ date: DEFAULT_DATE_TIME }); + this.set("onChange", setDate); - beforeEach() { - this.setProperties({ date: DEFAULT_DATE_TIME }); - this.set("onChange", setDate); - }, + await render( + hbs`` + ); - async test(assert) { - dateInput().value = "2019-01-02"; - dateInput().dispatchEvent(new Event("change")); + dateInput().value = "2019-01-02"; + dateInput().dispatchEvent(new Event("change")); - assert.ok(this.date.isSame(moment("2019-01-02 14:45"))); - }, + assert.ok(this.date.isSame(moment("2019-01-02 14:45"))); }); - componentTest("can hide time", { - template: hbs`{{date-time-input date=date showTime=false}}`, + test("can hide time", async function (assert) { + this.setProperties({ date: DEFAULT_DATE_TIME }); - beforeEach() { - this.setProperties({ date: DEFAULT_DATE_TIME }); - }, + await render( + hbs`` + ); - async test(assert) { - assert.notOk(exists(timeInput())); - }, + assert.notOk(exists(timeInput())); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/emoji-picker-test.js b/app/assets/javascripts/discourse/tests/integration/components/emoji-picker-test.js index 6f530a82377..012f3cd2a99 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/emoji-picker-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/emoji-picker-test.js @@ -1,52 +1,43 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -import { click } from "@ember/test-helpers"; -discourseModule("Integration | Component | emoji-picker", function (hooks) { +module("Integration | Component | emoji-picker", function (hooks) { setupRenderingTest(hooks); - componentTest("when placement == bottom, places the picker on the bottom", { - template: hbs` - {{d-button class="emoji-picker-anchor" action=showEmojiPicker}} - {{emoji-picker isActive=pickerIsActive placement="bottom"}} - `, + test("when placement == bottom, places the picker on the bottom", async function (assert) { + this.set("showEmojiPicker", () => { + this.set("pickerIsActive", true); + }); - beforeEach() { - this.set("showEmojiPicker", () => { - this.set("pickerIsActive", true); - }); - }, + await render(hbs` + + + `); - async test(assert) { - await click(".emoji-picker-anchor"); - assert.equal( - query(".emoji-picker.opened").getAttribute("data-popper-placement"), - "bottom" - ); - }, + await click(".emoji-picker-anchor"); + assert.strictEqual( + query(".emoji-picker.opened").getAttribute("data-popper-placement"), + "bottom" + ); }); - componentTest("when placement == right, places the picker on the right", { - template: hbs` - {{d-button class="emoji-picker-anchor" action=showEmojiPicker}} - {{emoji-picker isActive=pickerIsActive placement="right"}} - `, + test("when placement == right, places the picker on the right", async function (assert) { + this.set("showEmojiPicker", () => { + this.set("pickerIsActive", true); + }); - beforeEach() { - this.set("showEmojiPicker", () => { - this.set("pickerIsActive", true); - }); - }, + await render(hbs` + + + `); - async test(assert) { - await click(".emoji-picker-anchor"); - assert.equal( - query(".emoji-picker.opened").getAttribute("data-popper-placement"), - "right" - ); - }, + await click(".emoji-picker-anchor"); + assert.strictEqual( + query(".emoji-picker.opened").getAttribute("data-popper-placement"), + "right" + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/emoji-uploader-test.js b/app/assets/javascripts/discourse/tests/integration/components/emoji-uploader-test.js index fbb4f5cf0d0..ddc1b00e307 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/emoji-uploader-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/emoji-uploader-test.js @@ -1,26 +1,16 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import selectKit from "discourse/tests/helpers/select-kit-helper"; -import { - createFile, - discourseModule, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { fillIn, render } from "@ember/test-helpers"; +import { createFile } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import pretender, { response } from "discourse/tests/helpers/create-pretender"; -import { fillIn } from "@ember/test-helpers"; +import selectKit from "discourse/tests/helpers/select-kit-helper"; let requestNumber; -discourseModule("Integration | Component | emoji-uploader", function (hooks) { +module("Integration | Component | emoji-uploader", function (hooks) { setupRenderingTest(hooks); - const template = hbs` {{emoji-uploader - emojiGroups=emojiGroups - done=doneUpload - id="emoji-uploader" - }}`; - hooks.beforeEach(function () { requestNumber = 0; this.setProperties({ @@ -46,84 +36,93 @@ discourseModule("Integration | Component | emoji-uploader", function (hooks) { }); }); - componentTest("uses the selected group for the upload", { - template, + test("uses the selected group for the upload", async function (assert) { + await render(hbs` + + `); - async test(assert) { - const done = assert.async(); - await selectKit("#emoji-group-selector").expand(); - await selectKit("#emoji-group-selector").selectRowByValue("cool-emojis"); + const done = assert.async(); + await selectKit("#emoji-group-selector").expand(); + await selectKit("#emoji-group-selector").selectRowByValue("cool-emojis"); - this.set("doneUpload", (upload, group) => { - assert.strictEqual("cool-emojis", group); + this.set("doneUpload", (upload, group) => { + assert.strictEqual("cool-emojis", group); + done(); + }); + const image = createFile("avatar.png"); + + await this.container + .lookup("service:app-events") + .trigger("upload-mixin:emoji-uploader:add-files", image); + }); + + test("does not clear the selected group between multiple uploads", async function (assert) { + await render(hbs` + + `); + + const done = assert.async(); + await selectKit("#emoji-group-selector").expand(); + await selectKit("#emoji-group-selector").selectRowByValue("cool-emojis"); + + let uploadDoneCount = 0; + this.set("doneUpload", (upload, group) => { + uploadDoneCount++; + assert.strictEqual("cool-emojis", group); + + if (uploadDoneCount === 2) { done(); - }); - const image = createFile("avatar.png"); - await this.container - .lookup("service:app-events") - .trigger("upload-mixin:emoji-uploader:add-files", image); - }, + } + }); + + const image = createFile("avatar.png"); + const image2 = createFile("avatar2.png"); + + await this.container + .lookup("service:app-events") + .trigger("upload-mixin:emoji-uploader:add-files", [image, image2]); }); - componentTest("does not clear the selected group between multiple uploads", { - template, + test("clears the name after the first upload to avoid duplicate names", async function (assert) { + await render(hbs` + + `); - async test(assert) { - const done = assert.async(); - await selectKit("#emoji-group-selector").expand(); - await selectKit("#emoji-group-selector").selectRowByValue("cool-emojis"); + const done = assert.async(); + await selectKit("#emoji-group-selector").expand(); + await selectKit("#emoji-group-selector").selectRowByValue("cool-emojis"); + await fillIn("#emoji-name", "okay"); - let uploadDoneCount = 0; - this.set("doneUpload", (upload, group) => { - uploadDoneCount++; - assert.strictEqual("cool-emojis", group); + let uploadDoneCount = 0; + this.set("doneUpload", (upload) => { + uploadDoneCount++; - if (uploadDoneCount === 2) { - done(); - } - }); + if (uploadDoneCount === 1) { + assert.strictEqual(upload.name, "okay"); + } - const image = createFile("avatar.png"); - const image2 = createFile("avatar2.png"); - await this.container - .lookup("service:app-events") - .trigger("upload-mixin:emoji-uploader:add-files", [image, image2]); - }, + if (uploadDoneCount === 2) { + assert.strictEqual(upload.name, null); + done(); + } + }); + + const image = createFile("avatar.png"); + const image2 = createFile("avatar2.png"); + await this.container + .lookup("service:app-events") + .trigger("upload-mixin:emoji-uploader:add-files", [image, image2]); }); - - componentTest( - "clears the name after the first upload to avoid duplicate names", - { - template, - - async test(assert) { - const done = assert.async(); - await selectKit("#emoji-group-selector").expand(); - await selectKit("#emoji-group-selector").selectRowByValue( - "cool-emojis" - ); - await fillIn("#emoji-name", "okay"); - - let uploadDoneCount = 0; - this.set("doneUpload", (upload) => { - uploadDoneCount++; - - if (uploadDoneCount === 1) { - assert.strictEqual(upload.name, "okay"); - } - - if (uploadDoneCount === 2) { - assert.strictEqual(upload.name, null); - done(); - } - }); - - const image = createFile("avatar.png"); - const image2 = createFile("avatar2.png"); - await this.container - .lookup("service:app-events") - .trigger("upload-mixin:emoji-uploader:add-files", [image, image2]); - }, - } - ); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/empty-state-test.js b/app/assets/javascripts/discourse/tests/integration/components/empty-state-test.js index 3c504caf2ba..b657e191853 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/empty-state-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/empty-state-test.js @@ -1,18 +1,16 @@ -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | empty-state", function (hooks) { +module("Integration | Component | empty-state", function (hooks) { setupRenderingTest(hooks); - componentTest("it renders", { - template: hbs``, + test("it renders", async function (assert) { + await render(hbs``); - test(assert) { - assert.strictEqual(query("[data-test-title]").textContent, "title"); - assert.strictEqual(query("[data-test-body]").textContent, "body"); - }, + assert.strictEqual(query("[data-test-title]").textContent, "title"); + assert.strictEqual(query("[data-test-body]").textContent, "body"); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/flat-button-test.js b/app/assets/javascripts/discourse/tests/integration/components/flat-button-test.js index 8b3e55aa457..7b838731014 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/flat-button-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/flat-button-test.js @@ -1,47 +1,35 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; -import { click, triggerKeyEvent } from "@ember/test-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render, triggerKeyEvent } from "@ember/test-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | flat-button", function (hooks) { +module("Integration | Component | flat-button", function (hooks) { setupRenderingTest(hooks); - componentTest("press Enter", { - template: hbs`{{flat-button action=action}}`, + test("press Enter", async function (assert) { + this.set("foo", null); + this.set("action", () => { + this.set("foo", "bar"); + }); - beforeEach() { - this.set("foo", null); - this.set("action", () => { - this.set("foo", "bar"); - }); - }, + await render(hbs``); - async test(assert) { - await triggerKeyEvent(".btn-flat", "keydown", 32); + await triggerKeyEvent(".btn-flat", "keydown", 32); + assert.strictEqual(this.foo, null); - assert.strictEqual(this.foo, null); - - await triggerKeyEvent(".btn-flat", "keydown", 13); - - assert.strictEqual(this.foo, "bar"); - }, + await triggerKeyEvent(".btn-flat", "keydown", 13); + assert.strictEqual(this.foo, "bar"); }); - componentTest("click", { - template: hbs`{{flat-button action=action}}`, - beforeEach() { - this.set("foo", null); - this.set("action", () => { - this.set("foo", "bar"); - }); - }, + test("click", async function (assert) { + this.set("foo", null); + this.set("action", () => { + this.set("foo", "bar"); + }); - async test(assert) { - await click(".btn-flat"); + await render(hbs``); - assert.strictEqual(this.foo, "bar"); - }, + await click(".btn-flat"); + assert.strictEqual(this.foo, "bar"); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/group-list-setting-test.js b/app/assets/javascripts/discourse/tests/integration/components/group-list-setting-test.js index 1aa7c22f7d4..03de1e1f605 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/group-list-setting-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/group-list-setting-test.js @@ -1,69 +1,60 @@ -import EmberObject from "@ember/object"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; - +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import selectKit from "discourse/tests/helpers/select-kit-helper"; import hbs from "htmlbars-inline-precompile"; +import EmberObject from "@ember/object"; -discourseModule( - "Integration | Component | group-list site-setting", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | group-list site-setting", function (hooks) { + setupRenderingTest(hooks); - componentTest("default", { - template: hbs`{{site-setting setting=setting}}`, - - beforeEach() { - this.site.groups = [ - { - id: 1, - name: "Donuts", - }, - { - id: 2, - name: "Cheese cake", - }, - ]; - - this.set( - "setting", - EmberObject.create({ - allowsNone: undefined, - category: "foo", - default: "", - description: "Choose groups", - overridden: false, - placeholder: null, - preview: null, - secret: false, - setting: "foo_bar", - type: "group_list", - validValues: undefined, - value: "1", - }) - ); + test("default", async function (assert) { + this.site.groups = [ + { + id: 1, + name: "Donuts", }, - - async test(assert) { - const subject = selectKit(".list-setting"); - - assert.strictEqual( - subject.header().value(), - "1", - "it selects the setting's value" - ); - - await subject.expand(); - await subject.selectRowByValue("2"); - - assert.strictEqual( - subject.header().value(), - "1,2", - "it allows to select a setting from the list of choices" - ); + { + id: 2, + name: "Cheese cake", }, - }); - } -); + ]; + + this.set( + "setting", + EmberObject.create({ + allowsNone: undefined, + category: "foo", + default: "", + description: "Choose groups", + overridden: false, + placeholder: null, + preview: null, + secret: false, + setting: "foo_bar", + type: "group_list", + validValues: undefined, + value: "1", + }) + ); + + await render(hbs``); + + const subject = selectKit(".list-setting"); + + assert.strictEqual( + subject.header().value(), + "1", + "it selects the setting's value" + ); + + await subject.expand(); + await subject.selectRowByValue("2"); + + assert.strictEqual( + subject.header().value(), + "1,2", + "it allows to select a setting from the list of choices" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/group-membership-button-test.js b/app/assets/javascripts/discourse/tests/integration/components/group-membership-button-test.js index bb3fef96e75..f29e72ac5cd 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/group-membership-button-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/group-membership-button-test.js @@ -1,88 +1,72 @@ -import { - count, - discourseModule, - exists, -} from "discourse/tests/helpers/qunit-helpers"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { count, exists } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule( - "Integration | Component | group-membership-button", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | group-membership-button", function (hooks) { + setupRenderingTest(hooks); - componentTest("canJoinGroup", { - template: hbs`{{group-membership-button model=model}}`, + test("canJoinGroup", async function (assert) { + this.set("model", { public_admission: false, is_group_user: true }); - beforeEach() { - this.set("model", { public_admission: false, is_group_user: true }); - }, + await render(hbs``); - async test(assert) { - assert.ok( - !exists(".group-index-join"), - "can't join group if public_admission is false" - ); + assert.ok( + !exists(".group-index-join"), + "can't join group if public_admission is false" + ); - this.set("model.public_admission", true); - assert.ok( - !exists(".group-index-join"), - "can't join group if user is already in the group" - ); + this.set("model.public_admission", true); + assert.ok( + !exists(".group-index-join"), + "can't join group if user is already in the group" + ); - this.set("model.is_group_user", false); - assert.ok(exists(".group-index-join"), "allowed to join group"); - }, + this.set("model.is_group_user", false); + assert.ok(exists(".group-index-join"), "allowed to join group"); + }); + + test("canLeaveGroup", async function (assert) { + this.set("model", { public_exit: false, is_group_user: false }); + + await render(hbs``); + + assert.ok( + !exists(".group-index-leave"), + "can't leave group if public_exit is false" + ); + + this.set("model.public_exit", true); + assert.ok( + !exists(".group-index-leave"), + "can't leave group if user is not in the group" + ); + + this.set("model.is_group_user", true); + assert.strictEqual( + count(".group-index-leave"), + 1, + "allowed to leave group" + ); + }); + + test("canRequestMembership", async function (assert) { + this.set("model", { + allow_membership_requests: true, + is_group_user: true, }); - componentTest("canLeaveGroup", { - template: hbs`{{group-membership-button model=model}}`, - beforeEach() { - this.set("model", { public_exit: false, is_group_user: false }); - }, - async test(assert) { - assert.ok( - !exists(".group-index-leave"), - "can't leave group if public_exit is false" - ); + await render(hbs``); - this.set("model.public_exit", true); - assert.ok( - !exists(".group-index-leave"), - "can't leave group if user is not in the group" - ); - - this.set("model.is_group_user", true); - assert.strictEqual( - count(".group-index-leave"), - 1, - "allowed to leave group" - ); - }, - }); - - componentTest("canRequestMembership", { - template: hbs`{{group-membership-button model=model}}`, - beforeEach() { - this.set("model", { - allow_membership_requests: true, - is_group_user: true, - }); - }, - - async test(assert) { - assert.ok( - !exists(".group-index-request"), - "can't request for membership if user is already in the group" - ); - this.set("model.is_group_user", false); - assert.ok( - exists(".group-index-request"), - "allowed to request for group membership" - ); - }, - }); - } -); + assert.ok( + !exists(".group-index-request"), + "can't request for membership if user is already in the group" + ); + this.set("model.is_group_user", false); + assert.ok( + exists(".group-index-request"), + "allowed to request for group membership" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/hidden-details-test.js b/app/assets/javascripts/discourse/tests/integration/components/hidden-details-test.js index 2214aa74020..3f7469260d1 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/hidden-details-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/hidden-details-test.js @@ -1,36 +1,29 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import I18n from "I18n"; -import { click } from "@ember/test-helpers"; -discourseModule("Integration | Component | hidden-details", function (hooks) { +module("Integration | Component | hidden-details", function (hooks) { setupRenderingTest(hooks); - componentTest("Shows a link and turns link into details on click", { - template: hbs`{{hidden-details label=label details=details}}`, + test("Shows a link and turns link into details on click", async function (assert) { + this.set("label", "label"); + this.set("details", "details"); - beforeEach() { - this.set("label", "label"); - this.set("details", "details"); - }, + await render( + hbs`` + ); - async test(assert) { - assert.ok(exists(".btn-link")); - assert.ok(query(".btn-link span").innerText === I18n.t("label")); - assert.notOk(exists(".description")); + assert.ok(exists(".btn-link")); + assert.strictEqual(query(".btn-link span").innerText, I18n.t("label")); + assert.notOk(exists(".description")); - await click(".btn-link"); + await click(".btn-link"); - assert.notOk(exists(".btn-link")); - assert.ok(exists(".description")); - assert.ok(query(".description").innerText === "details"); - }, + assert.notOk(exists(".btn-link")); + assert.ok(exists(".description")); + assert.strictEqual(query(".description").innerText, "details"); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/highlighted-code-test.js b/app/assets/javascripts/discourse/tests/integration/components/highlighted-code-test.js index b10cc00af74..251e9d5a07b 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/highlighted-code-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/highlighted-code-test.js @@ -1,48 +1,34 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; const LONG_CODE_BLOCK = "puts a\n".repeat(15000); -discourseModule("Integration | Component | highlighted-code", function (hooks) { +module("Integration | Component | highlighted-code", function (hooks) { setupRenderingTest(hooks); - componentTest("highlighting code", { - template: hbs`{{highlighted-code lang='ruby' code=code}}`, + test("highlighting code", async function (assert) { + this.session.highlightJsPath = + "/assets/highlightjs/highlight-test-bundle.min.js"; + this.set("code", "def test; end"); - beforeEach() { - this.session.highlightJsPath = - "/assets/highlightjs/highlight-test-bundle.min.js"; - this.set("code", "def test; end"); - }, + await render(hbs``); - test(assert) { - assert.strictEqual( - queryAll("code.ruby.hljs .hljs-function .hljs-keyword").text().trim(), - "def" - ); - }, + assert.strictEqual( + query("code.ruby.hljs .hljs-function .hljs-keyword").innerText.trim(), + "def" + ); }); - componentTest("large code blocks are not highlighted", { - template: hbs`{{highlighted-code lang='ruby' code=code}}`, + test("large code blocks are not highlighted", async function (assert) { + this.session.highlightJsPath = + "/assets/highlightjs/highlight-test-bundle.min.js"; + this.set("code", LONG_CODE_BLOCK); - beforeEach() { - this.session.highlightJsPath = - "/assets/highlightjs/highlight-test-bundle.min.js"; - this.set("code", LONG_CODE_BLOCK); - }, + await render(hbs``); - test(assert) { - assert.strictEqual( - queryAll("code").text().trim(), - LONG_CODE_BLOCK.trim() - ); - }, + assert.strictEqual(query("code").innerText.trim(), LONG_CODE_BLOCK.trim()); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/html-safe-helper-test.js b/app/assets/javascripts/discourse/tests/integration/components/html-safe-helper-test.js index 2c99c132791..83960e8f560 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/html-safe-helper-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/html-safe-helper-test.js @@ -1,21 +1,17 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, exists } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | html-safe-helper", function (hooks) { +module("Integration | Component | html-safe-helper", function (hooks) { setupRenderingTest(hooks); - componentTest("default", { - template: hbs`{{html-safe string}}`, + test("default", async function (assert) { + this.set("string", "

biscuits

"); - beforeEach() { - this.set("string", "

biscuits

"); - }, + await render(hbs`{{html-safe string}}`); - async test(assert) { - assert.ok(exists("p.cookies"), "it displays the string as html"); - }, + assert.ok(exists("p.cookies"), "it displays the string as html"); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/iframed-html-test.js b/app/assets/javascripts/discourse/tests/integration/components/iframed-html-test.js index 10809a6222e..857e11e5467 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/iframed-html-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/iframed-html-test.js @@ -1,33 +1,29 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { queryAll } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | iframed-html", function (hooks) { +module("Integration | Component | iframed-html", function (hooks) { setupRenderingTest(hooks); - componentTest("appends the html into the iframe", { - template: hbs`{{iframed-html html="

hello

" className='this-is-an-iframe'}}`, + test("appends the html into the iframe", async function (assert) { + await render( + hbs`` + ); - async test(assert) { - const iframe = queryAll("iframe.this-is-an-iframe"); - assert.strictEqual(iframe.length, 1, "inserts an iframe"); + const iframe = queryAll("iframe.this-is-an-iframe"); + assert.strictEqual(iframe.length, 1, "inserts an iframe"); - assert.ok( - iframe[0].classList.contains("this-is-an-iframe"), - "Adds className to the iframes classList" - ); + assert.ok( + iframe[0].classList.contains("this-is-an-iframe"), + "Adds className to the iframes classList" + ); - assert.strictEqual( - iframe[0].contentWindow.document.body.querySelectorAll("#find-me") - .length, - 1, - "inserts the passed in html into the iframe" - ); - }, + assert.strictEqual( + iframe[0].contentWindow.document.body.querySelectorAll("#find-me").length, + 1, + "inserts the passed in html into the iframe" + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/input-size-test.js b/app/assets/javascripts/discourse/tests/integration/components/input-size-test.js index e1c6aa7afa7..37d2c5ab85c 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/input-size-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/input-size-test.js @@ -1,19 +1,22 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; - -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; +import { module } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { chromeTest, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule( +module( "Integration | Component | consistent input/dropdown/button sizes", function (hooks) { setupRenderingTest(hooks); - componentTest("icon only button, icon and text button, text only button", { - template: hbs`{{d-button icon="plus"}} {{d-button icon="plus" label="topic.create"}} {{d-button label="topic.create"}}`, + // these tests fail on Firefox 78 in CI, skipping for now + chromeTest( + "icon only button, icon and text button, text only button", + async function (assert) { + await render( + hbs` ` + ); - test(assert) { assert.strictEqual( query(".btn:nth-child(1)").offsetHeight, query(".btn:nth-child(2)").offsetHeight, @@ -24,37 +27,31 @@ discourseModule( query(".btn:nth-child(3)").offsetHeight, "have equal height" ); - }, - // these tests fail on Firefox 78 in CI, skipping for now - skip: !navigator.userAgent.includes("Chrome"), + } + ); + + chromeTest("button + text input", async function (assert) { + await render( + hbs` ` + ); + + assert.strictEqual( + query("input").offsetHeight, + query(".btn").offsetHeight, + "have equal height" + ); }); - componentTest("button + text input", { - template: hbs`{{text-field}} {{d-button icon="plus" label="topic.create"}}`, + chromeTest("combo box + input", async function (assert) { + await render( + hbs` ` + ); - test(assert) { - assert.strictEqual( - query("input").offsetHeight, - query(".btn").offsetHeight, - "have equal height" - ); - }, - - skip: !navigator.userAgent.includes("Chrome"), - }); - - componentTest("combo box + input", { - template: hbs`{{combo-box options=(hash none="category.none")}} {{text-field}}`, - - test(assert) { - assert.strictEqual( - query("input").offsetHeight, - query(".combo-box").offsetHeight, - "have equal height" - ); - }, - - skip: !navigator.userAgent.includes("Chrome"), + assert.strictEqual( + query("input").offsetHeight, + query(".combo-box").offsetHeight, + "have equal height" + ); }); } ); diff --git a/app/assets/javascripts/discourse/tests/integration/components/invite-panel-test.js b/app/assets/javascripts/discourse/tests/integration/components/invite-panel-test.js index e9bee7f8fc4..59c3a091db7 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/invite-panel-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/invite-panel-test.js @@ -1,57 +1,48 @@ -import { set } from "@ember/object"; -import { click } from "@ember/test-helpers"; -import User from "discourse/models/user"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import pretender from "discourse/tests/helpers/create-pretender"; -import { - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; -import selectKit from "discourse/tests/helpers/select-kit-helper"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; +import pretender from "discourse/tests/helpers/create-pretender"; +import selectKit from "discourse/tests/helpers/select-kit-helper"; +import User from "discourse/models/user"; -discourseModule("Integration | Component | invite-panel", function (hooks) { +module("Integration | Component | invite-panel", function (hooks) { setupRenderingTest(hooks); - componentTest("shows the invite link after it is generated", { - template: hbs`{{invite-panel panel=panel}}`, + test("shows the invite link after it is generated", async function (assert) { + pretender.get("/u/search/users", () => { + return [200, { "Content-Type": "application/json" }, { users: [] }]; + }); - beforeEach() { - pretender.get("/u/search/users", () => { - return [200, { "Content-Type": "application/json" }, { users: [] }]; - }); + pretender.post("/invites", () => { + return [ + 200, + { "Content-Type": "application/json" }, + { + link: "http://example.com/invites/92c297e886a0ca03089a109ccd6be155", + }, + ]; + }); - pretender.post("/invites", () => { - return [ - 200, - { "Content-Type": "application/json" }, - { - link: "http://example.com/invites/92c297e886a0ca03089a109ccd6be155", - }, - ]; - }); + this.currentUser.set("details", { can_invite_via_email: true }); + this.set("panel", { + id: "invite", + model: { inviteModel: User.create(this.currentUser) }, + }); - set(this.currentUser, "details", { can_invite_via_email: true }); - this.set("panel", { - id: "invite", - model: { inviteModel: User.create(this.currentUser) }, - }); - }, + await render(hbs``); - async test(assert) { - const input = selectKit(".invite-user-input"); - await input.expand(); - await input.fillInFilter("eviltrout@example.com"); - await input.selectRowByValue("eviltrout@example.com"); - assert.ok(!exists(".send-invite:disabled")); - await click(".generate-invite-link"); - assert.strictEqual( - query(".invite-link-input").value, - "http://example.com/invites/92c297e886a0ca03089a109ccd6be155" - ); - }, + const input = selectKit(".invite-user-input"); + await input.expand(); + await input.fillInFilter("eviltrout@example.com"); + await input.selectRowByValue("eviltrout@example.com"); + assert.ok(!exists(".send-invite:disabled")); + + await click(".generate-invite-link"); + assert.strictEqual( + query(".invite-link-input").value, + "http://example.com/invites/92c297e886a0ca03089a109ccd6be155" + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/load-more-test.js b/app/assets/javascripts/discourse/tests/integration/components/load-more-test.js index 9ff074d046b..3dff04df1af 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/load-more-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/load-more-test.js @@ -1,34 +1,32 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import { configureEyeline } from "discourse/lib/eyeline"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | load-more", function (hooks) { +module("Integration | Component | load-more", function (hooks) { setupRenderingTest(hooks); - componentTest("updates once after initialization", { - template: hbs` - {{#load-more selector=".numbers tr" action=loadMore}} + hooks.beforeEach(function () { + configureEyeline({ + skipUpdate: false, + rootElement: "#ember-testing", + }); + }); + + hooks.afterEach(function () { + configureEyeline(); + }); + + test("updates once after initialization", async function (assert) { + this.set("loadMore", () => this.set("loadedMore", true)); + + await render(hbs` +
- {{/load-more}} - `, +
+ `); - beforeEach() { - this.set("loadMore", () => this.set("loadedMore", true)); - configureEyeline({ - skipUpdate: false, - rootElement: "#ember-testing", - }); - }, - - afterEach() { - configureEyeline(); - }, - - test(assert) { - assert.ok(this.loadedMore); - }, + assert.ok(this.loadedMore); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/pending-post-test.js b/app/assets/javascripts/discourse/tests/integration/components/pending-post-test.js index 85be0e9dffd..2eb61d5b097 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/pending-post-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/pending-post-test.js @@ -1,35 +1,31 @@ -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import createStore from "discourse/tests/helpers/create-store"; -discourseModule("Integration | Component | pending-post", function (hooks) { +module("Integration | Component | pending-post", function (hooks) { setupRenderingTest(hooks); - componentTest("it renders", { - template: hbs``, + test("it renders", async function (assert) { + const store = createStore(); + store.createRecord("category", { id: 2 }); + const post = store.createRecord("pending-post", { + id: 1, + topic_url: "topic-url", + username: "USERNAME", + category_id: 2, + raw_text: "**bold text**", + }); + this.set("post", post); - beforeEach() { - const store = createStore(); - store.createRecord("category", { id: 2 }); - const post = store.createRecord("pending-post", { - id: 1, - topic_url: "topic-url", - username: "USERNAME", - category_id: 2, - raw_text: "**bold text**", - }); - this.set("post", post); - }, + await render(hbs``); - test(assert) { - assert.strictEqual( - query("p.excerpt").textContent.trim(), - "bold text", - "renders the cooked text" - ); - }, + assert.strictEqual( + query("p.excerpt").textContent.trim(), + "bold text", + "renders the cooked text" + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/relative-time-picker-test.js b/app/assets/javascripts/discourse/tests/integration/components/relative-time-picker-test.js index 3176aa8659c..8cb17c76857 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/relative-time-picker-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/relative-time-picker-test.js @@ -1,120 +1,94 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; -discourseModule( - "Integration | Component | relative-time-picker", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | relative-time-picker", function (hooks) { + setupRenderingTest(hooks); - hooks.beforeEach(function () { - this.set("subject", selectKit()); - }); + hooks.beforeEach(function () { + this.set("subject", selectKit()); + }); - componentTest("prefills and preselects minutes", { - template: hbs`{{relative-time-picker durationMinutes="5"}}`, + test("prefills and preselects minutes", async function (assert) { + await render(hbs``); - test(assert) { - const prefilledDuration = query(".relative-time-duration").value; - assert.strictEqual(this.subject.header().value(), "mins"); - assert.strictEqual(prefilledDuration, "5"); - }, - }); + const prefilledDuration = query(".relative-time-duration").value; + assert.strictEqual(this.subject.header().value(), "mins"); + assert.strictEqual(prefilledDuration, "5"); + }); - componentTest("prefills and preselects hours based on translated minutes", { - template: hbs`{{relative-time-picker durationMinutes="90"}}`, + test("prefills and preselects hours based on translated minutes", async function (assert) { + await render(hbs``); - test(assert) { - const prefilledDuration = query(".relative-time-duration").value; - assert.strictEqual(this.subject.header().value(), "hours"); - assert.strictEqual(prefilledDuration, "1.5"); - }, - }); + const prefilledDuration = query(".relative-time-duration").value; + assert.strictEqual(this.subject.header().value(), "hours"); + assert.strictEqual(prefilledDuration, "1.5"); + }); - componentTest("prefills and preselects days based on translated minutes", { - template: hbs`{{relative-time-picker durationMinutes="2880"}}`, + test("prefills and preselects days based on translated minutes", async function (assert) { + await render(hbs``); - test(assert) { - const prefilledDuration = query(".relative-time-duration").value; - assert.strictEqual(this.subject.header().value(), "days"); - assert.strictEqual(prefilledDuration, "2"); - }, - }); + const prefilledDuration = query(".relative-time-duration").value; + assert.strictEqual(this.subject.header().value(), "days"); + assert.strictEqual(prefilledDuration, "2"); + }); - componentTest( - "prefills and preselects months based on translated minutes", - { - template: hbs`{{relative-time-picker durationMinutes="129600"}}`, + test("prefills and preselects months based on translated minutes", async function (assert) { + await render(hbs``); - test(assert) { - const prefilledDuration = query(".relative-time-duration").value; - assert.strictEqual(this.subject.header().value(), "months"); - assert.strictEqual(prefilledDuration, "3"); - }, - } - ); + const prefilledDuration = query(".relative-time-duration").value; + assert.strictEqual(this.subject.header().value(), "months"); + assert.strictEqual(prefilledDuration, "3"); + }); - componentTest("prefills and preselects years based on translated minutes", { - template: hbs`{{relative-time-picker durationMinutes="525600"}}`, + test("prefills and preselects years based on translated minutes", async function (assert) { + await render(hbs``); - test(assert) { - const prefilledDuration = query(".relative-time-duration").value; - assert.strictEqual(this.subject.header().value(), "years"); - assert.strictEqual(prefilledDuration, "1"); - }, - }); + const prefilledDuration = query(".relative-time-duration").value; + assert.strictEqual(this.subject.header().value(), "years"); + assert.strictEqual(prefilledDuration, "1"); + }); - componentTest("prefills and preselects hours", { - template: hbs`{{relative-time-picker durationHours="5"}}`, + test("prefills and preselects hours", async function (assert) { + await render(hbs``); - test(assert) { - const prefilledDuration = query(".relative-time-duration").value; - assert.strictEqual(this.subject.header().value(), "hours"); - assert.strictEqual(prefilledDuration, "5"); - }, - }); + const prefilledDuration = query(".relative-time-duration").value; + assert.strictEqual(this.subject.header().value(), "hours"); + assert.strictEqual(prefilledDuration, "5"); + }); - componentTest("prefills and preselects minutes based on translated hours", { - template: hbs`{{relative-time-picker durationHours="0.5"}}`, + test("prefills and preselects minutes based on translated hours", async function (assert) { + await render(hbs``); - test(assert) { - const prefilledDuration = query(".relative-time-duration").value; - assert.strictEqual(this.subject.header().value(), "mins"); - assert.strictEqual(prefilledDuration, "30"); - }, - }); + const prefilledDuration = query(".relative-time-duration").value; + assert.strictEqual(this.subject.header().value(), "mins"); + assert.strictEqual(prefilledDuration, "30"); + }); - componentTest("prefills and preselects days based on translated hours", { - template: hbs`{{relative-time-picker durationHours="48"}}`, + test("prefills and preselects days based on translated hours", async function (assert) { + await render(hbs``); - test(assert) { - const prefilledDuration = query(".relative-time-duration").value; - assert.strictEqual(this.subject.header().value(), "days"); - assert.strictEqual(prefilledDuration, "2"); - }, - }); + const prefilledDuration = query(".relative-time-duration").value; + assert.strictEqual(this.subject.header().value(), "days"); + assert.strictEqual(prefilledDuration, "2"); + }); - componentTest("prefills and preselects months based on translated hours", { - template: hbs`{{relative-time-picker durationHours="2160"}}`, + test("prefills and preselects months based on translated hours", async function (assert) { + await render(hbs``); - test(assert) { - const prefilledDuration = query(".relative-time-duration").value; - assert.strictEqual(this.subject.header().value(), "months"); - assert.strictEqual(prefilledDuration, "3"); - }, - }); + const prefilledDuration = query(".relative-time-duration").value; + assert.strictEqual(this.subject.header().value(), "months"); + assert.strictEqual(prefilledDuration, "3"); + }); - componentTest("prefills and preselects years based on translated hours", { - template: hbs`{{relative-time-picker durationHours="17520"}}`, + test("prefills and preselects years based on translated hours", async function (assert) { + await render(hbs``); - test(assert) { - const prefilledDuration = query(".relative-time-duration").value; - assert.strictEqual(this.subject.header().value(), "years"); - assert.strictEqual(prefilledDuration, "2"); - }, - }); - } -); + const prefilledDuration = query(".relative-time-duration").value; + assert.strictEqual(this.subject.header().value(), "years"); + assert.strictEqual(prefilledDuration, "2"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/secret-value-list-test.js b/app/assets/javascripts/discourse/tests/integration/components/secret-value-list-test.js index 32f3bd17ebe..c58ba5ccfae 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/secret-value-list-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/secret-value-list-test.js @@ -1,151 +1,130 @@ -import { blur, click, fillIn } from "@ember/test-helpers"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, - query, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { blur, click, fillIn, render } from "@ember/test-helpers"; +import { count, exists, query } from "discourse/tests/helpers/qunit-helpers"; import I18n from "I18n"; import hbs from "htmlbars-inline-precompile"; -discourseModule( - "Integration | Component | secret-value-list", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | secret-value-list", function (hooks) { + setupRenderingTest(hooks); - componentTest("adding a value", { - template: hbs`{{secret-value-list values=values}}`, + test("adding a value", async function (assert) { + await render(hbs``); - async test(assert) { - this.set("values", "firstKey|FirstValue\nsecondKey|secondValue"); + this.set("values", "firstKey|FirstValue\nsecondKey|secondValue"); - await fillIn(".new-value-input.key", "thirdKey"); - await click(".add-value-btn"); + await fillIn(".new-value-input.key", "thirdKey"); + await click(".add-value-btn"); - assert.strictEqual( - count(".values .value"), - 2, - "it doesn't add the value to the list if secret is missing" - ); + assert.strictEqual( + count(".values .value"), + 2, + "it doesn't add the value to the list if secret is missing" + ); - await fillIn(".new-value-input.key", ""); - await fillIn(".new-value-input.secret", "thirdValue"); - await click(".add-value-btn"); + await fillIn(".new-value-input.key", ""); + await fillIn(".new-value-input.secret", "thirdValue"); + await click(".add-value-btn"); - assert.strictEqual( - count(".values .value"), - 2, - "it doesn't add the value to the list if key is missing" - ); + assert.strictEqual( + count(".values .value"), + 2, + "it doesn't add the value to the list if key is missing" + ); - await fillIn(".new-value-input.key", "thirdKey"); - await fillIn(".new-value-input.secret", "thirdValue"); - await click(".add-value-btn"); + await fillIn(".new-value-input.key", "thirdKey"); + await fillIn(".new-value-input.secret", "thirdValue"); + await click(".add-value-btn"); - assert.strictEqual( - count(".values .value"), - 3, - "it adds the value to the list of values" - ); + assert.strictEqual( + count(".values .value"), + 3, + "it adds the value to the list of values" + ); - assert.deepEqual( - this.values, - "firstKey|FirstValue\nsecondKey|secondValue\nthirdKey|thirdValue", - "it adds the value to the list of values" - ); - }, - }); + assert.deepEqual( + this.values, + "firstKey|FirstValue\nsecondKey|secondValue\nthirdKey|thirdValue", + "it adds the value to the list of values" + ); + }); - componentTest("adding an invalid value", { - template: hbs`{{secret-value-list values=values}}`, + test("adding an invalid value", async function (assert) { + await render(hbs``); - async test(assert) { - await fillIn(".new-value-input.key", "someString"); - await fillIn(".new-value-input.secret", "keyWithAPipe|Hidden"); - await click(".add-value-btn"); + await fillIn(".new-value-input.key", "someString"); + await fillIn(".new-value-input.secret", "keyWithAPipe|Hidden"); + await click(".add-value-btn"); - assert.ok( - !exists(".values .value"), - "it doesn't add the value to the list of values" - ); + assert.ok( + !exists(".values .value"), + "it doesn't add the value to the list of values" + ); - assert.deepEqual( - this.values, - undefined, - "it doesn't add the value to the list of values" - ); + assert.deepEqual( + this.values, + undefined, + "it doesn't add the value to the list of values" + ); - assert.ok( - queryAll(".validation-error") - .html() - .indexOf(I18n.t("admin.site_settings.secret_list.invalid_input")) > - -1, - "it shows validation error" - ); - }, - }); + assert.ok( + query(".validation-error").innerText.includes( + I18n.t("admin.site_settings.secret_list.invalid_input") + ), + "it shows validation error" + ); + }); - componentTest("changing a value", { - template: hbs`{{secret-value-list values=values}}`, + test("changing a value", async function (assert) { + await render(hbs``); - async test(assert) { - this.set("values", "firstKey|FirstValue\nsecondKey|secondValue"); + this.set("values", "firstKey|FirstValue\nsecondKey|secondValue"); - await fillIn( - ".values .value[data-index='1'] .value-input:first-of-type", - "changedKey" - ); - await blur(".values .value[data-index='1'] .value-input:first-of-type"); + await fillIn( + ".values .value[data-index='1'] .value-input:first-of-type", + "changedKey" + ); + await blur(".values .value[data-index='1'] .value-input:first-of-type"); - assert.strictEqual( - query(".values .value[data-index='1'] .value-input:first-of-type") - .value, - "changedKey" - ); + assert.strictEqual( + query(".values .value[data-index='1'] .value-input:first-of-type").value, + "changedKey" + ); - await fillIn( - ".values .value[data-index='1'] .value-input:last-of-type", - "changedValue" - ); - await blur(".values .value[data-index='1'] .value-input:last-of-type"); + await fillIn( + ".values .value[data-index='1'] .value-input:last-of-type", + "changedValue" + ); + await blur(".values .value[data-index='1'] .value-input:last-of-type"); - assert.strictEqual( - query(".values .value[data-index='1'] .value-input:last-of-type") - .value, - "changedValue" - ); - assert.deepEqual( - this.values, - "firstKey|FirstValue\nchangedKey|changedValue", - "updates the value list" - ); - }, - }); + assert.strictEqual( + query(".values .value[data-index='1'] .value-input:last-of-type").value, + "changedValue" + ); + assert.deepEqual( + this.values, + "firstKey|FirstValue\nchangedKey|changedValue", + "updates the value list" + ); + }); - componentTest("removing a value", { - template: hbs`{{secret-value-list values=values}}`, + test("removing a value", async function (assert) { + await render(hbs``); - async test(assert) { - this.set("values", "firstKey|FirstValue\nsecondKey|secondValue"); + this.set("values", "firstKey|FirstValue\nsecondKey|secondValue"); - await click(".values .value[data-index='0'] .remove-value-btn"); + await click(".values .value[data-index='0'] .remove-value-btn"); - assert.strictEqual( - count(".values .value"), - 1, - "it removes the value from the list of values" - ); + assert.strictEqual( + count(".values .value"), + 1, + "it removes the value from the list of values" + ); - assert.strictEqual( - this.values, - "secondKey|secondValue", - "it removes the expected value" - ); - }, - }); - } -); + assert.strictEqual( + this.values, + "secondKey|secondValue", + "it removes the expected value" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/api-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/api-test.js index 41e63a1718d..5523c650ec3 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/api-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/api-test.js @@ -1,10 +1,7 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; import selectKit, { DEFAULT_CONTENT, setDefaultState, @@ -13,12 +10,11 @@ import { clearCallbacks } from "select-kit/mixins/plugin-api"; import hbs from "htmlbars-inline-precompile"; import { withPluginApi } from "discourse/lib/plugin-api"; -discourseModule("Integration | Component | select-kit:api", function (hooks) { +module("Integration | Component | select-kit/api", function (hooks) { setupRenderingTest(hooks); hooks.beforeEach(function () { this.setProperties({ - // subject: selectKit(); comboBox: selectKit(".combo-box"), singleSelect: selectKit(".single-select:not(.combo-box)"), }); @@ -28,97 +24,82 @@ discourseModule("Integration | Component | select-kit:api", function (hooks) { clearCallbacks(); }); - componentTest("modifySelectKit(identifier).appendContent", { - template: hbs` - {{combo-box value=value content=content onChange=onChange}} - {{single-select value=value content=content onChange=onChange}} - `, + test("modifySelectKit(identifier).appendContent", async function (assert) { + setDefaultState(this, null, { content: DEFAULT_CONTENT }); - beforeEach() { - setDefaultState(this, null, { content: DEFAULT_CONTENT }); - - withPluginApi("0.8.43", (api) => { - api.modifySelectKit("combo-box").appendContent(() => { - return { - id: "alpaca", - name: "Alpaca", - }; - }); - api.modifySelectKit("combo-box").appendContent(() => {}); + withPluginApi("0.8.43", (api) => { + api.modifySelectKit("combo-box").appendContent(() => { + return { + id: "alpaca", + name: "Alpaca", + }; }); - }, + api.modifySelectKit("combo-box").appendContent(() => {}); + }); - async test(assert) { - await this.comboBox.expand(); + await render(hbs` + + + `); + await this.comboBox.expand(); - assert.strictEqual(this.comboBox.rows().length, 4); + assert.strictEqual(this.comboBox.rows().length, 4); - const appendedRow = this.comboBox.rowByIndex(3); - assert.ok(appendedRow.exists()); - assert.strictEqual(appendedRow.value(), "alpaca"); + const appendedRow = this.comboBox.rowByIndex(3); + assert.ok(appendedRow.exists()); + assert.strictEqual(appendedRow.value(), "alpaca"); - await this.comboBox.collapse(); + await this.comboBox.collapse(); - assert.notOk(this.singleSelect.rowByValue("alpaca").exists()); - }, + assert.notOk(this.singleSelect.rowByValue("alpaca").exists()); }); - componentTest("modifySelectKit(identifier).prependContent", { - template: hbs` - {{combo-box value=value content=content onChange=onChange}} - {{single-select value=value content=content onChange=onChange}} - `, + test("modifySelectKit(identifier).prependContent", async function (assert) { + setDefaultState(this, null, { content: DEFAULT_CONTENT }); - beforeEach() { - setDefaultState(this, null, { content: DEFAULT_CONTENT }); - - withPluginApi("0.8.43", (api) => { - api.modifySelectKit("combo-box").prependContent(() => { - return { - id: "alpaca", - name: "Alpaca", - }; - }); - api.modifySelectKit("combo-box").prependContent(() => {}); + withPluginApi("0.8.43", (api) => { + api.modifySelectKit("combo-box").prependContent(() => { + return { + id: "alpaca", + name: "Alpaca", + }; }); - }, + api.modifySelectKit("combo-box").prependContent(() => {}); + }); - async test(assert) { - await this.comboBox.expand(); + await render(hbs` + + + `); + await this.comboBox.expand(); - assert.strictEqual(this.comboBox.rows().length, 4); + assert.strictEqual(this.comboBox.rows().length, 4); - const prependedRow = this.comboBox.rowByIndex(0); - assert.ok(prependedRow.exists()); - assert.strictEqual(prependedRow.value(), "alpaca"); + const prependedRow = this.comboBox.rowByIndex(0); + assert.ok(prependedRow.exists()); + assert.strictEqual(prependedRow.value(), "alpaca"); - await this.comboBox.collapse(); + await this.comboBox.collapse(); - assert.notOk(this.singleSelect.rowByValue("alpaca").exists()); - }, + assert.notOk(this.singleSelect.rowByValue("alpaca").exists()); }); - componentTest("modifySelectKit(identifier).onChange", { - template: hbs` + test("modifySelectKit(identifier).onChange", async function (assert) { + setDefaultState(this, null, { content: DEFAULT_CONTENT }); + + withPluginApi("0.8.43", (api) => { + api.modifySelectKit("combo-box").onChange((component, value, item) => { + query("#test").innerText = item.name; + }); + }); + + await render(hbs`
- {{combo-box value=value content=content onChange=onChange}} - `, + + `); + await this.comboBox.expand(); + await this.comboBox.selectRowByIndex(0); - beforeEach() { - setDefaultState(this, null, { content: DEFAULT_CONTENT }); - - withPluginApi("0.8.43", (api) => { - api.modifySelectKit("combo-box").onChange((component, value, item) => { - queryAll("#test").text(item.name); - }); - }); - }, - - async test(assert) { - await this.comboBox.expand(); - await this.comboBox.selectRowByIndex(0); - - assert.strictEqual(queryAll("#test").text(), "foo"); - }, + assert.strictEqual(query("#test").innerText, "foo"); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/category-chooser-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/category-chooser-test.js index 75d9e005a3f..ea76287b5a5 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/category-chooser-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/category-chooser-test.js @@ -1,13 +1,12 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import I18n from "I18n"; import createStore from "discourse/tests/helpers/create-store"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; -discourseModule( +module( "Integration | Component | select-kit/category-chooser", function (hooks) { setupRenderingTest(hooks); @@ -16,309 +15,265 @@ discourseModule( this.set("subject", selectKit()); }); - componentTest("with value", { - template: hbs` - {{category-chooser - value=value - }} - `, + test("with value", async function (assert) { + this.set("value", 2); - beforeEach() { - this.set("value", 2); - }, + await render(hbs` + + `); - async test(assert) { - assert.strictEqual(this.subject.header().value(), "2"); - assert.strictEqual(this.subject.header().label(), "feature"); - }, + assert.strictEqual(this.subject.header().value(), "2"); + assert.strictEqual(this.subject.header().label(), "feature"); }); - componentTest("with excludeCategoryId", { - template: hbs` - {{category-chooser - value=value - options=(hash + test("with excludeCategoryId", async function (assert) { + await render(hbs` + + `); - async test(assert) { - await this.subject.expand(); + await this.subject.expand(); - assert.notOk(this.subject.rowByValue(2).exists()); - }, + assert.notOk(this.subject.rowByValue(2).exists()); }); - componentTest("with scopedCategoryId", { - template: hbs` - {{category-chooser - value=value - options=(hash + test("with scopedCategoryId", async function (assert) { + await render(hbs` + + `); - async test(assert) { - await this.subject.expand(); + await this.subject.expand(); - assert.strictEqual(this.subject.rowByIndex(0).title(), "feature"); - assert.strictEqual(this.subject.rowByIndex(0).value(), "2"); - assert.strictEqual(this.subject.rowByIndex(1).title(), "spec"); - assert.strictEqual(this.subject.rowByIndex(1).value(), "26"); - assert.strictEqual( - this.subject.rows().length, - 2, - "default content is scoped" - ); + assert.strictEqual(this.subject.rowByIndex(0).title(), "feature"); + assert.strictEqual(this.subject.rowByIndex(0).value(), "2"); + assert.strictEqual(this.subject.rowByIndex(1).title(), "spec"); + assert.strictEqual(this.subject.rowByIndex(1).value(), "26"); + assert.strictEqual( + this.subject.rows().length, + 2, + "default content is scoped" + ); - await this.subject.fillInFilter("bug"); + await this.subject.fillInFilter("bug"); - assert.strictEqual( - this.subject.rowByIndex(0).name(), - "bug", - "search finds outside of scope" - ); - }, + assert.strictEqual( + this.subject.rowByIndex(0).name(), + "bug", + "search finds outside of scope" + ); }); - componentTest("with prioritizedCategoryId", { - template: hbs` - {{category-chooser - value=value - options=(hash + test("with prioritizedCategoryId", async function (assert) { + await render(hbs` + + `); - async test(assert) { - await this.subject.expand(); + await this.subject.expand(); - // The prioritized category - assert.strictEqual(this.subject.rowByIndex(0).value(), "5"); - // The prioritized category's child - assert.strictEqual(this.subject.rowByIndex(1).value(), "22"); - // Other categories in the default order - assert.strictEqual(this.subject.rowByIndex(2).value(), "6"); - assert.strictEqual(this.subject.rowByIndex(3).value(), "21"); - assert.strictEqual(this.subject.rowByIndex(4).value(), "1"); + // The prioritized category + assert.strictEqual(this.subject.rowByIndex(0).value(), "5"); + // The prioritized category's child + assert.strictEqual(this.subject.rowByIndex(1).value(), "22"); + // Other categories in the default order + assert.strictEqual(this.subject.rowByIndex(2).value(), "6"); + assert.strictEqual(this.subject.rowByIndex(3).value(), "21"); + assert.strictEqual(this.subject.rowByIndex(4).value(), "1"); - assert.strictEqual( - this.subject.rows().length, - 25, - "all categories are visible" - ); + assert.strictEqual( + this.subject.rows().length, + 25, + "all categories are visible" + ); - await this.subject.fillInFilter("bug"); + await this.subject.fillInFilter("bug"); - assert.strictEqual( - this.subject.rowByIndex(0).name(), - "bug", - "search still finds categories" - ); - }, + assert.strictEqual( + this.subject.rowByIndex(0).name(), + "bug", + "search still finds categories" + ); }); - componentTest("with allowUncategorized=null", { - template: hbs` - {{category-chooser - value=value - options=(hash + test("with allowUncategorized=null", async function (assert) { + this.siteSettings.allow_uncategorized_topics = false; + + await render(hbs` + + `); - beforeEach() { - this.siteSettings.allow_uncategorized_topics = false; - }, - - test(assert) { - assert.strictEqual(this.subject.header().value(), null); - assert.strictEqual(this.subject.header().label(), "category…"); - }, + assert.strictEqual(this.subject.header().value(), null); + assert.strictEqual(this.subject.header().label(), "category…"); }); - componentTest("with allowUncategorized=null none=true", { - template: hbs` - {{category-chooser - value=value - options=(hash + test("with allowUncategorized=null none=true", async function (assert) { + this.siteSettings.allow_uncategorized_topics = false; + + await render(hbs` + + `); - beforeEach() { - this.siteSettings.allow_uncategorized_topics = false; - }, - - test(assert) { - assert.strictEqual(this.subject.header().value(), null); - assert.strictEqual(this.subject.header().label(), "(no category)"); - }, + assert.strictEqual(this.subject.header().value(), null); + assert.strictEqual(this.subject.header().label(), "(no category)"); }); - componentTest("with disallowed uncategorized, none", { - template: hbs` - {{category-chooser - value=value - options=(hash + test("with disallowed uncategorized, none", async function (assert) { + I18n.translations[I18n.locale].js.test = { root: "root none label" }; + this.siteSettings.allow_uncategorized_topics = false; + + await render(hbs` + + `); - beforeEach() { - I18n.translations[I18n.locale].js.test = { root: "root none label" }; - this.siteSettings.allow_uncategorized_topics = false; - }, - - test(assert) { - assert.strictEqual(this.subject.header().value(), null); - assert.strictEqual(this.subject.header().label(), "root none label"); - }, + assert.strictEqual(this.subject.header().value(), null); + assert.strictEqual(this.subject.header().label(), "root none label"); }); - componentTest("with allowed uncategorized", { - template: hbs` - {{category-chooser - value=value - options=(hash + test("with allowed uncategorized", async function (assert) { + this.siteSettings.allow_uncategorized_topics = true; + + await render(hbs` + + `); - beforeEach() { - this.siteSettings.allow_uncategorized_topics = true; - }, - - test(assert) { - assert.strictEqual(this.subject.header().value(), null); - assert.strictEqual(this.subject.header().label(), "uncategorized"); - }, + assert.strictEqual(this.subject.header().value(), null); + assert.strictEqual(this.subject.header().label(), "uncategorized"); }); - componentTest("with allowed uncategorized and none=true", { - template: hbs` - {{category-chooser - value=value - options=(hash + test("with allowed uncategorized and none=true", async function (assert) { + this.siteSettings.allow_uncategorized_topics = true; + + await render(hbs` + + `); - beforeEach() { - this.siteSettings.allow_uncategorized_topics = true; - }, - - test(assert) { - assert.strictEqual(this.subject.header().value(), null); - assert.strictEqual(this.subject.header().label(), "(no category)"); - }, + assert.strictEqual(this.subject.header().value(), null); + assert.strictEqual(this.subject.header().label(), "(no category)"); }); - componentTest("with allowed uncategorized and none", { - template: hbs` - {{category-chooser - value=value - options=(hash + test("with allowed uncategorized and none", async function (assert) { + I18n.translations[I18n.locale].js.test = { root: "root none label" }; + this.siteSettings.allow_uncategorized_topics = true; + + await render(hbs` + + `); - beforeEach() { - I18n.translations[I18n.locale].js.test = { root: "root none label" }; - this.siteSettings.allow_uncategorized_topics = true; - }, - - test(assert) { - assert.strictEqual(this.subject.header().value(), null); - assert.strictEqual(this.subject.header().label(), "root none label"); - }, + assert.strictEqual(this.subject.header().value(), null); + assert.strictEqual(this.subject.header().label(), "root none label"); }); - componentTest("filter is case insensitive", { - template: hbs` - {{category-chooser - value=value - }} - `, + test("filter is case insensitive", async function (assert) { + await render(hbs` + + `); - async test(assert) { - await this.subject.expand(); - await this.subject.fillInFilter("bug"); + await this.subject.expand(); + await this.subject.fillInFilter("bug"); - assert.strictEqual(this.subject.rows().length, 1); - assert.strictEqual(this.subject.rowByIndex(0).name(), "bug"); + assert.strictEqual(this.subject.rows().length, 1); + assert.strictEqual(this.subject.rowByIndex(0).name(), "bug"); - await this.subject.emptyFilter(); - await this.subject.fillInFilter("Bug"); + await this.subject.emptyFilter(); + await this.subject.fillInFilter("Bug"); - assert.strictEqual(this.subject.rows().length, 1); - assert.strictEqual(this.subject.rowByIndex(0).name(), "bug"); - }, + assert.strictEqual(this.subject.rows().length, 1); + assert.strictEqual(this.subject.rowByIndex(0).name(), "bug"); }); - componentTest("filter works with non english characters", { - template: hbs` - {{category-chooser - value=value - }} - `, + test("filter works with non english characters", async function (assert) { + const store = createStore(); + store.createRecord("category", { + id: 1, + name: "chữ Quốc ngữ", + }); - beforeEach() { - const store = createStore(); - store.createRecord("category", { - id: 1, - name: "chữ Quốc ngữ", - }); - }, + await render(hbs` + + `); - async test(assert) { - await this.subject.expand(); - await this.subject.fillInFilter("gữ"); + await this.subject.expand(); + await this.subject.fillInFilter("gữ"); - assert.strictEqual(this.subject.rows().length, 1); - assert.strictEqual(this.subject.rowByIndex(0).name(), "chữ Quốc ngữ"); - }, + assert.strictEqual(this.subject.rows().length, 1); + assert.strictEqual(this.subject.rowByIndex(0).name(), "chữ Quốc ngữ"); }); - componentTest("decodes entities in row title", { - template: hbs` - {{category-chooser - value=value - options=(hash scopedCategoryId=1) - }} - `, + test("decodes entities in row title", async function (assert) { + const store = createStore(); + store.createRecord("category", { + id: 1, + name: "cat-with-entities", + description_text: "baz "bar ‘foo’", + }); - beforeEach() { - const store = createStore(); - store.createRecord("category", { - id: 1, - name: "cat-with-entities", - description_text: "baz "bar ‘foo’", - }); - }, + await render(hbs` + + `); - async test(assert) { - await this.subject.expand(); + await this.subject.expand(); - assert.strictEqual( - this.subject.rowByIndex(0).el().querySelector(".category-desc") - .innerText, - 'baz "bar ‘foo’' - ); - }, + assert.strictEqual( + this.subject.rowByIndex(0).el().querySelector(".category-desc") + .innerText, + 'baz "bar ‘foo’' + ); }); } ); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/category-drop-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/category-drop-test.js index 8f60850e36d..96a66a1450f 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/category-drop-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/category-drop-test.js @@ -1,11 +1,10 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import { ALL_CATEGORIES_ID, NO_CATEGORIES_ID, } from "select-kit/components/category-drop"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; import Category from "discourse/models/category"; import DiscourseURL from "discourse/lib/url"; import I18n from "I18n"; @@ -35,428 +34,344 @@ function initCategoriesWithParentCategory(context) { }); } -discourseModule( - "Integration | Component | select-kit/category-drop", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | select-kit/category-drop", function (hooks) { + setupRenderingTest(hooks); - hooks.beforeEach(function () { - this.set("subject", selectKit()); - }); + hooks.beforeEach(function () { + this.set("subject", selectKit()); + }); - componentTest("caretUpIcon", { - template: hbs` - {{category-drop - category=value - categories=content - }} - `, + test("caretUpIcon", async function (assert) { + await render(hbs` + + `); - async test(assert) { - const header = this.subject.header().el(); + const header = this.subject.header().el(); - assert.ok( - header.querySelector(`.d-icon-caret-right`), - "it uses the correct default icon" - ); - }, - }); - - componentTest("none", { - template: hbs` - {{category-drop - category=value - categories=content - }} - `, - - async test(assert) { - const text = this.subject.header().label(); - assert.strictEqual( - text, - I18n.t("category.all").toLowerCase(), - "it uses the noneLabel" - ); - }, - }); - - componentTest("[not staff - TL0] displayCategoryDescription", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - }} - `, - - beforeEach() { - set(this.currentUser, "staff", false); - set(this.currentUser, "trust_level", 0); - - initCategories(this); - }, - - async test(assert) { - await this.subject.expand(); - - const row = this.subject.rowByValue(this.category.id); - assert.ok( - row.el().querySelector(".category-desc"), - "it shows category description for newcomers" - ); - }, - }); - - componentTest("[not staff - TL1] displayCategoryDescription", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - }} - `, - - beforeEach() { - set(this.currentUser, "moderator", false); - set(this.currentUser, "admin", false); - set(this.currentUser, "trust_level", 1); - initCategories(this); - }, - - async test(assert) { - await this.subject.expand(); - - const row = this.subject.rowByValue(this.category.id); - assert.notOk( - row.el().querySelector(".category-desc"), - "it doesn't shows category description for TL0+" - ); - }, - }); - - componentTest("[staff - TL0] displayCategoryDescription", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - }} - `, - - beforeEach() { - set(this.currentUser, "moderator", true); - set(this.currentUser, "trust_level", 0); - - initCategories(this); - }, - - async test(assert) { - await this.subject.expand(); - - const row = this.subject.rowByValue(this.category.id); - assert.notOk( - row.el().querySelector(".category-desc"), - "it doesn't show category description for staff" - ); - }, - }); - - componentTest("hideParentCategory (default: false)", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - }} - `, - - beforeEach() { - initCategories(this); - }, - - async test(assert) { - await this.subject.expand(); - - const row = this.subject.rowByValue(this.category.id); - assert.strictEqual(row.value(), this.category.id.toString()); - assert.strictEqual(this.category.parent_category_id, undefined); - }, - }); - - componentTest("hideParentCategory (true)", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - options=(hash - hideParentCategory=true - ) - }} - `, - - beforeEach() { - initCategoriesWithParentCategory(this); - }, - - async test(assert) { - await this.subject.expand(); - - const parentRow = this.subject.rowByValue(this.parentCategory.id); - assert.notOk(parentRow.exists(), "the parent row is not showing"); - - const childCategory = this.categories.firstObject; - const childCategoryId = childCategory.id; - const childRow = this.subject.rowByValue(childCategoryId); - assert.ok(childRow.exists(), "the child row is showing"); - - const categoryStatus = childRow.el().querySelector(".category-status"); - assert.ok(categoryStatus.innerText.trim().match(/^spec/)); - }, - }); - - componentTest("allow_uncategorized_topics (true)", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - }} - `, - - beforeEach() { - this.siteSettings.allow_uncategorized_topics = true; - initCategories(this); - }, - - async test(assert) { - await this.subject.expand(); - - const uncategorizedCategoryId = this.site.uncategorized_category_id; - const row = this.subject.rowByValue(uncategorizedCategoryId); - assert.ok(row.exists(), "the uncategorized row is showing"); - }, - }); - - componentTest("allow_uncategorized_topics (false)", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - }} - `, - - beforeEach() { - this.siteSettings.allow_uncategorized_topics = false; - initCategories(this); - }, - - async test(assert) { - await this.subject.expand(); - - const uncategorizedCategoryId = this.site.uncategorized_category_id; - const row = this.subject.rowByValue(uncategorizedCategoryId); - assert.notOk(row.exists(), "the uncategorized row is not showing"); - }, - }); - - componentTest("countSubcategories (default: false)", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - }} - `, - - beforeEach() { - initCategories(this); - }, - - async test(assert) { - await this.subject.expand(); - - const category = Category.findById(7); - const row = this.subject.rowByValue(category.id); - const topicCount = row - .el() - .querySelector(".topic-count") - .innerText.trim(); - - assert.strictEqual( - topicCount, - "× 481", - "it doesn't include the topic count of subcategories" - ); - }, - }); - - componentTest("countSubcategories (true)", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - options=(hash - countSubcategories=true - ) - }} - `, - - beforeEach() { - initCategories(this); - }, - - async test(assert) { - await this.subject.expand(); - - const category = Category.findById(7); - const row = this.subject.rowByValue(category.id); - const topicCount = row - .el() - .querySelector(".topic-count") - .innerText.trim(); - - assert.strictEqual( - topicCount, - "× 584", - "it includes the topic count of subcategories" - ); - }, - }); - - componentTest("shortcuts:default", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - }} - `, - - beforeEach() { - initCategories(this); - this.set("category", null); - }, - - async test(assert) { - await this.subject.expand(); - - assert.strictEqual( - this.subject.rowByIndex(0).value(), - this.categories.firstObject.id.toString(), - "Shortcuts are not prepended when no category is selected" - ); - }, - }); - - componentTest("shortcuts:category is set", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - }} - `, - - beforeEach() { - initCategories(this); - }, - - async test(assert) { - await this.subject.expand(); - - assert.strictEqual( - this.subject.rowByIndex(0).value(), - ALL_CATEGORIES_ID - ); - }, - }); - - componentTest("shortcuts with parentCategory/subCategory=true:default", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - options=(hash - subCategory=true - ) - }} - `, - - beforeEach() { - initCategoriesWithParentCategory(this); - }, - - async test(assert) { - await this.subject.expand(); - - assert.strictEqual( - this.subject.rowByIndex(0).value(), - NO_CATEGORIES_ID - ); - }, - }); - - componentTest( - "shortcuts with parentCategory/subCategory=true:category is selected", - { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - options=(hash - subCategory=true - ) - }} - `, - - beforeEach() { - initCategoriesWithParentCategory(this); - this.set("category", this.categories.firstObject); - }, - - async test(assert) { - await this.subject.expand(); - - assert.strictEqual( - this.subject.rowByIndex(0).value(), - ALL_CATEGORIES_ID - ); - assert.strictEqual( - this.subject.rowByIndex(1).value(), - NO_CATEGORIES_ID - ); - }, - } + assert.ok( + header.querySelector(`.d-icon-caret-right`), + "it uses the correct default icon" ); + }); - componentTest("category url", { - template: hbs` - {{category-drop - category=category - categories=categories - parentCategory=parentCategory - }} - `, + test("none", async function (assert) { + await render(hbs` + + `); - beforeEach() { - initCategoriesWithParentCategory(this); - sinon.stub(DiscourseURL, "routeTo"); - }, + const text = this.subject.header().label(); + assert.strictEqual( + text, + I18n.t("category.all").toLowerCase(), + "it uses the noneLabel" + ); + }); - async test(assert) { - await this.subject.expand(); - await this.subject.selectRowByValue(26); + test("[not staff - TL0] displayCategoryDescription", async function (assert) { + set(this.currentUser, "staff", false); + set(this.currentUser, "trust_level", 0); - assert.ok( - DiscourseURL.routeTo.calledWith("/c/feature/spec/26"), - "it builds a correct URL" - ); - }, - }); - } -); + initCategories(this); + + await render(hbs` + + `); + + await this.subject.expand(); + + const row = this.subject.rowByValue(this.category.id); + assert.ok( + row.el().querySelector(".category-desc"), + "it shows category description for newcomers" + ); + }); + + test("[not staff - TL1] displayCategoryDescription", async function (assert) { + set(this.currentUser, "moderator", false); + set(this.currentUser, "admin", false); + set(this.currentUser, "trust_level", 1); + initCategories(this); + + await render(hbs` + + `); + + await this.subject.expand(); + + const row = this.subject.rowByValue(this.category.id); + assert.notOk( + row.el().querySelector(".category-desc"), + "it doesn't shows category description for TL0+" + ); + }); + + test("[staff - TL0] displayCategoryDescription", async function (assert) { + set(this.currentUser, "moderator", true); + set(this.currentUser, "trust_level", 0); + + initCategories(this); + + await render(hbs` + + `); + + await this.subject.expand(); + + const row = this.subject.rowByValue(this.category.id); + assert.notOk( + row.el().querySelector(".category-desc"), + "it doesn't show category description for staff" + ); + }); + + test("hideParentCategory (default: false)", async function (assert) { + initCategories(this); + + await render(hbs` + + `); + + await this.subject.expand(); + + const row = this.subject.rowByValue(this.category.id); + assert.strictEqual(row.value(), this.category.id.toString()); + assert.strictEqual(this.category.parent_category_id, undefined); + }); + + test("hideParentCategory (true)", async function (assert) { + initCategoriesWithParentCategory(this); + + await render(hbs` + + `); + + await this.subject.expand(); + + const parentRow = this.subject.rowByValue(this.parentCategory.id); + assert.notOk(parentRow.exists(), "the parent row is not showing"); + + const childCategory = this.categories.firstObject; + const childCategoryId = childCategory.id; + const childRow = this.subject.rowByValue(childCategoryId); + assert.ok(childRow.exists(), "the child row is showing"); + + const categoryStatus = childRow.el().querySelector(".category-status"); + assert.ok(categoryStatus.innerText.trim().match(/^spec/)); + }); + + test("allow_uncategorized_topics (true)", async function (assert) { + this.siteSettings.allow_uncategorized_topics = true; + initCategories(this); + + await render(hbs` + + `); + + await this.subject.expand(); + + const uncategorizedCategoryId = this.site.uncategorized_category_id; + const row = this.subject.rowByValue(uncategorizedCategoryId); + assert.ok(row.exists(), "the uncategorized row is showing"); + }); + + test("allow_uncategorized_topics (false)", async function (assert) { + this.siteSettings.allow_uncategorized_topics = false; + initCategories(this); + + await render(hbs` + + `); + + await this.subject.expand(); + + const uncategorizedCategoryId = this.site.uncategorized_category_id; + const row = this.subject.rowByValue(uncategorizedCategoryId); + assert.notOk(row.exists(), "the uncategorized row is not showing"); + }); + + test("countSubcategories (default: false)", async function (assert) { + initCategories(this); + + await render(hbs` + + `); + + await this.subject.expand(); + + const category = Category.findById(7); + const row = this.subject.rowByValue(category.id); + const topicCount = row.el().querySelector(".topic-count").innerText.trim(); + + assert.strictEqual( + topicCount, + "× 481", + "it doesn't include the topic count of subcategories" + ); + }); + + test("countSubcategories (true)", async function (assert) { + initCategories(this); + + await render(hbs` + + `); + + await this.subject.expand(); + + const category = Category.findById(7); + const row = this.subject.rowByValue(category.id); + const topicCount = row.el().querySelector(".topic-count").innerText.trim(); + + assert.strictEqual( + topicCount, + "× 584", + "it includes the topic count of subcategories" + ); + }); + + test("shortcuts:default", async function (assert) { + initCategories(this); + this.set("category", null); + + await render(hbs` + + `); + + await this.subject.expand(); + + assert.strictEqual( + this.subject.rowByIndex(0).value(), + this.categories.firstObject.id.toString(), + "Shortcuts are not prepended when no category is selected" + ); + }); + + test("shortcuts:category is set", async function (assert) { + initCategories(this); + + await render(hbs` + + `); + + await this.subject.expand(); + + assert.strictEqual(this.subject.rowByIndex(0).value(), ALL_CATEGORIES_ID); + }); + + test("shortcuts with parentCategory/subCategory=true:default", async function (assert) { + initCategoriesWithParentCategory(this); + + await render(hbs` + + `); + + await this.subject.expand(); + + assert.strictEqual(this.subject.rowByIndex(0).value(), NO_CATEGORIES_ID); + }); + + test("shortcuts with parentCategory/subCategory=true:category is selected", async function (assert) { + initCategoriesWithParentCategory(this); + this.set("category", this.categories.firstObject); + + await render(hbs` + + `); + + await this.subject.expand(); + + assert.strictEqual(this.subject.rowByIndex(0).value(), ALL_CATEGORIES_ID); + assert.strictEqual(this.subject.rowByIndex(1).value(), NO_CATEGORIES_ID); + }); + + test("category url", async function (assert) { + initCategoriesWithParentCategory(this); + sinon.stub(DiscourseURL, "routeTo"); + + await render(hbs` + + `); + + await this.subject.expand(); + await this.subject.selectRowByValue(26); + + assert.ok( + DiscourseURL.routeTo.calledWith("/c/feature/spec/26"), + "it builds a correct URL" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/combo-box-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/combo-box-test.js index 8d4d7d57c93..7ddfa76f890 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/combo-box-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/combo-box-test.js @@ -1,8 +1,6 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; -import { click } from "@ember/test-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; @@ -14,98 +12,87 @@ const DEFAULT_CONTENT = [ const DEFAULT_VALUE = 1; -const setDefaultState = (ctx, options) => { +const setDefaultState = (ctx, options = {}) => { const properties = Object.assign( { content: DEFAULT_CONTENT, value: DEFAULT_VALUE, }, - options || {} + options ); ctx.setProperties(properties); }; -discourseModule( - "Integration | Component | select-kit/combo-box", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | select-kit/combo-box", function (hooks) { + setupRenderingTest(hooks); - hooks.beforeEach(function () { - this.set("subject", selectKit()); - }); + hooks.beforeEach(function () { + this.set("subject", selectKit()); + }); - componentTest("options.clearable", { - template: hbs` - {{combo-box - value=value - content=content - onChange=onChange - options=(hash clearable=clearable) - }} - `, - - beforeEach() { - setDefaultState(this, { - clearable: true, - onChange: (value) => { - this.set("value", value); - }, - }); - }, - - async test(assert) { - const header = this.subject.header(); - - assert.ok( - header.el().querySelector(".btn-clear"), - "it shows the clear button" - ); - assert.strictEqual(header.value(), DEFAULT_VALUE.toString()); - - await click(header.el().querySelector(".btn-clear")); - - assert.notOk( - header.el().querySelector(".btn-clear"), - "it hides the clear button" - ); - assert.strictEqual(header.value(), null); + test("options.clearable", async function (assert) { + setDefaultState(this, { + clearable: true, + onChange: (value) => { + this.set("value", value); }, }); - componentTest("options.{caretUpIcon,caretDownIcon}", { - template: hbs` - {{combo-box - value=value - content=content - options=(hash + await render(hbs` + + `); + + const header = this.subject.header(); + + assert.ok( + header.el().querySelector(".btn-clear"), + "it shows the clear button" + ); + assert.strictEqual(header.value(), DEFAULT_VALUE.toString()); + + await click(header.el().querySelector(".btn-clear")); + + assert.notOk( + header.el().querySelector(".btn-clear"), + "it hides the clear button" + ); + assert.strictEqual(header.value(), null); + }); + + test("options.{caretUpIcon,caretDownIcon}", async function (assert) { + setDefaultState(this, { + caretUpIcon: "pencil-alt", + caretDownIcon: "trash-alt", + }); + + await render(hbs` + + `); - beforeEach() { - setDefaultState(this, { - caretUpIcon: "pencil-alt", - caretDownIcon: "trash-alt", - }); - }, + const header = this.subject.header().el(); - async test(assert) { - const header = this.subject.header().el(); + assert.ok( + header.querySelector(`.d-icon-${this.caretDownIcon}`), + "it uses the icon provided" + ); - assert.ok( - header.querySelector(`.d-icon-${this.caretDownIcon}`), - "it uses the icon provided" - ); + await this.subject.expand(); - await this.subject.expand(); - - assert.ok( - header.querySelector(`.d-icon-${this.caretUpIcon}`), - "it uses the icon provided" - ); - }, - }); - } -); + assert.ok( + header.querySelector(`.d-icon-${this.caretUpIcon}`), + "it uses the icon provided" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/dropdown-select-box-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/dropdown-select-box-test.js index d2539e9fbbd..3649cadf680 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/dropdown-select-box-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/dropdown-select-box-test.js @@ -1,7 +1,6 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; @@ -27,7 +26,7 @@ const setDefaultState = (ctx, options) => { ctx.setProperties(properties); }; -discourseModule( +module( "Integration | Component | select-kit/dropdown-select-box", function (hooks) { setupRenderingTest(hooks); @@ -36,86 +35,74 @@ discourseModule( this.set("subject", selectKit()); }); - componentTest("selection behavior", { - template: hbs` - {{dropdown-select-box - value=value - content=content - }} - `, + test("selection behavior", async function (assert) { + setDefaultState(this); - beforeEach() { - setDefaultState(this); - }, + await render(hbs` + + `); - async test(assert) { - await this.subject.expand(); - assert.ok(this.subject.isExpanded()); + await this.subject.expand(); + assert.ok(this.subject.isExpanded()); - await this.subject.selectRowByValue(DEFAULT_VALUE); - assert.notOk( - this.subject.isExpanded(), - "it collapses the dropdown on select" - ); - }, + await this.subject.selectRowByValue(DEFAULT_VALUE); + assert.notOk( + this.subject.isExpanded(), + "it collapses the dropdown on select" + ); }); - componentTest("options.showFullTitle=false", { - template: hbs` - {{dropdown-select-box - value=value - content=content - options=(hash - icon="times" - showFullTitle=showFullTitle - none=none - ) - }} - `, + test("options.showFullTitle=false", async function (assert) { + setDefaultState(this, { + value: null, + showFullTitle: false, + none: "test_none", + }); - beforeEach() { - setDefaultState(this, { - value: null, - showFullTitle: false, - none: "test_none", - }); - }, + await render(hbs` + + `); - async test(assert) { - assert.notOk( - this.subject.header().el().querySelector(".selected-name"), - "it hides the text of the selected item" - ); + assert.notOk( + this.subject.header().el().querySelector(".selected-name"), + "it hides the text of the selected item" + ); - assert.strictEqual( - this.subject.header().el().getAttribute("title"), - "[en.test_none]", - "it adds a title attribute to the button" - ); - }, + assert.strictEqual( + this.subject.header().el().getAttribute("title"), + "[en.test_none]", + "it adds a title attribute to the button" + ); }); - componentTest("options.showFullTitle=true", { - template: hbs` - {{dropdown-select-box - value=value - content=content - options=(hash - showFullTitle=showFullTitle - ) - }} - `, + test("options.showFullTitle=true", async function (assert) { + setDefaultState(this, { showFullTitle: true }); - beforeEach() { - setDefaultState(this, { showFullTitle: true }); - }, + await render(hbs` + + `); - async test(assert) { - assert.ok( - this.subject.header().el().querySelector(".selected-name"), - "it shows the text of the selected item" - ); - }, + assert.ok( + this.subject.header().el().querySelector(".selected-name"), + "it shows the text of the selected item" + ); }); } ); diff --git a/app/assets/javascripts/discourse/tests/integration/components/future-date-input-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/future-date-input-test.js similarity index 56% rename from app/assets/javascripts/discourse/tests/integration/components/future-date-input-test.js rename to app/assets/javascripts/discourse/tests/integration/components/select-kit/future-date-input-test.js index de4be909250..5f6ddf3949a 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/future-date-input-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/future-date-input-test.js @@ -1,45 +1,50 @@ -import selectKit from "discourse/tests/helpers/select-kit-helper"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { fillIn, render } from "@ember/test-helpers"; import { - discourseModule, exists, fakeTime, queryAll, } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; +import selectKit from "discourse/tests/helpers/select-kit-helper"; import I18n from "I18n"; -import { fillIn } from "@ember/test-helpers"; -discourseModule("Unit | Lib | select-kit/future-date-input", function (hooks) { - setupRenderingTest(hooks); +function getOptions() { + return Array.from( + queryAll(`.select-kit-collection .select-kit-row`).map( + (_, span) => span.dataset.name + ) + ); +} - hooks.beforeEach(function () { - this.set("subject", selectKit()); - }); +module( + "Integration | Component | select-kit/future-date-input", + function (hooks) { + setupRenderingTest(hooks); - hooks.afterEach(function () { - if (this.clock) { - this.clock.restore(); - } - }); + hooks.beforeEach(function () { + this.set("subject", selectKit()); + }); - componentTest("rendering and expanding", { - template: hbs` - {{future-date-input - options=(hash + hooks.afterEach(function () { + this.clock?.restore(); + }); + + test("rendering and expanding", async function (assert) { + await render(hbs` + + `); - async test(assert) { assert.ok(exists(".future-date-input-selector"), "Selector is rendered"); - assert.ok( - this.subject.header().label() === - I18n.t("time_shortcut.select_timeframe"), + assert.strictEqual( + this.subject.header().label(), + I18n.t("time_shortcut.select_timeframe"), "Default text is rendered" ); @@ -49,18 +54,14 @@ discourseModule("Unit | Lib | select-kit/future-date-input", function (hooks) { exists(".select-kit-collection"), "List of options is rendered" ); - }, - }); + }); - componentTest("renders default options", { - template: hbs`{{future-date-input}}`, - - beforeEach() { + test("renders default options", async function (assert) { const monday = "2100-12-13T08:00:00"; this.clock = fakeTime(monday, this.currentUser.timezone, true); - }, - async test(assert) { + await render(hbs``); + await this.subject.expand(); const options = getOptions(); const expected = [ @@ -80,61 +81,53 @@ discourseModule("Unit | Lib | select-kit/future-date-input", function (hooks) { ]; assert.deepEqual(options, expected); - }, - }); + }); - componentTest("shows 'Custom date and time' by default", { - template: hbs`{{future-date-input}}`, + test("shows 'Custom date and time' by default", async function (assert) { + await render(hbs``); - async test(assert) { await this.subject.expand(); const options = getOptions(); const customDateAndTime = I18n.t("time_shortcut.custom"); assert.ok(options.includes(customDateAndTime)); - }, - }); + }); - componentTest("doesn't show 'Custom date and time' if disabled", { - template: hbs` - {{future-date-input - includeDateTime=false - }} - `, + test("doesn't show 'Custom date and time' if disabled", async function (assert) { + await render(hbs` + + `); - async test(assert) { await this.subject.expand(); const options = getOptions(); const customDateAndTime = I18n.t("time_shortcut.custom"); assert.notOk(options.includes(customDateAndTime)); - }, - }); + }); - componentTest("shows the now option if enabled", { - template: hbs` - {{future-date-input - includeNow=true - }} - `, + test("shows the now option if enabled", async function (assert) { + await render(hbs` + + `); - async test(assert) { await this.subject.expand(); const options = getOptions(); const now = I18n.t("time_shortcut.now"); assert.ok(options.includes(now)); - }, - }); + }); - componentTest("changing date/time updates the input correctly", { - template: hbs`{{future-date-input input=input onChangeInput=(action (mut input))}}`, - - beforeEach() { + test("changing date/time updates the input correctly", async function (assert) { this.set("input", moment("2032-01-01 11:10")); - }, - async test(assert) { + await render( + hbs`` + ); + await fillIn(".time-input", "11:15"); assert.ok(this.input.includes("2032-01-01")); @@ -144,14 +137,6 @@ discourseModule("Unit | Lib | select-kit/future-date-input", function (hooks) { assert.ok(this.input.includes("2033-01-01")); assert.ok(this.input.includes("11:15")); - }, - }); - - function getOptions() { - return Array.from( - queryAll(`.select-kit-collection .select-kit-row`).map( - (_, span) => span.dataset.name - ) - ); + }); } -}); +); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/host-list-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/host-list-test.js deleted file mode 100644 index d1da220959c..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/host-list-test.js +++ /dev/null @@ -1,31 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule( - "Integration | Component | site-setting | host-list", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("displays setting value", { - template: hbs`{{site-setting setting=setting}}`, - - beforeEach() { - this.set("setting", { - setting: "blocked_onebox_domains", - value: "a.com|b.com", - type: "host_list", - }); - }, - - async test(assert) { - assert.strictEqual( - query(".formatted-selection").innerText, - "a.com, b.com" - ); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/list-setting-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/list-setting-test.js index 99ab0b94630..5b6a0c283a8 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/list-setting-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/list-setting-test.js @@ -1,41 +1,33 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; -discourseModule( - "Integration | Component | select-kit/list-setting", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | select-kit/list-setting", function (hooks) { + setupRenderingTest(hooks); - hooks.beforeEach(function () { - this.set("subject", selectKit()); - }); + hooks.beforeEach(function () { + this.set("subject", selectKit()); + }); - componentTest("default", { - template: hbs` - {{list-setting - value=value - choices=choices - }} - `, + test("default", async function (assert) { + this.set("value", ["bold", "italic"]); + this.set("choices", ["bold", "italic", "underline"]); - beforeEach() { - this.set("value", ["bold", "italic"]); - this.set("choices", ["bold", "italic", "underline"]); - }, + await render(hbs` + + `); - async test(assert) { - assert.strictEqual(this.subject.header().name(), "bold,italic"); - assert.strictEqual(this.subject.header().value(), "bold,italic"); + assert.strictEqual(this.subject.header().name(), "bold,italic"); + assert.strictEqual(this.subject.header().value(), "bold,italic"); - await this.subject.expand(); + await this.subject.expand(); - assert.strictEqual(this.subject.rows().length, 1); - assert.strictEqual(this.subject.rowByIndex(0).value(), "underline"); - }, - }); - } -); + assert.strictEqual(this.subject.rows().length, 1); + assert.strictEqual(this.subject.rowByIndex(0).value(), "underline"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/mini-tag-chooser-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/mini-tag-chooser-test.js index d239a2c6472..e7eafd2d1b0 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/mini-tag-chooser-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/mini-tag-chooser-test.js @@ -1,16 +1,12 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - query, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query, queryAll } from "discourse/tests/helpers/qunit-helpers"; import I18n from "I18n"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; -discourseModule( +module( "Integration | Component | select-kit/mini-tag-chooser", function (hooks) { setupRenderingTest(hooks); @@ -19,97 +15,83 @@ discourseModule( this.set("subject", selectKit()); }); - componentTest("displays tags", { - template: hbs`{{mini-tag-chooser value=value}}`, + test("displays tags", async function (assert) { + this.set("value", ["foo", "bar"]); - beforeEach() { - this.set("value", ["foo", "bar"]); - }, + await render(hbs``); - async test(assert) { - assert.strictEqual(this.subject.header().value(), "foo,bar"); - }, + assert.strictEqual(this.subject.header().value(), "foo,bar"); }); - componentTest("create a tag", { - template: hbs`{{mini-tag-chooser value=value}}`, + test("create a tag", async function (assert) { + this.set("value", ["foo", "bar"]); - beforeEach() { - this.set("value", ["foo", "bar"]); - }, + await render(hbs``); - async test(assert) { - assert.strictEqual(this.subject.header().value(), "foo,bar"); + assert.strictEqual(this.subject.header().value(), "foo,bar"); - await this.subject.expand(); - await this.subject.fillInFilter("mon"); - assert.strictEqual( - queryAll(".select-kit-row").text().trim(), - "monkey x1\ngazelle x2" - ); - await this.subject.fillInFilter("key"); - assert.strictEqual( - queryAll(".select-kit-row").text().trim(), - "monkey x1\ngazelle x2" - ); - await this.subject.selectRowByValue("monkey"); + await this.subject.expand(); + await this.subject.fillInFilter("mon"); + assert.deepEqual( + [...queryAll(".select-kit-row")].map((el) => el.textContent.trim()), + ["monkey x1", "gazelle x2"] + ); + await this.subject.fillInFilter("key"); + assert.deepEqual( + [...queryAll(".select-kit-row")].map((el) => el.textContent.trim()), + ["monkey x1", "gazelle x2"] + ); + await this.subject.selectRowByValue("monkey"); - assert.strictEqual(this.subject.header().value(), "foo,bar,monkey"); - }, + assert.strictEqual(this.subject.header().value(), "foo,bar,monkey"); }); - componentTest("max_tags_per_topic", { - template: hbs`{{mini-tag-chooser value=value}}`, + test("max_tags_per_topic", async function (assert) { + this.set("value", ["foo", "bar"]); + this.siteSettings.max_tags_per_topic = 2; - beforeEach() { - this.set("value", ["foo", "bar"]); - this.siteSettings.max_tags_per_topic = 2; - }, + await render(hbs``); - async test(assert) { - assert.strictEqual(this.subject.header().value(), "foo,bar"); + assert.strictEqual(this.subject.header().value(), "foo,bar"); - await this.subject.expand(); - await this.subject.fillInFilter("baz"); - await this.subject.selectRowByValue("monkey"); + await this.subject.expand(); + await this.subject.fillInFilter("baz"); + await this.subject.selectRowByValue("monkey"); - const error = queryAll(".select-kit-error").text(); - assert.strictEqual( - error, - I18n.t("select_kit.max_content_reached", { - count: this.siteSettings.max_tags_per_topic, - }) - ); - }, + const error = query(".select-kit-error").innerText; + assert.strictEqual( + error, + I18n.t("select_kit.max_content_reached", { + count: this.siteSettings.max_tags_per_topic, + }) + ); }); - componentTest("required_tag_group", { - template: hbs`{{mini-tag-chooser value=value options=(hash categoryId=1)}}`, + test("required_tag_group", async function (assert) { + this.set("value", ["foo", "bar"]); - beforeEach() { - this.set("value", ["foo", "bar"]); - }, + await render( + hbs`` + ); - async test(assert) { - assert.strictEqual(this.subject.header().value(), "foo,bar"); + assert.strictEqual(this.subject.header().value(), "foo,bar"); - await this.subject.expand(); + await this.subject.expand(); - assert.strictEqual( - query("input[name=filter-input-search]").placeholder, - I18n.t("tagging.choose_for_topic_required_group", { - count: 1, - name: "monkey group", - }) - ); + assert.strictEqual( + query("input[name=filter-input-search]").placeholder, + I18n.t("tagging.choose_for_topic_required_group", { + count: 1, + name: "monkey group", + }) + ); - await this.subject.selectRowByValue("monkey"); + await this.subject.selectRowByValue("monkey"); - assert.strictEqual( - query("input[name=filter-input-search]").placeholder, - I18n.t("select_kit.filter_placeholder") - ); - }, + assert.strictEqual( + query("input[name=filter-input-search]").placeholder, + I18n.t("select_kit.filter_placeholder") + ); }); } ); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/multi-select-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/multi-select-test.js index 131a5f65a40..a2aea61574a 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/multi-select-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/multi-select-test.js @@ -1,7 +1,6 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; @@ -22,120 +21,83 @@ const setDefaultState = (ctx, options) => { ctx.setProperties(properties); }; -discourseModule( - "Integration | Component | select-kit/multi-select", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | select-kit/multi-select", function (hooks) { + setupRenderingTest(hooks); - hooks.beforeEach(function () { - this.set("subject", selectKit()); - }); + hooks.beforeEach(function () { + this.set("subject", selectKit()); + }); - componentTest("content", { - template: hbs` - {{multi-select - value=value - content=content - }} - `, + test("content", async function (assert) { + setDefaultState(this); - beforeEach() { - setDefaultState(this); - }, + await render(hbs` + + `); - async test(assert) { - await this.subject.expand(); + await this.subject.expand(); - const content = this.subject.displayedContent(); - assert.strictEqual(content.length, 3, "it shows rows"); - assert.strictEqual( - content[0].name, - this.content.firstObject.name, - "it has the correct name" - ); - assert.strictEqual( - content[0].id, - this.content.firstObject.id.toString(), - "it has the correct value" - ); - assert.strictEqual( - this.subject.header().value(), - null, - "it doesn't set a value from the content" - ); - }, - }); - } -); + const content = this.subject.displayedContent(); + assert.strictEqual(content.length, 3, "it shows rows"); + assert.strictEqual( + content[0].name, + this.content.firstObject.name, + "it has the correct name" + ); + assert.strictEqual( + content[0].id, + this.content.firstObject.id.toString(), + "it has the correct value" + ); + assert.strictEqual( + this.subject.header().value(), + null, + "it doesn't set a value from the content" + ); + }); -discourseModule( - "Integration | Component | select-kit/multi-select | maximum=1", - function (hooks) { - setupRenderingTest(hooks); + test("maximum=1", async function (assert) { + setDefaultState(this); - hooks.beforeEach(function () { - this.set("subject", selectKit()); - }); + await render(hbs` + + `); - componentTest("content", { - template: hbs` - {{multi-select - value=value - content=content - options=(hash maximum=1) - }} - `, + await this.subject.expand(); + await this.subject.selectRowByValue(1); - beforeEach() { - setDefaultState(this); - }, + assert.notOk(this.subject.isExpanded(), "it closes the dropdown"); - async test(assert) { - await this.subject.expand(); - await this.subject.selectRowByValue(1); + await this.subject.expand(); + await this.subject.deselectItemByValue(1); - assert.notOk(this.subject.isExpanded(), "it closes the dropdown"); + assert.ok( + this.subject.isExpanded(), + "it doesn’t close the dropdown when no selection has been made" + ); + }); - await this.subject.expand(); - await this.subject.deselectItemByValue(1); + test("maximum=2", async function (assert) { + setDefaultState(this); - assert.ok( - this.subject.isExpanded(), - "it doesn’t close the dropdown when no selection has been made" - ); - }, - }); - } -); + await render(hbs` + + `); -discourseModule( - "Integration | Component | select-kit/multi-select | maximum=2", - function (hooks) { - setupRenderingTest(hooks); + await this.subject.expand(); + await this.subject.selectRowByValue(1); - hooks.beforeEach(function () { - this.set("subject", selectKit()); - }); - - componentTest("content", { - template: hbs` - {{multi-select - value=value - content=content - options=(hash maximum=2) - }} - `, - - beforeEach() { - setDefaultState(this); - }, - - async test(assert) { - await this.subject.expand(); - await this.subject.selectRowByValue(1); - - assert.ok(this.subject.isExpanded(), "it doesn’t close the dropdown"); - }, - }); - } -); + assert.ok(this.subject.isExpanded(), "it doesn’t close the dropdown"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/notifications-button-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/notifications-button-test.js index 997722851eb..561cf914741 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/notifications-button-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/notifications-button-test.js @@ -1,13 +1,12 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import selectKit, { setDefaultState, } from "discourse/tests/helpers/select-kit-helper"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule( +module( "Integration | Component | select-kit/notifications-button", function (hooks) { setupRenderingTest(hooks); @@ -16,40 +15,35 @@ discourseModule( this.set("subject", selectKit()); }); - componentTest("default", { - template: hbs` - {{notifications-button - value=value - options=(hash - i18nPrefix=i18nPrefix - i18nPostfix=i18nPostfix - ) - }} - `, + test("default", async function (assert) { + this.set("value", 1); + setDefaultState(this, 1, { i18nPrefix: "pre", i18nPostfix: "post" }); - beforeEach() { - this.set("value", 1); + await render(hbs` + + `); - setDefaultState(this, 1, { i18nPrefix: "pre", i18nPostfix: "post" }); - }, + assert.ok(this.subject.header().value()); - async test(assert) { - assert.ok(this.subject.header().value()); + assert.ok( + this.subject + .header() + .label() + .includes(`${this.i18nPrefix}.regular${this.i18nPostfix}`), + "it shows the regular choice when value is not set" + ); - assert.ok( - this.subject - .header() - .label() - .includes(`${this.i18nPrefix}.regular${this.i18nPostfix}`), - "it shows the regular choice when value is not set" - ); - - const icon = this.subject.header().icon(); - assert.ok( - icon.classList.contains("d-icon-d-regular"), - "it shows the correct icon" - ); - }, + const icon = this.subject.header().icon(); + assert.ok( + icon.classList.contains("d-icon-d-regular"), + "it shows the correct icon" + ); }); } ); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/pinned-options-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/pinned-options-test.js index 0294ef8a8bb..9caffe84c34 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/pinned-options-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/pinned-options-test.js @@ -1,8 +1,7 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import Topic from "discourse/models/topic"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; @@ -15,49 +14,42 @@ const buildTopic = function (pinned = true) { }); }; -discourseModule( - "Integration | Component | select-kit/pinned-options", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | select-kit/pinned-options", function (hooks) { + setupRenderingTest(hooks); - hooks.beforeEach(function () { - this.set("subject", selectKit()); - }); + hooks.beforeEach(function () { + this.set("subject", selectKit()); + }); - componentTest("unpinning", { - template: hbs`{{pinned-options value=topic.pinned topic=topic}}`, + test("unpinning", async function (assert) { + this.siteSettings.automatically_unpin_topics = false; + this.set("topic", buildTopic()); - beforeEach() { - this.siteSettings.automatically_unpin_topics = false; - this.set("topic", buildTopic()); - }, + await render( + hbs`` + ); - async test(assert) { - assert.strictEqual(this.subject.header().name(), "pinned"); + assert.strictEqual(this.subject.header().name(), "pinned"); - await this.subject.expand(); - await this.subject.selectRowByValue("unpinned"); + await this.subject.expand(); + await this.subject.selectRowByValue("unpinned"); - assert.strictEqual(this.subject.header().name(), "unpinned"); - }, - }); + assert.strictEqual(this.subject.header().name(), "unpinned"); + }); - componentTest("pinning", { - template: hbs`{{pinned-options value=topic.pinned topic=topic}}`, + test("pinning", async function (assert) { + this.siteSettings.automatically_unpin_topics = false; + this.set("topic", buildTopic(false)); - beforeEach() { - this.siteSettings.automatically_unpin_topics = false; - this.set("topic", buildTopic(false)); - }, + await render( + hbs`` + ); - async test(assert) { - assert.strictEqual(this.subject.header().name(), "unpinned"); + assert.strictEqual(this.subject.header().name(), "unpinned"); - await this.subject.expand(); - await this.subject.selectRowByValue("pinned"); + await this.subject.expand(); + await this.subject.selectRowByValue("pinned"); - assert.strictEqual(this.subject.header().name(), "pinned"); - }, - }); - } -); + assert.strictEqual(this.subject.header().name(), "pinned"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/single-select-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/single-select-test.js index d84a898827e..3f2015b5381 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/single-select-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/single-select-test.js @@ -1,8 +1,7 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import I18n from "I18n"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; @@ -30,421 +29,366 @@ const setDefaultState = (ctx, options) => { ctx.setProperties(properties); }; -discourseModule( - "Integration | Component | select-kit/single-select", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | select-kit/single-select", function (hooks) { + setupRenderingTest(hooks); - hooks.beforeEach(function () { - this.set("subject", selectKit()); - }); + hooks.beforeEach(function () { + this.set("subject", selectKit()); + }); - componentTest("content", { - template: hbs`{{single-select content=content}}`, + test("content", async function (assert) { + setDefaultState(this); - beforeEach() { - setDefaultState(this); - }, + await render(hbs``); - async test(assert) { - await this.subject.expand(); + await this.subject.expand(); - const content = this.subject.displayedContent(); - assert.strictEqual(content.length, 3, "it shows rows"); - assert.strictEqual( - content[0].name, - this.content.firstObject.name, - "it has the correct name" - ); - assert.strictEqual( - content[0].id, - this.content.firstObject.id.toString(), - "it has the correct value" - ); - assert.strictEqual( - this.subject.header().value(), - null, - "it doesn't set a value from the content" - ); - }, - }); + const content = this.subject.displayedContent(); + assert.strictEqual(content.length, 3, "it shows rows"); + assert.strictEqual( + content[0].name, + this.content.firstObject.name, + "it has the correct name" + ); + assert.strictEqual( + content[0].id, + this.content.firstObject.id.toString(), + "it has the correct value" + ); + assert.strictEqual( + this.subject.header().value(), + null, + "it doesn't set a value from the content" + ); + }); - componentTest("value", { - template: hbs` - {{single-select - value=value - content=content - nameProperty=nameProperty - valueProperty=valueProperty - onChange=onChange - }} - `, + test("value", async function (assert) { + setDefaultState(this); - beforeEach() { - setDefaultState(this); - }, + await render(hbs` + + `); - test(assert) { - assert.strictEqual( - this.subject.header().value(this.content), - "1", - "it selects the correct content to display" - ); - }, - }); + assert.strictEqual( + this.subject.header().value(this.content), + "1", + "it selects the correct content to display" + ); + }); - componentTest("options.filterable", { - template: hbs` - {{single-select - value=value - content=content - nameProperty=nameProperty - valueProperty=valueProperty - onChange=onChange - options=(hash - filterable=filterable - ) - }} - `, + test("options.filterable", async function (assert) { + setDefaultState(this, { filterable: true }); - beforeEach() { - setDefaultState(this, { filterable: true }); - }, - - async test(assert) { - await this.subject.expand(); - assert.ok(this.subject.filter().exists(), "it shows the filter"); - - const filter = this.subject.displayedContent()[1].name; - await this.subject.fillInFilter(filter); - assert.strictEqual( - this.subject.displayedContent()[0].name, - filter, - "it filters the list" - ); - }, - }); - - componentTest("options.limitMatches", { - template: hbs` - {{single-select - value=value - content=content - nameProperty=nameProperty - valueProperty=valueProperty - onChange=onChange - options=(hash - limitMatches=limitMatches - filterable=filterable - ) - }} - `, - - beforeEach() { - setDefaultState(this, { limitMatches: 1, filterable: true }); - }, - - async test(assert) { - await this.subject.expand(); - await this.subject.fillInFilter("ba"); - - assert.strictEqual( - this.subject.displayedContent().length, - 1, - "it returns only 1 result" - ); - }, - }); - - componentTest("valueAttribute (deprecated)", { - template: hbs` - {{single-select - value=value - content=content - valueAttribute="value" - }} - `, - - beforeEach() { - this.set("value", "normal"); - - const content = [ - { name: "Smallest", value: "smallest" }, - { name: "Smaller", value: "smaller" }, - { name: "Normal", value: "normal" }, - { name: "Larger", value: "larger" }, - { name: "Largest", value: "largest" }, - ]; - this.set("content", content); - }, - - async test(assert) { - await this.subject.expand(); - - assert.strictEqual(this.subject.selectedRow().value(), this.value); - }, - }); - - componentTest("none:string", { - template: hbs` - {{single-select - value=value - content=content - nameProperty=nameProperty - valueProperty=valueProperty - onChange=onChange - options=(hash - none="test.none" - ) - }} - `, - - beforeEach() { - I18n.translations[I18n.locale].js.test = { none: "(default)" }; - setDefaultState(this, { value: 1 }); - }, - - async test(assert) { - await this.subject.expand(); - - const noneRow = this.subject.rowByIndex(0); - assert.strictEqual(noneRow.value(), null); - assert.strictEqual(noneRow.name(), I18n.t("test.none")); - }, - }); - - componentTest("none:object", { - template: hbs` - {{single-select - value=value - content=content - nameProperty=nameProperty - valueProperty=valueProperty - onChange=onChange - options=(hash - none=none - ) - }} - `, - - beforeEach() { - setDefaultState(this, { none: { value: null, name: "(default)" } }); - }, - - async test(assert) { - await this.subject.expand(); - - const noneRow = this.subject.rowByIndex(0); - assert.strictEqual(noneRow.value(), null); - assert.strictEqual(noneRow.name(), "(default)"); - }, - }); - - componentTest("content is a basic array", { - template: hbs` - {{single-select - value=value - content=content - nameProperty=nameProperty - valueProperty=valueProperty - onChange=onChange - options=(hash - none="test.none" - ) - }} - `, - - beforeEach() { - I18n.translations[I18n.locale].js.test = { none: "(default)" }; - setDefaultState(this, { - nameProperty: null, - valueProperty: null, - value: "foo", - content: ["foo", "bar", "baz"], - }); - }, - - async test(assert) { - await this.subject.expand(); - - const noneRow = this.subject.rowByIndex(0); - assert.strictEqual(noneRow.value(), I18n.t("test.none")); - assert.strictEqual(noneRow.name(), I18n.t("test.none")); - assert.strictEqual(this.value, "foo"); - - await this.subject.selectRowByIndex(0); - - assert.strictEqual(this.value, null); - }, - }); - - componentTest("selected value can be 0", { - template: hbs` - {{single-select - value=value - content=content - nameProperty=nameProperty - valueProperty=valueProperty - onChange=onChange - }} - `, - - beforeEach() { - setDefaultState(this, { - value: 1, - content: [ - { id: 0, name: "foo" }, - { id: 1, name: "bar" }, - ], - }); - }, - - async test(assert) { - assert.strictEqual(this.subject.header().value(), "1"); - - await this.subject.expand(); - await this.subject.selectRowByValue(0); - - assert.strictEqual(this.subject.header().value(), "0"); - }, - }); - - componentTest("prevents propagating click event on header", { - template: hbs` - {{#d-button icon='times' action=onClick}} - {{single-select - options=(hash preventsClickPropagation=true) - value=value - content=content + await render(hbs` + + `); - beforeEach() { - this.setProperties({ - onClick: () => this.set("value", "foo"), - content: DEFAULT_CONTENT, - value: DEFAULT_VALUE, - }); - }, + await this.subject.expand(); + assert.ok(this.subject.filter().exists(), "it shows the filter"); - async test(assert) { - assert.strictEqual(this.value, DEFAULT_VALUE); - await this.subject.expand(); - assert.strictEqual(this.value, DEFAULT_VALUE); - }, + const filter = this.subject.displayedContent()[1].name; + await this.subject.fillInFilter(filter); + assert.strictEqual( + this.subject.displayedContent()[0].name, + filter, + "it filters the list" + ); + }); + + test("options.limitMatches", async function (assert) { + setDefaultState(this, { limitMatches: 1, filterable: true }); + + await render(hbs` + + `); + + await this.subject.expand(); + await this.subject.fillInFilter("ba"); + + assert.strictEqual( + this.subject.displayedContent().length, + 1, + "it returns only 1 result" + ); + }); + + test("valueAttribute (deprecated)", async function (assert) { + this.set("value", "normal"); + + const content = [ + { name: "Smallest", value: "smallest" }, + { name: "Smaller", value: "smaller" }, + { name: "Normal", value: "normal" }, + { name: "Larger", value: "larger" }, + { name: "Largest", value: "largest" }, + ]; + this.set("content", content); + + await render(hbs` + + `); + + await this.subject.expand(); + + assert.strictEqual(this.subject.selectedRow().value(), this.value); + }); + + test("none:string", async function (assert) { + I18n.translations[I18n.locale].js.test = { none: "(default)" }; + setDefaultState(this, { value: 1 }); + + await render(hbs` + + `); + + await this.subject.expand(); + + const noneRow = this.subject.rowByIndex(0); + assert.strictEqual(noneRow.value(), null); + assert.strictEqual(noneRow.name(), I18n.t("test.none")); + }); + + test("none:object", async function (assert) { + setDefaultState(this, { none: { value: null, name: "(default)" } }); + + await render(hbs` + + `); + + await this.subject.expand(); + + const noneRow = this.subject.rowByIndex(0); + assert.strictEqual(noneRow.value(), null); + assert.strictEqual(noneRow.name(), "(default)"); + }); + + test("content is a basic array", async function (assert) { + I18n.translations[I18n.locale].js.test = { none: "(default)" }; + setDefaultState(this, { + nameProperty: null, + valueProperty: null, + value: "foo", + content: ["foo", "bar", "baz"], }); - componentTest("labelProperty", { - template: hbs` - {{single-select - labelProperty="foo" - value=value - content=content - }} - `, + await render(hbs` + + `); - beforeEach() { - this.setProperties({ - content: [{ id: 1, name: "john", foo: "JACKSON" }], - value: 1, - }); - }, + await this.subject.expand(); - async test(assert) { - assert.strictEqual(this.subject.header().label(), "JACKSON"); + const noneRow = this.subject.rowByIndex(0); + assert.strictEqual(noneRow.value(), I18n.t("test.none")); + assert.strictEqual(noneRow.name(), I18n.t("test.none")); + assert.strictEqual(this.value, "foo"); - await this.subject.expand(); + await this.subject.selectRowByIndex(0); - const row = this.subject.rowByValue(1); + assert.strictEqual(this.value, null); + }); - assert.strictEqual(row.label(), "JACKSON"); - }, + test("selected value can be 0", async function (assert) { + setDefaultState(this, { + value: 1, + content: [ + { id: 0, name: "foo" }, + { id: 1, name: "bar" }, + ], }); - componentTest("titleProperty", { - template: hbs` - {{single-select - titleProperty="foo" - value=value - content=content - }} - `, + await render(hbs` + + `); - beforeEach() { - this.setProperties({ - content: [{ id: 1, name: "john", foo: "JACKSON" }], - value: 1, - }); - }, + assert.strictEqual(this.subject.header().value(), "1"); - async test(assert) { - assert.strictEqual(this.subject.header().title(), "JACKSON"); + await this.subject.expand(); + await this.subject.selectRowByValue(0); - await this.subject.expand(); + assert.strictEqual(this.subject.header().value(), "0"); + }); - const row = this.subject.rowByValue(1); - - assert.strictEqual(row.title(), "JACKSON"); - }, + test("prevents propagating click event on header", async function (assert) { + this.setProperties({ + onClick: () => this.set("value", "foo"), + content: DEFAULT_CONTENT, + value: DEFAULT_VALUE, }); - componentTest("langProperty", { - template: hbs`{{single-select langProperty="foo" value=value content=content}}`, + await render(hbs` + + + + `); - beforeEach() { - this.setProperties({ - content: [{ id: 1, name: "john", foo: "be" }], - value: null, - }); - }, + assert.strictEqual(this.value, DEFAULT_VALUE); + await this.subject.expand(); + assert.strictEqual(this.value, DEFAULT_VALUE); + }); - async test(assert) { - assert.strictEqual( - this.subject.header().el().querySelector(".selected-name").lang, - "" - ); - - await this.subject.expand(); - - const row = this.subject.rowByValue(1); - assert.strictEqual(row.el().lang, "be"); - - await this.subject.selectRowByValue(1); - - assert.strictEqual( - this.subject.header().el().querySelector(".selected-name").lang, - "be" - ); - }, + test("labelProperty", async function (assert) { + this.setProperties({ + content: [{ id: 1, name: "john", foo: "JACKSON" }], + value: 1, }); - componentTest("name", { - template: hbs`{{single-select value=value content=content}}`, + await render(hbs` + + `); - beforeEach() { - this.setProperties({ - content: [{ id: 1, name: "john" }], - value: null, - }); - }, + assert.strictEqual(this.subject.header().label(), "JACKSON"); - async test(assert) { - assert.strictEqual( - this.subject.header().el().getAttribute("name"), - I18n.t("select_kit.select_to_filter") - ); + await this.subject.expand(); - await this.subject.expand(); - await this.subject.selectRowByValue(1); + const row = this.subject.rowByValue(1); - assert.strictEqual( - this.subject.header().el().getAttribute("name"), - I18n.t("select_kit.filter_by", { - name: this.content.firstObject.name, - }) - ); - }, + assert.strictEqual(row.label(), "JACKSON"); + }); + + test("titleProperty", async function (assert) { + this.setProperties({ + content: [{ id: 1, name: "john", foo: "JACKSON" }], + value: 1, }); - } -); + + await render(hbs` + + `); + + assert.strictEqual(this.subject.header().title(), "JACKSON"); + + await this.subject.expand(); + + const row = this.subject.rowByValue(1); + + assert.strictEqual(row.title(), "JACKSON"); + }); + + test("langProperty", async function (assert) { + this.setProperties({ + content: [{ id: 1, name: "john", foo: "be" }], + value: null, + }); + + await render( + hbs`` + ); + + assert.strictEqual( + this.subject.header().el().querySelector(".selected-name").lang, + "" + ); + + await this.subject.expand(); + + const row = this.subject.rowByValue(1); + assert.strictEqual(row.el().lang, "be"); + + await this.subject.selectRowByValue(1); + + assert.strictEqual( + this.subject.header().el().querySelector(".selected-name").lang, + "be" + ); + }); + + test("name", async function (assert) { + this.setProperties({ + content: [{ id: 1, name: "john" }], + value: null, + }); + + await render( + hbs`` + ); + + assert.strictEqual( + this.subject.header().el().getAttribute("name"), + I18n.t("select_kit.select_to_filter") + ); + + await this.subject.expand(); + await this.subject.selectRowByValue(1); + + assert.strictEqual( + this.subject.header().el().getAttribute("name"), + I18n.t("select_kit.filter_by", { + name: this.content.firstObject.name, + }) + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/tag-drop-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/tag-drop-test.js index d745244802c..d9f83109e80 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/tag-drop-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/tag-drop-test.js @@ -1,13 +1,10 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import I18n from "I18n"; -import Site from "discourse/models/site"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -import pretender from "discourse/tests/helpers/create-pretender"; +import pretender, { response } from "discourse/tests/helpers/create-pretender"; import selectKit from "discourse/tests/helpers/select-kit-helper"; -import { set } from "@ember/object"; function initTags(context) { const categories = context.site.categoriesList; @@ -20,94 +17,70 @@ function initTags(context) { }); } -discourseModule( - "Integration | Component | select-kit/tag-drop", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | select-kit/tag-drop", function (hooks) { + setupRenderingTest(hooks); - hooks.beforeEach(function () { - this.set("subject", selectKit()); + hooks.beforeEach(function () { + this.set("subject", selectKit()); - const site = Site.current(); - set(site, "top_tags", ["jeff", "neil", "arpit", "régis"]); + this.site.set("top_tags", ["jeff", "neil", "arpit", "régis"]); - const response = (object) => { - return [200, { "Content-Type": "application/json" }, object]; - }; - - pretender.get("/tags/filter/search", (params) => { - if (params.queryParams.q === "dav") { - return response({ - results: [{ id: "David", name: "David", count: 2, pm_count: 0 }], - }); - } - }); + pretender.get("/tags/filter/search", (params) => { + if (params.queryParams.q === "dav") { + return response({ + results: [{ id: "David", name: "David", count: 2, pm_count: 0 }], + }); + } }); + }); - componentTest("default", { - template: hbs` - {{tag-drop - currentCategory=currentCategory - tagId=tagId - options=(hash - tagId=tagId - ) - }} - `, + test("default", async function (assert) { + initTags(this); - beforeEach() { - initTags(this); - }, + await render(hbs` + + `); - async test(assert) { - await this.subject.expand(); + await this.subject.expand(); - assert.ok(true); - // const row = this.subject.rowByValue(this.category.id); - // assert.ok( - // exists(row.el().find(".category-desc")), - // "it shows category description for newcomers" - // ); + const content = this.subject.displayedContent(); - const content = this.subject.displayedContent(); + assert.strictEqual( + content[0].name, + I18n.t("tagging.selector_no_tags"), + "it has the translated label for no-tags" + ); + assert.strictEqual( + content[1].name, + I18n.t("tagging.selector_all_tags"), + "it has the correct label for all-tags" + ); - assert.strictEqual( - content[0].name, - I18n.t("tagging.selector_no_tags"), - "it has the translated label for no-tags" - ); - assert.strictEqual( - content[1].name, - I18n.t("tagging.selector_all_tags"), - "it has the correct label for all-tags" - ); + await this.subject.fillInFilter("dav"); - await this.subject.fillInFilter("dav"); + assert.strictEqual( + this.subject.rows()[0].textContent.trim(), + "David", + "it has no tag count when filtering in a category context" + ); + }); - assert.strictEqual( - this.subject.rows()[0].textContent.trim(), - "David", - "it has no tag count when filtering in a category context" - ); - }, - }); + test("default global (no category)", async function (assert) { + await render(hbs``); - componentTest("default global (no category)", { - template: hbs`{{tag-drop}}`, + await this.subject.expand(); + await this.subject.fillInFilter("dav"); - async test(assert) { - await this.subject.expand(); - - assert.ok(true); - - await this.subject.fillInFilter("dav"); - - assert.strictEqual( - this.subject.rows()[0].textContent.trim(), - "David x2", - "it has the tag count" - ); - }, - }); - } -); + assert.strictEqual( + this.subject.rows()[0].textContent.trim(), + "David x2", + "it has the tag count" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/topic-notifications-button-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/topic-notifications-button-test.js index 500d7a1ab26..163d1208a41 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/topic-notifications-button-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/topic-notifications-button-test.js @@ -1,12 +1,9 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import I18n from "I18n"; import Topic from "discourse/models/topic"; -import { - discourseModule, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; @@ -28,7 +25,7 @@ const buildTopic = function (opts) { const originalTranslation = I18n.translations.en.js.topic.notifications.tracking_pm.title; -discourseModule( +module( "Integration | Component | select-kit/topic-notifications-button", function (hooks) { setupRenderingTest(hooks); @@ -38,247 +35,192 @@ discourseModule( originalTranslation; }); - componentTest("the header has a localized title", { - template: hbs` - {{topic-notifications-button - notificationLevel=topic.details.notification_level - topic=topic - }} - `, + test("the header has a localized title", async function (assert) { + this.set("topic", buildTopic({ level: 1 })); - beforeEach() { - this.set("topic", buildTopic({ level: 1 })); - }, + await render(hbs` + + `); - async test(assert) { - assert.strictEqual( - selectKit().header().label(), - "Normal", - "it has the correct label" - ); + assert.strictEqual( + selectKit().header().label(), + "Normal", + "it has the correct label" + ); - await this.set("topic", buildTopic({ level: 2 })); + this.set("topic", buildTopic({ level: 2 })); - assert.strictEqual( - selectKit().header().label(), - "Tracking", - "it correctly changes the label" - ); - }, + assert.strictEqual( + selectKit().header().label(), + "Tracking", + "it correctly changes the label" + ); }); - componentTest("the header has a localized title", { - template: hbs` - {{topic-notifications-button - notificationLevel=topic.details.notification_level - topic=topic - }} - `, + test("the header has a localized title", async function (assert) { + I18n.translations.en.js.topic.notifications.tracking_pm.title = `${originalTranslation} PM`; + this.set("topic", buildTopic({ level: 2, archetype: "private_message" })); - beforeEach() { - I18n.translations.en.js.topic.notifications.tracking_pm.title = `${originalTranslation} PM`; - this.set( - "topic", - buildTopic({ level: 2, archetype: "private_message" }) - ); - }, + await render(hbs` + + `); - test(assert) { - assert.strictEqual( - selectKit().header().label(), - `${originalTranslation} PM`, - "it has the correct label for PMs" - ); - }, + assert.strictEqual( + selectKit().header().label(), + `${originalTranslation} PM`, + "it has the correct label for PMs" + ); }); - componentTest("notification reason text - user mailing list mode", { - template: hbs` - {{topic-notifications-button - notificationLevel=topic.details.notification_level - topic=topic - }} - `, + test("notification reason text - user mailing list mode", async function (assert) { + this.currentUser.set("mailing_list_mode", true); + this.set("topic", buildTopic({ level: 2 })); - beforeEach() { - this.currentUser.set("mailing_list_mode", true); - this.set("topic", buildTopic({ level: 2 })); - }, + await render(hbs` + + `); - test(assert) { - assert.strictEqual( - queryAll(".topic-notifications-button .text").text(), - I18n.t("topic.notifications.reasons.mailing_list_mode"), - "mailing_list_mode enabled for the user shows unique text" - ); - }, + assert.strictEqual( + query(".topic-notifications-button .text").innerText, + I18n.t("topic.notifications.reasons.mailing_list_mode"), + "mailing_list_mode enabled for the user shows unique text" + ); }); - componentTest("notification reason text - bad notification reason", { - template: hbs` - {{topic-notifications-button - notificationLevel=topic.details.notification_level - topic=topic - }} - `, + test("notification reason text - bad notification reason", async function (assert) { + this.set("topic", buildTopic({ level: 2 })); - beforeEach() { - this.set("topic", buildTopic({ level: 2 })); - }, + await render(hbs` + + `); - test(assert) { - this.set("topic", buildTopic({ level: 3, reason: 999 })); + this.set("topic", buildTopic({ level: 3, reason: 999 })); - assert.strictEqual( - queryAll(".topic-notifications-button .text").text(), - I18n.t("topic.notifications.reasons.3"), - "fallback to regular level translation if reason does not exist" - ); - }, + assert.strictEqual( + query(".topic-notifications-button .text").innerText, + I18n.t("topic.notifications.reasons.3"), + "fallback to regular level translation if reason does not exist" + ); }); - componentTest("notification reason text - user tracking category", { - template: hbs` - {{topic-notifications-button - notificationLevel=topic.details.notification_level - topic=topic - }} - `, + test("notification reason text - user tracking category", async function (assert) { + this.currentUser.set("tracked_category_ids", [88]); + this.set("topic", buildTopic({ level: 2, reason: 8, category_id: 88 })); - beforeEach() { - this.currentUser.set("tracked_category_ids", [88]); - this.set("topic", buildTopic({ level: 2, reason: 8, category_id: 88 })); - }, + await render(hbs` + + `); - test(assert) { - assert.strictEqual( - queryAll(".topic-notifications-button .text").text(), - I18n.t("topic.notifications.reasons.2_8"), - "use 2_8 notification if user is still tracking category" - ); - }, + assert.strictEqual( + query(".topic-notifications-button .text").innerText, + I18n.t("topic.notifications.reasons.2_8"), + "use 2_8 notification if user is still tracking category" + ); }); - componentTest( - "notification reason text - user no longer tracking category", - { - template: hbs` - {{topic-notifications-button - notificationLevel=topic.details.notification_level - topic=topic - }} - `, + test("notification reason text - user no longer tracking category", async function (assert) { + this.currentUser.set("tracked_category_ids", []); + this.set("topic", buildTopic({ level: 2, reason: 8, category_id: 88 })); - beforeEach() { - this.currentUser.set("tracked_category_ids", []); - this.set( - "topic", - buildTopic({ level: 2, reason: 8, category_id: 88 }) - ); - }, + await render(hbs` + + `); - test(assert) { - assert.strictEqual( - queryAll(".topic-notifications-button .text").text(), - I18n.t("topic.notifications.reasons.2_8_stale"), - "use _stale notification if user is no longer tracking category" - ); - }, - } - ); - - componentTest("notification reason text - user watching category", { - template: hbs` - {{topic-notifications-button - notificationLevel=topic.details.notification_level - topic=topic - }} - `, - - beforeEach() { - this.currentUser.set("watched_category_ids", [88]); - this.set("topic", buildTopic({ level: 3, reason: 6, category_id: 88 })); - }, - - test(assert) { - assert.strictEqual( - queryAll(".topic-notifications-button .text").text(), - I18n.t("topic.notifications.reasons.3_6"), - "use 3_6 notification if user is still watching category" - ); - }, + assert.strictEqual( + query(".topic-notifications-button .text").innerText, + I18n.t("topic.notifications.reasons.2_8_stale"), + "use _stale notification if user is no longer tracking category" + ); }); - componentTest( - "notification reason text - user no longer watching category", - { - template: hbs` - {{topic-notifications-button - notificationLevel=topic.details.notification_level - topic=topic - }} - `, + test("notification reason text - user watching category", async function (assert) { + this.currentUser.set("watched_category_ids", [88]); + this.set("topic", buildTopic({ level: 3, reason: 6, category_id: 88 })); - beforeEach() { - this.currentUser.set("watched_category_ids", []); - this.set( - "topic", - buildTopic({ level: 3, reason: 6, category_id: 88 }) - ); - }, + await render(hbs` + + `); - test(assert) { - assert.strictEqual( - queryAll(".topic-notifications-button .text").text(), - I18n.t("topic.notifications.reasons.3_6_stale"), - "use _stale notification if user is no longer watching category" - ); - }, - } - ); - - componentTest("notification reason text - user watching tag", { - template: hbs` - {{topic-notifications-button - notificationLevel=topic.details.notification_level - topic=topic - }} - `, - - beforeEach() { - this.currentUser.set("watched_tags", ["test"]); - this.set("topic", buildTopic({ level: 3, reason: 10, tags: ["test"] })); - }, - - test(assert) { - assert.strictEqual( - queryAll(".topic-notifications-button .text").text(), - I18n.t("topic.notifications.reasons.3_10"), - "use 3_10 notification if user is still watching tag" - ); - }, + assert.strictEqual( + query(".topic-notifications-button .text").innerText, + I18n.t("topic.notifications.reasons.3_6"), + "use 3_6 notification if user is still watching category" + ); }); - componentTest("notification reason text - user no longer watching tag", { - template: hbs` - {{topic-notifications-button - notificationLevel=topic.details.notification_level - topic=topic - }} - `, + test("notification reason text - user no longer watching category", async function (assert) { + this.currentUser.set("watched_category_ids", []); + this.set("topic", buildTopic({ level: 3, reason: 6, category_id: 88 })); - beforeEach() { - this.currentUser.set("watched_tags", []); - this.set("topic", buildTopic({ level: 3, reason: 10, tags: ["test"] })); - }, + await render(hbs` + + `); - test(assert) { - assert.strictEqual( - queryAll(".topic-notifications-button .text").text(), - I18n.t("topic.notifications.reasons.3_10_stale"), - "use _stale notification if user is no longer watching tag" - ); - }, + assert.strictEqual( + query(".topic-notifications-button .text").innerText, + I18n.t("topic.notifications.reasons.3_6_stale"), + "use _stale notification if user is no longer watching category" + ); + }); + + test("notification reason text - user watching tag", async function (assert) { + this.currentUser.set("watched_tags", ["test"]); + this.set("topic", buildTopic({ level: 3, reason: 10, tags: ["test"] })); + + await render(hbs` + + `); + + assert.strictEqual( + query(".topic-notifications-button .text").innerText, + I18n.t("topic.notifications.reasons.3_10"), + "use 3_10 notification if user is still watching tag" + ); + }); + + test("notification reason text - user no longer watching tag", async function (assert) { + this.currentUser.set("watched_tags", []); + this.set("topic", buildTopic({ level: 3, reason: 10, tags: ["test"] })); + + await render(hbs` + + `); + + assert.strictEqual( + query(".topic-notifications-button .text").innerText, + I18n.t("topic.notifications.reasons.3_10_stale"), + "use _stale notification if user is no longer watching tag" + ); }); } ); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/topic-notifications-options-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/topic-notifications-options-test.js index 027b40f8a20..394a3f045ec 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/topic-notifications-options-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/topic-notifications-options-test.js @@ -1,9 +1,8 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import I18n from "I18n"; import Topic from "discourse/models/topic"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; @@ -29,76 +28,69 @@ function getTranslations(type = "") { }); } -discourseModule( +module( "Integration | Component | select-kit/topic-notifications-options", function (hooks) { setupRenderingTest(hooks); - componentTest("regular topic notification level descriptions", { - template: hbs` - {{topic-notifications-options - value=topic.details.notification_level - topic=topic - }} - `, + test("regular topic notification level descriptions", async function (assert) { + this.set("topic", buildTopic("regular")); - beforeEach() { - this.set("topic", buildTopic("regular")); - }, + await render(hbs` + + `); - async test(assert) { - await selectKit().expand(); + await selectKit().expand(); - const uiTexts = extractDescriptions(selectKit().rows()); - const descriptions = getTranslations(); + const uiTexts = extractDescriptions(selectKit().rows()); + const descriptions = getTranslations(); + assert.strictEqual( + uiTexts.length, + descriptions.length, + "it has the correct copy" + ); + + uiTexts.forEach((text, index) => { assert.strictEqual( - uiTexts.length, - descriptions.length, + text.trim(), + descriptions[index].trim(), "it has the correct copy" ); - uiTexts.forEach((text, index) => { - assert.strictEqual( - text.trim(), - descriptions[index].trim(), - "it has the correct copy" - ); - }); - }, + }); }); - componentTest("PM topic notification level descriptions", { - template: hbs` - {{topic-notifications-options - value=topic.details.notification_level - topic=topic - }} - `, + test("PM topic notification level descriptions", async function (assert) { + this.set("topic", buildTopic("private_message")); - beforeEach() { - this.set("topic", buildTopic("private_message")); - }, + await render(hbs` + + `); - async test(assert) { - await selectKit().expand(); + await selectKit().expand(); - const uiTexts = extractDescriptions(selectKit().rows()); - const descriptions = getTranslations("_pm"); + const uiTexts = extractDescriptions(selectKit().rows()); + const descriptions = getTranslations("_pm"); + assert.strictEqual( + uiTexts.length, + descriptions.length, + "it has the correct copy" + ); + + uiTexts.forEach((text, index) => { assert.strictEqual( - uiTexts.length, - descriptions.length, + text.trim(), + descriptions[index].trim(), "it has the correct copy" ); - - uiTexts.forEach((text, index) => { - assert.strictEqual( - text.trim(), - descriptions[index].trim(), - "it has the correct copy" - ); - }); - }, + }); }); } ); diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/user-chooser-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/user-chooser-test.js index 74b7a2eb213..80d6d360ceb 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/user-chooser-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/user-chooser-test.js @@ -1,43 +1,31 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; -discourseModule( - "Integration | Component | select-kit/user-chooser", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | select-kit/user-chooser", function (hooks) { + setupRenderingTest(hooks); - hooks.beforeEach(function () { - this.set("subject", selectKit()); - }); + hooks.beforeEach(function () { + this.set("subject", selectKit()); + }); - componentTest("displays usernames", { - template: hbs`{{user-chooser value=value}}`, + test("displays usernames", async function (assert) { + this.set("value", ["bob", "martin"]); - beforeEach() { - this.set("value", ["bob", "martin"]); - }, + await render(hbs``); - async test(assert) { - assert.strictEqual(this.subject.header().name(), "bob,martin"); - }, - }); + assert.strictEqual(this.subject.header().name(), "bob,martin"); + }); - componentTest("can remove a username", { - template: hbs`{{user-chooser value=value}}`, + test("can remove a username", async function (assert) { + this.set("value", ["bob", "martin"]); - beforeEach() { - this.set("value", ["bob", "martin"]); - }, + await render(hbs``); - async test(assert) { - await this.subject.expand(); - await this.subject.deselectItemByValue("bob"); - assert.strictEqual(this.subject.header().name(), "martin"); - }, - }); - } -); + await this.subject.expand(); + await this.subject.deselectItemByValue("bob"); + assert.strictEqual(this.subject.header().name(), "martin"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/simple-list-test.js b/app/assets/javascripts/discourse/tests/integration/components/simple-list-test.js index 3ba4ad2f7db..223ffe7eaba 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/simple-list-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/simple-list-test.js @@ -1,3 +1,5 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; import { blur, click, @@ -5,57 +7,45 @@ import { render, triggerKeyEvent, } from "@ember/test-helpers"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; +import { count, exists, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -import { test } from "qunit"; -discourseModule("Integration | Component | simple-list", function (hooks) { +module("Integration | Component | simple-list", function (hooks) { setupRenderingTest(hooks); - componentTest("adding a value", { - template: hbs`{{simple-list values=values}}`, + test("adding a value", async function (assert) { + this.set("values", "vinkas\nosama"); - beforeEach() { - this.set("values", "vinkas\nosama"); - }, + await render(hbs``); - async test(assert) { - assert.ok( - exists(".add-value-btn[disabled]"), - "while loading the + button is disabled" - ); + assert.ok( + exists(".add-value-btn[disabled]"), + "while loading the + button is disabled" + ); - await fillIn(".add-value-input", "penar"); - await click(".add-value-btn"); + await fillIn(".add-value-input", "penar"); + await click(".add-value-btn"); - assert.strictEqual( - count(".values .value"), - 3, - "it adds the value to the list of values" - ); + assert.strictEqual( + count(".values .value"), + 3, + "it adds the value to the list of values" + ); - assert.ok( - query(".values .value[data-index='2'] .value-input").value === "penar", - "it sets the correct value for added item" - ); + assert.strictEqual( + query(".values .value[data-index='2'] .value-input").value, + "penar", + "it sets the correct value for added item" + ); - await fillIn(".add-value-input", "eviltrout"); - await triggerKeyEvent(".add-value-input", "keydown", 13); // enter + await fillIn(".add-value-input", "eviltrout"); + await triggerKeyEvent(".add-value-input", "keydown", 13); // enter - assert.strictEqual( - count(".values .value"), - 4, - "it adds the value when keying Enter" - ); - }, + assert.strictEqual( + count(".values .value"), + 4, + "it adds the value when keying Enter" + ); }); test("changing a value", async function (assert) { @@ -67,7 +57,9 @@ discourseModule("Integration | Component | simple-list", function (hooks) { done(); }); - await render(hbs`{{simple-list values=values onChange=onChange}}`); + await render( + hbs`` + ); await fillIn(".values .value[data-index='1'] .value-input", "jarek"); await blur(".values .value[data-index='1'] .value-input"); @@ -78,51 +70,46 @@ discourseModule("Integration | Component | simple-list", function (hooks) { ); }); - componentTest("removing a value", { - template: hbs`{{simple-list values=values}}`, + test("removing a value", async function (assert) { + this.set("values", "vinkas\nosama"); - beforeEach() { - this.set("values", "vinkas\nosama"); - }, + await render(hbs``); - async test(assert) { - await click(".values .value[data-index='0'] .remove-value-btn"); + await click(".values .value[data-index='0'] .remove-value-btn"); - assert.strictEqual( - count(".values .value"), - 1, - "it removes the value from the list of values" - ); + assert.strictEqual( + count(".values .value"), + 1, + "it removes the value from the list of values" + ); - assert.ok( - query(".values .value[data-index='0'] .value-input").value === "osama", - "it removes the correct value" - ); - }, + assert.strictEqual( + query(".values .value[data-index='0'] .value-input").value, + "osama", + "it removes the correct value" + ); }); - componentTest("delimiter support", { - template: hbs`{{simple-list values=values inputDelimiter='|'}}`, + test("delimiter support", async function (assert) { + this.set("values", "vinkas|osama"); - beforeEach() { - this.set("values", "vinkas|osama"); - }, + await render( + hbs`` + ); - async test(assert) { - await fillIn(".add-value-input", "eviltrout"); - await click(".add-value-btn"); + await fillIn(".add-value-input", "eviltrout"); + await click(".add-value-btn"); - assert.strictEqual( - count(".values .value"), - 3, - "it adds the value to the list of values" - ); + assert.strictEqual( + count(".values .value"), + 3, + "it adds the value to the list of values" + ); - assert.ok( - query(".values .value[data-index='2'] .value-input").value === - "eviltrout", - "it adds the correct value" - ); - }, + assert.strictEqual( + query(".values .value[data-index='2'] .value-input").value, + "eviltrout", + "it adds the correct value" + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/site-header-test.js b/app/assets/javascripts/discourse/tests/integration/components/site-header-test.js index 6574a061440..7ec05275f63 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/site-header-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/site-header-test.js @@ -1,16 +1,11 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { count, exists } from "discourse/tests/helpers/qunit-helpers"; import pretender from "discourse/tests/helpers/create-pretender"; import hbs from "htmlbars-inline-precompile"; -import { click } from "@ember/test-helpers"; -discourseModule("Integration | Component | site-header", function (hooks) { +module("Integration | Component | site-header", function (hooks) { setupRenderingTest(hooks); hooks.beforeEach(function () { @@ -18,43 +13,40 @@ discourseModule("Integration | Component | site-header", function (hooks) { this.currentUser.set("read_first_notification", false); }); - componentTest("first notification mask", { - template: hbs`{{site-header}}`, + test("first notification mask", async function (assert) { + await render(hbs``); - async test(assert) { - assert.strictEqual( - count(".ring-backdrop"), - 1, - "there is the first notification mask" - ); + assert.strictEqual( + count(".ring-backdrop"), + 1, + "there is the first notification mask" + ); - // Click anywhere - await click("header.d-header"); + // Click anywhere + await click("header.d-header"); - assert.ok( - !exists(".ring-backdrop"), - "it hides the first notification mask" - ); - }, + assert.ok( + !exists(".ring-backdrop"), + "it hides the first notification mask" + ); }); - componentTest("do not call authenticated endpoints as anonymous", { - template: hbs`{{site-header}}`, - anonymous: true, + test("do not call authenticated endpoints as anonymous", async function (assert) { + this.owner.unregister("current-user:main"); - async test(assert) { - assert.ok( - !exists(".ring-backdrop"), - "there is no first notification mask for anonymous users" - ); + await render(hbs``); - pretender.get("/notifications", () => { - assert.ok(false, "it should not try to refresh notifications"); - return [403, { "Content-Type": "application/json" }, {}]; - }); + assert.ok( + !exists(".ring-backdrop"), + "there is no first notification mask for anonymous users" + ); - // Click anywhere - await click("header.d-header"); - }, + pretender.get("/notifications", () => { + assert.ok(false, "it should not try to refresh notifications"); + return [403, { "Content-Type": "application/json" }, {}]; + }); + + // Click anywhere + await click("header.d-header"); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/site-setting-test.js b/app/assets/javascripts/discourse/tests/integration/components/site-setting-test.js new file mode 100644 index 00000000000..afc1e634b42 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/site-setting-test.js @@ -0,0 +1,21 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; + +module("Integration | Component | site-setting", function (hooks) { + setupRenderingTest(hooks); + + test("displays host-list setting value", async function (assert) { + this.set("setting", { + setting: "blocked_onebox_domains", + value: "a.com|b.com", + type: "host_list", + }); + + await render(hbs``); + + assert.strictEqual(query(".formatted-selection").innerText, "a.com, b.com"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/slow-mode-info-test.js b/app/assets/javascripts/discourse/tests/integration/components/slow-mode-info-test.js index 628b15e8b3a..03c3ed04a7f 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/slow-mode-info-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/slow-mode-info-test.js @@ -1,82 +1,62 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { count, exists } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | slow-mode-info", function (hooks) { +module("Integration | Component | slow-mode-info", function (hooks) { setupRenderingTest(hooks); - componentTest("doesn't render if the topic is closed", { - template: hbs`{{slow-mode-info topic=topic}}`, + test("doesn't render if the topic is closed", async function (assert) { + this.set("topic", { slow_mode_seconds: 3600, closed: true }); - beforeEach() { - this.set("topic", { slow_mode_seconds: 3600, closed: true }); - }, + await render(hbs``); - test(assert) { - assert.ok(!exists(".slow-mode-heading"), "it doesn't render the notice"); - }, + assert.ok(!exists(".slow-mode-heading"), "it doesn't render the notice"); }); - componentTest("doesn't render if the slow mode is disabled", { - template: hbs`{{slow-mode-info topic=topic}}`, + test("doesn't render if the slow mode is disabled", async function (assert) { + this.set("topic", { slow_mode_seconds: 0, closed: false }); - beforeEach() { - this.set("topic", { slow_mode_seconds: 0, closed: false }); - }, + await render(hbs``); - test(assert) { - assert.ok(!exists(".slow-mode-heading"), "it doesn't render the notice"); - }, + assert.ok(!exists(".slow-mode-heading"), "it doesn't render the notice"); }); - componentTest("renders if slow mode is enabled", { - template: hbs`{{slow-mode-info topic=topic}}`, + test("renders if slow mode is enabled", async function (assert) { + this.set("topic", { slow_mode_seconds: 3600, closed: false }); - beforeEach() { - this.set("topic", { slow_mode_seconds: 3600, closed: false }); - }, + await render(hbs``); - test(assert) { - assert.strictEqual(count(".slow-mode-heading"), 1); - }, + assert.strictEqual(count(".slow-mode-heading"), 1); }); - componentTest("staff and TL4 users can disable slow mode", { - template: hbs`{{slow-mode-info topic=topic user=user}}`, + test("staff and TL4 users can disable slow mode", async function (assert) { + this.setProperties({ + topic: { slow_mode_seconds: 3600, closed: false }, + user: { canManageTopic: true }, + }); - beforeEach() { - this.setProperties({ - topic: { slow_mode_seconds: 3600, closed: false }, - user: { canManageTopic: true }, - }); - }, + await render( + hbs`` + ); - test(assert) { - assert.strictEqual(count(".slow-mode-remove"), 1); - }, + assert.strictEqual(count(".slow-mode-remove"), 1); }); - componentTest("regular users can't disable slow mode", { - template: hbs`{{slow-mode-info topic=topic user=user}}`, + test("regular users can't disable slow mode", async function (assert) { + this.setProperties({ + topic: { slow_mode_seconds: 3600, closed: false }, + user: { canManageTopic: false }, + }); - beforeEach() { - this.setProperties({ - topic: { slow_mode_seconds: 3600, closed: false }, - user: { canManageTopic: false }, - }); - }, + await render( + hbs`` + ); - test(assert) { - assert.ok( - !exists(".slow-mode-remove"), - "it doesn't let you disable slow mode" - ); - }, + assert.ok( + !exists(".slow-mode-remove"), + "it doesn't let you disable slow mode" + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/software-update-prompt-test.js b/app/assets/javascripts/discourse/tests/integration/components/software-update-prompt-test.js new file mode 100644 index 00000000000..6fb93bacf2b --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/software-update-prompt-test.js @@ -0,0 +1,35 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { + count, + exists, + publishToMessageBus, +} from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import { later } from "@ember/runloop"; + +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}}`); + + assert.ok( + !exists("div.software-update-prompt"), + "it does not have the class to show the prompt" + ); + + publishToMessageBus("/global/asset-version", "somenewversion"); + + const done = assert.async(); + later(() => { + assert.strictEqual( + count("div.software-update-prompt.require-software-refresh"), + 1, + "it does have the class to show the prompt" + ); + done(); + }, 10); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/text-field-test.js b/app/assets/javascripts/discourse/tests/integration/components/text-field-test.js index 250052e6163..3a56a9810aa 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/text-field-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/text-field-test.js @@ -1,102 +1,84 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import I18n from "I18n"; -import { fillIn } from "@ember/test-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { fillIn, render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import sinon from "sinon"; +import I18n from "I18n"; -discourseModule("Integration | Component | text-field", function (hooks) { +module("Integration | Component | text-field", function (hooks) { setupRenderingTest(hooks); - componentTest("renders correctly with no properties set", { - template: hbs`{{text-field}}`, + test("renders correctly with no properties set", async function (assert) { + await render(hbs``); - test(assert) { - assert.ok(exists("input[type=text]")); - }, + assert.ok(exists("input[type=text]")); }); - componentTest("support a placeholder", { - template: hbs`{{text-field placeholderKey="placeholder.i18n.key"}}`, + test("support a placeholder", async function (assert) { + sinon.stub(I18n, "t").returnsArg(0); - beforeEach() { - sinon.stub(I18n, "t").returnsArg(0); - }, + await render(hbs``); - test(assert) { - assert.ok(exists("input[type=text]")); - assert.strictEqual( - queryAll("input").prop("placeholder"), - "placeholder.i18n.key" - ); - }, + assert.ok(exists("input[type=text]")); + assert.strictEqual(query("input").placeholder, "placeholder.i18n.key"); }); - componentTest("sets the dir attribute to ltr for Hebrew text", { - template: hbs`{{text-field value='זהו שם עברי עם מקום עברי'}}`, - beforeEach() { - this.siteSettings.support_mixed_text_direction = true; - }, + test("sets the dir attribute to ltr for Hebrew text", async function (assert) { + this.siteSettings.support_mixed_text_direction = true; - test(assert) { - assert.strictEqual(queryAll("input").attr("dir"), "rtl"); - }, + await render(hbs``); + + assert.strictEqual(query("input").getAttribute("dir"), "rtl"); }); - componentTest("sets the dir attribute to ltr for English text", { - template: hbs`{{text-field value='This is a ltr title'}}`, - beforeEach() { - this.siteSettings.support_mixed_text_direction = true; - }, + test("sets the dir attribute to ltr for English text", async function (assert) { + this.siteSettings.support_mixed_text_direction = true; - test(assert) { - assert.strictEqual(queryAll("input").attr("dir"), "ltr"); - }, + await render(hbs``); + + assert.strictEqual(query("input").getAttribute("dir"), "ltr"); }); - componentTest("supports onChange", { - template: hbs`{{text-field class="tf-test" value=value onChange=changed}}`, - beforeEach() { - this.called = false; - this.newValue = null; - this.set("value", "hello"); - this.set("changed", (v) => { - this.newValue = v; - this.called = true; - }); - }, - async test(assert) { - await fillIn(".tf-test", "hello"); - assert.ok(!this.called); - await fillIn(".tf-test", "new text"); - assert.ok(this.called); - assert.strictEqual(this.newValue, "new text"); - }, + test("supports onChange", async function (assert) { + this.called = false; + this.newValue = null; + this.set("value", "hello"); + this.set("changed", (v) => { + this.newValue = v; + this.called = true; + }); + + await render( + hbs`` + ); + + await fillIn(".tf-test", "hello"); + assert.ok(!this.called); + + await fillIn(".tf-test", "new text"); + assert.ok(this.called); + assert.strictEqual(this.newValue, "new text"); }); - componentTest("supports onChangeImmediate", { - template: hbs`{{text-field class="tf-test" value=value onChangeImmediate=changed}}`, - beforeEach() { - this.called = false; - this.newValue = null; - this.set("value", "old"); - this.set("changed", (v) => { - this.newValue = v; - this.called = true; - }); - }, - async test(assert) { - await fillIn(".tf-test", "old"); - assert.ok(!this.called); - await fillIn(".tf-test", "no longer old"); - assert.ok(this.called); - assert.strictEqual(this.newValue, "no longer old"); - }, + test("supports onChangeImmediate", async function (assert) { + this.called = false; + this.newValue = null; + this.set("value", "old"); + this.set("changed", (v) => { + this.newValue = v; + this.called = true; + }); + + await render( + hbs`` + ); + + await fillIn(".tf-test", "old"); + assert.ok(!this.called); + + await fillIn(".tf-test", "no longer old"); + assert.ok(this.called); + assert.strictEqual(this.newValue, "no longer old"); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/themes-list-item-test.js b/app/assets/javascripts/discourse/tests/integration/components/themes-list-item-test.js index 49a74ca2961..ed875355619 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/themes-list-item-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/themes-list-item-test.js @@ -1,104 +1,87 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { count, query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; import I18n from "I18n"; import Theme from "admin/models/theme"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | themes-list-item", function (hooks) { +module("Integration | Component | themes-list-item", function (hooks) { setupRenderingTest(hooks); - componentTest("default theme", { - template: hbs`{{themes-list-item theme=theme}}`, - beforeEach() { - this.set("theme", Theme.create({ name: "Test", default: true })); - }, - test(assert) { - assert.expect(1); - assert.strictEqual(count(".d-icon-check"), 1, "shows default theme icon"); - }, + test("default theme", async function (assert) { + this.set("theme", Theme.create({ name: "Test", default: true })); + + await render(hbs``); + + assert.expect(1); + assert.strictEqual(count(".d-icon-check"), 1, "shows default theme icon"); }); - componentTest("pending updates", { - template: hbs`{{themes-list-item theme=theme}}`, - beforeEach() { - this.set( - "theme", - Theme.create({ name: "Test", remote_theme: { commits_behind: 6 } }) - ); - }, + test("pending updates", async function (assert) { + this.set( + "theme", + Theme.create({ name: "Test", remote_theme: { commits_behind: 6 } }) + ); - test(assert) { - assert.expect(1); - assert.strictEqual(count(".d-icon-sync"), 1, "shows pending update icon"); - }, + await render(hbs``); + + assert.expect(1); + assert.strictEqual(count(".d-icon-sync"), 1, "shows pending update icon"); }); - componentTest("broken theme", { - template: hbs`{{themes-list-item theme=theme}}`, - beforeEach() { - this.set( - "theme", - Theme.create({ - name: "Test", - theme_fields: [{ name: "scss", type_id: 1, error: "something" }], - }) - ); - }, + test("broken theme", async function (assert) { + this.set( + "theme", + Theme.create({ + name: "Test", + theme_fields: [{ name: "scss", type_id: 1, error: "something" }], + }) + ); - test(assert) { - assert.expect(1); - assert.strictEqual( - count(".d-icon-exclamation-circle"), - 1, - "shows broken theme icon" - ); - }, + await render(hbs``); + + assert.expect(1); + assert.strictEqual( + count(".d-icon-exclamation-circle"), + 1, + "shows broken theme icon" + ); }); - componentTest("with children", { - template: hbs`{{themes-list-item theme=theme}}`, + test("with children", async function (assert) { + this.childrenList = [1, 2, 3, 4, 5].map((num) => + Theme.create({ name: `Child ${num}`, component: true }) + ); - beforeEach() { - this.childrenList = [1, 2, 3, 4, 5].map((num) => - Theme.create({ name: `Child ${num}`, component: true }) - ); + this.set( + "theme", + Theme.create({ + name: "Test", + childThemes: this.childrenList, + default: true, + }) + ); - this.set( - "theme", - Theme.create({ - name: "Test", - childThemes: this.childrenList, - default: true, - }) - ); - }, + await render(hbs``); - test(assert) { - assert.expect(2); - assert.deepEqual( - queryAll(".components") - .text() - .trim() - .split(",") - .map((n) => n.trim()) - .join(","), - this.childrenList - .splice(0, 4) - .map((theme) => theme.get("name")) - .join(","), - "lists the first 4 children" - ); - assert.deepEqual( - queryAll(".others-count").text().trim(), - I18n.t("admin.customize.theme.and_x_more", { count: 1 }), - "shows count of remaining children" - ); - }, + assert.expect(2); + assert.deepEqual( + query(".components") + .innerText.trim() + .split(",") + .map((n) => n.trim()) + .join(","), + this.childrenList + .splice(0, 4) + .map((theme) => theme.get("name")) + .join(","), + "lists the first 4 children" + ); + assert.deepEqual( + query(".others-count").innerText.trim(), + I18n.t("admin.customize.theme.and_x_more", { count: 1 }), + "shows count of remaining children" + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/themes-list-test.js b/app/assets/javascripts/discourse/tests/integration/components/themes-list-test.js index 6392cc84b81..aa4affe1d14 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/themes-list-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/themes-list-test.js @@ -1,17 +1,15 @@ -import Theme, { COMPONENTS, THEMES } from "admin/models/theme"; -import I18n from "I18n"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, fillIn, render } from "@ember/test-helpers"; import { count, - discourseModule, exists, query, queryAll, } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -import { click, fillIn } from "@ember/test-helpers"; +import Theme, { COMPONENTS, THEMES } from "admin/models/theme"; +import I18n from "I18n"; function createThemes(itemsCount, customAttributesCallback) { return [...Array(itemsCount)].map((_, i) => { @@ -23,273 +21,254 @@ function createThemes(itemsCount, customAttributesCallback) { }); } -discourseModule("Integration | Component | themes-list", function (hooks) { +module("Integration | Component | themes-list", function (hooks) { setupRenderingTest(hooks); - componentTest("current tab is themes", { - template: hbs`{{themes-list themes=themes components=components currentTab=currentTab}}`, - beforeEach() { - this.themes = createThemes(5); - this.components = createThemes(5, (n) => { - return { - name: `Child ${n}`, - component: true, - parentThemes: [this.themes[n - 1]], - parent_themes: [1, 2, 3, 4, 5], - }; - }); - this.setProperties({ - themes: this.themes, - components: this.components, - currentTab: THEMES, - }); - }, - test(assert) { - assert.strictEqual( - queryAll(".themes-tab").hasClass("active"), - true, - "themes tab is active" - ); - assert.strictEqual( - queryAll(".components-tab").hasClass("active"), - false, - "components tab is not active" - ); + test("current tab is themes", async function (assert) { + this.themes = createThemes(5); + this.components = createThemes(5, (n) => { + return { + name: `Child ${n}`, + component: true, + parentThemes: [this.themes[n - 1]], + parent_themes: [1, 2, 3, 4, 5], + }; + }); + this.setProperties({ + themes: this.themes, + components: this.components, + currentTab: THEMES, + }); - assert.strictEqual( - queryAll(".inactive-indicator").index(), - -1, - "there is no inactive themes separator when all themes are inactive" - ); - assert.strictEqual(count(".themes-list-item"), 5, "displays all themes"); + await render( + hbs`` + ); - [2, 3].forEach((num) => this.themes[num].set("user_selectable", true)); - this.themes[4].set("default", true); - this.set("themes", this.themes); - const names = [4, 2, 3, 0, 1].map((num) => this.themes[num].get("name")); // default theme always on top, followed by user-selectable ones and then the rest - assert.deepEqual( - Array.from(queryAll(".themes-list-item .name")).map((node) => - node.innerText.trim() - ), - names, - "sorts themes correctly" - ); - assert.strictEqual( - queryAll(".inactive-indicator").index(), - 3, - "the separator is in the right location" - ); + assert.strictEqual( + query(".themes-tab").classList.contains("active"), + true, + "themes tab is active" + ); + assert.strictEqual( + query(".components-tab").classList.contains("active"), + false, + "components tab is not active" + ); - this.themes.forEach((theme) => theme.set("user_selectable", true)); - this.set("themes", this.themes); - assert.strictEqual( - queryAll(".inactive-indicator").index(), - -1, - "there is no inactive themes separator when all themes are user-selectable" - ); + assert.notOk( + exists(".inactive-indicator"), + "there is no inactive themes separator when all themes are inactive" + ); + assert.strictEqual(count(".themes-list-item"), 5, "displays all themes"); - this.set("themes", []); - assert.strictEqual( - count(".themes-list-item"), - 1, - "shows one entry with a message when there is nothing to display" - ); - assert.strictEqual( - queryAll(".themes-list-item span.empty").text().trim(), - I18n.t("admin.customize.theme.empty"), - "displays the right message" - ); - }, + [2, 3].forEach((num) => this.themes[num].set("user_selectable", true)); + this.themes[4].set("default", true); + this.set("themes", this.themes); + const names = [4, 2, 3, 0, 1].map((num) => this.themes[num].get("name")); // default theme always on top, followed by user-selectable ones and then the rest + assert.deepEqual( + Array.from(queryAll(".themes-list-item .name")).map((node) => + node.innerText.trim() + ), + names, + "sorts themes correctly" + ); + assert.strictEqual( + queryAll(".inactive-indicator").index(), + 3, + "the separator is in the right location" + ); + + this.themes.forEach((theme) => theme.set("user_selectable", true)); + this.set("themes", this.themes); + assert.notOk( + exists(".inactive-indicator"), + "there is no inactive themes separator when all themes are user-selectable" + ); + + this.set("themes", []); + assert.strictEqual( + count(".themes-list-item"), + 1, + "shows one entry with a message when there is nothing to display" + ); + assert.strictEqual( + query(".themes-list-item span.empty").innerText.trim(), + I18n.t("admin.customize.theme.empty"), + "displays the right message" + ); }); - componentTest("current tab is components", { - template: hbs`{{themes-list themes=themes components=components currentTab=currentTab}}`, - beforeEach() { - this.themes = createThemes(5); - this.components = createThemes(5, (n) => { - return { - name: `Child ${n}`, - component: true, - parentThemes: [this.themes[n - 1]], - parent_themes: [1, 2, 3, 4, 5], - }; - }); - this.setProperties({ - themes: this.themes, - components: this.components, - currentTab: COMPONENTS, - }); - }, + test("current tab is components", async function (assert) { + this.themes = createThemes(5); + this.components = createThemes(5, (n) => { + return { + name: `Child ${n}`, + component: true, + parentThemes: [this.themes[n - 1]], + parent_themes: [1, 2, 3, 4, 5], + }; + }); + this.setProperties({ + themes: this.themes, + components: this.components, + currentTab: COMPONENTS, + }); - test(assert) { - assert.strictEqual( - queryAll(".components-tab").hasClass("active"), - true, - "components tab is active" - ); - assert.strictEqual( - queryAll(".themes-tab").hasClass("active"), - false, - "themes tab is not active" - ); + await render( + hbs`` + ); - assert.strictEqual( - queryAll(".inactive-indicator").index(), - -1, - "there is no separator" - ); - assert.strictEqual( - count(".themes-list-item"), - 5, - "displays all components" - ); + assert.strictEqual( + query(".components-tab").classList.contains("active"), + true, + "components tab is active" + ); + assert.strictEqual( + query(".themes-tab").classList.contains("active"), + false, + "themes tab is not active" + ); - this.set("components", []); - assert.strictEqual( - count(".themes-list-item"), - 1, - "shows one entry with a message when there is nothing to display" - ); - assert.strictEqual( - queryAll(".themes-list-item span.empty").text().trim(), - I18n.t("admin.customize.theme.empty"), - "displays the right message" - ); - }, + assert.notOk(exists(".inactive-indicator"), "there is no separator"); + assert.strictEqual( + count(".themes-list-item"), + 5, + "displays all components" + ); + + this.set("components", []); + assert.strictEqual( + count(".themes-list-item"), + 1, + "shows one entry with a message when there is nothing to display" + ); + assert.strictEqual( + query(".themes-list-item span.empty").innerText.trim(), + I18n.t("admin.customize.theme.empty"), + "displays the right message" + ); }); - componentTest( - "themes filter is not visible when there are less than 10 themes", - { - template: hbs`{{themes-list themes=themes components=[] currentTab=currentTab}}`, + test("themes filter is not visible when there are less than 10 themes", async function (assert) { + const themes = createThemes(9); + this.setProperties({ + themes, + currentTab: THEMES, + }); - beforeEach() { - const themes = createThemes(9); - this.setProperties({ - themes, - currentTab: THEMES, - }); - }, - async test(assert) { - assert.ok( - !exists(".themes-list-filter"), - "filter input not shown when we have fewer than 10 themes" - ); - }, - } - ); + await render( + hbs`` + ); - componentTest( - "themes filter keeps themes whose names include the filter term", - { - template: hbs`{{themes-list themes=themes components=[] currentTab=currentTab}}`, + assert.ok( + !exists(".themes-list-filter"), + "filter input not shown when we have fewer than 10 themes" + ); + }); - beforeEach() { - const themes = ["osama", "OsAmaa", "osAMA 1234"] - .map((name) => Theme.create({ name: `Theme ${name}` })) - .concat(createThemes(7)); - this.setProperties({ - themes, - currentTab: THEMES, - }); - }, - async test(assert) { - assert.ok(exists(".themes-list-filter")); - await fillIn(".themes-list-filter .filter-input", " oSAma "); - assert.deepEqual( - Array.from(queryAll(".themes-list-item .name")).map((node) => - node.textContent.trim() - ), - ["Theme osama", "Theme OsAmaa", "Theme osAMA 1234"], - "only themes whose names include the filter term are shown" - ); - }, - } - ); + test("themes filter keeps themes whose names include the filter term", async function (assert) { + const themes = ["osama", "OsAmaa", "osAMA 1234"] + .map((name) => Theme.create({ name: `Theme ${name}` })) + .concat(createThemes(7)); + this.setProperties({ + themes, + currentTab: THEMES, + }); - componentTest( - "switching between themes and components tabs keeps the filter visible only if both tabs have at least 10 items", - { - template: hbs`{{themes-list themes=themes components=components currentTab=currentTab}}`, + await render( + hbs`` + ); - beforeEach() { - const themes = createThemes(10, (n) => { - return { name: `Theme ${n}${n}` }; - }); - const components = createThemes(5, (n) => { + assert.ok(exists(".themes-list-filter")); + await fillIn(".themes-list-filter .filter-input", " oSAma "); + assert.deepEqual( + Array.from(queryAll(".themes-list-item .name")).map((node) => + node.textContent.trim() + ), + ["Theme osama", "Theme OsAmaa", "Theme osAMA 1234"], + "only themes whose names include the filter term are shown" + ); + }); + + test("switching between themes and components tabs keeps the filter visible only if both tabs have at least 10 items", async function (assert) { + const themes = createThemes(10, (n) => { + return { name: `Theme ${n}${n}` }; + }); + const components = createThemes(5, (n) => { + return { + name: `Component ${n}${n}`, + component: true, + parent_themes: [1], + parentThemes: [1], + }; + }); + this.setProperties({ + themes, + components, + currentTab: THEMES, + }); + + await render( + hbs`` + ); + + await fillIn(".themes-list-filter .filter-input", "11"); + assert.strictEqual( + query(".themes-list-container").textContent.trim(), + "Theme 11", + "only 1 theme is shown" + ); + await click(".themes-list-header .components-tab"); + assert.ok( + !exists(".themes-list-filter"), + "filter input/term do not persist when we switch to the other" + + " tab because it has fewer than 10 items" + ); + assert.deepEqual( + Array.from(queryAll(".themes-list-item .name")).map((node) => + node.textContent.trim() + ), + [ + "Component 11", + "Component 22", + "Component 33", + "Component 44", + "Component 55", + ], + "all components are shown" + ); + + this.set( + "components", + this.components.concat( + createThemes(5, (n) => { + n += 5; return { name: `Component ${n}${n}`, component: true, parent_themes: [1], parentThemes: [1], }; - }); - this.setProperties({ - themes, - components, - currentTab: THEMES, - }); - }, - async test(assert) { - await fillIn(".themes-list-filter .filter-input", "11"); - assert.strictEqual( - query(".themes-list-container").textContent.trim(), - "Theme 11", - "only 1 theme is shown" - ); - await click(".themes-list-header .components-tab"); - assert.ok( - !exists(".themes-list-filter"), - "filter input/term do not persist when we switch to the other" + - " tab because it has fewer than 10 items" - ); - assert.deepEqual( - Array.from(queryAll(".themes-list-item .name")).map((node) => - node.textContent.trim() - ), - [ - "Component 11", - "Component 22", - "Component 33", - "Component 44", - "Component 55", - ], - "all components are shown" - ); + }) + ) + ); + assert.ok( + exists(".themes-list-filter"), + "filter is now shown for the components tab" + ); - this.set( - "components", - this.components.concat( - createThemes(5, (n) => { - n += 5; - return { - name: `Component ${n}${n}`, - component: true, - parent_themes: [1], - parentThemes: [1], - }; - }) - ) - ); - assert.ok( - exists(".themes-list-filter"), - "filter is now shown for the components tab" - ); + await fillIn(".themes-list-filter .filter-input", "66"); + assert.strictEqual( + query(".themes-list-container").textContent.trim(), + "Component 66", + "only 1 component is shown" + ); - await fillIn(".themes-list-filter .filter-input", "66"); - assert.strictEqual( - query(".themes-list-container").textContent.trim(), - "Component 66", - "only 1 component is shown" - ); - - await click(".themes-list-header .themes-tab"); - assert.strictEqual( - query(".themes-list-container").textContent.trim(), - "Theme 66", - "filter term persisted between tabs because both have more than 10 items" - ); - }, - } - ); + await click(".themes-list-header .themes-tab"); + assert.strictEqual( + query(".themes-list-container").textContent.trim(), + "Theme 66", + "filter term persisted between tabs because both have more than 10 items" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/time-input-test.js b/app/assets/javascripts/discourse/tests/integration/components/time-input-test.js index 2a06b622684..68a1e4450ca 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/time-input-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/time-input-test.js @@ -1,7 +1,6 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; @@ -9,51 +8,45 @@ function setTime(time) { this.setProperties(time); } -discourseModule("Integration | Component | time-input", function (hooks) { +module("Integration | Component | time-input", function (hooks) { setupRenderingTest(hooks); hooks.beforeEach(function () { this.set("subject", selectKit()); }); - componentTest("default", { - template: hbs`{{time-input hours=hours minutes=minutes}}`, + test("default", async function (assert) { + this.setProperties({ hours: "14", minutes: "58" }); - beforeEach() { - this.setProperties({ hours: "14", minutes: "58" }); - }, + await render( + hbs`` + ); - test(assert) { - assert.strictEqual(this.subject.header().name(), "14:58"); - }, + assert.strictEqual(this.subject.header().name(), "14:58"); }); - componentTest("prevents mutations", { - template: hbs`{{time-input hours=hours minutes=minutes}}`, + test("prevents mutations", async function (assert) { + this.setProperties({ hours: "14", minutes: "58" }); - beforeEach() { - this.setProperties({ hours: "14", minutes: "58" }); - }, + await render( + hbs`` + ); - async test(assert) { - await this.subject.expand(); - await this.subject.selectRowByIndex(3); - assert.strictEqual(this.subject.header().name(), "14:58"); - }, + await this.subject.expand(); + await this.subject.selectRowByIndex(3); + assert.strictEqual(this.subject.header().name(), "14:58"); }); - componentTest("allows mutations through actions", { - template: hbs`{{time-input hours=hours minutes=minutes onChange=onChange}}`, + test("allows mutations through actions", async function (assert) { + this.setProperties({ hours: "14", minutes: "58" }); + this.set("onChange", setTime); - beforeEach() { - this.setProperties({ hours: "14", minutes: "58" }); - this.set("onChange", setTime); - }, + await render( + hbs`` + ); - async test(assert) { - await this.subject.expand(); - await this.subject.selectRowByIndex(3); - assert.strictEqual(this.subject.header().name(), "00:45"); - }, + await this.subject.expand(); + await this.subject.selectRowByIndex(3); + assert.strictEqual(this.subject.header().name(), "00:45"); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/time-shortcut-picker-test.js b/app/assets/javascripts/discourse/tests/integration/components/time-shortcut-picker-test.js index 395742c782d..a830cefaa59 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/time-shortcut-picker-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/time-shortcut-picker-test.js @@ -1,8 +1,7 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; import { - discourseModule, exists, fakeTime, query, @@ -10,222 +9,168 @@ import { } from "discourse/tests/helpers/qunit-helpers"; import I18n from "I18n"; import hbs from "htmlbars-inline-precompile"; -import { click } from "@ember/test-helpers"; -discourseModule( - "Integration | Component | time-shortcut-picker", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | time-shortcut-picker", function (hooks) { + setupRenderingTest(hooks); - const template = hbs`{{time-shortcut-picker _itsatrap=itsatrap}}`; + hooks.beforeEach(function () { + const itsatrapStub = { + bind: () => {}, + unbind: () => {}, + }; - hooks.beforeEach(function () { - const itsatrapStub = { - bind: () => {}, - unbind: () => {}, - }; + this.set("itsatrap", itsatrapStub); + }); - this.set("itsatrap", itsatrapStub); - }); + hooks.afterEach(function () { + this.clock?.restore(); + }); - hooks.afterEach(function () { - if (this.clock) { - this.clock.restore(); - } - }); + test("shows default options", async function (assert) { + this.siteSettings.suggest_weekends_in_date_pickers = true; + const tuesday = "2100-06-08T08:00:00"; + this.clock = fakeTime(tuesday, this.currentUser.timezone, true); - componentTest("shows default options", { - template, + await render(hbs``); - beforeEach() { - this.siteSettings.suggest_weekends_in_date_pickers = true; - const tuesday = "2100-06-08T08:00:00"; - this.clock = fakeTime(tuesday, this.currentUser.timezone, true); - }, + const expected = [ + I18n.t("time_shortcut.later_today"), + I18n.t("time_shortcut.tomorrow"), + I18n.t("time_shortcut.later_this_week"), + I18n.t("time_shortcut.this_weekend"), + I18n.t("time_shortcut.start_of_next_business_week"), + I18n.t("time_shortcut.next_month"), + I18n.t("time_shortcut.custom"), + I18n.t("time_shortcut.none"), + ]; - async test(assert) { - const expected = [ - I18n.t("time_shortcut.later_today"), - I18n.t("time_shortcut.tomorrow"), - I18n.t("time_shortcut.later_this_week"), - I18n.t("time_shortcut.this_weekend"), - I18n.t("time_shortcut.start_of_next_business_week"), - I18n.t("time_shortcut.next_month"), - I18n.t("time_shortcut.custom"), - I18n.t("time_shortcut.none"), - ]; - - const options = Array.from( - queryAll("div.tap-tile-grid div.tap-tile-title").map((_, div) => - div.innerText.trim() - ) - ); - - assert.deepEqual(options, expected); - }, - }); - - componentTest("show 'Later This Week' if today is < Thursday", { - template, - - beforeEach() { - const monday = "2100-06-07T08:00:00"; - this.clock = fakeTime(monday, this.currentUser.timezone, true); - }, - - test(assert) { - assert.ok( - exists("#tap_tile_later_this_week"), - "it has later this week" - ); - }, - }); - - componentTest("does not show 'Later This Week' if today is >= Thursday", { - template, - - beforeEach() { - const thursday = "2100-06-10T08:00:00"; - this.clock = fakeTime(thursday, this.currentUser.timezone, true); - }, - - test(assert) { - assert.notOk( - exists("#tap_tile_later_this_week"), - "it does not have later this week" - ); - }, - }); - - componentTest("does not show 'Later Today' if 'Later Today' is tomorrow", { - template, - - beforeEach() { - this.clock = fakeTime( - "2100-12-11T22:00:00", // + 3 hours is tomorrow - this.currentUser.timezone, - true - ); - }, - - test(assert) { - assert.notOk( - exists("#tap_tile_later_today"), - "it does not have later today" - ); - }, - }); - - componentTest("shows 'Later Today' if it is before 5pm", { - template, - - beforeEach() { - this.clock = fakeTime( - "2100-12-11T16:50:00", - this.currentUser.timezone, - true - ); - }, - - test(assert) { - assert.ok(exists("#tap_tile_later_today"), "it does have later today"); - }, - }); - - componentTest("does not show 'Later Today' if it is after 5pm", { - template, - - beforeEach() { - this.clock = fakeTime( - "2100-12-11T17:00:00", - this.currentUser.timezone, - true - ); - }, - - test(assert) { - assert.notOk( - exists("#tap_tile_later_today"), - "it does not have later today" - ); - }, - }); - - componentTest("defaults to 08:00 for custom time", { - template, - - async test(assert) { - await click("#tap_tile_custom"); - assert.strictEqual(query("#custom-time").value, "08:00"); - }, - }); - - componentTest("shows 'Next Monday' instead of 'Monday' on Sundays", { - template, - - beforeEach() { - const sunday = "2100-01-24T08:00:00"; - this.clock = fakeTime(sunday, this.currentUser.timezone, true); - }, - - async test(assert) { - assert.equal( - query("#tap_tile_start_of_next_business_week .tap-tile-title") - .innerText, - "Next Monday" - ); - - assert.equal( - query("div#tap_tile_start_of_next_business_week div.tap-tile-date") - .innerText, - "Feb 1, 8:00 am" - ); - }, - }); - - componentTest("shows 'Next Monday' instead of 'Monday' on Mondays", { - template, - - beforeEach() { - const monday = "2100-01-25T08:00:00"; - this.clock = fakeTime(monday, this.currentUser.timezone, true); - }, - - async test(assert) { - assert.equal( - query("#tap_tile_start_of_next_business_week .tap-tile-title") - .innerText, - "Next Monday" - ); - - assert.equal( - query("div#tap_tile_start_of_next_business_week div.tap-tile-date") - .innerText, - "Feb 1, 8:00 am" - ); - }, - }); - - componentTest( - "the 'Next Month' option points to the first day of the next month", - { - template, - - beforeEach() { - this.clock = fakeTime( - "2100-01-01T08:00:00", - this.currentUser.timezone, - true - ); - }, - - async test(assert) { - assert.strictEqual( - query("div#tap_tile_next_month div.tap-tile-date").innerText, - "Feb 1, 8:00 am" - ); - }, - } + const options = Array.from( + queryAll("div.tap-tile-grid div.tap-tile-title").map((_, div) => + div.innerText.trim() + ) ); - } -); + + assert.deepEqual(options, expected); + }); + + test("show 'Later This Week' if today is < Thursday", async function (assert) { + const monday = "2100-06-07T08:00:00"; + this.clock = fakeTime(monday, this.currentUser.timezone, true); + + await render(hbs``); + + assert.ok(exists("#tap_tile_later_this_week"), "it has later this week"); + }); + + test("does not show 'Later This Week' if today is >= Thursday", async function (assert) { + const thursday = "2100-06-10T08:00:00"; + this.clock = fakeTime(thursday, this.currentUser.timezone, true); + + await render(hbs``); + + assert.notOk( + exists("#tap_tile_later_this_week"), + "it does not have later this week" + ); + }); + + test("does not show 'Later Today' if 'Later Today' is tomorrow", async function (assert) { + this.clock = fakeTime( + "2100-12-11T22:00:00", // + 3 hours is tomorrow + this.currentUser.timezone, + true + ); + + await render(hbs``); + + assert.notOk( + exists("#tap_tile_later_today"), + "it does not have later today" + ); + }); + + test("shows 'Later Today' if it is before 5pm", async function (assert) { + this.clock = fakeTime( + "2100-12-11T16:50:00", + this.currentUser.timezone, + true + ); + + await render(hbs``); + + assert.ok(exists("#tap_tile_later_today"), "it does have later today"); + }); + + test("does not show 'Later Today' if it is after 5pm", async function (assert) { + this.clock = fakeTime( + "2100-12-11T17:00:00", + this.currentUser.timezone, + true + ); + + await render(hbs``); + + assert.notOk( + exists("#tap_tile_later_today"), + "it does not have later today" + ); + }); + + test("defaults to 08:00 for custom time", async function (assert) { + await render(hbs``); + + await click("#tap_tile_custom"); + assert.strictEqual(query("#custom-time").value, "08:00"); + }); + + test("shows 'Next Monday' instead of 'Monday' on Sundays", async function (assert) { + const sunday = "2100-01-24T08:00:00"; + this.clock = fakeTime(sunday, this.currentUser.timezone, true); + + await render(hbs``); + + assert.strictEqual( + query("#tap_tile_start_of_next_business_week .tap-tile-title").innerText, + "Next Monday" + ); + + assert.strictEqual( + query("div#tap_tile_start_of_next_business_week div.tap-tile-date") + .innerText, + "Feb 1, 8:00 am" + ); + }); + + test("shows 'Next Monday' instead of 'Monday' on Mondays", async function (assert) { + const monday = "2100-01-25T08:00:00"; + this.clock = fakeTime(monday, this.currentUser.timezone, true); + + await render(hbs``); + + assert.strictEqual( + query("#tap_tile_start_of_next_business_week .tap-tile-title").innerText, + "Next Monday" + ); + + assert.strictEqual( + query("div#tap_tile_start_of_next_business_week div.tap-tile-date") + .innerText, + "Feb 1, 8:00 am" + ); + }); + + test("the 'Next Month' option points to the first day of the next month", async function (assert) { + this.clock = fakeTime( + "2100-01-01T08:00:00", + this.currentUser.timezone, + true + ); + + await render(hbs``); + + assert.strictEqual( + query("div#tap_tile_next_month div.tap-tile-date").innerText, + "Feb 1, 8:00 am" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/topic-list-item-test.js b/app/assets/javascripts/discourse/tests/integration/components/topic-list-item-test.js index e890958a8f3..2fc1cf42099 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/topic-list-item-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/topic-list-item-test.js @@ -1,42 +1,37 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { queryAll } from "discourse/tests/helpers/qunit-helpers"; import Topic from "discourse/models/topic"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | topic-list-item", function (hooks) { +module("Integration | Component | topic-list-item", function (hooks) { setupRenderingTest(hooks); - componentTest("checkbox is rendered checked if topic is in selected array", { - template: hbs`{{topic-list-item - topic=topic - bulkSelectEnabled=true - selected=selected - }} - {{topic-list-item - topic=topic2 - bulkSelectEnabled=true - selected=selected - }}`, + test("checkbox is rendered checked if topic is in selected array", async function (assert) { + const topic = Topic.create({ id: 24234 }); + const topic2 = Topic.create({ id: 24235 }); + this.setProperties({ + topic, + topic2, + selected: [topic], + }); - beforeEach() { - const topic = Topic.create({ id: 24234 }); - const topic2 = Topic.create({ id: 24235 }); - this.setProperties({ - topic, - topic2, - selected: [topic], - }); - }, + await render(hbs` + + + `); - async test(assert) { - const checkboxes = queryAll("input.bulk-select"); - assert.ok(checkboxes[0].checked); - assert.ok(!checkboxes[1].checked); - }, + const checkboxes = queryAll("input.bulk-select"); + assert.ok(checkboxes[0].checked); + assert.ok(!checkboxes[1].checked); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/topic-list-test.js b/app/assets/javascripts/discourse/tests/integration/components/topic-list-test.js index 7d0cd8db84a..a44703cbf03 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/topic-list-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/topic-list-test.js @@ -1,70 +1,64 @@ -import { click } from "@ember/test-helpers"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; import Topic from "discourse/models/topic"; import hbs from "htmlbars-inline-precompile"; -discourseModule("Integration | Component | topic-list", function (hooks) { +module("Integration | Component | topic-list", function (hooks) { setupRenderingTest(hooks); - componentTest("bulk select", { - template: hbs`{{topic-list - canBulkSelect=true - toggleBulkSelect=toggleBulkSelect - bulkSelectEnabled=bulkSelectEnabled - autoAddTopicsToBulkSelect=autoAddTopicsToBulkSelect - updateAutoAddTopicsToBulkSelect=updateAutoAddTopicsToBulkSelect - topics=topics - selected=selected - }}`, + test("bulk select", async function (assert) { + this.setProperties({ + topics: [Topic.create({ id: 24234 }), Topic.create({ id: 24235 })], + selected: [], + bulkSelectEnabled: false, + autoAddTopicsToBulkSelect: false, - beforeEach() { - const topic = Topic.create({ id: 24234 }); - const topic2 = Topic.create({ id: 24235 }); - this.setProperties({ - topics: [topic, topic2], - selected: [], - bulkSelectEnabled: false, - autoAddTopicsToBulkSelect: false, + toggleBulkSelect() { + this.toggleProperty("bulkSelectEnabled"); + }, - toggleBulkSelect() { - this.toggleProperty("bulkSelectEnabled"); - }, + updateAutoAddTopicsToBulkSelect(newVal) { + this.set("autoAddTopicsToBulkSelect", newVal); + }, + }); - updateAutoAddTopicsToBulkSelect(newVal) { - this.set("autoAddTopicsToBulkSelect", newVal); - }, - }); - }, + await render(hbs` + + `); - async test(assert) { - assert.strictEqual(this.selected.length, 0, "defaults to 0"); - await click("button.bulk-select"); - assert.ok(this.bulkSelectEnabled, "bulk select is enabled"); + assert.strictEqual(this.selected.length, 0, "defaults to 0"); + await click("button.bulk-select"); + assert.ok(this.bulkSelectEnabled, "bulk select is enabled"); - await click("button.bulk-select-all"); - assert.strictEqual( - this.selected.length, - 2, - "clicking Select All selects all loaded topics" - ); - assert.ok( - this.autoAddTopicsToBulkSelect, - "clicking Select All turns on the autoAddTopicsToBulkSelect flag" - ); + await click("button.bulk-select-all"); + assert.strictEqual( + this.selected.length, + 2, + "clicking Select All selects all loaded topics" + ); + assert.ok( + this.autoAddTopicsToBulkSelect, + "clicking Select All turns on the autoAddTopicsToBulkSelect flag" + ); - await click("button.bulk-clear-all"); - assert.strictEqual( - this.selected.length, - 0, - "clicking Clear All deselects all topics" - ); - assert.ok( - !this.autoAddTopicsToBulkSelect, - "clicking Clear All turns off the autoAddTopicsToBulkSelect flag" - ); - }, + await click("button.bulk-clear-all"); + assert.strictEqual( + this.selected.length, + 0, + "clicking Clear All deselects all topics" + ); + assert.ok( + !this.autoAddTopicsToBulkSelect, + "clicking Clear All turns off the autoAddTopicsToBulkSelect flag" + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/uppy-image-uploader-test.js b/app/assets/javascripts/discourse/tests/integration/components/uppy-image-uploader-test.js index 41410e677f7..186463c0390 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/uppy-image-uploader-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/uppy-image-uploader-test.js @@ -1,100 +1,88 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, -} from "discourse/tests/helpers/qunit-helpers"; -import { click } from "@ember/test-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { count, exists } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule( - "Integration | Component | uppy-image-uploader", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | uppy-image-uploader", function (hooks) { + setupRenderingTest(hooks); - componentTest("with image", { - template: hbs` - {{uppy-image-uploader id="test-uppy-image-uploader" imageUrl='/images/avatar.png' placeholderUrl='/not/used.png'}} - `, + test("with image", async function (assert) { + await render(hbs` + + `); - async test(assert) { - assert.strictEqual( - count(".d-icon-far-image"), - 1, - "it displays the upload icon" - ); + assert.strictEqual( + count(".d-icon-far-image"), + 1, + "it displays the upload icon" + ); - assert.strictEqual( - count(".d-icon-far-trash-alt"), - 1, - "it displays the trash icon" - ); + assert.strictEqual( + count(".d-icon-far-trash-alt"), + 1, + "it displays the trash icon" + ); - assert.ok( - !exists(".placeholder-overlay"), - "it does not display the placeholder image" - ); + assert.ok( + !exists(".placeholder-overlay"), + "it does not display the placeholder image" + ); - await click(".image-uploader-lightbox-btn"); + await click(".image-uploader-lightbox-btn"); - assert.strictEqual( - document.querySelectorAll(".mfp-container").length, - 1, - "it displays the image lightbox" - ); - }, - }); + assert.strictEqual( + document.querySelectorAll(".mfp-container").length, + 1, + "it displays the image lightbox" + ); + }); - componentTest("without image", { - template: hbs`{{uppy-image-uploader id="test-uppy-image-uploader"}}`, + test("without image", async function (assert) { + await render(hbs``); - test(assert) { - assert.strictEqual( - count(".d-icon-far-image"), - 1, - "it displays the upload icon" - ); + assert.strictEqual( + count(".d-icon-far-image"), + 1, + "it displays the upload icon" + ); - assert.ok( - !exists(".d-icon-far-trash-alt"), - "it does not display trash icon" - ); + assert.ok( + !exists(".d-icon-far-trash-alt"), + "it does not display trash icon" + ); - assert.ok( - !exists(".image-uploader-lightbox-btn"), - "it does not display the button to open image lightbox" - ); - }, - }); + assert.ok( + !exists(".image-uploader-lightbox-btn"), + "it does not display the button to open image lightbox" + ); + }); - componentTest("with placeholder", { - template: hbs`{{uppy-image-uploader id="test-uppy-image-uploader" placeholderUrl='/images/avatar.png'}}`, + test("with placeholder", async function (assert) { + await render( + hbs`` + ); - test(assert) { - assert.strictEqual( - count(".d-icon-far-image"), - 1, - "it displays the upload icon" - ); + assert.strictEqual( + count(".d-icon-far-image"), + 1, + "it displays the upload icon" + ); - assert.ok( - !exists(".d-icon-far-trash-alt"), - "it does not display trash icon" - ); + assert.ok( + !exists(".d-icon-far-trash-alt"), + "it does not display trash icon" + ); - assert.ok( - !exists(".image-uploader-lightbox-btn"), - "it does not display the button to open image lightbox" - ); + assert.ok( + !exists(".image-uploader-lightbox-btn"), + "it does not display the button to open image lightbox" + ); - assert.strictEqual( - count(".placeholder-overlay"), - 1, - "it displays the placeholder image" - ); - }, - }); - } -); + assert.strictEqual( + count(".placeholder-overlay"), + 1, + "it displays the placeholder image" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/user-avatar-flair-test.js b/app/assets/javascripts/discourse/tests/integration/components/user-avatar-flair-test.js index e9fc44e45c9..1b2d9d73cfe 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/user-avatar-flair-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/user-avatar-flair-test.js @@ -1,11 +1,7 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import { resetFlair } from "discourse/lib/avatar-flair"; @@ -42,177 +38,140 @@ function setupSiteGroups(that) { ]; } -discourseModule( - "Integration | Component | user-avatar-flair", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | user-avatar-flair", function (hooks) { + setupRenderingTest(hooks); - componentTest("avatar flair for admin user", { - template: hbs`{{user-avatar-flair user=args}}`, - beforeEach() { - resetFlair(); - this.set("args", { - admin: true, - moderator: false, - trust_level: 2, - }); - setupSiteGroups(this); - }, - afterEach() { - resetFlair(); - }, - test(assert) { - assert.ok(exists(".avatar-flair"), "it has the tag"); - assert.ok(exists("svg.d-icon-bars"), "it has the svg icon"); - assert.strictEqual( - queryAll(".avatar-flair").attr("style"), - "background-color: #CC000A; color: #FFFFFA; ", - "it has styles" - ); - }, + hooks.beforeEach(function () { + resetFlair(); + }); + + hooks.afterEach(function () { + resetFlair(); + }); + + test("avatar flair for admin user", async function (assert) { + this.set("args", { + admin: true, + moderator: false, + trust_level: 2, + }); + setupSiteGroups(this); + + await render(hbs``); + + assert.ok(exists(".avatar-flair"), "it has the tag"); + assert.ok(exists("svg.d-icon-bars"), "it has the svg icon"); + assert.strictEqual( + query(".avatar-flair").getAttribute("style"), + "background-color: #CC000A; color: #FFFFFA; ", + "it has styles" + ); + }); + + test("avatar flair for moderator user with fallback to staff", async function (assert) { + this.set("args", { + admin: false, + moderator: true, + trust_level: 2, + }); + setupSiteGroups(this); + + await render(hbs``); + + assert.ok(exists(".avatar-flair"), "it has the tag"); + assert.ok(exists("svg.d-icon-bars"), "it has the svg icon"); + assert.strictEqual( + query(".avatar-flair").getAttribute("style"), + "background-color: #CC0005; color: #FFFFF5; ", + "it has styles" + ); + }); + + test("avatar flair for trust level", async function (assert) { + this.set("args", { + admin: false, + moderator: false, + trust_level: 2, + }); + setupSiteGroups(this); + + await render(hbs``); + + assert.ok(exists(".avatar-flair"), "it has the tag"); + assert.ok(exists("svg.d-icon-dice-two"), "it has the svg icon"); + assert.strictEqual( + query(".avatar-flair").getAttribute("style"), + "background-color: #CC0002; color: #FFFFF2; ", + "it has styles" + ); + }); + + test("avatar flair for trust level with fallback", async function (assert) { + this.set("args", { + admin: false, + moderator: false, + trust_level: 3, + }); + setupSiteGroups(this); + + await render(hbs``); + + assert.ok(exists(".avatar-flair"), "it has the tag"); + assert.ok(exists("svg.d-icon-dice-two"), "it has the svg icon"); + assert.strictEqual( + query(".avatar-flair").getAttribute("style"), + "background-color: #CC0002; color: #FFFFF2; ", + "it has styles" + ); + }); + + test("avatar flair for login-required site, before login", async function (assert) { + this.set("args", { + admin: false, + moderator: false, + trust_level: 3, + }); + // Groups not serialized for anon on login_required + this.site.groups = undefined; + + await render(hbs``); + + assert.ok(!exists(".avatar-flair"), "it does not render a flair"); + }); + + test("avatar flair for primary group flair", async function (assert) { + this.set("args", { + admin: false, + moderator: false, + trust_level: 3, + flair_name: "Band Geeks", + flair_url: "fa-times", + flair_bg_color: "123456", + flair_color: "B0B0B0", + primary_group_name: "Band Geeks", + }); + setupSiteGroups(this); + + await render(hbs``); + + assert.ok(exists(".avatar-flair"), "it has the tag"); + assert.ok(exists("svg.d-icon-times"), "it has the svg icon"); + assert.strictEqual( + query(".avatar-flair").getAttribute("style"), + "background-color: #123456; color: #B0B0B0; ", + "it has styles" + ); + }); + + test("user-avatar-flair for user with no flairs", async function (assert) { + this.set("args", { + admin: false, + moderator: false, + trust_level: 1, }); - componentTest("avatar flair for moderator user with fallback to staff", { - template: hbs`{{user-avatar-flair user=args}}`, - beforeEach() { - resetFlair(); - this.set("args", { - admin: false, - moderator: true, - trust_level: 2, - }); - setupSiteGroups(this); - }, - afterEach() { - resetFlair(); - }, - test(assert) { - assert.ok(exists(".avatar-flair"), "it has the tag"); - assert.ok(exists("svg.d-icon-bars"), "it has the svg icon"); - assert.strictEqual( - queryAll(".avatar-flair").attr("style"), - "background-color: #CC0005; color: #FFFFF5; ", - "it has styles" - ); - }, - }); + await render(hbs``); - componentTest("avatar flair for trust level", { - template: hbs`{{user-avatar-flair user=args}}`, - beforeEach() { - resetFlair(); - this.set("args", { - admin: false, - moderator: false, - trust_level: 2, - }); - setupSiteGroups(this); - }, - afterEach() { - resetFlair(); - }, - test(assert) { - assert.ok(exists(".avatar-flair"), "it has the tag"); - assert.ok(exists("svg.d-icon-dice-two"), "it has the svg icon"); - assert.strictEqual( - queryAll(".avatar-flair").attr("style"), - "background-color: #CC0002; color: #FFFFF2; ", - "it has styles" - ); - }, - }); - - componentTest("avatar flair for trust level with fallback", { - template: hbs`{{user-avatar-flair user=args}}`, - beforeEach() { - resetFlair(); - this.set("args", { - admin: false, - moderator: false, - trust_level: 3, - }); - setupSiteGroups(this); - }, - afterEach() { - resetFlair(); - }, - test(assert) { - assert.ok(exists(".avatar-flair"), "it has the tag"); - assert.ok(exists("svg.d-icon-dice-two"), "it has the svg icon"); - assert.strictEqual( - queryAll(".avatar-flair").attr("style"), - "background-color: #CC0002; color: #FFFFF2; ", - "it has styles" - ); - }, - }); - - componentTest("avatar flair for login-required site, before login", { - template: hbs`{{user-avatar-flair user=args}}`, - beforeEach() { - resetFlair(); - this.set("args", { - admin: false, - moderator: false, - trust_level: 3, - }); - // Groups not serialized for anon on login_required - this.site.groups = undefined; - }, - afterEach() { - resetFlair(); - }, - test(assert) { - assert.ok(!exists(".avatar-flair"), "it does not render a flair"); - }, - }); - - componentTest("avatar flair for primary group flair", { - template: hbs`{{user-avatar-flair user=args}}`, - beforeEach() { - resetFlair(); - this.set("args", { - admin: false, - moderator: false, - trust_level: 3, - flair_name: "Band Geeks", - flair_url: "fa-times", - flair_bg_color: "123456", - flair_color: "B0B0B0", - primary_group_name: "Band Geeks", - }); - setupSiteGroups(this); - }, - afterEach() { - resetFlair(); - }, - test(assert) { - assert.ok(exists(".avatar-flair"), "it has the tag"); - assert.ok(exists("svg.d-icon-times"), "it has the svg icon"); - assert.strictEqual( - queryAll(".avatar-flair").attr("style"), - "background-color: #123456; color: #B0B0B0; ", - "it has styles" - ); - }, - }); - - componentTest("user-avatar-flair for user with no flairs", { - template: hbs`{{user-avatar-flair user=args}}`, - beforeEach() { - resetFlair(); - this.set("args", { - admin: false, - moderator: false, - trust_level: 1, - }); - }, - afterEach() { - resetFlair(); - }, - test(assert) { - assert.ok(!exists(".avatar-flair"), "it does not render a flair"); - }, - }); - } -); + assert.ok(!exists(".avatar-flair"), "it does not render a flair"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/user-info-test.js b/app/assets/javascripts/discourse/tests/integration/components/user-info-test.js index 0203a64d98c..f911a669152 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/user-info-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/user-info-test.js @@ -1,71 +1,53 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import hbs from "htmlbars-inline-precompile"; -import { - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; -discourseModule("Integration | Component | user-info", function (hooks) { +module("Integration | Component | user-info", function (hooks) { setupRenderingTest(hooks); - componentTest("prioritized name", { - template: hbs`{{user-info user=currentUser}}`, + test("prioritized name", async function (assert) { + this.siteSettings.prioritize_username_in_ux = false; + this.currentUser.name = "Evil Trout"; - beforeEach() { - this.siteSettings.prioritize_username_in_ux = false; - this.currentUser.name = "Evil Trout"; - }, + await render(hbs``); - async test(assert) { - assert.equal(query(".name.bold").innerText.trim(), "Evil Trout"); - assert.equal(query(".username.margin").innerText.trim(), "eviltrout"); - }, + assert.strictEqual(query(".name.bold").innerText.trim(), "Evil Trout"); + assert.strictEqual(query(".username.margin").innerText.trim(), "eviltrout"); }); - componentTest("prioritized username", { - template: hbs`{{user-info user=currentUser}}`, + test("prioritized username", async function (assert) { + this.siteSettings.prioritize_username_in_ux = true; + this.currentUser.name = "Evil Trout"; - beforeEach() { - this.siteSettings.prioritize_username_in_ux = true; - this.currentUser.name = "Evil Trout"; - }, + await render(hbs``); - async test(assert) { - assert.equal(query(".username.bold").innerText.trim(), "eviltrout"); - assert.equal(query(".name.margin").innerText.trim(), "Evil Trout"); - }, + assert.strictEqual(query(".username.bold").innerText.trim(), "eviltrout"); + assert.strictEqual(query(".name.margin").innerText.trim(), "Evil Trout"); }); - componentTest("includeLink", { - template: hbs`{{user-info user=currentUser includeLink=includeLink}}`, + test("includeLink", async function (assert) { + await render( + hbs`` + ); - async test(assert) { - this.set("includeLink", true); + this.set("includeLink", true); + assert.ok(exists(`.username a[href="/u/${this.currentUser.username}"]`)); - assert.ok(exists(`.username a[href="/u/${this.currentUser.username}"]`)); - - this.set("includeLink", false); - - assert.notOk( - exists(`.username a[href="/u/${this.currentUser.username}"]`) - ); - }, + this.set("includeLink", false); + assert.notOk(exists(`.username a[href="/u/${this.currentUser.username}"]`)); }); - componentTest("includeAvatar", { - template: hbs`{{user-info user=currentUser includeAvatar=includeAvatar}}`, + test("includeAvatar", async function (assert) { + await render( + hbs`` + ); - async test(assert) { - this.set("includeAvatar", true); + this.set("includeAvatar", true); + assert.ok(exists(".user-image")); - assert.ok(exists(".user-image")); - - this.set("includeAvatar", false); - - assert.notOk(exists(".user-image")); - }, + this.set("includeAvatar", false); + assert.notOk(exists(".user-image")); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/user-selector-test.js b/app/assets/javascripts/discourse/tests/integration/components/user-selector-test.js index 0409551dca7..acbbbee747b 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/user-selector-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/user-selector-test.js @@ -1,7 +1,7 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; function paste(element, text) { @@ -10,51 +10,47 @@ function paste(element, text) { element.dispatchEvent(e); } -discourseModule("Integration | Component | user-selector", function (hooks) { +module("Integration | Component | user-selector", function (hooks) { setupRenderingTest(hooks); - componentTest("pasting a list of usernames", { - template: hbs`{{user-selector usernames=usernames class="test-selector"}}`, + test("pasting a list of usernames", async function (assert) { + this.set("usernames", "evil,trout"); - beforeEach() { - this.set("usernames", "evil,trout"); - }, + await render( + hbs`` + ); - test(assert) { - let element = query(".test-selector"); + let element = query(".test-selector"); - assert.strictEqual(this.get("usernames"), "evil,trout"); - paste(element, "zip,zap,zoom"); - assert.strictEqual(this.get("usernames"), "evil,trout,zip,zap,zoom"); - paste(element, "evil,abc,abc,abc"); - assert.strictEqual(this.get("usernames"), "evil,trout,zip,zap,zoom,abc"); + assert.strictEqual(this.get("usernames"), "evil,trout"); + paste(element, "zip,zap,zoom"); + assert.strictEqual(this.get("usernames"), "evil,trout,zip,zap,zoom"); + paste(element, "evil,abc,abc,abc"); + assert.strictEqual(this.get("usernames"), "evil,trout,zip,zap,zoom,abc"); - this.set("usernames", ""); - paste(element, "names with spaces"); - assert.strictEqual(this.get("usernames"), "names,with,spaces"); + this.set("usernames", ""); + paste(element, "names with spaces"); + assert.strictEqual(this.get("usernames"), "names,with,spaces"); - this.set("usernames", null); - paste(element, "@eviltrout,@codinghorror sam"); - assert.strictEqual(this.get("usernames"), "eviltrout,codinghorror,sam"); + this.set("usernames", null); + paste(element, "@eviltrout,@codinghorror sam"); + assert.strictEqual(this.get("usernames"), "eviltrout,codinghorror,sam"); - this.set("usernames", null); - paste(element, "eviltrout\nsam\ncodinghorror"); - assert.strictEqual(this.get("usernames"), "eviltrout,sam,codinghorror"); - }, + this.set("usernames", null); + paste(element, "eviltrout\nsam\ncodinghorror"); + assert.strictEqual(this.get("usernames"), "eviltrout,sam,codinghorror"); }); - componentTest("excluding usernames", { - template: hbs`{{user-selector usernames=usernames excludedUsernames=excludedUsernames class="test-selector"}}`, + test("excluding usernames", async function (assert) { + this.set("usernames", "mark"); + this.set("excludedUsernames", ["jeff", "sam", "robin"]); - beforeEach() { - this.set("usernames", "mark"); - this.set("excludedUsernames", ["jeff", "sam", "robin"]); - }, + await render( + hbs`` + ); - test(assert) { - let element = query(".test-selector"); - paste(element, "roman,penar,jeff,robin"); - assert.strictEqual(this.get("usernames"), "mark,roman,penar"); - }, + let element = query(".test-selector"); + paste(element, "roman,penar,jeff,robin"); + assert.strictEqual(this.get("usernames"), "mark,roman,penar"); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/value-list-test.js b/app/assets/javascripts/discourse/tests/integration/components/value-list-test.js index 80b9a39bda2..b7783701102 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/value-list-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/value-list-test.js @@ -1,170 +1,145 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - query, -} from "discourse/tests/helpers/qunit-helpers"; -import { blur, click, fillIn } from "@ember/test-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { blur, click, fillIn, render } from "@ember/test-helpers"; +import { count, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import selectKit from "discourse/tests/helpers/select-kit-helper"; -discourseModule("Integration | Component | value-list", function (hooks) { +module("Integration | Component | value-list", function (hooks) { setupRenderingTest(hooks); - componentTest("adding a value", { - template: hbs`{{value-list values=values}}`, + test("adding a value", async function (assert) { + this.set("values", "vinkas\nosama"); - beforeEach() { - this.set("values", "vinkas\nosama"); - }, + await render(hbs``); - async test(assert) { - await selectKit().expand(); - await selectKit().fillInFilter("eviltrout"); - await selectKit().keyboard("Enter"); + await selectKit().expand(); + await selectKit().fillInFilter("eviltrout"); + await selectKit().keyboard("Enter"); - assert.strictEqual( - count(".values .value"), - 3, - "it adds the value to the list of values" - ); + assert.strictEqual( + count(".values .value"), + 3, + "it adds the value to the list of values" + ); - assert.deepEqual( - this.values, - "vinkas\nosama\neviltrout", - "it adds the value to the list of values" - ); - }, + assert.strictEqual( + this.values, + "vinkas\nosama\neviltrout", + "it adds the value to the list of values" + ); }); - componentTest("changing a value", { - template: hbs`{{value-list values=values}}`, + test("changing a value", async function (assert) { + this.set("values", "vinkas\nosama"); - beforeEach() { - this.set("values", "vinkas\nosama"); - }, + await render(hbs``); - async test(assert) { - await fillIn(".values .value[data-index='1'] .value-input", "jarek"); - await blur(".values .value[data-index='1'] .value-input"); + await fillIn(".values .value[data-index='1'] .value-input", "jarek"); + await blur(".values .value[data-index='1'] .value-input"); - assert.strictEqual( - query(".values .value[data-index='1'] .value-input").value, - "jarek" - ); - assert.deepEqual(this.values, "vinkas\njarek", "updates the value list"); - }, + assert.strictEqual( + query(".values .value[data-index='1'] .value-input").value, + "jarek" + ); + assert.deepEqual(this.values, "vinkas\njarek", "updates the value list"); }); - componentTest("removing a value", { - template: hbs`{{value-list values=values}}`, + test("removing a value", async function (assert) { + this.set("values", "vinkas\nosama"); - beforeEach() { - this.set("values", "vinkas\nosama"); - }, + await render(hbs``); - async test(assert) { - await click(".values .value[data-index='0'] .remove-value-btn"); + await click(".values .value[data-index='0'] .remove-value-btn"); - assert.strictEqual( - count(".values .value"), - 1, - "it removes the value from the list of values" - ); + assert.strictEqual( + count(".values .value"), + 1, + "it removes the value from the list of values" + ); - assert.strictEqual(this.values, "osama", "it removes the expected value"); + assert.strictEqual(this.values, "osama", "it removes the expected value"); - await selectKit().expand(); + await selectKit().expand(); - assert.ok( - query(".select-kit-collection li.select-kit-row span.name") - .innerText === "vinkas", - "it adds the removed value to choices" - ); - }, + assert.strictEqual( + query(".select-kit-collection li.select-kit-row span.name").innerText, + "vinkas", + "it adds the removed value to choices" + ); }); - componentTest("selecting a value", { - template: hbs`{{value-list values=values choices=choices}}`, + test("selecting a value", async function (assert) { + this.setProperties({ + values: "vinkas\nosama", + choices: ["maja", "michael"], + }); - beforeEach() { - this.setProperties({ - values: "vinkas\nosama", - choices: ["maja", "michael"], - }); - }, + await render( + hbs`` + ); - async test(assert) { - await selectKit().expand(); - await selectKit().selectRowByValue("maja"); + await selectKit().expand(); + await selectKit().selectRowByValue("maja"); - assert.strictEqual( - count(".values .value"), - 3, - "it adds the value to the list of values" - ); + assert.strictEqual( + count(".values .value"), + 3, + "it adds the value to the list of values" + ); - assert.deepEqual( - this.values, - "vinkas\nosama\nmaja", - "it adds the value to the list of values" - ); - }, + assert.strictEqual( + this.values, + "vinkas\nosama\nmaja", + "it adds the value to the list of values" + ); }); - componentTest("array support", { - template: hbs`{{value-list values=values inputType='array'}}`, + test("array support", async function (assert) { + this.set("values", ["vinkas", "osama"]); - beforeEach() { - this.set("values", ["vinkas", "osama"]); - }, + await render(hbs``); - async test(assert) { - this.set("values", ["vinkas", "osama"]); + this.set("values", ["vinkas", "osama"]); - await selectKit().expand(); - await selectKit().fillInFilter("eviltrout"); - await selectKit().selectRowByValue("eviltrout"); + await selectKit().expand(); + await selectKit().fillInFilter("eviltrout"); + await selectKit().selectRowByValue("eviltrout"); - assert.strictEqual( - count(".values .value"), - 3, - "it adds the value to the list of values" - ); + assert.strictEqual( + count(".values .value"), + 3, + "it adds the value to the list of values" + ); - assert.deepEqual( - this.values, - ["vinkas", "osama", "eviltrout"], - "it adds the value to the list of values" - ); - }, + assert.deepEqual( + this.values, + ["vinkas", "osama", "eviltrout"], + "it adds the value to the list of values" + ); }); - componentTest("delimiter support", { - template: hbs`{{value-list values=values inputDelimiter='|'}}`, + test("delimiter support", async function (assert) { + this.set("values", "vinkas|osama"); - beforeEach() { - this.set("values", "vinkas|osama"); - }, + await render( + hbs`` + ); - async test(assert) { - await selectKit().expand(); - await selectKit().fillInFilter("eviltrout"); - await selectKit().keyboard("Enter"); + await selectKit().expand(); + await selectKit().fillInFilter("eviltrout"); + await selectKit().keyboard("Enter"); - assert.strictEqual( - count(".values .value"), - 3, - "it adds the value to the list of values" - ); + assert.strictEqual( + count(".values .value"), + 3, + "it adds the value to the list of values" + ); - assert.deepEqual( - this.values, - "vinkas|osama|eviltrout", - "it adds the value to the list of values" - ); - }, + assert.strictEqual( + this.values, + "vinkas|osama|eviltrout", + "it adds the value to the list of values" + ); }); }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/watched-word-uploader-test.js b/app/assets/javascripts/discourse/tests/integration/components/watched-word-uploader-test.js index 49272b6556b..90651eb1ce7 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/watched-word-uploader-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/watched-word-uploader-test.js @@ -1,51 +1,45 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - createFile, - discourseModule, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render, waitFor } from "@ember/test-helpers"; +import { createFile } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import pretender, { response } from "discourse/tests/helpers/create-pretender"; -import { click, waitFor } from "@ember/test-helpers"; -discourseModule( - "Integration | Component | watched-word-uploader", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | watched-word-uploader", function (hooks) { + setupRenderingTest(hooks); - hooks.beforeEach(function () { - pretender.post("/admin/customize/watched_words/upload.json", function () { - return response(200, {}); - }); + hooks.beforeEach(function () { + pretender.post("/admin/customize/watched_words/upload.json", function () { + return response(200, {}); + }); + }); + + test("sets the proper action key on uploads", async function (assert) { + const done = assert.async(); + this.set("actionNameKey", "flag"); + this.set("doneUpload", function () { + assert.strictEqual( + Object.entries(this._uppyInstance.getState().files)[0][1].meta + .action_key, + "flag" + ); + done(); }); - componentTest("sets the proper action key on uploads", { - template: hbs`{{watched-word-uploader - id="watched-word-uploader" - actionKey=actionNameKey - done=doneUpload - }}`, + await render(hbs` + + `); - async test(assert) { - const done = assert.async(); - this.set("actionNameKey", "flag"); - this.set("doneUpload", function () { - assert.equal( - Object.entries(this._uppyInstance.getState().files)[0][1].meta - .action_key, - "flag" - ); - done(); - }); + const words = createFile("watched-words.txt"); + await this.container + .lookup("service:app-events") + .trigger("upload-mixin:watched-word-uploader:add-files", words); + await waitFor(".bootbox span.d-button-label"); - const words = createFile("watched-words.txt"); - await this.container - .lookup("service:app-events") - .trigger("upload-mixin:watched-word-uploader:add-files", words); - await waitFor(".bootbox span.d-button-label"); - await click(".bootbox span.d-button-label"); - }, - }); - } -); + await click(".bootbox span.d-button-label"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/actions-summary-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/actions-summary-test.js new file mode 100644 index 00000000000..2a84f1fd82c --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/actions-summary-test.js @@ -0,0 +1,32 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { count } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; + +module("Integration | Component | Widget | actions-summary", function (hooks) { + setupRenderingTest(hooks); + + test("post deleted", async function (assert) { + this.set("args", { + deleted_at: "2016-01-01", + deletedByUsername: "eviltrout", + deletedByAvatarTemplate: "/images/avatar.png", + }); + + await render( + hbs`` + ); + + assert.strictEqual( + count(".post-action .d-icon-far-trash-alt"), + 1, + "it has the deleted icon" + ); + assert.strictEqual( + count(".avatar[title=eviltrout]"), + 1, + "it has the deleted by avatar" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/avatar-flair-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/avatar-flair-test.js new file mode 100644 index 00000000000..91e977ea9ff --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/avatar-flair-test.js @@ -0,0 +1,42 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; + +module("Integration | Component | Widget | avatar-flair", function (hooks) { + setupRenderingTest(hooks); + + test("avatar flair with an icon", async function (assert) { + this.set("args", { + flair_url: "fa-bars", + flair_bg_color: "CC0000", + flair_color: "FFFFFF", + }); + + await render( + hbs`` + ); + + assert.ok(exists(".avatar-flair"), "it has the tag"); + assert.ok(exists("svg.d-icon-bars"), "it has the svg icon"); + assert.strictEqual( + query(".avatar-flair").getAttribute("style"), + "background-color: #CC0000; color: #FFFFFF; ", + "it has styles" + ); + }); + + test("avatar flair with an image", async function (assert) { + this.set("args", { + flair_url: "/images/avatar.png", + }); + + await render( + hbs`` + ); + + assert.ok(exists(".avatar-flair"), "it has the tag"); + assert.ok(!exists("svg"), "it does not have an svg icon"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/button-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/button-test.js new file mode 100644 index 00000000000..b8098a138d6 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/button-test.js @@ -0,0 +1,66 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; + +module("Integration | Component | Widget | button", function (hooks) { + setupRenderingTest(hooks); + + test("icon only button", async function (assert) { + this.set("args", { icon: "far-smile" }); + + 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-far-smile"), "it has the icon"); + }); + + test("icon and text button", async function (assert) { + this.set("args", { icon: "plus", label: "topic.create" }); + + 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("emoji and text button", async function (assert) { + this.set("args", { emoji: "mega", label: "topic.create" }); + + await render(hbs``); + + assert.ok(exists("button.widget-button"), "renders the widget"); + assert.ok(exists("button img.emoji"), "it renders the emoji"); + assert.ok(exists("button span.d-button-label"), "it renders the label"); + }); + + test("text only button", async function (assert) { + this.set("args", { label: "topic.create" }); + + 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("translatedLabel", async function (assert) { + this.set("args", { translatedLabel: "foo bar" }); + + await render(hbs``); + + assert.strictEqual( + query("button span.d-button-label").innerText, + "foo bar" + ); + }); + + test("translatedTitle", async function (assert) { + this.set("args", { label: "topic.create", translatedTitle: "foo bar" }); + + await render(hbs``); + + assert.strictEqual(query("button").title, "foo bar"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/default-notification-item-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/default-notification-item-test.js new file mode 100644 index 00000000000..57ecf376448 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/default-notification-item-test.js @@ -0,0 +1,62 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render, triggerEvent } from "@ember/test-helpers"; +import { count, exists } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import pretender, { response } from "discourse/tests/helpers/create-pretender"; +import EmberObject from "@ember/object"; + +module( + "Integration | Component | Widget | default-notification-item", + function (hooks) { + setupRenderingTest(hooks); + + test("sets notification as read on middle click", async function (assert) { + this.set( + "args", + EmberObject.create({ + id: 3, + user_id: 1, + notification_type: 6, + read: false, + created_at: "2020-01-01T12:00:00.000Z", + post_number: 1, + topic_id: 10, + fancy_title: "Greetings!", + slug: "greetings", + data: { + topic_title: "Greetings!", + original_post_id: 14, + original_post_type: 1, + original_username: "discobot", + revision_number: null, + display_username: "discobot", + }, + }) + ); + + await render( + hbs`` + ); + + let requests = 0; + pretender.put("/notifications/mark-read", (request) => { + ++requests; + + assert.strictEqual( + request.requestBody, + `id=${this.args.id}`, + "it sets correct request parameters" + ); + + return response({ success: true }); + }); + + assert.ok(!exists("li.read")); + + await triggerEvent("li", "mouseup", { button: 1, which: 2 }); + assert.strictEqual(count("li.read"), 1); + assert.strictEqual(requests, 1); + }); + } +); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/hamburger-menu-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/hamburger-menu-test.js new file mode 100644 index 00000000000..605770ee66d --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/hamburger-menu-test.js @@ -0,0 +1,213 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { count, exists, queryAll } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import { NotificationLevels } from "discourse/lib/notification-levels"; + +const topCategoryIds = [2, 3, 1]; +let mutedCategoryIds = []; +let unreadCategoryIds = []; +let categoriesByCount = []; + +module("Integration | Component | Widget | hamburger-menu", function (hooks) { + setupRenderingTest(hooks); + + test("prioritize faq", async function (assert) { + this.siteSettings.faq_url = "http://example.com/faq"; + this.currentUser.set("read_faq", false); + + await render(hbs``); + + assert.ok(exists(".faq-priority")); + assert.ok(!exists(".faq-link")); + }); + + test("prioritize faq - user has read", async function (assert) { + this.siteSettings.faq_url = "http://example.com/faq"; + this.currentUser.set("read_faq", true); + + await render(hbs``); + + assert.ok(!exists(".faq-priority")); + assert.ok(exists(".faq-link")); + }); + + test("staff menu - not staff", async function (assert) { + this.currentUser.set("staff", false); + + await render(hbs``); + + assert.ok(!exists(".admin-link")); + }); + + test("staff menu - moderator", async function (assert) { + this.currentUser.set("moderator", true); + this.currentUser.set("can_review", true); + + await render(hbs``); + + assert.ok(exists(".admin-link")); + assert.ok(exists(".review")); + assert.ok(!exists(".settings-link")); + }); + + test("staff menu - admin", async function (assert) { + this.currentUser.setProperties({ admin: true }); + + await render(hbs``); + + assert.ok(exists(".settings-link")); + }); + + test("logged in links", async function (assert) { + await render(hbs``); + + assert.ok(exists(".new-topics-link")); + assert.ok(exists(".unread-topics-link")); + }); + + test("general links", async function (assert) { + this.owner.unregister("current-user:main"); + + await render(hbs``); + + assert.ok(!exists("li[class='']")); + assert.ok(exists(".latest-topics-link")); + assert.ok(!exists(".new-topics-link")); + assert.ok(!exists(".unread-topics-link")); + assert.ok(exists(".top-topics-link")); + assert.ok(exists(".badge-link")); + assert.ok(exists(".category-link")); + assert.ok(exists(".about-link")); + assert.ok(exists(".keyboard-shortcuts-link")); + }); + + let maxCategoriesToDisplay; + + test("top categories - anonymous", async function (assert) { + this.owner.unregister("current-user:main"); + this.siteSettings.header_dropdown_category_count = 8; + + await render(hbs``); + + assert.strictEqual(count(".category-link"), 8); + assert.deepEqual( + [...queryAll(".category-link .category-name")].map((el) => el.innerText), + this.site + .get("categoriesByCount") + .slice(0, 8) + .map((c) => c.name) + ); + }); + + test("top categories - allow_uncategorized_topics", async function (assert) { + this.owner.unregister("current-user:main"); + this.siteSettings.allow_uncategorized_topics = false; + this.siteSettings.header_dropdown_category_count = 8; + + await render(hbs``); + + assert.strictEqual(count(".category-link"), 8); + assert.deepEqual( + [...queryAll(".category-link .category-name")].map((el) => el.innerText), + this.site + .get("categoriesByCount") + .filter((c) => c.name !== "uncategorized") + .slice(0, 8) + .map((c) => c.name) + ); + }); + + test("top categories", async function (assert) { + this.siteSettings.header_dropdown_category_count = 8; + maxCategoriesToDisplay = this.siteSettings.header_dropdown_category_count; + categoriesByCount = this.site.get("categoriesByCount").slice(); + categoriesByCount.every((c) => { + if (!topCategoryIds.includes(c.id)) { + if (mutedCategoryIds.length === 0) { + mutedCategoryIds.push(c.id); + c.set("notification_level", NotificationLevels.MUTED); + } else if (unreadCategoryIds.length === 0) { + unreadCategoryIds.push(c.id); + for (let i = 0; i < 5; i++) { + c.topicTrackingState.modifyState(123 + i, { + category_id: c.id, + last_read_post_number: 1, + highest_post_number: 2, + notification_level: NotificationLevels.TRACKING, + unread_not_too_old: true, + }); + } + } else { + unreadCategoryIds.splice(0, 0, c.id); + for (let i = 0; i < 10; i++) { + c.topicTrackingState.modifyState(321 + i, { + category_id: c.id, + last_read_post_number: null, + created_in_new_period: true, + }); + } + return false; + } + } + return true; + }); + this.currentUser.set("top_category_ids", topCategoryIds); + + await render(hbs``); + + assert.strictEqual( + count(".category-link"), + maxCategoriesToDisplay, + "categories displayed limited by header_dropdown_category_count" + ); + + categoriesByCount = categoriesByCount.filter( + (c) => !mutedCategoryIds.includes(c.id) + ); + let ids = [ + ...unreadCategoryIds, + ...topCategoryIds, + ...categoriesByCount.map((c) => c.id), + ] + .uniq() + .slice(0, maxCategoriesToDisplay); + + assert.deepEqual( + [...queryAll(".category-link .category-name")].map((el) => el.innerText), + ids.map( + (id) => categoriesByCount.find((category) => category.id === id).name + ), + "top categories are in the correct order" + ); + }); + + test("badges link - disabled", async function (assert) { + this.siteSettings.enable_badges = false; + + await render(hbs``); + + assert.ok(!exists(".badge-link")); + }); + + test("badges link", async function (assert) { + await render(hbs``); + + assert.ok(exists(".badge-link")); + }); + + test("user directory link", async function (assert) { + await render(hbs``); + + assert.ok(exists(".user-directory-link")); + }); + + test("user directory link - disabled", async function (assert) { + this.siteSettings.enable_user_directory = false; + + await render(hbs``); + + assert.ok(!exists(".user-directory-link")); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/header-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/header-test.js new file mode 100644 index 00000000000..402faaf871b --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/header-test.js @@ -0,0 +1,85 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { exists } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; + +module("Integration | Component | Widget | header", function (hooks) { + setupRenderingTest(hooks); + + test("rendering basics", async function (assert) { + await render(hbs``); + + assert.ok(exists("header.d-header")); + assert.ok(exists("#site-logo")); + }); + + test("sign up / login buttons", async function (assert) { + this.owner.unregister("current-user:main"); + this.set("args", { canSignUp: true }); + this.set("showCreateAccount", () => (this.signupShown = true)); + this.set("showLogin", () => (this.loginShown = true)); + + await render(hbs` + + `); + + assert.ok(exists("button.sign-up-button")); + assert.ok(exists("button.login-button")); + + await click("button.sign-up-button"); + assert.ok(this.signupShown); + + await click("button.login-button"); + assert.ok(this.loginShown); + }); + + test("anon when login required", async function (assert) { + this.owner.unregister("current-user:main"); + this.set("args", { canSignUp: true }); + this.set("showCreateAccount", () => (this.signupShown = true)); + this.set("showLogin", () => (this.loginShown = true)); + this.siteSettings.login_required = true; + + await render(hbs` + + `); + + assert.ok(exists("button.login-button")); + assert.ok(exists("button.sign-up-button")); + assert.ok(!exists("#search-button")); + assert.ok(!exists("#toggle-hamburger-menu")); + }); + + test("logged in when login required", async function (assert) { + this.set("args", { canSignUp: true }); + this.set("showCreateAccount", () => (this.signupShown = true)); + this.set("showLogin", () => (this.loginShown = true)); + this.siteSettings.login_required = true; + + await render(hbs` + + `); + + assert.ok(!exists("button.login-button")); + assert.ok(!exists("button.sign-up-button")); + assert.ok(exists("#search-button")); + assert.ok(exists("#toggle-hamburger-menu")); + assert.ok(exists("#current-user")); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/home-logo-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/home-logo-test.js new file mode 100644 index 00000000000..6cab1456f55 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/home-logo-test.js @@ -0,0 +1,194 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { count, exists, query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import Session from "discourse/models/session"; + +const bigLogo = "/images/d-logo-sketch.png?test"; +const smallLogo = "/images/d-logo-sketch-small.png?test"; +const mobileLogo = "/images/d-logo-sketch.png?mobile"; +const darkLogo = "/images/d-logo-sketch.png?dark"; +const title = "Cool Forum"; +const prefersDark = "(prefers-color-scheme: dark)"; + +module("Integration | Component | Widget | home-logo", function (hooks) { + setupRenderingTest(hooks); + + hooks.afterEach(function () { + Session.currentProp("darkModeAvailable", null); + Session.currentProp("defaultColorSchemeIsDark", null); + }); + + test("basics", async function (assert) { + this.siteSettings.site_logo_url = bigLogo; + this.siteSettings.site_logo_small_url = smallLogo; + this.siteSettings.title = title; + this.set("args", { minimized: false }); + + await render(hbs``); + + assert.strictEqual(count(".title"), 1); + assert.strictEqual(count("img#site-logo.logo-big"), 1); + assert.strictEqual(query("#site-logo").getAttribute("src"), bigLogo); + assert.strictEqual(query("#site-logo").getAttribute("alt"), title); + }); + + test("basics - minimized", async function (assert) { + this.siteSettings.site_logo_url = bigLogo; + this.siteSettings.site_logo_small_url = smallLogo; + this.siteSettings.title = title; + this.set("args", { minimized: true }); + + await render(hbs``); + + assert.strictEqual(count("img.logo-small"), 1); + assert.strictEqual(query("img.logo-small").getAttribute("src"), smallLogo); + assert.strictEqual(query("img.logo-small").getAttribute("alt"), title); + assert.strictEqual(query("img.logo-small").getAttribute("width"), "36"); + }); + + test("no logo", async function (assert) { + this.siteSettings.site_logo_url = ""; + this.siteSettings.site_logo_small_url = ""; + this.siteSettings.title = title; + this.set("args", { minimized: false }); + + await render(hbs``); + + assert.strictEqual(count("h1#site-text-logo.text-logo"), 1); + assert.strictEqual(query("#site-text-logo").innerText, title); + }); + + test("no logo - minimized", async function (assert) { + this.siteSettings.site_logo_url = ""; + this.siteSettings.site_logo_small_url = ""; + this.siteSettings.title = title; + this.set("args", { minimized: true }); + + await render(hbs``); + + assert.strictEqual(count(".d-icon-home"), 1); + }); + + test("mobile logo", async function (assert) { + this.siteSettings.site_mobile_logo_url = mobileLogo; + this.siteSettings.site_logo_small_url = smallLogo; + this.site.mobileView = true; + + await render(hbs``); + + assert.strictEqual(count("img#site-logo.logo-mobile"), 1); + assert.strictEqual(query("#site-logo").getAttribute("src"), mobileLogo); + }); + + test("mobile without logo", async function (assert) { + this.siteSettings.site_logo_url = bigLogo; + this.site.mobileView = true; + + await render(hbs``); + + assert.strictEqual(count("img#site-logo.logo-big"), 1); + assert.strictEqual(query("#site-logo").getAttribute("src"), bigLogo); + }); + + test("logo with dark mode alternative", async function (assert) { + this.siteSettings.site_logo_url = bigLogo; + this.siteSettings.site_logo_dark_url = darkLogo; + Session.currentProp("darkModeAvailable", true); + + await render(hbs``); + + assert.strictEqual(count("img#site-logo.logo-big"), 1); + assert.strictEqual(query("#site-logo").getAttribute("src"), bigLogo); + + assert.strictEqual( + query("picture source").getAttribute("media"), + prefersDark, + "includes dark mode media attribute" + ); + assert.strictEqual( + query("picture source").getAttribute("srcset"), + darkLogo, + "includes dark mode alternative logo source" + ); + }); + + test("mobile logo with dark mode alternative", async function (assert) { + this.siteSettings.site_logo_url = bigLogo; + this.siteSettings.site_mobile_logo_url = mobileLogo; + this.siteSettings.site_mobile_logo_dark_url = darkLogo; + Session.currentProp("darkModeAvailable", true); + + this.site.mobileView = true; + + await render(hbs``); + + assert.strictEqual(query("#site-logo").getAttribute("src"), mobileLogo); + + assert.strictEqual( + query("picture source").getAttribute("media"), + prefersDark, + "includes dark mode media attribute" + ); + assert.strictEqual( + query("picture source").getAttribute("srcset"), + darkLogo, + "includes dark mode alternative logo source" + ); + }); + + test("dark mode enabled but no dark logo set", async function (assert) { + this.siteSettings.site_logo_url = bigLogo; + this.siteSettings.site_logo_dark_url = ""; + Session.currentProp("darkModeAvailable", true); + + await render(hbs``); + + assert.strictEqual(count("img#site-logo.logo-big"), 1); + assert.strictEqual(query("#site-logo").getAttribute("src"), bigLogo); + assert.ok(!exists("picture"), "does not include alternative logo"); + }); + + test("dark logo set but no dark mode", async function (assert) { + this.siteSettings.site_logo_url = bigLogo; + this.siteSettings.site_logo_dark_url = darkLogo; + + await render(hbs``); + + assert.strictEqual(count("img#site-logo.logo-big"), 1); + assert.strictEqual(query("#site-logo").getAttribute("src"), bigLogo); + assert.ok(!exists("picture"), "does not include alternative logo"); + }); + + test("dark color scheme and dark logo set", async function (assert) { + this.siteSettings.site_logo_url = bigLogo; + this.siteSettings.site_logo_dark_url = darkLogo; + Session.currentProp("defaultColorSchemeIsDark", true); + + await render(hbs``); + + assert.strictEqual(count("img#site-logo.logo-big"), 1); + assert.strictEqual( + query("#site-logo").getAttribute("src"), + darkLogo, + "uses dark logo" + ); + assert.ok(!exists("picture"), "does not add dark mode alternative"); + }); + + test("dark color scheme and dark logo not set", async function (assert) { + this.siteSettings.site_logo_url = bigLogo; + this.siteSettings.site_logo_dark_url = ""; + Session.currentProp("defaultColorSchemeIsDark", true); + + await render(hbs``); + + assert.strictEqual(count("img#site-logo.logo-big"), 1); + assert.strictEqual( + query("#site-logo").getAttribute("src"), + bigLogo, + "uses regular logo on dark scheme if no dark logo" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/post-links-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/post-links-test.js new file mode 100644 index 00000000000..6016d1298c0 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/post-links-test.js @@ -0,0 +1,85 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { count } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; + +module("Integration | Component | Widget | post-links", function (hooks) { + setupRenderingTest(hooks); + + test("duplicate links", async function (assert) { + this.set("args", { + id: 2, + links: [ + { + title: "Evil Trout Link", + url: "http://eviltrout.com", + reflection: true, + }, + { + title: "Evil Trout Link", + url: "http://dupe.eviltrout.com", + reflection: true, + }, + ], + }); + + await render(hbs``); + + assert.strictEqual( + count(".post-links a.track-link"), + 1, + "it hides the dupe link" + ); + }); + + test("collapsed links", async function (assert) { + this.set("args", { + id: 1, + links: [ + { + title: "Link 1", + url: "http://eviltrout.com?1", + reflection: true, + }, + { + title: "Link 2", + url: "http://eviltrout.com?2", + reflection: true, + }, + { + title: "Link 3", + url: "http://eviltrout.com?3", + reflection: true, + }, + { + title: "Link 4", + url: "http://eviltrout.com?4", + reflection: true, + }, + { + title: "Link 5", + url: "http://eviltrout.com?5", + reflection: true, + }, + { + title: "Link 6", + url: "http://eviltrout.com?6", + reflection: true, + }, + { + title: "Link 7", + url: "http://eviltrout.com?7", + reflection: true, + }, + ], + }); + + await render(hbs``); + + assert.strictEqual(count(".expand-links"), 1, "collapsed by default"); + + await click("a.expand-links"); + assert.strictEqual(count(".post-links a.track-link"), 7); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/post-menu-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/post-menu-test.js new file mode 100644 index 00000000000..d5a2f6a650f --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/post-menu-test.js @@ -0,0 +1,78 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { count, exists } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import { resetPostMenuExtraButtons } from "discourse/widgets/post-menu"; +import { withPluginApi } from "discourse/lib/plugin-api"; + +module("Integration | Component | Widget | post-menu", function (hooks) { + setupRenderingTest(hooks); + + hooks.afterEach(function () { + resetPostMenuExtraButtons(); + }); + + test("add extra button", async function (assert) { + this.set("args", {}); + withPluginApi("0.14.0", (api) => { + api.addPostMenuButton("coffee", () => { + return { + action: "drinkCoffee", + icon: "coffee", + className: "hot-coffee", + title: "coffee.title", + position: "first", + }; + }); + }); + + await render(hbs``); + + assert.strictEqual( + count(".actions .extra-buttons .hot-coffee"), + 1, + "It renders extra button" + ); + }); + + test("removes button based on callback", async function (assert) { + this.set("args", { canCreatePost: true, canRemoveReply: true }); + + withPluginApi("0.14.0", (api) => { + api.removePostMenuButton("reply", (attrs) => { + return attrs.canRemoveReply; + }); + }); + + await render(hbs``); + + assert.ok(!exists(".actions .reply"), "it removes reply button"); + }); + + test("does not remove button", async function (assert) { + this.set("args", { canCreatePost: true, canRemoveReply: false }); + + withPluginApi("0.14.0", (api) => { + api.removePostMenuButton("reply", (attrs) => { + return attrs.canRemoveReply; + }); + }); + + await render(hbs``); + + assert.ok(exists(".actions .reply"), "it does not remove reply button"); + }); + + test("removes button", async function (assert) { + this.set("args", { canCreatePost: true }); + + withPluginApi("0.14.0", (api) => { + api.removePostMenuButton("reply"); + }); + + await render(hbs``); + + assert.ok(!exists(".actions .reply"), "it removes reply button"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/post-small-action-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/post-small-action-test.js new file mode 100644 index 00000000000..2bfa596bf6e --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/post-small-action-test.js @@ -0,0 +1,93 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; + +module( + "Integration | Component | Widget | post-small-action", + function (hooks) { + setupRenderingTest(hooks); + + test("does not have delete/edit/recover buttons by default", async function (assert) { + this.set("args", { id: 123 }); + + await render( + hbs`` + ); + + assert.ok(!exists(".small-action-desc > .small-action-delete")); + assert.ok(!exists(".small-action-desc > .small-action-recover")); + assert.ok(!exists(".small-action-desc > .small-action-edit")); + }); + + test("shows edit button if canEdit", async function (assert) { + this.set("args", { id: 123, canEdit: true }); + + await render( + hbs`` + ); + + assert.ok( + exists(".small-action-desc > .small-action-edit"), + "it adds the edit small action button" + ); + }); + + test("uses custom widget if actionDescriptionWidget", async function (assert) { + this.set("args", { id: 123, actionDescriptionWidget: "button" }); + + await render( + hbs`` + ); + + assert.ok( + exists(".small-action .widget-button"), + "it adds the custom widget" + ); + }); + + test("does not show edit button if canRecover even if canEdit", async function (assert) { + this.set("args", { id: 123, canEdit: true, canRecover: true }); + + await render( + hbs`` + ); + + assert.ok( + !exists(".small-action-desc > .small-action-edit"), + "it does not add the edit small action button" + ); + assert.ok( + exists(".small-action-desc > .small-action-recover"), + "it adds the recover small action button" + ); + }); + + test("shows delete button if canDelete", async function (assert) { + this.set("args", { id: 123, canDelete: true }); + + await render( + hbs`` + ); + + assert.ok( + exists(".small-action-desc > .small-action-delete"), + "it adds the delete small action button" + ); + }); + + test("shows undo button if canRecover", async function (assert) { + this.set("args", { id: 123, canRecover: true }); + + await render( + hbs`` + ); + + assert.ok( + exists(".small-action-desc > .small-action-recover"), + "it adds the recover small action button" + ); + }); + } +); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/post-stream-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/post-stream-test.js new file mode 100644 index 00000000000..5bda0515aca --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/post-stream-test.js @@ -0,0 +1,154 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { count } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import Post from "discourse/models/post"; +import Topic from "discourse/models/topic"; + +function postStreamTest(name, attrs) { + test(name, async function (assert) { + const site = this.container.lookup("site:main"); + let posts = attrs.posts.call(this); + posts.forEach((p) => p.set("site", site)); + this.set("posts", posts); + + await render( + hbs`` + ); + + attrs.test.call(this, assert); + }); +} + +module("Integration | Component | Widget | post-stream", function (hooks) { + setupRenderingTest(hooks); + + postStreamTest("basics", { + posts() { + const site = this.container.lookup("site:main"); + const topic = Topic.create(); + topic.set("details.created_by", { id: 123 }); + return [ + Post.create({ + topic, + id: 1, + post_number: 1, + user_id: 123, + primary_group_name: "trout", + avatar_template: "/images/avatar.png", + }), + Post.create({ + topic, + id: 2, + post_number: 2, + post_type: site.get("post_types.moderator_action"), + }), + Post.create({ topic, id: 3, post_number: 3, hidden: true }), + Post.create({ + topic, + id: 4, + post_number: 4, + post_type: site.get("post_types.whisper"), + }), + Post.create({ + topic, + id: 5, + post_number: 5, + wiki: true, + via_email: true, + }), + Post.create({ + topic, + id: 6, + post_number: 6, + via_email: true, + is_auto_generated: true, + }), + ]; + }, + + test(assert) { + assert.strictEqual(count(".post-stream"), 1); + assert.strictEqual(count(".topic-post"), 6, "renders all posts"); + + // look for special class bindings + assert.strictEqual( + count(".topic-post:nth-of-type(1).topic-owner"), + 1, + "it applies the topic owner class" + ); + assert.strictEqual( + count(".topic-post:nth-of-type(1).group-trout"), + 1, + "it applies the primary group class" + ); + assert.strictEqual( + count(".topic-post:nth-of-type(1).regular"), + 1, + "it applies the regular class" + ); + assert.strictEqual( + count(".topic-post:nth-of-type(2).moderator"), + 1, + "it applies the moderator class" + ); + assert.strictEqual( + count(".topic-post:nth-of-type(3).post-hidden"), + 1, + "it applies the hidden class" + ); + assert.strictEqual( + count(".topic-post:nth-of-type(4).whisper"), + 1, + "it applies the whisper class" + ); + assert.strictEqual( + count(".topic-post:nth-of-type(5).wiki"), + 1, + "it applies the wiki class" + ); + + // it renders an article for the body with appropriate attributes + assert.strictEqual(count("article#post_2"), 1); + assert.strictEqual(count('article[data-user-id="123"]'), 1); + assert.strictEqual(count('article[data-post-id="3"]'), 1); + assert.strictEqual(count("article#post_5.via-email"), 1); + assert.strictEqual(count("article#post_6.is-auto-generated"), 1); + + assert.strictEqual( + count("article:nth-of-type(1) .main-avatar"), + 1, + "renders the main avatar" + ); + }, + }); + + postStreamTest("deleted posts", { + posts() { + const topic = Topic.create(); + topic.set("details.created_by", { id: 123 }); + return [ + Post.create({ + topic, + id: 1, + post_number: 1, + deleted_at: new Date().toString(), + }), + ]; + }, + + test(assert) { + assert.strictEqual( + count(".topic-post.deleted"), + 1, + "it applies the deleted class" + ); + assert.strictEqual( + count(".deleted-user-avatar"), + 1, + "it has the trash avatar" + ); + }, + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/post-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/post-test.js new file mode 100644 index 00000000000..cd0c67c839c --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/post-test.js @@ -0,0 +1,920 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { + count, + exists, + query, + queryAll, +} from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import EmberObject from "@ember/object"; +import I18n from "I18n"; +import createStore from "discourse/tests/helpers/create-store"; + +module("Integration | Component | Widget | post", function (hooks) { + setupRenderingTest(hooks); + + test("basic elements", async function (assert) { + this.set("args", { shareUrl: "/example", post_number: 1 }); + + await render(hbs``); + + assert.ok(exists(".names"), "includes poster name"); + assert.ok(exists("a.post-date"), "includes post date"); + }); + + test("post - links", async function (assert) { + this.set("args", { + cooked: + "first link and second link", + linkCounts: [ + { url: "http://link1.example.com/", clicks: 1, internal: true }, + { url: "http://link2.example.com/", clicks: 2, internal: true }, + ], + }); + + await render( + hbs`` + ); + + assert.strictEqual(queryAll(".badge.clicks")[0].innerText, "1"); + assert.strictEqual(queryAll(".badge.clicks")[1].innerText, "2"); + }); + + test("post - onebox links", async function (assert) { + this.set("args", { + cooked: ` +

Other URL

+ + `, + linkCounts: [ + { url: "https://example.com", clicks: 1 }, + { url: "https://twitter.com/codinghorror", clicks: 2 }, + ], + }); + + await render( + hbs`` + ); + + assert.strictEqual(count(".badge.clicks"), 2); + assert.strictEqual(queryAll(".badge.clicks")[0].innerText, "1"); + assert.strictEqual(queryAll(".badge.clicks")[1].innerText, "2"); + }); + + test("wiki", async function (assert) { + this.set("args", { wiki: true, version: 2, canViewEditHistory: true }); + this.set("showHistory", () => (this.historyShown = true)); + + await render(hbs` + + `); + + await click(".post-info .wiki"); + assert.ok( + this.historyShown, + "clicking the wiki icon displays the post history" + ); + }); + + test("wiki without revision", async function (assert) { + this.set("args", { wiki: true, version: 1, canViewEditHistory: true }); + this.set("editPost", () => (this.editPostCalled = true)); + + await render(hbs` + + `); + + await click(".post-info .wiki"); + assert.ok(this.editPostCalled, "clicking wiki icon edits the post"); + }); + + test("via-email", async function (assert) { + this.set("args", { via_email: true, canViewRawEmail: true }); + this.set("showRawEmail", () => (this.rawEmailShown = true)); + + await render(hbs` + + `); + + await click(".post-info.via-email"); + assert.ok(this.rawEmailShown, "clicking the envelope shows the raw email"); + }); + + test("via-email without permission", async function (assert) { + this.set("args", { via_email: true, canViewRawEmail: false }); + this.set("showRawEmail", () => (this.rawEmailShown = true)); + + await render(hbs` + + `); + + await click(".post-info.via-email"); + assert.ok( + !this.rawEmailShown, + "clicking the envelope doesn't show the raw email" + ); + }); + + test("history", async function (assert) { + this.set("args", { version: 3, canViewEditHistory: true }); + this.set("showHistory", () => (this.historyShown = true)); + + await render(hbs` + + `); + + await click(".post-info.edits button"); + assert.ok(this.historyShown, "clicking the pencil shows the history"); + }); + + test("history without view permission", async function (assert) { + this.set("args", { version: 3, canViewEditHistory: false }); + this.set("showHistory", () => (this.historyShown = true)); + + await render(hbs` + + `); + + await click(".post-info.edits"); + assert.ok( + !this.historyShown, + `clicking the pencil doesn't show the history` + ); + }); + + test("whisper", async function (assert) { + this.set("args", { isWhisper: true }); + + await render(hbs``); + + assert.strictEqual(count(".topic-post.whisper"), 1); + assert.strictEqual(count(".post-info.whisper"), 1); + }); + + test("like count button", async function (assert) { + const store = createStore(); + const topic = store.createRecord("topic", { id: 123 }); + const post = store.createRecord("post", { + id: 1, + post_number: 1, + topic, + like_count: 3, + actions_summary: [{ id: 2, count: 1, hidden: false, can_act: true }], + }); + this.set("post", post); + this.set("args", { likeCount: 1 }); + + await render( + hbs`` + ); + + assert.strictEqual(count("button.like-count"), 1); + assert.ok(!exists(".who-liked")); + + // toggle it on + await click("button.like-count"); + assert.strictEqual(count(".who-liked"), 1); + assert.strictEqual(count(".who-liked a.trigger-user-card"), 1); + + // toggle it off + await click("button.like-count"); + assert.ok(!exists(".who-liked")); + assert.ok(!exists(".who-liked a.trigger-user-card")); + }); + + test(`like count with no likes`, async function (assert) { + this.set("args", { likeCount: 0 }); + + await render( + hbs`` + ); + + assert.ok(!exists("button.like-count")); + }); + + test("share button", async function (assert) { + this.set("args", { shareUrl: "http://share-me.example.com" }); + + await render(hbs``); + + assert.ok(exists(".actions button.share"), "it renders a share button"); + }); + + test("liking", async function (assert) { + const args = { showLike: true, canToggleLike: true, id: 5 }; + this.set("args", args); + this.set("toggleLike", () => { + args.liked = !args.liked; + args.likeCount = args.liked ? 1 : 0; + }); + + await render(hbs` + + `); + + assert.ok(exists(".actions button.like")); + assert.ok(!exists(".actions button.like-count")); + + await click(".actions button.like"); + assert.ok(!exists(".actions button.like")); + assert.ok(exists(".actions button.has-like")); + assert.strictEqual(count(".actions button.like-count"), 1); + + await click(".actions button.has-like"); + assert.ok(exists(".actions button.like")); + assert.ok(!exists(".actions button.has-like")); + assert.ok(!exists(".actions button.like-count")); + }); + + test("anon liking", async function (assert) { + this.owner.unregister("current-user:main"); + const args = { showLike: true }; + this.set("args", args); + this.set("showLogin", () => (this.loginShown = true)); + + await render(hbs` + + `); + + assert.ok(exists(".actions button.like")); + assert.ok(!exists(".actions button.like-count")); + + assert.strictEqual( + query("button.like").getAttribute("title"), + I18n.t("post.controls.like"), + `shows the right button title for anonymous users` + ); + + await click(".actions button.like"); + assert.ok(this.loginShown); + }); + + test("edit button", async function (assert) { + this.set("args", { canEdit: true }); + this.set("editPost", () => (this.editPostCalled = true)); + + await render(hbs` + + `); + + await click("button.edit"); + assert.ok(this.editPostCalled, "it triggered the edit action"); + }); + + test(`edit button - can't edit`, async function (assert) { + this.set("args", { canEdit: false }); + + await render(hbs``); + + assert.ok(!exists("button.edit"), "button is not displayed"); + }); + + test("recover button", async function (assert) { + this.set("args", { canDelete: true }); + this.set("deletePost", () => (this.deletePostCalled = true)); + + await render(hbs` + + `); + + await click("button.delete"); + assert.ok(this.deletePostCalled, "it triggered the delete action"); + }); + + test("delete topic button", async function (assert) { + this.set("args", { canDeleteTopic: true }); + this.set("deletePost", () => (this.deletePostCalled = true)); + + await render(hbs` + + `); + + await click("button.delete"); + assert.ok(this.deletePostCalled, "it triggered the delete action"); + }); + + test(`delete topic button - can't delete`, async function (assert) { + this.set("args", { canDeleteTopic: false }); + + await render(hbs``); + + assert.ok(!exists("button.delete"), `button is not displayed`); + }); + + test(`delete topic button - can't delete when topic author without permission`, async function (assert) { + this.set("args", { + canDeleteTopic: false, + showFlagDelete: true, + canFlag: true, + }); + + await render(hbs``); + + await click(".show-more-actions"); + + assert.strictEqual(count("button.create-flag"), 1, `button is displayed`); + assert.strictEqual(count("button.delete"), 1, `button is displayed`); + assert.strictEqual( + query("button.delete").getAttribute("title"), + I18n.t("post.controls.delete_topic_disallowed"), + `shows the right button title for users without permissions` + ); + }); + + test("recover topic button", async function (assert) { + this.set("args", { canRecoverTopic: true }); + this.set("recoverPost", () => (this.recovered = true)); + + await render(hbs` + + `); + + await click("button.recover"); + assert.ok(this.recovered); + }); + + test(`recover topic button - can't recover`, async function (assert) { + this.set("args", { canRecoverTopic: false }); + + await render(hbs``); + + assert.ok(!exists("button.recover"), `button is not displayed`); + }); + + test("delete post button", async function (assert) { + this.set("args", { canDelete: true, canFlag: true }); + this.set("deletePost", () => (this.deletePostCalled = true)); + + await render(hbs` + + `); + + await click(".show-more-actions"); + await click("button.delete"); + assert.ok(this.deletePostCalled, "it triggered the delete action"); + }); + + test(`delete post button - can't delete`, async function (assert) { + this.set("args", { canDelete: false }); + + await render(hbs``); + + assert.ok(!exists("button.delete"), `button is not displayed`); + }); + + test(`delete post button - can't delete, can't flag`, async function (assert) { + this.set("args", { + canDeleteTopic: false, + showFlagDelete: false, + canFlag: false, + }); + + await render(hbs``); + + assert.ok(!exists("button.delete"), `delete button is not displayed`); + assert.ok(!exists("button.create-flag"), `flag button is not displayed`); + }); + + test("recover post button", async function (assert) { + this.set("args", { canRecover: true }); + this.set("recoverPost", () => (this.recovered = true)); + + await render(hbs` + + `); + + await click("button.recover"); + assert.ok(this.recovered); + }); + + test(`recover post button - can't recover`, async function (assert) { + this.set("args", { canRecover: false }); + + await render(hbs``); + + assert.ok(!exists("button.recover"), `button is not displayed`); + }); + + test(`flagging`, async function (assert) { + this.set("args", { canFlag: true }); + this.set("showFlags", () => (this.flagsShown = true)); + + await render(hbs` + + `); + + assert.strictEqual(count("button.create-flag"), 1); + + await click("button.create-flag"); + assert.ok(this.flagsShown, "it triggered the action"); + }); + + test(`flagging: can't flag`, async function (assert) { + this.set("args", { canFlag: false }); + + await render(hbs``); + + assert.ok(!exists("button.create-flag")); + }); + + test(`flagging: can't flag when post is hidden`, async function (assert) { + this.set("args", { canFlag: true, hidden: true }); + + await render(hbs``); + + assert.ok(!exists("button.create-flag")); + }); + + test(`read indicator`, async function (assert) { + this.set("args", { read: true }); + + await render(hbs``); + + assert.ok(exists(".read-state.read")); + }); + + test(`unread indicator`, async function (assert) { + this.set("args", { read: false }); + + await render(hbs``); + + assert.ok(exists(".read-state")); + }); + + test("reply directly above (suppressed)", async function (assert) { + this.set("args", { + replyToUsername: "eviltrout", + replyToAvatarTemplate: "/images/avatar.png", + replyDirectlyAbove: true, + }); + + await render(hbs``); + + assert.ok(!exists("a.reply-to-tab"), "hides the tab"); + assert.ok(!exists(".avoid-tab"), "doesn't have the avoid tab class"); + }); + + test("reply a few posts above (suppressed)", async function (assert) { + this.set("args", { + replyToUsername: "eviltrout", + replyToAvatarTemplate: "/images/avatar.png", + replyDirectlyAbove: false, + }); + + await render(hbs``); + + assert.ok(exists("a.reply-to-tab"), "shows the tab"); + assert.strictEqual(count(".avoid-tab"), 1, "has the avoid tab class"); + }); + + test("reply directly above", async function (assert) { + this.set("args", { + replyToUsername: "eviltrout", + replyToAvatarTemplate: "/images/avatar.png", + replyDirectlyAbove: true, + }); + this.siteSettings.suppress_reply_directly_above = false; + + await render(hbs``); + + assert.strictEqual(count(".avoid-tab"), 1, "has the avoid tab class"); + await click("a.reply-to-tab"); + assert.strictEqual(count("section.embedded-posts.top .cooked"), 1); + assert.strictEqual(count("section.embedded-posts .d-icon-arrow-up"), 1); + }); + + test("cooked content hidden", async function (assert) { + this.set("args", { cooked_hidden: true }); + this.set("expandHidden", () => (this.unhidden = true)); + + await render(hbs` + + `); + + await click(".topic-body .expand-hidden"); + assert.ok(this.unhidden, "triggers the action"); + }); + + test("expand first post", async function (assert) { + const store = createStore(); + this.set("args", { expandablePost: true }); + this.set("post", store.createRecord("post", { id: 1234 })); + + await render( + hbs`` + ); + + await click(".topic-body .expand-post"); + assert.ok(!exists(".expand-post"), "button is gone"); + }); + + test("can't bookmark", async function (assert) { + this.set("args", { canBookmark: false }); + + await render(hbs``); + + assert.ok(!exists("button.bookmark")); + assert.ok(!exists("button.bookmarked")); + }); + + test("bookmark", async function (assert) { + const args = { canBookmark: true }; + + this.set("args", args); + this.set("toggleBookmark", () => (args.bookmarked = true)); + + await render(hbs` + + `); + + assert.strictEqual(count(".post-menu-area .bookmark"), 1); + assert.ok(!exists("button.bookmarked")); + }); + + test("can't show admin menu when you can't manage", async function (assert) { + this.set("args", { canManage: false }); + + await render(hbs``); + + assert.ok(!exists(".post-menu-area .show-post-admin-menu")); + }); + + test("show admin menu", async function (assert) { + this.set("args", { canManage: true }); + + await render(hbs``); + + assert.ok(!exists(".post-admin-menu")); + await click(".post-menu-area .show-post-admin-menu"); + assert.strictEqual(count(".post-admin-menu"), 1, "it shows the popup"); + await click(".post-menu-area"); + assert.ok(!exists(".post-admin-menu"), "clicking outside clears the popup"); + }); + + test("permanently delete topic", async function (assert) { + this.set("args", { canManage: true, canPermanentlyDelete: true }); + this.set("permanentlyDeletePost", () => (this.deleted = true)); + + await render( + hbs`` + ); + + await click(".post-menu-area .show-post-admin-menu"); + await click(".post-admin-menu .permanently-delete"); + assert.ok(this.deleted); + assert.ok(!exists(".post-admin-menu"), "also hides the menu"); + }); + + test("permanently delete post", async function (assert) { + this.set("args", { canManage: true, canPermanentlyDelete: true }); + this.set("permanentlyDeletePost", () => (this.deleted = true)); + + await render(hbs` + + `); + + await click(".post-menu-area .show-post-admin-menu"); + await click(".post-admin-menu .permanently-delete"); + assert.ok(this.deleted); + assert.ok(!exists(".post-admin-menu"), "also hides the menu"); + }); + + test("toggle moderator post", async function (assert) { + this.currentUser.set("moderator", true); + this.set("args", { canManage: true }); + this.set("togglePostType", () => (this.toggled = true)); + + await render(hbs` + + `); + + await click(".post-menu-area .show-post-admin-menu"); + await click(".post-admin-menu .toggle-post-type"); + + assert.ok(this.toggled); + assert.ok(!exists(".post-admin-menu"), "also hides the menu"); + }); + + test("toggle moderator post", async function (assert) { + this.currentUser.set("moderator", true); + this.set("args", { canManage: true }); + this.set("togglePostType", () => (this.toggled = true)); + + await render(hbs` + + `); + + await click(".post-menu-area .show-post-admin-menu"); + await click(".post-admin-menu .toggle-post-type"); + + assert.ok(this.toggled); + assert.ok(!exists(".post-admin-menu"), "also hides the menu"); + }); + + test("rebake post", async function (assert) { + this.set("args", { canManage: true }); + this.set("rebakePost", () => (this.baked = true)); + + await render(hbs` + + `); + + await click(".post-menu-area .show-post-admin-menu"); + await click(".post-admin-menu .rebuild-html"); + assert.ok(this.baked); + assert.ok(!exists(".post-admin-menu"), "also hides the menu"); + }); + + test("unhide post", async function (assert) { + this.currentUser.admin = true; + this.set("args", { canManage: true, hidden: true }); + this.set("unhidePost", () => (this.unhidden = true)); + + await render(hbs` + + `); + + await click(".post-menu-area .show-post-admin-menu"); + await click(".post-admin-menu .unhide-post"); + assert.ok(this.unhidden); + assert.ok(!exists(".post-admin-menu"), "also hides the menu"); + }); + + test("change owner", async function (assert) { + this.currentUser.admin = true; + this.set("args", { canManage: true }); + this.set("changePostOwner", () => (this.owned = true)); + + await render(hbs` + + `); + + await click(".post-menu-area .show-post-admin-menu"); + await click(".post-admin-menu .change-owner"); + assert.ok(this.owned); + assert.ok(!exists(".post-admin-menu"), "also hides the menu"); + }); + + test("reply", async function (assert) { + this.set("args", { canCreatePost: true }); + this.set("replyToPost", () => (this.replied = true)); + + await render(hbs` + + `); + + await click(".post-controls .create"); + assert.ok(this.replied); + }); + + test("reply - without permissions", async function (assert) { + this.set("args", { canCreatePost: false }); + + await render(hbs``); + + assert.ok(!exists(".post-controls .create")); + }); + + test("replies - no replies", async function (assert) { + this.set("args", { replyCount: 0 }); + + await render(hbs``); + + assert.ok(!exists("button.show-replies")); + }); + + test("replies - multiple replies", async function (assert) { + this.siteSettings.suppress_reply_directly_below = true; + this.set("args", { replyCount: 2, replyDirectlyBelow: true }); + + await render(hbs``); + + assert.strictEqual(count("button.show-replies"), 1); + }); + + test("replies - one below, suppressed", async function (assert) { + this.siteSettings.suppress_reply_directly_below = true; + this.set("args", { replyCount: 1, replyDirectlyBelow: true }); + + await render(hbs``); + + assert.ok(!exists("button.show-replies")); + }); + + test("replies - one below, not suppressed", async function (assert) { + this.siteSettings.suppress_reply_directly_below = false; + this.set("args", { id: 6654, replyCount: 1, replyDirectlyBelow: true }); + + await render(hbs``); + + await click("button.show-replies"); + assert.strictEqual(count("section.embedded-posts.bottom .cooked"), 1); + assert.strictEqual(count("section.embedded-posts .d-icon-arrow-down"), 1); + }); + + test("topic map not shown", async function (assert) { + this.set("args", { showTopicMap: false }); + + await render(hbs``); + + assert.ok(!exists(".topic-map")); + }); + + test("topic map - few posts", async function (assert) { + this.set("args", { + showTopicMap: true, + topicPostsCount: 2, + participants: [{ username: "eviltrout" }, { username: "codinghorror" }], + }); + + await render(hbs``); + + assert.ok( + !exists("li.avatars a.poster"), + "shows no participants when collapsed" + ); + + await click("nav.buttons button"); + assert.strictEqual( + count(".topic-map-expanded a.poster"), + 2, + "shows all when expanded" + ); + }); + + test("topic map - participants", async function (assert) { + this.set("args", { + showTopicMap: true, + topicPostsCount: 10, + participants: [ + { username: "eviltrout" }, + { username: "codinghorror" }, + { username: "sam" }, + { username: "ZogStrIP" }, + ], + userFilters: ["sam", "codinghorror"], + }); + + await render(hbs``); + + assert.strictEqual( + count("li.avatars a.poster"), + 3, + "limits to three participants" + ); + + await click("nav.buttons button"); + assert.ok(!exists("li.avatars a.poster")); + assert.strictEqual( + count(".topic-map-expanded a.poster"), + 4, + "shows all when expanded" + ); + assert.strictEqual(count("a.poster.toggled"), 2, "two are toggled"); + }); + + test("topic map - links", async function (assert) { + this.set("args", { + showTopicMap: true, + topicLinks: [ + { url: "http://link1.example.com", clicks: 0 }, + { url: "http://link2.example.com", clicks: 0 }, + { url: "http://link3.example.com", clicks: 0 }, + { url: "http://link4.example.com", clicks: 0 }, + { url: "http://link5.example.com", clicks: 0 }, + { url: "http://link6.example.com", clicks: 0 }, + ], + }); + + await render(hbs``); + + assert.strictEqual(count(".topic-map"), 1); + assert.strictEqual(count(".map.map-collapsed"), 1); + assert.ok(!exists(".topic-map-expanded")); + + await click("nav.buttons button"); + assert.ok(!exists(".map.map-collapsed")); + assert.strictEqual(count(".topic-map .d-icon-chevron-up"), 1); + assert.strictEqual(count(".topic-map-expanded"), 1); + assert.strictEqual( + count(".topic-map-expanded .topic-link"), + 5, + "it limits the links displayed" + ); + + await click(".link-summary button"); + assert.strictEqual( + count(".topic-map-expanded .topic-link"), + 6, + "all links now shown" + ); + }); + + test("topic map - no summary", async function (assert) { + this.set("args", { showTopicMap: true }); + + await render(hbs``); + + assert.ok(!exists(".toggle-summary")); + }); + + test("topic map - has summary", async function (assert) { + this.set("args", { showTopicMap: true, hasTopicSummary: true }); + this.set("showSummary", () => (this.summaryToggled = true)); + + await render( + hbs`` + ); + + assert.strictEqual(count(".toggle-summary"), 1); + + await click(".toggle-summary button"); + assert.ok(this.summaryToggled); + }); + + test("pm map", async function (assert) { + this.set("args", { + showTopicMap: true, + showPMMap: true, + allowedGroups: [], + allowedUsers: [EmberObject.create({ username: "eviltrout" })], + }); + + await render(hbs``); + + assert.strictEqual(count(".private-message-map"), 1); + assert.strictEqual(count(".private-message-map .user"), 1); + }); + + test("post notice - with username", async function (assert) { + const twoDaysAgo = new Date(); + twoDaysAgo.setDate(twoDaysAgo.getDate() - 2); + this.siteSettings.display_name_on_posts = false; + this.siteSettings.prioritize_username_in_ux = true; + this.siteSettings.old_post_notice_days = 14; + this.set("args", { + username: "codinghorror", + name: "Jeff", + created_at: new Date(), + notice: { + type: "returning_user", + lastPostedAt: twoDaysAgo, + }, + }); + + await render(hbs``); + + assert.strictEqual( + query(".post-notice.returning-user:not(.old)").innerText.trim(), + I18n.t("post.notice.returning_user", { + user: "codinghorror", + time: "2 days ago", + }) + ); + }); + + test("post notice - with name", async function (assert) { + this.siteSettings.display_name_on_posts = true; + this.siteSettings.prioritize_username_in_ux = false; + this.siteSettings.old_post_notice_days = 14; + this.set("args", { + username: "codinghorror", + name: "Jeff", + created_at: new Date(2019, 0, 1), + notice: { type: "new_user" }, + }); + + await render(hbs``); + + assert.strictEqual( + query(".post-notice.old.new-user").innerText.trim(), + I18n.t("post.notice.new_user", { user: "Jeff", time: "Jan '10" }) + ); + }); + + test("show group request in post", async function (assert) { + this.set("args", { + username: "foo", + requestedGroupName: "testGroup", + }); + + await render(hbs``); + + const link = query(".group-request a"); + assert.strictEqual(link.innerText.trim(), I18n.t("groups.requests.handle")); + assert.strictEqual( + link.getAttribute("href"), + "/g/testGroup/requests?filter=foo" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/poster-name-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/poster-name-test.js new file mode 100644 index 00000000000..a1a240bb353 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/poster-name-test.js @@ -0,0 +1,75 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; + +module("Integration | Component | Widget | poster-name", function (hooks) { + setupRenderingTest(hooks); + + test("basic rendering", async function (assert) { + this.set("args", { + username: "eviltrout", + usernameUrl: "/u/eviltrout", + name: "Robin Ward", + user_title: "Trout Master", + }); + + await render( + hbs`` + ); + + assert.ok(exists(".names")); + assert.ok(exists("span.username")); + assert.ok(exists('a[data-user-card="eviltrout"]')); + assert.strictEqual(query(".username a").innerText, "eviltrout"); + assert.strictEqual(query(".full-name a").innerText, "Robin Ward"); + assert.strictEqual(query(".user-title").innerText, "Trout Master"); + }); + + test("extra classes and glyphs", async function (assert) { + this.set("args", { + username: "eviltrout", + usernameUrl: "/u/eviltrout", + staff: true, + admin: true, + moderator: true, + new_user: true, + primary_group_name: "fish", + }); + + await render( + hbs`` + ); + + assert.ok(exists("span.staff")); + assert.ok(exists("span.admin")); + assert.ok(exists("span.moderator")); + assert.ok(exists(".d-icon-shield-alt")); + assert.ok(exists("span.new-user")); + assert.ok(exists("span.fish")); + }); + + test("disable display name on posts", async function (assert) { + this.siteSettings.display_name_on_posts = false; + this.set("args", { username: "eviltrout", name: "Robin Ward" }); + + await render( + hbs`` + ); + + assert.ok(!exists(".full-name")); + }); + + test("doesn't render a name if it's similar to the username", async function (assert) { + 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`` + ); + + assert.ok(!exists(".second")); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/quick-access-item-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/quick-access-item-test.js new file mode 100644 index 00000000000..3477530da05 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/quick-access-item-test.js @@ -0,0 +1,36 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; + +const CONTENT_DIV_SELECTOR = "li > a > div"; + +module( + "Integration | Component | Widget | quick-access-item", + function (hooks) { + setupRenderingTest(hooks); + + test("content attribute is escaped", async function (assert) { + this.set("args", { content: "bold" }); + + await render( + hbs`` + ); + + const contentDiv = query(CONTENT_DIV_SELECTOR); + assert.strictEqual(contentDiv.innerText, "bold"); + }); + + test("escapedContent attribute is not escaped", async function (assert) { + this.set("args", { escapedContent: ""quote"" }); + + await render( + hbs`` + ); + + const contentDiv = query(CONTENT_DIV_SELECTOR); + assert.strictEqual(contentDiv.innerText, '"quote"'); + }); + } +); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/small-user-list-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/small-user-list-test.js new file mode 100644 index 00000000000..2c072b9e055 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/small-user-list-test.js @@ -0,0 +1,26 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { count, exists } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; + +module("Integration | Component | Widget | small-user-list", function (hooks) { + setupRenderingTest(hooks); + + test("renders avatars and support for unknown", async function (assert) { + this.set("args", { + users: [ + { id: 456, username: "eviltrout" }, + { id: 457, username: "someone", unknown: true }, + ], + }); + + await render( + hbs`` + ); + + assert.strictEqual(count('[data-user-card="eviltrout"]'), 1); + assert.ok(!exists('[data-user-card="someone"]')); + assert.ok(exists(".unknown"), "includes unknown user"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-admin-menu-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-admin-menu-test.js new file mode 100644 index 00000000000..32aa23b855d --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-admin-menu-test.js @@ -0,0 +1,69 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import Category from "discourse/models/category"; +import Topic from "discourse/models/topic"; + +const createArgs = (topic) => { + return { + topic, + openUpwards: "true", + toggleMultiSelect: () => {}, + deleteTopic: () => {}, + recoverTopic: () => {}, + toggleClosed: () => {}, + toggleArchived: () => {}, + toggleVisibility: () => {}, + showTopicTimerModal: () => {}, + showFeatureTopic: () => {}, + showChangeTimestamp: () => {}, + resetBumpDate: () => {}, + convertToPublicTopic: () => {}, + convertToPrivateMessage: () => {}, + }; +}; + +module( + "Integration | Component | Widget | topic-admin-menu-button", + function (hooks) { + setupRenderingTest(hooks); + + test("topic-admin-menu-button is present for admin/moderators", async function (assert) { + this.currentUser.setProperties({ + admin: true, + moderator: true, + id: 123, + }); + const topic = Topic.create({ user_id: this.currentUser.id }); + topic.set("category_id", Category.create({ read_restricted: true }).id); + this.siteSettings.allow_featured_topic_on_user_profiles = true; + this.set("args", createArgs(topic)); + + await render( + hbs`` + ); + + assert.ok(exists(".toggle-admin-menu"), "admin wrench is present"); + }); + + test("topic-admin-menu-button hides for non-admin when there is no action", async function (assert) { + this.currentUser.setProperties({ + admin: false, + moderator: false, + id: 123, + }); + const topic = Topic.create({ user_id: this.currentUser.id }); + topic.set("category_id", Category.create({ read_restricted: true }).id); + this.siteSettings.allow_featured_topic_on_user_profiles = true; + this.set("args", createArgs(topic)); + + await render( + hbs`` + ); + + assert.ok(!exists(".toggle-admin-menu"), "admin wrench is not present"); + }); + } +); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-participant-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-participant-test.js new file mode 100644 index 00000000000..418ed4379ef --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-participant-test.js @@ -0,0 +1,55 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { exists } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; + +module( + "Integration | Component | Widget | topic-participant", + function (hooks) { + setupRenderingTest(hooks); + + test("one post", async function (assert) { + this.set("args", { + username: "test", + avatar_template: "/images/avatar.png", + post_count: 1, + }); + + await render( + hbs`` + ); + + assert.ok(exists("a.poster.trigger-user-card")); + assert.ok(!exists("span.post-count"), "don't show count for only 1 post"); + assert.ok(!exists(".avatar-flair"), "no avatar flair"); + }); + + test("many posts, a primary group with flair", async function (assert) { + this.set("args", { + username: "test", + avatar_template: "/images/avatar.png", + post_count: 2, + primary_group_name: "devs", + flair_name: "devs", + flair_url: "/images/d-logo-sketch-small.png", + flair_bg_color: "222", + }); + + await render( + hbs`` + ); + + assert.ok(exists("a.poster.trigger-user-card")); + assert.ok(exists("span.post-count"), "show count for many posts"); + assert.ok( + exists(".group-devs a.poster"), + "add class for the group outside the link" + ); + assert.ok( + exists(".avatar-flair.avatar-flair-devs"), + "show flair with group class" + ); + }); + } +); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-status-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-status-test.js new file mode 100644 index 00000000000..808c5e14c8e --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-status-test.js @@ -0,0 +1,76 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { exists } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import TopicStatusIcons from "discourse/helpers/topic-status-icons"; +import createStore from "discourse/tests/helpers/create-store"; + +module("Integration | Component | Widget | topic-status", function (hooks) { + setupRenderingTest(hooks); + + test("basics", async function (assert) { + const store = createStore(); + this.set("args", { + topic: store.createRecord("topic", { closed: true }), + disableActions: true, + }); + + await render( + hbs`` + ); + + assert.ok(exists(".topic-status .d-icon-lock")); + }); + + test("extendability", async function (assert) { + const store = createStore(); + TopicStatusIcons.addObject([ + "has_accepted_answer", + "far-check-square", + "solved", + ]); + this.set("args", { + topic: store.createRecord("topic", { + has_accepted_answer: true, + }), + disableActions: true, + }); + + await render( + hbs`` + ); + + assert.ok(exists(".topic-status .d-icon-far-check-square")); + }); + + test("toggling pin status", async function (assert) { + const store = createStore(); + this.set("args", { + topic: store.createRecord("topic", { closed: true, pinned: true }), + }); + + await render( + hbs`` + ); + + assert.ok(exists(".topic-statuses .pinned"), "pinned icon is shown"); + assert.ok( + !exists(".topic-statuses .unpinned"), + "unpinned icon is not shown" + ); + + await click(".topic-statuses .pin-toggle-button"); + + assert.ok(!exists(".topic-statuses .pinned"), "pinned icon is not shown"); + assert.ok(exists(".topic-statuses .unpinned"), "unpinned icon is shown"); + + await click(".topic-statuses .pin-toggle-button"); + + assert.ok(exists(".topic-statuses .pinned"), "pinned icon is shown"); + assert.ok( + !exists(".topic-statuses .unpinned"), + "unpinned icon is not shown" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/user-menu-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/user-menu-test.js new file mode 100644 index 00000000000..580be04c358 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/user-menu-test.js @@ -0,0 +1,221 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { exists, query, queryAll } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import sinon from "sinon"; +import DiscourseURL from "discourse/lib/url"; +import I18n from "I18n"; + +module("Integration | Component | Widget | user-menu", function (hooks) { + setupRenderingTest(hooks); + + test("basics", async function (assert) { + await render(hbs``); + + assert.ok(exists(".user-menu")); + assert.ok(exists(".user-preferences-link")); + assert.ok(exists(".user-notifications-link")); + assert.ok(exists(".user-bookmarks-link")); + assert.ok(exists(".quick-access-panel")); + assert.ok(exists(".notifications-dismiss")); + }); + + test("notifications", async function (assert) { + await render(hbs``); + + const links = queryAll(".quick-access-panel li a"); + + assert.strictEqual(links.length, 6); + assert.ok(links[1].href.includes("/t/a-slug/123")); + + assert.ok( + links[2].href.includes( + "/u/eviltrout/notifications/likes-received?acting_username=aquaman" + ) + ); + + assert.strictEqual( + links[2].text, + `aquaman ${I18n.t("notifications.liked_consolidated_description", { + count: 5, + })}` + ); + + assert.ok(links[3].href.includes("/u/test2/messages/group/test")); + assert.ok( + links[3].innerHTML.includes( + I18n.t("notifications.group_message_summary", { + count: 5, + group_name: "test", + }) + ) + ); + + assert.ok(links[4].href.includes("/u/test1")); + assert.ok( + links[4].innerHTML.includes( + I18n.t("notifications.invitee_accepted", { username: "test1" }) + ) + ); + + assert.ok(links[5].href.includes("/g/test")); + assert.ok( + links[5].innerHTML.includes( + I18n.t("notifications.membership_request_accepted", { + group_name: "test", + }) + ) + ); + + const routeToStub = sinon.stub(DiscourseURL, "routeTo"); + await click(".user-notifications-link"); + assert.ok( + routeToStub.calledWith(query(".user-notifications-link").dataset.url), + "a second click should redirect to the full notifications page" + ); + }); + + test("log out", async function (assert) { + this.set("logout", () => (this.loggedOut = true)); + + await render( + hbs`` + ); + + await click(".user-preferences-link"); + + assert.ok(exists(".logout")); + + await click(".logout button"); + assert.ok(this.loggedOut); + }); + + test("private messages - disabled", async function (assert) { + this.siteSettings.enable_personal_messages = false; + + await render(hbs``); + + assert.ok(!exists(".user-pms-link")); + }); + + test("private messages - enabled", async function (assert) { + this.siteSettings.enable_personal_messages = true; + + await render(hbs``); + + const userPmsLink = query(".user-pms-link").dataset.url; + assert.ok(userPmsLink); + await click(".user-pms-link"); + + const message = query(".quick-access-panel li a"); + assert.ok(message); + + assert.ok( + message.href.includes("/t/bug-can-not-render-emoji-properly/174/2"), + "should link to the next unread post" + ); + assert.ok( + message.innerHTML.includes("mixtape"), + "should include the last poster's username" + ); + assert.ok( + message.innerHTML.match(//), + "should correctly render emoji in message title" + ); + + const routeToStub = sinon.stub(DiscourseURL, "routeTo"); + await click(".user-pms-link"); + assert.ok( + routeToStub.calledWith(userPmsLink), + "a second click should redirect to the full private messages page" + ); + }); + + test("bookmarks", async function (assert) { + await render(hbs``); + + await click(".user-bookmarks-link"); + + const allBookmarks = queryAll(".quick-access-panel li a"); + const bookmark = allBookmarks[0]; + + assert.ok( + bookmark.href.includes("/t/yelling-topic-title/119"), + "the Post bookmark should have a link to the topic" + ); + assert.ok( + bookmark.innerHTML.includes("someguy"), + "should include the last poster's username" + ); + assert.ok( + bookmark.innerHTML.match(//), + "should correctly render emoji in bookmark title" + ); + assert.ok( + bookmark.innerHTML.includes("d-icon-bookmark"), + "should use the correct icon based on no reminder_at present" + ); + + const routeToStub = sinon.stub(DiscourseURL, "routeTo"); + await click(".user-bookmarks-link"); + assert.ok( + routeToStub.calledWith(query(".user-bookmarks-link").dataset.url), + "a second click should redirect to the full bookmarks page" + ); + + const nonPostBookmarkableBookmark = allBookmarks[1]; + assert.ok( + nonPostBookmarkableBookmark.href.includes("chat/message/2437"), + "bookmarkable_type that is not Post or Topic should use bookmarkable_url for the item link" + ); + assert.ok( + nonPostBookmarkableBookmark.innerHTML.includes( + "d-icon-discourse-bookmark-clock" + ), + "should use the correct icon based on reminder_at present" + ); + }); + + test("anonymous", async function (assert) { + this.currentUser.setProperties({ is_anonymous: false, trust_level: 3 }); + this.siteSettings.allow_anonymous_posting = true; + this.siteSettings.anonymous_posting_min_trust_level = 3; + this.set("toggleAnonymous", () => (this.anonymous = true)); + + await render(hbs` + + `); + + await click(".user-preferences-link"); + assert.ok(exists(".enable-anonymous")); + + await click(".enable-anonymous"); + assert.ok(this.anonymous); + }); + + test("anonymous - disabled", async function (assert) { + this.siteSettings.allow_anonymous_posting = false; + + await render(hbs``); + + await click(".user-preferences-link"); + assert.ok(!exists(".enable-anonymous")); + }); + + test("anonymous - switch back", async function (assert) { + this.currentUser.setProperties({ is_anonymous: true }); + this.siteSettings.allow_anonymous_posting = true; + this.set("toggleAnonymous", () => (this.anonymous = false)); + + await render(hbs` + + `); + + await click(".user-preferences-link"); + assert.ok(exists(".disable-anonymous")); + + await click(".disable-anonymous"); + assert.notOk(this.anonymous); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/widget-dropdown-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/widget-dropdown-test.js new file mode 100644 index 00000000000..63a828c4a0b --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/widget-dropdown-test.js @@ -0,0 +1,280 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { exists, query } from "discourse/tests/helpers/qunit-helpers"; +import I18n from "I18n"; +import hbs from "htmlbars-inline-precompile"; + +const DEFAULT_CONTENT = { + content: [ + { id: 1, label: "foo" }, + { id: 2, translatedLabel: "FooBar" }, + "separator", + { id: 3, translatedLabel: "With icon", icon: "times" }, + { id: 4, html: "baz" }, + { id: 5, translatedLabel: "Disabled", disabled: true }, + ], + label: "foo", +}; + +async function clickRowById(id) { + await click(`#my-dropdown .widget-dropdown-item.item-${id}`); +} + +function rowById(id) { + return query(`#my-dropdown .widget-dropdown-item.item-${id}`); +} + +async function toggle() { + await click("#my-dropdown .widget-dropdown-header"); +} + +function headerLabel() { + return query("#my-dropdown .widget-dropdown-header .label").innerText.trim(); +} + +function header() { + return query("#my-dropdown .widget-dropdown-header"); +} + +function body() { + return query("#my-dropdown .widget-dropdown-body"); +} + +const TEMPLATE = hbs` + +`; + +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(TEMPLATE); + + assert.ok(exists("#my-dropdown")); + }); + + test("label", async function (assert) { + I18n.translations = { en: { js: { foo: "FooBaz" } } }; + this.setProperties(DEFAULT_CONTENT); + + await render(TEMPLATE); + + assert.strictEqual(headerLabel(), "FooBaz"); + }); + + test("translatedLabel", async function (assert) { + I18n.translations = { en: { js: { foo: "FooBaz" } } }; + this.setProperties(DEFAULT_CONTENT); + this.set("translatedLabel", "BazFoo"); + + await render(TEMPLATE); + + assert.strictEqual(headerLabel(), this.translatedLabel); + }); + + test("content", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + + await render(TEMPLATE); + + await toggle(); + assert.strictEqual(rowById(1).dataset.id, "1", "it creates rows"); + assert.strictEqual(rowById(2).dataset.id, "2", "it creates rows"); + assert.strictEqual(rowById(3).dataset.id, "3", "it creates rows"); + }); + + test("onChange action", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + this.set("onChange", (item) => (query("#test").innerText = item.id)); + + await render(hbs` +
+ + + `); + + await toggle(); + await clickRowById(2); + assert.strictEqual( + query("#test").innerText, + "2", + "it calls the onChange actions" + ); + }); + + test("can be opened and closed", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + + await render(TEMPLATE); + + assert.ok(exists("#my-dropdown.closed")); + assert.ok(!exists("#my-dropdown .widget-dropdown-body")); + await toggle(); + assert.strictEqual(rowById(2).innerText.trim(), "FooBar"); + assert.ok(exists("#my-dropdown.opened")); + assert.ok(exists("#my-dropdown .widget-dropdown-body")); + await toggle(); + assert.ok(exists("#my-dropdown.closed")); + assert.ok(!exists("#my-dropdown .widget-dropdown-body")); + }); + + test("icon", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + this.set("icon", "times"); + + await render(TEMPLATE); + + assert.ok(exists(header().querySelector(".d-icon-times"))); + }); + + test("class", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + this.set("class", "activated"); + + await render(TEMPLATE); + + assert.ok(exists("#my-dropdown.activated")); + }); + + test("content with translatedLabel", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + + await render(TEMPLATE); + + await toggle(); + assert.strictEqual(rowById(2).innerText.trim(), "FooBar"); + }); + + test("content with label", async function (assert) { + I18n.translations = { en: { js: { foo: "FooBaz" } } }; + this.setProperties(DEFAULT_CONTENT); + + await render(TEMPLATE); + + await toggle(); + assert.strictEqual(rowById(1).innerText.trim(), "FooBaz"); + }); + + test("content with icon", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + + await render(TEMPLATE); + + await toggle(); + assert.ok(exists(rowById(3).querySelector(".d-icon-times"))); + }); + + test("content with html", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + + await render(TEMPLATE); + + await toggle(); + assert.strictEqual(rowById(4).innerHTML.trim(), "baz"); + }); + + test("separator", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + + await render(TEMPLATE); + + await toggle(); + assert.ok( + query( + "#my-dropdown .widget-dropdown-item:nth-child(3)" + ).classList.contains("separator") + ); + }); + + test("hides widget if no content", async function (assert) { + this.setProperties({ content: null, label: "foo" }); + + await render(TEMPLATE); + + assert.notOk(exists("#my-dropdown .widget-dropdown-header")); + assert.notOk(exists("#my-dropdown .widget-dropdown-body")); + }); + + test("headerClass option", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + this.set("options", { headerClass: "btn-small and-text" }); + + await render(TEMPLATE); + + assert.ok(header().classList.contains("widget-dropdown-header")); + assert.ok(header().classList.contains("btn-small")); + assert.ok(header().classList.contains("and-text")); + }); + + test("bodyClass option", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + this.set("options", { bodyClass: "gigantic and-yet-small" }); + + await render(TEMPLATE); + + await toggle(); + assert.ok(body().classList.contains("widget-dropdown-body")); + assert.ok(body().classList.contains("gigantic")); + assert.ok(body().classList.contains("and-yet-small")); + }); + + test("caret option", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + this.set("options", { caret: true }); + + await render(TEMPLATE); + + assert.ok( + exists("#my-dropdown .widget-dropdown-header .d-icon-caret-down") + ); + }); + + test("disabled widget", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + this.set("options", { disabled: true }); + + await render(TEMPLATE); + + assert.ok(exists("#my-dropdown.disabled")); + + await toggle(); + assert.strictEqual(rowById(1), null, "it does not display options"); + }); + + test("disabled item", async function (assert) { + this.setProperties(DEFAULT_CONTENT); + + await render(TEMPLATE); + + await toggle(); + assert.ok(exists(".widget-dropdown-item.item-5.disabled")); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/widget-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/widget-test.js new file mode 100644 index 00000000000..e68baf73d70 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/widget-test.js @@ -0,0 +1,397 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { count, exists, query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import widgetHbs from "discourse/widgets/hbs-compiler"; +import I18n from "I18n"; +import { Promise } from "rsvp"; +import { createWidget } from "discourse/widgets/widget"; +import { next } from "@ember/runloop"; +import { withPluginApi } from "discourse/lib/plugin-api"; + +module("Integration | Component | Widget | base", function (hooks) { + setupRenderingTest(hooks); + + let _translations = I18n.translations; + + hooks.afterEach(function () { + I18n.translations = _translations; + }); + + test("widget attributes are passed in via args", async function (assert) { + createWidget("hello-test", { + tagName: "div.test", + template: widgetHbs`Hello {{attrs.name}}`, + }); + + this.set("args", { name: "Robin" }); + + await render(hbs``); + + assert.strictEqual(query(".test").innerText, "Hello Robin"); + }); + + test("widget services", async function (assert) { + createWidget("service-test", { + tagName: "div.base-url-test", + services: ["router"], + html() { + return this.router.rootURL; + }, + }); + + await render(hbs``); + + assert.strictEqual(query(".base-url-test").innerText, "/"); + }); + + test("hbs template - no tagName", async function (assert) { + createWidget("hbs-test", { + template: widgetHbs`
Hello {{attrs.name}}
`, + }); + + this.set("args", { name: "Robin" }); + + await render(hbs``); + + assert.strictEqual(query("div.test").innerText, "Hello Robin"); + }); + + test("hbs template - with tagName", async function (assert) { + createWidget("hbs-test", { + tagName: "div.test", + template: widgetHbs`Hello {{attrs.name}}`, + }); + + this.set("args", { name: "Robin" }); + + await render(hbs``); + + assert.strictEqual(query("div.test").innerText, "Hello Robin"); + }); + + test("hbs template - with data attributes", async function (assert) { + createWidget("hbs-test", { + template: widgetHbs`
`, + }); + + await render(hbs``); + + assert.strictEqual(query("div.my-div").dataset.myTest, "hello world"); + }); + + test("buildClasses", async function (assert) { + createWidget("classname-test", { + tagName: "div.test", + + buildClasses(attrs) { + return ["static", attrs.dynamic]; + }, + }); + + this.set("args", { dynamic: "cool-class" }); + + await render( + hbs`` + ); + + assert.ok(exists(".test.static.cool-class"), "it has all the classes"); + }); + + test("buildAttributes", async function (assert) { + createWidget("attributes-test", { + tagName: "div.test", + + buildAttributes(attrs) { + return { "data-evil": "trout", "aria-label": attrs.label }; + }, + }); + + this.set("args", { label: "accessibility" }); + + await render( + hbs`` + ); + + assert.ok(exists('.test[data-evil="trout"]')); + assert.ok(exists('.test[aria-label="accessibility"]')); + }); + + test("buildId", async function (assert) { + createWidget("id-test", { + buildId(attrs) { + return `test-${attrs.id}`; + }, + }); + + this.set("args", { id: 1234 }); + + await render(hbs``); + + assert.ok(exists("#test-1234")); + }); + + test("widget state", async function (assert) { + createWidget("state-test", { + tagName: "button.test", + buildKey: () => `button-test`, + template: widgetHbs`{{state.clicks}} clicks`, + + defaultState() { + return { clicks: 0 }; + }, + + click() { + this.state.clicks++; + }, + }); + + await render(hbs``); + + assert.ok(exists("button.test"), "it renders the button"); + assert.strictEqual(query("button.test").innerText, "0 clicks"); + + await click(query("button")); + assert.strictEqual(query("button.test").innerText, "1 clicks"); + }); + + test("widget update with promise", async function (assert) { + createWidget("promise-test", { + tagName: "button.test", + buildKey: () => "promise-test", + template: widgetHbs` + {{#if state.name}} + {{state.name}} + {{else}} + No name + {{/if}} + `, + + click() { + return new Promise((resolve) => { + next(() => { + this.state.name = "Robin"; + resolve(); + }); + }); + }, + }); + + await render(hbs``); + + assert.strictEqual(query("button.test").innerText.trim(), "No name"); + + await click(query("button")); + assert.strictEqual(query("button.test").innerText.trim(), "Robin"); + }); + + test("widget attaching", async function (assert) { + createWidget("test-embedded", { tagName: "div.embedded" }); + + createWidget("attach-test", { + tagName: "div.container", + template: widgetHbs`{{attach widget="test-embedded" attrs=attrs}}`, + }); + + await render(hbs``); + + assert.ok(exists(".container"), "renders container"); + assert.ok(exists(".container .embedded"), "renders attached"); + }); + + test("magic attaching by name", async function (assert) { + createWidget("test-embedded", { tagName: "div.embedded" }); + + createWidget("attach-test", { + tagName: "div.container", + template: widgetHbs`{{test-embedded attrs=attrs}}`, + }); + + await render(hbs``); + + assert.ok(exists(".container"), "renders container"); + assert.ok(exists(".container .embedded"), "renders attached"); + }); + + test("custom attrs to a magic attached widget", async function (assert) { + createWidget("testing", { + tagName: "span.value", + template: widgetHbs`{{attrs.value}}`, + }); + + createWidget("attach-test", { + tagName: "div.container", + template: widgetHbs`{{testing value=(concat "hello" " " "world")}}`, + }); + + await render(hbs``); + + assert.ok(exists(".container"), "renders container"); + assert.strictEqual(query(".container .value").innerText, "hello world"); + }); + + test("using transformed values in a sub-expression", async function (assert) { + createWidget("testing", { + tagName: "span.value", + template: widgetHbs`{{attrs.value}}`, + }); + + createWidget("attach-test", { + transform() { + return { someValue: "world" }; + }, + tagName: "div.container", + template: widgetHbs`{{testing value=(concat "hello" " " transformed.someValue)}}`, + }); + + await render(hbs``); + + assert.ok(count(".container"), "renders container"); + assert.strictEqual(query(".container .value").innerText, "hello world"); + }); + + test("handlebars d-icon", async function (assert) { + createWidget("hbs-icon-test", { + template: widgetHbs`{{d-icon "arrow-down"}}`, + }); + + await render( + hbs`` + ); + + assert.strictEqual(count(".d-icon-arrow-down"), 1); + }); + + test("handlebars i18n", async function (assert) { + createWidget("hbs-i18n-test", { + template: widgetHbs` + {{i18n "hbs_test0"}} + {{i18n attrs.key}} + test + `, + }); + I18n.translations = { + en: { + js: { + hbs_test0: "evil", + hbs_test1: "trout", + }, + }, + }; + this.set("args", { key: "hbs_test1" }); + + await render( + hbs`` + ); + + // coming up + assert.strictEqual(query("span.string").innerText, "evil"); + assert.strictEqual(query("span.var").innerText, "trout"); + assert.strictEqual(query("a").title, "evil"); + }); + + test("handlebars #each", async function (assert) { + createWidget("hbs-each-test", { + tagName: "ul", + template: widgetHbs` + {{#each attrs.items as |item|}} +
  • {{item}}
  • + {{/each}} + `, + }); + + this.set("args", { + items: ["one", "two", "three"], + }); + + await render( + hbs`` + ); + + assert.strictEqual(count("ul li"), 3); + assert.strictEqual(query("ul li:nth-of-type(1)").innerText, "one"); + }); + + test("widget decorating", async function (assert) { + createWidget("decorate-test", { + tagName: "div.decorate", + template: widgetHbs`main content`, + }); + + withPluginApi("0.1", (api) => { + api.decorateWidget("decorate-test:before", (dec) => { + return dec.h("b", "before"); + }); + + api.decorateWidget("decorate-test:after", (dec) => { + return dec.h("i", "after"); + }); + }); + + await render(hbs``); + + assert.ok(exists(".decorate")); + assert.strictEqual(query(".decorate b").innerText, "before"); + assert.strictEqual(query(".decorate i").innerText, "after"); + }); + + test("widget settings", async function (assert) { + createWidget("settings-test", { + tagName: "div.settings", + template: widgetHbs`age is {{settings.age}}`, + settings: { age: 36 }, + }); + + await render(hbs``); + + assert.strictEqual(query(".settings").innerText, "age is 36"); + }); + + test("override settings", async function (assert) { + createWidget("ov-settings-test", { + tagName: "div.settings", + template: widgetHbs`age is {{settings.age}}`, + settings: { age: 36 }, + }); + + withPluginApi("0.1", (api) => { + api.changeWidgetSetting("ov-settings-test", "age", 37); + }); + + await render(hbs``); + + assert.strictEqual(query(".settings").innerText, "age is 37"); + }); + + test("get accessor", async function (assert) { + createWidget("get-accessor-test", { + tagName: "div.test", + template: widgetHbs`Hello {{transformed.name}}`, + transform() { + return { + name: this.get("currentUser.username"), + }; + }, + }); + + await render(hbs``); + + assert.strictEqual(query("div.test").innerText, "Hello eviltrout"); + }); + + test("tagName", async function (assert) { + createWidget("test-override", { tagName: "div.not-override" }); + + createWidget("tag-name-override-test", { + template: widgetHbs`{{attach widget="test-override" attrs=attrs otherOpts=(hash tagName="section.override")}}`, + }); + + await render(hbs``); + + assert.ok( + exists("section.override"), + "renders container with overridden tagName" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/components/wizard-invite-list-test.js b/app/assets/javascripts/discourse/tests/integration/components/wizard-invite-list-test.js index 39f54e07a63..ae2d7da5d3c 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/wizard-invite-list-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/wizard-invite-list-test.js @@ -1,100 +1,73 @@ -import { - count, - discourseModule, - exists, -} from "discourse/tests/helpers/qunit-helpers"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { click, fillIn } from "@ember/test-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, fillIn, render } from "@ember/test-helpers"; +import { count, exists } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule( - "Integration | Component | Wizard | invite-list", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | Wizard | invite-list", function (hooks) { + setupRenderingTest(hooks); - componentTest("can add users", { - template: hbs`{{invite-list field=field}}`, + test("can add users", async function (assert) { + this.set("field", {}); - beforeEach() { - this.set("field", {}); - }, + await render(hbs``); - async test(assert) { - assert.ok( - !exists(".users-list .invite-list-user"), - "no users at first" - ); - assert.ok(!exists(".new-user .invalid"), "not invalid at first"); + assert.ok(!exists(".users-list .invite-list-user"), "no users at first"); + assert.ok(!exists(".new-user .invalid"), "not invalid at first"); - const firstVal = JSON.parse(this.field.value); - assert.strictEqual(firstVal.length, 0, "empty JSON at first"); + const firstVal = JSON.parse(this.field.value); + assert.strictEqual(firstVal.length, 0, "empty JSON at first"); - assert.ok( - this.field.warning, - "it has a warning since no users were added" - ); + assert.ok(this.field.warning, "it has a warning since no users were added"); - await click(".add-user"); - assert.ok( - !exists(".users-list .invite-list-user"), - "doesn't add a blank user" - ); - assert.strictEqual(count(".new-user .invalid"), 1); + await click(".add-user"); + assert.ok( + !exists(".users-list .invite-list-user"), + "doesn't add a blank user" + ); + assert.strictEqual(count(".new-user .invalid"), 1); - await fillIn(".invite-email", "eviltrout@example.com"); - await click(".add-user"); + await fillIn(".invite-email", "eviltrout@example.com"); + await click(".add-user"); - assert.strictEqual( - count(".users-list .invite-list-user"), - 1, - "adds the user" - ); - assert.ok(!exists(".new-user .invalid")); + assert.strictEqual( + count(".users-list .invite-list-user"), + 1, + "adds the user" + ); + assert.ok(!exists(".new-user .invalid")); - const val = JSON.parse(this.field.value); - assert.strictEqual(val.length, 1); - assert.strictEqual( - val[0].email, - "eviltrout@example.com", - "adds the email to the JSON" - ); - assert.ok(val[0].role.length, "adds the role to the JSON"); - assert.ok( - !this.get("field.warning"), - "no warning once the user is added" - ); + const val = JSON.parse(this.field.value); + assert.strictEqual(val.length, 1); + assert.strictEqual( + val[0].email, + "eviltrout@example.com", + "adds the email to the JSON" + ); + assert.ok(val[0].role.length, "adds the role to the JSON"); + assert.ok(!this.get("field.warning"), "no warning once the user is added"); - await fillIn(".invite-email", "eviltrout@example.com"); - await click(".add-user"); + await fillIn(".invite-email", "eviltrout@example.com"); + await click(".add-user"); - assert.strictEqual( - count(".users-list .invite-list-user"), - 1, - "can't add the same user twice" - ); - assert.strictEqual(count(".new-user .invalid"), 1); + assert.strictEqual( + count(".users-list .invite-list-user"), + 1, + "can't add the same user twice" + ); + assert.strictEqual(count(".new-user .invalid"), 1); - await fillIn(".invite-email", "not-an-email"); - await click(".add-user"); + await fillIn(".invite-email", "not-an-email"); + await click(".add-user"); - assert.strictEqual( - count(".users-list .invite-list-user"), - 1, - "won't add an invalid email" - ); - assert.strictEqual(count(".new-user .invalid"), 1); + assert.strictEqual( + count(".users-list .invite-list-user"), + 1, + "won't add an invalid email" + ); + assert.strictEqual(count(".new-user .invalid"), 1); - await click( - ".invite-list .invite-list-user:nth-of-type(1) .remove-user" - ); - assert.ok( - !exists(".users-list .invite-list-user"), - 0, - "removed the user" - ); - }, - }); - } -); + await click(".invite-list .invite-list-user:nth-of-type(1) .remove-user"); + assert.ok(!exists(".users-list .invite-list-user"), 0, "removed the user"); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/actions-summary-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/actions-summary-test.js deleted file mode 100644 index f99a79b6697..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/actions-summary-test.js +++ /dev/null @@ -1,35 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { count, discourseModule } from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule( - "Integration | Component | Widget | actions-summary", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("post deleted", { - template: hbs`{{mount-widget widget="actions-summary" args=args}}`, - beforeEach() { - this.set("args", { - deleted_at: "2016-01-01", - deletedByUsername: "eviltrout", - deletedByAvatarTemplate: "/images/avatar.png", - }); - }, - test(assert) { - assert.strictEqual( - count(".post-action .d-icon-far-trash-alt"), - 1, - "it has the deleted icon" - ); - assert.strictEqual( - count(".avatar[title=eviltrout]"), - 1, - "it has the deleted by avatar" - ); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/avatar-flair-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/avatar-flair-test.js deleted file mode 100644 index 49a43589a71..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/avatar-flair-test.js +++ /dev/null @@ -1,49 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule( - "Integration | Component | Widget | avatar-flair", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("avatar flair with an icon", { - template: hbs`{{mount-widget widget="avatar-flair" args=args}}`, - beforeEach() { - this.set("args", { - flair_url: "fa-bars", - flair_bg_color: "CC0000", - flair_color: "FFFFFF", - }); - }, - test(assert) { - assert.ok(exists(".avatar-flair"), "it has the tag"); - assert.ok(exists("svg.d-icon-bars"), "it has the svg icon"); - assert.strictEqual( - queryAll(".avatar-flair").attr("style"), - "background-color: #CC0000; color: #FFFFFF; ", - "it has styles" - ); - }, - }); - - componentTest("avatar flair with an image", { - template: hbs`{{mount-widget widget="avatar-flair" args=args}}`, - beforeEach() { - this.set("args", { - flair_url: "/images/avatar.png", - }); - }, - test(assert) { - assert.ok(exists(".avatar-flair"), "it has the tag"); - assert.ok(!exists("svg"), "it does not have an svg icon"); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/button-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/button-test.js deleted file mode 100644 index af5a242b776..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/button-test.js +++ /dev/null @@ -1,97 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule("Integration | Component | Widget | button", function (hooks) { - setupRenderingTest(hooks); - - componentTest("icon only button", { - template: hbs`{{mount-widget widget="button" args=args}}`, - - beforeEach() { - this.set("args", { icon: "far-smile" }); - }, - - test(assert) { - assert.ok( - exists("button.btn.btn-icon.no-text"), - "it has all the classes" - ); - assert.ok(exists("button .d-icon.d-icon-far-smile"), "it has the icon"); - }, - }); - - componentTest("icon and text button", { - template: hbs`{{mount-widget widget="button" args=args}}`, - - beforeEach() { - this.set("args", { icon: "plus", label: "topic.create" }); - }, - - test(assert) { - 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"); - }, - }); - - componentTest("emoji and text button", { - template: hbs`{{mount-widget widget="button" args=args}}`, - - beforeEach() { - this.set("args", { emoji: "mega", label: "topic.create" }); - }, - - test(assert) { - assert.ok(exists("button.widget-button"), "renders the widget"); - assert.ok(exists("button img.emoji"), "it renders the emoji"); - assert.ok(exists("button span.d-button-label"), "it renders the label"); - }, - }); - - componentTest("text only button", { - template: hbs`{{mount-widget widget="button" args=args}}`, - - beforeEach() { - this.set("args", { label: "topic.create" }); - }, - - test(assert) { - assert.ok(exists("button.btn.btn-text"), "it has all the classes"); - assert.ok(exists("button span.d-button-label"), "it has the label"); - }, - }); - - componentTest("translatedLabel", { - template: hbs`{{mount-widget widget="button" args=args}}`, - - beforeEach() { - this.set("args", { translatedLabel: "foo bar" }); - }, - - test(assert) { - assert.strictEqual( - query("button span.d-button-label").innerText, - "foo bar" - ); - }, - }); - - componentTest("translatedTitle", { - template: hbs`{{mount-widget widget="button" args=args}}`, - - beforeEach() { - this.set("args", { label: "topic.create", translatedTitle: "foo bar" }); - }, - - test(assert) { - assert.strictEqual(query("button").title, "foo bar"); - }, - }); -}); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/default-notification-item-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/default-notification-item-test.js deleted file mode 100644 index b21b598345b..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/default-notification-item-test.js +++ /dev/null @@ -1,80 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; -import EmberObject from "@ember/object"; -import hbs from "htmlbars-inline-precompile"; -import pretender from "discourse/tests/helpers/create-pretender"; -import { settled } from "@ember/test-helpers"; - -discourseModule( - "Integration | Component | Widget | default-notification-item", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("sets notification as read on middle click", { - template: hbs`{{mount-widget widget="default-notification-item" args=args}}`, - beforeEach() { - this.set( - "args", - EmberObject.create({ - id: 3, - user_id: 1, - notification_type: 6, - read: false, - created_at: "2020-01-01T12:00:00.000Z", - post_number: 1, - topic_id: 10, - fancy_title: "Greetings!", - slug: "greetings", - data: { - topic_title: "Greetings!", - original_post_id: 14, - original_post_type: 1, - original_username: "discobot", - revision_number: null, - display_username: "discobot", - }, - }) - ); - }, - async test(assert) { - let requests = 0; - pretender.put("/notifications/mark-read", (request) => { - ++requests; - - assert.strictEqual( - request.requestBody, - `id=${this.args.id}`, - "it sets correct request parameters" - ); - - return [ - 200, - { "Content-Type": "application/json" }, - { success: true }, - ]; - }); - - assert.ok(!exists("li.read")); - - $(document).trigger( - $.Event("mouseup", { - target: query("li"), - button: 1, - which: 2, - }) - ); - await settled(); - - assert.strictEqual(count("li.read"), 1); - assert.strictEqual(requests, 1); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/hamburger-menu-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/hamburger-menu-test.js deleted file mode 100644 index 949a2c4f6d9..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/hamburger-menu-test.js +++ /dev/null @@ -1,274 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import { NotificationLevels } from "discourse/lib/notification-levels"; -import hbs from "htmlbars-inline-precompile"; - -const topCategoryIds = [2, 3, 1]; -let mutedCategoryIds = []; -let unreadCategoryIds = []; -let categoriesByCount = []; - -discourseModule( - "Integration | Component | Widget | hamburger-menu", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("prioritize faq", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - - beforeEach() { - this.siteSettings.faq_url = "http://example.com/faq"; - this.currentUser.set("read_faq", false); - }, - - test(assert) { - assert.ok(exists(".faq-priority")); - assert.ok(!exists(".faq-link")); - }, - }); - - componentTest("prioritize faq - user has read", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - - beforeEach() { - this.siteSettings.faq_url = "http://example.com/faq"; - this.currentUser.set("read_faq", true); - }, - - test(assert) { - assert.ok(!exists(".faq-priority")); - assert.ok(exists(".faq-link")); - }, - }); - - componentTest("staff menu - not staff", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - - beforeEach() { - this.currentUser.set("staff", false); - }, - - test(assert) { - assert.ok(!exists(".admin-link")); - }, - }); - - componentTest("staff menu - moderator", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - - beforeEach() { - this.currentUser.set("moderator", true); - this.currentUser.set("can_review", true); - }, - - test(assert) { - assert.ok(exists(".admin-link")); - assert.ok(exists(".review")); - assert.ok(!exists(".settings-link")); - }, - }); - - componentTest("staff menu - admin", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - - beforeEach() { - this.currentUser.setProperties({ admin: true }); - }, - - test(assert) { - assert.ok(exists(".settings-link")); - }, - }); - - componentTest("logged in links", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - - test(assert) { - assert.ok(exists(".new-topics-link")); - assert.ok(exists(".unread-topics-link")); - }, - }); - - componentTest("general links", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - anonymous: true, - - test(assert) { - assert.ok(!exists("li[class='']")); - assert.ok(exists(".latest-topics-link")); - assert.ok(!exists(".new-topics-link")); - assert.ok(!exists(".unread-topics-link")); - assert.ok(exists(".top-topics-link")); - assert.ok(exists(".badge-link")); - assert.ok(exists(".category-link")); - assert.ok(exists(".about-link")); - assert.ok(exists(".keyboard-shortcuts-link")); - }, - }); - - let maxCategoriesToDisplay; - - componentTest("top categories - anonymous", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - anonymous: true, - - beforeEach() { - this.siteSettings.header_dropdown_category_count = 8; - }, - - test(assert) { - assert.strictEqual(count(".category-link"), 8); - assert.strictEqual( - queryAll(".category-link .category-name").text(), - this.site - .get("categoriesByCount") - .slice(0, 8) - .map((c) => c.name) - .join("") - ); - }, - }); - - componentTest("top categories - allow_uncategorized_topics", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - anonymous: true, - - beforeEach() { - this.siteSettings.allow_uncategorized_topics = false; - this.siteSettings.header_dropdown_category_count = 8; - }, - - test(assert) { - assert.strictEqual(count(".category-link"), 8); - assert.strictEqual( - queryAll(".category-link .category-name").text(), - this.site - .get("categoriesByCount") - .filter((c) => c.name !== "uncategorized") - .slice(0, 8) - .map((c) => c.name) - .join("") - ); - }, - }); - - componentTest("top categories", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - - beforeEach() { - this.siteSettings.header_dropdown_category_count = 8; - maxCategoriesToDisplay = - this.siteSettings.header_dropdown_category_count; - categoriesByCount = this.site.get("categoriesByCount").slice(); - categoriesByCount.every((c) => { - if (!topCategoryIds.includes(c.id)) { - if (mutedCategoryIds.length === 0) { - mutedCategoryIds.push(c.id); - c.set("notification_level", NotificationLevels.MUTED); - } else if (unreadCategoryIds.length === 0) { - unreadCategoryIds.push(c.id); - for (let i = 0; i < 5; i++) { - c.topicTrackingState.modifyState(123 + i, { - category_id: c.id, - last_read_post_number: 1, - highest_post_number: 2, - notification_level: NotificationLevels.TRACKING, - unread_not_too_old: true, - }); - } - } else { - unreadCategoryIds.splice(0, 0, c.id); - for (let i = 0; i < 10; i++) { - c.topicTrackingState.modifyState(321 + i, { - category_id: c.id, - last_read_post_number: null, - created_in_new_period: true, - }); - } - return false; - } - } - return true; - }); - this.currentUser.set("top_category_ids", topCategoryIds); - }, - - test(assert) { - assert.strictEqual( - count(".category-link"), - maxCategoriesToDisplay, - "categories displayed limited by header_dropdown_category_count" - ); - - categoriesByCount = categoriesByCount.filter( - (c) => !mutedCategoryIds.includes(c.id) - ); - let ids = [ - ...unreadCategoryIds, - ...topCategoryIds, - ...categoriesByCount.map((c) => c.id), - ] - .uniq() - .slice(0, maxCategoriesToDisplay); - - assert.strictEqual( - queryAll(".category-link .category-name").text(), - ids - .map( - (id) => - categoriesByCount.find((category) => category.id === id).name - ) - .join(""), - "top categories are in the correct order" - ); - }, - }); - - componentTest("badges link - disabled", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - - beforeEach() { - this.siteSettings.enable_badges = false; - }, - - test(assert) { - assert.ok(!exists(".badge-link")); - }, - }); - - componentTest("badges link", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - - test(assert) { - assert.ok(exists(".badge-link")); - }, - }); - - componentTest("user directory link", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - - test(assert) { - assert.ok(exists(".user-directory-link")); - }, - }); - - componentTest("user directory link - disabled", { - template: hbs`{{mount-widget widget="hamburger-menu"}}`, - - beforeEach() { - this.siteSettings.enable_user_directory = false; - }, - - test(assert) { - assert.ok(!exists(".user-directory-link")); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/header-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/header-test.js deleted file mode 100644 index 433ace45ca5..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/header-test.js +++ /dev/null @@ -1,99 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, exists } from "discourse/tests/helpers/qunit-helpers"; -import { click } from "@ember/test-helpers"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule("Integration | Component | Widget | header", function (hooks) { - setupRenderingTest(hooks); - - componentTest("rendering basics", { - template: hbs`{{mount-widget widget="header"}}`, - test(assert) { - assert.ok(exists("header.d-header")); - assert.ok(exists("#site-logo")); - }, - }); - - componentTest("sign up / login buttons", { - template: hbs` - {{mount-widget - widget="header" - showCreateAccount=showCreateAccount - showLogin=showLogin - args=args - }} - `, - anonymous: true, - - beforeEach() { - this.set("args", { canSignUp: true }); - this.set("showCreateAccount", () => (this.signupShown = true)); - this.set("showLogin", () => (this.loginShown = true)); - }, - - async test(assert) { - assert.ok(exists("button.sign-up-button")); - assert.ok(exists("button.login-button")); - - await click("button.sign-up-button"); - assert.ok(this.signupShown); - - await click("button.login-button"); - assert.ok(this.loginShown); - }, - }); - - componentTest("anon when login required", { - template: hbs` - {{mount-widget - widget="header" - showCreateAccount=showCreateAccount - showLogin=showLogin - args=args - }} - `, - anonymous: true, - - beforeEach() { - this.set("args", { canSignUp: true }); - this.set("showCreateAccount", () => (this.signupShown = true)); - this.set("showLogin", () => (this.loginShown = true)); - this.siteSettings.login_required = true; - }, - - test(assert) { - assert.ok(exists("button.login-button")); - assert.ok(exists("button.sign-up-button")); - assert.ok(!exists("#search-button")); - assert.ok(!exists("#toggle-hamburger-menu")); - }, - }); - - componentTest("logged in when login required", { - template: hbs` - {{mount-widget - widget="header" - showCreateAccount=showCreateAccount - showLogin=showLogin - args=args - }} - `, - - beforeEach() { - this.set("args", { canSignUp: true }); - this.set("showCreateAccount", () => (this.signupShown = true)); - this.set("showLogin", () => (this.loginShown = true)); - this.siteSettings.login_required = true; - }, - - test(assert) { - assert.ok(!exists("button.login-button")); - assert.ok(!exists("button.sign-up-button")); - assert.ok(exists("#search-button")); - assert.ok(exists("#toggle-hamburger-menu")); - assert.ok(exists("#current-user")); - }, - }); -}); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/home-logo-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/home-logo-test.js deleted file mode 100644 index 9582b3a590f..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/home-logo-test.js +++ /dev/null @@ -1,247 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import Session from "discourse/models/session"; -import hbs from "htmlbars-inline-precompile"; - -const bigLogo = "/images/d-logo-sketch.png?test"; -const smallLogo = "/images/d-logo-sketch-small.png?test"; -const mobileLogo = "/images/d-logo-sketch.png?mobile"; -const darkLogo = "/images/d-logo-sketch.png?dark"; -const title = "Cool Forum"; -const prefersDark = "(prefers-color-scheme: dark)"; - -discourseModule( - "Integration | Component | Widget | home-logo", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("basics", { - template: hbs`{{mount-widget widget="home-logo" args=args}}`, - beforeEach() { - this.siteSettings.site_logo_url = bigLogo; - this.siteSettings.site_logo_small_url = smallLogo; - this.siteSettings.title = title; - this.set("args", { minimized: false }); - }, - - test(assert) { - assert.strictEqual(count(".title"), 1); - - assert.strictEqual(count("img#site-logo.logo-big"), 1); - assert.strictEqual(queryAll("#site-logo").attr("src"), bigLogo); - assert.strictEqual(queryAll("#site-logo").attr("alt"), title); - }, - }); - - componentTest("basics - minimized", { - template: hbs`{{mount-widget widget="home-logo" args=args}}`, - beforeEach() { - this.siteSettings.site_logo_url = bigLogo; - this.siteSettings.site_logo_small_url = smallLogo; - this.siteSettings.title = title; - this.set("args", { minimized: true }); - }, - - test(assert) { - assert.strictEqual(count("img.logo-small"), 1); - assert.strictEqual(queryAll("img.logo-small").attr("src"), smallLogo); - assert.strictEqual(queryAll("img.logo-small").attr("alt"), title); - assert.strictEqual(queryAll("img.logo-small").attr("width"), "36"); - }, - }); - - componentTest("no logo", { - template: hbs`{{mount-widget widget="home-logo" args=args}}`, - beforeEach() { - this.siteSettings.site_logo_url = ""; - this.siteSettings.site_logo_small_url = ""; - this.siteSettings.title = title; - this.set("args", { minimized: false }); - }, - - test(assert) { - assert.strictEqual(count("h1#site-text-logo.text-logo"), 1); - assert.strictEqual(queryAll("#site-text-logo").text(), title); - }, - }); - - componentTest("no logo - minimized", { - template: hbs`{{mount-widget widget="home-logo" args=args}}`, - beforeEach() { - this.siteSettings.site_logo_url = ""; - this.siteSettings.site_logo_small_url = ""; - this.siteSettings.title = title; - this.set("args", { minimized: true }); - }, - - test(assert) { - assert.strictEqual(count(".d-icon-home"), 1); - }, - }); - - componentTest("mobile logo", { - template: hbs`{{mount-widget widget="home-logo" args=args}}`, - beforeEach() { - this.siteSettings.site_mobile_logo_url = mobileLogo; - this.siteSettings.site_logo_small_url = smallLogo; - this.site.mobileView = true; - }, - - test(assert) { - assert.strictEqual(count("img#site-logo.logo-mobile"), 1); - assert.strictEqual(queryAll("#site-logo").attr("src"), mobileLogo); - }, - }); - - componentTest("mobile without logo", { - template: hbs`{{mount-widget widget="home-logo" args=args}}`, - beforeEach() { - this.siteSettings.site_logo_url = bigLogo; - this.site.mobileView = true; - }, - - test(assert) { - assert.strictEqual(count("img#site-logo.logo-big"), 1); - assert.strictEqual(queryAll("#site-logo").attr("src"), bigLogo); - }, - }); - - componentTest("logo with dark mode alternative", { - template: hbs`{{mount-widget widget="home-logo" args=args}}`, - beforeEach() { - this.siteSettings.site_logo_url = bigLogo; - this.siteSettings.site_logo_dark_url = darkLogo; - Session.currentProp("darkModeAvailable", true); - }, - afterEach() { - Session.currentProp("darkModeAvailable", null); - }, - - test(assert) { - assert.strictEqual(count("img#site-logo.logo-big"), 1); - assert.strictEqual(queryAll("#site-logo").attr("src"), bigLogo); - - assert.strictEqual( - queryAll("picture source").attr("media"), - prefersDark, - "includes dark mode media attribute" - ); - assert.strictEqual( - queryAll("picture source").attr("srcset"), - darkLogo, - "includes dark mode alternative logo source" - ); - }, - }); - - componentTest("mobile logo with dark mode alternative", { - template: hbs`{{mount-widget widget="home-logo" args=args}}`, - beforeEach() { - this.siteSettings.site_logo_url = bigLogo; - this.siteSettings.site_mobile_logo_url = mobileLogo; - this.siteSettings.site_mobile_logo_dark_url = darkLogo; - Session.currentProp("darkModeAvailable", true); - - this.site.mobileView = true; - }, - afterEach() { - Session.currentProp("darkModeAvailable", null); - }, - - test(assert) { - assert.strictEqual(queryAll("#site-logo").attr("src"), mobileLogo); - - assert.strictEqual( - queryAll("picture source").attr("media"), - prefersDark, - "includes dark mode media attribute" - ); - assert.strictEqual( - queryAll("picture source").attr("srcset"), - darkLogo, - "includes dark mode alternative logo source" - ); - }, - }); - - componentTest("dark mode enabled but no dark logo set", { - template: hbs`{{mount-widget widget="home-logo" args=args}}`, - beforeEach() { - this.siteSettings.site_logo_url = bigLogo; - this.siteSettings.site_logo_dark_url = ""; - Session.currentProp("darkModeAvailable", true); - }, - afterEach() { - Session.currentProp("darkModeAvailable", null); - }, - - test(assert) { - assert.strictEqual(count("img#site-logo.logo-big"), 1); - assert.strictEqual(queryAll("#site-logo").attr("src"), bigLogo); - assert.ok(!exists("picture"), "does not include alternative logo"); - }, - }); - - componentTest("dark logo set but no dark mode", { - template: hbs`{{mount-widget widget="home-logo" args=args}}`, - beforeEach() { - this.siteSettings.site_logo_url = bigLogo; - this.siteSettings.site_logo_dark_url = darkLogo; - }, - - test(assert) { - assert.strictEqual(count("img#site-logo.logo-big"), 1); - assert.strictEqual(queryAll("#site-logo").attr("src"), bigLogo); - assert.ok(!exists("picture"), "does not include alternative logo"); - }, - }); - - componentTest("dark color scheme and dark logo set", { - template: hbs`{{mount-widget widget="home-logo" args=args}}`, - beforeEach() { - this.siteSettings.site_logo_url = bigLogo; - this.siteSettings.site_logo_dark_url = darkLogo; - Session.currentProp("defaultColorSchemeIsDark", true); - }, - afterEach() { - Session.currentProp("defaultColorSchemeIsDark", null); - }, - test(assert) { - assert.strictEqual(count("img#site-logo.logo-big"), 1); - assert.strictEqual( - queryAll("#site-logo").attr("src"), - darkLogo, - "uses dark logo" - ); - assert.ok(!exists("picture"), "does not add dark mode alternative"); - }, - }); - - componentTest("dark color scheme and dark logo not set", { - template: hbs`{{mount-widget widget="home-logo" args=args}}`, - beforeEach() { - this.siteSettings.site_logo_url = bigLogo; - this.siteSettings.site_logo_dark_url = ""; - Session.currentProp("defaultColorSchemeIsDark", true); - }, - afterEach() { - Session.currentProp("defaultColorSchemeIsDark", null); - }, - test(assert) { - assert.strictEqual(count("img#site-logo.logo-big"), 1); - assert.strictEqual( - queryAll("#site-logo").attr("src"), - bigLogo, - "uses regular logo on dark scheme if no dark logo" - ); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/post-links-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/post-links-test.js deleted file mode 100644 index 34b78dd6a5e..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/post-links-test.js +++ /dev/null @@ -1,92 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { count, discourseModule } from "discourse/tests/helpers/qunit-helpers"; -import { click } from "@ember/test-helpers"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule( - "Integration | Component | Widget | post-links", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("duplicate links", { - template: hbs`{{mount-widget widget="post-links" args=args}}`, - beforeEach() { - this.set("args", { - id: 2, - links: [ - { - title: "Evil Trout Link", - url: "http://eviltrout.com", - reflection: true, - }, - { - title: "Evil Trout Link", - url: "http://dupe.eviltrout.com", - reflection: true, - }, - ], - }); - }, - test(assert) { - assert.strictEqual( - count(".post-links a.track-link"), - 1, - "it hides the dupe link" - ); - }, - }); - - componentTest("collapsed links", { - template: hbs`{{mount-widget widget="post-links" args=args}}`, - beforeEach() { - this.set("args", { - id: 1, - links: [ - { - title: "Link 1", - url: "http://eviltrout.com?1", - reflection: true, - }, - { - title: "Link 2", - url: "http://eviltrout.com?2", - reflection: true, - }, - { - title: "Link 3", - url: "http://eviltrout.com?3", - reflection: true, - }, - { - title: "Link 4", - url: "http://eviltrout.com?4", - reflection: true, - }, - { - title: "Link 5", - url: "http://eviltrout.com?5", - reflection: true, - }, - { - title: "Link 6", - url: "http://eviltrout.com?6", - reflection: true, - }, - { - title: "Link 7", - url: "http://eviltrout.com?7", - reflection: true, - }, - ], - }); - }, - async test(assert) { - assert.strictEqual(count(".expand-links"), 1, "collapsed by default"); - await click("a.expand-links"); - assert.strictEqual(count(".post-links a.track-link"), 7); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/post-menu-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/post-menu-test.js deleted file mode 100644 index 3cd9961d0d3..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/post-menu-test.js +++ /dev/null @@ -1,99 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, -} from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; -import { resetPostMenuExtraButtons } from "discourse/widgets/post-menu"; -import { withPluginApi } from "discourse/lib/plugin-api"; - -discourseModule( - "Integration | Component | Widget | post-menu", - function (hooks) { - hooks.afterEach(() => { - resetPostMenuExtraButtons(); - }); - - setupRenderingTest(hooks); - - componentTest("add extra button", { - template: hbs`{{mount-widget widget="post-menu" args=args}}`, - beforeEach() { - this.set("args", {}); - withPluginApi("0.14.0", (api) => { - api.addPostMenuButton("coffee", () => { - return { - action: "drinkCoffee", - icon: "coffee", - className: "hot-coffee", - title: "coffee.title", - position: "first", - }; - }); - }); - }, - - async test(assert) { - assert.strictEqual( - count(".actions .extra-buttons .hot-coffee"), - 1, - "It renders extra button" - ); - }, - }); - - componentTest("removes button based on callback", { - template: hbs`{{mount-widget widget="post-menu" args=args}}`, - - beforeEach() { - this.set("args", { canCreatePost: true, canRemoveReply: true }); - - withPluginApi("0.14.0", (api) => { - api.removePostMenuButton("reply", (attrs) => { - return attrs.canRemoveReply; - }); - }); - }, - - async test(assert) { - assert.ok(!exists(".actions .reply"), "it removes reply button"); - }, - }); - - componentTest("does not remove butto", { - template: hbs`{{mount-widget widget="post-menu" args=args}}`, - - beforeEach() { - this.set("args", { canCreatePost: true, canRemoveReply: false }); - - withPluginApi("0.14.0", (api) => { - api.removePostMenuButton("reply", (attrs) => { - return attrs.canRemoveReply; - }); - }); - }, - - async test(assert) { - assert.ok(exists(".actions .reply"), "it does not remove reply button"); - }, - }); - - componentTest("removes button", { - template: hbs`{{mount-widget widget="post-menu" args=args}}`, - beforeEach() { - this.set("args", { canCreatePost: true }); - - withPluginApi("0.14.0", (api) => { - api.removePostMenuButton("reply"); - }); - }, - - async test(assert) { - assert.ok(!exists(".actions .reply"), "it removes reply button"); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/post-small-action-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/post-small-action-test.js deleted file mode 100644 index e50ddc735e6..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/post-small-action-test.js +++ /dev/null @@ -1,93 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, exists } from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule( - "Integration | Component | Widget | post-small-action", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("does not have delete/edit/recover buttons by default", { - template: hbs`{{mount-widget widget="post-small-action" args=args}}`, - beforeEach() { - this.set("args", { id: 123 }); - }, - async test(assert) { - assert.ok(!exists(".small-action-desc > .small-action-delete")); - assert.ok(!exists(".small-action-desc > .small-action-recover")); - assert.ok(!exists(".small-action-desc > .small-action-edit")); - }, - }); - - componentTest("shows edit button if canEdit", { - template: hbs`{{mount-widget widget="post-small-action" args=args}}`, - beforeEach() { - this.set("args", { id: 123, canEdit: true }); - }, - async test(assert) { - assert.ok( - exists(".small-action-desc > .small-action-edit"), - "it adds the edit small action button" - ); - }, - }); - - componentTest("uses custom widget if actionDescriptionWidget", { - template: hbs`{{mount-widget widget="post-small-action" args=args}}`, - beforeEach() { - this.set("args", { id: 123, actionDescriptionWidget: "button" }); - }, - async test(assert) { - assert.ok( - exists(".small-action .widget-button"), - "it adds the custom widget" - ); - }, - }); - - componentTest("does not show edit button if canRecover even if canEdit", { - template: hbs`{{mount-widget widget="post-small-action" args=args}}`, - beforeEach() { - this.set("args", { id: 123, canEdit: true, canRecover: true }); - }, - async test(assert) { - assert.ok( - !exists(".small-action-desc > .small-action-edit"), - "it does not add the edit small action button" - ); - assert.ok( - exists(".small-action-desc > .small-action-recover"), - "it adds the recover small action button" - ); - }, - }); - - componentTest("shows delete button if canDelete", { - template: hbs`{{mount-widget widget="post-small-action" args=args}}`, - beforeEach() { - this.set("args", { id: 123, canDelete: true }); - }, - async test(assert) { - assert.ok( - exists(".small-action-desc > .small-action-delete"), - "it adds the delete small action button" - ); - }, - }); - - componentTest("shows undo button if canRecover", { - template: hbs`{{mount-widget widget="post-small-action" args=args}}`, - beforeEach() { - this.set("args", { id: 123, canRecover: true }); - }, - async test(assert) { - assert.ok( - exists(".small-action-desc > .small-action-recover"), - "it adds the recover small action button" - ); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/post-stream-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/post-stream-test.js deleted file mode 100644 index 76e63c55dd1..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/post-stream-test.js +++ /dev/null @@ -1,159 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import Post from "discourse/models/post"; -import Topic from "discourse/models/topic"; -import hbs from "htmlbars-inline-precompile"; - -function postStreamTest(name, attrs) { - componentTest(name, { - template: hbs`{{mount-widget widget="post-stream" args=(hash posts=posts)}}`, - beforeEach() { - const site = this.container.lookup("site:main"); - let posts = attrs.posts.call(this); - posts.forEach((p) => p.set("site", site)); - this.set("posts", posts); - }, - test: attrs.test, - }); -} - -discourseModule( - "Integration | Component | Widget | post-stream", - function (hooks) { - setupRenderingTest(hooks); - - postStreamTest("basics", { - posts() { - const site = this.container.lookup("site:main"); - const topic = Topic.create(); - topic.set("details.created_by", { id: 123 }); - return [ - Post.create({ - topic, - id: 1, - post_number: 1, - user_id: 123, - primary_group_name: "trout", - avatar_template: "/images/avatar.png", - }), - Post.create({ - topic, - id: 2, - post_number: 2, - post_type: site.get("post_types.moderator_action"), - }), - Post.create({ topic, id: 3, post_number: 3, hidden: true }), - Post.create({ - topic, - id: 4, - post_number: 4, - post_type: site.get("post_types.whisper"), - }), - Post.create({ - topic, - id: 5, - post_number: 5, - wiki: true, - via_email: true, - }), - Post.create({ - topic, - id: 6, - post_number: 6, - via_email: true, - is_auto_generated: true, - }), - ]; - }, - - test(assert) { - assert.strictEqual(count(".post-stream"), 1); - assert.strictEqual(count(".topic-post"), 6, "renders all posts"); - - // look for special class bindings - assert.strictEqual( - queryAll(".topic-post:nth-of-type(1).topic-owner").length, - 1, - "it applies the topic owner class" - ); - assert.strictEqual( - queryAll(".topic-post:nth-of-type(1).group-trout").length, - 1, - "it applies the primary group class" - ); - assert.strictEqual( - queryAll(".topic-post:nth-of-type(1).regular").length, - 1, - "it applies the regular class" - ); - assert.strictEqual( - queryAll(".topic-post:nth-of-type(2).moderator").length, - 1, - "it applies the moderator class" - ); - assert.strictEqual( - queryAll(".topic-post:nth-of-type(3).post-hidden").length, - 1, - "it applies the hidden class" - ); - assert.strictEqual( - queryAll(".topic-post:nth-of-type(4).whisper").length, - 1, - "it applies the whisper class" - ); - assert.strictEqual( - queryAll(".topic-post:nth-of-type(5).wiki").length, - 1, - "it applies the wiki class" - ); - - // it renders an article for the body with appropriate attributes - assert.strictEqual(count("article#post_2"), 1); - assert.strictEqual(count('article[data-user-id="123"]'), 1); - assert.strictEqual(count('article[data-post-id="3"]'), 1); - assert.strictEqual(count("article#post_5.via-email"), 1); - assert.strictEqual(count("article#post_6.is-auto-generated"), 1); - - assert.strictEqual( - queryAll("article:nth-of-type(1) .main-avatar").length, - 1, - "renders the main avatar" - ); - }, - }); - - postStreamTest("deleted posts", { - posts() { - const topic = Topic.create(); - topic.set("details.created_by", { id: 123 }); - return [ - Post.create({ - topic, - id: 1, - post_number: 1, - deleted_at: new Date().toString(), - }), - ]; - }, - - test(assert) { - assert.strictEqual( - count(".topic-post.deleted"), - 1, - "it applies the deleted class" - ); - assert.strictEqual( - count(".deleted-user-avatar"), - 1, - "it has the trash avatar" - ); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/post-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/post-test.js deleted file mode 100644 index a7551381c9b..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/post-test.js +++ /dev/null @@ -1,1044 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import EmberObject from "@ember/object"; -import I18n from "I18n"; -import { click } from "@ember/test-helpers"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule("Integration | Component | Widget | post", function (hooks) { - setupRenderingTest(hooks); - - componentTest("basic elements", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { shareUrl: "/example", post_number: 1 }); - }, - test(assert) { - assert.ok(exists(".names"), "includes poster name"); - assert.ok(exists("a.post-date"), "includes post date"); - }, - }); - - componentTest("post - links", { - template: hbs`{{mount-widget widget="post-contents" args=args}}`, - beforeEach() { - this.set("args", { - cooked: - "first link and second link", - linkCounts: [ - { url: "http://link1.example.com/", clicks: 1, internal: true }, - { url: "http://link2.example.com/", clicks: 2, internal: true }, - ], - }); - }, - async test(assert) { - assert.strictEqual(queryAll(".badge.clicks:nth(0)").text(), "1"); - assert.strictEqual(queryAll(".badge.clicks:nth(1)").text(), "2"); - }, - }); - - componentTest("post - onebox links", { - template: hbs`{{mount-widget widget="post-contents" args=args}}`, - beforeEach() { - this.set("args", { - cooked: ` -

    Other URL

    - - `, - linkCounts: [ - { url: "https://example.com", clicks: 1 }, - { url: "https://twitter.com/codinghorror", clicks: 2 }, - ], - }); - }, - async test(assert) { - assert.strictEqual(queryAll(".badge.clicks").length, 2); - assert.strictEqual(queryAll(".badge.clicks:nth(0)").text(), "1"); - assert.strictEqual(queryAll(".badge.clicks:nth(1)").text(), "2"); - }, - }); - - componentTest("wiki", { - template: hbs` - {{mount-widget widget="post" args=args showHistory=showHistory}} - `, - beforeEach() { - this.set("args", { wiki: true, version: 2, canViewEditHistory: true }); - this.set("showHistory", () => (this.historyShown = true)); - }, - async test(assert) { - await click(".post-info .wiki"); - assert.ok( - this.historyShown, - "clicking the wiki icon displays the post history" - ); - }, - }); - - componentTest("wiki without revision", { - template: hbs` - {{mount-widget widget="post" args=args editPost=editPost}} - `, - beforeEach() { - this.set("args", { wiki: true, version: 1, canViewEditHistory: true }); - this.set("editPost", () => (this.editPostCalled = true)); - }, - async test(assert) { - await click(".post-info .wiki"); - assert.ok(this.editPostCalled, "clicking wiki icon edits the post"); - }, - }); - - componentTest("via-email", { - template: hbs` - {{mount-widget widget="post" args=args showRawEmail=showRawEmail}} - `, - beforeEach() { - this.set("args", { via_email: true, canViewRawEmail: true }); - this.set("showRawEmail", () => (this.rawEmailShown = true)); - }, - async test(assert) { - await click(".post-info.via-email"); - assert.ok( - this.rawEmailShown, - "clicking the envelope shows the raw email" - ); - }, - }); - - componentTest("via-email without permission", { - template: hbs` - {{mount-widget widget="post" args=args showRawEmail=showRawEmail}} - `, - beforeEach() { - this.set("args", { via_email: true, canViewRawEmail: false }); - this.set("showRawEmail", () => (this.rawEmailShown = true)); - }, - async test(assert) { - await click(".post-info.via-email"); - assert.ok( - !this.rawEmailShown, - "clicking the envelope doesn't show the raw email" - ); - }, - }); - - componentTest("history", { - template: hbs` - {{mount-widget widget="post" args=args showHistory=showHistory}} - `, - beforeEach() { - this.set("args", { version: 3, canViewEditHistory: true }); - this.set("showHistory", () => (this.historyShown = true)); - }, - async test(assert) { - await click(".post-info.edits button"); - assert.ok(this.historyShown, "clicking the pencil shows the history"); - }, - }); - - componentTest("history without view permission", { - template: hbs` - {{mount-widget widget="post" args=args showHistory=showHistory}} - `, - beforeEach() { - this.set("args", { version: 3, canViewEditHistory: false }); - this.set("showHistory", () => (this.historyShown = true)); - }, - async test(assert) { - await click(".post-info.edits"); - assert.ok( - !this.historyShown, - `clicking the pencil doesn't show the history` - ); - }, - }); - - componentTest("whisper", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { isWhisper: true }); - }, - test(assert) { - assert.strictEqual(count(".topic-post.whisper"), 1); - assert.strictEqual(count(".post-info.whisper"), 1); - }, - }); - - componentTest("like count button", { - template: hbs`{{mount-widget widget="post" model=post args=args}}`, - beforeEach(store) { - const topic = store.createRecord("topic", { id: 123 }); - const post = store.createRecord("post", { - id: 1, - post_number: 1, - topic, - like_count: 3, - actions_summary: [{ id: 2, count: 1, hidden: false, can_act: true }], - }); - this.set("post", post); - this.set("args", { likeCount: 1 }); - }, - async test(assert) { - assert.strictEqual(count("button.like-count"), 1); - assert.ok(!exists(".who-liked")); - - // toggle it on - await click("button.like-count"); - assert.strictEqual(count(".who-liked"), 1); - assert.strictEqual(count(".who-liked a.trigger-user-card"), 1); - - // toggle it off - await click("button.like-count"); - assert.ok(!exists(".who-liked")); - assert.ok(!exists(".who-liked a.trigger-user-card")); - }, - }); - - componentTest(`like count with no likes`, { - template: hbs`{{mount-widget widget="post" model=post args=args}}`, - beforeEach() { - this.set("args", { likeCount: 0 }); - }, - test(assert) { - assert.ok(!exists("button.like-count")); - }, - }); - - componentTest("share button", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { shareUrl: "http://share-me.example.com" }); - }, - test(assert) { - assert.ok(exists(".actions button.share"), "it renders a share button"); - }, - }); - - componentTest("liking", { - template: hbs` - {{mount-widget widget="post-menu" args=args toggleLike=toggleLike}} - `, - beforeEach() { - const args = { showLike: true, canToggleLike: true, id: 5 }; - this.set("args", args); - this.set("toggleLike", () => { - args.liked = !args.liked; - args.likeCount = args.liked ? 1 : 0; - }); - }, - async test(assert) { - assert.ok(exists(".actions button.like")); - assert.ok(!exists(".actions button.like-count")); - - await click(".actions button.like"); - assert.ok(!exists(".actions button.like")); - assert.ok(exists(".actions button.has-like")); - assert.strictEqual(count(".actions button.like-count"), 1); - - await click(".actions button.has-like"); - assert.ok(exists(".actions button.like")); - assert.ok(!exists(".actions button.has-like")); - assert.ok(!exists(".actions button.like-count")); - }, - }); - - componentTest("anon liking", { - template: hbs` - {{mount-widget widget="post-menu" args=args showLogin=showLogin}} - `, - anonymous: true, - beforeEach() { - const args = { showLike: true }; - this.set("args", args); - this.set("showLogin", () => (this.loginShown = true)); - }, - async test(assert) { - assert.ok(exists(".actions button.like")); - assert.ok(!exists(".actions button.like-count")); - - assert.strictEqual( - queryAll("button.like").attr("title"), - I18n.t("post.controls.like"), - `shows the right button title for anonymous users` - ); - - await click(".actions button.like"); - assert.ok(this.loginShown); - }, - }); - - componentTest("edit button", { - template: hbs` - {{mount-widget widget="post" args=args editPost=editPost}} - `, - beforeEach() { - this.set("args", { canEdit: true }); - this.set("editPost", () => (this.editPostCalled = true)); - }, - async test(assert) { - await click("button.edit"); - assert.ok(this.editPostCalled, "it triggered the edit action"); - }, - }); - - componentTest(`edit button - can't edit`, { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { canEdit: false }); - }, - test(assert) { - assert.ok(!exists("button.edit"), "button is not displayed"); - }, - }); - - componentTest("recover button", { - template: hbs` - {{mount-widget widget="post" args=args deletePost=deletePost}} - `, - beforeEach() { - this.set("args", { canDelete: true }); - this.set("deletePost", () => (this.deletePostCalled = true)); - }, - async test(assert) { - await click("button.delete"); - assert.ok(this.deletePostCalled, "it triggered the delete action"); - }, - }); - - componentTest("delete topic button", { - template: hbs` - {{mount-widget widget="post" args=args deletePost=deletePost}} - `, - beforeEach() { - this.set("args", { canDeleteTopic: true }); - this.set("deletePost", () => (this.deletePostCalled = true)); - }, - async test(assert) { - await click("button.delete"); - assert.ok(this.deletePostCalled, "it triggered the delete action"); - }, - }); - - componentTest(`delete topic button - can't delete`, { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { canDeleteTopic: false }); - }, - test(assert) { - assert.ok(!exists("button.delete"), `button is not displayed`); - }, - }); - - componentTest( - `delete topic button - can't delete when topic author without permission`, - { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { - canDeleteTopic: false, - showFlagDelete: true, - canFlag: true, - }); - }, - - async test(assert) { - await click(".show-more-actions"); - - assert.strictEqual( - count("button.create-flag"), - 1, - `button is displayed` - ); - assert.strictEqual(count("button.delete"), 1, `button is displayed`); - assert.strictEqual( - queryAll("button.delete").attr("title"), - I18n.t("post.controls.delete_topic_disallowed"), - `shows the right button title for users without permissions` - ); - }, - } - ); - - componentTest("recover topic button", { - template: hbs` - {{mount-widget widget="post" args=args recoverPost=recoverPost}} - `, - beforeEach() { - this.set("args", { canRecoverTopic: true }); - this.set("recoverPost", () => (this.recovered = true)); - }, - async test(assert) { - await click("button.recover"); - assert.ok(this.recovered); - }, - }); - - componentTest(`recover topic button - can't recover`, { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { canRecoverTopic: false }); - }, - test(assert) { - assert.ok(!exists("button.recover"), `button is not displayed`); - }, - }); - - componentTest("delete post button", { - template: hbs` - {{mount-widget widget="post" args=args deletePost=deletePost}} - `, - beforeEach() { - this.set("args", { canDelete: true, canFlag: true }); - this.set("deletePost", () => (this.deletePostCalled = true)); - }, - async test(assert) { - await click(".show-more-actions"); - await click("button.delete"); - assert.ok(this.deletePostCalled, "it triggered the delete action"); - }, - }); - - componentTest(`delete post button - can't delete`, { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { canDelete: false }); - }, - test(assert) { - assert.ok(!exists("button.delete"), `button is not displayed`); - }, - }); - - componentTest(`delete post button - can't delete, can't flag`, { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { - canDeleteTopic: false, - showFlagDelete: false, - canFlag: false, - }); - }, - test(assert) { - assert.ok(!exists("button.delete"), `delete button is not displayed`); - assert.ok(!exists("button.create-flag"), `flag button is not displayed`); - }, - }); - - componentTest("recover post button", { - template: hbs` - {{mount-widget widget="post" args=args recoverPost=recoverPost}} - `, - beforeEach() { - this.set("args", { canRecover: true }); - this.set("recoverPost", () => (this.recovered = true)); - }, - async test(assert) { - await click("button.recover"); - assert.ok(this.recovered); - }, - }); - - componentTest(`recover post button - can't recover`, { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { canRecover: false }); - }, - test(assert) { - assert.ok(!exists("button.recover"), `button is not displayed`); - }, - }); - - componentTest(`flagging`, { - template: hbs` - {{mount-widget widget="post" args=args showFlags=showFlags}} - `, - beforeEach() { - this.set("args", { canFlag: true }); - this.set("showFlags", () => (this.flagsShown = true)); - }, - async test(assert) { - assert.strictEqual(count("button.create-flag"), 1); - - await click("button.create-flag"); - assert.ok(this.flagsShown, "it triggered the action"); - }, - }); - - componentTest(`flagging: can't flag`, { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { canFlag: false }); - }, - test(assert) { - assert.ok(!exists("button.create-flag")); - }, - }); - - componentTest(`flagging: can't flag when post is hidden`, { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { canFlag: true, hidden: true }); - }, - test(assert) { - assert.ok(!exists("button.create-flag")); - }, - }); - - componentTest(`read indicator`, { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { read: true }); - }, - test(assert) { - assert.ok(exists(".read-state.read")); - }, - }); - - componentTest(`unread indicator`, { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { read: false }); - }, - test(assert) { - assert.ok(exists(".read-state")); - }, - }); - - componentTest("reply directly above (suppressed)", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { - replyToUsername: "eviltrout", - replyToAvatarTemplate: "/images/avatar.png", - replyDirectlyAbove: true, - }); - }, - test(assert) { - assert.ok(!exists("a.reply-to-tab"), "hides the tab"); - assert.ok(!exists(".avoid-tab"), "doesn't have the avoid tab class"); - }, - }); - - componentTest("reply a few posts above (suppressed)", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { - replyToUsername: "eviltrout", - replyToAvatarTemplate: "/images/avatar.png", - replyDirectlyAbove: false, - }); - }, - test(assert) { - assert.ok(exists("a.reply-to-tab"), "shows the tab"); - assert.strictEqual(count(".avoid-tab"), 1, "has the avoid tab class"); - }, - }); - - componentTest("reply directly above", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { - replyToUsername: "eviltrout", - replyToAvatarTemplate: "/images/avatar.png", - replyDirectlyAbove: true, - }); - this.siteSettings.suppress_reply_directly_above = false; - }, - async test(assert) { - assert.strictEqual(count(".avoid-tab"), 1, "has the avoid tab class"); - await click("a.reply-to-tab"); - assert.strictEqual(count("section.embedded-posts.top .cooked"), 1); - assert.strictEqual(count("section.embedded-posts .d-icon-arrow-up"), 1); - }, - }); - - componentTest("cooked content hidden", { - template: hbs` - {{mount-widget widget="post" args=args expandHidden=expandHidden}} - `, - beforeEach() { - this.set("args", { cooked_hidden: true }); - this.set("expandHidden", () => (this.unhidden = true)); - }, - async test(assert) { - await click(".topic-body .expand-hidden"); - assert.ok(this.unhidden, "triggers the action"); - }, - }); - - componentTest("expand first post", { - template: hbs`{{mount-widget widget="post" model=post args=args}}`, - beforeEach(store) { - this.set("args", { expandablePost: true }); - this.set("post", store.createRecord("post", { id: 1234 })); - }, - async test(assert) { - await click(".topic-body .expand-post"); - assert.ok(!exists(".expand-post"), "button is gone"); - }, - }); - - componentTest("can't bookmark", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { canBookmark: false }); - }, - test(assert) { - assert.ok(!exists("button.bookmark")); - assert.ok(!exists("button.bookmarked")); - }, - }); - - componentTest("bookmark", { - template: hbs` - {{mount-widget widget="post" args=args toggleBookmark=toggleBookmark}} - `, - beforeEach() { - const args = { canBookmark: true }; - - this.set("args", args); - this.set("toggleBookmark", () => (args.bookmarked = true)); - }, - async test(assert) { - assert.strictEqual(count(".post-menu-area .bookmark"), 1); - assert.ok(!exists("button.bookmarked")); - }, - }); - - componentTest("can't show admin menu when you can't manage", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { canManage: false }); - }, - test(assert) { - assert.ok(!exists(".post-menu-area .show-post-admin-menu")); - }, - }); - - componentTest("show admin menu", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { canManage: true }); - }, - async test(assert) { - assert.ok(!exists(".post-admin-menu")); - await click(".post-menu-area .show-post-admin-menu"); - assert.strictEqual(count(".post-admin-menu"), 1, "it shows the popup"); - await click(".post-menu-area"); - assert.ok( - !exists(".post-admin-menu"), - "clicking outside clears the popup" - ); - }, - }); - - componentTest("permanently delete topic", { - template: hbs`{{mount-widget widget="post" args=args permanentlyDeletePost=permanentlyDeletePost}}`, - beforeEach() { - this.set("args", { canManage: true, canPermanentlyDelete: true }); - this.set("permanentlyDeletePost", () => (this.deleted = true)); - }, - async test(assert) { - await click(".post-menu-area .show-post-admin-menu"); - await click(".post-admin-menu .permanently-delete"); - assert.ok(this.deleted); - assert.ok(!exists(".post-admin-menu"), "also hides the menu"); - }, - }); - - componentTest("permanently delete post", { - template: hbs` - {{mount-widget widget="post" args=args permanentlyDeletePost=permanentlyDeletePost}} - `, - beforeEach() { - this.set("args", { canManage: true, canPermanentlyDelete: true }); - this.set("permanentlyDeletePost", () => (this.deleted = true)); - }, - async test(assert) { - await click(".post-menu-area .show-post-admin-menu"); - await click(".post-admin-menu .permanently-delete"); - assert.ok(this.deleted); - assert.ok(!exists(".post-admin-menu"), "also hides the menu"); - }, - }); - - componentTest("toggle moderator post", { - template: hbs` - {{mount-widget widget="post" args=args togglePostType=togglePostType}} - `, - beforeEach() { - this.currentUser.set("moderator", true); - this.set("args", { canManage: true }); - this.set("togglePostType", () => (this.toggled = true)); - }, - async test(assert) { - await click(".post-menu-area .show-post-admin-menu"); - await click(".post-admin-menu .toggle-post-type"); - - assert.ok(this.toggled); - assert.ok(!exists(".post-admin-menu"), "also hides the menu"); - }, - }); - componentTest("toggle moderator post", { - template: hbs` - {{mount-widget widget="post" args=args togglePostType=togglePostType}} - `, - beforeEach() { - this.currentUser.set("moderator", true); - this.set("args", { canManage: true }); - this.set("togglePostType", () => (this.toggled = true)); - }, - async test(assert) { - await click(".post-menu-area .show-post-admin-menu"); - await click(".post-admin-menu .toggle-post-type"); - - assert.ok(this.toggled); - assert.ok(!exists(".post-admin-menu"), "also hides the menu"); - }, - }); - - componentTest("rebake post", { - template: hbs` - {{mount-widget widget="post" args=args rebakePost=rebakePost}} - `, - beforeEach() { - this.set("args", { canManage: true }); - this.set("rebakePost", () => (this.baked = true)); - }, - async test(assert) { - await click(".post-menu-area .show-post-admin-menu"); - await click(".post-admin-menu .rebuild-html"); - assert.ok(this.baked); - assert.ok(!exists(".post-admin-menu"), "also hides the menu"); - }, - }); - - componentTest("unhide post", { - template: hbs` - {{mount-widget widget="post" args=args unhidePost=unhidePost}} - `, - beforeEach() { - this.currentUser.admin = true; - this.set("args", { canManage: true, hidden: true }); - this.set("unhidePost", () => (this.unhidden = true)); - }, - async test(assert) { - await click(".post-menu-area .show-post-admin-menu"); - await click(".post-admin-menu .unhide-post"); - assert.ok(this.unhidden); - assert.ok(!exists(".post-admin-menu"), "also hides the menu"); - }, - }); - - componentTest("change owner", { - template: hbs` - {{mount-widget widget="post" args=args changePostOwner=changePostOwner}} - `, - beforeEach() { - this.currentUser.admin = true; - this.set("args", { canManage: true }); - this.set("changePostOwner", () => (this.owned = true)); - }, - async test(assert) { - await click(".post-menu-area .show-post-admin-menu"); - await click(".post-admin-menu .change-owner"); - assert.ok(this.owned); - assert.ok(!exists(".post-admin-menu"), "also hides the menu"); - }, - }); - - componentTest("reply", { - template: hbs` - {{mount-widget widget="post" args=args replyToPost=replyToPost}} - `, - beforeEach() { - this.set("args", { canCreatePost: true }); - this.set("replyToPost", () => (this.replied = true)); - }, - async test(assert) { - await click(".post-controls .create"); - assert.ok(this.replied); - }, - }); - - componentTest("reply - without permissions", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { canCreatePost: false }); - }, - test(assert) { - assert.ok(!exists(".post-controls .create")); - }, - }); - - componentTest("replies - no replies", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { replyCount: 0 }); - }, - test(assert) { - assert.ok(!exists("button.show-replies")); - }, - }); - - componentTest("replies - multiple replies", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.siteSettings.suppress_reply_directly_below = true; - this.set("args", { replyCount: 2, replyDirectlyBelow: true }); - }, - test(assert) { - assert.strictEqual(count("button.show-replies"), 1); - }, - }); - - componentTest("replies - one below, suppressed", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.siteSettings.suppress_reply_directly_below = true; - this.set("args", { replyCount: 1, replyDirectlyBelow: true }); - }, - test(assert) { - assert.ok(!exists("button.show-replies")); - }, - }); - - componentTest("replies - one below, not suppressed", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.siteSettings.suppress_reply_directly_below = false; - this.set("args", { id: 6654, replyCount: 1, replyDirectlyBelow: true }); - }, - async test(assert) { - await click("button.show-replies"); - assert.strictEqual(count("section.embedded-posts.bottom .cooked"), 1); - assert.strictEqual(count("section.embedded-posts .d-icon-arrow-down"), 1); - }, - }); - - componentTest("topic map not shown", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { showTopicMap: false }); - }, - test(assert) { - assert.ok(!exists(".topic-map")); - }, - }); - - componentTest("topic map - few posts", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { - showTopicMap: true, - topicPostsCount: 2, - participants: [{ username: "eviltrout" }, { username: "codinghorror" }], - }); - }, - async test(assert) { - assert.ok( - !exists("li.avatars a.poster"), - "shows no participants when collapsed" - ); - - await click("nav.buttons button"); - assert.strictEqual( - count(".topic-map-expanded a.poster"), - 2, - "shows all when expanded" - ); - }, - }); - - componentTest("topic map - participants", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { - showTopicMap: true, - topicPostsCount: 10, - participants: [ - { username: "eviltrout" }, - { username: "codinghorror" }, - { username: "sam" }, - { username: "ZogStrIP" }, - ], - userFilters: ["sam", "codinghorror"], - }); - }, - async test(assert) { - assert.strictEqual( - count("li.avatars a.poster"), - 3, - "limits to three participants" - ); - - await click("nav.buttons button"); - assert.ok(!exists("li.avatars a.poster")); - assert.strictEqual( - count(".topic-map-expanded a.poster"), - 4, - "shows all when expanded" - ); - assert.strictEqual(count("a.poster.toggled"), 2, "two are toggled"); - }, - }); - - componentTest("topic map - links", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { - showTopicMap: true, - topicLinks: [ - { url: "http://link1.example.com", clicks: 0 }, - { url: "http://link2.example.com", clicks: 0 }, - { url: "http://link3.example.com", clicks: 0 }, - { url: "http://link4.example.com", clicks: 0 }, - { url: "http://link5.example.com", clicks: 0 }, - { url: "http://link6.example.com", clicks: 0 }, - ], - }); - }, - async test(assert) { - assert.strictEqual(count(".topic-map"), 1); - assert.strictEqual(count(".map.map-collapsed"), 1); - assert.ok(!exists(".topic-map-expanded")); - - await click("nav.buttons button"); - assert.ok(!exists(".map.map-collapsed")); - assert.strictEqual(count(".topic-map .d-icon-chevron-up"), 1); - assert.strictEqual(count(".topic-map-expanded"), 1); - assert.strictEqual( - count(".topic-map-expanded .topic-link"), - 5, - "it limits the links displayed" - ); - - await click(".link-summary button"); - assert.strictEqual( - count(".topic-map-expanded .topic-link"), - 6, - "all links now shown" - ); - }, - }); - - componentTest("topic map - no summary", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { showTopicMap: true }); - }, - test(assert) { - assert.ok(!exists(".toggle-summary")); - }, - }); - - componentTest("topic map - has summary", { - template: hbs`{{mount-widget widget="post" args=args showSummary=showSummary}}`, - beforeEach() { - this.set("args", { showTopicMap: true, hasTopicSummary: true }); - this.set("showSummary", () => (this.summaryToggled = true)); - }, - async test(assert) { - assert.strictEqual(count(".toggle-summary"), 1); - - await click(".toggle-summary button"); - assert.ok(this.summaryToggled); - }, - }); - - componentTest("pm map", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { - showTopicMap: true, - showPMMap: true, - allowedGroups: [], - allowedUsers: [EmberObject.create({ username: "eviltrout" })], - }); - }, - test(assert) { - assert.strictEqual(count(".private-message-map"), 1); - assert.strictEqual(count(".private-message-map .user"), 1); - }, - }); - - componentTest("post notice - with username", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - const twoDaysAgo = new Date(); - twoDaysAgo.setDate(twoDaysAgo.getDate() - 2); - this.siteSettings.display_name_on_posts = false; - this.siteSettings.prioritize_username_in_ux = true; - this.siteSettings.old_post_notice_days = 14; - this.set("args", { - username: "codinghorror", - name: "Jeff", - created_at: new Date(), - notice: { - type: "returning_user", - lastPostedAt: twoDaysAgo, - }, - }); - }, - test(assert) { - assert.strictEqual( - queryAll(".post-notice.returning-user:not(.old)").text().trim(), - I18n.t("post.notice.returning_user", { - user: "codinghorror", - time: "2 days ago", - }) - ); - }, - }); - - componentTest("post notice - with name", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.siteSettings.display_name_on_posts = true; - this.siteSettings.prioritize_username_in_ux = false; - this.siteSettings.old_post_notice_days = 14; - this.set("args", { - username: "codinghorror", - name: "Jeff", - created_at: new Date(2019, 0, 1), - notice: { type: "new_user" }, - }); - }, - test(assert) { - assert.strictEqual( - queryAll(".post-notice.old.new-user").text().trim(), - I18n.t("post.notice.new_user", { user: "Jeff", time: "Jan '10" }) - ); - }, - }); - - componentTest("show group request in post", { - template: hbs`{{mount-widget widget="post" args=args}}`, - beforeEach() { - this.set("args", { - username: "foo", - requestedGroupName: "testGroup", - }); - }, - test(assert) { - const link = queryAll(".group-request a"); - assert.strictEqual(link.text().trim(), I18n.t("groups.requests.handle")); - assert.strictEqual(link.attr("href"), "/g/testGroup/requests?filter=foo"); - }, - }); -}); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/poster-name-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/poster-name-test.js deleted file mode 100644 index 4b62324e76c..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/poster-name-test.js +++ /dev/null @@ -1,82 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule( - "Integration | Component | Widget | poster-name", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("basic rendering", { - template: hbs`{{mount-widget widget="poster-name" args=args}}`, - beforeEach() { - this.set("args", { - username: "eviltrout", - usernameUrl: "/u/eviltrout", - name: "Robin Ward", - user_title: "Trout Master", - }); - }, - test(assert) { - assert.ok(exists(".names")); - assert.ok(exists("span.username")); - assert.ok(exists('a[data-user-card="eviltrout"]')); - assert.strictEqual(queryAll(".username a").text(), "eviltrout"); - assert.strictEqual(queryAll(".full-name a").text(), "Robin Ward"); - assert.strictEqual(queryAll(".user-title").text(), "Trout Master"); - }, - }); - - componentTest("extra classes and glyphs", { - template: hbs`{{mount-widget widget="poster-name" args=args}}`, - beforeEach() { - this.set("args", { - username: "eviltrout", - usernameUrl: "/u/eviltrout", - staff: true, - admin: true, - moderator: true, - new_user: true, - primary_group_name: "fish", - }); - }, - test(assert) { - assert.ok(exists("span.staff")); - assert.ok(exists("span.admin")); - assert.ok(exists("span.moderator")); - assert.ok(exists(".d-icon-shield-alt")); - assert.ok(exists("span.new-user")); - assert.ok(exists("span.fish")); - }, - }); - - componentTest("disable display name on posts", { - template: hbs`{{mount-widget widget="poster-name" args=args}}`, - beforeEach() { - this.siteSettings.display_name_on_posts = false; - this.set("args", { username: "eviltrout", name: "Robin Ward" }); - }, - test(assert) { - assert.ok(!exists(".full-name")); - }, - }); - - componentTest("doesn't render a name if it's similar to the username", { - template: hbs`{{mount-widget widget="poster-name" args=args}}`, - beforeEach() { - this.siteSettings.prioritize_username_in_ux = true; - this.siteSettings.display_name_on_posts = true; - this.set("args", { username: "eviltrout", name: "evil-trout" }); - }, - test(assert) { - assert.ok(!exists(".second")); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/quick-access-item-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/quick-access-item-test.js deleted file mode 100644 index be52259f424..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/quick-access-item-test.js +++ /dev/null @@ -1,40 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; - -const CONTENT_DIV_SELECTOR = "li > a > div"; - -discourseModule( - "Integration | Component | Widget | quick-access-item", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("content attribute is escaped", { - template: hbs`{{mount-widget widget="quick-access-item" args=args}}`, - - beforeEach() { - this.set("args", { content: "bold" }); - }, - - test(assert) { - const contentDiv = query(CONTENT_DIV_SELECTOR); - assert.strictEqual(contentDiv.innerText, "bold"); - }, - }); - - componentTest("escapedContent attribute is not escaped", { - template: hbs`{{mount-widget widget="quick-access-item" args=args}}`, - - beforeEach() { - this.set("args", { escapedContent: ""quote"" }); - }, - - test(assert) { - const contentDiv = query(CONTENT_DIV_SELECTOR); - assert.strictEqual(contentDiv.innerText, '"quote"'); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/small-user-list-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/small-user-list-test.js deleted file mode 100644 index b79df35d367..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/small-user-list-test.js +++ /dev/null @@ -1,33 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, -} from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule( - "Integration | Component | Widget | small-user-list", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("renders avatars and support for unknown", { - template: hbs`{{mount-widget widget="small-user-list" args=args}}`, - beforeEach() { - this.set("args", { - users: [ - { id: 456, username: "eviltrout" }, - { id: 457, username: "someone", unknown: true }, - ], - }); - }, - async test(assert) { - assert.strictEqual(count('[data-user-card="eviltrout"]'), 1); - assert.ok(!exists('[data-user-card="someone"]')); - assert.ok(exists(".unknown"), "includes unknown user"); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/software-update-prompt-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/software-update-prompt-test.js deleted file mode 100644 index 21aee3a4473..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/software-update-prompt-test.js +++ /dev/null @@ -1,44 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, - publishToMessageBus, -} from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; -import { later } from "@ember/runloop"; - -discourseModule( - "Integration | Component | software-update-prompt", - function (hooks) { - setupRenderingTest(hooks); - - componentTest( - "software-update-prompt gets correct CSS class after messageBus message", - { - template: hbs`{{software-update-prompt}}`, - - test(assert) { - assert.ok( - !exists("div.software-update-prompt"), - "it does not have the class to show the prompt" - ); - - publishToMessageBus("/global/asset-version", "somenewversion"); - - const done = assert.async(); - later(() => { - assert.strictEqual( - count("div.software-update-prompt.require-software-refresh"), - 1, - "it does have the class to show the prompt" - ); - done(); - }, 10); - }, - } - ); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/topic-admin-menu-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/topic-admin-menu-test.js deleted file mode 100644 index 7f4e56e2434..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/topic-admin-menu-test.js +++ /dev/null @@ -1,82 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, exists } from "discourse/tests/helpers/qunit-helpers"; -import Category from "discourse/models/category"; -import Topic from "discourse/models/topic"; -import hbs from "htmlbars-inline-precompile"; - -const createArgs = (topic) => { - return { - topic, - openUpwards: "true", - toggleMultiSelect: () => {}, - deleteTopic: () => {}, - recoverTopic: () => {}, - toggleClosed: () => {}, - toggleArchived: () => {}, - toggleVisibility: () => {}, - showTopicTimerModal: () => {}, - showFeatureTopic: () => {}, - showChangeTimestamp: () => {}, - resetBumpDate: () => {}, - convertToPublicTopic: () => {}, - convertToPrivateMessage: () => {}, - }; -}; - -discourseModule( - "Integration | Component | Widget | topic-admin-menu-button", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("topic-admin-menu-button is present for admin/moderators", { - template: hbs`{{mount-widget widget="topic-admin-menu-button" args=args}}`, - - beforeEach() { - this.currentUser.setProperties({ - admin: true, - moderator: true, - id: 123, - }); - const topic = Topic.create({ user_id: this.currentUser.id }); - topic.set("category_id", Category.create({ read_restricted: true }).id); - this.siteSettings.allow_featured_topic_on_user_profiles = true; - this.set("args", createArgs(topic)); - }, - - test(assert) { - assert.ok(exists(".toggle-admin-menu"), "admin wrench is present"); - }, - }); - - componentTest( - "topic-admin-menu-button hides for non-admin when there is no action", - { - template: hbs`{{mount-widget widget="topic-admin-menu-button" args=args}}`, - - beforeEach() { - this.currentUser.setProperties({ - admin: false, - moderator: false, - id: 123, - }); - const topic = Topic.create({ user_id: this.currentUser.id }); - topic.set( - "category_id", - Category.create({ read_restricted: true }).id - ); - this.siteSettings.allow_featured_topic_on_user_profiles = true; - this.set("args", createArgs(topic)); - }, - - test(assert) { - assert.ok( - !exists(".toggle-admin-menu"), - "admin wrench is not present" - ); - }, - } - ); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/topic-participant-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/topic-participant-test.js deleted file mode 100644 index 38ba3462e04..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/topic-participant-test.js +++ /dev/null @@ -1,62 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, exists } from "discourse/tests/helpers/qunit-helpers"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule( - "Integration | Component | Widget | topic-participant", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("one post", { - template: hbs`{{mount-widget widget="topic-participant" args=args}}`, - - beforeEach() { - this.set("args", { - username: "test", - avatar_template: "/images/avatar.png", - post_count: 1, - }); - }, - - test(assert) { - assert.ok(exists("a.poster.trigger-user-card")); - assert.ok( - !exists("span.post-count"), - "don't show count for only 1 post" - ); - assert.ok(!exists(".avatar-flair"), "no avatar flair"); - }, - }); - - componentTest("many posts, a primary group with flair", { - template: hbs`{{mount-widget widget="topic-participant" args=args}}`, - - beforeEach() { - this.set("args", { - username: "test", - avatar_template: "/images/avatar.png", - post_count: 2, - primary_group_name: "devs", - flair_name: "devs", - flair_url: "/images/d-logo-sketch-small.png", - flair_bg_color: "222", - }); - }, - - test(assert) { - assert.ok(exists("a.poster.trigger-user-card")); - assert.ok(exists("span.post-count"), "show count for many posts"); - assert.ok( - exists(".group-devs a.poster"), - "add class for the group outside the link" - ); - assert.ok( - exists(".avatar-flair.avatar-flair-devs"), - "show flair with group class" - ); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/topic-status-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/topic-status-test.js deleted file mode 100644 index c3f07cdedfc..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/topic-status-test.js +++ /dev/null @@ -1,82 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, exists } from "discourse/tests/helpers/qunit-helpers"; -import { click } from "@ember/test-helpers"; -import TopicStatusIcons from "discourse/helpers/topic-status-icons"; -import hbs from "htmlbars-inline-precompile"; - -discourseModule( - "Integration | Component | Widget | topic-status", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("basics", { - template: hbs`{{mount-widget widget="topic-status" args=args}}`, - beforeEach(store) { - this.set("args", { - topic: store.createRecord("topic", { closed: true }), - disableActions: true, - }); - }, - test(assert) { - assert.ok(exists(".topic-status .d-icon-lock")); - }, - }); - - componentTest("extendability", { - template: hbs`{{mount-widget widget="topic-status" args=args}}`, - beforeEach(store) { - TopicStatusIcons.addObject([ - "has_accepted_answer", - "far-check-square", - "solved", - ]); - this.set("args", { - topic: store.createRecord("topic", { - has_accepted_answer: true, - }), - disableActions: true, - }); - }, - test(assert) { - assert.ok(exists(".topic-status .d-icon-far-check-square")); - }, - }); - - componentTest("toggling pin status", { - template: hbs`{{mount-widget widget="topic-status" args=args}}`, - beforeEach(store) { - this.set("args", { - topic: store.createRecord("topic", { closed: true, pinned: true }), - }); - }, - async test(assert) { - assert.ok(exists(".topic-statuses .pinned"), "pinned icon is shown"); - assert.ok( - !exists(".topic-statuses .unpinned"), - "unpinned icon is not shown" - ); - - await click(".topic-statuses .pin-toggle-button"); - - assert.ok( - !exists(".topic-statuses .pinned"), - "pinned icon is not shown" - ); - assert.ok( - exists(".topic-statuses .unpinned"), - "unpinned icon is shown" - ); - - await click(".topic-statuses .pin-toggle-button"); - - assert.ok(exists(".topic-statuses .pinned"), "pinned icon is shown"); - assert.ok( - !exists(".topic-statuses .unpinned"), - "unpinned icon is not shown" - ); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/user-menu-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/user-menu-test.js deleted file mode 100644 index 80b776091aa..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/user-menu-test.js +++ /dev/null @@ -1,260 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - query, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import DiscourseURL from "discourse/lib/url"; -import I18n from "I18n"; -import { click } from "@ember/test-helpers"; -import hbs from "htmlbars-inline-precompile"; -import sinon from "sinon"; - -discourseModule( - "Integration | Component | Widget | user-menu", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("basics", { - template: hbs`{{mount-widget widget="user-menu"}}`, - - test(assert) { - assert.ok(exists(".user-menu")); - assert.ok(exists(".user-preferences-link")); - assert.ok(exists(".user-notifications-link")); - assert.ok(exists(".user-bookmarks-link")); - assert.ok(exists(".quick-access-panel")); - assert.ok(exists(".notifications-dismiss")); - }, - }); - - componentTest("notifications", { - template: hbs`{{mount-widget widget="user-menu"}}`, - - async test(assert) { - const $links = queryAll(".quick-access-panel li a"); - - assert.strictEqual($links.length, 6); - assert.ok($links[1].href.includes("/t/a-slug/123")); - - assert.ok( - $links[2].href.includes( - "/u/eviltrout/notifications/likes-received?acting_username=aquaman" - ) - ); - - assert.strictEqual( - $links[2].text, - `aquaman ${I18n.t("notifications.liked_consolidated_description", { - count: 5, - })}` - ); - - assert.ok($links[3].href.includes("/u/test2/messages/group/test")); - assert.ok( - $links[3].innerHTML.includes( - I18n.t("notifications.group_message_summary", { - count: 5, - group_name: "test", - }) - ) - ); - - assert.ok($links[4].href.includes("/u/test1")); - assert.ok( - $links[4].innerHTML.includes( - I18n.t("notifications.invitee_accepted", { username: "test1" }) - ) - ); - - assert.ok($links[5].href.includes("/g/test")); - assert.ok( - $links[5].innerHTML.includes( - I18n.t("notifications.membership_request_accepted", { - group_name: "test", - }) - ) - ); - - const routeToStub = sinon.stub(DiscourseURL, "routeTo"); - await click(".user-notifications-link"); - assert.ok( - routeToStub.calledWith( - queryAll(".user-notifications-link").data("url") - ), - "a second click should redirect to the full notifications page" - ); - }, - }); - - componentTest("log out", { - template: hbs`{{mount-widget widget="user-menu" logout=logout}}`, - - beforeEach() { - this.set("logout", () => (this.loggedOut = true)); - }, - - async test(assert) { - await click(".user-preferences-link"); - - assert.ok(exists(".logout")); - - await click(".logout button"); - assert.ok(this.loggedOut); - }, - }); - - componentTest("private messages - disabled", { - template: hbs`{{mount-widget widget="user-menu"}}`, - beforeEach() { - this.siteSettings.enable_personal_messages = false; - }, - - test(assert) { - assert.ok(!exists(".user-pms-link")); - }, - }); - - componentTest("private messages - enabled", { - template: hbs`{{mount-widget widget="user-menu"}}`, - beforeEach() { - this.siteSettings.enable_personal_messages = true; - }, - - async test(assert) { - const userPmsLink = queryAll(".user-pms-link").data("url"); - assert.ok(userPmsLink); - await click(".user-pms-link"); - - const message = query(".quick-access-panel li a"); - assert.ok(message); - - assert.ok( - message.href.includes("/t/bug-can-not-render-emoji-properly/174/2"), - "should link to the next unread post" - ); - assert.ok( - message.innerHTML.includes("mixtape"), - "should include the last poster's username" - ); - assert.ok( - message.innerHTML.match(//), - "should correctly render emoji in message title" - ); - - const routeToStub = sinon.stub(DiscourseURL, "routeTo"); - await click(".user-pms-link"); - assert.ok( - routeToStub.calledWith(userPmsLink), - "a second click should redirect to the full private messages page" - ); - }, - }); - - componentTest("bookmarks", { - template: hbs`{{mount-widget widget="user-menu"}}`, - - async test(assert) { - await click(".user-bookmarks-link"); - - const allBookmarks = queryAll(".quick-access-panel li a"); - const bookmark = allBookmarks[0]; - - assert.ok( - bookmark.href.includes("/t/yelling-topic-title/119"), - "the Post bookmark should have a link to the topic" - ); - assert.ok( - bookmark.innerHTML.includes("someguy"), - "should include the last poster's username" - ); - assert.ok( - bookmark.innerHTML.match(//), - "should correctly render emoji in bookmark title" - ); - assert.ok( - bookmark.innerHTML.includes("d-icon-bookmark"), - "should use the correct icon based on no reminder_at present" - ); - - const routeToStub = sinon.stub(DiscourseURL, "routeTo"); - await click(".user-bookmarks-link"); - assert.ok( - routeToStub.calledWith(queryAll(".user-bookmarks-link").data("url")), - "a second click should redirect to the full bookmarks page" - ); - - const nonPostBookmarkableBookmark = allBookmarks[1]; - assert.ok( - nonPostBookmarkableBookmark.href.includes("chat/message/2437"), - "bookmarkable_type that is not Post or Topic should use bookmarkable_url for the item link" - ); - assert.ok( - nonPostBookmarkableBookmark.innerHTML.includes( - "d-icon-discourse-bookmark-clock" - ), - "should use the correct icon based on reminder_at present" - ); - }, - }); - - componentTest("anonymous", { - template: hbs` - {{mount-widget widget="user-menu" toggleAnonymous=toggleAnonymous}} - `, - - beforeEach() { - this.currentUser.setProperties({ is_anonymous: false, trust_level: 3 }); - this.siteSettings.allow_anonymous_posting = true; - this.siteSettings.anonymous_posting_min_trust_level = 3; - - this.set("toggleAnonymous", () => (this.anonymous = true)); - }, - - async test(assert) { - await click(".user-preferences-link"); - assert.ok(exists(".enable-anonymous")); - - await click(".enable-anonymous"); - assert.ok(this.anonymous); - }, - }); - - componentTest("anonymous - disabled", { - template: hbs`{{mount-widget widget="user-menu"}}`, - - beforeEach() { - this.siteSettings.allow_anonymous_posting = false; - }, - - async test(assert) { - await click(".user-preferences-link"); - assert.ok(!exists(".enable-anonymous")); - }, - }); - - componentTest("anonymous - switch back", { - template: hbs` - {{mount-widget widget="user-menu" toggleAnonymous=toggleAnonymous}} - `, - - beforeEach() { - this.currentUser.setProperties({ is_anonymous: true }); - this.siteSettings.allow_anonymous_posting = true; - - this.set("toggleAnonymous", () => (this.anonymous = false)); - }, - - async test(assert) { - await click(".user-preferences-link"); - assert.ok(exists(".disable-anonymous")); - - await click(".disable-anonymous"); - assert.notOk(this.anonymous); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/widget-dropdown-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/widget-dropdown-test.js deleted file mode 100644 index b6942f5d16b..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/widget-dropdown-test.js +++ /dev/null @@ -1,383 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - query, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import I18n from "I18n"; -import { click } from "@ember/test-helpers"; -import hbs from "htmlbars-inline-precompile"; - -const DEFAULT_CONTENT = { - content: [ - { id: 1, label: "foo" }, - { id: 2, translatedLabel: "FooBar" }, - "separator", - { id: 3, translatedLabel: "With icon", icon: "times" }, - { id: 4, html: "baz" }, - { id: 5, translatedLabel: "Disabled", disabled: true }, - ], - label: "foo", -}; - -async function clickRowById(id) { - await click(`#my-dropdown .widget-dropdown-item.item-${id}`); -} - -function rowById(id) { - return query(`#my-dropdown .widget-dropdown-item.item-${id}`); -} - -async function toggle() { - await click("#my-dropdown .widget-dropdown-header"); -} - -function headerLabel() { - return queryAll( - "#my-dropdown .widget-dropdown-header .label" - )[0].innerText.trim(); -} - -function header() { - return query("#my-dropdown .widget-dropdown-header"); -} - -function body() { - return query("#my-dropdown .widget-dropdown-body"); -} - -const TEMPLATE = hbs` - {{mount-widget - widget="widget-dropdown" - args=(hash - id="my-dropdown" - icon=icon - label=label - class=class - translatedLabel=translatedLabel - content=content - options=options - ) -}}`; - -discourseModule( - "Integration | Component | Widget | widget-dropdown", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("dropdown id", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - }, - - test(assert) { - assert.ok(exists("#my-dropdown")); - }, - }); - - componentTest("label", { - template: TEMPLATE, - - _translations: I18n.translations, - - beforeEach() { - I18n.translations = { en: { js: { foo: "FooBaz" } } }; - this.setProperties(DEFAULT_CONTENT); - }, - - afterEach() { - I18n.translations = this._translations; - }, - - test(assert) { - assert.strictEqual(headerLabel(), "FooBaz"); - }, - }); - - componentTest("translatedLabel", { - template: TEMPLATE, - - _translations: I18n.translations, - - beforeEach() { - I18n.translations = { en: { js: { foo: "FooBaz" } } }; - this.setProperties(DEFAULT_CONTENT); - this.set("translatedLabel", "BazFoo"); - }, - - afterEach() { - I18n.translations = this._translations; - }, - - test(assert) { - assert.strictEqual(headerLabel(), this.translatedLabel); - }, - }); - - componentTest("content", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - }, - - async test(assert) { - await toggle(); - assert.strictEqual(rowById(1).dataset.id, "1", "it creates rows"); - assert.strictEqual(rowById(2).dataset.id, "2", "it creates rows"); - assert.strictEqual(rowById(3).dataset.id, "3", "it creates rows"); - }, - }); - - componentTest("onChange action", { - template: hbs` -
    - {{mount-widget - widget="widget-dropdown" - args=(hash - id="my-dropdown" - label=label - content=content - onChange=onChange - ) - }} - `, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - - this.set("onChange", (item) => (query("#test").innerText = item.id)); - }, - - async test(assert) { - await toggle(); - await clickRowById(2); - assert.strictEqual( - queryAll("#test").text(), - "2", - "it calls the onChange actions" - ); - }, - }); - - componentTest("can be opened and closed", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - }, - - async test(assert) { - assert.ok(exists("#my-dropdown.closed")); - assert.ok(!exists("#my-dropdown .widget-dropdown-body")); - await toggle(); - assert.strictEqual(rowById(2).innerText.trim(), "FooBar"); - assert.ok(exists("#my-dropdown.opened")); - assert.ok(exists("#my-dropdown .widget-dropdown-body")); - await toggle(); - assert.ok(exists("#my-dropdown.closed")); - assert.ok(!exists("#my-dropdown .widget-dropdown-body")); - }, - }); - - componentTest("icon", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - this.set("icon", "times"); - }, - - test(assert) { - assert.ok(exists(header().querySelector(".d-icon-times"))); - }, - }); - - componentTest("class", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - this.set("class", "activated"); - }, - - test(assert) { - assert.ok(exists("#my-dropdown.activated")); - }, - }); - - componentTest("content with translatedLabel", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - }, - - async test(assert) { - await toggle(); - assert.strictEqual(rowById(2).innerText.trim(), "FooBar"); - }, - }); - - componentTest("content with label", { - template: TEMPLATE, - - _translations: I18n.translations, - - beforeEach() { - I18n.translations = { en: { js: { foo: "FooBaz" } } }; - this.setProperties(DEFAULT_CONTENT); - }, - - afterEach() { - I18n.translations = this._translations; - }, - - async test(assert) { - await toggle(); - assert.strictEqual(rowById(1).innerText.trim(), "FooBaz"); - }, - }); - - componentTest("content with icon", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - }, - - async test(assert) { - await toggle(); - assert.ok(exists(rowById(3).querySelector(".d-icon-times"))); - }, - }); - - componentTest("content with html", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - }, - - async test(assert) { - await toggle(); - assert.strictEqual( - rowById(4).innerHTML.trim(), - "baz" - ); - }, - }); - - componentTest("separator", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - }, - - async test(assert) { - await toggle(); - assert.ok( - queryAll( - "#my-dropdown .widget-dropdown-item:nth-child(3)" - )[0].classList.contains("separator") - ); - }, - }); - - componentTest("hides widget if no content", { - template: TEMPLATE, - - beforeEach() { - this.setProperties({ content: null, label: "foo" }); - }, - - test(assert) { - assert.notOk(exists("#my-dropdown .widget-dropdown-header")); - assert.notOk(exists("#my-dropdown .widget-dropdown-body")); - }, - }); - - componentTest("headerClass option", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - this.set("options", { headerClass: "btn-small and-text" }); - }, - - test(assert) { - assert.ok(header().classList.contains("widget-dropdown-header")); - assert.ok(header().classList.contains("btn-small")); - assert.ok(header().classList.contains("and-text")); - }, - }); - - componentTest("bodyClass option", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - this.set("options", { bodyClass: "gigantic and-yet-small" }); - }, - - async test(assert) { - await toggle(); - assert.ok(body().classList.contains("widget-dropdown-body")); - assert.ok(body().classList.contains("gigantic")); - assert.ok(body().classList.contains("and-yet-small")); - }, - }); - - componentTest("caret option", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - this.set("options", { caret: true }); - }, - - test(assert) { - assert.ok( - exists("#my-dropdown .widget-dropdown-header .d-icon-caret-down") - ); - }, - }); - - componentTest("disabled widget", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - this.set("options", { disabled: true }); - }, - - test(assert) { - assert.ok(exists("#my-dropdown.disabled")); - }, - - async test(assert) { - await toggle(); - assert.strictEqual(rowById(1), null, "it does not display options"); - }, - }); - - componentTest("disabled item", { - template: TEMPLATE, - - beforeEach() { - this.setProperties(DEFAULT_CONTENT); - }, - - async test(assert) { - await toggle(); - assert.ok(exists(".widget-dropdown-item.item-5.disabled")); - }, - }); - } -); diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/widget-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/widget-test.js deleted file mode 100644 index 465cf66be40..00000000000 --- a/app/assets/javascripts/discourse/tests/integration/widgets/widget-test.js +++ /dev/null @@ -1,482 +0,0 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - count, - discourseModule, - exists, - query, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import I18n from "I18n"; -import { Promise } from "rsvp"; -import { click } from "@ember/test-helpers"; -import { createWidget } from "discourse/widgets/widget"; -import hbs from "htmlbars-inline-precompile"; -import widgetHbs from "discourse/widgets/hbs-compiler"; -import { next } from "@ember/runloop"; -import { withPluginApi } from "discourse/lib/plugin-api"; - -discourseModule("Integration | Component | Widget | base", function (hooks) { - setupRenderingTest(hooks); - - componentTest("widget attributes are passed in via args", { - template: hbs`{{mount-widget widget="hello-test" args=args}}`, - - beforeEach() { - createWidget("hello-test", { - tagName: "div.test", - template: widgetHbs`Hello {{attrs.name}}`, - }); - - this.set("args", { name: "Robin" }); - }, - - test(assert) { - assert.strictEqual(queryAll(".test").text(), "Hello Robin"); - }, - }); - - componentTest("widget services", { - template: hbs`{{mount-widget widget="service-test"}}`, - - beforeEach() { - createWidget("service-test", { - tagName: "div.base-url-test", - services: ["router"], - html() { - return this.router.rootURL; - }, - }); - }, - - test(assert) { - assert.strictEqual(queryAll(".base-url-test").text(), "/"); - }, - }); - - componentTest("hbs template - no tagName", { - template: hbs`{{mount-widget widget="hbs-test" args=args}}`, - - beforeEach() { - createWidget("hbs-test", { - template: widgetHbs`
    Hello {{attrs.name}}
    `, - }); - - this.set("args", { name: "Robin" }); - }, - - test(assert) { - assert.strictEqual(queryAll("div.test").text(), "Hello Robin"); - }, - }); - - componentTest("hbs template - with tagName", { - template: hbs`{{mount-widget widget="hbs-test" args=args}}`, - - beforeEach() { - createWidget("hbs-test", { - tagName: "div.test", - template: widgetHbs`Hello {{attrs.name}}`, - }); - - this.set("args", { name: "Robin" }); - }, - - test(assert) { - assert.strictEqual(queryAll("div.test").text(), "Hello Robin"); - }, - }); - - componentTest("hbs template - with data attributes", { - template: hbs`{{mount-widget widget="hbs-test" args=args}}`, - - beforeEach() { - createWidget("hbs-test", { - template: widgetHbs`
    `, - }); - }, - - test(assert) { - assert.strictEqual(queryAll("div.mydiv").data("my-test"), "hello world"); - }, - }); - - componentTest("buildClasses", { - template: hbs`{{mount-widget widget="classname-test" args=args}}`, - - beforeEach() { - createWidget("classname-test", { - tagName: "div.test", - - buildClasses(attrs) { - return ["static", attrs.dynamic]; - }, - }); - - this.set("args", { dynamic: "cool-class" }); - }, - - test(assert) { - assert.ok(exists(".test.static.cool-class"), "it has all the classes"); - }, - }); - - componentTest("buildAttributes", { - template: hbs`{{mount-widget widget="attributes-test" args=args}}`, - - beforeEach() { - createWidget("attributes-test", { - tagName: "div.test", - - buildAttributes(attrs) { - return { "data-evil": "trout", "aria-label": attrs.label }; - }, - }); - - this.set("args", { label: "accessibility" }); - }, - - test(assert) { - assert.ok(exists('.test[data-evil="trout"]')); - assert.ok(exists('.test[aria-label="accessibility"]')); - }, - }); - - componentTest("buildId", { - template: hbs`{{mount-widget widget="id-test" args=args}}`, - - beforeEach() { - createWidget("id-test", { - buildId(attrs) { - return `test-${attrs.id}`; - }, - }); - - this.set("args", { id: 1234 }); - }, - - test(assert) { - assert.ok(exists("#test-1234")); - }, - }); - - componentTest("widget state", { - template: hbs`{{mount-widget widget="state-test"}}`, - - beforeEach() { - createWidget("state-test", { - tagName: "button.test", - buildKey: () => `button-test`, - template: widgetHbs`{{state.clicks}} clicks`, - - defaultState() { - return { clicks: 0 }; - }, - - click() { - this.state.clicks++; - }, - }); - }, - - async test(assert) { - assert.ok(exists("button.test"), "it renders the button"); - assert.strictEqual(queryAll("button.test").text(), "0 clicks"); - - await click(query("button")); - assert.strictEqual(queryAll("button.test").text(), "1 clicks"); - }, - }); - - componentTest("widget update with promise", { - template: hbs`{{mount-widget widget="promise-test"}}`, - - beforeEach() { - createWidget("promise-test", { - tagName: "button.test", - buildKey: () => "promise-test", - template: widgetHbs` - {{#if state.name}} - {{state.name}} - {{else}} - No name - {{/if}} - `, - - click() { - return new Promise((resolve) => { - next(() => { - this.state.name = "Robin"; - resolve(); - }); - }); - }, - }); - }, - - async test(assert) { - assert.strictEqual(queryAll("button.test").text().trim(), "No name"); - - await click(query("button")); - assert.strictEqual(queryAll("button.test").text().trim(), "Robin"); - }, - }); - - componentTest("widget attaching", { - template: hbs`{{mount-widget widget="attach-test"}}`, - - beforeEach() { - createWidget("test-embedded", { tagName: "div.embedded" }); - - createWidget("attach-test", { - tagName: "div.container", - template: widgetHbs`{{attach widget="test-embedded" attrs=attrs}}`, - }); - }, - - test(assert) { - assert.ok(exists(".container"), "renders container"); - assert.ok(exists(".container .embedded"), "renders attached"); - }, - }); - - componentTest("magic attaching by name", { - template: hbs`{{mount-widget widget="attach-test"}}`, - - beforeEach() { - createWidget("test-embedded", { tagName: "div.embedded" }); - - createWidget("attach-test", { - tagName: "div.container", - template: widgetHbs`{{test-embedded attrs=attrs}}`, - }); - }, - - test(assert) { - assert.ok(exists(".container"), "renders container"); - assert.ok(exists(".container .embedded"), "renders attached"); - }, - }); - - componentTest("custom attrs to a magic attached widget", { - template: hbs`{{mount-widget widget="attach-test"}}`, - - beforeEach() { - createWidget("testing", { - tagName: "span.value", - template: widgetHbs`{{attrs.value}}`, - }); - - createWidget("attach-test", { - tagName: "div.container", - template: widgetHbs`{{testing value=(concat "hello" " " "world")}}`, - }); - }, - - test(assert) { - assert.ok(exists(".container"), "renders container"); - assert.strictEqual(queryAll(".container .value").text(), "hello world"); - }, - }); - - componentTest("using transformed values in a subexpression", { - template: hbs`{{mount-widget widget="attach-test"}}`, - - beforeEach() { - createWidget("testing", { - tagName: "span.value", - template: widgetHbs`{{attrs.value}}`, - }); - - createWidget("attach-test", { - transform() { - return { someValue: "world" }; - }, - tagName: "div.container", - template: widgetHbs`{{testing value=(concat "hello" " " transformed.someValue)}}`, - }); - }, - - test(assert) { - assert.ok(queryAll(".container").length, "renders container"); - assert.strictEqual(queryAll(".container .value").text(), "hello world"); - }, - }); - - componentTest("handlebars d-icon", { - template: hbs`{{mount-widget widget="hbs-icon-test" args=args}}`, - - beforeEach() { - createWidget("hbs-icon-test", { - template: widgetHbs`{{d-icon "arrow-down"}}`, - }); - }, - - test(assert) { - assert.strictEqual(count(".d-icon-arrow-down"), 1); - }, - }); - - componentTest("handlebars i18n", { - _translations: I18n.translations, - - template: hbs`{{mount-widget widget="hbs-i18n-test" args=args}}`, - - beforeEach() { - createWidget("hbs-i18n-test", { - template: widgetHbs` - {{i18n "hbs_test0"}} - {{i18n attrs.key}} - test - `, - }); - I18n.translations = { - en: { - js: { - hbs_test0: "evil", - hbs_test1: "trout", - }, - }, - }; - this.set("args", { key: "hbs_test1" }); - }, - - afterEach() { - I18n.translations = this._translations; - }, - - test(assert) { - // coming up - assert.strictEqual(queryAll("span.string").text(), "evil"); - assert.strictEqual(queryAll("span.var").text(), "trout"); - assert.strictEqual(queryAll("a").prop("title"), "evil"); - }, - }); - - componentTest("handlebars #each", { - template: hbs`{{mount-widget widget="hbs-each-test" args=args}}`, - - beforeEach() { - createWidget("hbs-each-test", { - tagName: "ul", - template: widgetHbs` - {{#each attrs.items as |item|}} -
  • {{item}}
  • - {{/each}} - `, - }); - - this.set("args", { - items: ["one", "two", "three"], - }); - }, - - test(assert) { - assert.strictEqual(count("ul li"), 3); - assert.strictEqual(queryAll("ul li:nth-of-type(1)").text(), "one"); - }, - }); - - componentTest("widget decorating", { - template: hbs`{{mount-widget widget="decorate-test"}}`, - - beforeEach() { - createWidget("decorate-test", { - tagName: "div.decorate", - template: widgetHbs`main content`, - }); - - withPluginApi("0.1", (api) => { - api.decorateWidget("decorate-test:before", (dec) => { - return dec.h("b", "before"); - }); - - api.decorateWidget("decorate-test:after", (dec) => { - return dec.h("i", "after"); - }); - }); - }, - - test(assert) { - assert.ok(exists(".decorate")); - assert.strictEqual(queryAll(".decorate b").text(), "before"); - assert.strictEqual(queryAll(".decorate i").text(), "after"); - }, - }); - - componentTest("widget settings", { - template: hbs`{{mount-widget widget="settings-test"}}`, - - beforeEach() { - createWidget("settings-test", { - tagName: "div.settings", - template: widgetHbs`age is {{settings.age}}`, - settings: { age: 36 }, - }); - }, - - test(assert) { - assert.strictEqual(queryAll(".settings").text(), "age is 36"); - }, - }); - - componentTest("override settings", { - template: hbs`{{mount-widget widget="ov-settings-test"}}`, - - beforeEach() { - createWidget("ov-settings-test", { - tagName: "div.settings", - template: widgetHbs`age is {{settings.age}}`, - settings: { age: 36 }, - }); - - withPluginApi("0.1", (api) => { - api.changeWidgetSetting("ov-settings-test", "age", 37); - }); - }, - - test(assert) { - assert.strictEqual(queryAll(".settings").text(), "age is 37"); - }, - }); - - componentTest("get accessor", { - template: hbs`{{mount-widget widget="get-accessor-test"}}`, - - beforeEach() { - createWidget("get-accessor-test", { - tagName: "div.test", - template: widgetHbs`Hello {{transformed.name}}`, - transform() { - return { - name: this.get("currentUser.username"), - }; - }, - }); - }, - - test(assert) { - assert.strictEqual(queryAll("div.test").text(), "Hello eviltrout"); - }, - }); - - componentTest("tagName", { - template: hbs`{{mount-widget widget="tag-name-override-test"}}`, - - beforeEach() { - createWidget("test-override", { tagName: "div.not-override" }); - - createWidget("tag-name-override-test", { - template: widgetHbs`{{attach widget="test-override" attrs=attrs otherOpts=(hash tagName="section.override")}}`, - }); - }, - - test(assert) { - assert.ok( - exists("section.override"), - "renders container with overridden tagName" - ); - }, - }); -}); diff --git a/plugins/poll/test/javascripts/widgets/discourse-poll-option-test.js b/plugins/poll/test/javascripts/widgets/discourse-poll-option-test.js index bb900876468..2e77e1b1a16 100644 --- a/plugins/poll/test/javascripts/widgets/discourse-poll-option-test.js +++ b/plugins/poll/test/javascripts/widgets/discourse-poll-option-test.js @@ -1,82 +1,68 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; +import { count } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule( +module( "Integration | Component | Widget | discourse-poll-option", function (hooks) { setupRenderingTest(hooks); - const template = hbs`{{mount-widget - widget="discourse-poll-option" - args=(hash option=option isMultiple=isMultiple vote=vote)}}`; - componentTest("single, not selected", { - template, + const template = hbs` + + `; - beforeEach() { - this.set("option", { id: "opt-id" }); - this.set("vote", []); - }, + test("single, not selected", async function (assert) { + this.set("option", { id: "opt-id" }); + this.set("vote", []); - test(assert) { - assert.ok( - queryAll("li .d-icon-far-circle:nth-of-type(1)").length === 1 - ); - }, + await render(template); + + assert.strictEqual(count("li .d-icon-far-circle:nth-of-type(1)"), 1); }); - componentTest("single, selected", { - template, + test("single, selected", async function (assert) { + this.set("option", { id: "opt-id" }); + this.set("vote", ["opt-id"]); - beforeEach() { - this.set("option", { id: "opt-id" }); - this.set("vote", ["opt-id"]); - }, + await render(template); - test(assert) { - assert.ok(queryAll("li .d-icon-circle:nth-of-type(1)").length === 1); - }, + assert.strictEqual(count("li .d-icon-circle:nth-of-type(1)"), 1); }); - componentTest("multi, not selected", { - template, + test("multi, not selected", async function (assert) { + this.setProperties({ + option: { id: "opt-id" }, + isMultiple: true, + vote: [], + }); - beforeEach() { - this.setProperties({ - option: { id: "opt-id" }, - isMultiple: true, - vote: [], - }); - }, + await render(template); - test(assert) { - assert.ok( - queryAll("li .d-icon-far-square:nth-of-type(1)").length === 1 - ); - }, + assert.strictEqual(count("li .d-icon-far-square:nth-of-type(1)"), 1); }); - componentTest("multi, selected", { - template, + test("multi, selected", async function (assert) { + this.setProperties({ + option: { id: "opt-id" }, + isMultiple: true, + vote: ["opt-id"], + }); - beforeEach() { - this.setProperties({ - option: { id: "opt-id" }, - isMultiple: true, - vote: ["opt-id"], - }); - }, + await render(template); - test(assert) { - assert.ok( - queryAll("li .d-icon-far-check-square:nth-of-type(1)").length === 1 - ); - }, + assert.strictEqual( + count("li .d-icon-far-check-square:nth-of-type(1)"), + 1 + ); }); } ); diff --git a/plugins/poll/test/javascripts/widgets/discourse-poll-standard-results-test.js b/plugins/poll/test/javascripts/widgets/discourse-poll-standard-results-test.js index 59dff66e234..43b3273c65a 100644 --- a/plugins/poll/test/javascripts/widgets/discourse-poll-standard-results-test.js +++ b/plugins/poll/test/javascripts/widgets/discourse-poll-standard-results-test.js @@ -1,98 +1,86 @@ -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { render } from "@ember/test-helpers"; import EmberObject from "@ember/object"; -import { - discourseModule, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; +import { queryAll } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; -discourseModule( +module( "Integration | Component | Widget | discourse-poll-standard-results", function (hooks) { setupRenderingTest(hooks); - const template = hbs`{{mount-widget - widget="discourse-poll-standard-results" - args=(hash poll=poll isMultiple=isMultiple)}}`; + const template = hbs` + + `; - componentTest("options in descending order", { - template, + test("options in descending order", async function (assert) { + this.set( + "poll", + EmberObject.create({ + options: [{ votes: 5 }, { votes: 4 }], + voters: 9, + }) + ); - beforeEach() { - this.set( - "poll", - EmberObject.create({ - options: [{ votes: 5 }, { votes: 4 }], - voters: 9, - }) - ); - }, + await render(template); - test(assert) { - assert.strictEqual(queryAll(".option .percentage")[0].innerText, "56%"); - assert.strictEqual(queryAll(".option .percentage")[1].innerText, "44%"); - }, + assert.strictEqual(queryAll(".option .percentage")[0].innerText, "56%"); + assert.strictEqual(queryAll(".option .percentage")[1].innerText, "44%"); }); - componentTest("options in ascending order", { - template, + test("options in ascending order", async function (assert) { + this.set( + "poll", + EmberObject.create({ + options: [{ votes: 4 }, { votes: 5 }], + voters: 9, + }) + ); - beforeEach() { - this.set( - "poll", - EmberObject.create({ - options: [{ votes: 4 }, { votes: 5 }], - voters: 9, - }) - ); - }, + await render(template); - test(assert) { - assert.strictEqual(queryAll(".option .percentage")[0].innerText, "56%"); - assert.strictEqual(queryAll(".option .percentage")[1].innerText, "44%"); - }, + assert.strictEqual(queryAll(".option .percentage")[0].innerText, "56%"); + assert.strictEqual(queryAll(".option .percentage")[1].innerText, "44%"); }); - componentTest("multiple options in descending order", { - template, + test("multiple options in descending order", async function (assert) { + this.set("isMultiple", true); + this.set( + "poll", + EmberObject.create({ + type: "multiple", + options: [ + { votes: 5, html: "a" }, + { votes: 2, html: "b" }, + { votes: 4, html: "c" }, + { votes: 1, html: "b" }, + { votes: 1, html: "a" }, + ], + voters: 12, + }) + ); - beforeEach() { - this.set("isMultiple", true); - this.set( - "poll", - EmberObject.create({ - type: "multiple", - options: [ - { votes: 5, html: "a" }, - { votes: 2, html: "b" }, - { votes: 4, html: "c" }, - { votes: 1, html: "b" }, - { votes: 1, html: "a" }, - ], - voters: 12, - }) - ); - }, + await render(template); - test(assert) { - let percentages = queryAll(".option .percentage"); - assert.strictEqual(percentages[0].innerText, "41%"); - assert.strictEqual(percentages[1].innerText, "33%"); - assert.strictEqual(percentages[2].innerText, "16%"); - assert.strictEqual(percentages[3].innerText, "8%"); + let percentages = queryAll(".option .percentage"); + assert.strictEqual(percentages[0].innerText, "41%"); + assert.strictEqual(percentages[1].innerText, "33%"); + assert.strictEqual(percentages[2].innerText, "16%"); + assert.strictEqual(percentages[3].innerText, "8%"); - assert.strictEqual( - queryAll(".option")[3].querySelectorAll("span")[1].innerText, - "a" - ); - assert.strictEqual(percentages[4].innerText, "8%"); - assert.strictEqual( - queryAll(".option")[4].querySelectorAll("span")[1].innerText, - "b" - ); - }, + assert.strictEqual( + queryAll(".option")[3].querySelectorAll("span")[1].innerText, + "a" + ); + assert.strictEqual(percentages[4].innerText, "8%"); + assert.strictEqual( + queryAll(".option")[4].querySelectorAll("span")[1].innerText, + "b" + ); }); } ); diff --git a/plugins/poll/test/javascripts/widgets/discourse-poll-test.js b/plugins/poll/test/javascripts/widgets/discourse-poll-test.js index b0e8411f072..1edf00c55fb 100644 --- a/plugins/poll/test/javascripts/widgets/discourse-poll-test.js +++ b/plugins/poll/test/javascripts/widgets/discourse-poll-test.js @@ -1,195 +1,172 @@ -import { - count, - discourseModule, - exists, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { count, exists, query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import pretender from "discourse/tests/helpers/create-pretender"; import EmberObject from "@ember/object"; import I18n from "I18n"; -import pretender from "discourse/tests/helpers/create-pretender"; -import hbs from "htmlbars-inline-precompile"; -import { click } from "@ember/test-helpers"; let requests = 0; -discourseModule( - "Integration | Component | Widget | discourse-poll", - function (hooks) { - setupRenderingTest(hooks); +module("Integration | Component | Widget | discourse-poll", function (hooks) { + setupRenderingTest(hooks); - pretender.put("/polls/vote", () => { - ++requests; - return [ - 200, - { "Content-Type": "application/json" }, - { - poll: { - name: "poll", - type: "regular", - status: "open", - results: "always", - options: [ - { - id: "1f972d1df351de3ce35a787c89faad29", - html: "yes", - votes: 1, - }, - { - id: "d7ebc3a9beea2e680815a1e4f57d6db6", - html: "no", - votes: 0, - }, - ], - voters: 1, - chart_type: "bar", - }, - vote: ["1f972d1df351de3ce35a787c89faad29"], + pretender.put("/polls/vote", () => { + ++requests; + return [ + 200, + { "Content-Type": "application/json" }, + { + poll: { + name: "poll", + type: "regular", + status: "open", + results: "always", + options: [ + { + id: "1f972d1df351de3ce35a787c89faad29", + html: "yes", + votes: 1, + }, + { + id: "d7ebc3a9beea2e680815a1e4f57d6db6", + html: "no", + votes: 0, + }, + ], + voters: 1, + chart_type: "bar", }, - ]; + vote: ["1f972d1df351de3ce35a787c89faad29"], + }, + ]; + }); + + const template = hbs` + + `; + + test("can vote", async function (assert) { + this.setProperties({ + post: EmberObject.create({ + id: 42, + topic: { + archived: false, + }, + }), + poll: EmberObject.create({ + name: "poll", + type: "regular", + status: "open", + results: "always", + options: [ + { id: "1f972d1df351de3ce35a787c89faad29", html: "yes", votes: 0 }, + { id: "d7ebc3a9beea2e680815a1e4f57d6db6", html: "no", votes: 0 }, + ], + voters: 0, + chart_type: "bar", + }), + vote: [], + groupableUserFields: [], }); - const template = hbs`{{mount-widget - widget="discourse-poll" - args=(hash id=id - post=post - poll=poll - vote=vote - groupableUserFields=groupableUserFields)}}`; + await render(template); - componentTest("can vote", { - template, + requests = 0; - beforeEach() { - this.setProperties({ - post: EmberObject.create({ - id: 42, - topic: { - archived: false, - }, - }), - poll: EmberObject.create({ - name: "poll", - type: "regular", - status: "open", - results: "always", - options: [ - { id: "1f972d1df351de3ce35a787c89faad29", html: "yes", votes: 0 }, - { id: "d7ebc3a9beea2e680815a1e4f57d6db6", html: "no", votes: 0 }, - ], - voters: 0, - chart_type: "bar", - }), - vote: [], - groupableUserFields: [], - }); - }, + await click("li[data-poll-option-id='1f972d1df351de3ce35a787c89faad29']"); + assert.strictEqual(requests, 1); + assert.strictEqual(count(".chosen"), 1); + assert.strictEqual(query(".chosen").innerText, "100%yes"); - async test(assert) { - requests = 0; + await click(".toggle-results"); + assert.strictEqual( + count("li[data-poll-option-id='1f972d1df351de3ce35a787c89faad29']"), + 1 + ); + }); - await click( - "li[data-poll-option-id='1f972d1df351de3ce35a787c89faad29']" - ); - assert.strictEqual(requests, 1); - assert.strictEqual(count(".chosen"), 1); - assert.strictEqual(queryAll(".chosen").text(), "100%yes"); - - await click(".toggle-results"); - assert.strictEqual( - queryAll("li[data-poll-option-id='1f972d1df351de3ce35a787c89faad29']") - .length, - 1 - ); - }, + test("cannot vote if not member of the right group", async function (assert) { + this.setProperties({ + post: EmberObject.create({ + id: 42, + topic: { + archived: false, + }, + }), + poll: EmberObject.create({ + name: "poll", + type: "regular", + status: "open", + results: "always", + options: [ + { id: "1f972d1df351de3ce35a787c89faad29", html: "yes", votes: 0 }, + { id: "d7ebc3a9beea2e680815a1e4f57d6db6", html: "no", votes: 0 }, + ], + voters: 0, + chart_type: "bar", + groups: "foo", + }), + vote: [], + groupableUserFields: [], }); - componentTest("cannot vote if not member of the right group", { - template, + await render(template); - beforeEach() { - this.setProperties({ - post: EmberObject.create({ - id: 42, - topic: { - archived: false, - }, - }), - poll: EmberObject.create({ - name: "poll", - type: "regular", - status: "open", - results: "always", - options: [ - { id: "1f972d1df351de3ce35a787c89faad29", html: "yes", votes: 0 }, - { id: "d7ebc3a9beea2e680815a1e4f57d6db6", html: "no", votes: 0 }, - ], - voters: 0, - chart_type: "bar", - groups: "foo", - }), - vote: [], - groupableUserFields: [], - }); - }, + requests = 0; - async test(assert) { - requests = 0; + await click("li[data-poll-option-id='1f972d1df351de3ce35a787c89faad29']"); + assert.strictEqual( + query(".poll-container .alert").innerText, + I18n.t("poll.results.groups.title", { groups: "foo" }) + ); + assert.strictEqual(requests, 0); + assert.ok(!exists(".chosen")); + }); - await click( - "li[data-poll-option-id='1f972d1df351de3ce35a787c89faad29']" - ); - assert.strictEqual( - queryAll(".poll-container .alert").text(), - I18n.t("poll.results.groups.title", { groups: "foo" }) - ); - assert.strictEqual(requests, 0); - assert.ok(!exists(".chosen")); - }, + test("voting on a multiple poll with no min attribute", async function (assert) { + this.setProperties({ + post: EmberObject.create({ + id: 42, + topic: { + archived: false, + }, + }), + poll: EmberObject.create({ + name: "poll", + type: "multiple", + status: "open", + results: "always", + max: 2, + options: [ + { id: "1f972d1df351de3ce35a787c89faad29", html: "yes", votes: 0 }, + { id: "d7ebc3a9beea2e680815a1e4f57d6db6", html: "no", votes: 0 }, + ], + voters: 0, + chart_type: "bar", + }), + vote: [], + groupableUserFields: [], }); - componentTest("voting on a multiple poll with no min attribute", { - template, + await render(template); - beforeEach() { - this.setProperties({ - post: EmberObject.create({ - id: 42, - topic: { - archived: false, - }, - }), - poll: EmberObject.create({ - name: "poll", - type: "multiple", - status: "open", - results: "always", - max: 2, - options: [ - { id: "1f972d1df351de3ce35a787c89faad29", html: "yes", votes: 0 }, - { id: "d7ebc3a9beea2e680815a1e4f57d6db6", html: "no", votes: 0 }, - ], - voters: 0, - chart_type: "bar", - }), - vote: [], - groupableUserFields: [], - }); - }, + assert.ok(exists(".poll-buttons .cast-votes[disabled=true]")); - async test(assert) { - assert.ok(exists(".poll-buttons .cast-votes[disabled=true]")); + await click("li[data-poll-option-id='1f972d1df351de3ce35a787c89faad29']"); - await click( - "li[data-poll-option-id='1f972d1df351de3ce35a787c89faad29']" - ); + await click(".poll-buttons .cast-votes"); - await click(".poll-buttons .cast-votes"); - - assert.ok(exists(".chosen")); - }, - }); - } -); + assert.ok(exists(".chosen")); + }); +});