diff --git a/app/assets/javascripts/discourse/tests/acceptance/composer-actions-test.js b/app/assets/javascripts/discourse/tests/acceptance/composer-actions-test.js index 13cbb7ce3d7..ea6ac67b006 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/composer-actions-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/composer-actions-test.js @@ -356,32 +356,28 @@ acceptance("Composer Actions", function (needs) { assert.equal(composerActions.rows().length, 1); assert.equal(composerActions.rowByIndex(0).value(), "reply_to_post"); }); +}); - acceptance("Composer Actions With New Topic Draft", { - loggedIn: true, - settings: { - enable_whispers: true, - }, - site: { - can_tag_topics: true, - }, - beforeEach() { - _clearSnapshots(); - }, - afterEach() { - _clearSnapshots(); - }, +function stubDraftResponse() { + sandbox.stub(Draft, "get").returns( + Promise.resolve({ + draft: + '{"reply":"dum de dum da ba.","action":"createTopic","title":"dum da ba dum dum","categoryId":null,"archetypeId":"regular","metaData":null,"composerTime":540879,"typingTime":3400}', + draft_sequence: 0, + }) + ); +} + +acceptance("Composer Actions With New Topic Draft", function (needs) { + needs.user(); + needs.settings({ + enable_whispers: true, }); - - const stubDraftResponse = () => { - sandbox.stub(Draft, "get").returns( - Promise.resolve({ - draft: - '{"reply":"dum de dum da ba.","action":"createTopic","title":"dum da ba dum dum","categoryId":null,"archetypeId":"regular","metaData":null,"composerTime":540879,"typingTime":3400}', - draft_sequence: 0, - }) - ); - }; + needs.site({ + can_tag_topics: true, + }); + needs.hooks.beforeEach(() => _clearSnapshots()); + needs.hooks.afterEach(() => _clearSnapshots()); test("shared draft", async (assert) => { stubDraftResponse(); diff --git a/app/assets/javascripts/discourse/tests/acceptance/composer-test.js b/app/assets/javascripts/discourse/tests/acceptance/composer-test.js index b026d473e4e..49f20fb8c95 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/composer-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/composer-test.js @@ -9,805 +9,821 @@ import { toggleCheckDraftPopup } from "discourse/controllers/composer"; import Draft from "discourse/models/draft"; import { Promise } from "rsvp"; -acceptance("Composer", { - loggedIn: true, - pretend(server, helper) { +acceptance("Composer", function (needs) { + needs.user(); + needs.settings({ enable_whispers: true }); + needs.pretender((server, helper) => { server.post("/uploads/lookup-urls", () => { return helper.response([]); }); - }, - settings: { - enable_whispers: true, - }, -}); - -skip("Tests the Composer controls", async (assert) => { - await visit("/"); - assert.ok(exists("#create-topic"), "the create button is visible"); - - await click("#create-topic"); - assert.ok(exists(".d-editor-input"), "the composer input is visible"); - assert.ok( - exists(".title-input .popup-tip.bad.hide"), - "title errors are hidden by default" - ); - assert.ok( - exists(".d-editor-textarea-wrapper .popup-tip.bad.hide"), - "body errors are hidden by default" - ); - - await click("a.toggle-preview"); - assert.ok( - !exists(".d-editor-preview:visible"), - "clicking the toggle hides the preview" - ); - - await click("a.toggle-preview"); - assert.ok( - exists(".d-editor-preview:visible"), - "clicking the toggle shows the preview again" - ); - - await click("#reply-control button.create"); - assert.ok( - !exists(".title-input .popup-tip.bad.hide"), - "it shows the empty title error" - ); - assert.ok( - !exists(".d-editor-wrapper .popup-tip.bad.hide"), - "it shows the empty body error" - ); - - await fillIn("#reply-title", "this is my new topic title"); - assert.ok(exists(".title-input .popup-tip.good"), "the title is now good"); - - await fillIn(".d-editor-input", "this is the *content* of a post"); - assert.equal( - find(".d-editor-preview").html().trim(), - "

this is the content of a post

", - "it previews content" - ); - assert.ok( - exists(".d-editor-textarea-wrapper .popup-tip.good"), - "the body is now good" - ); - - const textarea = find("#reply-control .d-editor-input")[0]; - textarea.selectionStart = textarea.value.length; - textarea.selectionEnd = textarea.value.length; - - // Testing keyboard events is tough! - const mac = /Mac|iPod|iPhone|iPad/.test(navigator.platform); - const event = document.createEvent("Event"); - event.initEvent("keydown", true, true); - event[mac ? "metaKey" : "ctrlKey"] = true; - event.keyCode = 66; - - run(() => textarea.dispatchEvent(event)); - - const example = I18n.t(`composer.bold_text`); - assert.equal( - find("#reply-control .d-editor-input").val().trim(), - `this is the *content* of a post**${example}**`, - "it supports keyboard shortcuts" - ); - - await click("#reply-control a.cancel"); - assert.ok(exists(".bootbox.modal"), "it pops up a confirmation dialog"); - - await click(".modal-footer a:eq(1)"); - assert.ok(!exists(".bootbox.modal"), "the confirmation can be cancelled"); -}); - -test("Composer upload placeholder", async (assert) => { - await visit("/"); - await click("#create-topic"); - - const file1 = new Blob([""], { type: "image/png" }); - file1.name = "test.png"; - const data1 = { - files: [file1], - result: { - original_filename: "test.png", - thumbnail_width: 200, - thumbnail_height: 300, - url: "/images/avatar.png?1", - }, - }; - - const file2 = new Blob([""], { type: "image/png" }); - file2.name = "test.png"; - const data2 = { - files: [file2], - result: { - original_filename: "test.png", - thumbnail_width: 100, - thumbnail_height: 200, - url: "/images/avatar.png?2", - }, - }; - - const file3 = new Blob([""], { type: "image/png" }); - file3.name = "image.png"; - const data3 = { - files: [file3], - result: { - original_filename: "image.png", - thumbnail_width: 300, - thumbnail_height: 400, - url: "/images/avatar.png?3", - }, - }; - - const file4 = new Blob([""], { type: "image/png" }); - file4.name = "ima++ge.png"; - const data4 = { - files: [file4], - result: { - original_filename: "ima++ge.png", - thumbnail_width: 300, - thumbnail_height: 400, - url: "/images/avatar.png?3", - }, - }; - - await find(".wmd-controls").trigger("fileuploadsend", data1); - assert.equal(find(".d-editor-input").val(), "[Uploading: test.png...]() "); - - await find(".wmd-controls").trigger("fileuploadsend", data2); - assert.equal( - find(".d-editor-input").val(), - "[Uploading: test.png...]() [Uploading: test.png(1)...]() " - ); - - await find(".wmd-controls").trigger("fileuploadsend", data4); - assert.equal( - find(".d-editor-input").val(), - "[Uploading: test.png...]() [Uploading: test.png(1)...]() [Uploading: ima++ge.png...]() ", - "should accept files with unescaped characters" - ); - - await find(".wmd-controls").trigger("fileuploadsend", data3); - assert.equal( - find(".d-editor-input").val(), - "[Uploading: test.png...]() [Uploading: test.png(1)...]() [Uploading: ima++ge.png...]() [Uploading: image.png...]() " - ); - - await find(".wmd-controls").trigger("fileuploaddone", data2); - assert.equal( - find(".d-editor-input").val(), - "[Uploading: test.png...]() ![test|100x200](/images/avatar.png?2) [Uploading: ima++ge.png...]() [Uploading: image.png...]() " - ); - - await find(".wmd-controls").trigger("fileuploaddone", data3); - assert.equal( - find(".d-editor-input").val(), - "[Uploading: test.png...]() ![test|100x200](/images/avatar.png?2) [Uploading: ima++ge.png...]() ![image|300x400](/images/avatar.png?3) " - ); - - await find(".wmd-controls").trigger("fileuploaddone", data1); - assert.equal( - find(".d-editor-input").val(), - "![test|200x300](/images/avatar.png?1) ![test|100x200](/images/avatar.png?2) [Uploading: ima++ge.png...]() ![image|300x400](/images/avatar.png?3) " - ); -}); - -test("Create a topic with server side errors", async (assert) => { - await visit("/"); - await click("#create-topic"); - await fillIn("#reply-title", "this title triggers an error"); - await fillIn(".d-editor-input", "this is the *content* of a post"); - await click("#reply-control button.create"); - assert.ok(exists(".bootbox.modal"), "it pops up an error message"); - await click(".bootbox.modal a.btn-primary"); - assert.ok(!exists(".bootbox.modal"), "it dismisses the error"); - assert.ok(exists(".d-editor-input"), "the composer input is visible"); -}); - -test("Create a Topic", async (assert) => { - await visit("/"); - await click("#create-topic"); - await fillIn("#reply-title", "Internationalization Localization"); - await fillIn(".d-editor-input", "this is the *content* of a new topic post"); - await click("#reply-control button.create"); - assert.equal( - currentURL(), - "/t/internationalization-localization/280", - "it transitions to the newly created topic URL" - ); -}); - -test("Create an enqueued Topic", async (assert) => { - await visit("/"); - await click("#create-topic"); - await fillIn("#reply-title", "Internationalization Localization"); - await fillIn(".d-editor-input", "enqueue this content please"); - await click("#reply-control button.create"); - assert.ok(visible(".d-modal"), "it pops up a modal"); - assert.equal(currentURL(), "/", "it doesn't change routes"); - - await click(".modal-footer button"); - assert.ok(invisible(".d-modal"), "the modal can be dismissed"); -}); - -test("Can display a message and route to a URL", async (assert) => { - await visit("/"); - await click("#create-topic"); - await fillIn("#reply-title", "This title doesn't matter"); - await fillIn(".d-editor-input", "custom message"); - await click("#reply-control button.create"); - assert.equal( - find(".bootbox .modal-body").text(), - "This is a custom response" - ); - assert.equal(currentURL(), "/", "it doesn't change routes"); - - await click(".bootbox .btn-primary"); - assert.equal( - currentURL(), - "/faq", - "can navigate to a `route_to` destination" - ); -}); - -test("Create a Reply", async (assert) => { - await visit("/t/internationalization-localization/280"); - - assert.ok( - !exists("article[data-post-id=12345]"), - "the post is not in the DOM" - ); - - await click("#topic-footer-buttons .btn.create"); - assert.ok(exists(".d-editor-input"), "the composer input is visible"); - assert.ok(!exists("#reply-title"), "there is no title since this is a reply"); - - await fillIn(".d-editor-input", "this is the content of my reply"); - await click("#reply-control button.create"); - assert.equal( - find(".cooked:last p").text(), - "If you use gettext format you could leverage Launchpad 13 translations and the community behind it." - ); -}); - -test("Can edit a post after starting a reply", async (assert) => { - await visit("/t/internationalization-localization/280"); - - await click("#topic-footer-buttons .create"); - await fillIn(".d-editor-input", "this is the content of my reply"); - - await click(".topic-post:eq(0) button.show-more-actions"); - await click(".topic-post:eq(0) button.edit"); - - await click("a[data-handler='0']"); - - assert.ok(!visible(".bootbox.modal")); - assert.equal( - find(".d-editor-input").val(), - "this is the content of my reply" - ); -}); - -test("Posting on a different topic", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click("#topic-footer-buttons .btn.create"); - await fillIn(".d-editor-input", "this is the content for a different topic"); - - await visit("/t/1-3-0beta9-no-rate-limit-popups/28830"); - assert.equal(currentURL(), "/t/1-3-0beta9-no-rate-limit-popups/28830"); - await click("#reply-control button.create"); - assert.ok(visible(".reply-where-modal"), "it pops up a modal"); - - await click(".btn-reply-here"); - assert.equal( - find(".cooked:last p").text(), - "If you use gettext format you could leverage Launchpad 13 translations and the community behind it." - ); -}); - -test("Create an enqueued Reply", async (assert) => { - await visit("/t/internationalization-localization/280"); - - assert.notOk(find(".pending-posts .reviewable-item").length); - - await click("#topic-footer-buttons .btn.create"); - assert.ok(exists(".d-editor-input"), "the composer input is visible"); - assert.ok(!exists("#reply-title"), "there is no title since this is a reply"); - - await fillIn(".d-editor-input", "enqueue this content please"); - await click("#reply-control button.create"); - assert.ok( - find(".cooked:last p").text() !== "enqueue this content please", - "it doesn't insert the post" - ); - - assert.ok(visible(".d-modal"), "it pops up a modal"); - - await click(".modal-footer button"); - assert.ok(invisible(".d-modal"), "the modal can be dismissed"); - - assert.ok(find(".pending-posts .reviewable-item").length); -}); - -test("Edit the first post", async (assert) => { - await visit("/t/internationalization-localization/280"); - - assert.ok( - !exists(".topic-post:eq(0) .post-info.edits"), - "it has no edits icon at first" - ); - - await click(".topic-post:eq(0) button.show-more-actions"); - await click(".topic-post:eq(0) button.edit"); - assert.equal( - find(".d-editor-input").val().indexOf("Any plans to support"), - 0, - "it populates the input with the post text" - ); - - await fillIn(".d-editor-input", "This is the new text for the post"); - await fillIn("#reply-title", "This is the new text for the title"); - await click("#reply-control button.create"); - assert.ok(!exists(".d-editor-input"), "it closes the composer"); - assert.ok( - exists(".topic-post:eq(0) .post-info.edits"), - "it has the edits icon" - ); - assert.ok( - find("#topic-title h1") - .text() - .indexOf("This is the new text for the title") !== -1, - "it shows the new title" - ); - assert.ok( - find(".topic-post:eq(0) .cooked") - .text() - .indexOf("This is the new text for the post") !== -1, - "it updates the post" - ); -}); - -test("Composer can switch between edits", async (assert) => { - await visit("/t/this-is-a-test-topic/9"); - - await click(".topic-post:eq(0) button.edit"); - assert.equal( - find(".d-editor-input").val().indexOf("This is the first post."), - 0, - "it populates the input with the post text" - ); - await click(".topic-post:eq(1) button.edit"); - assert.equal( - find(".d-editor-input").val().indexOf("This is the second post."), - 0, - "it populates the input with the post text" - ); -}); - -test("Composer with dirty edit can toggle to another edit", async (assert) => { - await visit("/t/this-is-a-test-topic/9"); - - await click(".topic-post:eq(0) button.edit"); - await fillIn(".d-editor-input", "This is a dirty reply"); - await click(".topic-post:eq(1) button.edit"); - assert.ok(exists(".bootbox.modal"), "it pops up a confirmation dialog"); - - await click(".modal-footer a:eq(0)"); - assert.equal( - find(".d-editor-input").val().indexOf("This is the second post."), - 0, - "it populates the input with the post text" - ); -}); - -test("Composer can toggle between edit and reply", async (assert) => { - await visit("/t/this-is-a-test-topic/9"); - - await click(".topic-post:eq(0) button.edit"); - assert.equal( - find(".d-editor-input").val().indexOf("This is the first post."), - 0, - "it populates the input with the post text" - ); - await click(".topic-post:eq(0) button.reply"); - assert.equal(find(".d-editor-input").val(), "", "it clears the input"); - await click(".topic-post:eq(0) button.edit"); - assert.equal( - find(".d-editor-input").val().indexOf("This is the first post."), - 0, - "it populates the input with the post text" - ); -}); - -test("Composer can toggle whispers", async (assert) => { - const menu = selectKit(".toolbar-popup-menu-options"); - - await visit("/t/this-is-a-test-topic/9"); - await click(".topic-post:eq(0) button.reply"); - - await menu.expand(); - await menu.selectRowByValue("toggleWhisper"); - - assert.ok( - find(".composer-fields .whisper .d-icon-far-eye-slash").length === 1, - "it sets the post type to whisper" - ); - - await menu.expand(); - await menu.selectRowByValue("toggleWhisper"); - - assert.ok( - find(".composer-fields .whisper .d-icon-far-eye-slash").length === 0, - "it removes the whisper mode" - ); - - await menu.expand(); - await menu.selectRowByValue("toggleWhisper"); - - await click(".toggle-fullscreen"); - - await menu.expand(); - - assert.ok( - menu.rowByValue("toggleWhisper").exists(), - "whisper toggling is still present when going fullscreen" - ); -}); - -test("Composer can toggle layouts (open, fullscreen and draft)", async (assert) => { - await visit("/t/this-is-a-test-topic/9"); - await click(".topic-post:eq(0) button.reply"); - - assert.ok( - find("#reply-control.open").length === 1, - "it starts in open state by default" - ); - - await click(".toggle-fullscreen"); - - assert.ok( - find("#reply-control.fullscreen").length === 1, - "it expands composer to full screen" - ); - - await click(".toggle-fullscreen"); - - assert.ok( - find("#reply-control.open").length === 1, - "it collapses composer to regular size" - ); - - await fillIn(".d-editor-input", "This is a dirty reply"); - await click(".toggler"); - - assert.ok( - find("#reply-control.draft").length === 1, - "it collapses composer to draft bar" - ); - - await click(".toggle-fullscreen"); - - assert.ok( - find("#reply-control.open").length === 1, - "from draft, it expands composer back to open state" - ); -}); - -test("Composer can toggle between reply and createTopic", async (assert) => { - await visit("/t/this-is-a-test-topic/9"); - await click(".topic-post:eq(0) button.reply"); - - await selectKit(".toolbar-popup-menu-options").expand(); - await selectKit(".toolbar-popup-menu-options").selectRowByValue( - "toggleWhisper" - ); - - assert.ok( - find(".composer-fields .whisper .d-icon-far-eye-slash").length === 1, - "it sets the post type to whisper" - ); - - await visit("/"); - assert.ok(exists("#create-topic"), "the create topic button is visible"); - - await click("#create-topic"); - assert.ok( - find(".composer-fields .whisper .d-icon-far-eye-slash").length === 0, - "it should reset the state of the composer's model" - ); - - await selectKit(".toolbar-popup-menu-options").expand(); - await selectKit(".toolbar-popup-menu-options").selectRowByValue( - "toggleInvisible" - ); - - assert.ok( - find(".composer-fields .unlist").text().indexOf(I18n.t("composer.unlist")) > - 0, - "it sets the topic to unlisted" - ); - - await visit("/t/this-is-a-test-topic/9"); - - await click(".topic-post:eq(0) button.reply"); - assert.ok( - find(".composer-fields .whisper") - .text() - .indexOf(I18n.t("composer.unlist")) === -1, - "it should reset the state of the composer's model" - ); -}); - -test("Composer with dirty reply can toggle to edit", async (assert) => { - await visit("/t/this-is-a-test-topic/9"); - - await click(".topic-post:eq(0) button.reply"); - await fillIn(".d-editor-input", "This is a dirty reply"); - await click(".topic-post:eq(0) button.edit"); - assert.ok(exists(".bootbox.modal"), "it pops up a confirmation dialog"); - await click(".modal-footer a:eq(0)"); - assert.equal( - find(".d-editor-input").val().indexOf("This is the first post."), - 0, - "it populates the input with the post text" - ); -}); - -test("Composer draft with dirty reply can toggle to edit", async (assert) => { - await visit("/t/this-is-a-test-topic/9"); - - await click(".topic-post:eq(0) button.reply"); - await fillIn(".d-editor-input", "This is a dirty reply"); - await click(".toggler"); - await click(".topic-post:eq(1) button.edit"); - assert.ok(exists(".bootbox.modal"), "it pops up a confirmation dialog"); - assert.equal( - find(".modal-footer a:eq(1)").text(), - I18n.t("post.abandon.no_value") - ); - await click(".modal-footer a:eq(0)"); - assert.equal( - find(".d-editor-input").val().indexOf("This is the second post."), - 0, - "it populates the input with the post text" - ); -}); - -test("Composer draft can switch to draft in new context without destroying current draft", async (assert) => { - await visit("/t/this-is-a-test-topic/9"); - - await click(".topic-post:eq(0) button.reply"); - await fillIn(".d-editor-input", "This is a dirty reply"); - - await click("#site-logo"); - await click("#create-topic"); - - assert.ok(exists(".bootbox.modal"), "it pops up a confirmation dialog"); - assert.equal( - find(".modal-footer a:eq(1)").text(), - I18n.t("post.abandon.no_save_draft") - ); - await click(".modal-footer a:eq(1)"); - assert.equal( - find(".d-editor-input").val(), - "", - "it populates the input with the post text" - ); -}); - -test("Checks for existing draft", async (assert) => { - try { - toggleCheckDraftPopup(true); - + }); + + skip("Tests the Composer controls", async (assert) => { + await visit("/"); + assert.ok(exists("#create-topic"), "the create button is visible"); + + await click("#create-topic"); + assert.ok(exists(".d-editor-input"), "the composer input is visible"); + assert.ok( + exists(".title-input .popup-tip.bad.hide"), + "title errors are hidden by default" + ); + assert.ok( + exists(".d-editor-textarea-wrapper .popup-tip.bad.hide"), + "body errors are hidden by default" + ); + + await click("a.toggle-preview"); + assert.ok( + !exists(".d-editor-preview:visible"), + "clicking the toggle hides the preview" + ); + + await click("a.toggle-preview"); + assert.ok( + exists(".d-editor-preview:visible"), + "clicking the toggle shows the preview again" + ); + + await click("#reply-control button.create"); + assert.ok( + !exists(".title-input .popup-tip.bad.hide"), + "it shows the empty title error" + ); + assert.ok( + !exists(".d-editor-wrapper .popup-tip.bad.hide"), + "it shows the empty body error" + ); + + await fillIn("#reply-title", "this is my new topic title"); + assert.ok(exists(".title-input .popup-tip.good"), "the title is now good"); + + await fillIn(".d-editor-input", "this is the *content* of a post"); + assert.equal( + find(".d-editor-preview").html().trim(), + "

this is the content of a post

", + "it previews content" + ); + assert.ok( + exists(".d-editor-textarea-wrapper .popup-tip.good"), + "the body is now good" + ); + + const textarea = find("#reply-control .d-editor-input")[0]; + textarea.selectionStart = textarea.value.length; + textarea.selectionEnd = textarea.value.length; + + // Testing keyboard events is tough! + const mac = /Mac|iPod|iPhone|iPad/.test(navigator.platform); + const event = document.createEvent("Event"); + event.initEvent("keydown", true, true); + event[mac ? "metaKey" : "ctrlKey"] = true; + event.keyCode = 66; + + run(() => textarea.dispatchEvent(event)); + + const example = I18n.t(`composer.bold_text`); + assert.equal( + find("#reply-control .d-editor-input").val().trim(), + `this is the *content* of a post**${example}**`, + "it supports keyboard shortcuts" + ); + + await click("#reply-control a.cancel"); + assert.ok(exists(".bootbox.modal"), "it pops up a confirmation dialog"); + + await click(".modal-footer a:eq(1)"); + assert.ok(!exists(".bootbox.modal"), "the confirmation can be cancelled"); + }); + + test("Composer upload placeholder", async (assert) => { + await visit("/"); + await click("#create-topic"); + + const file1 = new Blob([""], { type: "image/png" }); + file1.name = "test.png"; + const data1 = { + files: [file1], + result: { + original_filename: "test.png", + thumbnail_width: 200, + thumbnail_height: 300, + url: "/images/avatar.png?1", + }, + }; + + const file2 = new Blob([""], { type: "image/png" }); + file2.name = "test.png"; + const data2 = { + files: [file2], + result: { + original_filename: "test.png", + thumbnail_width: 100, + thumbnail_height: 200, + url: "/images/avatar.png?2", + }, + }; + + const file3 = new Blob([""], { type: "image/png" }); + file3.name = "image.png"; + const data3 = { + files: [file3], + result: { + original_filename: "image.png", + thumbnail_width: 300, + thumbnail_height: 400, + url: "/images/avatar.png?3", + }, + }; + + const file4 = new Blob([""], { type: "image/png" }); + file4.name = "ima++ge.png"; + const data4 = { + files: [file4], + result: { + original_filename: "ima++ge.png", + thumbnail_width: 300, + thumbnail_height: 400, + url: "/images/avatar.png?3", + }, + }; + + await find(".wmd-controls").trigger("fileuploadsend", data1); + assert.equal(find(".d-editor-input").val(), "[Uploading: test.png...]() "); + + await find(".wmd-controls").trigger("fileuploadsend", data2); + assert.equal( + find(".d-editor-input").val(), + "[Uploading: test.png...]() [Uploading: test.png(1)...]() " + ); + + await find(".wmd-controls").trigger("fileuploadsend", data4); + assert.equal( + find(".d-editor-input").val(), + "[Uploading: test.png...]() [Uploading: test.png(1)...]() [Uploading: ima++ge.png...]() ", + "should accept files with unescaped characters" + ); + + await find(".wmd-controls").trigger("fileuploadsend", data3); + assert.equal( + find(".d-editor-input").val(), + "[Uploading: test.png...]() [Uploading: test.png(1)...]() [Uploading: ima++ge.png...]() [Uploading: image.png...]() " + ); + + await find(".wmd-controls").trigger("fileuploaddone", data2); + assert.equal( + find(".d-editor-input").val(), + "[Uploading: test.png...]() ![test|100x200](/images/avatar.png?2) [Uploading: ima++ge.png...]() [Uploading: image.png...]() " + ); + + await find(".wmd-controls").trigger("fileuploaddone", data3); + assert.equal( + find(".d-editor-input").val(), + "[Uploading: test.png...]() ![test|100x200](/images/avatar.png?2) [Uploading: ima++ge.png...]() ![image|300x400](/images/avatar.png?3) " + ); + + await find(".wmd-controls").trigger("fileuploaddone", data1); + assert.equal( + find(".d-editor-input").val(), + "![test|200x300](/images/avatar.png?1) ![test|100x200](/images/avatar.png?2) [Uploading: ima++ge.png...]() ![image|300x400](/images/avatar.png?3) " + ); + }); + + test("Create a topic with server side errors", async (assert) => { + await visit("/"); + await click("#create-topic"); + await fillIn("#reply-title", "this title triggers an error"); + await fillIn(".d-editor-input", "this is the *content* of a post"); + await click("#reply-control button.create"); + assert.ok(exists(".bootbox.modal"), "it pops up an error message"); + await click(".bootbox.modal a.btn-primary"); + assert.ok(!exists(".bootbox.modal"), "it dismisses the error"); + assert.ok(exists(".d-editor-input"), "the composer input is visible"); + }); + + test("Create a Topic", async (assert) => { + await visit("/"); + await click("#create-topic"); + await fillIn("#reply-title", "Internationalization Localization"); + await fillIn( + ".d-editor-input", + "this is the *content* of a new topic post" + ); + await click("#reply-control button.create"); + assert.equal( + currentURL(), + "/t/internationalization-localization/280", + "it transitions to the newly created topic URL" + ); + }); + + test("Create an enqueued Topic", async (assert) => { + await visit("/"); + await click("#create-topic"); + await fillIn("#reply-title", "Internationalization Localization"); + await fillIn(".d-editor-input", "enqueue this content please"); + await click("#reply-control button.create"); + assert.ok(visible(".d-modal"), "it pops up a modal"); + assert.equal(currentURL(), "/", "it doesn't change routes"); + + await click(".modal-footer button"); + assert.ok(invisible(".d-modal"), "the modal can be dismissed"); + }); + + test("Can display a message and route to a URL", async (assert) => { + await visit("/"); + await click("#create-topic"); + await fillIn("#reply-title", "This title doesn't matter"); + await fillIn(".d-editor-input", "custom message"); + await click("#reply-control button.create"); + assert.equal( + find(".bootbox .modal-body").text(), + "This is a custom response" + ); + assert.equal(currentURL(), "/", "it doesn't change routes"); + + await click(".bootbox .btn-primary"); + assert.equal( + currentURL(), + "/faq", + "can navigate to a `route_to` destination" + ); + }); + + test("Create a Reply", async (assert) => { await visit("/t/internationalization-localization/280"); + assert.ok( + !exists("article[data-post-id=12345]"), + "the post is not in the DOM" + ); + + await click("#topic-footer-buttons .btn.create"); + assert.ok(exists(".d-editor-input"), "the composer input is visible"); + assert.ok( + !exists("#reply-title"), + "there is no title since this is a reply" + ); + + await fillIn(".d-editor-input", "this is the content of my reply"); + await click("#reply-control button.create"); + assert.equal( + find(".cooked:last p").text(), + "If you use gettext format you could leverage Launchpad 13 translations and the community behind it." + ); + }); + + test("Can edit a post after starting a reply", async (assert) => { + await visit("/t/internationalization-localization/280"); + + await click("#topic-footer-buttons .create"); + await fillIn(".d-editor-input", "this is the content of my reply"); + await click(".topic-post:eq(0) button.show-more-actions"); await click(".topic-post:eq(0) button.edit"); - assert.equal(find(".modal-body").text(), I18n.t("drafts.abandon.confirm")); + await click("a[data-handler='0']"); - await click(".modal-footer .btn.btn-default"); - } finally { - toggleCheckDraftPopup(false); - } -}); + assert.ok(!visible(".bootbox.modal")); + assert.equal( + find(".d-editor-input").val(), + "this is the content of my reply" + ); + }); -test("Can switch states without abandon popup", async (assert) => { - try { - toggleCheckDraftPopup(true); + test("Posting on a different topic", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click("#topic-footer-buttons .btn.create"); + await fillIn( + ".d-editor-input", + "this is the content for a different topic" + ); + await visit("/t/1-3-0beta9-no-rate-limit-popups/28830"); + assert.equal(currentURL(), "/t/1-3-0beta9-no-rate-limit-popups/28830"); + await click("#reply-control button.create"); + assert.ok(visible(".reply-where-modal"), "it pops up a modal"); + + await click(".btn-reply-here"); + assert.equal( + find(".cooked:last p").text(), + "If you use gettext format you could leverage Launchpad 13 translations and the community behind it." + ); + }); + + test("Create an enqueued Reply", async (assert) => { await visit("/t/internationalization-localization/280"); - const longText = "a".repeat(256); + assert.notOk(find(".pending-posts .reviewable-item").length); - sandbox.stub(Draft, "get").returns( - Promise.resolve({ - draft: null, - draft_sequence: 0, - }) + await click("#topic-footer-buttons .btn.create"); + assert.ok(exists(".d-editor-input"), "the composer input is visible"); + assert.ok( + !exists("#reply-title"), + "there is no title since this is a reply" ); - await click(".btn-primary.create.btn"); + await fillIn(".d-editor-input", "enqueue this content please"); + await click("#reply-control button.create"); + assert.ok( + find(".cooked:last p").text() !== "enqueue this content please", + "it doesn't insert the post" + ); - await fillIn(".d-editor-input", longText); + assert.ok(visible(".d-modal"), "it pops up a modal"); - await click("article#post_3 button.reply"); + await click(".modal-footer button"); + assert.ok(invisible(".d-modal"), "the modal can be dismissed"); - const composerActions = selectKit(".composer-actions"); - await composerActions.expand(); - await composerActions.selectRowByValue("reply_as_private_message"); + assert.ok(find(".pending-posts .reviewable-item").length); + }); + + test("Edit the first post", async (assert) => { + await visit("/t/internationalization-localization/280"); + + assert.ok( + !exists(".topic-post:eq(0) .post-info.edits"), + "it has no edits icon at first" + ); + + await click(".topic-post:eq(0) button.show-more-actions"); + await click(".topic-post:eq(0) button.edit"); + assert.equal( + find(".d-editor-input").val().indexOf("Any plans to support"), + 0, + "it populates the input with the post text" + ); + + await fillIn(".d-editor-input", "This is the new text for the post"); + await fillIn("#reply-title", "This is the new text for the title"); + await click("#reply-control button.create"); + assert.ok(!exists(".d-editor-input"), "it closes the composer"); + assert.ok( + exists(".topic-post:eq(0) .post-info.edits"), + "it has the edits icon" + ); + assert.ok( + find("#topic-title h1") + .text() + .indexOf("This is the new text for the title") !== -1, + "it shows the new title" + ); + assert.ok( + find(".topic-post:eq(0) .cooked") + .text() + .indexOf("This is the new text for the post") !== -1, + "it updates the post" + ); + }); + + test("Composer can switch between edits", async (assert) => { + await visit("/t/this-is-a-test-topic/9"); + + await click(".topic-post:eq(0) button.edit"); + assert.equal( + find(".d-editor-input").val().indexOf("This is the first post."), + 0, + "it populates the input with the post text" + ); + await click(".topic-post:eq(1) button.edit"); + assert.equal( + find(".d-editor-input").val().indexOf("This is the second post."), + 0, + "it populates the input with the post text" + ); + }); + + test("Composer with dirty edit can toggle to another edit", async (assert) => { + await visit("/t/this-is-a-test-topic/9"); + + await click(".topic-post:eq(0) button.edit"); + await fillIn(".d-editor-input", "This is a dirty reply"); + await click(".topic-post:eq(1) button.edit"); + assert.ok(exists(".bootbox.modal"), "it pops up a confirmation dialog"); + + await click(".modal-footer a:eq(0)"); + assert.equal( + find(".d-editor-input").val().indexOf("This is the second post."), + 0, + "it populates the input with the post text" + ); + }); + + test("Composer can toggle between edit and reply", async (assert) => { + await visit("/t/this-is-a-test-topic/9"); + + await click(".topic-post:eq(0) button.edit"); + assert.equal( + find(".d-editor-input").val().indexOf("This is the first post."), + 0, + "it populates the input with the post text" + ); + await click(".topic-post:eq(0) button.reply"); + assert.equal(find(".d-editor-input").val(), "", "it clears the input"); + await click(".topic-post:eq(0) button.edit"); + assert.equal( + find(".d-editor-input").val().indexOf("This is the first post."), + 0, + "it populates the input with the post text" + ); + }); + + test("Composer can toggle whispers", async (assert) => { + const menu = selectKit(".toolbar-popup-menu-options"); + + await visit("/t/this-is-a-test-topic/9"); + await click(".topic-post:eq(0) button.reply"); + + await menu.expand(); + await menu.selectRowByValue("toggleWhisper"); + + assert.ok( + find(".composer-fields .whisper .d-icon-far-eye-slash").length === 1, + "it sets the post type to whisper" + ); + + await menu.expand(); + await menu.selectRowByValue("toggleWhisper"); + + assert.ok( + find(".composer-fields .whisper .d-icon-far-eye-slash").length === 0, + "it removes the whisper mode" + ); + + await menu.expand(); + await menu.selectRowByValue("toggleWhisper"); + + await click(".toggle-fullscreen"); + + await menu.expand(); + + assert.ok( + menu.rowByValue("toggleWhisper").exists(), + "whisper toggling is still present when going fullscreen" + ); + }); + + test("Composer can toggle layouts (open, fullscreen and draft)", async (assert) => { + await visit("/t/this-is-a-test-topic/9"); + await click(".topic-post:eq(0) button.reply"); + + assert.ok( + find("#reply-control.open").length === 1, + "it starts in open state by default" + ); + + await click(".toggle-fullscreen"); + + assert.ok( + find("#reply-control.fullscreen").length === 1, + "it expands composer to full screen" + ); + + await click(".toggle-fullscreen"); + + assert.ok( + find("#reply-control.open").length === 1, + "it collapses composer to regular size" + ); + + await fillIn(".d-editor-input", "This is a dirty reply"); + await click(".toggler"); + + assert.ok( + find("#reply-control.draft").length === 1, + "it collapses composer to draft bar" + ); + + await click(".toggle-fullscreen"); + + assert.ok( + find("#reply-control.open").length === 1, + "from draft, it expands composer back to open state" + ); + }); + + test("Composer can toggle between reply and createTopic", async (assert) => { + await visit("/t/this-is-a-test-topic/9"); + await click(".topic-post:eq(0) button.reply"); + + await selectKit(".toolbar-popup-menu-options").expand(); + await selectKit(".toolbar-popup-menu-options").selectRowByValue( + "toggleWhisper" + ); + + assert.ok( + find(".composer-fields .whisper .d-icon-far-eye-slash").length === 1, + "it sets the post type to whisper" + ); + + await visit("/"); + assert.ok(exists("#create-topic"), "the create topic button is visible"); + + await click("#create-topic"); + assert.ok( + find(".composer-fields .whisper .d-icon-far-eye-slash").length === 0, + "it should reset the state of the composer's model" + ); + + await selectKit(".toolbar-popup-menu-options").expand(); + await selectKit(".toolbar-popup-menu-options").selectRowByValue( + "toggleInvisible" + ); + + assert.ok( + find(".composer-fields .unlist") + .text() + .indexOf(I18n.t("composer.unlist")) > 0, + "it sets the topic to unlisted" + ); + + await visit("/t/this-is-a-test-topic/9"); + + await click(".topic-post:eq(0) button.reply"); + assert.ok( + find(".composer-fields .whisper") + .text() + .indexOf(I18n.t("composer.unlist")) === -1, + "it should reset the state of the composer's model" + ); + }); + + test("Composer with dirty reply can toggle to edit", async (assert) => { + await visit("/t/this-is-a-test-topic/9"); + + await click(".topic-post:eq(0) button.reply"); + await fillIn(".d-editor-input", "This is a dirty reply"); + await click(".topic-post:eq(0) button.edit"); + assert.ok(exists(".bootbox.modal"), "it pops up a confirmation dialog"); + await click(".modal-footer a:eq(0)"); + assert.equal( + find(".d-editor-input").val().indexOf("This is the first post."), + 0, + "it populates the input with the post text" + ); + }); + + test("Composer draft with dirty reply can toggle to edit", async (assert) => { + await visit("/t/this-is-a-test-topic/9"); + + await click(".topic-post:eq(0) button.reply"); + await fillIn(".d-editor-input", "This is a dirty reply"); + await click(".toggler"); + await click(".topic-post:eq(1) button.edit"); + assert.ok(exists(".bootbox.modal"), "it pops up a confirmation dialog"); + assert.equal( + find(".modal-footer a:eq(1)").text(), + I18n.t("post.abandon.no_value") + ); + await click(".modal-footer a:eq(0)"); + assert.equal( + find(".d-editor-input").val().indexOf("This is the second post."), + 0, + "it populates the input with the post text" + ); + }); + + test("Composer draft can switch to draft in new context without destroying current draft", async (assert) => { + await visit("/t/this-is-a-test-topic/9"); + + await click(".topic-post:eq(0) button.reply"); + await fillIn(".d-editor-input", "This is a dirty reply"); + + await click("#site-logo"); + await click("#create-topic"); + + assert.ok(exists(".bootbox.modal"), "it pops up a confirmation dialog"); + assert.equal( + find(".modal-footer a:eq(1)").text(), + I18n.t("post.abandon.no_save_draft") + ); + await click(".modal-footer a:eq(1)"); + assert.equal( + find(".d-editor-input").val(), + "", + "it populates the input with the post text" + ); + }); + + test("Checks for existing draft", async (assert) => { + try { + toggleCheckDraftPopup(true); + + await visit("/t/internationalization-localization/280"); + + await click(".topic-post:eq(0) button.show-more-actions"); + await click(".topic-post:eq(0) button.edit"); + + assert.equal( + find(".modal-body").text(), + I18n.t("drafts.abandon.confirm") + ); + + await click(".modal-footer .btn.btn-default"); + } finally { + toggleCheckDraftPopup(false); + } + }); + + test("Can switch states without abandon popup", async (assert) => { + try { + toggleCheckDraftPopup(true); + + await visit("/t/internationalization-localization/280"); + + const longText = "a".repeat(256); + + sandbox.stub(Draft, "get").returns( + Promise.resolve({ + draft: null, + draft_sequence: 0, + }) + ); + + await click(".btn-primary.create.btn"); + + await fillIn(".d-editor-input", longText); + + await click("article#post_3 button.reply"); + + const composerActions = selectKit(".composer-actions"); + await composerActions.expand(); + await composerActions.selectRowByValue("reply_as_private_message"); + + assert.equal( + find(".modal-body").text(), + "", + "abandon popup shouldn't come" + ); + + assert.ok( + find(".d-editor-input").val().includes(longText), + "entered text should still be there" + ); + + assert.ok( + find( + '.action-title a[href="/t/internationalization-localization/280"]' + ), + "mode should have changed" + ); + + assert.ok(find(".save-animation"), "save animation should show"); + } finally { + toggleCheckDraftPopup(false); + } + sandbox.restore(); + }); + + test("Loading draft also replaces the recipients", async (assert) => { + try { + toggleCheckDraftPopup(true); + + sandbox.stub(Draft, "get").returns( + Promise.resolve({ + draft: + '{"reply":"hello","action":"privateMessage","title":"hello","categoryId":null,"archetypeId":"private_message","metaData":null,"recipients":"codinghorror","composerTime":9159,"typingTime":2500}', + draft_sequence: 0, + }) + ); + + await visit("/u/charlie"); + await click("button.compose-pm"); + await click(".modal .btn-default"); + + assert.equal(find(".users-input .item:eq(0)").text(), "codinghorror"); + } finally { + toggleCheckDraftPopup(false); + } + }); + + test("Deleting the text content of the first post in a private message", async (assert) => { + await visit("/t/34"); + + await click("#post_1 .d-icon-ellipsis-h"); + + await click("#post_1 .d-icon-pencil-alt"); + + await fillIn(".d-editor-input", ""); assert.equal( - find(".modal-body").text(), - "", - "abandon popup shouldn't come" + find(".d-editor-container textarea").attr("placeholder"), + I18n.t("composer.reply_placeholder"), + "it should not block because of missing category" ); + }); + + const assertImageResized = (assert, uploads) => { + assert.equal( + find(".d-editor-input").val(), + uploads.join("\n"), + "it resizes uploaded image" + ); + }; + + test("Image resizing buttons", async (assert) => { + await visit("/"); + await click("#create-topic"); + + let uploads = [ + // 0 Default markdown with dimensions- should work + "![test|690x313](upload://test.png)", + // 1 Image with scaling percentage, should work + "![test|690x313,50%](upload://test.png)", + // 2 image with scaling percentage and a proceeding whitespace, should work + "![test|690x313, 50%](upload://test.png)", + // 3 No dimensions, should not work + "![test](upload://test.jpeg)", + // 4 Wrapped in backquetes should not work + "`![test|690x313](upload://test.png)`", + // 5 html image - should not work + "", + // 6 two images one the same line, but both are syntactically correct - both should work + "![onTheSameLine1|200x200](upload://onTheSameLine1.jpeg) ![onTheSameLine2|250x250](upload://onTheSameLine2.jpeg)", + // 7 & 8 Identical images - both should work + "![identicalImage|300x300](upload://identicalImage.png)", + "![identicalImage|300x300](upload://identicalImage.png)", + // 9 Image with whitespaces in alt - should work + "![image with spaces in alt|690x220](upload://test.png)", + // 10 Image with markdown title - should work + `![image|690x220](upload://test.png "image title")`, + // 11 bbcode - should not work + "[img]/images/avatar.png[/img]", + // 12 Image with data attributes + "![test|foo=bar|690x313,50%|bar=baz](upload://test.png)", + ]; + + await fillIn(".d-editor-input", uploads.join("\n")); assert.ok( - find(".d-editor-input").val().includes(longText), - "entered text should still be there" + find(".button-wrapper").length === 10, + "it adds correct amount of scaling button groups" ); - assert.ok( - find('.action-title a[href="/t/internationalization-localization/280"]'), - "mode should have changed" + // Default + uploads[0] = + "![test|690x313, 50%](upload://test.png)"; + await click( + find(".button-wrapper[data-image-index='0'] .scale-btn[data-scale='50']") ); + assertImageResized(assert, uploads); - assert.ok(find(".save-animation"), "save animation should show"); - } finally { - toggleCheckDraftPopup(false); - } - sandbox.restore(); -}); - -test("Loading draft also replaces the recipients", async (assert) => { - try { - toggleCheckDraftPopup(true); - - sandbox.stub(Draft, "get").returns( - Promise.resolve({ - draft: - '{"reply":"hello","action":"privateMessage","title":"hello","categoryId":null,"archetypeId":"private_message","metaData":null,"recipients":"codinghorror","composerTime":9159,"typingTime":2500}', - draft_sequence: 0, - }) + // Targets the correct image if two on the same line + uploads[6] = + "![onTheSameLine1|200x200, 50%](upload://onTheSameLine1.jpeg) ![onTheSameLine2|250x250](upload://onTheSameLine2.jpeg)"; + await click( + find(".button-wrapper[data-image-index='3'] .scale-btn[data-scale='50']") ); + assertImageResized(assert, uploads); - await visit("/u/charlie"); - await click("button.compose-pm"); - await click(".modal .btn-default"); + // Try the other image on the same line + uploads[6] = + "![onTheSameLine1|200x200, 50%](upload://onTheSameLine1.jpeg) ![onTheSameLine2|250x250, 75%](upload://onTheSameLine2.jpeg)"; + await click( + find(".button-wrapper[data-image-index='4'] .scale-btn[data-scale='75']") + ); + assertImageResized(assert, uploads); - assert.equal(find(".users-input .item:eq(0)").text(), "codinghorror"); - } finally { - toggleCheckDraftPopup(false); - } -}); + // Make sure we target the correct image if there are duplicates + uploads[7] = "![identicalImage|300x300, 50%](upload://identicalImage.png)"; + await click( + find(".button-wrapper[data-image-index='5'] .scale-btn[data-scale='50']") + ); + assertImageResized(assert, uploads); -test("Deleting the text content of the first post in a private message", async (assert) => { - await visit("/t/34"); + // Try the other dupe + uploads[8] = "![identicalImage|300x300, 75%](upload://identicalImage.png)"; + await click( + find(".button-wrapper[data-image-index='6'] .scale-btn[data-scale='75']") + ); + assertImageResized(assert, uploads); - await click("#post_1 .d-icon-ellipsis-h"); + // Don't mess with image titles + uploads[10] = `![image|690x220, 75%](upload://test.png "image title")`; + await click( + find(".button-wrapper[data-image-index='8'] .scale-btn[data-scale='75']") + ); + assertImageResized(assert, uploads); - await click("#post_1 .d-icon-pencil-alt"); + // Keep data attributes + uploads[12] = `![test|foo=bar|690x313, 75%|bar=baz](upload://test.png)`; + await click( + find(".button-wrapper[data-image-index='9'] .scale-btn[data-scale='75']") + ); + assertImageResized(assert, uploads); - await fillIn(".d-editor-input", ""); - - assert.equal( - find(".d-editor-container textarea").attr("placeholder"), - I18n.t("composer.reply_placeholder"), - "it should not block because of missing category" - ); -}); - -const assertImageResized = (assert, uploads) => { - assert.equal( - find(".d-editor-input").val(), - uploads.join("\n"), - "it resizes uploaded image" - ); -}; - -test("Image resizing buttons", async (assert) => { - await visit("/"); - await click("#create-topic"); - - let uploads = [ - // 0 Default markdown with dimensions- should work - "![test|690x313](upload://test.png)", - // 1 Image with scaling percentage, should work - "![test|690x313,50%](upload://test.png)", - // 2 image with scaling percentage and a proceeding whitespace, should work - "![test|690x313, 50%](upload://test.png)", - // 3 No dimensions, should not work - "![test](upload://test.jpeg)", - // 4 Wrapped in backquetes should not work - "`![test|690x313](upload://test.png)`", - // 5 html image - should not work - "", - // 6 two images one the same line, but both are syntactically correct - both should work - "![onTheSameLine1|200x200](upload://onTheSameLine1.jpeg) ![onTheSameLine2|250x250](upload://onTheSameLine2.jpeg)", - // 7 & 8 Identical images - both should work - "![identicalImage|300x300](upload://identicalImage.png)", - "![identicalImage|300x300](upload://identicalImage.png)", - // 9 Image with whitespaces in alt - should work - "![image with spaces in alt|690x220](upload://test.png)", - // 10 Image with markdown title - should work - `![image|690x220](upload://test.png "image title")`, - // 11 bbcode - should not work - "[img]/images/avatar.png[/img]", - // 12 Image with data attributes - "![test|foo=bar|690x313,50%|bar=baz](upload://test.png)", - ]; - - await fillIn(".d-editor-input", uploads.join("\n")); - - assert.ok( - find(".button-wrapper").length === 10, - "it adds correct amount of scaling button groups" - ); - - // Default - uploads[0] = - "![test|690x313, 50%](upload://test.png)"; - await click( - find(".button-wrapper[data-image-index='0'] .scale-btn[data-scale='50']") - ); - assertImageResized(assert, uploads); - - // Targets the correct image if two on the same line - uploads[6] = - "![onTheSameLine1|200x200, 50%](upload://onTheSameLine1.jpeg) ![onTheSameLine2|250x250](upload://onTheSameLine2.jpeg)"; - await click( - find(".button-wrapper[data-image-index='3'] .scale-btn[data-scale='50']") - ); - assertImageResized(assert, uploads); - - // Try the other image on the same line - uploads[6] = - "![onTheSameLine1|200x200, 50%](upload://onTheSameLine1.jpeg) ![onTheSameLine2|250x250, 75%](upload://onTheSameLine2.jpeg)"; - await click( - find(".button-wrapper[data-image-index='4'] .scale-btn[data-scale='75']") - ); - assertImageResized(assert, uploads); - - // Make sure we target the correct image if there are duplicates - uploads[7] = "![identicalImage|300x300, 50%](upload://identicalImage.png)"; - await click( - find(".button-wrapper[data-image-index='5'] .scale-btn[data-scale='50']") - ); - assertImageResized(assert, uploads); - - // Try the other dupe - uploads[8] = "![identicalImage|300x300, 75%](upload://identicalImage.png)"; - await click( - find(".button-wrapper[data-image-index='6'] .scale-btn[data-scale='75']") - ); - assertImageResized(assert, uploads); - - // Don't mess with image titles - uploads[10] = `![image|690x220, 75%](upload://test.png "image title")`; - await click( - find(".button-wrapper[data-image-index='8'] .scale-btn[data-scale='75']") - ); - assertImageResized(assert, uploads); - - // Keep data attributes - uploads[12] = `![test|foo=bar|690x313, 75%|bar=baz](upload://test.png)`; - await click( - find(".button-wrapper[data-image-index='9'] .scale-btn[data-scale='75']") - ); - assertImageResized(assert, uploads); - - await fillIn( - ".d-editor-input", - ` + await fillIn( + ".d-editor-input", + ` ![test|690x313](upload://test.png) \`\` ` - ); + ); - assert.ok( - find("script").length === 0, - "it does not unescapes script tags in code blocks" - ); + assert.ok( + find("script").length === 0, + "it does not unescapes script tags in code blocks" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/dashboard-test.js b/app/assets/javascripts/discourse/tests/acceptance/dashboard-test.js index 7d76cd84a9a..a0c1a68c49c 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/dashboard-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/dashboard-test.js @@ -136,13 +136,13 @@ acceptance("Dashboard: dashboard_visible_tabs", function (needs) { assert.ok(exists(".dashboard .navigation-item.security"), "security tab"); assert.ok(exists(".dashboard .navigation-item.reports"), "reports tab"); }); +}); - acceptance("Dashboard: dashboard_hidden_reports", { - loggedIn: true, - settings: { - dashboard_visible_tabs: "reports", - dashboard_hidden_reports: "posts|dau_by_mau", - }, +acceptance("Dashboard: dashboard_hidden_reports", function (needs) { + needs.user(); + needs.settings({ + dashboard_visible_tabs: "reports", + dashboard_hidden_reports: "posts|dau_by_mau", }); test("hidden reports", async (assert) => { diff --git a/app/assets/javascripts/discourse/tests/acceptance/encoded-category-test.js b/app/assets/javascripts/discourse/tests/acceptance/encoded-category-test.js index decd49b2899..71b8776ca11 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/encoded-category-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/encoded-category-test.js @@ -3,28 +3,11 @@ import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import DiscoveryFixtures from "discourse/tests/fixtures/discovery-fixtures"; -acceptance("Encoded Sub Category Discovery", { - pretend(server, helper) { - server.get( - "/c/%E6%BC%A2%E5%AD%97-parent/%E6%BC%A2%E5%AD%97-subcategory/6/l/latest.json", - () => { - return helper.response( - DiscoveryFixtures["/latest_can_create_topic.json"] - ); - } - ); - server.get( - "/c/%E6%BC%A2%E5%AD%97-parent/%E6%BC%A2%E5%AD%97-subcategory/find_by_slug.json", - () => { - //respond with an error here: these tests are to check that ember can route this itself without falling back to rails - return helper.response(500, {}); - } - ); - }, - settings: { +acceptance("Encoded Sub Category Discovery", function (needs) { + needs.settings({ slug_generation_method: "encoded", - }, - site: { + }); + needs.site({ categories: [ { id: 5, @@ -40,19 +23,36 @@ acceptance("Encoded Sub Category Discovery", { parent_category_id: 5, }, ], - }, -}); + }); + needs.pretender((server, helper) => { + server.get( + "/c/%E6%BC%A2%E5%AD%97-parent/%E6%BC%A2%E5%AD%97-subcategory/6/l/latest.json", + () => { + return helper.response( + DiscoveryFixtures["/latest_can_create_topic.json"] + ); + } + ); + server.get( + "/c/%E6%BC%A2%E5%AD%97-parent/%E6%BC%A2%E5%AD%97-subcategory/find_by_slug.json", + () => { + //respond with an error here: these tests are to check that ember can route this itself without falling back to rails + return helper.response(500, {}); + } + ); + }); -test("Visit subcategory by slug", async (assert) => { - let bodySelector = - "body.category-\\%E6\\%BC\\%A2\\%E5\\%AD\\%97-parent-\\%E6\\%BC\\%A2\\%E5\\%AD\\%97-subcategory"; - await visit("/c/%E6%BC%A2%E5%AD%97-parent/%E6%BC%A2%E5%AD%97-subcategory"); - assert.ok($(bodySelector).length, "has the default navigation"); - assert.ok(exists(".topic-list"), "The list of topics was rendered"); - assert.ok(exists(".topic-list .topic-list-item"), "has topics"); + test("Visit subcategory by slug", async (assert) => { + let bodySelector = + "body.category-\\%E6\\%BC\\%A2\\%E5\\%AD\\%97-parent-\\%E6\\%BC\\%A2\\%E5\\%AD\\%97-subcategory"; + await visit("/c/%E6%BC%A2%E5%AD%97-parent/%E6%BC%A2%E5%AD%97-subcategory"); + assert.ok($(bodySelector).length, "has the default navigation"); + assert.ok(exists(".topic-list"), "The list of topics was rendered"); + assert.ok(exists(".topic-list .topic-list-item"), "has topics"); - await visit("/c/漢字-parent/漢字-subcategory"); - assert.ok($(bodySelector).length, "has the default navigation"); - assert.ok(exists(".topic-list"), "The list of topics was rendered"); - assert.ok(exists(".topic-list .topic-list-item"), "has topics"); + await visit("/c/漢字-parent/漢字-subcategory"); + assert.ok($(bodySelector).length, "has the default navigation"); + assert.ok(exists(".topic-list"), "The list of topics was rendered"); + assert.ok(exists(".topic-list .topic-list-item"), "has topics"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/group-manage-logs-test.js b/app/assets/javascripts/discourse/tests/acceptance/group-manage-logs-test.js index 2fb23d2513a..467cb1187c2 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/group-manage-logs-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/group-manage-logs-test.js @@ -2,9 +2,9 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Group logs", { - loggedIn: true, - pretend(server, helper) { +acceptance("Group logs", function (needs) { + needs.user(); + needs.pretender((server, helper) => { server.get("/groups/snorlax.json", () => { return helper.response({ group: { @@ -91,19 +91,19 @@ acceptance("Group logs", { }); } }); - }, -}); + }); -test("Browsing group logs", async (assert) => { - await visit("/g/snorlax/manage/logs"); - assert.ok( - find("tr.group-manage-logs-row").length === 2, - "it should display the right number of logs" - ); + test("Browsing group logs", async (assert) => { + await visit("/g/snorlax/manage/logs"); + assert.ok( + find("tr.group-manage-logs-row").length === 2, + "it should display the right number of logs" + ); - await click(find(".group-manage-logs-row button")[0]); - assert.ok( - find("tr.group-manage-logs-row").length === 1, - "it should display the right number of logs" - ); + await click(find(".group-manage-logs-row button")[0]); + assert.ok( + find("tr.group-manage-logs-row").length === 1, + "it should display the right number of logs" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/group-manage-membership-test.js b/app/assets/javascripts/discourse/tests/acceptance/group-manage-membership-test.js index 0ce999a6500..839a3a14798 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/group-manage-membership-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/group-manage-membership-test.js @@ -6,119 +6,121 @@ import { } from "discourse/tests/helpers/qunit-helpers"; import selectKit from "discourse/tests/helpers/select-kit-helper"; -acceptance("Managing Group Membership", { - loggedIn: true, -}); - -test("As an admin", async (assert) => { - updateCurrentUser({ can_create_group: true }); - - await visit("/g/alternative-group/manage/membership"); - - assert.ok( - find('label[for="automatic_membership"]').length === 1, - "it should display automatic membership label" - ); - - assert.ok( - find(".groups-form-primary-group").length === 1, - "it should display set as primary group checkbox" - ); - - assert.ok( - find(".groups-form-grant-trust-level").length === 1, - "it should display grant trust level selector" - ); - - assert.ok( - find(".group-form-public-admission").length === 1, - "it should display group public admission input" - ); - - assert.ok( - find(".group-form-public-exit").length === 1, - "it should display group public exit input" - ); - - assert.ok( - find(".group-form-allow-membership-requests").length === 1, - "it should display group allow_membership_request input" - ); - - assert.ok( - find(".group-form-allow-membership-requests[disabled]").length === 1, - "it should disable group allow_membership_request input" - ); - - await click(".group-form-public-admission"); - await click(".group-form-allow-membership-requests"); - - assert.ok( - find(".group-form-public-admission[disabled]").length === 1, - "it should disable group public admission input" - ); - - assert.ok( - find(".group-form-public-exit[disabled]").length === 0, - "it should not disable group public exit input" - ); - - assert.equal( - find(".group-form-membership-request-template").length, - 1, - "it should display the membership request template field" - ); - - const emailDomains = selectKit(".group-form-automatic-membership-automatic"); - await emailDomains.expand(); - await emailDomains.fillInFilter("foo.com"); - await emailDomains.keyboard("enter"); - - assert.equal(emailDomains.header().value(), "foo.com"); -}); - -test("As a group owner", async (assert) => { - updateCurrentUser({ moderator: false, admin: false }); - - await visit("/g/discourse/manage/membership"); - - assert.ok( - find('label[for="automatic_membership"]').length === 0, - "it should not display automatic membership label" - ); - - assert.ok( - find(".groups-form-automatic-membership-retroactive").length === 0, - "it should not display automatic membership retroactive checkbox" - ); - - assert.ok( - find(".groups-form-primary-group").length === 0, - "it should not display set as primary group checkbox" - ); - - assert.ok( - find(".groups-form-grant-trust-level").length === 0, - "it should not display grant trust level selector" - ); - - assert.ok( - find(".group-form-public-admission").length === 1, - "it should display group public admission input" - ); - - assert.ok( - find(".group-form-public-exit").length === 1, - "it should display group public exit input" - ); - - assert.ok( - find(".group-form-allow-membership-requests").length === 1, - "it should display group allow_membership_request input" - ); - - assert.ok( - find(".group-form-allow-membership-requests[disabled]").length === 1, - "it should disable group allow_membership_request input" - ); +acceptance("Managing Group Membership", function (needs) { + needs.user(); + + test("As an admin", async (assert) => { + updateCurrentUser({ can_create_group: true }); + + await visit("/g/alternative-group/manage/membership"); + + assert.ok( + find('label[for="automatic_membership"]').length === 1, + "it should display automatic membership label" + ); + + assert.ok( + find(".groups-form-primary-group").length === 1, + "it should display set as primary group checkbox" + ); + + assert.ok( + find(".groups-form-grant-trust-level").length === 1, + "it should display grant trust level selector" + ); + + assert.ok( + find(".group-form-public-admission").length === 1, + "it should display group public admission input" + ); + + assert.ok( + find(".group-form-public-exit").length === 1, + "it should display group public exit input" + ); + + assert.ok( + find(".group-form-allow-membership-requests").length === 1, + "it should display group allow_membership_request input" + ); + + assert.ok( + find(".group-form-allow-membership-requests[disabled]").length === 1, + "it should disable group allow_membership_request input" + ); + + await click(".group-form-public-admission"); + await click(".group-form-allow-membership-requests"); + + assert.ok( + find(".group-form-public-admission[disabled]").length === 1, + "it should disable group public admission input" + ); + + assert.ok( + find(".group-form-public-exit[disabled]").length === 0, + "it should not disable group public exit input" + ); + + assert.equal( + find(".group-form-membership-request-template").length, + 1, + "it should display the membership request template field" + ); + + const emailDomains = selectKit( + ".group-form-automatic-membership-automatic" + ); + await emailDomains.expand(); + await emailDomains.fillInFilter("foo.com"); + await emailDomains.keyboard("enter"); + + assert.equal(emailDomains.header().value(), "foo.com"); + }); + + test("As a group owner", async (assert) => { + updateCurrentUser({ moderator: false, admin: false }); + + await visit("/g/discourse/manage/membership"); + + assert.ok( + find('label[for="automatic_membership"]').length === 0, + "it should not display automatic membership label" + ); + + assert.ok( + find(".groups-form-automatic-membership-retroactive").length === 0, + "it should not display automatic membership retroactive checkbox" + ); + + assert.ok( + find(".groups-form-primary-group").length === 0, + "it should not display set as primary group checkbox" + ); + + assert.ok( + find(".groups-form-grant-trust-level").length === 0, + "it should not display grant trust level selector" + ); + + assert.ok( + find(".group-form-public-admission").length === 1, + "it should display group public admission input" + ); + + assert.ok( + find(".group-form-public-exit").length === 1, + "it should display group public exit input" + ); + + assert.ok( + find(".group-form-allow-membership-requests").length === 1, + "it should display group allow_membership_request input" + ); + + assert.ok( + find(".group-form-allow-membership-requests[disabled]").length === 1, + "it should disable group allow_membership_request input" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/group-manage-profile-test.js b/app/assets/javascripts/discourse/tests/acceptance/group-manage-profile-test.js index 0defaa9d298..30b77abb718 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/group-manage-profile-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/group-manage-profile-test.js @@ -5,51 +5,54 @@ import { updateCurrentUser, } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Managing Group Profile"); -test("As an anonymous user", async (assert) => { - await visit("/g/discourse/manage/profile"); +acceptance("Managing Group Profile", function () { + test("As an anonymous user", async (assert) => { + await visit("/g/discourse/manage/profile"); - assert.ok( - count(".group-members tr") > 0, - "it should redirect to members page for an anonymous user" - ); + assert.ok( + count(".group-members tr") > 0, + "it should redirect to members page for an anonymous user" + ); + }); }); -acceptance("Managing Group Profile", { loggedIn: true }); +acceptance("Managing Group Profile", function (needs) { + needs.user(); -test("As an admin", async (assert) => { - await visit("/g/discourse/manage/profile"); + test("As an admin", async (assert) => { + await visit("/g/discourse/manage/profile"); - assert.ok( - find(".group-flair-inputs").length === 1, - "it should display avatar flair inputs" - ); - assert.ok( - find(".group-form-bio").length === 1, - "it should display group bio input" - ); - assert.ok( - find(".group-form-name").length === 1, - "it should display group name input" - ); - assert.ok( - find(".group-form-full-name").length === 1, - "it should display group full name input" - ); -}); - -test("As a group owner", async (assert) => { - updateCurrentUser({ - moderator: false, - admin: false, - can_create_group: false, + assert.ok( + find(".group-flair-inputs").length === 1, + "it should display avatar flair inputs" + ); + assert.ok( + find(".group-form-bio").length === 1, + "it should display group bio input" + ); + assert.ok( + find(".group-form-name").length === 1, + "it should display group name input" + ); + assert.ok( + find(".group-form-full-name").length === 1, + "it should display group full name input" + ); }); - await visit("/g/discourse/manage/profile"); + test("As a group owner", async (assert) => { + updateCurrentUser({ + moderator: false, + admin: false, + can_create_group: false, + }); - assert.equal( - find(".group-form-name").length, - 0, - "it should not display group name input" - ); + await visit("/g/discourse/manage/profile"); + + assert.equal( + find(".group-form-name").length, + 0, + "it should not display group name input" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/group-manage-tags-test.js b/app/assets/javascripts/discourse/tests/acceptance/group-manage-tags-test.js index 675f235372c..7cf0ebfbeb3 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/group-manage-tags-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/group-manage-tags-test.js @@ -5,34 +5,37 @@ import { updateCurrentUser, } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Managing Group Tag Notification Defaults"); -test("As an anonymous user", async (assert) => { - await visit("/g/discourse/manage/tags"); +acceptance("Managing Group Tag Notification Defaults", function () { + test("As an anonymous user", async (assert) => { + await visit("/g/discourse/manage/tags"); - assert.ok( - count(".group-members tr") > 0, - "it should redirect to members page for an anonymous user" - ); + assert.ok( + count(".group-members tr") > 0, + "it should redirect to members page for an anonymous user" + ); + }); }); -acceptance("Managing Group Tag Notification Defaults", { loggedIn: true }); +acceptance("Managing Group Tag Notification Defaults", function (needs) { + needs.user(); -test("As an admin", async (assert) => { - await visit("/g/discourse/manage/tags"); + test("As an admin", async (assert) => { + await visit("/g/discourse/manage/tags"); - assert.ok( - find(".groups-notifications-form .tag-chooser").length === 5, - "it should display tag inputs" - ); -}); - -test("As a group owner", async (assert) => { - updateCurrentUser({ moderator: false, admin: false }); - - await visit("/g/discourse/manage/tags"); - - assert.ok( - find(".groups-notifications-form .tag-chooser").length === 5, - "it should display tag inputs" - ); + assert.ok( + find(".groups-notifications-form .tag-chooser").length === 5, + "it should display tag inputs" + ); + }); + + test("As a group owner", async (assert) => { + updateCurrentUser({ moderator: false, admin: false }); + + await visit("/g/discourse/manage/tags"); + + assert.ok( + find(".groups-notifications-form .tag-chooser").length === 5, + "it should display tag inputs" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/group-requests-test.js b/app/assets/javascripts/discourse/tests/acceptance/group-requests-test.js index 2a33a616773..d696c23f522 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/group-requests-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/group-requests-test.js @@ -1,13 +1,14 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -import { parsePostData } from "discourse/tests/helpers/create-pretender"; -let requests = []; +acceptance("Group Requests", function (needs) { + let requests; -acceptance("Group Requests", { - loggedIn: true, - pretend(server, helper) { + needs.user(); + needs.hooks.beforeEach(() => (requests = [])); + + needs.pretender((server, helper) => { server.get("/groups/Macdonald.json", () => { return helper.response({ group: { @@ -75,53 +76,53 @@ acceptance("Group Requests", { }); server.put("/groups/42/handle_membership_request.json", (request) => { - const body = parsePostData(request.requestBody); + const body = helper.parsePostData(request.requestBody); requests.push([body["user_id"], body["accept"]]); return helper.success(); }); - }, -}); - -test("Group Requests", async (assert) => { - await visit("/g/Macdonald/requests"); - - assert.equal(find(".group-members tr").length, 2); - assert.equal( - find(".group-members tr:first-child td:nth-child(1)") - .text() - .trim() - .replace(/\s+/g, " "), - "eviltrout Robin Ward" - ); - assert.equal( - find(".group-members tr:first-child td:nth-child(3)").text().trim(), - "Please accept my membership request." - ); - assert.equal( - find(".group-members tr:first-child .btn-primary").text().trim(), - "Accept" - ); - assert.equal( - find(".group-members tr:first-child .btn-danger").text().trim(), - "Deny" - ); - - await click(".group-members tr:first-child .btn-primary"); - assert.ok( - find(".group-members tr:first-child td:nth-child(4)") - .text() - .trim() - .indexOf("accepted") === 0 - ); - assert.deepEqual(requests, [["19", "true"]]); - - await click(".group-members tr:last-child .btn-danger"); - assert.equal( - find(".group-members tr:last-child td:nth-child(4)").text().trim(), - "denied" - ); - assert.deepEqual(requests, [ - ["19", "true"], - ["20", undefined], - ]); + }); + + test("Group Requests", async (assert) => { + await visit("/g/Macdonald/requests"); + + assert.equal(find(".group-members tr").length, 2); + assert.equal( + find(".group-members tr:first-child td:nth-child(1)") + .text() + .trim() + .replace(/\s+/g, " "), + "eviltrout Robin Ward" + ); + assert.equal( + find(".group-members tr:first-child td:nth-child(3)").text().trim(), + "Please accept my membership request." + ); + assert.equal( + find(".group-members tr:first-child .btn-primary").text().trim(), + "Accept" + ); + assert.equal( + find(".group-members tr:first-child .btn-danger").text().trim(), + "Deny" + ); + + await click(".group-members tr:first-child .btn-primary"); + assert.ok( + find(".group-members tr:first-child td:nth-child(4)") + .text() + .trim() + .indexOf("accepted") === 0 + ); + assert.deepEqual(requests, [["19", "true"]]); + + await click(".group-members tr:last-child .btn-danger"); + assert.equal( + find(".group-members tr:last-child td:nth-child(4)").text().trim(), + "denied" + ); + assert.deepEqual(requests, [ + ["19", "true"], + ["20", undefined], + ]); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/group-test.js b/app/assets/javascripts/discourse/tests/acceptance/group-test.js index d96b5e9c783..988a859a1c0 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/group-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/group-test.js @@ -3,286 +3,289 @@ import { test } from "qunit"; import I18n from "I18n"; import selectKit from "discourse/tests/helpers/select-kit-helper"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -import pretender from "discourse/tests/helpers/create-pretender"; -let groupArgs = { - settings: { - enable_group_directory: true, - }, - pretend(pretenderServer, helper) { - pretenderServer.post("/groups/Macdonald/request_membership", () => { - return helper.response({ - relative_url: "/t/internationalization-localization/280", - }); +function setupGroupPretender(server, helper) { + server.post("/groups/Macdonald/request_membership", () => { + return helper.response({ + relative_url: "/t/internationalization-localization/280", }); - }, -}; + }); +} -acceptance("Group", groupArgs); +function setupGroupTest(needs) { + needs.settings({ enable_group_directory: true }); +} -const response = (object) => { - return [200, { "Content-Type": "application/json" }, object]; -}; +acceptance("Group - Anonymous", function (needs) { + setupGroupTest(needs); + needs.pretender(setupGroupPretender); -test("Anonymous Viewing Group", async function (assert) { - await visit("/g/discourse"); + test("Anonymous Viewing Group", async function (assert) { + await visit("/g/discourse"); - assert.equal( - count(".nav-pills li a[title='Messages']"), - 0, - "it does not show group messages navigation link" - ); + assert.equal( + count(".nav-pills li a[title='Messages']"), + 0, + "it does not show group messages navigation link" + ); - await click(".nav-pills li a[title='Activity']"); + await click(".nav-pills li a[title='Activity']"); - assert.ok(count(".user-stream-item") > 0, "it lists stream items"); + assert.ok(count(".user-stream-item") > 0, "it lists stream items"); - await click(".activity-nav li a[href='/g/discourse/activity/topics']"); + await click(".activity-nav li a[href='/g/discourse/activity/topics']"); - assert.ok(find(".topic-list"), "it shows the topic list"); - assert.equal(count(".topic-list-item"), 2, "it lists stream items"); + assert.ok(find(".topic-list"), "it shows the topic list"); + assert.equal(count(".topic-list-item"), 2, "it lists stream items"); - await click(".activity-nav li a[href='/g/discourse/activity/mentions']"); + await click(".activity-nav li a[href='/g/discourse/activity/mentions']"); - assert.ok(count(".user-stream-item") > 0, "it lists stream items"); - assert.ok( - find(".nav-pills li a[title='Edit Group']").length === 0, - "it should not show messages tab if user is not admin" - ); - assert.ok( - find(".nav-pills li a[title='Logs']").length === 0, - "it should not show Logs tab if user is not admin" - ); - assert.ok(count(".user-stream-item") > 0, "it lists stream items"); + assert.ok(count(".user-stream-item") > 0, "it lists stream items"); + assert.ok( + find(".nav-pills li a[title='Edit Group']").length === 0, + "it should not show messages tab if user is not admin" + ); + assert.ok( + find(".nav-pills li a[title='Logs']").length === 0, + "it should not show Logs tab if user is not admin" + ); + assert.ok(count(".user-stream-item") > 0, "it lists stream items"); - const groupDropdown = selectKit(".group-dropdown"); - await groupDropdown.expand(); + const groupDropdown = selectKit(".group-dropdown"); + await groupDropdown.expand(); - assert.equal(groupDropdown.rowByIndex(1).name(), "discourse"); + assert.equal(groupDropdown.rowByIndex(1).name(), "discourse"); - assert.equal( - groupDropdown.rowByIndex(0).name(), - I18n.t("groups.index.all").toLowerCase() - ); + assert.equal( + groupDropdown.rowByIndex(0).name(), + I18n.t("groups.index.all").toLowerCase() + ); - this.siteSettings.enable_group_directory = false; + this.siteSettings.enable_group_directory = false; - await visit("/g"); - await visit("/g/discourse"); + await visit("/g"); + await visit("/g/discourse"); - await groupDropdown.expand(); + await groupDropdown.expand(); - assert.equal( - find(".group-dropdown-filter").length, - 0, - "it should not display the default header" - ); + assert.equal( + find(".group-dropdown-filter").length, + 0, + "it should not display the default header" + ); + }); + + test("Anonymous Viewing Automatic Group", async (assert) => { + await visit("/g/moderators"); + + assert.equal( + count(".nav-pills li a[title='Manage']"), + 0, + "it does not show group messages navigation link" + ); + }); }); -test("Anonymous Viewing Automatic Group", async (assert) => { - await visit("/g/moderators"); +acceptance("Group - Authenticated", function (needs) { + setupGroupTest(needs); + needs.user(); - assert.equal( - count(".nav-pills li a[title='Manage']"), - 0, - "it does not show group messages navigation link" - ); -}); + needs.pretender((server, helper) => { + setupGroupPretender(server, helper); + server.get( + "/topics/private-messages-group/eviltrout/alternative-group.json", + () => { + return helper.response({ topic_list: { topics: [] } }); + } + ); -acceptance("Group", Object.assign({ loggedIn: true }, groupArgs)); - -test("User Viewing Group", async (assert) => { - await visit("/g"); - await click(".group-index-request"); - - assert.equal( - find(".modal-header").text().trim(), - I18n.t("groups.membership_request.title", { group_name: "Macdonald" }) - ); - - assert.equal( - find(".request-group-membership-form textarea").val(), - "Please add me" - ); - - await click(".modal-footer .btn-primary"); - - assert.equal( - find(".fancy-title").text().trim(), - "Internationalization / localization" - ); - - await visit("/g/discourse"); - - await click(".group-message-button"); - - assert.ok(count("#reply-control") === 1, "it opens the composer"); - assert.equal( - find(".ac-wrap .item").text(), - "discourse", - "it prefills the group name" - ); -}); - -test("Admin viewing group messages when there are no messages", async (assert) => { - pretender.get( - "/topics/private-messages-group/eviltrout/discourse.json", - () => { - return response({ topic_list: { topics: [] } }); - } - ); - - await visit("/g/discourse"); - await click(".nav-pills li a[title='Messages']"); - - assert.equal( - find(".alert").text().trim(), - I18n.t("choose_topic.none_found"), - "it should display the right alert" - ); -}); - -test("Admin viewing group messages", async (assert) => { - pretender.get( - "/topics/private-messages-group/eviltrout/discourse.json", - () => { - return response({ - users: [ - { - id: 2, - username: "bruce1", - avatar_template: - "/user_avatar/meta.discourse.org/bruce1/{size}/5245.png", - }, - { - id: 3, - username: "CodingHorror", - avatar_template: - "/user_avatar/meta.discourse.org/codinghorror/{size}/5245.png", - }, - ], - primary_groups: [], - topic_list: { - can_create_topic: true, - draft: null, - draft_key: "new_topic", - draft_sequence: 0, - per_page: 30, - topics: [ + server.get( + "/topics/private-messages-group/eviltrout/discourse.json", + () => { + return helper.response({ + users: [ { - id: 12199, - title: "This is a private message 1", - fancy_title: "This is a private message 1", - slug: "this-is-a-private-message-1", - posts_count: 0, - reply_count: 0, - highest_post_number: 0, - image_url: null, - created_at: "2018-03-16T03:38:45.583Z", - last_posted_at: null, - bumped: true, - bumped_at: "2018-03-16T03:38:45.583Z", - unseen: false, - pinned: false, - unpinned: null, - visible: true, - closed: false, - archived: false, - bookmarked: null, - liked: null, - views: 0, - like_count: 0, - has_summary: false, - archetype: "private_message", - last_poster_username: "bruce1", - category_id: null, - pinned_globally: false, - featured_link: null, - posters: [ - { - extras: "latest single", - description: "Original Poster, Most Recent Poster", - user_id: 2, - primary_group_id: null, - }, - ], - participants: [ - { - extras: "latest", - description: null, - user_id: 2, - primary_group_id: null, - }, - { - extras: null, - description: null, - user_id: 3, - primary_group_id: null, - }, - ], + id: 2, + username: "bruce1", + avatar_template: + "/user_avatar/meta.discourse.org/bruce1/{size}/5245.png", + }, + { + id: 3, + username: "CodingHorror", + avatar_template: + "/user_avatar/meta.discourse.org/codinghorror/{size}/5245.png", }, ], - }, - }); - } - ); + primary_groups: [], + topic_list: { + can_create_topic: true, + draft: null, + draft_key: "new_topic", + draft_sequence: 0, + per_page: 30, + topics: [ + { + id: 12199, + title: "This is a private message 1", + fancy_title: "This is a private message 1", + slug: "this-is-a-private-message-1", + posts_count: 0, + reply_count: 0, + highest_post_number: 0, + image_url: null, + created_at: "2018-03-16T03:38:45.583Z", + last_posted_at: null, + bumped: true, + bumped_at: "2018-03-16T03:38:45.583Z", + unseen: false, + pinned: false, + unpinned: null, + visible: true, + closed: false, + archived: false, + bookmarked: null, + liked: null, + views: 0, + like_count: 0, + has_summary: false, + archetype: "private_message", + last_poster_username: "bruce1", + category_id: null, + pinned_globally: false, + featured_link: null, + posters: [ + { + extras: "latest single", + description: "Original Poster, Most Recent Poster", + user_id: 2, + primary_group_id: null, + }, + ], + participants: [ + { + extras: "latest", + description: null, + user_id: 2, + primary_group_id: null, + }, + { + extras: null, + description: null, + user_id: 3, + primary_group_id: null, + }, + ], + }, + ], + }, + }); + } + ); + }); - await visit("/g/discourse"); - await click(".nav-pills li a[title='Messages']"); + test("User Viewing Group", async (assert) => { + await visit("/g"); + await click(".group-index-request"); - assert.equal( - find(".topic-list-item .link-top-line").text().trim(), - "This is a private message 1", - "it should display the list of group topics" - ); -}); - -test("Admin Viewing Group", async (assert) => { - await visit("/g/discourse"); - - assert.ok( - find(".nav-pills li a[title='Manage']").length === 1, - "it should show manage group tab if user is admin" - ); - - assert.equal( - count(".group-message-button"), - 1, - "it displays show group message button" - ); - assert.equal( - find(".group-info-name").text(), - "Awesome Team", - "it should display the group name" - ); -}); - -test("Moderator Viewing Group", async (assert) => { - await visit("/g/alternative-group"); - - assert.ok( - find(".nav-pills li a[title='Manage']").length === 1, - "it should show manage group tab if user can_admin_group" - ); - - await click(".group-members-add.btn"); - - assert.ok( - find(".group-add-members-modal .group-add-members-make-owner"), - "it allows moderators to set group owners" - ); - - await click(".group-add-members-modal .modal-close"); - - const memberDropdown = selectKit(".group-member-dropdown:first"); - await memberDropdown.expand(); - - assert.equal( - memberDropdown.rowByIndex(0).name(), - I18n.t("groups.members.remove_member") - ); - assert.equal( - memberDropdown.rowByIndex(1).name(), - I18n.t("groups.members.make_owner") - ); + assert.equal( + find(".modal-header").text().trim(), + I18n.t("groups.membership_request.title", { group_name: "Macdonald" }) + ); + + assert.equal( + find(".request-group-membership-form textarea").val(), + "Please add me" + ); + + await click(".modal-footer .btn-primary"); + + assert.equal( + find(".fancy-title").text().trim(), + "Internationalization / localization" + ); + + await visit("/g/discourse"); + + await click(".group-message-button"); + + assert.ok(count("#reply-control") === 1, "it opens the composer"); + assert.equal( + find(".ac-wrap .item").text(), + "discourse", + "it prefills the group name" + ); + }); + + test("Admin viewing group messages when there are no messages", async (assert) => { + await visit("/g/alternative-group"); + await click(".nav-pills li a[title='Messages']"); + + assert.equal( + find(".alert").text().trim(), + I18n.t("choose_topic.none_found"), + "it should display the right alert" + ); + }); + + test("Admin viewing group messages", async (assert) => { + await visit("/g/discourse"); + await click(".nav-pills li a[title='Messages']"); + + assert.equal( + find(".topic-list-item .link-top-line").text().trim(), + "This is a private message 1", + "it should display the list of group topics" + ); + }); + + test("Admin Viewing Group", async (assert) => { + await visit("/g/discourse"); + + assert.ok( + find(".nav-pills li a[title='Manage']").length === 1, + "it should show manage group tab if user is admin" + ); + + assert.equal( + count(".group-message-button"), + 1, + "it displays show group message button" + ); + assert.equal( + find(".group-info-name").text(), + "Awesome Team", + "it should display the group name" + ); + }); + + test("Moderator Viewing Group", async (assert) => { + await visit("/g/alternative-group"); + + assert.ok( + find(".nav-pills li a[title='Manage']").length === 1, + "it should show manage group tab if user can_admin_group" + ); + + await click(".group-members-add.btn"); + + assert.ok( + find(".group-add-members-modal .group-add-members-make-owner"), + "it allows moderators to set group owners" + ); + + await click(".group-add-members-modal .modal-close"); + + const memberDropdown = selectKit(".group-member-dropdown:first"); + await memberDropdown.expand(); + + assert.equal( + memberDropdown.rowByIndex(0).name(), + I18n.t("groups.members.remove_member") + ); + assert.equal( + memberDropdown.rowByIndex(1).name(), + I18n.t("groups.members.make_owner") + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/groups-index-test.js b/app/assets/javascripts/discourse/tests/acceptance/groups-index-test.js index 4a22e7debc1..64c45ac4f69 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/groups-index-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/groups-index-test.js @@ -2,48 +2,48 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Groups"); +acceptance("Groups", function () { + test("Browsing Groups", async (assert) => { + await visit("/g?username=eviltrout"); -test("Browsing Groups", async (assert) => { - await visit("/g?username=eviltrout"); + assert.equal(count(".group-box"), 1, "it displays user's groups"); - assert.equal(count(".group-box"), 1, "it displays user's groups"); + await visit("/g"); - await visit("/g"); + assert.equal(count(".group-box"), 2, "it displays visible groups"); + assert.equal( + find(".group-index-join").length, + 1, + "it shows button to join group" + ); + assert.equal( + find(".group-index-request").length, + 1, + "it shows button to request for group membership" + ); - assert.equal(count(".group-box"), 2, "it displays visible groups"); - assert.equal( - find(".group-index-join").length, - 1, - "it shows button to join group" - ); - assert.equal( - find(".group-index-request").length, - 1, - "it shows button to request for group membership" - ); + await click(".group-index-join"); - await click(".group-index-join"); + assert.ok(exists(".modal.login-modal"), "it shows the login modal"); - assert.ok(exists(".modal.login-modal"), "it shows the login modal"); + await click(".login-modal .close"); - await click(".login-modal .close"); + assert.ok(invisible(".modal.login-modal"), "it closes the login modal"); - assert.ok(invisible(".modal.login-modal"), "it closes the login modal"); + await click(".group-index-request"); - await click(".group-index-request"); + assert.ok(exists(".modal.login-modal"), "it shows the login modal"); - assert.ok(exists(".modal.login-modal"), "it shows the login modal"); + await click("a[href='/g/discourse/members']"); - await click("a[href='/g/discourse/members']"); + assert.equal( + find(".group-info-name").text().trim(), + "Awesome Team", + "it displays the group page" + ); - assert.equal( - find(".group-info-name").text().trim(), - "Awesome Team", - "it displays the group page" - ); + await click(".group-index-join"); - await click(".group-index-join"); - - assert.ok(exists(".modal.login-modal"), "it shows the login modal"); + assert.ok(exists(".modal.login-modal"), "it shows the login modal"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/groups-new-test.js b/app/assets/javascripts/discourse/tests/acceptance/groups-new-test.js index 7ae37ac5762..a0396d4f138 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/groups-new-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/groups-new-test.js @@ -3,75 +3,76 @@ import { test } from "qunit"; import I18n from "I18n"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("New Group"); +acceptance("New Group - Anonymous", function () { + test("As an anon user", async (assert) => { + await visit("/g"); -test("As an anon user", async (assert) => { - await visit("/g"); - - assert.equal( - find(".groups-header-new").length, - 0, - "it should not display the button to create a group" - ); + assert.equal( + find(".groups-header-new").length, + 0, + "it should not display the button to create a group" + ); + }); }); -acceptance("New Group", { loggedIn: true }); +acceptance("New Group - Authenticated", function (needs) { + needs.user(); + test("Creating a new group", async (assert) => { + await visit("/g"); + await click(".groups-header-new"); -test("Creating a new group", async (assert) => { - await visit("/g"); - await click(".groups-header-new"); + assert.equal( + find(".group-form-save[disabled]").length, + 1, + "save button should be disabled" + ); - assert.equal( - find(".group-form-save[disabled]").length, - 1, - "save button should be disabled" - ); + await fillIn("input[name='name']", "1"); - await fillIn("input[name='name']", "1"); + assert.equal( + find(".tip.bad").text().trim(), + I18n.t("admin.groups.new.name.too_short"), + "it should show the right validation tooltip" + ); - assert.equal( - find(".tip.bad").text().trim(), - I18n.t("admin.groups.new.name.too_short"), - "it should show the right validation tooltip" - ); + assert.ok( + find(".group-form-save:disabled").length === 1, + "it should disable the save button" + ); - assert.ok( - find(".group-form-save:disabled").length === 1, - "it should disable the save button" - ); + await fillIn( + "input[name='name']", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + ); - await fillIn( - "input[name='name']", - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - ); + assert.equal( + find(".tip.bad").text().trim(), + I18n.t("admin.groups.new.name.too_long"), + "it should show the right validation tooltip" + ); - assert.equal( - find(".tip.bad").text().trim(), - I18n.t("admin.groups.new.name.too_long"), - "it should show the right validation tooltip" - ); + await fillIn("input[name='name']", ""); - await fillIn("input[name='name']", ""); + assert.equal( + find(".tip.bad").text().trim(), + I18n.t("admin.groups.new.name.blank"), + "it should show the right validation tooltip" + ); - assert.equal( - find(".tip.bad").text().trim(), - I18n.t("admin.groups.new.name.blank"), - "it should show the right validation tooltip" - ); + await fillIn("input[name='name']", "goodusername"); - await fillIn("input[name='name']", "goodusername"); + assert.equal( + find(".tip.good").text().trim(), + I18n.t("admin.groups.new.name.available"), + "it should show the right validation tooltip" + ); - assert.equal( - find(".tip.good").text().trim(), - I18n.t("admin.groups.new.name.available"), - "it should show the right validation tooltip" - ); + await click(".group-form-public-admission"); - await click(".group-form-public-admission"); - - assert.equal( - find("groups-new-allow-membership-requests").length, - 0, - "it should disable the membership requests checkbox" - ); + assert.equal( + find("groups-new-allow-membership-requests").length, + 0, + "it should disable the membership requests checkbox" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/hamburger-menu-test.js b/app/assets/javascripts/discourse/tests/acceptance/hamburger-menu-test.js index 93eead54e27..ac40fce0057 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/hamburger-menu-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/hamburger-menu-test.js @@ -5,18 +5,19 @@ import { updateCurrentUser, } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Opening the hamburger menu with some reviewables", { - loggedIn: true, - pretend: (server, helper) => { +acceptance("Opening the hamburger menu with some reviewables", function ( + needs +) { + needs.user(); + needs.pretender((server, helper) => { server.get("/review/count.json", () => helper.response({ count: 3 })); - }, -}); - -test("As a staff member", async (assert) => { - updateCurrentUser({ moderator: true, admin: false }); - - await visit("/"); - await click(".hamburger-dropdown"); - - assert.equal(find(".review .badge-notification.reviewables").text(), "3"); + }); + test("As a staff member", async (assert) => { + updateCurrentUser({ moderator: true, admin: false }); + + await visit("/"); + await click(".hamburger-dropdown"); + + assert.equal(find(".review .badge-notification.reviewables").text(), "3"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/hashtags-test.js b/app/assets/javascripts/discourse/tests/acceptance/hashtags-test.js index 6b09b30b8de..e732ba5363a 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/hashtags-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/hashtags-test.js @@ -2,10 +2,10 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Category and Tag Hashtags", { - loggedIn: true, - settings: { tagging_enabled: true }, - pretend(server, helper) { +acceptance("Category and Tag Hashtags", function (needs) { + needs.user(); + needs.settings({ tagging_enabled: true }); + needs.pretender((server, helper) => { server.get("/hashtags", () => { return helper.response({ categories: { bug: "/c/bugs" }, @@ -15,26 +15,26 @@ acceptance("Category and Tag Hashtags", { }, }); }); - }, -}); + }); -test("hashtags are cooked properly", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click("#topic-footer-buttons .btn.create"); + test("hashtags are cooked properly", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click("#topic-footer-buttons .btn.create"); - await fillIn( - ".d-editor-input", - `this is a category hashtag #bug + await fillIn( + ".d-editor-input", + `this is a category hashtag #bug this is a tag hashtag #monkey category vs tag: #bug vs #bug::tag` - ); + ); - assert.equal( - find(".d-editor-preview:visible").html().trim(), - `

this is a category hashtag #bug

+ assert.equal( + find(".d-editor-preview:visible").html().trim(), + `

this is a category hashtag #bug

this is a tag hashtag #monkey

category vs tag: #bug vs #bug

` - ); + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/invite-accept-test.js b/app/assets/javascripts/discourse/tests/acceptance/invite-accept-test.js index 1c114f96098..1861bb6e5aa 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/invite-accept-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/invite-accept-test.js @@ -3,82 +3,80 @@ import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import PreloadStore from "discourse/lib/preload-store"; -acceptance("Invite Accept", { - settings: { - full_name_required: true, - }, -}); +acceptance("Invite Accept", function (needs) { + needs.settings({ full_name_required: true }); -test("Invite Acceptance Page", async (assert) => { - PreloadStore.store("invite_info", { - invited_by: { - id: 123, - username: "neil", - avatar_template: "/user_avatar/localhost/neil/{size}/25_1.png", - name: "Neil Lalonde", - title: "team", - }, - email: null, - username: "invited", - is_invite_link: true, + test("Invite Acceptance Page", async (assert) => { + PreloadStore.store("invite_info", { + invited_by: { + id: 123, + username: "neil", + avatar_template: "/user_avatar/localhost/neil/{size}/25_1.png", + name: "Neil Lalonde", + title: "team", + }, + email: null, + username: "invited", + is_invite_link: true, + }); + + await visit("/invites/myvalidinvitetoken"); + assert.ok(exists("#new-account-email"), "shows the email input"); + assert.ok(exists("#new-account-username"), "shows the username input"); + assert.equal( + find("#new-account-username").val(), + "invited", + "username is prefilled" + ); + assert.ok(exists("#new-account-name"), "shows the name input"); + assert.ok(exists("#new-account-password"), "shows the password input"); + assert.ok( + exists(".invites-show .btn-primary:disabled"), + "submit is disabled because name and email is not filled" + ); + + await fillIn("#new-account-name", "John Doe"); + assert.ok( + exists(".invites-show .btn-primary:disabled"), + "submit is disabled because email is not filled" + ); + + await fillIn("#new-account-email", "john.doe@example.com"); + assert.not( + exists(".invites-show .btn-primary:disabled"), + "submit is enabled" + ); + + await fillIn("#new-account-username", "a"); + assert.ok(exists(".username-input .bad"), "username is not valid"); + assert.ok( + exists(".invites-show .btn-primary:disabled"), + "submit is disabled" + ); + + await fillIn("#new-account-password", "aaa"); + assert.ok(exists(".password-input .bad"), "password is not valid"); + assert.ok( + exists(".invites-show .btn-primary:disabled"), + "submit is disabled" + ); + + await fillIn("#new-account-email", "john.doe@example"); + assert.ok(exists(".email-input .bad"), "email is not valid"); + assert.ok( + exists(".invites-show .btn-primary:disabled"), + "submit is disabled" + ); + + await fillIn("#new-account-username", "validname"); + await fillIn("#new-account-password", "secur3ty4Y0uAndMe"); + await fillIn("#new-account-email", "john.doe@example.com"); + assert.ok(exists(".username-input .good"), "username is valid"); + assert.ok(exists(".password-input .good"), "password is valid"); + assert.ok(exists(".email-input .good"), "email is valid"); + assert.not( + exists(".invites-show .btn-primary:disabled"), + "submit is enabled" + ); }); - - await visit("/invites/myvalidinvitetoken"); - assert.ok(exists("#new-account-email"), "shows the email input"); - assert.ok(exists("#new-account-username"), "shows the username input"); - assert.equal( - find("#new-account-username").val(), - "invited", - "username is prefilled" - ); - assert.ok(exists("#new-account-name"), "shows the name input"); - assert.ok(exists("#new-account-password"), "shows the password input"); - assert.ok( - exists(".invites-show .btn-primary:disabled"), - "submit is disabled because name and email is not filled" - ); - - await fillIn("#new-account-name", "John Doe"); - assert.ok( - exists(".invites-show .btn-primary:disabled"), - "submit is disabled because email is not filled" - ); - - await fillIn("#new-account-email", "john.doe@example.com"); - assert.not( - exists(".invites-show .btn-primary:disabled"), - "submit is enabled" - ); - - await fillIn("#new-account-username", "a"); - assert.ok(exists(".username-input .bad"), "username is not valid"); - assert.ok( - exists(".invites-show .btn-primary:disabled"), - "submit is disabled" - ); - - await fillIn("#new-account-password", "aaa"); - assert.ok(exists(".password-input .bad"), "password is not valid"); - assert.ok( - exists(".invites-show .btn-primary:disabled"), - "submit is disabled" - ); - - await fillIn("#new-account-email", "john.doe@example"); - assert.ok(exists(".email-input .bad"), "email is not valid"); - assert.ok( - exists(".invites-show .btn-primary:disabled"), - "submit is disabled" - ); - - await fillIn("#new-account-username", "validname"); - await fillIn("#new-account-password", "secur3ty4Y0uAndMe"); - await fillIn("#new-account-email", "john.doe@example.com"); - assert.ok(exists(".username-input .good"), "username is valid"); - assert.ok(exists(".password-input .good"), "password is valid"); - assert.ok(exists(".email-input .good"), "email is valid"); - assert.not( - exists(".invites-show .btn-primary:disabled"), - "submit is enabled" - ); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/invite-show-user-fields-test.js b/app/assets/javascripts/discourse/tests/acceptance/invite-show-user-fields-test.js index d4d0ed9257e..b1051c65f62 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/invite-show-user-fields-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/invite-show-user-fields-test.js @@ -3,8 +3,8 @@ import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import PreloadStore from "discourse/lib/preload-store"; -acceptance("Accept Invite - User Fields", { - site: { +acceptance("Accept Invite - User Fields", function (needs) { + needs.site({ user_fields: [ { id: 34, @@ -25,57 +25,57 @@ acceptance("Accept Invite - User Fields", { required: false, }, ], - }, -}); - -test("accept invite with user fields", async (assert) => { - PreloadStore.store("invite_info", { - invited_by: { - id: 123, - username: "neil", - avatar_template: "/user_avatar/localhost/neil/{size}/25_1.png", - name: "Neil Lalonde", - title: "team", - }, - email: "invited@asdf.com", - username: "invited", - is_invite_link: false, }); - await visit("/invites/myvalidinvitetoken"); - assert.ok(exists(".invites-show"), "shows the accept invite page"); - assert.ok(exists(".user-field"), "it has at least one user field"); - assert.ok( - exists(".invites-show .btn-primary:disabled"), - "submit is disabled" - ); + test("accept invite with user fields", async (assert) => { + PreloadStore.store("invite_info", { + invited_by: { + id: 123, + username: "neil", + avatar_template: "/user_avatar/localhost/neil/{size}/25_1.png", + name: "Neil Lalonde", + title: "team", + }, + email: "invited@asdf.com", + username: "invited", + is_invite_link: false, + }); - await fillIn("#new-account-name", "John Doe"); - await fillIn("#new-account-username", "validname"); - await fillIn("#new-account-password", "secur3ty4Y0uAndMe"); + await visit("/invites/myvalidinvitetoken"); + assert.ok(exists(".invites-show"), "shows the accept invite page"); + assert.ok(exists(".user-field"), "it has at least one user field"); + assert.ok( + exists(".invites-show .btn-primary:disabled"), + "submit is disabled" + ); - assert.ok(exists(".username-input .good"), "username is valid"); - assert.ok( - exists(".invites-show .btn-primary:disabled"), - "submit is still disabled due to lack of user fields" - ); + await fillIn("#new-account-name", "John Doe"); + await fillIn("#new-account-username", "validname"); + await fillIn("#new-account-password", "secur3ty4Y0uAndMe"); - await fillIn(".user-field input[type=text]:first", "Barky"); + assert.ok(exists(".username-input .good"), "username is valid"); + assert.ok( + exists(".invites-show .btn-primary:disabled"), + "submit is still disabled due to lack of user fields" + ); - assert.ok( - exists(".invites-show .btn-primary:disabled"), - "submit is disabled because field is not checked" - ); + await fillIn(".user-field input[type=text]:first", "Barky"); - await click(".user-field input[type=checkbox]"); - assert.not( - exists(".invites-show .btn-primary:disabled"), - "submit is enabled because field is checked" - ); + assert.ok( + exists(".invites-show .btn-primary:disabled"), + "submit is disabled because field is not checked" + ); - await click(".user-field input[type=checkbox]"); - assert.ok( - exists(".invites-show .btn-primary:disabled"), - "unclicking the checkbox disables the submit" - ); + await click(".user-field input[type=checkbox]"); + assert.not( + exists(".invites-show .btn-primary:disabled"), + "submit is enabled because field is checked" + ); + + await click(".user-field input[type=checkbox]"); + assert.ok( + exists(".invites-show .btn-primary:disabled"), + "unclicking the checkbox disables the submit" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/jump-to-test.js b/app/assets/javascripts/discourse/tests/acceptance/jump-to-test.js index 58ccd1e398d..f03d197ff61 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/jump-to-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/jump-to-test.js @@ -2,12 +2,11 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Jump to", { - loggedIn: true, +acceptance("Jump to", function (needs) { + needs.user(); + needs.mobileView(); - mobileView: true, - - pretend(server, helper) { + needs.pretender((server, helper) => { server.get("/t/280/excerpts.json", () => helper.response(200, [])); server.get("/t/280/3.json", () => helper.response(200, {})); server.get("/posts/by-date/280/:date", (req) => { @@ -19,36 +18,36 @@ acceptance("Jump to", { return helper.response(404, null); }); - }, -}); - -test("default", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click("nav#topic-progress .nums"); - await click("button.jump-to-post"); - - assert.ok(exists(".jump-to-post-modal"), "it shows the modal"); - - await fillIn("input.date-picker", "2014-02-24"); - await click(".jump-to-post-modal .btn-primary"); - - assert.equal( - currentURL(), - "/t/internationalization-localization/280/3", - "it jumps to the correct post" - ); -}); - -test("invalid date", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click("nav#topic-progress .nums"); - await click("button.jump-to-post"); - await fillIn("input.date-picker", "2094-02-24"); - await click(".jump-to-post-modal .btn-primary"); - - assert.equal( - currentURL(), - "/t/internationalization-localization/280/20", - "it jumps to the last post if no post found" - ); + }); + + test("default", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click("nav#topic-progress .nums"); + await click("button.jump-to-post"); + + assert.ok(exists(".jump-to-post-modal"), "it shows the modal"); + + await fillIn("input.date-picker", "2014-02-24"); + await click(".jump-to-post-modal .btn-primary"); + + assert.equal( + currentURL(), + "/t/internationalization-localization/280/3", + "it jumps to the correct post" + ); + }); + + test("invalid date", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click("nav#topic-progress .nums"); + await click("button.jump-to-post"); + await fillIn("input.date-picker", "2094-02-24"); + await click(".jump-to-post-modal .btn-primary"); + + assert.equal( + currentURL(), + "/t/internationalization-localization/280/20", + "it jumps to the last post if no post found" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/keyboard-shortcuts-test.js b/app/assets/javascripts/discourse/tests/acceptance/keyboard-shortcuts-test.js index a82a37c5454..c68fb69264f 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/keyboard-shortcuts-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/keyboard-shortcuts-test.js @@ -1,66 +1,43 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -import pretender from "discourse/tests/helpers/create-pretender"; -acceptance("Keyboard Shortcuts", { loggedIn: true }); +acceptance("Keyboard Shortcuts", function (needs) { + needs.pretender((server, helper) => { + server.get("/t/27331/4.json", () => helper.response({})); + server.get("/t/27331.json", () => helper.response({})); -test("go to first suggested topic", async (assert) => { - pretender.get("/t/27331/4.json", () => [ - 200, - { "Content-Type": "application/json" }, - {}, - ]); + // No suggested topics exist. + server.get("/t/9/last.json", () => helper.response({})); - pretender.get("/t/27331.json", () => [ - 200, - { "Content-Type": "application/json" }, - {}, - ]); + // Suggested topic is returned by server. + server.get("/t/28830/last.json", () => { + return helper.response({ + suggested_topics: [ + { + id: 27331, + slug: "keyboard-shortcuts-are-awesome", + }, + ], + }); + }); + }); - /* - * No suggested topics exist. - */ + test("go to first suggested topic", async (assert) => { + await visit("/t/this-is-a-test-topic/9"); + await keyEvent(document, "keypress", "g".charCodeAt(0)); + await keyEvent(document, "keypress", "s".charCodeAt(0)); + assert.equal(currentURL(), "/t/this-is-a-test-topic/9"); - pretender.get("/t/9/last.json", () => [ - 200, - { "Content-Type": "application/json" }, - {}, - ]); + // Suggested topics elements exist. + await visit("/t/internationalization-localization/280"); + await keyEvent(document, "keypress", "g".charCodeAt(0)); + await keyEvent(document, "keypress", "s".charCodeAt(0)); + assert.equal(currentURL(), "/t/polls-are-still-very-buggy/27331/4"); - await visit("/t/this-is-a-test-topic/9"); - await keyEvent(document, "keypress", "g".charCodeAt(0)); - await keyEvent(document, "keypress", "s".charCodeAt(0)); - assert.equal(currentURL(), "/t/this-is-a-test-topic/9"); - - /* - * Suggested topics elements exist. - */ - - await visit("/t/internationalization-localization/280"); - await keyEvent(document, "keypress", "g".charCodeAt(0)); - await keyEvent(document, "keypress", "s".charCodeAt(0)); - assert.equal(currentURL(), "/t/polls-are-still-very-buggy/27331/4"); - - /* - * Suggested topic is returned by server. - */ - - pretender.get("/t/28830/last.json", () => [ - 200, - { "Content-Type": "application/json" }, - { - suggested_topics: [ - { - id: 27331, - slug: "keyboard-shortcuts-are-awesome", - }, - ], - }, - ]); - - await visit("/t/1-3-0beta9-no-rate-limit-popups/28830"); - await keyEvent(document, "keypress", "g".charCodeAt(0)); - await keyEvent(document, "keypress", "s".charCodeAt(0)); - assert.equal(currentURL(), "/t/keyboard-shortcuts-are-awesome/27331"); + await visit("/t/1-3-0beta9-no-rate-limit-popups/28830"); + await keyEvent(document, "keypress", "g".charCodeAt(0)); + await keyEvent(document, "keypress", "s".charCodeAt(0)); + assert.equal(currentURL(), "/t/keyboard-shortcuts-are-awesome/27331"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/login-redirect-test.js b/app/assets/javascripts/discourse/tests/acceptance/login-redirect-test.js index 424c89ba7ca..0c3ad6a9925 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/login-redirect-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/login-redirect-test.js @@ -2,27 +2,28 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Login redirect"); -test("redirects login to default homepage", async function (assert) { - await visit("/login"); - assert.equal( - currentPath(), - "discovery.latest", - "it works when latest is the homepage" - ); +acceptance("Login redirect - anonymous", function () { + test("redirects login to default homepage", async function (assert) { + await visit("/login"); + assert.equal( + currentPath(), + "discovery.latest", + "it works when latest is the homepage" + ); + }); }); -acceptance("Login redirect - categories default", { - settings: { +acceptance("Login redirect - categories default", function (needs) { + needs.settings({ top_menu: "categories|latest|top|hot", - }, -}); + }); -test("when site setting is categories", async function (assert) { - await visit("/login"); - assert.equal( - currentPath(), - "discovery.categories", - "it works when categories is the homepage" - ); + test("when site setting is categories", async function (assert) { + await visit("/login"); + assert.equal( + currentPath(), + "discovery.categories", + "it works when categories is the homepage" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/login-required-test.js b/app/assets/javascripts/discourse/tests/acceptance/login-required-test.js index f95856e1fba..f081f685cd5 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/login-required-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/login-required-test.js @@ -2,22 +2,24 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Login Required", { - settings: { - login_required: true, - }, -}); - -test("redirect", async (assert) => { - await visit("/latest"); - assert.equal(currentPath(), "login", "it redirects them to login"); - - await click("#site-logo"); - assert.equal(currentPath(), "login", "clicking the logo keeps them on login"); - - await click("header .login-button"); - assert.ok(exists(".login-modal"), "they can still access the login modal"); - - await click(".modal-header .close"); - assert.ok(invisible(".login-modal"), "it closes the login modal"); +acceptance("Login Required", function (needs) { + needs.settings({ login_required: true }); + + test("redirect", async (assert) => { + await visit("/latest"); + assert.equal(currentPath(), "login", "it redirects them to login"); + + await click("#site-logo"); + assert.equal( + currentPath(), + "login", + "clicking the logo keeps them on login" + ); + + await click("header .login-button"); + assert.ok(exists(".login-modal"), "they can still access the login modal"); + + await click(".modal-header .close"); + assert.ok(invisible(".login-modal"), "it closes the login modal"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/login-with-email-and-hide-email-address-taken-test.js b/app/assets/javascripts/discourse/tests/acceptance/login-with-email-and-hide-email-address-taken-test.js index e81fd5cb408..a7aa19c66ae 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/login-with-email-and-hide-email-address-taken-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/login-with-email-and-hide-email-address-taken-test.js @@ -2,35 +2,31 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import I18n from "I18n"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -import pretender from "discourse/tests/helpers/create-pretender"; -acceptance("Login with email - hide email address taken", { - settings: { +acceptance("Login with email - hide email address taken", function (needs) { + needs.settings({ enable_local_logins_via_email: true, hide_email_address_taken: true, - }, - beforeEach() { - const response = (object) => { - return [200, { "Content-Type": "application/json" }, object]; - }; + }); - pretender.post("/u/email-login", () => { - return response({ success: "OK" }); + needs.pretender((server, helper) => { + server.post("/u/email-login", () => { + return helper.response({ success: "OK" }); }); - }, -}); + }); -test("with hide_email_address_taken enabled", async (assert) => { - await visit("/"); - await click("header .login-button"); - await fillIn("#login-account-name", "someuser@example.com"); - await click(".login-with-email-button"); + test("with hide_email_address_taken enabled", async (assert) => { + await visit("/"); + await click("header .login-button"); + await fillIn("#login-account-name", "someuser@example.com"); + await click(".login-with-email-button"); - assert.equal( - find(".alert-success").html().trim(), - I18n.t("email_login.complete_email_found", { - email: "someuser@example.com", - }), - "it should display the success message for any email address" - ); + assert.equal( + find(".alert-success").html().trim(), + I18n.t("email_login.complete_email_found", { + email: "someuser@example.com", + }), + "it should display the success message for any email address" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/login-with-email-and-no-social-logins-test.js b/app/assets/javascripts/discourse/tests/acceptance/login-with-email-and-no-social-logins-test.js index 6f712c21676..62dc8a69221 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/login-with-email-and-no-social-logins-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/login-with-email-and-no-social-logins-test.js @@ -2,25 +2,22 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Login with email - no social logins", { - settings: { - enable_local_logins_via_email: true, - }, - pretend(server, helper) { +acceptance("Login with email - no social logins", function (needs) { + needs.settings({ enable_local_logins_via_email: true }); + needs.pretender((server, helper) => { server.post("/u/email-login", () => helper.response({ success: "OK" })); - }, -}); - -test("with login with email enabled", async (assert) => { - await visit("/"); - await click("header .login-button"); - - assert.ok(exists(".login-with-email-button")); -}); - -test("with login with email disabled", async (assert) => { - await visit("/"); - await click("header .login-button"); - - assert.notOk(find(".login-buttons").is(":visible")); + }); + test("with login with email enabled", async (assert) => { + await visit("/"); + await click("header .login-button"); + + assert.ok(exists(".login-with-email-button")); + }); + + test("with login with email disabled", async (assert) => { + await visit("/"); + await click("header .login-button"); + + assert.notOk(find(".login-buttons").is(":visible")); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/login-with-email-disabled-test.js b/app/assets/javascripts/discourse/tests/acceptance/login-with-email-disabled-test.js index 9463ca1de15..bc82f0bd3f6 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/login-with-email-disabled-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/login-with-email-disabled-test.js @@ -2,24 +2,24 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Login with email disabled", { - settings: { +acceptance("Login with email disabled", function (needs) { + needs.settings({ enable_local_logins_via_email: false, enable_facebook_logins: true, - }, -}); - -test("with email button", async (assert) => { - await visit("/"); - await click("header .login-button"); - - assert.ok( - exists(".btn-social.facebook"), - "it displays the facebook login button" - ); - - assert.notOk( - exists(".login-with-email-button"), - "it displays the login with email button" - ); + }); + + test("with email button", async (assert) => { + await visit("/"); + await click("header .login-button"); + + assert.ok( + exists(".btn-social.facebook"), + "it displays the facebook login button" + ); + + assert.notOk( + exists(".login-with-email-button"), + "it displays the login with email button" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/login-with-email-test.js b/app/assets/javascripts/discourse/tests/acceptance/login-with-email-test.js index 58ba28cb87e..45b3b2ea78f 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/login-with-email-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/login-with-email-test.js @@ -3,80 +3,80 @@ import { test } from "qunit"; import I18n from "I18n"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -let userFound = false; - -acceptance("Login with email", { - settings: { +acceptance("Login with email", function (needs) { + needs.settings({ enable_local_logins_via_email: true, enable_facebook_logins: true, - }, - pretend(server, helper) { + }); + + let userFound = false; + needs.pretender((server, helper) => { server.post("/u/email-login", () => helper.response({ success: "OK", user_found: userFound }) ); - }, -}); - -test("with email button", async (assert) => { - await visit("/"); - await click("header .login-button"); - - assert.ok( - exists(".btn-social.facebook"), - "it displays the facebook login button" - ); - - assert.ok( - exists(".login-with-email-button"), - "it displays the login with email button" - ); - - await fillIn("#login-account-name", "someuser"); - await click(".login-with-email-button"); - - assert.equal( - find(".alert-error").html(), - I18n.t("email_login.complete_username_not_found", { - username: "someuser", - }), - "it should display an error for an invalid username" - ); - - await fillIn("#login-account-name", "someuser@gmail.com"); - await click(".login-with-email-button"); - - assert.equal( - find(".alert-error").html(), - I18n.t("email_login.complete_email_not_found", { - email: "someuser@gmail.com", - }), - "it should display an error for an invalid email" - ); - - await fillIn("#login-account-name", "someuser"); - - userFound = true; - - await click(".login-with-email-button"); - - assert.equal( - find(".alert-success").html().trim(), - I18n.t("email_login.complete_username_found", { username: "someuser" }), - "it should display a success message for a valid username" - ); - - await visit("/"); - await click("header .login-button"); - await fillIn("#login-account-name", "someuser@gmail.com"); - await click(".login-with-email-button"); - - assert.equal( - find(".alert-success").html().trim(), - I18n.t("email_login.complete_email_found", { - email: "someuser@gmail.com", - }), - "it should display a success message for a valid email" - ); - - userFound = false; + }); + + test("with email button", async (assert) => { + await visit("/"); + await click("header .login-button"); + + assert.ok( + exists(".btn-social.facebook"), + "it displays the facebook login button" + ); + + assert.ok( + exists(".login-with-email-button"), + "it displays the login with email button" + ); + + await fillIn("#login-account-name", "someuser"); + await click(".login-with-email-button"); + + assert.equal( + find(".alert-error").html(), + I18n.t("email_login.complete_username_not_found", { + username: "someuser", + }), + "it should display an error for an invalid username" + ); + + await fillIn("#login-account-name", "someuser@gmail.com"); + await click(".login-with-email-button"); + + assert.equal( + find(".alert-error").html(), + I18n.t("email_login.complete_email_not_found", { + email: "someuser@gmail.com", + }), + "it should display an error for an invalid email" + ); + + await fillIn("#login-account-name", "someuser"); + + userFound = true; + + await click(".login-with-email-button"); + + assert.equal( + find(".alert-success").html().trim(), + I18n.t("email_login.complete_username_found", { username: "someuser" }), + "it should display a success message for a valid username" + ); + + await visit("/"); + await click("header .login-button"); + await fillIn("#login-account-name", "someuser@gmail.com"); + await click(".login-with-email-button"); + + assert.equal( + find(".alert-success").html().trim(), + I18n.t("email_login.complete_email_found", { + email: "someuser@gmail.com", + }), + "it should display a success message for a valid email" + ); + + userFound = false; + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/mobile-discovery-test.js b/app/assets/javascripts/discourse/tests/acceptance/mobile-discovery-test.js index 2aee9f628f7..a8baeaea814 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/mobile-discovery-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/mobile-discovery-test.js @@ -1,13 +1,15 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Topic Discovery - Mobile", { mobileView: true }); -test("Visit Discovery Pages", async (assert) => { - await visit("/"); - assert.ok(exists(".topic-list"), "The list of topics was rendered"); - assert.ok(exists(".topic-list .topic-list-item"), "has topics"); +acceptance("Topic Discovery - Mobile", function (needs) { + needs.mobileView(); + test("Visit Discovery Pages", async (assert) => { + await visit("/"); + assert.ok(exists(".topic-list"), "The list of topics was rendered"); + assert.ok(exists(".topic-list .topic-list-item"), "has topics"); - await visit("/categories"); - assert.ok(exists(".category"), "has a list of categories"); + await visit("/categories"); + assert.ok(exists(".category"), "has a list of categories"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/mobile-sign-in-test.js b/app/assets/javascripts/discourse/tests/acceptance/mobile-sign-in-test.js index 3b8c43c18f1..f59f04762be 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/mobile-sign-in-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/mobile-sign-in-test.js @@ -2,10 +2,11 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Signing In - Mobile", { mobileView: true }); - -test("sign in", async (assert) => { - await visit("/"); - await click("header .login-button"); - assert.ok(exists("#login-form"), "it shows the login modal"); +acceptance("Signing In - Mobile", function (needs) { + needs.mobileView(); + test("sign in", async (assert) => { + await visit("/"); + await click("header .login-button"); + assert.ok(exists("#login-form"), "it shows the login modal"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/mobile-users-test.js b/app/assets/javascripts/discourse/tests/acceptance/mobile-users-test.js index b3af9090778..5fb974f9745 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/mobile-users-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/mobile-users-test.js @@ -2,9 +2,10 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("User Directory - Mobile", { mobileView: true }); - -test("Visit Page", async (assert) => { - await visit("/u"); - assert.ok(exists(".directory .user"), "has a list of users"); +acceptance("User Directory - Mobile", function (needs) { + needs.mobileView(); + test("Visit Page", async (assert) => { + await visit("/u"); + assert.ok(exists(".directory .user"), "has a list of users"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/modal-test.js b/app/assets/javascripts/discourse/tests/acceptance/modal-test.js index c2427734c5a..3aa7e7f4ada 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/modal-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/modal-test.js @@ -1,5 +1,4 @@ import { visit } from "@ember/test-helpers"; -import { skip } from "qunit"; import { test } from "qunit"; import I18n from "I18n"; import { run } from "@ember/runloop"; @@ -9,9 +8,10 @@ import { } from "discourse/tests/helpers/qunit-helpers"; import showModal from "discourse/lib/show-modal"; -acceptance("Modal", { - beforeEach() { - this._translations = I18n.translations; +acceptance("Modal", function (needs) { + let _translations; + needs.hooks.beforeEach(() => { + _translations = I18n.translations; I18n.translations = { en: { @@ -20,144 +20,146 @@ acceptance("Modal", { }, }, }; - }, + }); - afterEach() { - I18n.translations = this._translations; - }, + needs.hooks.afterEach(() => { + I18n.translations = _translations; + }); + + test("modal", async function (assert) { + await visit("/"); + + assert.ok( + find(".d-modal:visible").length === 0, + "there is no modal at first" + ); + + await click(".login-button"); + assert.ok(find(".d-modal:visible").length === 1, "modal should appear"); + + let controller = controllerFor("modal"); + assert.equal(controller.name, "login"); + + await click(".modal-outer-container"); + assert.ok( + find(".d-modal:visible").length === 0, + "modal should disappear when you click outside" + ); + assert.equal(controller.name, null); + + await click(".login-button"); + assert.ok(find(".d-modal:visible").length === 1, "modal should reappear"); + + await keyEvent("#main-outlet", "keyup", 27); + assert.ok( + find(".d-modal:visible").length === 0, + "ESC should close the modal" + ); + + Ember.TEMPLATES["modal/not-dismissable"] = Ember.HTMLBars.compile( + '{{#d-modal-body title="" class="" dismissable=false}}test{{/d-modal-body}}' + ); + + run(() => showModal("not-dismissable", {})); + + assert.ok(find(".d-modal:visible").length === 1, "modal should appear"); + + await click(".modal-outer-container"); + assert.ok( + find(".d-modal:visible").length === 1, + "modal should not disappear when you click outside" + ); + await keyEvent("#main-outlet", "keyup", 27); + assert.ok( + find(".d-modal:visible").length === 1, + "ESC should not close the modal" + ); + }); + + test("rawTitle in modal panels", async function (assert) { + Ember.TEMPLATES["modal/test-raw-title-panels"] = Ember.HTMLBars.compile(""); + const panels = [ + { id: "test1", rawTitle: "Test 1" }, + { id: "test2", rawTitle: "Test 2" }, + ]; + + await visit("/"); + run(() => showModal("test-raw-title-panels", { panels })); + + assert.equal( + find(".d-modal .modal-tab:first-child").text().trim(), + "Test 1", + "it should display the raw title" + ); + }); + + test("modal title", async function (assert) { + Ember.TEMPLATES["modal/test-title"] = Ember.HTMLBars.compile(""); + Ember.TEMPLATES["modal/test-title-with-body"] = Ember.HTMLBars.compile( + "{{#d-modal-body}}test{{/d-modal-body}}" + ); + + await visit("/"); + + run(() => showModal("test-title", { title: "test_title" })); + assert.equal( + find(".d-modal .title").text().trim(), + "Test title", + "it should display the title" + ); + + await click(".d-modal .close"); + + run(() => showModal("test-title-with-body", { title: "test_title" })); + assert.equal( + find(".d-modal .title").text().trim(), + "Test title", + "it should display the title when used with d-modal-body" + ); + + await click(".d-modal .close"); + + run(() => showModal("test-title")); + assert.ok( + find(".d-modal .title").length === 0, + "it should not re-use the previous title" + ); + }); }); -skip("modal", async function (assert) { - await visit("/"); +acceptance("Modal Keyboard Events", function (needs) { + needs.user(); - assert.ok( - find(".d-modal:visible").length === 0, - "there is no modal at first" - ); + test("modal-keyboard-events", async function (assert) { + await visit("/t/internationalization-localization/280"); - await click(".login-button"); - assert.ok(find(".d-modal:visible").length === 1, "modal should appear"); + await click(".toggle-admin-menu"); + await click(".topic-admin-status-update button"); + await keyEvent(".d-modal", "keyup", 13); - let controller = controllerFor("modal"); - assert.equal(controller.name, "login"); + assert.ok( + find("#modal-alert:visible").length === 1, + "hitting Enter triggers modal action" + ); + assert.ok( + find(".d-modal:visible").length === 1, + "hitting Enter does not dismiss modal due to alert error" + ); - await click(".modal-outer-container"); - assert.ok( - find(".d-modal:visible").length === 0, - "modal should disappear when you click outside" - ); - assert.equal(controller.name, null); + await keyEvent("#main-outlet", "keyup", 27); + assert.ok( + find(".d-modal:visible").length === 0, + "ESC should close the modal" + ); - await click(".login-button"); - assert.ok(find(".d-modal:visible").length === 1, "modal should reappear"); + await click(".topic-body button.reply"); - await keyEvent("#main-outlet", "keyup", 27); - assert.ok( - find(".d-modal:visible").length === 0, - "ESC should close the modal" - ); + await click(".d-editor-button-bar .btn.link"); - Ember.TEMPLATES["modal/not-dismissable"] = Ember.HTMLBars.compile( - '{{#d-modal-body title="" class="" dismissable=false}}test{{/d-modal-body}}' - ); - - run(() => showModal("not-dismissable", {})); - - assert.ok(find(".d-modal:visible").length === 1, "modal should appear"); - - await click(".modal-outer-container"); - assert.ok( - find(".d-modal:visible").length === 1, - "modal should not disappear when you click outside" - ); - await keyEvent("#main-outlet", "keyup", 27); - assert.ok( - find(".d-modal:visible").length === 1, - "ESC should not close the modal" - ); -}); - -test("rawTitle in modal panels", async function (assert) { - Ember.TEMPLATES["modal/test-raw-title-panels"] = Ember.HTMLBars.compile(""); - const panels = [ - { id: "test1", rawTitle: "Test 1" }, - { id: "test2", rawTitle: "Test 2" }, - ]; - - await visit("/"); - run(() => showModal("test-raw-title-panels", { panels })); - - assert.equal( - find(".d-modal .modal-tab:first-child").text().trim(), - "Test 1", - "it should display the raw title" - ); -}); - -test("modal title", async function (assert) { - Ember.TEMPLATES["modal/test-title"] = Ember.HTMLBars.compile(""); - Ember.TEMPLATES["modal/test-title-with-body"] = Ember.HTMLBars.compile( - "{{#d-modal-body}}test{{/d-modal-body}}" - ); - - await visit("/"); - - run(() => showModal("test-title", { title: "test_title" })); - assert.equal( - find(".d-modal .title").text().trim(), - "Test title", - "it should display the title" - ); - - await click(".d-modal .close"); - - run(() => showModal("test-title-with-body", { title: "test_title" })); - assert.equal( - find(".d-modal .title").text().trim(), - "Test title", - "it should display the title when used with d-modal-body" - ); - - await click(".d-modal .close"); - - run(() => showModal("test-title")); - assert.ok( - find(".d-modal .title").length === 0, - "it should not re-use the previous title" - ); -}); - -acceptance("Modal Keyboard Events", { loggedIn: true }); - -test("modal-keyboard-events", async function (assert) { - await visit("/t/internationalization-localization/280"); - - await click(".toggle-admin-menu"); - await click(".topic-admin-status-update button"); - await keyEvent(".d-modal", "keyup", 13); - - assert.ok( - find("#modal-alert:visible").length === 1, - "hitting Enter triggers modal action" - ); - assert.ok( - find(".d-modal:visible").length === 1, - "hitting Enter does not dismiss modal due to alert error" - ); - - await keyEvent("#main-outlet", "keyup", 27); - assert.ok( - find(".d-modal:visible").length === 0, - "ESC should close the modal" - ); - - await click(".topic-body button.reply"); - - await click(".d-editor-button-bar .btn.link"); - - await keyEvent(".d-modal", "keyup", 13); - assert.ok( - find(".d-modal:visible").length === 0, - "modal should disappear on hitting Enter" - ); + await keyEvent(".d-modal", "keyup", 13); + assert.ok( + find(".d-modal:visible").length === 0, + "modal should disappear on hitting Enter" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/new-message-test.js b/app/assets/javascripts/discourse/tests/acceptance/new-message-test.js index a19a707de46..fbb84cd1e90 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/new-message-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/new-message-test.js @@ -2,36 +2,39 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("New Message"); +acceptance("New Message - Anonymous", function () { + test("accessing new-message route when logged out", async (assert) => { + await visit( + "/new-message?username=charlie&title=message%20title&body=message%20body" + ); -test("accessing new-message route when logged out", async (assert) => { - await visit( - "/new-message?username=charlie&title=message%20title&body=message%20body" - ); - - assert.ok(exists(".modal.login-modal"), "it shows the login modal"); + assert.ok(exists(".modal.login-modal"), "it shows the login modal"); + }); }); -acceptance("New Message", { loggedIn: true }); -test("accessing new-message route when logged in", async (assert) => { - await visit( - "/new-message?username=charlie&title=message%20title&body=message%20body" - ); +acceptance("New Message - Authenticated", function (needs) { + needs.user(); - assert.ok(exists(".composer-fields"), "it opens composer"); - assert.equal( - find("#reply-title").val().trim(), - "message title", - "it pre-fills message title" - ); - assert.equal( - find(".d-editor-input").val().trim(), - "message body", - "it pre-fills message body" - ); - assert.equal( - find(".users-input .item:eq(0)").text().trim(), - "charlie", - "it selects correct username" - ); + test("accessing new-message route when logged in", async (assert) => { + await visit( + "/new-message?username=charlie&title=message%20title&body=message%20body" + ); + + assert.ok(exists(".composer-fields"), "it opens composer"); + assert.equal( + find("#reply-title").val().trim(), + "message title", + "it pre-fills message title" + ); + assert.equal( + find(".d-editor-input").val().trim(), + "message body", + "it pre-fills message body" + ); + assert.equal( + find(".users-input .item:eq(0)").text().trim(), + "charlie", + "it selects correct username" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/new-topic-test.js b/app/assets/javascripts/discourse/tests/acceptance/new-topic-test.js index 5cbcc370565..3564fe9e025 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/new-topic-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/new-topic-test.js @@ -3,32 +3,36 @@ import { test } from "qunit"; import selectKit from "discourse/tests/helpers/select-kit-helper"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("New Topic"); +acceptance("New Topic - Anonymous", function () { + test("accessing new-topic route when logged out", async (assert) => { + await visit("/new-topic?title=topic%20title&body=topic%20body"); -test("accessing new-topic route when logged out", async (assert) => { - await visit("/new-topic?title=topic%20title&body=topic%20body"); - - assert.ok(exists(".modal.login-modal"), "it shows the login modal"); + assert.ok(exists(".modal.login-modal"), "it shows the login modal"); + }); }); -acceptance("New Topic", { loggedIn: true }); -test("accessing new-topic route when logged in", async (assert) => { - await visit("/new-topic?title=topic%20title&body=topic%20body&category=bug"); +acceptance("New Topic - Authenticated", function (needs) { + needs.user(); + test("accessing new-topic route when logged in", async (assert) => { + await visit( + "/new-topic?title=topic%20title&body=topic%20body&category=bug" + ); - assert.ok(exists(".composer-fields"), "it opens composer"); - assert.equal( - find("#reply-title").val().trim(), - "topic title", - "it pre-fills topic title" - ); - assert.equal( - find(".d-editor-input").val().trim(), - "topic body", - "it pre-fills topic body" - ); - assert.equal( - selectKit(".category-chooser").header().value(), - 1, - "it selects desired category" - ); + assert.ok(exists(".composer-fields"), "it opens composer"); + assert.equal( + find("#reply-title").val().trim(), + "topic title", + "it pre-fills topic title" + ); + assert.equal( + find(".d-editor-input").val().trim(), + "topic body", + "it pre-fills topic body" + ); + assert.equal( + selectKit(".category-chooser").header().value(), + 1, + "it selects desired category" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/notifications-filter-test.js b/app/assets/javascripts/discourse/tests/acceptance/notifications-filter-test.js index aeaa907c68c..9b5013bd48f 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/notifications-filter-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/notifications-filter-test.js @@ -3,32 +3,32 @@ import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import selectKit from "discourse/tests/helpers/select-kit-helper"; -acceptance("NotificationsFilter", { - loggedIn: true, -}); - -test("Notifications filter true", async (assert) => { - await visit("/u/eviltrout/notifications"); - - assert.ok(find(".large-notification").length >= 0); -}); - -test("Notifications filter read", async (assert) => { - await visit("/u/eviltrout/notifications"); - - const dropdown = selectKit(".notifications-filter"); - await dropdown.expand(); - await dropdown.selectRowByValue("read"); - - assert.ok(find(".large-notification").length >= 0); -}); - -test("Notifications filter unread", async (assert) => { - await visit("/u/eviltrout/notifications"); - - const dropdown = selectKit(".notifications-filter"); - await dropdown.expand(); - await dropdown.selectRowByValue("unread"); - - assert.ok(find(".large-notification").length >= 0); +acceptance("Notifications filter", function (needs) { + needs.user(); + + test("Notifications filter true", async (assert) => { + await visit("/u/eviltrout/notifications"); + + assert.ok(find(".large-notification").length >= 0); + }); + + test("Notifications filter read", async (assert) => { + await visit("/u/eviltrout/notifications"); + + const dropdown = selectKit(".notifications-filter"); + await dropdown.expand(); + await dropdown.selectRowByValue("read"); + + assert.ok(find(".large-notification").length >= 0); + }); + + test("Notifications filter unread", async (assert) => { + await visit("/u/eviltrout/notifications"); + + const dropdown = selectKit(".notifications-filter"); + await dropdown.expand(); + await dropdown.selectRowByValue("unread"); + + assert.ok(find(".large-notification").length >= 0); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/page-publishing-test.js b/app/assets/javascripts/discourse/tests/acceptance/page-publishing-test.js index c62873891f4..33033f29d9d 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/page-publishing-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/page-publishing-test.js @@ -2,9 +2,9 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Page Publishing", { - loggedIn: true, - pretend(server, helper) { +acceptance("Page Publishing", function (needs) { + needs.user(); + needs.pretender((server, helper) => { const validSlug = helper.response({ valid_slug: true }); server.put("/pub/by-topic/280", () => { @@ -22,21 +22,22 @@ acceptance("Page Publishing", { reason: "i don't need a reason", }); }); - }, -}); -test("can publish a page via modal", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click(".topic-post:eq(0) button.show-more-actions"); - await click(".topic-post:eq(0) button.show-post-admin-menu"); - await click(".topic-post:eq(0) .publish-page"); + }); - await fillIn(".publish-slug", "bad-slug"); - assert.ok(!exists(".valid-slug")); - assert.ok(exists(".invalid-slug")); - await fillIn(".publish-slug", "internationalization-localization"); - assert.ok(exists(".valid-slug")); - assert.ok(!exists(".invalid-slug")); + test("can publish a page via modal", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click(".topic-post:eq(0) button.show-more-actions"); + await click(".topic-post:eq(0) button.show-post-admin-menu"); + await click(".topic-post:eq(0) .publish-page"); - await click(".publish-page"); - assert.ok(exists(".current-url")); + await fillIn(".publish-slug", "bad-slug"); + assert.ok(!exists(".valid-slug")); + assert.ok(exists(".invalid-slug")); + await fillIn(".publish-slug", "internationalization-localization"); + assert.ok(exists(".valid-slug")); + assert.ok(!exists(".invalid-slug")); + + await click(".publish-page"); + assert.ok(exists(".current-url")); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/password-reset-test.js b/app/assets/javascripts/discourse/tests/acceptance/password-reset-test.js index e7a08c03975..8e2cdb59f9f 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/password-reset-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/password-reset-test.js @@ -5,25 +5,25 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import PreloadStore from "discourse/lib/preload-store"; import { parsePostData } from "discourse/tests/helpers/create-pretender"; -acceptance("Password Reset", { - pretend(server, helper) { +acceptance("Password Reset", function (needs) { + needs.pretender((server, helper) => { server.get("/u/confirm-email-token/myvalidtoken.json", () => - helper.response(200, { success: "OK" }) + helper.response({ success: "OK" }) ); server.get("/u/confirm-email-token/requiretwofactor.json", () => - helper.response(200, { success: "OK" }) + helper.response({ success: "OK" }) ); server.put("/u/password-reset/myvalidtoken.json", (request) => { const body = parsePostData(request.requestBody); if (body.password === "jonesyAlienSlayer") { - return helper.response(200, { + return helper.response({ success: false, errors: { password: ["is the name of your cat"] }, }); } else { - return helper.response(200, { + return helper.response({ success: "OK", message: I18n.t("password_reset.success"), }); @@ -36,87 +36,88 @@ acceptance("Password Reset", { body.password === "perf3ctly5ecur3" && body.second_factor_token === "123123" ) { - return helper.response(200, { + return helper.response({ success: "OK", message: I18n.t("password_reset.success"), }); } else if (body.second_factor_token === "123123") { - return helper.response(200, { + return helper.response({ success: false, errors: { password: ["invalid"] }, }); } else { - return helper.response(200, { + return helper.response({ success: false, message: "invalid token", errors: { user_second_factors: ["invalid token"] }, }); } }); - }, -}); - -test("Password Reset Page", async (assert) => { - PreloadStore.store("password_reset", { is_developer: false }); - - await visit("/u/password-reset/myvalidtoken"); - assert.ok(exists(".password-reset input"), "shows the input"); - - await fillIn(".password-reset input", "perf3ctly5ecur3"); - assert.ok(exists(".password-reset .tip.good"), "input looks good"); - - await fillIn(".password-reset input", "123"); - assert.ok(exists(".password-reset .tip.bad"), "input is not valid"); - assert.ok( - find(".password-reset .tip.bad") - .html() - .indexOf(I18n.t("user.password.too_short")) > -1, - "password too short" - ); - - await fillIn(".password-reset input", "jonesyAlienSlayer"); - await click(".password-reset form button"); - assert.ok(exists(".password-reset .tip.bad"), "input is not valid"); - assert.ok( - find(".password-reset .tip.bad").html().indexOf("is the name of your cat") > - -1, - "server validation error message shows" - ); - - await fillIn(".password-reset input", "perf3ctly5ecur3"); - await click(".password-reset form button"); - assert.ok(!exists(".password-reset form"), "form is gone"); -}); - -test("Password Reset Page With Second Factor", async (assert) => { - PreloadStore.store("password_reset", { - is_developer: false, - second_factor_required: true, }); - await visit("/u/password-reset/requiretwofactor"); + test("Password Reset Page", async (assert) => { + PreloadStore.store("password_reset", { is_developer: false }); - assert.notOk(exists("#new-account-password"), "does not show the input"); - assert.ok(exists("#second-factor"), "shows the second factor prompt"); + await visit("/u/password-reset/myvalidtoken"); + assert.ok(exists(".password-reset input"), "shows the input"); - await fillIn("input#second-factor", "0000"); - await click(".password-reset form button"); + await fillIn(".password-reset input", "perf3ctly5ecur3"); + assert.ok(exists(".password-reset .tip.good"), "input looks good"); - assert.ok(exists(".alert-error"), "shows 2 factor error"); + await fillIn(".password-reset input", "123"); + assert.ok(exists(".password-reset .tip.bad"), "input is not valid"); + assert.ok( + find(".password-reset .tip.bad") + .html() + .indexOf(I18n.t("user.password.too_short")) > -1, + "password too short" + ); - assert.ok( - find(".alert-error").html().indexOf("invalid token") > -1, - "shows server validation error message" - ); + await fillIn(".password-reset input", "jonesyAlienSlayer"); + await click(".password-reset form button"); + assert.ok(exists(".password-reset .tip.bad"), "input is not valid"); + assert.ok( + find(".password-reset .tip.bad") + .html() + .indexOf("is the name of your cat") > -1, + "server validation error message shows" + ); - await fillIn("input#second-factor", "123123"); - await click(".password-reset form button"); + await fillIn(".password-reset input", "perf3ctly5ecur3"); + await click(".password-reset form button"); + assert.ok(!exists(".password-reset form"), "form is gone"); + }); - assert.notOk(exists(".alert-error"), "hides error"); - assert.ok(exists("#new-account-password"), "shows the input"); + test("Password Reset Page With Second Factor", async (assert) => { + PreloadStore.store("password_reset", { + is_developer: false, + second_factor_required: true, + }); - await fillIn(".password-reset input", "perf3ctly5ecur3"); - await click(".password-reset form button"); + await visit("/u/password-reset/requiretwofactor"); - assert.ok(!exists(".password-reset form"), "form is gone"); + assert.notOk(exists("#new-account-password"), "does not show the input"); + assert.ok(exists("#second-factor"), "shows the second factor prompt"); + + await fillIn("input#second-factor", "0000"); + await click(".password-reset form button"); + + assert.ok(exists(".alert-error"), "shows 2 factor error"); + + assert.ok( + find(".alert-error").html().indexOf("invalid token") > -1, + "shows server validation error message" + ); + + await fillIn("input#second-factor", "123123"); + await click(".password-reset form button"); + + assert.notOk(exists(".alert-error"), "hides error"); + assert.ok(exists("#new-account-password"), "shows the input"); + + await fillIn(".password-reset input", "perf3ctly5ecur3"); + await click(".password-reset form button"); + + assert.ok(!exists(".password-reset form"), "form is gone"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/personal-message-test.js b/app/assets/javascripts/discourse/tests/acceptance/personal-message-test.js index 3e7110b1c08..ede9e093169 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/personal-message-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/personal-message-test.js @@ -3,24 +3,24 @@ import { test } from "qunit"; import I18n from "I18n"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Personal Message", { - loggedIn: true, -}); - -test("footer edit button", async (assert) => { - await visit("/t/pm-for-testing/12"); - - assert.ok( - !exists(".edit-message"), - "does not show edit first post button on footer by default" - ); -}); - -test("suggested messages", async (assert) => { - await visit("/t/pm-for-testing/12"); - - assert.equal( - find("#suggested-topics .suggested-topics-title").text().trim(), - I18n.t("suggested_topics.pm_title") - ); +acceptance("Personal Message", function (needs) { + needs.user(); + + test("footer edit button", async (assert) => { + await visit("/t/pm-for-testing/12"); + + assert.ok( + !exists(".edit-message"), + "does not show edit first post button on footer by default" + ); + }); + + test("suggested messages", async (assert) => { + await visit("/t/pm-for-testing/12"); + + assert.equal( + find("#suggested-topics .suggested-topics-title").text().trim(), + I18n.t("suggested_topics.pm_title") + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/plugin-keyboard-shortcut-test.js b/app/assets/javascripts/discourse/tests/acceptance/plugin-keyboard-shortcut-test.js index d4b86744634..38f544c9fc5 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/plugin-keyboard-shortcut-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/plugin-keyboard-shortcut-test.js @@ -5,49 +5,46 @@ import { withPluginApi } from "discourse/lib/plugin-api"; import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts"; import KeyboardShortcutInitializer from "discourse/initializers/keyboard-shortcuts"; -acceptance("Plugin Keyboard Shortcuts - Logged In", { - loggedIn: true, - beforeEach() { +acceptance("Plugin Keyboard Shortcuts - Logged In", function (needs) { + needs.user(); + needs.hooks.beforeEach(function () { KeyboardShortcutInitializer.initialize(this.container); - }, -}); - -test("a plugin can add a keyboard shortcut", async (assert) => { - withPluginApi("0.8.38", (api) => { - api.addKeyboardShortcut("]", () => { - $("#qunit-fixture").html( - "
Test adding plugin shortcut
" - ); - }); }); + test("a plugin can add a keyboard shortcut", async (assert) => { + withPluginApi("0.8.38", (api) => { + api.addKeyboardShortcut("]", () => { + $("#qunit-fixture").html( + "
Test adding plugin shortcut
" + ); + }); + }); - await visit("/t/this-is-a-test-topic/9"); - await keyEvent(document, "keypress", "]".charCodeAt(0)); - assert.equal( - $("#added-element").length, - 1, - "the keyboard shortcut callback fires successfully" - ); + await visit("/t/this-is-a-test-topic/9"); + await keyEvent(document, "keypress", "]".charCodeAt(0)); + assert.equal( + $("#added-element").length, + 1, + "the keyboard shortcut callback fires successfully" + ); + }); }); -acceptance("Plugin Keyboard Shortcuts - Anonymous", { - loggedIn: false, - beforeEach() { +acceptance("Plugin Keyboard Shortcuts - Anonymous", function (needs) { + needs.hooks.beforeEach(function () { KeyboardShortcutInitializer.initialize(this.container); - }, -}); - -test("a plugin can add a keyboard shortcut with an option", async (assert) => { - let spy = sandbox.spy(KeyboardShortcuts, "_bindToPath"); - withPluginApi("0.8.38", (api) => { - api.addKeyboardShortcut("]", () => {}, { - anonymous: true, - path: "test-path", - }); }); + test("a plugin can add a keyboard shortcut with an option", async (assert) => { + let spy = sandbox.spy(KeyboardShortcuts, "_bindToPath"); + withPluginApi("0.8.38", (api) => { + api.addKeyboardShortcut("]", () => {}, { + anonymous: true, + path: "test-path", + }); + }); - assert.ok( - spy.calledWith("test-path", "]"), - "bindToPath is called due to options provided" - ); + assert.ok( + spy.calledWith("test-path", "]"), + "bindToPath is called due to options provided" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-connector-class-test.js b/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-connector-class-test.js index 0096e8ec76e..21384b082a5 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-connector-class-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-connector-class-test.js @@ -5,8 +5,9 @@ import { extraConnectorClass } from "discourse/lib/plugin-connectors"; import { action } from "@ember/object"; const PREFIX = "javascripts/single-test/connectors"; -acceptance("Plugin Outlet - Connector Class", { - beforeEach() { + +acceptance("Plugin Outlet - Connector Class", function (needs) { + needs.hooks.beforeEach(() => { extraConnectorClass("user-profile-primary/hello", { actions: { sayHello() { @@ -57,33 +58,33 @@ acceptance("Plugin Outlet - Connector Class", { Ember.TEMPLATES[ `${PREFIX}/user-profile-primary/dont-render` ] = Ember.HTMLBars.compile(`I'm not rendered!`); - }, + }); - afterEach() { + needs.hooks.afterEach(() => { delete Ember.TEMPLATES[`${PREFIX}/user-profile-primary/hello`]; delete Ember.TEMPLATES[`${PREFIX}/user-profile-primary/hi`]; delete Ember.TEMPLATES[`${PREFIX}/user-profile-primary/dont-render`]; - }, -}); - -test("Renders a template into the outlet", async (assert) => { - await visit("/u/eviltrout"); - assert.ok( - find(".user-profile-primary-outlet.hello").length === 1, - "it has class names" - ); - assert.ok( - !find(".user-profile-primary-outlet.dont-render").length, - "doesn't render" - ); - - await click(".say-hello"); - assert.equal( - find(".hello-result").text(), - "hello!", - "actions delegate properly" - ); - - await click(".say-hi"); - assert.equal(find(".hi-result").text(), "hi!", "actions delegate properly"); + }); + + test("Renders a template into the outlet", async (assert) => { + await visit("/u/eviltrout"); + assert.ok( + find(".user-profile-primary-outlet.hello").length === 1, + "it has class names" + ); + assert.ok( + !find(".user-profile-primary-outlet.dont-render").length, + "doesn't render" + ); + + await click(".say-hello"); + assert.equal( + find(".hello-result").text(), + "hello!", + "actions delegate properly" + ); + + await click(".say-hi"); + assert.equal(find(".hi-result").text(), "hi!", "actions delegate properly"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-decorator-test.js b/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-decorator-test.js index 1e306decbe0..86a2560a26e 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-decorator-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-decorator-test.js @@ -4,10 +4,11 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import { withPluginApi } from "discourse/lib/plugin-api"; const PREFIX = "javascripts/single-test/connectors"; -acceptance("Plugin Outlet - Decorator", { - loggedIn: true, - beforeEach() { +acceptance("Plugin Outlet - Decorator", function (needs) { + needs.user(); + + needs.hooks.beforeEach(() => { Ember.TEMPLATES[ `${PREFIX}/discovery-list-container-top/foo` ] = Ember.HTMLBars.compile("FOO"); @@ -32,29 +33,29 @@ acceptance("Plugin Outlet - Decorator", { { id: "yellow-decorator" } ); }); - }, + }); - afterEach() { + needs.hooks.afterEach(() => { delete Ember.TEMPLATES[`${PREFIX}/discovery-list-container-top/foo`]; delete Ember.TEMPLATES[`${PREFIX}/discovery-list-container-top/bar`]; - }, -}); - -test("Calls the plugin callback with the rendered outlet", async (assert) => { - await visit("/"); - - const fooConnector = find(".discovery-list-container-top-outlet.foo ")[0]; - const barConnector = find(".discovery-list-container-top-outlet.bar ")[0]; - - assert.ok(exists(fooConnector)); - assert.equal(fooConnector.style.backgroundColor, "yellow"); - assert.equal(barConnector.style.backgroundColor, ""); - - await visit("/c/bug"); - - assert.ok(fooConnector.classList.contains("in-category")); - - await visit("/"); - - assert.notOk(fooConnector.classList.contains("in-category")); + }); + + test("Calls the plugin callback with the rendered outlet", async (assert) => { + await visit("/"); + + const fooConnector = find(".discovery-list-container-top-outlet.foo ")[0]; + const barConnector = find(".discovery-list-container-top-outlet.bar ")[0]; + + assert.ok(exists(fooConnector)); + assert.equal(fooConnector.style.backgroundColor, "yellow"); + assert.equal(barConnector.style.backgroundColor, ""); + + await visit("/c/bug"); + + assert.ok(fooConnector.classList.contains("in-category")); + + await visit("/"); + + assert.notOk(fooConnector.classList.contains("in-category")); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-multi-template-test.js b/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-multi-template-test.js index 48d88c9a40c..30163072f2f 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-multi-template-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-multi-template-test.js @@ -7,8 +7,8 @@ const HELLO = "javascripts/multi-test/connectors/user-profile-primary/hello"; const GOODBYE = "javascripts/multi-test/connectors/user-profile-primary/goodbye"; -acceptance("Plugin Outlet - Multi Template", { - beforeEach() { +acceptance("Plugin Outlet - Multi Template", function (needs) { + needs.hooks.beforeEach(() => { clearCache(); Ember.TEMPLATES[HELLO] = Ember.HTMLBars.compile( `Hello` @@ -16,33 +16,33 @@ acceptance("Plugin Outlet - Multi Template", { Ember.TEMPLATES[GOODBYE] = Ember.HTMLBars.compile( `Goodbye` ); - }, + }); - afterEach() { + needs.hooks.afterEach(() => { delete Ember.TEMPLATES[HELLO]; delete Ember.TEMPLATES[GOODBYE]; clearCache(); - }, -}); + }); -test("Renders a template into the outlet", async (assert) => { - await visit("/u/eviltrout"); - assert.ok( - find(".user-profile-primary-outlet.hello").length === 1, - "it has class names" - ); - assert.ok( - find(".user-profile-primary-outlet.goodbye").length === 1, - "it has class names" - ); - assert.equal( - find(".hello-span").text(), - "Hello", - "it renders into the outlet" - ); - assert.equal( - find(".bye-span").text(), - "Goodbye", - "it renders into the outlet" - ); + test("Renders a template into the outlet", async (assert) => { + await visit("/u/eviltrout"); + assert.ok( + find(".user-profile-primary-outlet.hello").length === 1, + "it has class names" + ); + assert.ok( + find(".user-profile-primary-outlet.goodbye").length === 1, + "it has class names" + ); + assert.equal( + find(".hello-span").text(), + "Hello", + "it renders into the outlet" + ); + assert.equal( + find(".bye-span").text(), + "Goodbye", + "it renders into the outlet" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-single-template-test.js b/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-single-template-test.js index 7f7270a86fd..2296e870d9e 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-single-template-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/plugin-outlet-single-template-test.js @@ -4,27 +4,28 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers"; const CONNECTOR = "javascripts/single-test/connectors/user-profile-primary/hello"; -acceptance("Plugin Outlet - Single Template", { - beforeEach() { + +acceptance("Plugin Outlet - Single Template", function (needs) { + needs.hooks.beforeEach(() => { Ember.TEMPLATES[CONNECTOR] = Ember.HTMLBars.compile( `{{model.username}}` ); - }, + }); - afterEach() { + needs.hooks.afterEach(() => { delete Ember.TEMPLATES[CONNECTOR]; - }, -}); + }); -test("Renders a template into the outlet", async (assert) => { - await visit("/u/eviltrout"); - assert.ok( - find(".user-profile-primary-outlet.hello").length === 1, - "it has class names" - ); - assert.equal( - find(".hello-username").text(), - "eviltrout", - "it renders into the outlet" - ); + test("Renders a template into the outlet", async (assert) => { + await visit("/u/eviltrout"); + assert.ok( + find(".user-profile-primary-outlet.hello").length === 1, + "it has class names" + ); + assert.equal( + find(".hello-username").text(), + "eviltrout", + "it renders into the outlet" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/post-admin-menu-test.js b/app/assets/javascripts/discourse/tests/acceptance/post-admin-menu-test.js index 917ce1b2aa9..643655b6be0 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/post-admin-menu-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/post-admin-menu-test.js @@ -2,33 +2,34 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Post - Admin Menu Anonymous Users", { loggedIn: false }); +acceptance("Post - Admin Menu - Anonymous", function () { + test("Enter as a anon user", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click(".show-more-actions"); -test("Enter as a anon user", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click(".show-more-actions"); - - assert.ok(exists("#topic"), "The topic was rendered"); - assert.ok( - exists("#post_1 .post-controls .edit"), - "The edit button was not rendered" - ); - assert.ok( - !exists(".show-post-admin-menu"), - "The wrench button was not rendered" - ); + assert.ok(exists("#topic"), "The topic was rendered"); + assert.ok( + exists("#post_1 .post-controls .edit"), + "The edit button was not rendered" + ); + assert.ok( + !exists(".show-post-admin-menu"), + "The wrench button was not rendered" + ); + }); }); -acceptance("Post - Admin Menu", { loggedIn: true }); +acceptance("Post - Admin Menu - Authenticated", function (needs) { + needs.user(); + test("Enter as a user with group moderator permissions", async (assert) => { + await visit("/t/topic-for-group-moderators/2480"); + await click(".show-more-actions"); + await click(".show-post-admin-menu"); -test("Enter as a user with group moderator permissions", async (assert) => { - await visit("/t/topic-for-group-moderators/2480"); - await click(".show-more-actions"); - await click(".show-post-admin-menu"); - - assert.ok( - exists("#post_1 .post-controls .edit"), - "The edit button was rendered" - ); - assert.ok(exists(".add-notice"), "The add notice button was rendered"); + assert.ok( + exists("#post_1 .post-controls .edit"), + "The edit button was rendered" + ); + assert.ok(exists(".add-notice"), "The add notice button was rendered"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js b/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js index c8d630345b3..c106cf311dd 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js @@ -66,184 +66,185 @@ function preferencesPretender(server, helper) { }); } -acceptance("User Preferences", { - loggedIn: true, - pretend: preferencesPretender, -}); +acceptance("User Preferences", function (needs) { + needs.user(); + needs.pretender(preferencesPretender); + test("update some fields", async (assert) => { + await visit("/u/eviltrout/preferences"); -test("update some fields", async (assert) => { - await visit("/u/eviltrout/preferences"); + assert.ok($("body.user-preferences-page").length, "has the body class"); + assert.equal( + currentURL(), + "/u/eviltrout/preferences/account", + "defaults to account tab" + ); + assert.ok(exists(".user-preferences"), "it shows the preferences"); - assert.ok($("body.user-preferences-page").length, "has the body class"); - assert.equal( - currentURL(), - "/u/eviltrout/preferences/account", - "defaults to account tab" - ); - assert.ok(exists(".user-preferences"), "it shows the preferences"); + const savePreferences = async () => { + assert.ok(!exists(".saved"), "it hasn't been saved yet"); + await click(".save-changes"); + assert.ok(exists(".saved"), "it displays the saved message"); + find(".saved").remove(); + }; - const savePreferences = async () => { - assert.ok(!exists(".saved"), "it hasn't been saved yet"); - await click(".save-changes"); - assert.ok(exists(".saved"), "it displays the saved message"); - find(".saved").remove(); - }; + fillIn(".pref-name input[type=text]", "Jon Snow"); + await savePreferences(); - fillIn(".pref-name input[type=text]", "Jon Snow"); - await savePreferences(); + click(".preferences-nav .nav-profile a"); + fillIn("#edit-location", "Westeros"); + await savePreferences(); - click(".preferences-nav .nav-profile a"); - fillIn("#edit-location", "Westeros"); - await savePreferences(); + click(".preferences-nav .nav-emails a"); + click(".pref-activity-summary input[type=checkbox]"); + await savePreferences(); - click(".preferences-nav .nav-emails a"); - click(".pref-activity-summary input[type=checkbox]"); - await savePreferences(); + click(".preferences-nav .nav-notifications a"); + await selectKit( + ".control-group.notifications .combo-box.duration" + ).expand(); + await selectKit( + ".control-group.notifications .combo-box.duration" + ).selectRowByValue(1440); + await savePreferences(); - click(".preferences-nav .nav-notifications a"); - await selectKit(".control-group.notifications .combo-box.duration").expand(); - await selectKit( - ".control-group.notifications .combo-box.duration" - ).selectRowByValue(1440); - await savePreferences(); - - click(".preferences-nav .nav-categories a"); - fillIn(".tracking-controls .category-selector", "faq"); - await savePreferences(); - - assert.ok( - !exists(".preferences-nav .nav-tags a"), - "tags tab isn't there when tags are disabled" - ); - - click(".preferences-nav .nav-interface a"); - click(".control-group.other input[type=checkbox]:first"); - savePreferences(); - - assert.ok( - !exists(".preferences-nav .nav-apps a"), - "apps tab isn't there when you have no authorized apps" - ); -}); - -test("username", async (assert) => { - await visit("/u/eviltrout/preferences/username"); - assert.ok(exists("#change_username"), "it has the input element"); -}); - -test("email", async (assert) => { - await visit("/u/eviltrout/preferences/email"); - - assert.ok(exists("#change-email"), "it has the input element"); - - await fillIn("#change-email", "invalidemail"); - - assert.equal( - find(".tip.bad").text().trim(), - I18n.t("user.email.invalid"), - "it should display invalid email tip" - ); -}); - -test("email field always shows up", async (assert) => { - await visit("/u/eviltrout/preferences/email"); - - assert.ok(exists("#change-email"), "it has the input element"); - - await fillIn("#change-email", "eviltrout@discourse.org"); - await click(".user-preferences button.btn-primary"); - - await visit("/u/eviltrout/preferences"); - await visit("/u/eviltrout/preferences/email"); - - assert.ok(exists("#change-email"), "it has the input element"); -}); - -test("connected accounts", async (assert) => { - await visit("/u/eviltrout/preferences/account"); - - assert.ok( - exists(".pref-associated-accounts"), - "it has the connected accounts section" - ); - assert.ok( - find(".pref-associated-accounts table tr:first td:first") - .html() - .indexOf("Facebook") > -1, - "it lists facebook" - ); - - await click(".pref-associated-accounts table tr:first td:last button"); - - find(".pref-associated-accounts table tr:first td:last button") - .html() - .indexOf("Connect") > -1; -}); - -test("second factor totp", async (assert) => { - await visit("/u/eviltrout/preferences/second-factor"); - - assert.ok(exists("#password"), "it has a password input"); - - await fillIn("#password", "secrets"); - await click(".user-preferences .btn-primary"); - assert.notOk(exists("#password"), "it hides the password input"); - - await click(".new-totp"); - assert.ok(exists("#test-qr"), "shows qr code"); - - await click(".add-totp"); - - assert.ok( - find(".alert-error").html().indexOf("provide a name and the code") > -1, - "shows name/token missing error message" - ); -}); - -test("second factor security keys", async (assert) => { - await visit("/u/eviltrout/preferences/second-factor"); - - assert.ok(exists("#password"), "it has a password input"); - - await fillIn("#password", "secrets"); - await click(".user-preferences .btn-primary"); - assert.notOk(exists("#password"), "it hides the password input"); - - await click(".new-security-key"); - assert.ok(exists("#security-key-name"), "shows security key name input"); - - fillIn("#security-key-name", ""); - - // The following tests can only run when Webauthn is enabled. This is not - // always the case, for example on a browser running on a non-standard port - if (typeof PublicKeyCredential !== "undefined") { - await click(".add-security-key"); + click(".preferences-nav .nav-categories a"); + fillIn(".tracking-controls .category-selector", "faq"); + await savePreferences(); assert.ok( - find(".alert-error").html().indexOf("provide a name") > -1, - "shows name missing error message" + !exists(".preferences-nav .nav-tags a"), + "tags tab isn't there when tags are disabled" ); - } + + click(".preferences-nav .nav-interface a"); + click(".control-group.other input[type=checkbox]:first"); + savePreferences(); + + assert.ok( + !exists(".preferences-nav .nav-apps a"), + "apps tab isn't there when you have no authorized apps" + ); + }); + + test("username", async (assert) => { + await visit("/u/eviltrout/preferences/username"); + assert.ok(exists("#change_username"), "it has the input element"); + }); + + test("email", async (assert) => { + await visit("/u/eviltrout/preferences/email"); + + assert.ok(exists("#change-email"), "it has the input element"); + + await fillIn("#change-email", "invalidemail"); + + assert.equal( + find(".tip.bad").text().trim(), + I18n.t("user.email.invalid"), + "it should display invalid email tip" + ); + }); + + test("email field always shows up", async (assert) => { + await visit("/u/eviltrout/preferences/email"); + + assert.ok(exists("#change-email"), "it has the input element"); + + await fillIn("#change-email", "eviltrout@discourse.org"); + await click(".user-preferences button.btn-primary"); + + await visit("/u/eviltrout/preferences"); + await visit("/u/eviltrout/preferences/email"); + + assert.ok(exists("#change-email"), "it has the input element"); + }); + + test("connected accounts", async (assert) => { + await visit("/u/eviltrout/preferences/account"); + + assert.ok( + exists(".pref-associated-accounts"), + "it has the connected accounts section" + ); + assert.ok( + find(".pref-associated-accounts table tr:first td:first") + .html() + .indexOf("Facebook") > -1, + "it lists facebook" + ); + + await click(".pref-associated-accounts table tr:first td:last button"); + + find(".pref-associated-accounts table tr:first td:last button") + .html() + .indexOf("Connect") > -1; + }); + + test("second factor totp", async (assert) => { + await visit("/u/eviltrout/preferences/second-factor"); + + assert.ok(exists("#password"), "it has a password input"); + + await fillIn("#password", "secrets"); + await click(".user-preferences .btn-primary"); + assert.notOk(exists("#password"), "it hides the password input"); + + await click(".new-totp"); + assert.ok(exists("#test-qr"), "shows qr code"); + + await click(".add-totp"); + + assert.ok( + find(".alert-error").html().indexOf("provide a name and the code") > -1, + "shows name/token missing error message" + ); + }); + + test("second factor security keys", async (assert) => { + await visit("/u/eviltrout/preferences/second-factor"); + + assert.ok(exists("#password"), "it has a password input"); + + await fillIn("#password", "secrets"); + await click(".user-preferences .btn-primary"); + assert.notOk(exists("#password"), "it hides the password input"); + + await click(".new-security-key"); + assert.ok(exists("#security-key-name"), "shows security key name input"); + + fillIn("#security-key-name", ""); + + // The following tests can only run when Webauthn is enabled. This is not + // always the case, for example on a browser running on a non-standard port + if (typeof PublicKeyCredential !== "undefined") { + await click(".add-security-key"); + + assert.ok( + find(".alert-error").html().indexOf("provide a name") > -1, + "shows name missing error message" + ); + } + }); + + test("default avatar selector", async (assert) => { + await visit("/u/eviltrout/preferences"); + + await click(".pref-avatar .btn"); + assert.ok(exists(".avatar-choice", "opens the avatar selection modal")); + + await click(".avatar-selector-refresh-gravatar"); + + assert.equal( + User.currentProp("gravatar_avatar_upload_id"), + 6543, + "it should set the gravatar_avatar_upload_id property" + ); + }); }); -test("default avatar selector", async (assert) => { - await visit("/u/eviltrout/preferences"); - - await click(".pref-avatar .btn"); - assert.ok(exists(".avatar-choice", "opens the avatar selection modal")); - - await click(".avatar-selector-refresh-gravatar"); - - assert.equal( - User.currentProp("gravatar_avatar_upload_id"), - 6543, - "it should set the gravatar_avatar_upload_id property" - ); -}); - -acceptance("Second Factor Backups", { - loggedIn: true, - pretend(server, helper) { +acceptance("Second Factor Backups", function (needs) { + needs.user(); + needs.pretender((server, helper) => { server.post("/u/second_factors.json", () => { return helper.response({ success: "OK", @@ -260,25 +261,28 @@ acceptance("Second Factor Backups", { server.get("/u/eviltrout/activity.json", () => { return helper.response({}); }); - }, -}); -test("second factor backup", async (assert) => { - updateCurrentUser({ second_factor_enabled: true }); - await visit("/u/eviltrout/preferences/second-factor"); - await click(".edit-2fa-backup"); - assert.ok( - exists(".second-factor-backup-preferences"), - "shows the 2fa backup panel" - ); - await click(".second-factor-backup-preferences .btn-primary"); + }); - assert.ok(exists(".backup-codes-area"), "shows backup codes"); + test("second factor backup", async (assert) => { + updateCurrentUser({ second_factor_enabled: true }); + await visit("/u/eviltrout/preferences/second-factor"); + await click(".edit-2fa-backup"); + assert.ok( + exists(".second-factor-backup-preferences"), + "shows the 2fa backup panel" + ); + await click(".second-factor-backup-preferences .btn-primary"); + + assert.ok(exists(".backup-codes-area"), "shows backup codes"); + }); }); -acceptance("Avatar selector when selectable avatars is enabled", { - loggedIn: true, - settings: { selectable_avatars_enabled: true }, - pretend(server) { +acceptance("Avatar selector when selectable avatars is enabled", function ( + needs +) { + needs.user(); + needs.settings({ selectable_avatars_enabled: true }); + needs.pretender((server) => { server.get("/site/selectable-avatars.json", () => { return [ 200, @@ -286,127 +290,129 @@ acceptance("Avatar selector when selectable avatars is enabled", { ["https://www.discourse.org", "https://meta.discourse.org"], ]; }); - }, + }); + + test("selectable avatars", async (assert) => { + await visit("/u/eviltrout/preferences"); + await click(".pref-avatar .btn"); + assert.ok( + exists(".selectable-avatars", "opens the avatar selection modal") + ); + }); }); -test("selectable avatars", async (assert) => { - await visit("/u/eviltrout/preferences"); +acceptance("User Preferences when badges are disabled", function (needs) { + needs.user(); + needs.settings({ enable_badges: false }); + needs.pretender(preferencesPretender); - await click(".pref-avatar .btn"); + test("visit my preferences", async (assert) => { + await visit("/u/eviltrout/preferences"); + assert.ok($("body.user-preferences-page").length, "has the body class"); + assert.equal( + currentURL(), + "/u/eviltrout/preferences/account", + "defaults to account tab" + ); + assert.ok(exists(".user-preferences"), "it shows the preferences"); + }); - assert.ok(exists(".selectable-avatars", "opens the avatar selection modal")); -}); + test("recently connected devices", async (assert) => { + await visit("/u/eviltrout/preferences"); -acceptance("User Preferences when badges are disabled", { - loggedIn: true, - settings: { enable_badges: false }, - pretend: preferencesPretender, -}); + assert.equal( + find(".auth-tokens > .auth-token:first .auth-token-device").text().trim(), + "Linux Computer", + "it should display active token first" + ); -test("visit my preferences", async (assert) => { - await visit("/u/eviltrout/preferences"); - assert.ok($("body.user-preferences-page").length, "has the body class"); - assert.equal( - currentURL(), - "/u/eviltrout/preferences/account", - "defaults to account tab" - ); - assert.ok(exists(".user-preferences"), "it shows the preferences"); -}); + assert.equal( + find(".pref-auth-tokens > a:first").text().trim(), + I18n.t("user.auth_tokens.show_all", { count: 3 }), + "it should display two tokens" + ); + assert.ok( + find(".pref-auth-tokens .auth-token").length === 2, + "it should display two tokens" + ); -test("recently connected devices", async (assert) => { - await visit("/u/eviltrout/preferences"); + await click(".pref-auth-tokens > a:first"); - assert.equal( - find(".auth-tokens > .auth-token:first .auth-token-device").text().trim(), - "Linux Computer", - "it should display active token first" - ); + assert.ok( + find(".pref-auth-tokens .auth-token").length === 3, + "it should display three tokens" + ); - assert.equal( - find(".pref-auth-tokens > a:first").text().trim(), - I18n.t("user.auth_tokens.show_all", { count: 3 }), - "it should display two tokens" - ); - assert.ok( - find(".pref-auth-tokens .auth-token").length === 2, - "it should display two tokens" - ); + await click(".auth-token-dropdown:first button"); + await click("li[data-value='notYou']"); - await click(".pref-auth-tokens > a:first"); + assert.ok(find(".d-modal:visible").length === 1, "modal should appear"); - assert.ok( - find(".pref-auth-tokens .auth-token").length === 3, - "it should display three tokens" - ); + await click(".modal-footer .btn-primary"); - await click(".auth-token-dropdown:first button"); - await click("li[data-value='notYou']"); - - assert.ok(find(".d-modal:visible").length === 1, "modal should appear"); - - await click(".modal-footer .btn-primary"); - - assert.ok( - find(".pref-password.highlighted").length === 1, - "it should highlight password preferences" - ); + assert.ok( + find(".pref-password.highlighted").length === 1, + "it should highlight password preferences" + ); + }); }); acceptance( "User can select a topic to feature on profile if site setting in enabled", - { - loggedIn: true, - settings: { allow_featured_topic_on_user_profiles: true }, - - pretend(server, helper) { + function (needs) { + needs.user(); + needs.settings({ allow_featured_topic_on_user_profiles: true }); + needs.pretender((server, helper) => { server.put("/u/eviltrout/feature-topic", () => { return helper.response({ success: true, }); }); - }, + }); + + test("setting featured topic on profile", async (assert) => { + await visit("/u/eviltrout/preferences/profile"); + + assert.ok( + !exists(".featured-topic-link"), + "no featured topic link to present" + ); + assert.ok( + !exists(".clear-feature-topic-on-profile-btn"), + "clear button not present" + ); + + const selectTopicBtn = find(".feature-topic-on-profile-btn:first"); + assert.ok(exists(selectTopicBtn), "feature topic button is present"); + + await click(selectTopicBtn); + + assert.ok( + exists(".feature-topic-on-profile"), + "topic picker modal is open" + ); + + const topicRadioBtn = find('input[name="choose_topic_id"]:first'); + assert.ok(exists(topicRadioBtn), "Topic options are prefilled"); + await click(topicRadioBtn); + + await click(".save-featured-topic-on-profile"); + + assert.ok( + exists(".featured-topic-link"), + "link to featured topic is present" + ); + assert.ok( + exists(".clear-feature-topic-on-profile-btn"), + "clear button is present" + ); + }); } ); -test("setting featured topic on profile", async (assert) => { - await visit("/u/eviltrout/preferences/profile"); - - assert.ok( - !exists(".featured-topic-link"), - "no featured topic link to present" - ); - assert.ok( - !exists(".clear-feature-topic-on-profile-btn"), - "clear button not present" - ); - - const selectTopicBtn = find(".feature-topic-on-profile-btn:first"); - assert.ok(exists(selectTopicBtn), "feature topic button is present"); - - await click(selectTopicBtn); - - assert.ok(exists(".feature-topic-on-profile"), "topic picker modal is open"); - - const topicRadioBtn = find('input[name="choose_topic_id"]:first'); - assert.ok(exists(topicRadioBtn), "Topic options are prefilled"); - await click(topicRadioBtn); - - await click(".save-featured-topic-on-profile"); - - assert.ok( - exists(".featured-topic-link"), - "link to featured topic is present" - ); - assert.ok( - exists(".clear-feature-topic-on-profile-btn"), - "clear button is present" - ); -}); - -acceptance("Custom User Fields", { - loggedIn: true, - site: { +acceptance("Custom User Fields", function (needs) { + needs.user(); + needs.site({ user_fields: [ { id: 30, @@ -416,46 +422,50 @@ acceptance("Custom User Fields", { required: true, }, ], - }, - pretend: preferencesPretender, -}); + }); + needs.pretender(preferencesPretender); -test("can select an option from a dropdown", async (assert) => { - await visit("/u/eviltrout/preferences/profile"); - assert.ok(exists(".user-field"), "it has at least one user field"); - await click(".user-field.dropdown"); + test("can select an option from a dropdown", async (assert) => { + await visit("/u/eviltrout/preferences/profile"); + assert.ok(exists(".user-field"), "it has at least one user field"); + await click(".user-field.dropdown"); - const field = selectKit( - ".user-field-what-kind-of-pet-do-you-have .combo-box" - ); - await field.expand(); - await field.selectRowByValue("Cat"); - assert.equal(field.header().value(), "Cat", "it sets the value of the field"); + const field = selectKit( + ".user-field-what-kind-of-pet-do-you-have .combo-box" + ); + await field.expand(); + await field.selectRowByValue("Cat"); + assert.equal( + field.header().value(), + "Cat", + "it sets the value of the field" + ); + }); }); acceptance( "User Preferences, selecting bookmarks discovery as user's default homepage", - { - loggedIn: true, - settings: { + function (needs) { + needs.user(); + needs.settings({ top_menu: "categories|latest|top|bookmarks", - }, + }); + + test("selecting bookmarks as home directs home to bookmarks", async (assert) => { + await visit("/u/eviltrout/preferences/interface"); + assert.ok(exists(".home .combo-box"), "it has a home selector combo-box"); + + const field = selectKit(".home .combo-box"); + await field.expand(); + await field.selectRowByValue("6"); + await click(".save-changes"); + await visit("/"); + assert.ok(exists(".topic-list"), "The list of topics was rendered"); + assert.equal( + currentPath(), + "discovery.bookmarks", + "it navigates to bookmarks" + ); + }); } ); - -test("selecting bookmarks as home directs home to bookmarks", async (assert) => { - await visit("/u/eviltrout/preferences/interface"); - assert.ok(exists(".home .combo-box"), "it has a home selector combo-box"); - - const field = selectKit(".home .combo-box"); - await field.expand(); - await field.selectRowByValue("6"); - await click(".save-changes"); - await visit("/"); - assert.ok(exists(".topic-list"), "The list of topics was rendered"); - assert.equal( - currentPath(), - "discovery.bookmarks", - "it navigates to bookmarks" - ); -}); diff --git a/app/assets/javascripts/discourse/tests/acceptance/raw-plugin-outlet-test.js b/app/assets/javascripts/discourse/tests/acceptance/raw-plugin-outlet-test.js index 150cc4b7d16..4e661e746b1 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/raw-plugin-outlet-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/raw-plugin-outlet-test.js @@ -10,25 +10,24 @@ import { const CONNECTOR = "javascripts/raw-test/connectors/topic-list-before-status/lala"; -acceptance("Raw Plugin Outlet", { - beforeEach() { +acceptance("Raw Plugin Outlet", function (needs) { + needs.hooks.beforeEach(() => { addRawTemplate( CONNECTOR, compile(`{{context.topic.id}}`) ); - }, + }); - afterEach() { + needs.hooks.afterEach(() => { removeRawTemplate(CONNECTOR); - }, -}); - -test("Renders the raw plugin outlet", async (assert) => { - await visit("/"); - assert.ok(find(".topic-lala").length > 0, "it renders the outlet"); - assert.equal( - find(".topic-lala:eq(0)").text(), - "11557", - "it has the topic id" - ); + }); + test("Renders the raw plugin outlet", async (assert) => { + await visit("/"); + assert.ok(find(".topic-lala").length > 0, "it renders the outlet"); + assert.equal( + find(".topic-lala:eq(0)").text(), + "11557", + "it has the topic id" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/redirect-to-top-test.js b/app/assets/javascripts/discourse/tests/acceptance/redirect-to-top-test.js index 860261ffc4c..eed2fdbc17a 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/redirect-to-top-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/redirect-to-top-test.js @@ -6,8 +6,8 @@ import { } from "discourse/tests/helpers/qunit-helpers"; import DiscoveryFixtures from "discourse/tests/fixtures/discovery-fixtures"; -acceptance("Redirect to Top", { - pretend(server, helper) { +acceptance("Redirect to Top", function (needs) { + needs.pretender((server, helper) => { server.get("/top/weekly.json", () => { return helper.response(DiscoveryFixtures["/latest.json"]); }); @@ -17,45 +17,49 @@ acceptance("Redirect to Top", { server.get("/top/all.json", () => { return helper.response(DiscoveryFixtures["/latest.json"]); }); - }, - loggedIn: true, -}); + }); + needs.user(); -test("redirects categories to weekly top", async (assert) => { - updateCurrentUser({ - should_be_redirected_to_top: true, - redirected_to_top: { - period: "weekly", - reason: "Welcome back!", - }, + test("redirects categories to weekly top", async (assert) => { + updateCurrentUser({ + should_be_redirected_to_top: true, + redirected_to_top: { + period: "weekly", + reason: "Welcome back!", + }, + }); + + await visit("/categories"); + assert.equal( + currentPath(), + "discovery.topWeekly", + "it works for categories" + ); }); - await visit("/categories"); - assert.equal(currentPath(), "discovery.topWeekly", "it works for categories"); -}); + test("redirects latest to monthly top", async (assert) => { + updateCurrentUser({ + should_be_redirected_to_top: true, + redirected_to_top: { + period: "monthly", + reason: "Welcome back!", + }, + }); -test("redirects latest to monthly top", async (assert) => { - updateCurrentUser({ - should_be_redirected_to_top: true, - redirected_to_top: { - period: "monthly", - reason: "Welcome back!", - }, + await visit("/latest"); + assert.equal(currentPath(), "discovery.topMonthly", "it works for latest"); }); - await visit("/latest"); - assert.equal(currentPath(), "discovery.topMonthly", "it works for latest"); -}); + test("redirects root to All top", async (assert) => { + updateCurrentUser({ + should_be_redirected_to_top: true, + redirected_to_top: { + period: null, + reason: "Welcome back!", + }, + }); -test("redirects root to All top", async (assert) => { - updateCurrentUser({ - should_be_redirected_to_top: true, - redirected_to_top: { - period: null, - reason: "Welcome back!", - }, + await visit("/"); + assert.equal(currentPath(), "discovery.topAll", "it works for root"); }); - - await visit("/"); - assert.equal(currentPath(), "discovery.topAll", "it works for root"); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/reports-test.js b/app/assets/javascripts/discourse/tests/acceptance/reports-test.js index 425d678899b..41ed562a3c9 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/reports-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/reports-test.js @@ -2,27 +2,27 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Reports", { - loggedIn: true, -}); - -test("Visit reports page", async (assert) => { - await visit("/admin/reports"); - - assert.equal($(".reports-list .report").length, 1); - - const $report = $(".reports-list .report:first-child"); - - assert.equal($report.find(".report-title").html().trim(), "My report"); - - assert.equal( - $report.find(".report-description").html().trim(), - "List of my activities" - ); -}); - -test("Visit report page", async (assert) => { - await visit("/admin/reports/staff_logins"); - - assert.ok(exists(".export-csv-btn")); +acceptance("Reports", function (needs) { + needs.user(); + + test("Visit reports page", async (assert) => { + await visit("/admin/reports"); + + assert.equal($(".reports-list .report").length, 1); + + const $report = $(".reports-list .report:first-child"); + + assert.equal($report.find(".report-title").html().trim(), "My report"); + + assert.equal( + $report.find(".report-description").html().trim(), + "List of my activities" + ); + }); + + test("Visit report page", async (assert) => { + await visit("/admin/reports/staff_logins"); + + assert.ok(exists(".export-csv-btn")); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/review-test.js b/app/assets/javascripts/discourse/tests/acceptance/review-test.js index 72af96ad52e..0631f2691f1 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/review-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/review-test.js @@ -3,132 +3,132 @@ import { test } from "qunit"; import selectKit from "discourse/tests/helpers/select-kit-helper"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Review", { - loggedIn: true, -}); - -const user = ".reviewable-item[data-reviewable-id=1234]"; - -test("It returns a list of reviewable items", async (assert) => { - await visit("/review"); - - assert.ok(find(".reviewable-item").length, "has a list of items"); - assert.ok(find(user).length); - assert.ok( - find(`${user}.reviewable-user`).length, - "applies a class for the type" - ); - assert.ok( - find(`${user} .reviewable-action.approve`).length, - "creates a button for approve" - ); - assert.ok( - find(`${user} .reviewable-action.reject`).length, - "creates a button for reject" - ); -}); - -test("Grouped by topic", async (assert) => { - await visit("/review/topics"); - assert.ok( - find(".reviewable-topic").length, - "it has a list of reviewable topics" - ); -}); - -test("Settings", async (assert) => { - await visit("/review/settings"); - - assert.ok(find(".reviewable-score-type").length, "has a list of bonuses"); - - const field = selectKit(".reviewable-score-type:eq(0) .field .combo-box"); - await field.expand(); - await field.selectRowByValue("5"); - await click(".save-settings"); - - assert.ok(find(".reviewable-settings .saved").length, "it saved"); -}); - -test("Flag related", async (assert) => { - await visit("/review"); - - assert.ok( - find(".reviewable-flagged-post .post-contents .username a[href]").length, - "it has a link to the user" - ); - - assert.equal( - find(".reviewable-flagged-post .post-body").html().trim(), - "cooked content" - ); - - assert.equal(find(".reviewable-flagged-post .reviewable-score").length, 2); -}); - -test("Flag related", async (assert) => { - await visit("/review/1"); - - assert.ok( - find(".reviewable-flagged-post").length, - "it shows the flagged post" - ); -}); - -test("Clicking the buttons triggers actions", async (assert) => { - await visit("/review"); - await click(`${user} .reviewable-action.approve`); - assert.equal(find(user).length, 0, "it removes the reviewable on success"); -}); - -test("Editing a reviewable", async (assert) => { - const topic = ".reviewable-item[data-reviewable-id=4321]"; - await visit("/review"); - assert.ok(find(`${topic} .reviewable-action.approve`).length); - assert.ok(!find(`${topic} .category-name`).length); - assert.equal(find(`${topic} .discourse-tag:eq(0)`).text(), "hello"); - assert.equal(find(`${topic} .discourse-tag:eq(1)`).text(), "world"); - - assert.equal(find(`${topic} .post-body`).text().trim(), "existing body"); - - await click(`${topic} .reviewable-action.edit`); - await click(`${topic} .reviewable-action.save-edit`); - assert.ok( - find(`${topic} .reviewable-action.approve`).length, - "saving without changes is a cancel" - ); - await click(`${topic} .reviewable-action.edit`); - - assert.equal( - find(`${topic} .reviewable-action.approve`).length, - 0, - "when editing actions are disabled" - ); - - await fillIn(".editable-field.payload-raw textarea", "new raw contents"); - await click(`${topic} .reviewable-action.cancel-edit`); - assert.equal( - find(`${topic} .post-body`).text().trim(), - "existing body", - "cancelling does not update the value" - ); - - await click(`${topic} .reviewable-action.edit`); - let category = selectKit(`${topic} .category-id .select-kit`); - await category.expand(); - await category.selectRowByValue("6"); - - let tags = selectKit(`${topic} .payload-tags .mini-tag-chooser`); - await tags.expand(); - await tags.fillInFilter("monkey"); - await tags.selectRowByValue("monkey"); - - await fillIn(".editable-field.payload-raw textarea", "new raw contents"); - await click(`${topic} .reviewable-action.save-edit`); - - assert.equal(find(`${topic} .discourse-tag:eq(0)`).text(), "hello"); - assert.equal(find(`${topic} .discourse-tag:eq(1)`).text(), "world"); - assert.equal(find(`${topic} .discourse-tag:eq(2)`).text(), "monkey"); - - assert.equal(find(`${topic} .post-body`).text().trim(), "new raw contents"); - assert.equal(find(`${topic} .category-name`).text().trim(), "support"); +acceptance("Review", function (needs) { + needs.user(); + + const user = ".reviewable-item[data-reviewable-id=1234]"; + + test("It returns a list of reviewable items", async (assert) => { + await visit("/review"); + + assert.ok(find(".reviewable-item").length, "has a list of items"); + assert.ok(find(user).length); + assert.ok( + find(`${user}.reviewable-user`).length, + "applies a class for the type" + ); + assert.ok( + find(`${user} .reviewable-action.approve`).length, + "creates a button for approve" + ); + assert.ok( + find(`${user} .reviewable-action.reject`).length, + "creates a button for reject" + ); + }); + + test("Grouped by topic", async (assert) => { + await visit("/review/topics"); + assert.ok( + find(".reviewable-topic").length, + "it has a list of reviewable topics" + ); + }); + + test("Settings", async (assert) => { + await visit("/review/settings"); + + assert.ok(find(".reviewable-score-type").length, "has a list of bonuses"); + + const field = selectKit(".reviewable-score-type:eq(0) .field .combo-box"); + await field.expand(); + await field.selectRowByValue("5"); + await click(".save-settings"); + + assert.ok(find(".reviewable-settings .saved").length, "it saved"); + }); + + test("Flag related", async (assert) => { + await visit("/review"); + + assert.ok( + find(".reviewable-flagged-post .post-contents .username a[href]").length, + "it has a link to the user" + ); + + assert.equal( + find(".reviewable-flagged-post .post-body").html().trim(), + "cooked content" + ); + + assert.equal(find(".reviewable-flagged-post .reviewable-score").length, 2); + }); + + test("Flag related", async (assert) => { + await visit("/review/1"); + + assert.ok( + find(".reviewable-flagged-post").length, + "it shows the flagged post" + ); + }); + + test("Clicking the buttons triggers actions", async (assert) => { + await visit("/review"); + await click(`${user} .reviewable-action.approve`); + assert.equal(find(user).length, 0, "it removes the reviewable on success"); + }); + + test("Editing a reviewable", async (assert) => { + const topic = ".reviewable-item[data-reviewable-id=4321]"; + await visit("/review"); + assert.ok(find(`${topic} .reviewable-action.approve`).length); + assert.ok(!find(`${topic} .category-name`).length); + assert.equal(find(`${topic} .discourse-tag:eq(0)`).text(), "hello"); + assert.equal(find(`${topic} .discourse-tag:eq(1)`).text(), "world"); + + assert.equal(find(`${topic} .post-body`).text().trim(), "existing body"); + + await click(`${topic} .reviewable-action.edit`); + await click(`${topic} .reviewable-action.save-edit`); + assert.ok( + find(`${topic} .reviewable-action.approve`).length, + "saving without changes is a cancel" + ); + await click(`${topic} .reviewable-action.edit`); + + assert.equal( + find(`${topic} .reviewable-action.approve`).length, + 0, + "when editing actions are disabled" + ); + + await fillIn(".editable-field.payload-raw textarea", "new raw contents"); + await click(`${topic} .reviewable-action.cancel-edit`); + assert.equal( + find(`${topic} .post-body`).text().trim(), + "existing body", + "cancelling does not update the value" + ); + + await click(`${topic} .reviewable-action.edit`); + let category = selectKit(`${topic} .category-id .select-kit`); + await category.expand(); + await category.selectRowByValue("6"); + + let tags = selectKit(`${topic} .payload-tags .mini-tag-chooser`); + await tags.expand(); + await tags.fillInFilter("monkey"); + await tags.selectRowByValue("monkey"); + + await fillIn(".editable-field.payload-raw textarea", "new raw contents"); + await click(`${topic} .reviewable-action.save-edit`); + + assert.equal(find(`${topic} .discourse-tag:eq(0)`).text(), "hello"); + assert.equal(find(`${topic} .discourse-tag:eq(1)`).text(), "world"); + assert.equal(find(`${topic} .discourse-tag:eq(2)`).text(), "monkey"); + + assert.equal(find(`${topic} .post-body`).text().trim(), "new raw contents"); + assert.equal(find(`${topic} .category-name`).text().trim(), "support"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js b/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js index 4c27297ee37..5d6a02a6409 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js @@ -8,10 +8,10 @@ import { waitFor, } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Search - Full Page", { - settings: { tagging_enabled: true }, - loggedIn: true, - pretend(server, helper) { +acceptance("Search - Full Page", function (needs) { + needs.user(); + needs.settings({ tagging_enabled: true }); + needs.pretender((server, helper) => { server.get("/tags/filter/search", () => { return helper.response({ results: [{ text: "monkey", count: 1 }] }); }); @@ -87,337 +87,337 @@ acceptance("Search - Full Page", { ], }); }); - }, -}); + }); -test("perform various searches", async (assert) => { - await visit("/search"); + test("perform various searches", async (assert) => { + await visit("/search"); - assert.ok($("body.search-page").length, "has body class"); - assert.ok(exists(".search-container"), "has container class"); - assert.ok(find(".search-query").length > 0); - assert.ok(find(".fps-topic").length === 0); + assert.ok($("body.search-page").length, "has body class"); + assert.ok(exists(".search-container"), "has container class"); + assert.ok(find(".search-query").length > 0); + assert.ok(find(".fps-topic").length === 0); - await fillIn(".search-query", "none"); - await click(".search-cta"); + await fillIn(".search-query", "none"); + await click(".search-cta"); - assert.ok(find(".fps-topic").length === 0, "has no results"); - assert.ok(find(".no-results-suggestion .google-search-form")); + assert.ok(find(".fps-topic").length === 0, "has no results"); + assert.ok(find(".no-results-suggestion .google-search-form")); - await fillIn(".search-query", "posts"); - await click(".search-cta"); + await fillIn(".search-query", "posts"); + await click(".search-cta"); - assert.ok(find(".fps-topic").length === 1, "has one post"); -}); + assert.ok(find(".fps-topic").length === 1, "has one post"); + }); -test("escape search term", async (assert) => { - await visit("/search"); - await fillIn(".search-query", "@gmail.com"); + test("escape search term", async (assert) => { + await visit("/search"); + await fillIn(".search-query", "@gmail.com"); - assert.ok( - exists( - '.search-advanced-options span:contains("<script>prompt(1337)</script>gmail.com")' - ), - "it escapes search term" - ); -}); - -skip("update username through advanced search ui", async (assert) => { - await visit("/search"); - await fillIn(".search-query", "none"); - await fillIn(".search-advanced-options .user-selector", "admin"); - await click(".search-advanced-options .user-selector"); - await keyEvent(".search-advanced-options .user-selector", "keydown", 8); - - waitFor(assert, async () => { - assert.ok( - visible(".search-advanced-options .autocomplete"), - '"autocomplete" popup is visible' - ); assert.ok( exists( - '.search-advanced-options .autocomplete ul li a span.username:contains("admin")' + '.search-advanced-options span:contains("<script>prompt(1337)</script>gmail.com")' ), - '"autocomplete" popup has an entry for "admin"' + "it escapes search term" + ); + }); + + skip("update username through advanced search ui", async (assert) => { + await visit("/search"); + await fillIn(".search-query", "none"); + await fillIn(".search-advanced-options .user-selector", "admin"); + await click(".search-advanced-options .user-selector"); + await keyEvent(".search-advanced-options .user-selector", "keydown", 8); + + waitFor(assert, async () => { + assert.ok( + visible(".search-advanced-options .autocomplete"), + '"autocomplete" popup is visible' + ); + assert.ok( + exists( + '.search-advanced-options .autocomplete ul li a span.username:contains("admin")' + ), + '"autocomplete" popup has an entry for "admin"' + ); + + await click(".search-advanced-options .autocomplete ul li a:first"); + + assert.ok( + exists('.search-advanced-options span:contains("admin")'), + 'has "admin" pre-populated' + ); + assert.equal( + find(".search-query").val(), + "none @admin", + 'has updated search term to "none user:admin"' + ); + }); + }); + + test("update category through advanced search ui", async (assert) => { + const categoryChooser = selectKit( + ".search-advanced-options .category-chooser" ); - await click(".search-advanced-options .autocomplete ul li a:first"); + await visit("/search"); + + await fillIn(".search-query", "none"); + + await categoryChooser.expand(); + await categoryChooser.fillInFilter("faq"); + await categoryChooser.selectRowByValue(4); assert.ok( - exists('.search-advanced-options span:contains("admin")'), - 'has "admin" pre-populated' + exists('.search-advanced-options .badge-category:contains("faq")'), + 'has "faq" populated' ); assert.equal( find(".search-query").val(), - "none @admin", - 'has updated search term to "none user:admin"' + "none #faq", + 'has updated search term to "none #faq"' + ); + }); + + test("update in:title filter through advanced search ui", async (assert) => { + await visit("/search"); + await fillIn(".search-query", "none"); + await click(".search-advanced-options .in-title"); + + assert.ok( + exists(".search-advanced-options .in-title:checked"), + 'has "in title" populated' + ); + assert.equal( + find(".search-query").val(), + "none in:title", + 'has updated search term to "none in:title"' + ); + + await fillIn(".search-query", "none in:titleasd"); + + assert.not( + exists(".search-advanced-options .in-title:checked"), + "does not populate title only checkbox" + ); + }); + + test("update in:likes filter through advanced search ui", async (assert) => { + await visit("/search"); + await fillIn(".search-query", "none"); + await click(".search-advanced-options .in-likes"); + + assert.ok( + exists(".search-advanced-options .in-likes:checked"), + 'has "I liked" populated' + ); + assert.equal( + find(".search-query").val(), + "none in:likes", + 'has updated search term to "none in:likes"' + ); + }); + + test("update in:personal filter through advanced search ui", async (assert) => { + await visit("/search"); + await fillIn(".search-query", "none"); + await click(".search-advanced-options .in-private"); + + assert.ok( + exists(".search-advanced-options .in-private:checked"), + 'has "are in my messages" populated' + ); + + assert.equal( + find(".search-query").val(), + "none in:personal", + 'has updated search term to "none in:personal"' + ); + + await fillIn(".search-query", "none in:personal-direct"); + + assert.not( + exists(".search-advanced-options .in-private:checked"), + "does not populate messages checkbox" + ); + }); + + test("update in:seen filter through advanced search ui", async (assert) => { + await visit("/search"); + await fillIn(".search-query", "none"); + await click(".search-advanced-options .in-seen"); + + assert.ok( + exists(".search-advanced-options .in-seen:checked"), + "it should check the right checkbox" + ); + + assert.equal( + find(".search-query").val(), + "none in:seen", + "it should update the search term" + ); + + await fillIn(".search-query", "none in:seenasdan"); + + assert.not( + exists(".search-advanced-options .in-seen:checked"), + "does not populate seen checkbox" + ); + }); + + test("update in filter through advanced search ui", async (assert) => { + const inSelector = selectKit(".search-advanced-options .select-kit#in"); + + await visit("/search"); + + await fillIn(".search-query", "none"); + await inSelector.expand(); + await inSelector.selectRowByValue("bookmarks"); + + assert.equal( + inSelector.header().label(), + "I bookmarked", + 'has "I bookmarked" populated' + ); + assert.equal( + find(".search-query").val(), + "none in:bookmarks", + 'has updated search term to "none in:bookmarks"' + ); + }); + + test("update status through advanced search ui", async (assert) => { + const statusSelector = selectKit( + ".search-advanced-options .select-kit#status" + ); + + await visit("/search"); + + await fillIn(".search-query", "none"); + await statusSelector.expand(); + await statusSelector.selectRowByValue("closed"); + + assert.equal( + statusSelector.header().label(), + "are closed", + 'has "are closed" populated' + ); + assert.equal( + find(".search-query").val(), + "none status:closed", + 'has updated search term to "none status:closed"' + ); + }); + + test("doesn't update status filter header if wrong value entered through searchbox", async (assert) => { + const statusSelector = selectKit( + ".search-advanced-options .select-kit#status" + ); + + await visit("/search"); + + await fillIn(".search-query", "status:none"); + + assert.equal(statusSelector.header().label(), "any", 'has "any" populated'); + }); + + test("doesn't update in filter header if wrong value entered through searchbox", async (assert) => { + const inSelector = selectKit(".search-advanced-options .select-kit#in"); + + await visit("/search"); + + await fillIn(".search-query", "in:none"); + + assert.equal(inSelector.header().label(), "any", 'has "any" populated'); + }); + + test("update post time through advanced search ui", async (assert) => { + await visit("/search?expanded=true&q=after:2018-08-22"); + + assert.equal( + find(".search-query").val(), + "after:2018-08-22", + "it should update the search term correctly" + ); + + await visit("/search"); + + await fillIn(".search-query", "none"); + await selectDate("#search-post-date .date-picker", "2016-10-05"); + + const postTimeSelector = selectKit( + ".search-advanced-options .select-kit#postTime" + ); + await postTimeSelector.expand(); + await postTimeSelector.selectRowByValue("after"); + + assert.equal( + postTimeSelector.header().label(), + "after", + 'has "after" populated' + ); + + assert.equal( + find(".search-query").val(), + "none after:2016-10-05", + 'has updated search term to "none after:2016-10-05"' + ); + }); + + test("update min post count through advanced search ui", async (assert) => { + await visit("/search"); + await fillIn(".search-query", "none"); + await fillIn("#search-min-post-count", "5"); + + assert.equal( + find(".search-advanced-options #search-min-post-count").val(), + "5", + 'has "5" populated' + ); + assert.equal( + find(".search-query").val(), + "none min_posts:5", + 'has updated search term to "none min_posts:5"' + ); + }); + + test("update max post count through advanced search ui", async (assert) => { + await visit("/search"); + await fillIn(".search-query", "none"); + await fillIn("#search-max-post-count", "5"); + + assert.equal( + find(".search-advanced-options #search-max-post-count").val(), + "5", + 'has "5" populated' + ); + assert.equal( + find(".search-query").val(), + "none max_posts:5", + 'has updated search term to "none max_posts:5"' + ); + }); + + test("validate advanced search when initially empty", async (assert) => { + await visit("/search?expanded=true"); + await click(".search-advanced-options .in-likes"); + + assert.ok( + selectKit(".search-advanced-options .in-likes:checked"), + 'has "I liked" populated' + ); + + assert.equal( + find(".search-query").val(), + "in:likes", + 'has updated search term to "in:likes"' + ); + + await fillIn(".search-query", "in:likesasdas"); + + assert.not( + exists(".search-advanced-options .in-likes:checked"), + "does not populate the likes checkbox" ); }); }); - -test("update category through advanced search ui", async (assert) => { - const categoryChooser = selectKit( - ".search-advanced-options .category-chooser" - ); - - await visit("/search"); - - await fillIn(".search-query", "none"); - - await categoryChooser.expand(); - await categoryChooser.fillInFilter("faq"); - await categoryChooser.selectRowByValue(4); - - assert.ok( - exists('.search-advanced-options .badge-category:contains("faq")'), - 'has "faq" populated' - ); - assert.equal( - find(".search-query").val(), - "none #faq", - 'has updated search term to "none #faq"' - ); -}); - -test("update in:title filter through advanced search ui", async (assert) => { - await visit("/search"); - await fillIn(".search-query", "none"); - await click(".search-advanced-options .in-title"); - - assert.ok( - exists(".search-advanced-options .in-title:checked"), - 'has "in title" populated' - ); - assert.equal( - find(".search-query").val(), - "none in:title", - 'has updated search term to "none in:title"' - ); - - await fillIn(".search-query", "none in:titleasd"); - - assert.not( - exists(".search-advanced-options .in-title:checked"), - "does not populate title only checkbox" - ); -}); - -test("update in:likes filter through advanced search ui", async (assert) => { - await visit("/search"); - await fillIn(".search-query", "none"); - await click(".search-advanced-options .in-likes"); - - assert.ok( - exists(".search-advanced-options .in-likes:checked"), - 'has "I liked" populated' - ); - assert.equal( - find(".search-query").val(), - "none in:likes", - 'has updated search term to "none in:likes"' - ); -}); - -test("update in:personal filter through advanced search ui", async (assert) => { - await visit("/search"); - await fillIn(".search-query", "none"); - await click(".search-advanced-options .in-private"); - - assert.ok( - exists(".search-advanced-options .in-private:checked"), - 'has "are in my messages" populated' - ); - - assert.equal( - find(".search-query").val(), - "none in:personal", - 'has updated search term to "none in:personal"' - ); - - await fillIn(".search-query", "none in:personal-direct"); - - assert.not( - exists(".search-advanced-options .in-private:checked"), - "does not populate messages checkbox" - ); -}); - -test("update in:seen filter through advanced search ui", async (assert) => { - await visit("/search"); - await fillIn(".search-query", "none"); - await click(".search-advanced-options .in-seen"); - - assert.ok( - exists(".search-advanced-options .in-seen:checked"), - "it should check the right checkbox" - ); - - assert.equal( - find(".search-query").val(), - "none in:seen", - "it should update the search term" - ); - - await fillIn(".search-query", "none in:seenasdan"); - - assert.not( - exists(".search-advanced-options .in-seen:checked"), - "does not populate seen checkbox" - ); -}); - -test("update in filter through advanced search ui", async (assert) => { - const inSelector = selectKit(".search-advanced-options .select-kit#in"); - - await visit("/search"); - - await fillIn(".search-query", "none"); - await inSelector.expand(); - await inSelector.selectRowByValue("bookmarks"); - - assert.equal( - inSelector.header().label(), - "I bookmarked", - 'has "I bookmarked" populated' - ); - assert.equal( - find(".search-query").val(), - "none in:bookmarks", - 'has updated search term to "none in:bookmarks"' - ); -}); - -test("update status through advanced search ui", async (assert) => { - const statusSelector = selectKit( - ".search-advanced-options .select-kit#status" - ); - - await visit("/search"); - - await fillIn(".search-query", "none"); - await statusSelector.expand(); - await statusSelector.selectRowByValue("closed"); - - assert.equal( - statusSelector.header().label(), - "are closed", - 'has "are closed" populated' - ); - assert.equal( - find(".search-query").val(), - "none status:closed", - 'has updated search term to "none status:closed"' - ); -}); - -test("doesn't update status filter header if wrong value entered through searchbox", async (assert) => { - const statusSelector = selectKit( - ".search-advanced-options .select-kit#status" - ); - - await visit("/search"); - - await fillIn(".search-query", "status:none"); - - assert.equal(statusSelector.header().label(), "any", 'has "any" populated'); -}); - -test("doesn't update in filter header if wrong value entered through searchbox", async (assert) => { - const inSelector = selectKit(".search-advanced-options .select-kit#in"); - - await visit("/search"); - - await fillIn(".search-query", "in:none"); - - assert.equal(inSelector.header().label(), "any", 'has "any" populated'); -}); - -test("update post time through advanced search ui", async (assert) => { - await visit("/search?expanded=true&q=after:2018-08-22"); - - assert.equal( - find(".search-query").val(), - "after:2018-08-22", - "it should update the search term correctly" - ); - - await visit("/search"); - - await fillIn(".search-query", "none"); - await selectDate("#search-post-date .date-picker", "2016-10-05"); - - const postTimeSelector = selectKit( - ".search-advanced-options .select-kit#postTime" - ); - await postTimeSelector.expand(); - await postTimeSelector.selectRowByValue("after"); - - assert.equal( - postTimeSelector.header().label(), - "after", - 'has "after" populated' - ); - - assert.equal( - find(".search-query").val(), - "none after:2016-10-05", - 'has updated search term to "none after:2016-10-05"' - ); -}); - -test("update min post count through advanced search ui", async (assert) => { - await visit("/search"); - await fillIn(".search-query", "none"); - await fillIn("#search-min-post-count", "5"); - - assert.equal( - find(".search-advanced-options #search-min-post-count").val(), - "5", - 'has "5" populated' - ); - assert.equal( - find(".search-query").val(), - "none min_posts:5", - 'has updated search term to "none min_posts:5"' - ); -}); - -test("update max post count through advanced search ui", async (assert) => { - await visit("/search"); - await fillIn(".search-query", "none"); - await fillIn("#search-max-post-count", "5"); - - assert.equal( - find(".search-advanced-options #search-max-post-count").val(), - "5", - 'has "5" populated' - ); - assert.equal( - find(".search-query").val(), - "none max_posts:5", - 'has updated search term to "none max_posts:5"' - ); -}); - -test("validate advanced search when initially empty", async (assert) => { - await visit("/search?expanded=true"); - await click(".search-advanced-options .in-likes"); - - assert.ok( - selectKit(".search-advanced-options .in-likes:checked"), - 'has "I liked" populated' - ); - - assert.equal( - find(".search-query").val(), - "in:likes", - 'has updated search term to "in:likes"' - ); - - await fillIn(".search-query", "in:likesasdas"); - - assert.not( - exists(".search-advanced-options .in-likes:checked"), - "does not populate the likes checkbox" - ); -}); diff --git a/app/assets/javascripts/discourse/tests/acceptance/search-mobile-test.js b/app/assets/javascripts/discourse/tests/acceptance/search-mobile-test.js index 288befa8e26..73a00aceeba 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/search-mobile-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/search-mobile-test.js @@ -2,42 +2,44 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Search - Mobile", { mobileView: true }); +acceptance("Search - Mobile", function (needs) { + needs.mobileView(); -test("search", async (assert) => { - await visit("/"); + test("search", async (assert) => { + await visit("/"); - await click("#search-button"); + await click("#search-button"); - assert.ok( - exists("input.full-page-search"), - "it shows the full page search form" - ); + assert.ok( + exists("input.full-page-search"), + "it shows the full page search form" + ); - assert.ok(!exists(".search-results .fps-topic"), "no results by default"); + assert.ok(!exists(".search-results .fps-topic"), "no results by default"); - await click(".search-advanced-title"); + await click(".search-advanced-title"); - assert.ok( - find(".search-advanced-filters").length === 1, - "it should expand advanced search filters" - ); + assert.ok( + find(".search-advanced-filters").length === 1, + "it should expand advanced search filters" + ); - await fillIn(".search-query", "posts"); - await click(".search-cta"); + await fillIn(".search-query", "posts"); + await click(".search-cta"); - assert.ok(find(".fps-topic").length === 1, "has one post"); + assert.ok(find(".fps-topic").length === 1, "has one post"); - assert.ok( - find(".search-advanced-filters").length === 0, - "it should collapse advanced search filters" - ); + assert.ok( + find(".search-advanced-filters").length === 0, + "it should collapse advanced search filters" + ); - await click("#search-button"); + await click("#search-button"); - assert.equal( - find("input.full-page-search").val(), - "posts", - "it does not reset input when hitting search icon again" - ); + assert.equal( + find("input.full-page-search").val(), + "posts", + "it does not reset input when hitting search icon again" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/search-test.js b/app/assets/javascripts/discourse/tests/acceptance/search-test.js index 98319ab7b6a..ed8b394d567 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/search-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/search-test.js @@ -2,200 +2,195 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import selectKit from "discourse/tests/helpers/select-kit-helper"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; +import searchFixtures from "discourse/tests/fixtures/search-fixtures"; -const emptySearchContextCallbacks = []; +acceptance("Search - Anonymous", function (needs) { + let calledEmpty = false; -let searchArgs = { - pretend(server) { - server.handledRequest = (verb, path, request) => { - if (request.queryParams["search_context[type]"] === undefined) { - emptySearchContextCallbacks.forEach((callback) => { - callback.call(); - }); + needs.pretender((server, helper) => { + server.get("/search/query", (request) => { + if (!request.queryParams["search_context[type]"]) { + calledEmpty = true; } - }; - }, -}; -acceptance("Search", searchArgs); - -test("search", async (assert) => { - await visit("/"); - - await click("#search-button"); - - assert.ok(exists("#search-term"), "it shows the search bar"); - assert.ok(!exists(".search-menu .results ul li"), "no results by default"); - - await fillIn("#search-term", "dev"); - await keyEvent("#search-term", "keyup", 16); - assert.ok(exists(".search-menu .results ul li"), "it shows results"); - assert.ok( - exists(".search-menu .results ul li .topic-title[data-topic-id]"), - "topic has data-topic-id" - ); - - await click(".show-help"); - - assert.equal( - find(".full-page-search").val(), - "dev", - "it shows the search term" - ); - assert.ok(exists(".search-advanced-options"), "advanced search is expanded"); -}); - -test("search for a tag", async (assert) => { - await visit("/"); - - await click("#search-button"); - - await fillIn("#search-term", "evil"); - await keyEvent("#search-term", "keyup", 16); - assert.ok(exists(".search-menu .results ul li"), "it shows results"); -}); - -test("search scope checkbox", async (assert) => { - await visit("/tag/important"); - await click("#search-button"); - assert.ok( - exists(".search-context input:checked"), - "scope to tag checkbox is checked" - ); - await click("#search-button"); - - await visit("/c/bug"); - await click("#search-button"); - assert.ok( - exists(".search-context input:checked"), - "scope to category checkbox is checked" - ); - await click("#search-button"); - - await visit("/t/internationalization-localization/280"); - await click("#search-button"); - assert.not( - exists(".search-context input:checked"), - "scope to topic checkbox is not checked" - ); - await click("#search-button"); - - await visit("/u/eviltrout"); - await click("#search-button"); - assert.ok( - exists(".search-context input:checked"), - "scope to user checkbox is checked" - ); -}); - -test("Search with context", async (assert) => { - await visit("/t/internationalization-localization/280/1"); - - await click("#search-button"); - await fillIn("#search-term", "a proper"); - await click(".search-context input[type='checkbox']"); - await keyEvent("#search-term", "keyup", 16); - - assert.ok(exists(".search-menu .results ul li"), "it shows results"); - - const highlighted = []; - - find("#post_7 span.highlighted").map((_, span) => { - highlighted.push(span.innerText); + return helper.response(searchFixtures["search/query"]); + }); }); - assert.deepEqual( - highlighted, - ["a proper"], - "it should highlight the post with the search terms correctly" - ); + test("search", async (assert) => { + await visit("/"); - let callbackCalled = false; + await click("#search-button"); - emptySearchContextCallbacks.push(() => { - callbackCalled = true; + assert.ok(exists("#search-term"), "it shows the search bar"); + assert.ok(!exists(".search-menu .results ul li"), "no results by default"); + + await fillIn("#search-term", "dev"); + await keyEvent("#search-term", "keyup", 16); + assert.ok(exists(".search-menu .results ul li"), "it shows results"); + assert.ok( + exists(".search-menu .results ul li .topic-title[data-topic-id]"), + "topic has data-topic-id" + ); + + await click(".show-help"); + + assert.equal( + find(".full-page-search").val(), + "dev", + "it shows the search term" + ); + assert.ok( + exists(".search-advanced-options"), + "advanced search is expanded" + ); }); - await visit("/"); - await click("#search-button"); + test("search for a tag", async (assert) => { + await visit("/"); - assert.ok(!exists(".search-context input[type='checkbox']")); - assert.ok(callbackCalled, "it triggers a new search"); + await click("#search-button"); - await visit("/t/internationalization-localization/280/1"); - await click("#search-button"); + await fillIn("#search-term", "evil"); + await keyEvent("#search-term", "keyup", 16); + assert.ok(exists(".search-menu .results ul li"), "it shows results"); + }); - assert.ok(!$(".search-context input[type=checkbox]").is(":checked")); + test("search scope checkbox", async (assert) => { + await visit("/tag/important"); + await click("#search-button"); + assert.ok( + exists(".search-context input:checked"), + "scope to tag checkbox is checked" + ); + await click("#search-button"); + + await visit("/c/bug"); + await click("#search-button"); + assert.ok( + exists(".search-context input:checked"), + "scope to category checkbox is checked" + ); + await click("#search-button"); + + await visit("/t/internationalization-localization/280"); + await click("#search-button"); + assert.not( + exists(".search-context input:checked"), + "scope to topic checkbox is not checked" + ); + await click("#search-button"); + + await visit("/u/eviltrout"); + await click("#search-button"); + assert.ok( + exists(".search-context input:checked"), + "scope to user checkbox is checked" + ); + }); + + test("Search with context", async (assert) => { + await visit("/t/internationalization-localization/280/1"); + + await click("#search-button"); + await fillIn("#search-term", "a proper"); + await click(".search-context input[type='checkbox']"); + await keyEvent("#search-term", "keyup", 16); + + assert.ok(exists(".search-menu .results ul li"), "it shows results"); + + const highlighted = []; + + find("#post_7 span.highlighted").map((_, span) => { + highlighted.push(span.innerText); + }); + + assert.deepEqual( + highlighted, + ["a proper"], + "it should highlight the post with the search terms correctly" + ); + + calledEmpty = false; + await visit("/"); + await click("#search-button"); + + assert.ok(!exists(".search-context input[type='checkbox']")); + assert.ok(calledEmpty, "it triggers a new search"); + + await visit("/t/internationalization-localization/280/1"); + await click("#search-button"); + + assert.ok(!$(".search-context input[type=checkbox]").is(":checked")); + }); + + test("Right filters are shown to anonymous users", async (assert) => { + const inSelector = selectKit(".select-kit#in"); + + await visit("/search?expanded=true"); + + await inSelector.expand(); + + assert.ok(inSelector.rowByValue("first").exists()); + assert.ok(inSelector.rowByValue("pinned").exists()); + assert.ok(inSelector.rowByValue("wiki").exists()); + assert.ok(inSelector.rowByValue("images").exists()); + + assert.notOk(inSelector.rowByValue("unseen").exists()); + assert.notOk(inSelector.rowByValue("posted").exists()); + assert.notOk(inSelector.rowByValue("watching").exists()); + assert.notOk(inSelector.rowByValue("tracking").exists()); + assert.notOk(inSelector.rowByValue("bookmarks").exists()); + + assert.notOk(exists(".search-advanced-options .in-likes")); + assert.notOk(exists(".search-advanced-options .in-private")); + assert.notOk(exists(".search-advanced-options .in-seen")); + }); }); -test("Right filters are shown to anonymous users", async (assert) => { - const inSelector = selectKit(".select-kit#in"); +acceptance("Search - Authenticated", function (needs) { + needs.user(); - await visit("/search?expanded=true"); + test("Right filters are shown to logged-in users", async (assert) => { + const inSelector = selectKit(".select-kit#in"); - await inSelector.expand(); + await visit("/search?expanded=true"); - assert.ok(inSelector.rowByValue("first").exists()); - assert.ok(inSelector.rowByValue("pinned").exists()); - assert.ok(inSelector.rowByValue("wiki").exists()); - assert.ok(inSelector.rowByValue("images").exists()); + await inSelector.expand(); - assert.notOk(inSelector.rowByValue("unseen").exists()); - assert.notOk(inSelector.rowByValue("posted").exists()); - assert.notOk(inSelector.rowByValue("watching").exists()); - assert.notOk(inSelector.rowByValue("tracking").exists()); - assert.notOk(inSelector.rowByValue("bookmarks").exists()); + assert.ok(inSelector.rowByValue("first").exists()); + assert.ok(inSelector.rowByValue("pinned").exists()); + assert.ok(inSelector.rowByValue("wiki").exists()); + assert.ok(inSelector.rowByValue("images").exists()); - assert.notOk(exists(".search-advanced-options .in-likes")); - assert.notOk(exists(".search-advanced-options .in-private")); - assert.notOk(exists(".search-advanced-options .in-seen")); + assert.ok(inSelector.rowByValue("unseen").exists()); + assert.ok(inSelector.rowByValue("posted").exists()); + assert.ok(inSelector.rowByValue("watching").exists()); + assert.ok(inSelector.rowByValue("tracking").exists()); + assert.ok(inSelector.rowByValue("bookmarks").exists()); + + assert.ok(exists(".search-advanced-options .in-likes")); + assert.ok(exists(".search-advanced-options .in-private")); + assert.ok(exists(".search-advanced-options .in-seen")); + }); }); -acceptance("Search", Object.assign({ loggedIn: true, searchArgs })); +acceptance("Search - with tagging enabled", function (needs) { + needs.user(); + needs.settings({ tagging_enabled: true }); -test("Right filters are shown to logged-in users", async (assert) => { - const inSelector = selectKit(".select-kit#in"); + test("displays tags", async (assert) => { + await visit("/"); - await visit("/search?expanded=true"); + await click("#search-button"); - await inSelector.expand(); + await fillIn("#search-term", "dev"); + await keyEvent("#search-term", "keyup", 16); - assert.ok(inSelector.rowByValue("first").exists()); - assert.ok(inSelector.rowByValue("pinned").exists()); - assert.ok(inSelector.rowByValue("wiki").exists()); - assert.ok(inSelector.rowByValue("images").exists()); + const tags = find(".search-menu .results ul li:eq(0) .discourse-tags") + .text() + .trim(); - assert.ok(inSelector.rowByValue("unseen").exists()); - assert.ok(inSelector.rowByValue("posted").exists()); - assert.ok(inSelector.rowByValue("watching").exists()); - assert.ok(inSelector.rowByValue("tracking").exists()); - assert.ok(inSelector.rowByValue("bookmarks").exists()); - - assert.ok(exists(".search-advanced-options .in-likes")); - assert.ok(exists(".search-advanced-options .in-private")); - assert.ok(exists(".search-advanced-options .in-seen")); -}); - -acceptance( - "Search - with tagging enabled", - Object.assign({ - loggedIn: true, - searchArgs, - settings: { tagging_enabled: true }, - }) -); - -test("displays tags", async (assert) => { - await visit("/"); - - await click("#search-button"); - - await fillIn("#search-term", "dev"); - await keyEvent("#search-term", "keyup", 16); - - const tags = find(".search-menu .results ul li:eq(0) .discourse-tags") - .text() - .trim(); - - assert.equal(tags, "dev slow"); + assert.equal(tags, "dev slow"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/share-and-invite-desktop-test.js b/app/assets/javascripts/discourse/tests/acceptance/share-and-invite-desktop-test.js index a0953221e55..5fa85ea991c 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/share-and-invite-desktop-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/share-and-invite-desktop-test.js @@ -2,92 +2,91 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Share and Invite modal - desktop", { - loggedIn: true, +acceptance("Share and Invite modal - desktop", function (needs) { + needs.user(); + + test("Topic footer button", async (assert) => { + await visit("/t/internationalization-localization/280"); + + assert.ok( + exists("#topic-footer-button-share-and-invite"), + "the button exists" + ); + + await click("#topic-footer-button-share-and-invite"); + + assert.ok(exists(".share-and-invite.modal"), "it shows the modal"); + + assert.ok( + exists(".share-and-invite.modal .modal-tab.share"), + "it shows the share tab" + ); + + assert.ok( + exists(".share-and-invite.modal .modal-tab.share.is-active"), + "it activates the share tab by default" + ); + + assert.ok( + exists(".share-and-invite.modal .modal-tab.invite"), + "it shows the invite tab" + ); + + assert.equal( + find(".share-and-invite.modal .modal-panel.share .title").text(), + "Topic: Internationalization / localization", + "it shows the topic title" + ); + + assert.ok( + find(".share-and-invite.modal .modal-panel.share .topic-share-url") + .val() + .includes("/t/internationalization-localization/280?u=eviltrout"), + "it shows the topic sharing url" + ); + + assert.ok( + find(".share-and-invite.modal .social-link").length > 1, + "it shows social sources" + ); + + await click(".share-and-invite.modal .modal-tab.invite"); + + assert.ok( + exists( + ".share-and-invite.modal .modal-panel.invite .send-invite:disabled" + ), + "send invite button is disabled" + ); + + assert.ok( + exists( + ".share-and-invite.modal .modal-panel.invite .generate-invite-link:disabled" + ), + "generate invite button is disabled" + ); + }); + + test("Post date link", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click("#post_2 .post-info.post-date a"); + + assert.ok(exists("#share-link"), "it shows the share modal"); + }); }); -test("Topic footer button", async (assert) => { - await visit("/t/internationalization-localization/280"); +acceptance("Share url with badges disabled - desktop", function (needs) { + needs.user(); + needs.settings({ enable_badges: false }); + test("topic footer button - badges disabled - desktop", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click("#topic-footer-button-share-and-invite"); - assert.ok( - exists("#topic-footer-button-share-and-invite"), - "the button exists" - ); - - await click("#topic-footer-button-share-and-invite"); - - assert.ok(exists(".share-and-invite.modal"), "it shows the modal"); - - assert.ok( - exists(".share-and-invite.modal .modal-tab.share"), - "it shows the share tab" - ); - - assert.ok( - exists(".share-and-invite.modal .modal-tab.share.is-active"), - "it activates the share tab by default" - ); - - assert.ok( - exists(".share-and-invite.modal .modal-tab.invite"), - "it shows the invite tab" - ); - - assert.equal( - find(".share-and-invite.modal .modal-panel.share .title").text(), - "Topic: Internationalization / localization", - "it shows the topic title" - ); - - assert.ok( - find(".share-and-invite.modal .modal-panel.share .topic-share-url") - .val() - .includes("/t/internationalization-localization/280?u=eviltrout"), - "it shows the topic sharing url" - ); - - assert.ok( - find(".share-and-invite.modal .social-link").length > 1, - "it shows social sources" - ); - - await click(".share-and-invite.modal .modal-tab.invite"); - - assert.ok( - exists(".share-and-invite.modal .modal-panel.invite .send-invite:disabled"), - "send invite button is disabled" - ); - - assert.ok( - exists( - ".share-and-invite.modal .modal-panel.invite .generate-invite-link:disabled" - ), - "generate invite button is disabled" - ); -}); - -test("Post date link", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click("#post_2 .post-info.post-date a"); - - assert.ok(exists("#share-link"), "it shows the share modal"); -}); - -acceptance("Share url with badges disabled - desktop", { - loggedIn: true, - settings: { - enable_badges: false, - }, -}); - -test("topic footer button - badges disabled - desktop", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click("#topic-footer-button-share-and-invite"); - - assert.notOk( - find(".share-and-invite.modal .modal-panel.share .topic-share-url") - .val() - .includes("?u=eviltrout"), - "it doesn't add the username param when badges are disabled" - ); + assert.notOk( + find(".share-and-invite.modal .modal-panel.share .topic-share-url") + .val() + .includes("?u=eviltrout"), + "it doesn't add the username param when badges are disabled" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/share-and-invite-mobile-test.js b/app/assets/javascripts/discourse/tests/acceptance/share-and-invite-mobile-test.js index 75e702d6086..071a7cbc7c8 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/share-and-invite-mobile-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/share-and-invite-mobile-test.js @@ -3,85 +3,84 @@ import { test } from "qunit"; import selectKit from "discourse/tests/helpers/select-kit-helper"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Share and Invite modal - mobile", { - loggedIn: true, - mobileView: true, +acceptance("Share and Invite modal - mobile", function (needs) { + needs.user(); + needs.mobileView(); + + test("Topic footer mobile button", async (assert) => { + await visit("/t/internationalization-localization/280"); + + assert.ok( + !exists("#topic-footer-button-share-and-invite"), + "the button doesn’t exist" + ); + + const subject = selectKit(".topic-footer-mobile-dropdown"); + await subject.expand(); + await subject.selectRowByValue("share-and-invite"); + + assert.ok(exists(".share-and-invite.modal"), "it shows the modal"); + + assert.ok( + exists(".share-and-invite.modal .modal-tab.share"), + "it shows the share tab" + ); + + assert.ok( + exists(".share-and-invite.modal .modal-tab.share.is-active"), + "it activates the share tab by default" + ); + + assert.ok( + exists(".share-and-invite.modal .modal-tab.invite"), + "it shows the invite tab" + ); + + assert.equal( + find(".share-and-invite.modal .modal-panel.share .title").text(), + "Topic: Internationalization / localization", + "it shows the topic title" + ); + + assert.ok( + find(".share-and-invite.modal .modal-panel.share .topic-share-url") + .val() + .includes("/t/internationalization-localization/280?u=eviltrout"), + "it shows the topic sharing url" + ); + + assert.ok( + find(".share-and-invite.modal .social-link").length > 1, + "it shows social sources" + ); + }); + + test("Post date link", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click("#post_2 .post-info.post-date a"); + + assert.ok(exists("#share-link"), "it shows the share modal"); + }); }); -test("Topic footer mobile button", async (assert) => { - await visit("/t/internationalization-localization/280"); - - assert.ok( - !exists("#topic-footer-button-share-and-invite"), - "the button doesn’t exist" - ); - - const subject = selectKit(".topic-footer-mobile-dropdown"); - await subject.expand(); - await subject.selectRowByValue("share-and-invite"); - - assert.ok(exists(".share-and-invite.modal"), "it shows the modal"); - - assert.ok( - exists(".share-and-invite.modal .modal-tab.share"), - "it shows the share tab" - ); - - assert.ok( - exists(".share-and-invite.modal .modal-tab.share.is-active"), - "it activates the share tab by default" - ); - - assert.ok( - exists(".share-and-invite.modal .modal-tab.invite"), - "it shows the invite tab" - ); - - assert.equal( - find(".share-and-invite.modal .modal-panel.share .title").text(), - "Topic: Internationalization / localization", - "it shows the topic title" - ); - - assert.ok( - find(".share-and-invite.modal .modal-panel.share .topic-share-url") - .val() - .includes("/t/internationalization-localization/280?u=eviltrout"), - "it shows the topic sharing url" - ); - - assert.ok( - find(".share-and-invite.modal .social-link").length > 1, - "it shows social sources" - ); -}); - -test("Post date link", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click("#post_2 .post-info.post-date a"); - - assert.ok(exists("#share-link"), "it shows the share modal"); -}); - -acceptance("Share url with badges disabled - mobile", { - loggedIn: true, - mobileView: true, - settings: { +acceptance("Share url with badges disabled - mobile", function (needs) { + needs.user(); + needs.mobileView(); + needs.settings({ enable_badges: false, - }, -}); - -test("topic footer button - badges disabled - mobile", async (assert) => { - await visit("/t/internationalization-localization/280"); - - const subject = selectKit(".topic-footer-mobile-dropdown"); - await subject.expand(); - await subject.selectRowByValue("share-and-invite"); - - assert.notOk( - find(".share-and-invite.modal .modal-panel.share .topic-share-url") - .val() - .includes("?u=eviltrout"), - "it doesn't add the username param when badges are disabled" - ); + }); + test("topic footer button - badges disabled - mobile", async (assert) => { + await visit("/t/internationalization-localization/280"); + + const subject = selectKit(".topic-footer-mobile-dropdown"); + await subject.expand(); + await subject.selectRowByValue("share-and-invite"); + + assert.notOk( + find(".share-and-invite.modal .modal-panel.share .topic-share-url") + .val() + .includes("?u=eviltrout"), + "it doesn't add the username param when badges are disabled" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/shared-drafts-test.js b/app/assets/javascripts/discourse/tests/acceptance/shared-drafts-test.js index 94732183704..eec894731e2 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/shared-drafts-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/shared-drafts-test.js @@ -3,16 +3,16 @@ import { test } from "qunit"; import selectKit from "discourse/tests/helpers/select-kit-helper"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Shared Drafts", { loggedIn: true }); +acceptance("Shared Drafts", function () { + test("Viewing", async (assert) => { + await visit("/t/some-topic/9"); + assert.ok(find(".shared-draft-controls").length === 1); + let categoryChooser = selectKit(".shared-draft-controls .category-chooser"); + assert.equal(categoryChooser.header().value(), "3"); -test("Viewing", async (assert) => { - await visit("/t/some-topic/9"); - assert.ok(find(".shared-draft-controls").length === 1); - let categoryChooser = selectKit(".shared-draft-controls .category-chooser"); - assert.equal(categoryChooser.header().value(), "3"); + await click(".publish-shared-draft"); + await click(".bootbox .btn-primary"); - await click(".publish-shared-draft"); - await click(".bootbox .btn-primary"); - - assert.ok(find(".shared-draft-controls").length === 0); + assert.ok(find(".shared-draft-controls").length === 0); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/sign-in-test.js b/app/assets/javascripts/discourse/tests/acceptance/sign-in-test.js index d4ddd062c24..cdb73404bdc 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/sign-in-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/sign-in-test.js @@ -1,199 +1,202 @@ import { visit } from "@ember/test-helpers"; -import { skip } from "qunit"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Signing In"); -test("sign in", async (assert) => { - await visit("/"); - await click("header .login-button"); - assert.ok(exists(".login-modal"), "it shows the login modal"); +acceptance("Signing In", function () { + test("sign in", async (assert) => { + await visit("/"); + await click("header .login-button"); + assert.ok(exists(".login-modal"), "it shows the login modal"); - // Test invalid password first - await fillIn("#login-account-name", "eviltrout"); - await fillIn("#login-account-password", "incorrect"); - await click(".modal-footer .btn-primary"); - assert.ok(exists("#modal-alert:visible"), "it displays the login error"); - assert.not( - exists(".modal-footer .btn-primary:disabled"), - "enables the login button" - ); + // Test invalid password first + await fillIn("#login-account-name", "eviltrout"); + await fillIn("#login-account-password", "incorrect"); + await click(".modal-footer .btn-primary"); + assert.ok(exists("#modal-alert:visible"), "it displays the login error"); + assert.not( + exists(".modal-footer .btn-primary:disabled"), + "enables the login button" + ); - // Use the correct password - await fillIn("#login-account-password", "correct"); - await click(".modal-footer .btn-primary"); - assert.ok( - exists(".modal-footer .btn-primary:disabled"), - "disables the login button" - ); -}); - -test("sign in - not activated", async (assert) => { - await visit("/"); - await click("header .login-button"); - assert.ok(exists(".login-modal"), "it shows the login modal"); - - await fillIn("#login-account-name", "eviltrout"); - await fillIn("#login-account-password", "not-activated"); - await click(".modal-footer .btn-primary"); - assert.equal( - find(".modal-body b").text(), - "eviltrout@example.com" - ); - assert.ok(!exists(".modal-body small"), "it escapes the email address"); - - await click(".modal-footer button.resend"); - assert.equal( - find(".modal-body b").text(), - "current@example.com" - ); - assert.ok(!exists(".modal-body small"), "it escapes the email address"); -}); - -test("sign in - not activated - edit email", async (assert) => { - await visit("/"); - await click("header .login-button"); - assert.ok(exists(".login-modal"), "it shows the login modal"); - - await fillIn("#login-account-name", "eviltrout"); - await fillIn("#login-account-password", "not-activated-edit"); - await click(".modal-footer .btn-primary"); - await click(".modal-footer button.edit-email"); - assert.equal(find(".activate-new-email").val(), "current@example.com"); - assert.equal( - find(".modal-footer .btn-primary:disabled").length, - 1, - "must change email" - ); - await fillIn(".activate-new-email", "different@example.com"); - assert.equal(find(".modal-footer .btn-primary:disabled").length, 0); - await click(".modal-footer .btn-primary"); - assert.equal(find(".modal-body b").text(), "different@example.com"); -}); - -skip("second factor", async (assert) => { - await visit("/"); - await click("header .login-button"); - - assert.ok(exists(".login-modal"), "it shows the login modal"); - - await fillIn("#login-account-name", "eviltrout"); - await fillIn("#login-account-password", "need-second-factor"); - await click(".modal-footer .btn-primary"); - - assert.not(exists("#modal-alert:visible"), "it hides the login error"); - assert.not( - exists("#credentials:visible"), - "it hides the username and password prompt" - ); - assert.ok( - exists("#second-factor:visible"), - "it displays the second factor prompt" - ); - assert.not( - exists(".modal-footer .btn-primary:disabled"), - "enables the login button" - ); - - await fillIn("#login-second-factor", "123456"); - await click(".modal-footer .btn-primary"); - - assert.ok( - exists(".modal-footer .btn-primary:disabled"), - "disables the login button" - ); -}); - -skip("security key", async (assert) => { - await visit("/"); - await click("header .login-button"); - - assert.ok(exists(".login-modal"), "it shows the login modal"); - - await fillIn("#login-account-name", "eviltrout"); - await fillIn("#login-account-password", "need-security-key"); - await click(".modal-footer .btn-primary"); - - assert.not(exists("#modal-alert:visible"), "it hides the login error"); - assert.not( - exists("#credentials:visible"), - "it hides the username and password prompt" - ); - assert.not( - exists("#login-second-factor:visible"), - "it does not display the second factor prompt" - ); - assert.ok( - exists("#security-key:visible"), - "it shows the security key prompt" - ); - assert.not(exists("#login-button:visible"), "hides the login button"); -}); - -test("create account", async (assert) => { - await visit("/"); - await click("header .sign-up-button"); - - assert.ok(exists(".create-account"), "it shows the create account modal"); - - await fillIn("#new-account-name", "Dr. Good Tuna"); - await fillIn("#new-account-password", "cool password bro"); - - // without this double fill, field will sometimes being empty - // got consistent repro by having browser search bar focused when starting test - await fillIn("#new-account-email", "good.tuna@test.com"); - await fillIn("#new-account-email", "good.tuna@test.com"); - - // Check username - await fillIn("#new-account-username", "taken"); - assert.ok( - exists("#username-validation.bad"), - "the username validation is bad" - ); - await click(".modal-footer .btn-primary"); - assert.ok(exists("#new-account-username:focus"), "username field is focused"); - - await fillIn("#new-account-username", "goodtuna"); - assert.ok( - exists("#username-validation.good"), - "the username validation is good" - ); - - await click(".modal-footer .btn-primary"); - assert.ok( - exists(".modal-footer .btn-primary:disabled"), - "create account is disabled" - ); -}); - -test("second factor backup - valid token", async (assert) => { - await visit("/"); - await click("header .login-button"); - await fillIn("#login-account-name", "eviltrout"); - await fillIn("#login-account-password", "need-second-factor"); - await click(".modal-footer .btn-primary"); - await click(".login-modal .toggle-second-factor-method"); - await fillIn("#login-second-factor", "123456"); - await click(".modal-footer .btn-primary"); - - assert.ok( - exists(".modal-footer .btn-primary:disabled"), - "it closes the modal when the code is valid" - ); -}); - -test("second factor backup - invalid token", async (assert) => { - await visit("/"); - await click("header .login-button"); - await fillIn("#login-account-name", "eviltrout"); - await fillIn("#login-account-password", "need-second-factor"); - await click(".modal-footer .btn-primary"); - await click(".login-modal .toggle-second-factor-method"); - await fillIn("#login-second-factor", "something"); - await click(".modal-footer .btn-primary"); - - assert.ok( - exists("#modal-alert:visible"), - "it shows an error when the code is invalid" - ); + // Use the correct password + await fillIn("#login-account-password", "correct"); + await click(".modal-footer .btn-primary"); + assert.ok( + exists(".modal-footer .btn-primary:disabled"), + "disables the login button" + ); + }); + + test("sign in - not activated", async (assert) => { + await visit("/"); + await click("header .login-button"); + assert.ok(exists(".login-modal"), "it shows the login modal"); + + await fillIn("#login-account-name", "eviltrout"); + await fillIn("#login-account-password", "not-activated"); + await click(".modal-footer .btn-primary"); + assert.equal( + find(".modal-body b").text(), + "eviltrout@example.com" + ); + assert.ok(!exists(".modal-body small"), "it escapes the email address"); + + await click(".modal-footer button.resend"); + assert.equal( + find(".modal-body b").text(), + "current@example.com" + ); + assert.ok(!exists(".modal-body small"), "it escapes the email address"); + }); + + test("sign in - not activated - edit email", async (assert) => { + await visit("/"); + await click("header .login-button"); + assert.ok(exists(".login-modal"), "it shows the login modal"); + + await fillIn("#login-account-name", "eviltrout"); + await fillIn("#login-account-password", "not-activated-edit"); + await click(".modal-footer .btn-primary"); + await click(".modal-footer button.edit-email"); + assert.equal(find(".activate-new-email").val(), "current@example.com"); + assert.equal( + find(".modal-footer .btn-primary:disabled").length, + 1, + "must change email" + ); + await fillIn(".activate-new-email", "different@example.com"); + assert.equal(find(".modal-footer .btn-primary:disabled").length, 0); + await click(".modal-footer .btn-primary"); + assert.equal(find(".modal-body b").text(), "different@example.com"); + }); + + test("second factor", async (assert) => { + await visit("/"); + await click("header .login-button"); + + assert.ok(exists(".login-modal"), "it shows the login modal"); + + await fillIn("#login-account-name", "eviltrout"); + await fillIn("#login-account-password", "need-second-factor"); + await click(".modal-footer .btn-primary"); + + assert.not(exists("#modal-alert:visible"), "it hides the login error"); + assert.not( + exists("#credentials:visible"), + "it hides the username and password prompt" + ); + assert.ok( + exists("#second-factor:visible"), + "it displays the second factor prompt" + ); + assert.not( + exists(".modal-footer .btn-primary:disabled"), + "enables the login button" + ); + + await fillIn("#login-second-factor", "123456"); + await click(".modal-footer .btn-primary"); + + assert.ok( + exists(".modal-footer .btn-primary:disabled"), + "disables the login button" + ); + }); + + test("security key", async (assert) => { + await visit("/"); + await click("header .login-button"); + + assert.ok(exists(".login-modal"), "it shows the login modal"); + + await fillIn("#login-account-name", "eviltrout"); + await fillIn("#login-account-password", "need-security-key"); + await click(".modal-footer .btn-primary"); + + assert.not(exists("#modal-alert:visible"), "it hides the login error"); + assert.not( + exists("#credentials:visible"), + "it hides the username and password prompt" + ); + assert.not( + exists("#login-second-factor:visible"), + "it does not display the second factor prompt" + ); + assert.ok( + exists("#security-key:visible"), + "it shows the security key prompt" + ); + assert.not(exists("#login-button:visible"), "hides the login button"); + }); + + test("create account", async (assert) => { + await visit("/"); + await click("header .sign-up-button"); + + assert.ok(exists(".create-account"), "it shows the create account modal"); + + await fillIn("#new-account-name", "Dr. Good Tuna"); + await fillIn("#new-account-password", "cool password bro"); + + // without this double fill, field will sometimes being empty + // got consistent repro by having browser search bar focused when starting test + await fillIn("#new-account-email", "good.tuna@test.com"); + await fillIn("#new-account-email", "good.tuna@test.com"); + + // Check username + await fillIn("#new-account-username", "taken"); + assert.ok( + exists("#username-validation.bad"), + "the username validation is bad" + ); + await click(".modal-footer .btn-primary"); + assert.ok( + exists("#new-account-username:focus"), + "username field is focused" + ); + + await fillIn("#new-account-username", "goodtuna"); + assert.ok( + exists("#username-validation.good"), + "the username validation is good" + ); + + await click(".modal-footer .btn-primary"); + assert.ok( + exists(".modal-footer .btn-primary:disabled"), + "create account is disabled" + ); + }); + + test("second factor backup - valid token", async (assert) => { + await visit("/"); + await click("header .login-button"); + await fillIn("#login-account-name", "eviltrout"); + await fillIn("#login-account-password", "need-second-factor"); + await click(".modal-footer .btn-primary"); + await click(".login-modal .toggle-second-factor-method"); + await fillIn("#login-second-factor", "123456"); + await click(".modal-footer .btn-primary"); + + assert.ok( + exists(".modal-footer .btn-primary:disabled"), + "it closes the modal when the code is valid" + ); + }); + + test("second factor backup - invalid token", async (assert) => { + await visit("/"); + await click("header .login-button"); + await fillIn("#login-account-name", "eviltrout"); + await fillIn("#login-account-password", "need-second-factor"); + await click(".modal-footer .btn-primary"); + await click(".login-modal .toggle-second-factor-method"); + await fillIn("#login-second-factor", "something"); + await click(".modal-footer .btn-primary"); + + assert.ok( + exists("#modal-alert:visible"), + "it shows an error when the code is invalid" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/static-test.js b/app/assets/javascripts/discourse/tests/acceptance/static-test.js index fc5553664e4..888d0b064bd 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/static-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/static-test.js @@ -1,29 +1,30 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Static"); -test("Static Pages", async (assert) => { - await visit("/faq"); - assert.ok($("body.static-faq").length, "has the body class"); - assert.ok(exists(".body-page"), "The content is present"); +acceptance("Static", function () { + test("Static Pages", async (assert) => { + await visit("/faq"); + assert.ok($("body.static-faq").length, "has the body class"); + assert.ok(exists(".body-page"), "The content is present"); - await visit("/guidelines"); - assert.ok($("body.static-guidelines").length, "has the body class"); - assert.ok(exists(".body-page"), "The content is present"); + await visit("/guidelines"); + assert.ok($("body.static-guidelines").length, "has the body class"); + assert.ok(exists(".body-page"), "The content is present"); - await visit("/tos"); - assert.ok($("body.static-tos").length, "has the body class"); - assert.ok(exists(".body-page"), "The content is present"); + await visit("/tos"); + assert.ok($("body.static-tos").length, "has the body class"); + assert.ok(exists(".body-page"), "The content is present"); - await visit("/privacy"); - assert.ok($("body.static-privacy").length, "has the body class"); - assert.ok(exists(".body-page"), "The content is present"); + await visit("/privacy"); + assert.ok($("body.static-privacy").length, "has the body class"); + assert.ok(exists(".body-page"), "The content is present"); - await visit("/login"); - assert.equal( - currentPath(), - "discovery.latest", - "it redirects them to latest unless `login_required`" - ); + await visit("/login"); + assert.equal( + currentPath(), + "discovery.latest", + "it redirects them to latest unless `login_required`" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/tag-groups-test.js b/app/assets/javascripts/discourse/tests/acceptance/tag-groups-test.js index 235d5279e30..7393d7c84fa 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/tag-groups-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/tag-groups-test.js @@ -3,10 +3,10 @@ import { test } from "qunit"; import selectKit from "discourse/tests/helpers/select-kit-helper"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Tag Groups", { - loggedIn: true, - settings: { tagging_enabled: true }, - pretend(server, helper) { +acceptance("Tag Groups", function (needs) { + needs.user(); + needs.settings({ tagging_enabled: true }); + needs.pretender((server, helper) => { server.post("/tag_groups", () => { return helper.response({ tag_group: { @@ -32,28 +32,25 @@ acceptance("Tag Groups", { }, ]); }); - }, -}); + }); -test("tag groups can be saved and deleted", async (assert) => { - const tags = selectKit(".tag-chooser"); + test("tag groups can be saved and deleted", async (assert) => { + const tags = selectKit(".tag-chooser"); - await visit("/tag_groups"); - await click(".content-list .btn"); + await visit("/tag_groups"); + await click(".content-list .btn"); - await fillIn(".tag-group-content h1 input", "test tag group"); - await tags.expand(); - await tags.selectRowByValue("monkey"); + await fillIn(".tag-group-content h1 input", "test tag group"); + await tags.expand(); + await tags.selectRowByValue("monkey"); - await click(".tag-group-content .btn.btn-default"); + await click(".tag-group-content .btn.btn-default"); - await click(".tag-chooser .choice:first"); - assert.ok(!find(".tag-group-content .btn.btn-danger")[0].disabled); -}); + await click(".tag-chooser .choice:first"); + assert.ok(!find(".tag-group-content .btn.btn-danger")[0].disabled); + }); -QUnit.test( - "tag groups can have multiple groups added to them", - async (assert) => { + test("tag groups can have multiple groups added to them", async (assert) => { const tags = selectKit(".tag-chooser"); const groups = selectKit(".group-chooser"); @@ -71,5 +68,5 @@ QUnit.test( await groups.selectRowByIndex(1); await groups.selectRowByIndex(0); assert.ok(!find(".tag-group-content .btn.btn-default")[0].disabled); - } -); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/acceptance/tags-intersection-test.js b/app/assets/javascripts/discourse/tests/acceptance/tags-intersection-test.js index fb4a3894c1f..7af006a050f 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/tags-intersection-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/tags-intersection-test.js @@ -2,11 +2,12 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Tags intersection", { - loggedIn: true, - site: { can_tag_topics: true }, - settings: { tagging_enabled: true }, - pretend(server, helper) { +acceptance("Tags intersection", function (needs) { + needs.user(); + needs.site({ can_tag_topics: true }); + needs.settings({ tagging_enabled: true }); + + needs.pretender((server, helper) => { server.get("/tag/first/notifications", () => { return helper.response({ tag_notification: { id: "first", notification_level: 1 }, @@ -27,17 +28,17 @@ acceptance("Tags intersection", { }, }); }); - }, -}); + }); -test("Populate tags when creating new topic", async (assert) => { - await visit("/tags/intersection/first/second"); - await click("#create-topic"); + test("Populate tags when creating new topic", async (assert) => { + await visit("/tags/intersection/first/second"); + await click("#create-topic"); - assert.ok(exists(".mini-tag-chooser"), "The tag selector appears"); - assert.equal( - $(".mini-tag-chooser").text().trim(), - "first, second", - "populates the tags when clicking 'New topic'" - ); + assert.ok(exists(".mini-tag-chooser"), "The tag selector appears"); + assert.equal( + $(".mini-tag-chooser").text().trim(), + "first, second", + "populates the tags when clicking 'New topic'" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/tags-test.js b/app/assets/javascripts/discourse/tests/acceptance/tags-test.js index 6c4a82fd637..50f1e2a95ae 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/tags-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/tags-test.js @@ -4,153 +4,151 @@ import { updateCurrentUser, acceptance, } from "discourse/tests/helpers/qunit-helpers"; -import pretender from "discourse/tests/helpers/create-pretender"; -acceptance("Tags", { loggedIn: true }); +acceptance("Tags", function (needs) { + needs.user(); -test("list the tags", async (assert) => { - await visit("/tags"); + test("list the tags", async (assert) => { + await visit("/tags"); - assert.ok($("body.tags-page").length, "has the body class"); - assert.ok( - $('*[data-tag-name="eviltrout"]').length, - "shows the eviltrout tag" - ); + assert.ok($("body.tags-page").length, "has the body class"); + assert.ok( + $('*[data-tag-name="eviltrout"]').length, + "shows the eviltrout tag" + ); + }); }); -acceptance("Tags listed by group", { - loggedIn: true, - settings: { +acceptance("Tags listed by group", function (needs) { + needs.user(); + needs.settings({ tags_listed_by_group: true, - }, + }); + needs.pretender((server, helper) => { + server.get("/tag/regular-tag/notifications", () => + helper.response({ + tag_notification: { id: "regular-tag", notification_level: 1 }, + }) + ); + + server.get("/tag/regular-tag/l/latest.json", () => + helper.response({ + users: [], + primary_groups: [], + topic_list: { + can_create_topic: true, + draft: null, + draft_key: "new_topic", + draft_sequence: 1, + per_page: 30, + tags: [ + { + id: 1, + name: "regular-tag", + topic_count: 1, + }, + ], + topics: [], + }, + }) + ); + + server.get("/tag/staff-only-tag/notifications", () => + helper.response({ + tag_notification: { id: "staff-only-tag", notification_level: 1 }, + }) + ); + + server.get("/tag/staff-only-tag/l/latest.json", () => + helper.response({ + users: [], + primary_groups: [], + topic_list: { + can_create_topic: true, + draft: null, + draft_key: "new_topic", + draft_sequence: 1, + per_page: 30, + tags: [ + { + id: 1, + name: "staff-only-tag", + topic_count: 1, + staff: true, + }, + ], + topics: [], + }, + }) + ); + }); + + test("list the tags in groups", async (assert) => { + await visit("/tags"); + assert.equal( + $(".tag-list").length, + 4, + "shows separate lists for the 3 groups and the ungrouped tags" + ); + assert.deepEqual( + $(".tag-list h3") + .toArray() + .map((i) => { + return $(i).text(); + }), + ["Ford Cars", "Honda Cars", "Makes", "Other Tags"], + "shown in given order and with tags that are not in a group" + ); + assert.deepEqual( + $(".tag-list:first .discourse-tag") + .toArray() + .map((i) => { + return $(i).text(); + }), + ["focus", "Escort"], + "shows the tags in default sort (by count)" + ); + assert.deepEqual( + $(".tag-list:first .discourse-tag") + .toArray() + .map((i) => { + return $(i).attr("href"); + }), + ["/tag/focus", "/tag/escort"], + "always uses lowercase URLs for mixed case tags" + ); + assert.equal( + $("a[data-tag-name='private']").attr("href"), + "/u/eviltrout/messages/tags/private", + "links to private messages" + ); + }); + + test("new topic button is not available for staff-only tags", async (assert) => { + updateCurrentUser({ moderator: false, admin: false }); + + await visit("/tag/regular-tag"); + assert.ok(find("#create-topic:disabled").length === 0); + + await visit("/tag/staff-only-tag"); + assert.ok(find("#create-topic:disabled").length === 1); + + updateCurrentUser({ moderator: true }); + + await visit("/tag/regular-tag"); + assert.ok(find("#create-topic:disabled").length === 0); + + await visit("/tag/staff-only-tag"); + assert.ok(find("#create-topic:disabled").length === 0); + }); }); -test("list the tags in groups", async (assert) => { - await visit("/tags"); - assert.equal( - $(".tag-list").length, - 4, - "shows separate lists for the 3 groups and the ungrouped tags" - ); - assert.deepEqual( - $(".tag-list h3") - .toArray() - .map((i) => { - return $(i).text(); - }), - ["Ford Cars", "Honda Cars", "Makes", "Other Tags"], - "shown in given order and with tags that are not in a group" - ); - assert.deepEqual( - $(".tag-list:first .discourse-tag") - .toArray() - .map((i) => { - return $(i).text(); - }), - ["focus", "Escort"], - "shows the tags in default sort (by count)" - ); - assert.deepEqual( - $(".tag-list:first .discourse-tag") - .toArray() - .map((i) => { - return $(i).attr("href"); - }), - ["/tag/focus", "/tag/escort"], - "always uses lowercase URLs for mixed case tags" - ); - assert.equal( - $("a[data-tag-name='private']").attr("href"), - "/u/eviltrout/messages/tags/private", - "links to private messages" - ); -}); - -test("new topic button is not available for staff-only tags", async (assert) => { - pretender.get("/tag/regular-tag/notifications", () => [ - 200, - { "Content-Type": "application/json" }, - { tag_notification: { id: "regular-tag", notification_level: 1 } }, - ]); - - pretender.get("/tag/regular-tag/l/latest.json", () => [ - 200, - { "Content-Type": "application/json" }, - { - users: [], - primary_groups: [], - topic_list: { - can_create_topic: true, - draft: null, - draft_key: "new_topic", - draft_sequence: 1, - per_page: 30, - tags: [ - { - id: 1, - name: "regular-tag", - topic_count: 1, - }, - ], - topics: [], - }, - }, - ]); - - pretender.get("/tag/staff-only-tag/notifications", () => [ - 200, - { "Content-Type": "application/json" }, - { tag_notification: { id: "staff-only-tag", notification_level: 1 } }, - ]); - - pretender.get("/tag/staff-only-tag/l/latest.json", () => [ - 200, - { "Content-Type": "application/json" }, - { - users: [], - primary_groups: [], - topic_list: { - can_create_topic: true, - draft: null, - draft_key: "new_topic", - draft_sequence: 1, - per_page: 30, - tags: [ - { - id: 1, - name: "staff-only-tag", - topic_count: 1, - staff: true, - }, - ], - topics: [], - }, - }, - ]); - - updateCurrentUser({ moderator: false, admin: false }); - - await visit("/tag/regular-tag"); - assert.ok(find("#create-topic:disabled").length === 0); - - await visit("/tag/staff-only-tag"); - assert.ok(find("#create-topic:disabled").length === 1); - - updateCurrentUser({ moderator: true }); - - await visit("/tag/regular-tag"); - assert.ok(find("#create-topic:disabled").length === 0); - - await visit("/tag/staff-only-tag"); - assert.ok(find("#create-topic:disabled").length === 0); -}); - -acceptance("Tag info", { - loggedIn: true, - settings: { +acceptance("Tag info", function (needs) { + needs.user(); + needs.settings({ tags_listed_by_group: true, - }, - pretend(server, helper) { + }); + needs.pretender((server, helper) => { server.get("/tag/planters/notifications", () => { return helper.response({ tag_notification: { id: "planters", notification_level: 1 }, @@ -219,64 +217,62 @@ acceptance("Tag info", { ], }); }); - }, -}); - -test("tag info can show synonyms", async (assert) => { - updateCurrentUser({ moderator: false, admin: false }); - - await visit("/tag/planters"); - assert.ok(find("#show-tag-info").length === 1); - - await click("#show-tag-info"); - assert.ok(exists(".tag-info .tag-name"), "show tag"); - assert.ok( - find(".tag-info .tag-associations").text().indexOf("Gardening") >= 0, - "show tag group names" - ); - assert.ok( - find(".tag-info .synonyms-list .tag-box").length === 2, - "shows the synonyms" - ); - assert.ok( - find(".tag-info .badge-category").length === 1, - "show the category" - ); - assert.ok(!exists("#rename-tag"), "can't rename tag"); - assert.ok(!exists("#edit-synonyms"), "can't edit synonyms"); - assert.ok(!exists("#delete-tag"), "can't delete tag"); -}); - -test("admin can manage tags", async (assert) => { - pretender.delete("/tag/planters/synonyms/containers", () => [ - 200, - { "Content-Type": "application/json" }, - { success: true }, - ]); - - updateCurrentUser({ moderator: false, admin: true }); - - await visit("/tag/planters"); - assert.ok(find("#show-tag-info").length === 1); - - await click("#show-tag-info"); - assert.ok(exists("#rename-tag"), "can rename tag"); - assert.ok(exists("#edit-synonyms"), "can edit synonyms"); - assert.ok(exists("#delete-tag"), "can delete tag"); - - await click("#edit-synonyms"); - assert.ok( - find(".unlink-synonym:visible").length === 2, - "unlink UI is visible" - ); - assert.ok( - find(".delete-synonym:visible").length === 2, - "delete UI is visible" - ); - - await click(".unlink-synonym:first"); - assert.ok( - find(".tag-info .synonyms-list .tag-box").length === 1, - "removed a synonym" - ); + + server.delete("/tag/planters/synonyms/containers", () => + helper.response({ success: true }) + ); + }); + + test("tag info can show synonyms", async (assert) => { + updateCurrentUser({ moderator: false, admin: false }); + + await visit("/tag/planters"); + assert.ok(find("#show-tag-info").length === 1); + + await click("#show-tag-info"); + assert.ok(exists(".tag-info .tag-name"), "show tag"); + assert.ok( + find(".tag-info .tag-associations").text().indexOf("Gardening") >= 0, + "show tag group names" + ); + assert.ok( + find(".tag-info .synonyms-list .tag-box").length === 2, + "shows the synonyms" + ); + assert.ok( + find(".tag-info .badge-category").length === 1, + "show the category" + ); + assert.ok(!exists("#rename-tag"), "can't rename tag"); + assert.ok(!exists("#edit-synonyms"), "can't edit synonyms"); + assert.ok(!exists("#delete-tag"), "can't delete tag"); + }); + + test("admin can manage tags", async (assert) => { + updateCurrentUser({ moderator: false, admin: true }); + + await visit("/tag/planters"); + assert.ok(find("#show-tag-info").length === 1); + + await click("#show-tag-info"); + assert.ok(exists("#rename-tag"), "can rename tag"); + assert.ok(exists("#edit-synonyms"), "can edit synonyms"); + assert.ok(exists("#delete-tag"), "can delete tag"); + + await click("#edit-synonyms"); + assert.ok( + find(".unlink-synonym:visible").length === 2, + "unlink UI is visible" + ); + assert.ok( + find(".delete-synonym:visible").length === 2, + "delete UI is visible" + ); + + await click(".unlink-synonym:first"); + assert.ok( + find(".tag-info .synonyms-list .tag-box").length === 1, + "removed a synonym" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-admin-menu-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-admin-menu-test.js index eeb56b06117..63bfd3e3bdd 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-admin-menu-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-admin-menu-test.js @@ -5,44 +5,51 @@ import { updateCurrentUser, } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Topic - Admin Menu Anonymous Users", { loggedIn: false }); - -test("Enter as a regular user", async (assert) => { - await visit("/t/internationalization-localization/280"); - assert.ok(exists("#topic"), "The topic was rendered"); - assert.ok( - !exists(".toggle-admin-menu"), - "The admin menu button was not rendered" - ); +acceptance("Topic - Admin Menu Anonymous Users", function () { + test("Enter as a regular user", async (assert) => { + await visit("/t/internationalization-localization/280"); + assert.ok(exists("#topic"), "The topic was rendered"); + assert.ok( + !exists(".toggle-admin-menu"), + "The admin menu button was not rendered" + ); + }); }); -acceptance("Topic - Admin Menu", { loggedIn: true }); +acceptance("Topic - Admin Menu", function (needs) { + needs.user(); + test("Enter as a user with group moderator permissions", async (assert) => { + updateCurrentUser({ moderator: false, admin: false, trust_level: 1 }); -test("Enter as a user with group moderator permissions", async (assert) => { - updateCurrentUser({ moderator: false, admin: false, trust_level: 1 }); + await visit("/t/topic-for-group-moderators/2480"); + assert.ok(exists("#topic"), "The topic was rendered"); + assert.ok( + exists(".toggle-admin-menu"), + "The admin menu button was rendered" + ); + }); - await visit("/t/topic-for-group-moderators/2480"); - assert.ok(exists("#topic"), "The topic was rendered"); - assert.ok(exists(".toggle-admin-menu"), "The admin menu button was rendered"); -}); - -test("Enter as a user with moderator and admin permissions", async (assert) => { - updateCurrentUser({ moderator: true, admin: true, trust_level: 4 }); - - await visit("/t/internationalization-localization/280"); - assert.ok(exists("#topic"), "The topic was rendered"); - assert.ok(exists(".toggle-admin-menu"), "The admin menu button was rendered"); -}); - -test("Toggle the menu as admin focuses the first item", async (assert) => { - updateCurrentUser({ admin: true }); - - await visit("/t/internationalization-localization/280"); - assert.ok(exists("#topic"), "The topic was rendered"); - await click(".toggle-admin-menu"); - - assert.equal( - document.activeElement, - document.querySelector(".topic-admin-multi-select > button") - ); + test("Enter as a user with moderator and admin permissions", async (assert) => { + updateCurrentUser({ moderator: true, admin: true, trust_level: 4 }); + + await visit("/t/internationalization-localization/280"); + assert.ok(exists("#topic"), "The topic was rendered"); + assert.ok( + exists(".toggle-admin-menu"), + "The admin menu button was rendered" + ); + }); + + test("Toggle the menu as admin focuses the first item", async (assert) => { + updateCurrentUser({ admin: true }); + + await visit("/t/internationalization-localization/280"); + assert.ok(exists("#topic"), "The topic was rendered"); + await click(".toggle-admin-menu"); + + assert.equal( + document.activeElement, + document.querySelector(".topic-admin-multi-select > button") + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-anonymous-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-anonymous-test.js index 3ac2aa5ac57..26b1432e7f7 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-anonymous-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-anonymous-test.js @@ -1,37 +1,38 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Topic - Anonymous"); -test("Enter a Topic", async (assert) => { - await visit("/t/internationalization-localization/280/1"); - assert.ok(exists("#topic"), "The topic was rendered"); - assert.ok(exists("#topic .cooked"), "The topic has cooked posts"); - assert.ok( - find(".shared-draft-notice").length === 0, - "no shared draft unless there's a dest category id" - ); -}); +acceptance("Topic - Anonymous", function () { + test("Enter a Topic", async (assert) => { + await visit("/t/internationalization-localization/280/1"); + assert.ok(exists("#topic"), "The topic was rendered"); + assert.ok(exists("#topic .cooked"), "The topic has cooked posts"); + assert.ok( + find(".shared-draft-notice").length === 0, + "no shared draft unless there's a dest category id" + ); + }); -test("Enter without an id", async (assert) => { - await visit("/t/internationalization-localization"); - assert.ok(exists("#topic"), "The topic was rendered"); -}); + test("Enter without an id", async (assert) => { + await visit("/t/internationalization-localization"); + assert.ok(exists("#topic"), "The topic was rendered"); + }); -test("Enter a 404 topic", async (assert) => { - await visit("/t/not-found/404"); - assert.ok(!exists("#topic"), "The topic was not rendered"); - assert.ok(exists(".topic-error"), "An error message is displayed"); -}); + test("Enter a 404 topic", async (assert) => { + await visit("/t/not-found/404"); + assert.ok(!exists("#topic"), "The topic was not rendered"); + assert.ok(exists(".topic-error"), "An error message is displayed"); + }); -test("Enter without access", async (assert) => { - await visit("/t/i-dont-have-access/403"); - assert.ok(!exists("#topic"), "The topic was not rendered"); - assert.ok(exists(".topic-error"), "An error message is displayed"); -}); + test("Enter without access", async (assert) => { + await visit("/t/i-dont-have-access/403"); + assert.ok(!exists("#topic"), "The topic was not rendered"); + assert.ok(exists(".topic-error"), "An error message is displayed"); + }); -test("Enter with 500 errors", async (assert) => { - await visit("/t/throws-error/500"); - assert.ok(!exists("#topic"), "The topic was not rendered"); - assert.ok(exists(".topic-error"), "An error message is displayed"); + test("Enter with 500 errors", async (assert) => { + await visit("/t/throws-error/500"); + assert.ok(!exists("#topic"), "The topic was not rendered"); + assert.ok(exists(".topic-error"), "An error message is displayed"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-discovery-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-discovery-test.js index 1af02a7f935..c46dbb374d6 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-discovery-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-discovery-test.js @@ -5,125 +5,125 @@ import selectKit from "discourse/tests/helpers/select-kit-helper"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import MessageBus from "message-bus-client"; -acceptance("Topic Discovery", { - settings: { +acceptance("Topic Discovery", function (needs) { + needs.settings({ show_pinned_excerpt_desktop: true, - }, -}); + }); -test("Visit Discovery Pages", async (assert) => { - await visit("/"); - assert.ok($("body.navigation-topics").length, "has the default navigation"); - assert.ok(exists(".topic-list"), "The list of topics was rendered"); - assert.ok(exists(".topic-list .topic-list-item"), "has topics"); + test("Visit Discovery Pages", async (assert) => { + await visit("/"); + assert.ok($("body.navigation-topics").length, "has the default navigation"); + assert.ok(exists(".topic-list"), "The list of topics was rendered"); + assert.ok(exists(".topic-list .topic-list-item"), "has topics"); - assert.equal( - find("a[data-user-card=eviltrout]:first img.avatar").attr("title"), - "Evil Trout - Most Posts", - "it shows user's full name in avatar title" - ); + assert.equal( + find("a[data-user-card=eviltrout]:first img.avatar").attr("title"), + "Evil Trout - Most Posts", + "it shows user's full name in avatar title" + ); - await visit("/c/bug"); - assert.ok(exists(".topic-list"), "The list of topics was rendered"); - assert.ok(exists(".topic-list .topic-list-item"), "has topics"); - assert.ok(!exists(".category-list"), "doesn't render subcategories"); - assert.ok( - $("body.category-bug").length, - "has a custom css class for the category id on the body" - ); + await visit("/c/bug"); + assert.ok(exists(".topic-list"), "The list of topics was rendered"); + assert.ok(exists(".topic-list .topic-list-item"), "has topics"); + assert.ok(!exists(".category-list"), "doesn't render subcategories"); + assert.ok( + $("body.category-bug").length, + "has a custom css class for the category id on the body" + ); - await visit("/categories"); - assert.ok($("body.navigation-categories").length, "has the body class"); - assert.ok( - $("body.category-bug").length === 0, - "removes the custom category class" - ); - assert.ok(exists(".category"), "has a list of categories"); - assert.ok( - $("body.categories-list").length, - "has a custom class to indicate categories" - ); + await visit("/categories"); + assert.ok($("body.navigation-categories").length, "has the body class"); + assert.ok( + $("body.category-bug").length === 0, + "removes the custom category class" + ); + assert.ok(exists(".category"), "has a list of categories"); + assert.ok( + $("body.categories-list").length, + "has a custom class to indicate categories" + ); - await visit("/top"); - assert.ok( - $("body.categories-list").length === 0, - "removes the `categories-list` class" - ); - assert.ok(exists(".topic-list .topic-list-item"), "has topics"); + await visit("/top"); + assert.ok( + $("body.categories-list").length === 0, + "removes the `categories-list` class" + ); + assert.ok(exists(".topic-list .topic-list-item"), "has topics"); - await visit("/c/feature"); - assert.ok(exists(".topic-list"), "The list of topics was rendered"); - assert.ok( - exists(".category-boxes"), - "The list of subcategories were rendered with box style" - ); + await visit("/c/feature"); + assert.ok(exists(".topic-list"), "The list of topics was rendered"); + assert.ok( + exists(".category-boxes"), + "The list of subcategories were rendered with box style" + ); - await visit("/c/dev"); - assert.ok(exists(".topic-list"), "The list of topics was rendered"); - assert.ok( - exists(".category-boxes-with-topics"), - "The list of subcategories were rendered with box-with-featured-topics style" - ); - assert.ok( - exists(".category-boxes-with-topics .featured-topics"), - "The featured topics are there too" - ); -}); + await visit("/c/dev"); + assert.ok(exists(".topic-list"), "The list of topics was rendered"); + assert.ok( + exists(".category-boxes-with-topics"), + "The list of subcategories were rendered with box-with-featured-topics style" + ); + assert.ok( + exists(".category-boxes-with-topics .featured-topics"), + "The featured topics are there too" + ); + }); -test("Clearing state after leaving a category", async (assert) => { - await visit("/c/dev"); - assert.ok( - exists(".topic-list-item[data-topic-id=11994] .topic-excerpt"), - "it expands pinned topics in a subcategory" - ); - await visit("/"); - assert.ok( - !exists(".topic-list-item[data-topic-id=11557] .topic-excerpt"), - "it doesn't expand all pinned in the latest category" - ); -}); + test("Clearing state after leaving a category", async (assert) => { + await visit("/c/dev"); + assert.ok( + exists(".topic-list-item[data-topic-id=11994] .topic-excerpt"), + "it expands pinned topics in a subcategory" + ); + await visit("/"); + assert.ok( + !exists(".topic-list-item[data-topic-id=11557] .topic-excerpt"), + "it doesn't expand all pinned in the latest category" + ); + }); -test("Live update unread state", async (assert) => { - await visit("/"); - assert.ok( - exists(".topic-list-item:not(.visited) a[data-topic-id='11995']"), - "shows the topic unread" - ); + test("Live update unread state", async (assert) => { + await visit("/"); + assert.ok( + exists(".topic-list-item:not(.visited) a[data-topic-id='11995']"), + "shows the topic unread" + ); - // Mimic a messagebus message - MessageBus.callbacks.filterBy("channel", "/latest").map((c) => - c.func({ - message_type: "read", - topic_id: 11995, - payload: { - highest_post_number: 1, - last_read_post_number: 2, - notification_level: 1, + // Mimic a messagebus message + MessageBus.callbacks.filterBy("channel", "/latest").map((c) => + c.func({ + message_type: "read", topic_id: 11995, - }, - }) - ); + payload: { + highest_post_number: 1, + last_read_post_number: 2, + notification_level: 1, + topic_id: 11995, + }, + }) + ); - await visit("/"); // We're already there, but use this to wait for re-render + await visit("/"); // We're already there, but use this to wait for re-render - assert.ok( - exists(".topic-list-item.visited a[data-topic-id='11995']"), - "shows the topic read" - ); -}); - -test("Using period chooser when query params are present", async (assert) => { - await visit("/top?f=foo&d=bar"); - - sandbox.stub(DiscourseURL, "routeTo"); - - const periodChooser = selectKit(".period-chooser"); - - await periodChooser.expand(); - await periodChooser.selectRowByValue("yearly"); - - assert.ok( - DiscourseURL.routeTo.calledWith("/top/yearly?f=foo&d=bar"), - "it keeps the query params" - ); + assert.ok( + exists(".topic-list-item.visited a[data-topic-id='11995']"), + "shows the topic read" + ); + }); + + test("Using period chooser when query params are present", async (assert) => { + await visit("/top?f=foo&d=bar"); + + sandbox.stub(DiscourseURL, "routeTo"); + + const periodChooser = selectKit(".period-chooser"); + + await periodChooser.expand(); + await periodChooser.selectRowByValue("yearly"); + + assert.ok( + DiscourseURL.routeTo.calledWith("/top/yearly?f=foo&d=bar"), + "it keeps the query params" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-edit-timer-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-edit-timer-test.js index 49d4ca619a3..24f4846ef89 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-edit-timer-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-edit-timer-test.js @@ -7,9 +7,9 @@ import { updateCurrentUser, } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Topic - Edit timer", { - loggedIn: true, - pretend(server, helper) { +acceptance("Topic - Edit timer", function (needs) { + needs.user(); + needs.pretender((server, helper) => { server.post("/t/280/timer", () => helper.response({ success: "OK", @@ -22,219 +22,240 @@ acceptance("Topic - Edit timer", { category_id: null, }) ); - }, -}); - -test("default", async (assert) => { - updateCurrentUser({ moderator: true }); - const futureDateInputSelector = selectKit(".future-date-input-selector"); - - await visit("/t/internationalization-localization"); - await click(".toggle-admin-menu"); - await click(".topic-admin-status-update button"); - - assert.equal(futureDateInputSelector.header().label(), "Select a timeframe"); - assert.equal(futureDateInputSelector.header().value(), null); -}); - -test("autoclose - specific time", async (assert) => { - updateCurrentUser({ moderator: true }); - const futureDateInputSelector = selectKit(".future-date-input-selector"); - - await visit("/t/internationalization-localization"); - await click(".toggle-admin-menu"); - await click(".topic-admin-status-update button"); - - await futureDateInputSelector.expand(); - await futureDateInputSelector.selectRowByValue("next_week"); - - assert.ok(futureDateInputSelector.header().label().includes("Next week")); - assert.equal(futureDateInputSelector.header().value(), "next_week"); - - const regex = /will automatically close in/g; - const html = find(".future-date-input .topic-status-info").html().trim(); - assert.ok(regex.test(html)); -}); - -skip("autoclose", async (assert) => { - updateCurrentUser({ moderator: true }); - const futureDateInputSelector = selectKit(".future-date-input-selector"); - - await visit("/t/internationalization-localization"); - await click(".toggle-admin-menu"); - await click(".topic-admin-status-update button"); - - await futureDateInputSelector.expand(); - await futureDateInputSelector.selectRowByValue("next_week"); - - assert.ok(futureDateInputSelector.header().label().includes("Next week")); - assert.equal(futureDateInputSelector.header().value(), "next_week"); - - const regex1 = /will automatically close in/g; - const html1 = find(".future-date-input .topic-status-info").html().trim(); - assert.ok(regex1.test(html1)); - - await futureDateInputSelector.expand(); - await futureDateInputSelector.selectRowByValue("pick_date_and_time"); - - await fillIn(".future-date-input .date-picker", "2099-11-24"); - - assert.ok( - futureDateInputSelector.header().label().includes("Pick date and time") - ); - assert.equal(futureDateInputSelector.header().value(), "pick_date_and_time"); - - const regex2 = /will automatically close in/g; - const html2 = find(".future-date-input .topic-status-info").html().trim(); - assert.ok(regex2.test(html2)); - - await futureDateInputSelector.expand(); - await futureDateInputSelector.selectRowByValue("set_based_on_last_post"); - - await fillIn(".future-date-input input[type=number]", "2"); - - assert.ok( - futureDateInputSelector - .header() - .label() - .includes("Close based on last post") - ); - assert.equal( - futureDateInputSelector.header().value(), - "set_based_on_last_post" - ); - - const regex3 = /This topic will close.*after the last reply/g; - const html3 = find(".future-date-input .topic-status-info").html().trim(); - assert.ok(regex3.test(html3)); -}); - -test("close temporarily", async (assert) => { - updateCurrentUser({ moderator: true }); - const timerType = selectKit(".select-kit.timer-type"); - const futureDateInputSelector = selectKit(".future-date-input-selector"); - - await visit("/t/internationalization-localization"); - await click(".toggle-admin-menu"); - await click(".topic-admin-status-update button"); - - await timerType.expand(); - await timerType.selectRowByValue("open"); - - assert.equal(futureDateInputSelector.header().label(), "Select a timeframe"); - assert.equal(futureDateInputSelector.header().value(), null); - - await futureDateInputSelector.expand(); - await futureDateInputSelector.selectRowByValue("next_week"); - - assert.ok(futureDateInputSelector.header().label().includes("Next week")); - assert.equal(futureDateInputSelector.header().value(), "next_week"); - - const regex1 = /will automatically open in/g; - const html1 = find(".future-date-input .topic-status-info").html().trim(); - assert.ok(regex1.test(html1)); - - await futureDateInputSelector.expand(); - await futureDateInputSelector.selectRowByValue("pick_date_and_time"); - - await fillIn(".future-date-input .date-picker", "2099-11-24"); - - assert.equal(futureDateInputSelector.header().label(), "Pick date and time"); - assert.equal(futureDateInputSelector.header().value(), "pick_date_and_time"); - - const regex2 = /will automatically open in/g; - const html2 = find(".future-date-input .topic-status-info").html().trim(); - assert.ok(regex2.test(html2)); -}); - -test("schedule", async (assert) => { - updateCurrentUser({ moderator: true }); - const timerType = selectKit(".select-kit.timer-type"); - const categoryChooser = selectKit(".modal-body .category-chooser"); - const futureDateInputSelector = selectKit(".future-date-input-selector"); - - await visit("/t/internationalization-localization"); - await click(".toggle-admin-menu"); - await click(".topic-admin-status-update button"); - - await timerType.expand(); - await timerType.selectRowByValue("publish_to_category"); - - assert.equal(categoryChooser.header().label(), "uncategorized"); - assert.equal(categoryChooser.header().value(), null); - - assert.equal(futureDateInputSelector.header().label(), "Select a timeframe"); - assert.equal(futureDateInputSelector.header().value(), null); - - await categoryChooser.expand(); - await categoryChooser.selectRowByValue("7"); - - await futureDateInputSelector.expand(); - await futureDateInputSelector.selectRowByValue("next_week"); - - assert.ok(futureDateInputSelector.header().label().includes("Next week")); - assert.equal(futureDateInputSelector.header().value(), "next_week"); - - const regex = /will be published to #dev/g; - const text = find(".future-date-input .topic-status-info").text().trim(); - assert.ok(regex.test(text)); -}); - -test("TL4 can't auto-delete", async (assert) => { - updateCurrentUser({ moderator: false, admin: false, trust_level: 4 }); - - await visit("/t/internationalization-localization"); - await click(".toggle-admin-menu"); - await click(".topic-admin-status-update button"); - - const timerType = selectKit(".select-kit.timer-type"); - - await timerType.expand(); - - assert.ok(!timerType.rowByValue("delete").exists()); -}); - -test("auto delete", async (assert) => { - updateCurrentUser({ moderator: true }); - const timerType = selectKit(".select-kit.timer-type"); - const futureDateInputSelector = selectKit(".future-date-input-selector"); - - await visit("/t/internationalization-localization"); - await click(".toggle-admin-menu"); - await click(".topic-admin-status-update button"); - - await timerType.expand(); - await timerType.selectRowByValue("delete"); - - assert.equal(futureDateInputSelector.header().label(), "Select a timeframe"); - assert.equal(futureDateInputSelector.header().value(), null); - - await futureDateInputSelector.expand(); - await futureDateInputSelector.selectRowByValue("two_weeks"); - - assert.ok(futureDateInputSelector.header().label().includes("Two Weeks")); - assert.equal(futureDateInputSelector.header().value(), "two_weeks"); - - const regex = /will be automatically deleted/g; - const html = find(".future-date-input .topic-status-info").html().trim(); - assert.ok(regex.test(html)); -}); - -test("Inline delete timer", async (assert) => { - updateCurrentUser({ moderator: true }); - const futureDateInputSelector = selectKit(".future-date-input-selector"); - - await visit("/t/internationalization-localization"); - await click(".toggle-admin-menu"); - await click(".topic-admin-status-update button"); - await futureDateInputSelector.expand(); - await futureDateInputSelector.selectRowByValue("next_week"); - await click(".modal-footer button.btn-primary"); - - const removeTimerButton = find(".topic-status-info .topic-timer-remove"); - assert.equal(removeTimerButton.attr("title"), "remove timer"); - - await click(".topic-status-info .topic-timer-remove"); - const topicStatusInfo = find(".topic-status-info .topic-timer-remove"); - assert.equal(topicStatusInfo.length, 0); + }); + + test("default", async (assert) => { + updateCurrentUser({ moderator: true }); + const futureDateInputSelector = selectKit(".future-date-input-selector"); + + await visit("/t/internationalization-localization"); + await click(".toggle-admin-menu"); + await click(".topic-admin-status-update button"); + + assert.equal( + futureDateInputSelector.header().label(), + "Select a timeframe" + ); + assert.equal(futureDateInputSelector.header().value(), null); + }); + + test("autoclose - specific time", async (assert) => { + updateCurrentUser({ moderator: true }); + const futureDateInputSelector = selectKit(".future-date-input-selector"); + + await visit("/t/internationalization-localization"); + await click(".toggle-admin-menu"); + await click(".topic-admin-status-update button"); + + await futureDateInputSelector.expand(); + await futureDateInputSelector.selectRowByValue("next_week"); + + assert.ok(futureDateInputSelector.header().label().includes("Next week")); + assert.equal(futureDateInputSelector.header().value(), "next_week"); + + const regex = /will automatically close in/g; + const html = find(".future-date-input .topic-status-info").html().trim(); + assert.ok(regex.test(html)); + }); + + skip("autoclose", async (assert) => { + updateCurrentUser({ moderator: true }); + const futureDateInputSelector = selectKit(".future-date-input-selector"); + + await visit("/t/internationalization-localization"); + await click(".toggle-admin-menu"); + await click(".topic-admin-status-update button"); + + await futureDateInputSelector.expand(); + await futureDateInputSelector.selectRowByValue("next_week"); + + assert.ok(futureDateInputSelector.header().label().includes("Next week")); + assert.equal(futureDateInputSelector.header().value(), "next_week"); + + const regex1 = /will automatically close in/g; + const html1 = find(".future-date-input .topic-status-info").html().trim(); + assert.ok(regex1.test(html1)); + + await futureDateInputSelector.expand(); + await futureDateInputSelector.selectRowByValue("pick_date_and_time"); + + await fillIn(".future-date-input .date-picker", "2099-11-24"); + + assert.ok( + futureDateInputSelector.header().label().includes("Pick date and time") + ); + assert.equal( + futureDateInputSelector.header().value(), + "pick_date_and_time" + ); + + const regex2 = /will automatically close in/g; + const html2 = find(".future-date-input .topic-status-info").html().trim(); + assert.ok(regex2.test(html2)); + + await futureDateInputSelector.expand(); + await futureDateInputSelector.selectRowByValue("set_based_on_last_post"); + + await fillIn(".future-date-input input[type=number]", "2"); + + assert.ok( + futureDateInputSelector + .header() + .label() + .includes("Close based on last post") + ); + assert.equal( + futureDateInputSelector.header().value(), + "set_based_on_last_post" + ); + + const regex3 = /This topic will close.*after the last reply/g; + const html3 = find(".future-date-input .topic-status-info").html().trim(); + assert.ok(regex3.test(html3)); + }); + + test("close temporarily", async (assert) => { + updateCurrentUser({ moderator: true }); + const timerType = selectKit(".select-kit.timer-type"); + const futureDateInputSelector = selectKit(".future-date-input-selector"); + + await visit("/t/internationalization-localization"); + await click(".toggle-admin-menu"); + await click(".topic-admin-status-update button"); + + await timerType.expand(); + await timerType.selectRowByValue("open"); + + assert.equal( + futureDateInputSelector.header().label(), + "Select a timeframe" + ); + assert.equal(futureDateInputSelector.header().value(), null); + + await futureDateInputSelector.expand(); + await futureDateInputSelector.selectRowByValue("next_week"); + + assert.ok(futureDateInputSelector.header().label().includes("Next week")); + assert.equal(futureDateInputSelector.header().value(), "next_week"); + + const regex1 = /will automatically open in/g; + const html1 = find(".future-date-input .topic-status-info").html().trim(); + assert.ok(regex1.test(html1)); + + await futureDateInputSelector.expand(); + await futureDateInputSelector.selectRowByValue("pick_date_and_time"); + + await fillIn(".future-date-input .date-picker", "2099-11-24"); + + assert.equal( + futureDateInputSelector.header().label(), + "Pick date and time" + ); + assert.equal( + futureDateInputSelector.header().value(), + "pick_date_and_time" + ); + + const regex2 = /will automatically open in/g; + const html2 = find(".future-date-input .topic-status-info").html().trim(); + assert.ok(regex2.test(html2)); + }); + + test("schedule", async (assert) => { + updateCurrentUser({ moderator: true }); + const timerType = selectKit(".select-kit.timer-type"); + const categoryChooser = selectKit(".modal-body .category-chooser"); + const futureDateInputSelector = selectKit(".future-date-input-selector"); + + await visit("/t/internationalization-localization"); + await click(".toggle-admin-menu"); + await click(".topic-admin-status-update button"); + + await timerType.expand(); + await timerType.selectRowByValue("publish_to_category"); + + assert.equal(categoryChooser.header().label(), "uncategorized"); + assert.equal(categoryChooser.header().value(), null); + + assert.equal( + futureDateInputSelector.header().label(), + "Select a timeframe" + ); + assert.equal(futureDateInputSelector.header().value(), null); + + await categoryChooser.expand(); + await categoryChooser.selectRowByValue("7"); + + await futureDateInputSelector.expand(); + await futureDateInputSelector.selectRowByValue("next_week"); + + assert.ok(futureDateInputSelector.header().label().includes("Next week")); + assert.equal(futureDateInputSelector.header().value(), "next_week"); + + const regex = /will be published to #dev/g; + const text = find(".future-date-input .topic-status-info").text().trim(); + assert.ok(regex.test(text)); + }); + + test("TL4 can't auto-delete", async (assert) => { + updateCurrentUser({ moderator: false, admin: false, trust_level: 4 }); + + await visit("/t/internationalization-localization"); + await click(".toggle-admin-menu"); + await click(".topic-admin-status-update button"); + + const timerType = selectKit(".select-kit.timer-type"); + + await timerType.expand(); + + assert.ok(!timerType.rowByValue("delete").exists()); + }); + + test("auto delete", async (assert) => { + updateCurrentUser({ moderator: true }); + const timerType = selectKit(".select-kit.timer-type"); + const futureDateInputSelector = selectKit(".future-date-input-selector"); + + await visit("/t/internationalization-localization"); + await click(".toggle-admin-menu"); + await click(".topic-admin-status-update button"); + + await timerType.expand(); + await timerType.selectRowByValue("delete"); + + assert.equal( + futureDateInputSelector.header().label(), + "Select a timeframe" + ); + assert.equal(futureDateInputSelector.header().value(), null); + + await futureDateInputSelector.expand(); + await futureDateInputSelector.selectRowByValue("two_weeks"); + + assert.ok(futureDateInputSelector.header().label().includes("Two Weeks")); + assert.equal(futureDateInputSelector.header().value(), "two_weeks"); + + const regex = /will be automatically deleted/g; + const html = find(".future-date-input .topic-status-info").html().trim(); + assert.ok(regex.test(html)); + }); + + test("Inline delete timer", async (assert) => { + updateCurrentUser({ moderator: true }); + const futureDateInputSelector = selectKit(".future-date-input-selector"); + + await visit("/t/internationalization-localization"); + await click(".toggle-admin-menu"); + await click(".topic-admin-status-update button"); + await futureDateInputSelector.expand(); + await futureDateInputSelector.selectRowByValue("next_week"); + await click(".modal-footer button.btn-primary"); + + const removeTimerButton = find(".topic-status-info .topic-timer-remove"); + assert.equal(removeTimerButton.attr("title"), "remove timer"); + + await click(".topic-status-info .topic-timer-remove"); + const topicStatusInfo = find(".topic-status-info .topic-timer-remove"); + assert.equal(topicStatusInfo.length, 0); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-footer-buttons-mobile-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-footer-buttons-mobile-test.js index a17494cabe9..f64412210d5 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-footer-buttons-mobile-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-footer-buttons-mobile-test.js @@ -8,10 +8,11 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers"; let _test; -acceptance("Topic footer buttons mobile", { - loggedIn: true, - mobileView: true, - beforeEach() { +acceptance("Topic footer buttons mobile", function (needs) { + needs.user(); + needs.mobileView(); + + needs.hooks.beforeEach(() => { I18n.translations[I18n.locale].js.test = { title: "My title", label: "My Label", @@ -29,22 +30,22 @@ acceptance("Topic footer buttons mobile", { }, }); }); - }, + }); - afterEach() { + needs.hooks.afterEach(() => { clearTopicFooterButtons(); _test = undefined; - }, -}); - -test("default", async (assert) => { - await visit("/t/internationalization-localization/280"); - - assert.equal(_test, null); - - const subject = selectKit(".topic-footer-mobile-dropdown"); - await subject.expand(); - await subject.selectRowByValue("my-button"); - - assert.equal(_test, 2); + }); + + test("default", async (assert) => { + await visit("/t/internationalization-localization/280"); + + assert.equal(_test, null); + + const subject = selectKit(".topic-footer-mobile-dropdown"); + await subject.expand(); + await subject.selectRowByValue("my-button"); + + assert.equal(_test, 2); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-list-tracker-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-list-tracker-test.js index 8a4e4756e11..b799fa071e0 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-list-tracker-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-list-tracker-test.js @@ -6,18 +6,19 @@ import { previousTopicUrl, setTopicId, } from "discourse/lib/topic-list-tracker"; -acceptance("Topic list tracking"); -test("Navigation", async (assert) => { - await visit("/"); - let url = await nextTopicUrl(); - assert.equal(url, "/t/error-after-upgrade-to-0-9-7-9/11557"); +acceptance("Topic list tracking", function () { + test("Navigation", async (assert) => { + await visit("/"); + let url = await nextTopicUrl(); + assert.equal(url, "/t/error-after-upgrade-to-0-9-7-9/11557"); - setTopicId(11557); + setTopicId(11557); - url = await nextTopicUrl(); - assert.equal(url, "/t/welcome-to-meta-discourse-org/1"); + url = await nextTopicUrl(); + assert.equal(url, "/t/welcome-to-meta-discourse-org/1"); - url = await previousTopicUrl(); - assert.equal(url, "/t/error-after-upgrade-to-0-9-7-9/11557"); + url = await previousTopicUrl(); + assert.equal(url, "/t/error-after-upgrade-to-0-9-7-9/11557"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-move-posts-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-move-posts-test.js index a69f3fb75ca..0451c380c7c 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-move-posts-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-move-posts-test.js @@ -2,141 +2,144 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import I18n from "I18n"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Topic move posts", { loggedIn: true }); -test("default", async (assert) => { - await visit("/t/internationalization-localization"); - await click(".toggle-admin-menu"); - await click(".topic-admin-multi-select .btn"); - await click("#post_11 .select-below"); +acceptance("Topic move posts", function (needs) { + needs.user(); - assert.equal( - find(".selected-posts .move-to-topic").text().trim(), - I18n.t("topic.move_to.action"), - "it should show the move to button" - ); + test("default", async (assert) => { + await visit("/t/internationalization-localization"); + await click(".toggle-admin-menu"); + await click(".topic-admin-multi-select .btn"); + await click("#post_11 .select-below"); - await click(".selected-posts .move-to-topic"); + assert.equal( + find(".selected-posts .move-to-topic").text().trim(), + I18n.t("topic.move_to.action"), + "it should show the move to button" + ); - assert.ok( - find(".choose-topic-modal .title") - .html() - .includes(I18n.t("topic.move_to.title")), - "it opens move to modal" - ); + await click(".selected-posts .move-to-topic"); - assert.ok( - find(".choose-topic-modal .radios") - .html() - .includes(I18n.t("topic.split_topic.radio_label")), - "it shows an option to move to new topic" - ); + assert.ok( + find(".choose-topic-modal .title") + .html() + .includes(I18n.t("topic.move_to.title")), + "it opens move to modal" + ); - assert.ok( - find(".choose-topic-modal .radios") - .html() - .includes(I18n.t("topic.merge_topic.radio_label")), - "it shows an option to move to existing topic" - ); + assert.ok( + find(".choose-topic-modal .radios") + .html() + .includes(I18n.t("topic.split_topic.radio_label")), + "it shows an option to move to new topic" + ); - assert.ok( - find(".choose-topic-modal .radios") - .html() - .includes(I18n.t("topic.move_to_new_message.radio_label")), - "it shows an option to move to new message" - ); -}); - -test("moving all posts", async (assert) => { - await visit("/t/internationalization-localization"); - await click(".toggle-admin-menu"); - await click(".topic-admin-multi-select .btn"); - await click(".select-all"); - await click(".selected-posts .move-to-topic"); - - assert.ok( - find(".choose-topic-modal .title") - .html() - .includes(I18n.t("topic.move_to.title")), - "it opens move to modal" - ); - - assert.not( - find(".choose-topic-modal .radios") - .html() - .includes(I18n.t("topic.split_topic.radio_label")), - "it does not show an option to move to new topic" - ); - - assert.ok( - find(".choose-topic-modal .radios") - .html() - .includes(I18n.t("topic.merge_topic.radio_label")), - "it shows an option to move to existing topic" - ); - - assert.not( - find(".choose-topic-modal .radios") - .html() - .includes(I18n.t("topic.move_to_new_message.radio_label")), - "it does not show an option to move to new message" - ); -}); - -test("moving posts from personal message", async (assert) => { - await visit("/t/pm-for-testing/12"); - await click(".toggle-admin-menu"); - await click(".topic-admin-multi-select .btn"); - await click("#post_1 .select-post"); - - assert.equal( - find(".selected-posts .move-to-topic").text().trim(), - I18n.t("topic.move_to.action"), - "it should show the move to button" - ); - - await click(".selected-posts .move-to-topic"); - - assert.ok( - find(".choose-topic-modal .title") - .html() - .includes(I18n.t("topic.move_to.title")), - "it opens move to modal" - ); - - assert.ok( - find(".choose-topic-modal .radios") - .html() - .includes(I18n.t("topic.move_to_new_message.radio_label")), - "it shows an option to move to new message" - ); - - assert.ok( - find(".choose-topic-modal .radios") - .html() - .includes(I18n.t("topic.move_to_existing_message.radio_label")), - "it shows an option to move to existing message" - ); -}); - -test("group moderator moving posts", async (assert) => { - await visit("/t/topic-for-group-moderators/2480"); - await click(".toggle-admin-menu"); - await click(".topic-admin-multi-select .btn"); - await click("#post_2 .select-below"); - - assert.equal( - find(".selected-posts .move-to-topic").text().trim(), - I18n.t("topic.move_to.action"), - "it should show the move to button" - ); - - await click(".selected-posts .move-to-topic"); - - assert.ok( - find(".choose-topic-modal .title") - .html() - .includes(I18n.t("topic.move_to.title")), - "it opens move to modal" - ); + assert.ok( + find(".choose-topic-modal .radios") + .html() + .includes(I18n.t("topic.merge_topic.radio_label")), + "it shows an option to move to existing topic" + ); + + assert.ok( + find(".choose-topic-modal .radios") + .html() + .includes(I18n.t("topic.move_to_new_message.radio_label")), + "it shows an option to move to new message" + ); + }); + + test("moving all posts", async (assert) => { + await visit("/t/internationalization-localization"); + await click(".toggle-admin-menu"); + await click(".topic-admin-multi-select .btn"); + await click(".select-all"); + await click(".selected-posts .move-to-topic"); + + assert.ok( + find(".choose-topic-modal .title") + .html() + .includes(I18n.t("topic.move_to.title")), + "it opens move to modal" + ); + + assert.not( + find(".choose-topic-modal .radios") + .html() + .includes(I18n.t("topic.split_topic.radio_label")), + "it does not show an option to move to new topic" + ); + + assert.ok( + find(".choose-topic-modal .radios") + .html() + .includes(I18n.t("topic.merge_topic.radio_label")), + "it shows an option to move to existing topic" + ); + + assert.not( + find(".choose-topic-modal .radios") + .html() + .includes(I18n.t("topic.move_to_new_message.radio_label")), + "it does not show an option to move to new message" + ); + }); + + test("moving posts from personal message", async (assert) => { + await visit("/t/pm-for-testing/12"); + await click(".toggle-admin-menu"); + await click(".topic-admin-multi-select .btn"); + await click("#post_1 .select-post"); + + assert.equal( + find(".selected-posts .move-to-topic").text().trim(), + I18n.t("topic.move_to.action"), + "it should show the move to button" + ); + + await click(".selected-posts .move-to-topic"); + + assert.ok( + find(".choose-topic-modal .title") + .html() + .includes(I18n.t("topic.move_to.title")), + "it opens move to modal" + ); + + assert.ok( + find(".choose-topic-modal .radios") + .html() + .includes(I18n.t("topic.move_to_new_message.radio_label")), + "it shows an option to move to new message" + ); + + assert.ok( + find(".choose-topic-modal .radios") + .html() + .includes(I18n.t("topic.move_to_existing_message.radio_label")), + "it shows an option to move to existing message" + ); + }); + + test("group moderator moving posts", async (assert) => { + await visit("/t/topic-for-group-moderators/2480"); + await click(".toggle-admin-menu"); + await click(".topic-admin-multi-select .btn"); + await click("#post_2 .select-below"); + + assert.equal( + find(".selected-posts .move-to-topic").text().trim(), + I18n.t("topic.move_to.action"), + "it should show the move to button" + ); + + await click(".selected-posts .move-to-topic"); + + assert.ok( + find(".choose-topic-modal .title") + .html() + .includes(I18n.t("topic.move_to.title")), + "it opens move to modal" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-notifications-button-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-notifications-button-test.js index 78ce034fe86..68be05e8334 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-notifications-button-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-notifications-button-test.js @@ -3,58 +3,59 @@ import { test } from "qunit"; import selectKit from "discourse/tests/helpers/select-kit-helper"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Topic Notifications button", { - loggedIn: true, - pretend(server, helper) { +acceptance("Topic Notifications button", function (needs) { + needs.user(); + + needs.pretender((server, helper) => { server.post("/t/280/notifications", () => { return helper.response({}); }); - }, -}); - -test("Updating topic notification level", async (assert) => { - const notificationOptions = selectKit( - "#topic-footer-buttons .topic-notifications-options" - ); - - await visit("/t/internationalization-localization/280"); - - assert.ok( - notificationOptions.exists(), - "it should display the notification options button in the topic's footer" - ); - - await notificationOptions.expand(); - await notificationOptions.selectRowByValue("3"); - - assert.equal( - notificationOptions.header().label(), - "Watching", - "it should display the right notification level" - ); - - const timelineNotificationOptions = selectKit( - ".topic-timeline .widget-component-connector .topic-notifications-options" - ); - - assert.equal( - timelineNotificationOptions.header().value(), - "3", - "it should display the right notification level" - ); - - await timelineNotificationOptions.expand(); - await timelineNotificationOptions.selectRowByValue("0"); - - assert.equal( - timelineNotificationOptions.header().value(), - "0", - "it should display the right notification level" - ); - - assert.equal( - notificationOptions.header().label(), - "Muted", - "it should display the right notification level" - ); + }); + + test("Updating topic notification level", async (assert) => { + const notificationOptions = selectKit( + "#topic-footer-buttons .topic-notifications-options" + ); + + await visit("/t/internationalization-localization/280"); + + assert.ok( + notificationOptions.exists(), + "it should display the notification options button in the topic's footer" + ); + + await notificationOptions.expand(); + await notificationOptions.selectRowByValue("3"); + + assert.equal( + notificationOptions.header().label(), + "Watching", + "it should display the right notification level" + ); + + const timelineNotificationOptions = selectKit( + ".topic-timeline .widget-component-connector .topic-notifications-options" + ); + + assert.equal( + timelineNotificationOptions.header().value(), + "3", + "it should display the right notification level" + ); + + await timelineNotificationOptions.expand(); + await timelineNotificationOptions.selectRowByValue("0"); + + assert.equal( + timelineNotificationOptions.header().value(), + "0", + "it should display the right notification level" + ); + + assert.equal( + notificationOptions.header().label(), + "Muted", + "it should display the right notification level" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-quote-button-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-quote-button-test.js index 11a1e815bd9..78f48ffddc9 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-quote-button-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-quote-button-test.js @@ -13,103 +13,102 @@ function selectText(selector) { selection.addRange(range); } -acceptance("Topic - Quote button - logged in", { - loggedIn: true, - settings: { +acceptance("Topic - Quote button - logged in", function (needs) { + needs.user(); + needs.settings({ share_quote_visibility: "anonymous", share_quote_buttons: "twitter|email", - }, + }); + + test("Does not show the quote share buttons by default", async (assert) => { + await visit("/t/internationalization-localization/280"); + selectText("#post_5 blockquote"); + assert.ok(exists(".insert-quote"), "it shows the quote button"); + assert.equal( + find(".quote-sharing").length, + 0, + "it does not show quote sharing" + ); + }); + + test("Shows quote share buttons with the right site settings", async function (assert) { + this.siteSettings.share_quote_visibility = "all"; + + await visit("/t/internationalization-localization/280"); + selectText("#post_5 blockquote"); + + assert.ok(exists(".quote-sharing"), "it shows the quote sharing options"); + assert.ok( + exists(`.quote-sharing .btn[title='${I18n.t("share.twitter")}']`), + "it includes the twitter share button" + ); + assert.ok( + exists(`.quote-sharing .btn[title='${I18n.t("share.email")}']`), + "it includes the email share button" + ); + }); }); -test("Does not show the quote share buttons by default", async (assert) => { - await visit("/t/internationalization-localization/280"); - selectText("#post_5 blockquote"); - assert.ok(exists(".insert-quote"), "it shows the quote button"); - assert.equal( - find(".quote-sharing").length, - 0, - "it does not show quote sharing" - ); -}); - -test("Shows quote share buttons with the right site settings", async function (assert) { - this.siteSettings.share_quote_visibility = "all"; - - await visit("/t/internationalization-localization/280"); - selectText("#post_5 blockquote"); - - assert.ok(exists(".quote-sharing"), "it shows the quote sharing options"); - assert.ok( - exists(`.quote-sharing .btn[title='${I18n.t("share.twitter")}']`), - "it includes the twitter share button" - ); - assert.ok( - exists(`.quote-sharing .btn[title='${I18n.t("share.email")}']`), - "it includes the email share button" - ); -}); - -acceptance("Topic - Quote button - anonymous", { - loggedIn: false, - settings: { +acceptance("Topic - Quote button - anonymous", function (needs) { + needs.settings({ share_quote_visibility: "anonymous", share_quote_buttons: "twitter|email", - }, -}); - -test("Shows quote share buttons with the right site settings", async function (assert) { - await visit("/t/internationalization-localization/280"); - selectText("#post_5 blockquote"); - - assert.ok(find(".quote-sharing"), "it shows the quote sharing options"); - assert.ok( - exists(`.quote-sharing .btn[title='${I18n.t("share.twitter")}']`), - "it includes the twitter share button" - ); - assert.ok( - exists(`.quote-sharing .btn[title='${I18n.t("share.email")}']`), - "it includes the email share button" - ); - assert.equal( - find(".insert-quote").length, - 0, - "it does not show the quote button" - ); -}); - -test("Shows single share button when site setting only has one item", async function (assert) { - this.siteSettings.share_quote_buttons = "twitter"; - - await visit("/t/internationalization-localization/280"); - selectText("#post_5 blockquote"); - - assert.ok(exists(".quote-sharing"), "it shows the quote sharing options"); - assert.ok( - exists(`.quote-sharing .btn[title='${I18n.t("share.twitter")}']`), - "it includes the twitter share button" - ); - assert.equal( - find(".quote-share-label").length, - 0, - "it does not show the Share label" - ); -}); - -test("Shows nothing when visibility is disabled", async function (assert) { - this.siteSettings.share_quote_visibility = "none"; - - await visit("/t/internationalization-localization/280"); - selectText("#post_5 blockquote"); - - assert.equal( - find(".quote-sharing").length, - 0, - "it does not show quote sharing" - ); - - assert.equal( - find(".insert-quote").length, - 0, - "it does not show the quote button" - ); + }); + + test("Shows quote share buttons with the right site settings", async function (assert) { + await visit("/t/internationalization-localization/280"); + selectText("#post_5 blockquote"); + + assert.ok(find(".quote-sharing"), "it shows the quote sharing options"); + assert.ok( + exists(`.quote-sharing .btn[title='${I18n.t("share.twitter")}']`), + "it includes the twitter share button" + ); + assert.ok( + exists(`.quote-sharing .btn[title='${I18n.t("share.email")}']`), + "it includes the email share button" + ); + assert.equal( + find(".insert-quote").length, + 0, + "it does not show the quote button" + ); + }); + + test("Shows single share button when site setting only has one item", async function (assert) { + this.siteSettings.share_quote_buttons = "twitter"; + + await visit("/t/internationalization-localization/280"); + selectText("#post_5 blockquote"); + + assert.ok(exists(".quote-sharing"), "it shows the quote sharing options"); + assert.ok( + exists(`.quote-sharing .btn[title='${I18n.t("share.twitter")}']`), + "it includes the twitter share button" + ); + assert.equal( + find(".quote-share-label").length, + 0, + "it does not show the Share label" + ); + }); + + test("Shows nothing when visibility is disabled", async function (assert) { + this.siteSettings.share_quote_visibility = "none"; + + await visit("/t/internationalization-localization/280"); + selectText("#post_5 blockquote"); + + assert.equal( + find(".quote-sharing").length, + 0, + "it does not show quote sharing" + ); + + assert.equal( + find(".insert-quote").length, + 0, + "it does not show the quote button" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-test.js index 96b9236b189..ab82f7f972b 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-test.js @@ -1,5 +1,4 @@ import { visit } from "@ember/test-helpers"; -import { skip } from "qunit"; import { test } from "qunit"; import I18n from "I18n"; import { withPluginApi } from "discourse/lib/plugin-api"; @@ -7,314 +6,6 @@ import selectKit from "discourse/tests/helpers/select-kit-helper"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import { IMAGE_VERSION as v } from "pretty-text/emoji/version"; -acceptance("Topic", { - loggedIn: true, - pretend(server, helper) { - server.put("/posts/398/wiki", () => { - return helper.response({}); - }); - }, -}); - -test("Reply as new topic", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click("button.share:eq(0)"); - await click(".reply-as-new-topic a"); - - assert.ok(exists(".d-editor-input"), "the composer input is visible"); - - assert.equal( - find(".d-editor-input").val().trim(), - `Continuing the discussion from [Internationalization / localization](${window.location.origin}/t/internationalization-localization/280):`, - "it fills composer with the ring string" - ); - assert.equal( - selectKit(".category-chooser").header().value(), - "2", - "it fills category selector with the right category" - ); -}); - -test("Reply as new message", async (assert) => { - await visit("/t/pm-for-testing/12"); - await click("button.share:eq(0)"); - await click(".reply-as-new-topic a"); - - assert.ok(exists(".d-editor-input"), "the composer input is visible"); - - assert.equal( - find(".d-editor-input").val().trim(), - `Continuing the discussion from [PM for testing](${window.location.origin}/t/pm-for-testing/12):`, - "it fills composer with the ring string" - ); - - const targets = find(".item span", ".composer-fields"); - - assert.equal( - $(targets[0]).text(), - "someguy", - "it fills up the composer with the right user to start the PM to" - ); - - assert.equal( - $(targets[1]).text(), - "test", - "it fills up the composer with the right user to start the PM to" - ); - - assert.equal( - $(targets[2]).text(), - "Group", - "it fills up the composer with the right group to start the PM to" - ); -}); - -test("Share Modal", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click(".topic-post:first-child button.share"); - - assert.ok(exists("#share-link"), "it shows the share modal"); -}); - -test("Showing and hiding the edit controls", async (assert) => { - await visit("/t/internationalization-localization/280"); - - await click("#topic-title .d-icon-pencil-alt"); - - assert.ok(exists("#edit-title"), "it shows the editing controls"); - assert.ok( - !exists(".title-wrapper .remove-featured-link"), - "link to remove featured link is not shown" - ); - - await fillIn("#edit-title", "this is the new title"); - await click("#topic-title .cancel-edit"); - assert.ok(!exists("#edit-title"), "it hides the editing controls"); -}); - -test("Updating the topic title and category", async (assert) => { - const categoryChooser = selectKit(".title-wrapper .category-chooser"); - - await visit("/t/internationalization-localization/280"); - - await click("#topic-title .d-icon-pencil-alt"); - await fillIn("#edit-title", "this is the new title"); - await categoryChooser.expand(); - await categoryChooser.selectRowByValue(4); - await click("#topic-title .submit-edit"); - - assert.equal( - find("#topic-title .badge-category").text(), - "faq", - "it displays the new category" - ); - assert.equal( - find(".fancy-title").text().trim(), - "this is the new title", - "it displays the new title" - ); -}); - -test("Marking a topic as wiki", async (assert) => { - await visit("/t/internationalization-localization/280"); - - assert.ok(find("a.wiki").length === 0, "it does not show the wiki icon"); - - await click(".topic-post:eq(0) button.show-more-actions"); - await click(".topic-post:eq(0) button.show-post-admin-menu"); - await click(".btn.wiki"); - - assert.ok(find("a.wiki").length === 1, "it shows the wiki icon"); -}); - -test("Visit topic routes", async (assert) => { - await visit("/t/12"); - - assert.equal( - find(".fancy-title").text().trim(), - "PM for testing", - "it routes to the right topic" - ); - - await visit("/t/280/20"); - - assert.equal( - find(".fancy-title").text().trim(), - "Internationalization / localization", - "it routes to the right topic" - ); -}); - -test("Updating the topic title with emojis", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click("#topic-title .d-icon-pencil-alt"); - - await fillIn("#edit-title", "emojis title :bike: :blonde_woman:t6:"); - - await click("#topic-title .submit-edit"); - - assert.equal( - find(".fancy-title").html().trim(), - `emojis title bike blonde_woman:t6`, - "it displays the new title with emojis" - ); -}); - -test("Updating the topic title with unicode emojis", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click("#topic-title .d-icon-pencil-alt"); - - await fillIn("#edit-title", "emojis title 👨‍🌾🙏"); - - await click("#topic-title .submit-edit"); - - assert.equal( - find(".fancy-title").html().trim(), - `emojis title man_farmerpray`, - "it displays the new title with escaped unicode emojis" - ); -}); - -test("Updating the topic title with unicode emojis without whitespaces", async function (assert) { - this.siteSettings.enable_inline_emoji_translation = true; - await visit("/t/internationalization-localization/280"); - await click("#topic-title .d-icon-pencil-alt"); - - await fillIn("#edit-title", "Test🙂Title"); - - await click("#topic-title .submit-edit"); - - assert.equal( - find(".fancy-title").html().trim(), - `Testslightly_smiling_faceTitle`, - "it displays the new title with escaped unicode emojis" - ); -}); - -test("Suggested topics", async (assert) => { - await visit("/t/internationalization-localization/280"); - - assert.equal( - find("#suggested-topics .suggested-topics-title").text().trim(), - I18n.t("suggested_topics.title") - ); -}); - -skip("Deleting a topic", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click(".topic-post:eq(0) button.show-more-actions"); - await click(".widget-button.delete"); - - assert.ok(exists(".widget-button.recover"), "it shows the recover button"); -}); - -test("Group category moderator posts", async (assert) => { - await visit("/t/topic-for-group-moderators/2480"); - - assert.ok(exists(".category-moderator"), "it has a class applied"); - assert.ok(exists(".d-icon-shield-alt"), "it shows an icon"); -}); - -acceptance("Topic featured links", { - loggedIn: true, - settings: { - topic_featured_link_enabled: true, - max_topic_title_length: 80, - }, -}); - -skip("remove featured link", async (assert) => { - await visit("/t/-/299/1"); - assert.ok( - exists(".title-wrapper .topic-featured-link"), - "link is shown with topic title" - ); - - await click(".title-wrapper .edit-topic"); - assert.ok( - exists(".title-wrapper .remove-featured-link"), - "link to remove featured link" - ); - - await click(".title-wrapper .remove-featured-link"); - await click(".title-wrapper .submit-edit"); - assert.ok(!exists(".title-wrapper .topic-featured-link"), "link is gone"); -}); - -test("Converting to a public topic", async (assert) => { - await visit("/t/test-pm/34"); - assert.ok(exists(".private_message")); - await click(".toggle-admin-menu"); - await click(".topic-admin-convert button"); - - let categoryChooser = selectKit(".convert-to-public-topic .category-chooser"); - await categoryChooser.expand(); - await categoryChooser.selectRowByValue(21); - - await click(".convert-to-public-topic .btn-primary"); - assert.ok(!exists(".private_message")); -}); - -test("Unpinning unlisted topic", async (assert) => { - await visit("/t/internationalization-localization/280"); - - await click(".toggle-admin-menu"); - await click(".topic-admin-pin .btn"); - await click(".btn-primary:last"); - - await click(".toggle-admin-menu"); - await click(".topic-admin-visible .btn"); - - await click(".toggle-admin-menu"); - assert.ok(exists(".topic-admin-pin"), "it should show the multi select menu"); -}); - -test("selecting posts", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click(".toggle-admin-menu"); - await click(".topic-admin-multi-select .btn"); - - assert.ok( - exists(".selected-posts:not(.hidden)"), - "it should show the multi select menu" - ); - - assert.ok( - exists(".select-all"), - "it should allow users to select all the posts" - ); -}); - -test("select below", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click(".toggle-admin-menu"); - await click(".topic-admin-multi-select .btn"); - await click("#post_3 .select-below"); - - assert.ok( - find(".selected-posts") - .html() - .includes(I18n.t("topic.multi_select.description", { count: 18 })), - "it should select the right number of posts" - ); - - await click("#post_2 .select-below"); - - assert.ok( - find(".selected-posts") - .html() - .includes(I18n.t("topic.multi_select.description", { count: 19 })), - "it should select the right number of posts" - ); -}); - -test("View Hidden Replies", async (assert) => { - await visit("/t/internationalization-localization/280"); - await click(".gap"); - - assert.equal(find(".gap").length, 0, "it hides gap"); -}); - function selectText(selector) { const range = document.createRange(); const node = document.querySelector(selector); @@ -325,92 +16,395 @@ function selectText(selector) { selection.addRange(range); } -test("Quoting a quote keeps the original poster name", async (assert) => { - await visit("/t/internationalization-localization/280"); - selectText("#post_5 blockquote"); - await click(".quote-button .insert-quote"); +acceptance("Topic", function (needs) { + needs.user(); + needs.pretender((server, helper) => { + server.put("/posts/398/wiki", () => { + return helper.response({}); + }); + }); - assert.ok( - find(".d-editor-input") - .val() - .indexOf('quote="codinghorror said, post:3, topic:280"') !== -1 - ); + test("Reply as new topic", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click("button.share:eq(0)"); + await click(".reply-as-new-topic a"); + + assert.ok(exists(".d-editor-input"), "the composer input is visible"); + + assert.equal( + find(".d-editor-input").val().trim(), + `Continuing the discussion from [Internationalization / localization](${window.location.origin}/t/internationalization-localization/280):`, + "it fills composer with the ring string" + ); + assert.equal( + selectKit(".category-chooser").header().value(), + "2", + "it fills category selector with the right category" + ); + }); + + test("Reply as new message", async (assert) => { + await visit("/t/pm-for-testing/12"); + await click("button.share:eq(0)"); + await click(".reply-as-new-topic a"); + + assert.ok(exists(".d-editor-input"), "the composer input is visible"); + + assert.equal( + find(".d-editor-input").val().trim(), + `Continuing the discussion from [PM for testing](${window.location.origin}/t/pm-for-testing/12):`, + "it fills composer with the ring string" + ); + + const targets = find(".item span", ".composer-fields"); + + assert.equal( + $(targets[0]).text(), + "someguy", + "it fills up the composer with the right user to start the PM to" + ); + + assert.equal( + $(targets[1]).text(), + "test", + "it fills up the composer with the right user to start the PM to" + ); + + assert.equal( + $(targets[2]).text(), + "Group", + "it fills up the composer with the right group to start the PM to" + ); + }); + + test("Share Modal", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click(".topic-post:first-child button.share"); + + assert.ok(exists("#share-link"), "it shows the share modal"); + }); + + test("Showing and hiding the edit controls", async (assert) => { + await visit("/t/internationalization-localization/280"); + + await click("#topic-title .d-icon-pencil-alt"); + + assert.ok(exists("#edit-title"), "it shows the editing controls"); + assert.ok( + !exists(".title-wrapper .remove-featured-link"), + "link to remove featured link is not shown" + ); + + await fillIn("#edit-title", "this is the new title"); + await click("#topic-title .cancel-edit"); + assert.ok(!exists("#edit-title"), "it hides the editing controls"); + }); + + test("Updating the topic title and category", async (assert) => { + const categoryChooser = selectKit(".title-wrapper .category-chooser"); + + await visit("/t/internationalization-localization/280"); + + await click("#topic-title .d-icon-pencil-alt"); + await fillIn("#edit-title", "this is the new title"); + await categoryChooser.expand(); + await categoryChooser.selectRowByValue(4); + await click("#topic-title .submit-edit"); + + assert.equal( + find("#topic-title .badge-category").text(), + "faq", + "it displays the new category" + ); + assert.equal( + find(".fancy-title").text().trim(), + "this is the new title", + "it displays the new title" + ); + }); + + test("Marking a topic as wiki", async (assert) => { + await visit("/t/internationalization-localization/280"); + + assert.ok(find("a.wiki").length === 0, "it does not show the wiki icon"); + + await click(".topic-post:eq(0) button.show-more-actions"); + await click(".topic-post:eq(0) button.show-post-admin-menu"); + await click(".btn.wiki"); + + assert.ok(find("a.wiki").length === 1, "it shows the wiki icon"); + }); + + test("Visit topic routes", async (assert) => { + await visit("/t/12"); + + assert.equal( + find(".fancy-title").text().trim(), + "PM for testing", + "it routes to the right topic" + ); + + await visit("/t/280/20"); + + assert.equal( + find(".fancy-title").text().trim(), + "Internationalization / localization", + "it routes to the right topic" + ); + }); + + test("Updating the topic title with emojis", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click("#topic-title .d-icon-pencil-alt"); + + await fillIn("#edit-title", "emojis title :bike: :blonde_woman:t6:"); + + await click("#topic-title .submit-edit"); + + assert.equal( + find(".fancy-title").html().trim(), + `emojis title bike blonde_woman:t6`, + "it displays the new title with emojis" + ); + }); + + test("Updating the topic title with unicode emojis", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click("#topic-title .d-icon-pencil-alt"); + + await fillIn("#edit-title", "emojis title 👨‍🌾🙏"); + + await click("#topic-title .submit-edit"); + + assert.equal( + find(".fancy-title").html().trim(), + `emojis title man_farmerpray`, + "it displays the new title with escaped unicode emojis" + ); + }); + + test("Updating the topic title with unicode emojis without whitespaces", async function (assert) { + this.siteSettings.enable_inline_emoji_translation = true; + await visit("/t/internationalization-localization/280"); + await click("#topic-title .d-icon-pencil-alt"); + + await fillIn("#edit-title", "Test🙂Title"); + + await click("#topic-title .submit-edit"); + + assert.equal( + find(".fancy-title").html().trim(), + `Testslightly_smiling_faceTitle`, + "it displays the new title with escaped unicode emojis" + ); + }); + + test("Suggested topics", async (assert) => { + await visit("/t/internationalization-localization/280"); + + assert.equal( + find("#suggested-topics .suggested-topics-title").text().trim(), + I18n.t("suggested_topics.title") + ); + }); + + test("Group category moderator posts", async (assert) => { + await visit("/t/topic-for-group-moderators/2480"); + + assert.ok(exists(".category-moderator"), "it has a class applied"); + assert.ok(exists(".d-icon-shield-alt"), "it shows an icon"); + }); }); -test("Quoting a quote of a different topic keeps the original topic title", async (assert) => { - await visit("/t/internationalization-localization/280"); - selectText("#post_9 blockquote"); - await click(".quote-button .insert-quote"); +acceptance("Topic featured links", function (needs) { + needs.user(); + needs.settings({ + topic_featured_link_enabled: true, + max_topic_title_length: 80, + }); + test("remove featured link", async (assert) => { + await visit("/t/-/299/1"); + assert.ok( + exists(".title-wrapper .topic-featured-link"), + "link is shown with topic title" + ); - assert.ok( - find(".d-editor-input") - .val() - .indexOf( - 'quote="A new topic with a link to another topic, post:3, topic:62"' - ) !== -1 - ); + await click(".title-wrapper .edit-topic"); + assert.ok( + exists(".title-wrapper .remove-featured-link"), + "link to remove featured link" + ); + + await click(".title-wrapper .remove-featured-link"); + await click(".title-wrapper .submit-edit"); + assert.ok(!exists(".title-wrapper .topic-featured-link"), "link is gone"); + }); + + test("Converting to a public topic", async (assert) => { + await visit("/t/test-pm/34"); + assert.ok(exists(".private_message")); + await click(".toggle-admin-menu"); + await click(".topic-admin-convert button"); + + let categoryChooser = selectKit( + ".convert-to-public-topic .category-chooser" + ); + await categoryChooser.expand(); + await categoryChooser.selectRowByValue(21); + + await click(".convert-to-public-topic .btn-primary"); + assert.ok(!exists(".private_message")); + }); + + test("Unpinning unlisted topic", async (assert) => { + await visit("/t/internationalization-localization/280"); + + await click(".toggle-admin-menu"); + await click(".topic-admin-pin .btn"); + await click(".btn-primary:last"); + + await click(".toggle-admin-menu"); + await click(".topic-admin-visible .btn"); + + await click(".toggle-admin-menu"); + assert.ok( + exists(".topic-admin-pin"), + "it should show the multi select menu" + ); + }); + + test("selecting posts", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click(".toggle-admin-menu"); + await click(".topic-admin-multi-select .btn"); + + assert.ok( + exists(".selected-posts:not(.hidden)"), + "it should show the multi select menu" + ); + + assert.ok( + exists(".select-all"), + "it should allow users to select all the posts" + ); + }); + + test("select below", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click(".toggle-admin-menu"); + await click(".topic-admin-multi-select .btn"); + await click("#post_3 .select-below"); + + assert.ok( + find(".selected-posts") + .html() + .includes(I18n.t("topic.multi_select.description", { count: 18 })), + "it should select the right number of posts" + ); + + await click("#post_2 .select-below"); + + assert.ok( + find(".selected-posts") + .html() + .includes(I18n.t("topic.multi_select.description", { count: 19 })), + "it should select the right number of posts" + ); + }); + + test("View Hidden Replies", async (assert) => { + await visit("/t/internationalization-localization/280"); + await click(".gap"); + + assert.equal(find(".gap").length, 0, "it hides gap"); + }); + + test("Quoting a quote keeps the original poster name", async (assert) => { + await visit("/t/internationalization-localization/280"); + selectText("#post_5 blockquote"); + await click(".quote-button .insert-quote"); + + assert.ok( + find(".d-editor-input") + .val() + .indexOf('quote="codinghorror said, post:3, topic:280"') !== -1 + ); + }); + + test("Quoting a quote of a different topic keeps the original topic title", async (assert) => { + await visit("/t/internationalization-localization/280"); + selectText("#post_9 blockquote"); + await click(".quote-button .insert-quote"); + + assert.ok( + find(".d-editor-input") + .val() + .indexOf( + 'quote="A new topic with a link to another topic, post:3, topic:62"' + ) !== -1 + ); + }); + + test("Quoting a quote with the Reply button keeps the original poster name", async (assert) => { + await visit("/t/internationalization-localization/280"); + selectText("#post_5 blockquote"); + await click(".reply"); + + assert.ok( + find(".d-editor-input") + .val() + .indexOf('quote="codinghorror said, post:3, topic:280"') !== -1 + ); + }); + + test("Quoting a quote with replyAsNewTopic keeps the original poster name", async (assert) => { + await visit("/t/internationalization-localization/280"); + selectText("#post_5 blockquote"); + await keyEvent(document, "keypress", "j".charCodeAt(0)); + await keyEvent(document, "keypress", "t".charCodeAt(0)); + + assert.ok( + find(".d-editor-input") + .val() + .indexOf('quote="codinghorror said, post:3, topic:280"') !== -1 + ); + }); + + test("Quoting by selecting text can mark the quote as full", async (assert) => { + await visit("/t/internationalization-localization/280"); + selectText("#post_5 .cooked"); + await click(".quote-button .insert-quote"); + + assert.ok( + find(".d-editor-input") + .val() + .indexOf('quote="pekka, post:5, topic:280, full:true"') !== -1 + ); + }); }); -test("Quoting a quote with the Reply button keeps the original poster name", async (assert) => { - await visit("/t/internationalization-localization/280"); - selectText("#post_5 blockquote"); - await click(".reply"); - - assert.ok( - find(".d-editor-input") - .val() - .indexOf('quote="codinghorror said, post:3, topic:280"') !== -1 - ); -}); - -test("Quoting a quote with replyAsNewTopic keeps the original poster name", async (assert) => { - await visit("/t/internationalization-localization/280"); - selectText("#post_5 blockquote"); - await keyEvent(document, "keypress", "j".charCodeAt(0)); - await keyEvent(document, "keypress", "t".charCodeAt(0)); - - assert.ok( - find(".d-editor-input") - .val() - .indexOf('quote="codinghorror said, post:3, topic:280"') !== -1 - ); -}); - -test("Quoting by selecting text can mark the quote as full", async (assert) => { - await visit("/t/internationalization-localization/280"); - selectText("#post_5 .cooked"); - await click(".quote-button .insert-quote"); - - assert.ok( - find(".d-editor-input") - .val() - .indexOf('quote="pekka, post:5, topic:280, full:true"') !== -1 - ); -}); - -acceptance("Topic with title decorated", { - loggedIn: true, - beforeEach() { +acceptance("Topic with title decorated", function (needs) { + needs.user(); + needs.hooks.beforeEach(() => { withPluginApi("0.8.40", (api) => { api.decorateTopicTitle((topic, node, topicTitleType) => { node.innerText = `${node.innerText}-${topic.id}-${topicTitleType}`; }); }); - }, -}); - -test("Decorate topic title", async (assert) => { - await visit("/t/internationalization-localization/280"); - - assert.ok( - find(".fancy-title")[0].innerText.endsWith("-280-topic-title"), - "it decorates topic title" - ); - - assert.ok( - find(".raw-topic-link:nth-child(1)")[0].innerText.endsWith( - "-27331-topic-list-item-title" - ), - "it decorates topic list item title" - ); + }); + test("Decorate topic title", async (assert) => { + await visit("/t/internationalization-localization/280"); + + assert.ok( + find(".fancy-title")[0].innerText.endsWith("-280-topic-title"), + "it decorates topic title" + ); + + assert.ok( + find(".raw-topic-link:nth-child(1)")[0].innerText.endsWith( + "-27331-topic-list-item-title" + ), + "it decorates topic list item title" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/unknown-test.js b/app/assets/javascripts/discourse/tests/acceptance/unknown-test.js index 388c65dd080..06ea60e5c42 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/unknown-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/unknown-test.js @@ -1,51 +1,43 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -import pretender from "discourse/tests/helpers/create-pretender"; -acceptance("Unknown"); -test("Permalink Unknown URL", async (assert) => { - await visit("/url-that-doesn't-exist"); - assert.ok(exists(".page-not-found"), "The not found content is present"); -}); +acceptance("Unknown", function (needs) { + const urls = { + "viewtopic.php": "/t/internationalization-localization/280", + "not-the-url-for-faq": "/faq", + }; -test("Permalink URL to a Topic", async (assert) => { - pretender.get("/permalink-check.json", () => { - return [ - 200, - { "Content-Type": "application/json" }, - { - found: true, - internal: true, - target_url: "/t/internationalization-localization/280", - }, - ]; + needs.pretender((server, helper) => { + server.get("/permalink-check.json", (request) => { + let url = urls[request.queryParams.path]; + if (url) { + return helper.response({ + found: true, + internal: true, + target_url: url, + }); + } else { + return helper.response({ + found: false, + html: "
not found
", + }); + } + }); }); - await visit("/viewtopic.php?f=8&t=280"); - assert.ok(exists(".topic-post")); -}); - -test("Permalink URL to a static page", async (assert) => { - pretender.get("/permalink-check.json", () => { - return [ - 200, - { "Content-Type": "application/json" }, - { - found: true, - internal: true, - target_url: "/faq", - }, - ]; + test("Permalink Unknown URL", async (assert) => { + await visit("/url-that-doesn't-exist"); + assert.ok(exists(".page-not-found"), "The not found content is present"); }); - await visit("/not-the-url-for-faq"); + test("Permalink URL to a Topic", async (assert) => { + await visit("/viewtopic.php?f=8&t=280"); + assert.equal(currentURL(), "/t/internationalization-localization/280"); + }); - // body is outside of #ember-testing-container and needs to be targeted - // through document instead of find - assert.ok( - document.querySelector("body.static-faq"), - "routed to the faq page" - ); - assert.ok(exists(".body-page")); + test("Permalink URL to a static page", async (assert) => { + await visit("/not-the-url-for-faq"); + assert.equal(currentURL(), "/faq"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-anonymous-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-anonymous-test.js index 09d4642f000..1d2cfefd8f2 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/user-anonymous-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/user-anonymous-test.js @@ -1,50 +1,44 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("User Anonymous"); -function hasStream(assert) { - assert.ok(exists(".user-main .about"), "it has the about section"); - assert.ok(count(".user-stream .item") > 0, "it has stream items"); -} +acceptance("User Anonymous", function () { + test("Root URL", async (assert) => { + await visit("/u/eviltrout"); + assert.ok($("body.user-summary-page").length, "has the body class"); + assert.equal(currentPath(), "user.summary", "it defaults to summary"); + }); -function hasTopicList(assert) { - assert.equal(count(".user-stream .item"), 0, "has no stream displayed"); - assert.ok(count(".topic-list tr") > 0, "it has a topic list"); -} + test("Filters", async (assert) => { + await visit("/u/eviltrout/activity"); + assert.ok($("body.user-activity-page").length, "has the body class"); + assert.ok(exists(".user-main .about"), "it has the about section"); + assert.ok(count(".user-stream .item") > 0, "it has stream items"); -test("Root URL", async (assert) => { - await visit("/u/eviltrout"); - assert.ok($("body.user-summary-page").length, "has the body class"); - assert.equal(currentPath(), "user.summary", "it defaults to summary"); -}); - -test("Filters", async (assert) => { - await visit("/u/eviltrout/activity"); - assert.ok($("body.user-activity-page").length, "has the body class"); - hasStream(assert); - - await visit("/u/eviltrout/activity/topics"); - await hasTopicList(assert); - - await visit("/u/eviltrout/activity/replies"); - hasStream(assert); - - assert.ok(exists(".user-stream.filter-5"), "stream has filter class"); -}); - -test("Badges", async (assert) => { - await visit("/u/eviltrout/badges"); - assert.ok($("body.user-badges-page").length, "has the body class"); - assert.ok(exists(".user-badges-list .badge-card"), "shows a badge"); -}); - -test("Restricted Routes", async (assert) => { - await visit("/u/eviltrout/preferences"); - - assert.equal( - currentURL(), - "/u/eviltrout/activity", - "it redirects from preferences" - ); + await visit("/u/eviltrout/activity/topics"); + assert.equal(count(".user-stream .item"), 0, "has no stream displayed"); + assert.ok(count(".topic-list tr") > 0, "it has a topic list"); + + await visit("/u/eviltrout/activity/replies"); + assert.ok(exists(".user-main .about"), "it has the about section"); + assert.ok(count(".user-stream .item") > 0, "it has stream items"); + + assert.ok(exists(".user-stream.filter-5"), "stream has filter class"); + }); + + test("Badges", async (assert) => { + await visit("/u/eviltrout/badges"); + assert.ok($("body.user-badges-page").length, "has the body class"); + assert.ok(exists(".user-badges-list .badge-card"), "shows a badge"); + }); + + test("Restricted Routes", async (assert) => { + await visit("/u/eviltrout/preferences"); + + assert.equal( + currentURL(), + "/u/eviltrout/activity", + "it redirects from preferences" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-bookmarks-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-bookmarks-test.js index a923a6ba51c..fb3611bc750 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/user-bookmarks-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/user-bookmarks-test.js @@ -2,74 +2,67 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import selectKit from "discourse/tests/helpers/select-kit-helper"; -import pretender from "discourse/tests/helpers/create-pretender"; import userFixtures from "discourse/tests/fixtures/user-fixtures"; +import { deepMerge } from "discourse-common/lib/object"; -acceptance("User's bookmarks", { - loggedIn: true, +acceptance("User's bookmarks", function (needs) { + needs.user(); - beforeEach() { - pretender.delete("/bookmarks/576", () => [ - 200, - { "Content-Type": "application/json" }, + test("removing a bookmark with no reminder does not show a confirmation", async (assert) => { + await visit("/u/eviltrout/activity/bookmarks"); + assert.ok(find(".bookmark-list-item").length > 0); + + const dropdown = selectKit(".bookmark-actions-dropdown:eq(0)"); + await dropdown.expand(); + await dropdown.selectRowByValue("remove"); + + assert.not(exists(".bootbox.modal"), "it should not show the modal"); + }); +}); + +acceptance("User's bookmarks - reminder", function (needs) { + needs.user(); + + needs.pretender((server, helper) => { + let listResponse = deepMerge( {}, - ]); - }, + userFixtures["/u/eviltrout/bookmarks.json"] + ); + listResponse.user_bookmark_list.bookmarks[0].reminder_at = + "2028-01-01T08:00"; + + server.get("/u/eviltrout/bookmarks.json", () => + helper.response(listResponse) + ); + }); + + test("removing a bookmark with a reminder shows a confirmation", async (assert) => { + await visit("/u/eviltrout/activity/bookmarks"); + + const dropdown = selectKit(".bookmark-actions-dropdown"); + await dropdown.expand(); + await dropdown.selectRowByValue("remove"); + + assert.ok(exists(".bootbox.modal"), "it asks for delete confirmation"); + + await click(".bootbox.modal a.btn-primary"); + assert.not(exists(".bootbox.modal")); + }); }); -test("listing user bookmarks", async (assert) => { - await visit("/u/eviltrout/activity/bookmarks"); +acceptance("User's bookmarks - no bookmarks", function (needs) { + needs.user(); + needs.pretender((server, helper) => { + server.get("/u/eviltrout/bookmarks.json", () => + helper.response({ + bookmarks: [], + no_results_help: "no bookmarks", + }) + ); + }); - assert.ok(find(".bookmark-list-item").length); -}); - -test("removing a bookmark with a reminder shows a confirmation", async (assert) => { - let listResponse = Object.assign( - {}, - userFixtures["/u/eviltrout/bookmarks.json"] - ); - listResponse.user_bookmark_list.bookmarks[0].reminder_at = "2028-01-01T08:00"; - pretender.get("/u/eviltrout/bookmarks.json", () => [ - 200, - { "Content-Type": "application/json" }, - listResponse, - ]); - await visit("/u/eviltrout/activity/bookmarks"); - - const dropdown = selectKit(".bookmark-actions-dropdown"); - await dropdown.expand(); - await dropdown.selectRowByValue("remove"); - - assert.ok(exists(".bootbox.modal"), "it asks for delete confirmation"); - - await click(".bootbox.modal a.btn-primary"); - assert.not(exists(".bootbox.modal")); - listResponse.user_bookmark_list.bookmarks[0].reminder_at = null; -}); - -test("listing users bookmarks - no bookmarks", async (assert) => { - pretender.get("/u/eviltrout/bookmarks.json", () => [ - 200, - { - "Content-Type": "application/json", - }, - { - bookmarks: [], - no_results_help: "no bookmarks", - }, - ]); - - await visit("/u/eviltrout/activity/bookmarks"); - - assert.equal(find(".alert.alert-info").text(), "no bookmarks"); -}); - -test("removing a bookmark with no reminder does not show a confirmation", async (assert) => { - await visit("/u/eviltrout/activity/bookmarks"); - - const dropdown = selectKit(".bookmark-actions-dropdown"); - await dropdown.expand(); - await dropdown.selectRowByValue("remove"); - - assert.not(exists(".bootbox.modal"), "it should not show the modal"); + test("listing users bookmarks - no bookmarks", async (assert) => { + await visit("/u/eviltrout/activity/bookmarks"); + assert.equal(find(".alert.alert-info").text(), "no bookmarks"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-card-mobile-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-card-mobile-test.js deleted file mode 100644 index 4d5cdb8d02c..00000000000 --- a/app/assets/javascripts/discourse/tests/acceptance/user-card-mobile-test.js +++ /dev/null @@ -1,24 +0,0 @@ -import { visit } from "@ember/test-helpers"; -import { skip } from "qunit"; -import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -import DiscourseURL from "discourse/lib/url"; - -acceptance("User Card - Mobile", { mobileView: true }); - -skip("user card", async (assert) => { - await visit("/t/internationalization-localization/280"); - assert.ok( - invisible(".user-card"), - "mobile user card is invisible by default" - ); - - await click("a[data-user-card=eviltrout]:first"); - assert.ok(visible(".user-card"), "mobile user card should appear"); - - sandbox.stub(DiscourseURL, "routeTo"); - await click(".card-content a.user-profile-link"); - assert.ok( - DiscourseURL.routeTo.calledWith("/u/eviltrout"), - "it should navigate to the user profile" - ); -}); diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-card-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-card-test.js index c2a561a88c1..a263e391844 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/user-card-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/user-card-test.js @@ -1,137 +1,27 @@ import { visit } from "@ember/test-helpers"; -import { skip } from "qunit"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -import DiscourseURL from "discourse/lib/url"; - -import pretender from "discourse/tests/helpers/create-pretender"; import userFixtures from "discourse/tests/fixtures/user-fixtures"; import User from "discourse/models/user"; -acceptance("User Card - Show Local Time", { - loggedIn: true, - settings: { display_local_time_in_user_card: true }, -}); - -skip("user card local time", async (assert) => { - User.current().changeTimezone("Australia/Brisbane"); - let cardResponse = Object.assign({}, userFixtures["/u/eviltrout/card.json"]); - cardResponse.user.timezone = "Australia/Perth"; - - pretender.get("/u/eviltrout/card.json", () => [ - 200, - { "Content-Type": "application/json" }, - cardResponse, - ]); - - await visit("/t/internationalization-localization/280"); - assert.ok(invisible(".user-card"), "user card is invisible by default"); - await click("a[data-user-card=eviltrout]:first"); - - let expectedTime = moment - .tz("Australia/Brisbane") - .add(-2, "hours") - .format("h:mm a"); - - assert.ok(visible(".user-card"), "card should appear"); - assert.equal( - find(".user-card .local-time").text().trim(), - expectedTime, - "user card contains the user's local time" - ); - - cardResponse = Object.assign({}, userFixtures["/u/charlie/card.json"]); - cardResponse.user.timezone = "America/New_York"; - - pretender.get("/u/charlie/card.json", () => [ - 200, - { "Content-Type": "application/json" }, - cardResponse, - ]); - - await click("a[data-user-card=charlie]:first"); - - expectedTime = moment - .tz("Australia/Brisbane") - .add(-14, "hours") - .format("h:mm a"); - - assert.equal( - find(".user-card .local-time").text().trim(), - expectedTime, - "opening another user card updates the local time in the card (no caching)" - ); -}); - -test("user card local time - does not update timezone for another user", async (assert) => { - User.current().changeTimezone("Australia/Brisbane"); - let cardResponse = Object.assign({}, userFixtures["/u/charlie/card.json"]); - delete cardResponse.user.timezone; - - pretender.get("/u/charlie/card.json", () => [ - 200, - { "Content-Type": "application/json" }, - cardResponse, - ]); - - await visit("/t/internationalization-localization/280"); - await click("a[data-user-card=charlie]:first"); - - assert.not( - exists(".user-card .local-time"), - "it does not show the local time if the user card returns a null/undefined timezone for another user" - ); -}); - -acceptance("User Card", { loggedIn: true }); - -skip("user card", async (assert) => { - await visit("/t/internationalization-localization/280"); - assert.ok(invisible(".user-card"), "user card is invisible by default"); - - await click("a[data-user-card=eviltrout]:first"); - assert.ok(visible(".user-card"), "card should appear"); - assert.equal( - find(".user-card .username").text().trim(), - "eviltrout", - "user card contains the data" - ); - - sandbox.stub(DiscourseURL, "routeTo"); - await click(".card-content a.user-profile-link"); - assert.ok( - DiscourseURL.routeTo.calledWith("/u/eviltrout"), - "it should navigate to the user profile" - ); - - await click("a[data-user-card=charlie]:first"); - assert.ok(visible(".user-card"), "card should appear"); - assert.equal( - find(".user-card .username").text().trim(), - "charlie", - "user card contains the data" - ); - - assert.ok( - !visible(".user-card .local-time"), - "local time with zone does not show by default" - ); - - await click(".card-content .compose-pm button"); - assert.ok( - invisible(".user-card"), - "user card dismissed after hitting Message button" - ); - - const mention = find("a.mention"); - const icon = document.createElement("span"); - icon.classList.add("icon"); - mention.append(icon); - await click("a.mention .icon"); - assert.ok(visible(".user-card"), "card should appear"); - assert.equal( - find(".user-card .username").text().trim(), - "eviltrout", - "user card contains the data" - ); +acceptance("User Card - Show Local Time", function (needs) { + needs.user(); + needs.settings({ display_local_time_in_user_card: true }); + needs.pretender((server, helper) => { + let cardResponse = Object.assign({}, userFixtures["/u/charlie/card.json"]); + delete cardResponse.user.timezone; + server.get("/u/charlie/card.json", () => helper.response(cardResponse)); + }); + + test("user card local time - does not update timezone for another user", async (assert) => { + User.current().changeTimezone("Australia/Brisbane"); + + await visit("/t/internationalization-localization/280"); + await click("a[data-user-card=charlie]:first"); + + assert.not( + exists(".user-card .local-time"), + "it does not show the local time if the user card returns a null/undefined timezone for another user" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-drafts-stream-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-drafts-stream-test.js index 16a3d3e00e2..1f87496a64c 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/user-drafts-stream-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/user-drafts-stream-test.js @@ -2,26 +2,28 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("User Drafts", { loggedIn: true }); +acceptance("User Drafts", function (needs) { + needs.user(); -test("Stream", async (assert) => { - await visit("/u/eviltrout/activity/drafts"); - assert.ok(find(".user-stream-item").length === 3, "has drafts"); + test("Stream", async (assert) => { + await visit("/u/eviltrout/activity/drafts"); + assert.ok(find(".user-stream-item").length === 3, "has drafts"); - await click(".user-stream-item:last-child .remove-draft"); - assert.ok( - find(".user-stream-item").length === 2, - "draft removed, list length diminished by one" - ); -}); - -test("Stream - resume draft", async (assert) => { - await visit("/u/eviltrout/activity/drafts"); - assert.ok(find(".user-stream-item").length > 0, "has drafts"); - - await click(".user-stream-item .resume-draft"); - assert.equal( - find(".d-editor-input").val().trim(), - "A fun new topic for testing drafts." - ); + await click(".user-stream-item:last-child .remove-draft"); + assert.ok( + find(".user-stream-item").length === 2, + "draft removed, list length diminished by one" + ); + }); + + test("Stream - resume draft", async (assert) => { + await visit("/u/eviltrout/activity/drafts"); + assert.ok(find(".user-stream-item").length > 0, "has drafts"); + + await click(".user-stream-item .resume-draft"); + assert.equal( + find(".d-editor-input").val().trim(), + "A fun new topic for testing drafts." + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-interface-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-interface-test.js index 8d1adbcea94..09504b051b4 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-interface-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-interface-test.js @@ -6,194 +6,198 @@ import Site from "discourse/models/site"; import Session from "discourse/models/session"; import cookie, { removeCookie } from "discourse/lib/cookie"; -acceptance("User Preferences - Interface", { - loggedIn: true, -}); +acceptance("User Preferences - Interface", function (needs) { + needs.user(); -test("font size change", async (assert) => { - removeCookie("text_size"); + test("font size change", async (assert) => { + removeCookie("text_size"); - const savePreferences = async () => { - assert.ok(!exists(".saved"), "it hasn't been saved yet"); - await click(".save-changes"); - assert.ok(exists(".saved"), "it displays the saved message"); - find(".saved").remove(); - }; + const savePreferences = async () => { + assert.ok(!exists(".saved"), "it hasn't been saved yet"); + await click(".save-changes"); + assert.ok(exists(".saved"), "it displays the saved message"); + find(".saved").remove(); + }; - await visit("/u/eviltrout/preferences/interface"); + await visit("/u/eviltrout/preferences/interface"); - // Live changes without reload - await selectKit(".text-size .combobox").expand(); - await selectKit(".text-size .combobox").selectRowByValue("larger"); - assert.ok(document.documentElement.classList.contains("text-size-larger")); + // Live changes without reload + await selectKit(".text-size .combobox").expand(); + await selectKit(".text-size .combobox").selectRowByValue("larger"); + assert.ok(document.documentElement.classList.contains("text-size-larger")); - await selectKit(".text-size .combobox").expand(); - await selectKit(".text-size .combobox").selectRowByValue("largest"); - assert.ok(document.documentElement.classList.contains("text-size-largest")); + await selectKit(".text-size .combobox").expand(); + await selectKit(".text-size .combobox").selectRowByValue("largest"); + assert.ok(document.documentElement.classList.contains("text-size-largest")); - assert.equal(cookie("text_size"), null, "cookie is not set"); + assert.equal(cookie("text_size"), null, "cookie is not set"); - // Click save (by default this sets for all browsers, no cookie) - await savePreferences(); + // Click save (by default this sets for all browsers, no cookie) + await savePreferences(); - assert.equal(cookie("text_size"), null, "cookie is not set"); + assert.equal(cookie("text_size"), null, "cookie is not set"); - await selectKit(".text-size .combobox").expand(); - await selectKit(".text-size .combobox").selectRowByValue("larger"); - await click(".text-size input[type=checkbox]"); + await selectKit(".text-size .combobox").expand(); + await selectKit(".text-size .combobox").selectRowByValue("larger"); + await click(".text-size input[type=checkbox]"); - await savePreferences(); + await savePreferences(); - assert.equal(cookie("text_size"), "larger|1", "cookie is set"); - await click(".text-size input[type=checkbox]"); - await selectKit(".text-size .combobox").expand(); - await selectKit(".text-size .combobox").selectRowByValue("largest"); + assert.equal(cookie("text_size"), "larger|1", "cookie is set"); + await click(".text-size input[type=checkbox]"); + await selectKit(".text-size .combobox").expand(); + await selectKit(".text-size .combobox").selectRowByValue("largest"); - await savePreferences(); - assert.equal(cookie("text_size"), null, "cookie is removed"); + await savePreferences(); + assert.equal(cookie("text_size"), null, "cookie is removed"); - removeCookie("text_size"); -}); - -test("does not show option to disable dark mode by default", async (assert) => { - await visit("/u/eviltrout/preferences/interface"); - assert.equal($(".control-group.dark-mode").length, 0); -}); - -test("shows light/dark color scheme pickers", async (assert) => { - let site = Site.current(); - site.set("user_color_schemes", [ - { id: 2, name: "Cool Breeze" }, - { id: 3, name: "Dark Night", is_dark: true }, - ]); - - await visit("/u/eviltrout/preferences/interface"); - assert.ok($(".light-color-scheme").length, "has regular dropdown"); - assert.ok($(".dark-color-scheme").length, "has dark color scheme dropdown"); -}); - -function interfacePretender(server, helper) { - server.get("/color-scheme-stylesheet/2.json", () => { - return helper.response({ - success: "OK", - }); + removeCookie("text_size"); }); -} -acceptance("User Preferences Color Schemes (with default dark scheme)", { - loggedIn: true, - settings: { default_dark_mode_color_scheme_id: 1 }, - pretend: interfacePretender, + test("does not show option to disable dark mode by default", async (assert) => { + await visit("/u/eviltrout/preferences/interface"); + assert.equal($(".control-group.dark-mode").length, 0); + }); + + test("shows light/dark color scheme pickers", async (assert) => { + let site = Site.current(); + site.set("user_color_schemes", [ + { id: 2, name: "Cool Breeze" }, + { id: 3, name: "Dark Night", is_dark: true }, + ]); + + await visit("/u/eviltrout/preferences/interface"); + assert.ok($(".light-color-scheme").length, "has regular dropdown"); + assert.ok($(".dark-color-scheme").length, "has dark color scheme dropdown"); + }); }); -test("show option to disable dark mode", async (assert) => { - await visit("/u/eviltrout/preferences/interface"); +acceptance( + "User Preferences Color Schemes (with default dark scheme)", + function (needs) { + needs.user(); + needs.settings({ default_dark_mode_color_scheme_id: 1 }); + needs.pretender((server, helper) => { + server.get("/color-scheme-stylesheet/2.json", () => { + return helper.response({ + success: "OK", + }); + }); + }); - assert.ok( - $(".control-group.dark-mode").length, - "it has the option to disable dark mode" - ); -}); + test("show option to disable dark mode", async (assert) => { + await visit("/u/eviltrout/preferences/interface"); -test("no color scheme picker by default", async (assert) => { - let site = Site.current(); - site.set("user_color_schemes", []); + assert.ok( + $(".control-group.dark-mode").length, + "it has the option to disable dark mode" + ); + }); - await visit("/u/eviltrout/preferences/interface"); - assert.equal($(".control-group.color-scheme").length, 0); -}); + test("no color scheme picker by default", async (assert) => { + let site = Site.current(); + site.set("user_color_schemes", []); -test("light color scheme picker", async (assert) => { - let site = Site.current(); - site.set("user_color_schemes", [{ id: 2, name: "Cool Breeze" }]); + await visit("/u/eviltrout/preferences/interface"); + assert.equal($(".control-group.color-scheme").length, 0); + }); - await visit("/u/eviltrout/preferences/interface"); - assert.ok($(".light-color-scheme").length, "has regular picker dropdown"); - assert.equal( - $(".dark-color-scheme").length, - 0, - "does not have a dark color scheme picker" - ); -}); + test("light color scheme picker", async (assert) => { + let site = Site.current(); + site.set("user_color_schemes", [{ id: 2, name: "Cool Breeze" }]); -test("light and dark color scheme pickers", async (assert) => { - let site = Site.current(); - let session = Session.current(); - session.userDarkSchemeId = 1; // same as default set in site settings + await visit("/u/eviltrout/preferences/interface"); + assert.ok($(".light-color-scheme").length, "has regular picker dropdown"); + assert.equal( + $(".dark-color-scheme").length, + 0, + "does not have a dark color scheme picker" + ); + }); - site.set("default_dark_color_scheme", { id: 1, name: "Dark" }); - site.set("user_color_schemes", [ - { id: 2, name: "Cool Breeze" }, - { id: 3, name: "Dark Night", is_dark: true }, - ]); + test("light and dark color scheme pickers", async (assert) => { + let site = Site.current(); + let session = Session.current(); + session.userDarkSchemeId = 1; // same as default set in site settings - const savePreferences = async () => { - assert.ok(!exists(".saved"), "it hasn't been saved yet"); - await click(".save-changes"); - assert.ok(exists(".saved"), "it displays the saved message"); - find(".saved").remove(); - }; + site.set("default_dark_color_scheme", { id: 1, name: "Dark" }); + site.set("user_color_schemes", [ + { id: 2, name: "Cool Breeze" }, + { id: 3, name: "Dark Night", is_dark: true }, + ]); - await visit("/u/eviltrout/preferences/interface"); - assert.ok($(".light-color-scheme").length, "has regular dropdown"); - assert.ok($(".dark-color-scheme").length, "has dark color scheme dropdown"); - assert.equal( - $(".dark-color-scheme .selected-name").data("value"), - session.userDarkSchemeId, - "sets site default as selected dark scheme" - ); - assert.equal( - $(".control-group.dark-mode").length, - 0, - "it does not show disable dark mode checkbox" - ); + const savePreferences = async () => { + assert.ok(!exists(".saved"), "it hasn't been saved yet"); + await click(".save-changes"); + assert.ok(exists(".saved"), "it displays the saved message"); + find(".saved").remove(); + }; - removeCookie("color_scheme_id"); - removeCookie("dark_scheme_id"); + await visit("/u/eviltrout/preferences/interface"); + assert.ok($(".light-color-scheme").length, "has regular dropdown"); + assert.ok( + $(".dark-color-scheme").length, + "has dark color scheme dropdown" + ); + assert.equal( + $(".dark-color-scheme .selected-name").data("value"), + session.userDarkSchemeId, + "sets site default as selected dark scheme" + ); + assert.equal( + $(".control-group.dark-mode").length, + 0, + "it does not show disable dark mode checkbox" + ); - await selectKit(".light-color-scheme .combobox").expand(); - await selectKit(".light-color-scheme .combobox").selectRowByValue(2); - assert.equal(cookie("color_scheme_id"), null, "cookie is not set"); - assert.ok( - exists(".color-scheme-checkbox input:checked"), - "defaults to storing values in user options" - ); + removeCookie("color_scheme_id"); + removeCookie("dark_scheme_id"); - await savePreferences(); - assert.equal(cookie("color_scheme_id"), null, "cookie is unchanged"); + await selectKit(".light-color-scheme .combobox").expand(); + await selectKit(".light-color-scheme .combobox").selectRowByValue(2); + assert.equal(cookie("color_scheme_id"), null, "cookie is not set"); + assert.ok( + exists(".color-scheme-checkbox input:checked"), + "defaults to storing values in user options" + ); - // Switch to saving changes in cookies - await click(".color-scheme-checkbox input[type=checkbox]"); - await savePreferences(); - assert.equal(cookie("color_scheme_id"), 2, "cookie is set"); + await savePreferences(); + assert.equal(cookie("color_scheme_id"), null, "cookie is unchanged"); - // dark scheme - await selectKit(".dark-color-scheme .combobox").expand(); - assert.ok( - selectKit(".dark-color-scheme .combobox").rowByValue(1).exists(), - "default dark scheme is included" - ); + // Switch to saving changes in cookies + await click(".color-scheme-checkbox input[type=checkbox]"); + await savePreferences(); + assert.equal(cookie("color_scheme_id"), 2, "cookie is set"); - await selectKit(".dark-color-scheme .combobox").selectRowByValue(-1); - assert.equal( - cookie("dark_scheme_id"), - null, - "cookie is not set before saving" - ); + // dark scheme + await selectKit(".dark-color-scheme .combobox").expand(); + assert.ok( + selectKit(".dark-color-scheme .combobox").rowByValue(1).exists(), + "default dark scheme is included" + ); - await savePreferences(); - assert.equal(cookie("dark_scheme_id"), -1, "cookie is set"); + await selectKit(".dark-color-scheme .combobox").selectRowByValue(-1); + assert.equal( + cookie("dark_scheme_id"), + null, + "cookie is not set before saving" + ); - await click("button.undo-preview"); - assert.equal( - selectKit(".light-color-scheme .combobox").header().value(), - null, - "resets light scheme dropdown" - ); + await savePreferences(); + assert.equal(cookie("dark_scheme_id"), -1, "cookie is set"); - assert.equal( - selectKit(".dark-color-scheme .combobox").header().value(), - session.userDarkSchemeId, - "resets dark scheme dropdown" - ); -}); + await click("button.undo-preview"); + assert.equal( + selectKit(".light-color-scheme .combobox").header().value(), + null, + "resets light scheme dropdown" + ); + + assert.equal( + selectKit(".dark-color-scheme .combobox").header().value(), + session.userDarkSchemeId, + "resets dark scheme dropdown" + ); + }); + } +); diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-test.js index d42c8a88185..e4439d50846 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/user-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/user-test.js @@ -2,93 +2,88 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import pretender from "discourse/tests/helpers/create-pretender"; -import Draft from "discourse/models/draft"; -import { Promise } from "rsvp"; -acceptance("User", { loggedIn: true }); +acceptance("User Routes", function (needs) { + needs.user(); -test("Invalid usernames", async (assert) => { - pretender.get("/u/eviltrout%2F..%2F..%2F.json", () => { - return [400, { "Content-Type": "application/json" }, {}]; + test("Invalid usernames", async (assert) => { + pretender.get("/u/eviltrout%2F..%2F..%2F.json", () => { + return [400, { "Content-Type": "application/json" }, {}]; + }); + + await visit("/u/eviltrout%2F..%2F..%2F/summary"); + + assert.equal(currentPath(), "exception-unknown"); }); - await visit("/u/eviltrout%2F..%2F..%2F/summary"); + test("Unicode usernames", async (assert) => { + await visit("/u/%E3%83%A9%E3%82%A4%E3%82%AA%E3%83%B3/summary"); - assert.equal(currentPath(), "exception-unknown"); -}); - -test("Unicode usernames", async (assert) => { - await visit("/u/%E3%83%A9%E3%82%A4%E3%82%AA%E3%83%B3/summary"); - - assert.equal(currentPath(), "user.summary"); -}); - -test("Invites", async (assert) => { - await visit("/u/eviltrout/invited/pending"); - assert.ok($("body.user-invites-page").length, "has the body class"); -}); - -test("Messages", async (assert) => { - await visit("/u/eviltrout/messages"); - assert.ok($("body.user-messages-page").length, "has the body class"); -}); - -test("Notifications", async (assert) => { - await visit("/u/eviltrout/notifications"); - assert.ok($("body.user-notifications-page").length, "has the body class"); - - const $links = find(".item.notification a"); - - assert.ok( - $links[1].href.includes( - "/u/eviltrout/notifications/likes-received?acting_username=aquaman" - ) - ); -}); - -test("Root URL - Viewing Self", async (assert) => { - await visit("/u/eviltrout"); - assert.ok($("body.user-activity-page").length, "has the body class"); - assert.equal( - currentPath(), - "user.userActivity.index", - "it defaults to activity" - ); - assert.ok(exists(".container.viewing-self"), "has the viewing-self class"); -}); - -test("Viewing Summary", async (assert) => { - await visit("/u/eviltrout/summary"); - - assert.ok(exists(".replies-section li a"), "replies"); - assert.ok(exists(".topics-section li a"), "topics"); - assert.ok(exists(".links-section li a"), "links"); - assert.ok(exists(".replied-section .user-info"), "liked by"); - assert.ok(exists(".liked-by-section .user-info"), "liked by"); - assert.ok(exists(".liked-section .user-info"), "liked"); - assert.ok(exists(".badges-section .badge-card"), "badges"); - assert.ok(exists(".top-categories-section .category-link"), "top categories"); -}); - -test("Viewing Drafts", async (assert) => { - sandbox.stub(Draft, "get").returns( - Promise.resolve({ - draft: null, - draft_sequence: 0, - }) - ); - - await visit("/u/eviltrout/activity/drafts"); - assert.ok(exists(".user-stream"), "has drafts stream"); - assert.ok( - exists(".user-stream .user-stream-item-draft-actions"), - "has draft action buttons" - ); - - await click(".user-stream button.resume-draft:eq(0)"); - assert.ok( - exists(".d-editor-input"), - "composer is visible after resuming a draft" - ); - sandbox.restore(); + assert.equal(currentPath(), "user.summary"); + }); + + test("Invites", async (assert) => { + await visit("/u/eviltrout/invited/pending"); + assert.ok($("body.user-invites-page").length, "has the body class"); + }); + + test("Messages", async (assert) => { + await visit("/u/eviltrout/messages"); + assert.ok($("body.user-messages-page").length, "has the body class"); + }); + + test("Notifications", async (assert) => { + await visit("/u/eviltrout/notifications"); + assert.ok($("body.user-notifications-page").length, "has the body class"); + + const $links = find(".item.notification a"); + + assert.ok( + $links[1].href.includes( + "/u/eviltrout/notifications/likes-received?acting_username=aquaman" + ) + ); + }); + + test("Root URL - Viewing Self", async (assert) => { + await visit("/u/eviltrout"); + assert.ok($("body.user-activity-page").length, "has the body class"); + assert.equal( + currentPath(), + "user.userActivity.index", + "it defaults to activity" + ); + assert.ok(exists(".container.viewing-self"), "has the viewing-self class"); + }); + + test("Viewing Summary", async (assert) => { + await visit("/u/eviltrout/summary"); + + assert.ok(exists(".replies-section li a"), "replies"); + assert.ok(exists(".topics-section li a"), "topics"); + assert.ok(exists(".links-section li a"), "links"); + assert.ok(exists(".replied-section .user-info"), "liked by"); + assert.ok(exists(".liked-by-section .user-info"), "liked by"); + assert.ok(exists(".liked-section .user-info"), "liked"); + assert.ok(exists(".badges-section .badge-card"), "badges"); + assert.ok( + exists(".top-categories-section .category-link"), + "top categories" + ); + }); + + test("Viewing Drafts", async (assert) => { + await visit("/u/eviltrout/activity/drafts"); + assert.ok(exists(".user-stream"), "has drafts stream"); + assert.ok( + exists(".user-stream .user-stream-item-draft-actions"), + "has draft action buttons" + ); + + await click(".user-stream button.resume-draft:eq(0)"); + assert.ok( + exists(".d-editor-input"), + "composer is visible after resuming a draft" + ); + }); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/users-test.js b/app/assets/javascripts/discourse/tests/acceptance/users-test.js index 02f8f9f5560..845da300f08 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/users-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/users-test.js @@ -2,27 +2,27 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("User Directory"); +acceptance("User Directory", function () { + test("Visit Page", async (assert) => { + await visit("/u"); + assert.ok($("body.users-page").length, "has the body class"); + assert.ok(exists(".directory table tr"), "has a list of users"); + }); -test("Visit Page", async (assert) => { - await visit("/u"); - assert.ok($("body.users-page").length, "has the body class"); - assert.ok(exists(".directory table tr"), "has a list of users"); -}); + test("Visit All Time", async (assert) => { + await visit("/u?period=all"); + assert.ok(exists(".time-read"), "has time read column"); + }); -test("Visit All Time", async (assert) => { - await visit("/u?period=all"); - assert.ok(exists(".time-read"), "has time read column"); -}); + test("Visit Without Usernames", async (assert) => { + await visit("/u?exclude_usernames=system"); + assert.ok($("body.users-page").length, "has the body class"); + assert.ok(exists(".directory table tr"), "has a list of users"); + }); -test("Visit Without Usernames", async (assert) => { - await visit("/u?exclude_usernames=system"); - assert.ok($("body.users-page").length, "has the body class"); - assert.ok(exists(".directory table tr"), "has a list of users"); -}); - -test("Visit With Group Filter", async (assert) => { - await visit("/u?group=trust_level_0"); - assert.ok($("body.users-page").length, "has the body class"); - assert.ok(exists(".directory table tr"), "has a list of users"); + test("Visit With Group Filter", async (assert) => { + await visit("/u?group=trust_level_0"); + assert.ok($("body.users-page").length, "has the body class"); + assert.ok(exists(".directory table tr"), "has a list of users"); + }); }); diff --git a/app/assets/javascripts/discourse/tests/helpers/create-pretender.js b/app/assets/javascripts/discourse/tests/helpers/create-pretender.js index 5bc446fd597..4ac5e00795e 100644 --- a/app/assets/javascripts/discourse/tests/helpers/create-pretender.js +++ b/app/assets/javascripts/discourse/tests/helpers/create-pretender.js @@ -129,6 +129,8 @@ export function applyDefaultHandlers(pretender) { ]; }); + pretender.delete("/bookmarks/:id", () => response({})); + pretender.get("/tags/filter/search", () => { return response({ results: [{ text: "monkey", count: 1 }] }); }); @@ -279,12 +281,7 @@ export function applyDefaultHandlers(pretender) { pretender.put("/t/:id/recover", success); pretender.put("/t/:id/publish", success); - pretender.get("/permalink-check.json", () => { - return response({ - found: false, - html: "
not found
", - }); - }); + pretender.get("/permalink-check.json", () => response({ found: false })); pretender.delete("/draft.json", success); pretender.post("/draft.json", success); diff --git a/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js b/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js index d1258fd712a..849518f1350 100644 --- a/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js +++ b/app/assets/javascripts/discourse/tests/helpers/qunit-helpers.js @@ -146,6 +146,11 @@ export function discourseModule(name, hooks) { export function addPretenderCallback(name, fn) { if (name && fn) { + if (_pretenderCallbacks[name]) { + // eslint-disable-next-line no-console + throw `There is already a pretender callback with module name (${name}).`; + } + _pretenderCallbacks[name] = fn; } } @@ -159,7 +164,7 @@ export function acceptance(name, optionsOrCallback) { callback = optionsOrCallback; } else if (typeof optionsOrCallback === "object") { deprecated( - "The second parameter to `acceptance` should be a function that encloses your tests.", + `${name}: The second parameter to \`acceptance\` should be a function that encloses your tests.`, { since: "2.6.0" } ); options = optionsOrCallback; @@ -168,6 +173,7 @@ export function acceptance(name, optionsOrCallback) { addPretenderCallback(name, options.pretend); let loggedIn = false; + let mobileView = false; let siteChanges; let settingChanges; let userChanges; @@ -180,7 +186,7 @@ export function acceptance(name, optionsOrCallback) { HeaderComponent.reopen({ examineDockHeader: function () {} }); resetExtraClasses(); - if (options.mobileView) { + if (mobileView) { forceMobile(); } @@ -266,6 +272,9 @@ export function acceptance(name, optionsOrCallback) { settings(changes) { settingChanges = changes; }, + mobileView() { + mobileView = true; + }, }; if (options.loggedIn) { @@ -277,6 +286,9 @@ export function acceptance(name, optionsOrCallback) { if (options.settings) { needs.settings(options.settings); } + if (options.mobileView) { + needs.mobileView(); + } if (callback) { // New, preferred way diff --git a/app/assets/javascripts/discourse/tests/setup-tests.js b/app/assets/javascripts/discourse/tests/setup-tests.js index 2e001d12810..e4dad15a604 100644 --- a/app/assets/javascripts/discourse/tests/setup-tests.js +++ b/app/assets/javascripts/discourse/tests/setup-tests.js @@ -71,8 +71,8 @@ export default function setupTests(app, container) { QUnit.testStart(function (ctx) { let settings = resetSettings(); server = createPretender; - applyDefaultHandlers(server); server.handlers = []; + applyDefaultHandlers(server); server.prepareBody = function (body) { if (body && typeof body === "object") { diff --git a/plugins/discourse-details/test/javascripts/acceptance/details-button-test.js.es6 b/plugins/discourse-details/test/javascripts/acceptance/details-button-test.js.es6 index 48a14e8a41f..a69bb764187 100644 --- a/plugins/discourse-details/test/javascripts/acceptance/details-button-test.js.es6 +++ b/plugins/discourse-details/test/javascripts/acceptance/details-button-test.js.es6 @@ -3,133 +3,131 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import { clearPopupMenuOptionsCallback } from "discourse/controllers/composer"; import selectKit from "discourse/tests/helpers/select-kit-helper"; -acceptance("Details Button", { - loggedIn: true, - beforeEach: function () { - clearPopupMenuOptionsCallback(); - }, -}); - -test("details button", async (assert) => { - const popupMenu = selectKit(".toolbar-popup-menu-options"); - - await visit("/"); - await click("#create-topic"); - - await popupMenu.expand(); - await popupMenu.selectRowByValue("insertDetails"); - - assert.equal( - find(".d-editor-input").val(), - `\n[details="${I18n.t("composer.details_title")}"]\n${I18n.t( - "composer.details_text" - )}\n[/details]\n`, - "it should contain the right output" - ); - - await fillIn(".d-editor-input", "This is my title"); - - const textarea = find(".d-editor-input")[0]; - textarea.selectionStart = 0; - textarea.selectionEnd = textarea.value.length; - - await popupMenu.expand(); - await popupMenu.selectRowByValue("insertDetails"); - - assert.equal( - find(".d-editor-input").val(), - `\n[details="${I18n.t( - "composer.details_title" - )}"]\nThis is my title\n[/details]\n`, - "it should contain the right selected output" - ); - - assert.equal( - textarea.selectionStart, - 21, - "it should start highlighting at the right position" - ); - assert.equal( - textarea.selectionEnd, - 37, - "it should end highlighting at the right position" - ); - - await fillIn(".d-editor-input", "Before some text in between After"); - - textarea.selectionStart = 7; - textarea.selectionEnd = 28; - - await popupMenu.expand(); - await popupMenu.selectRowByValue("insertDetails"); - - assert.equal( - find(".d-editor-input").val(), - `Before \n[details="${I18n.t( - "composer.details_title" - )}"]\nsome text in between\n[/details]\n After`, - "it should contain the right output" - ); - - assert.equal( - textarea.selectionStart, - 28, - "it should start highlighting at the right position" - ); - assert.equal( - textarea.selectionEnd, - 48, - "it should end highlighting at the right position" - ); - - await fillIn(".d-editor-input", "Before \nsome text in between\n After"); - - textarea.selectionStart = 8; - textarea.selectionEnd = 29; - - await popupMenu.expand(); - await popupMenu.selectRowByValue("insertDetails"); - - assert.equal( - find(".d-editor-input").val(), - `Before \n\n[details="${I18n.t( - "composer.details_title" - )}"]\nsome text in between\n[/details]\n\n After`, - "it should contain the right output" - ); - - assert.equal( - textarea.selectionStart, - 29, - "it should start highlighting at the right position" - ); - assert.equal( - textarea.selectionEnd, - 49, - "it should end highlighting at the right position" - ); -}); - -test("details button surrounds all selected text in a single details block", async (assert) => { - const multilineInput = "first line\n\nsecond line\n\nthird line"; - const popupMenu = selectKit(".toolbar-popup-menu-options"); - - await visit("/"); - await click("#create-topic"); - await fillIn(".d-editor-input", multilineInput); - - const textarea = find(".d-editor-input")[0]; - textarea.selectionStart = 0; - textarea.selectionEnd = textarea.value.length; - - await popupMenu.expand(); - await popupMenu.selectRowByValue("insertDetails"); - - assert.equal( - find(".d-editor-input").val(), - `\n[details="${I18n.t( - "composer.details_title" - )}"]\n${multilineInput}\n[/details]\n`, - "it should contain the right output" - ); +acceptance("Details Button", function (needs) { + needs.user(); + needs.hooks.beforeEach(() => clearPopupMenuOptionsCallback()); + + test("details button", async (assert) => { + const popupMenu = selectKit(".toolbar-popup-menu-options"); + + await visit("/"); + await click("#create-topic"); + + await popupMenu.expand(); + await popupMenu.selectRowByValue("insertDetails"); + + assert.equal( + find(".d-editor-input").val(), + `\n[details="${I18n.t("composer.details_title")}"]\n${I18n.t( + "composer.details_text" + )}\n[/details]\n`, + "it should contain the right output" + ); + + await fillIn(".d-editor-input", "This is my title"); + + const textarea = find(".d-editor-input")[0]; + textarea.selectionStart = 0; + textarea.selectionEnd = textarea.value.length; + + await popupMenu.expand(); + await popupMenu.selectRowByValue("insertDetails"); + + assert.equal( + find(".d-editor-input").val(), + `\n[details="${I18n.t( + "composer.details_title" + )}"]\nThis is my title\n[/details]\n`, + "it should contain the right selected output" + ); + + assert.equal( + textarea.selectionStart, + 21, + "it should start highlighting at the right position" + ); + assert.equal( + textarea.selectionEnd, + 37, + "it should end highlighting at the right position" + ); + + await fillIn(".d-editor-input", "Before some text in between After"); + + textarea.selectionStart = 7; + textarea.selectionEnd = 28; + + await popupMenu.expand(); + await popupMenu.selectRowByValue("insertDetails"); + + assert.equal( + find(".d-editor-input").val(), + `Before \n[details="${I18n.t( + "composer.details_title" + )}"]\nsome text in between\n[/details]\n After`, + "it should contain the right output" + ); + + assert.equal( + textarea.selectionStart, + 28, + "it should start highlighting at the right position" + ); + assert.equal( + textarea.selectionEnd, + 48, + "it should end highlighting at the right position" + ); + + await fillIn(".d-editor-input", "Before \nsome text in between\n After"); + + textarea.selectionStart = 8; + textarea.selectionEnd = 29; + + await popupMenu.expand(); + await popupMenu.selectRowByValue("insertDetails"); + + assert.equal( + find(".d-editor-input").val(), + `Before \n\n[details="${I18n.t( + "composer.details_title" + )}"]\nsome text in between\n[/details]\n\n After`, + "it should contain the right output" + ); + + assert.equal( + textarea.selectionStart, + 29, + "it should start highlighting at the right position" + ); + assert.equal( + textarea.selectionEnd, + 49, + "it should end highlighting at the right position" + ); + }); + + test("details button surrounds all selected text in a single details block", async (assert) => { + const multilineInput = "first line\n\nsecond line\n\nthird line"; + const popupMenu = selectKit(".toolbar-popup-menu-options"); + + await visit("/"); + await click("#create-topic"); + await fillIn(".d-editor-input", multilineInput); + + const textarea = find(".d-editor-input")[0]; + textarea.selectionStart = 0; + textarea.selectionEnd = textarea.value.length; + + await popupMenu.expand(); + await popupMenu.selectRowByValue("insertDetails"); + + assert.equal( + find(".d-editor-input").val(), + `\n[details="${I18n.t( + "composer.details_title" + )}"]\n${multilineInput}\n[/details]\n`, + "it should contain the right output" + ); + }); }); diff --git a/plugins/discourse-local-dates/test/javascripts/acceptance/local-dates-composer-test.js.es6 b/plugins/discourse-local-dates/test/javascripts/acceptance/local-dates-composer-test.js.es6 index dfb3298e9e5..2101c00a2c6 100644 --- a/plugins/discourse-local-dates/test/javascripts/acceptance/local-dates-composer-test.js.es6 +++ b/plugins/discourse-local-dates/test/javascripts/acceptance/local-dates-composer-test.js.es6 @@ -1,50 +1,54 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Local Dates - composer", { - loggedIn: true, - settings: { discourse_local_dates_enabled: true }, -}); +acceptance("Local Dates - composer", function (needs) { + needs.user(); + needs.settings({ discourse_local_dates_enabled: true }); -test("composer bbcode", async (assert) => { - const getAttr = (attr) => { - return find(".d-editor-preview .discourse-local-date.cooked-date").attr( - `data-${attr}` + test("composer bbcode", async (assert) => { + const getAttr = (attr) => { + return find(".d-editor-preview .discourse-local-date.cooked-date").attr( + `data-${attr}` + ); + }; + + await visit("/"); + await click("#create-topic"); + + await fillIn( + ".d-editor-input", + '[date=2017-10-23 time=01:30:00 displayedTimezone="America/Chicago" format="LLLL" calendar="off" recurring="1.weeks" timezone="Asia/Calcutta" timezones="Europe/Paris|America/Los_Angeles"]' ); - }; - await visit("/"); - await click("#create-topic"); + assert.equal(getAttr("date"), "2017-10-23", "it has the correct date"); + assert.equal(getAttr("time"), "01:30:00", "it has the correct time"); + assert.equal( + getAttr("displayed-timezone"), + "America/Chicago", + "it has the correct displayed timezone" + ); + assert.equal(getAttr("format"), "LLLL", "it has the correct format"); + assert.equal( + getAttr("timezones"), + "Europe/Paris|America/Los_Angeles", + "it has the correct timezones" + ); + assert.equal( + getAttr("recurring"), + "1.weeks", + "it has the correct recurring" + ); + assert.equal( + getAttr("timezone"), + "Asia/Calcutta", + "it has the correct timezone" + ); - await fillIn( - ".d-editor-input", - '[date=2017-10-23 time=01:30:00 displayedTimezone="America/Chicago" format="LLLL" calendar="off" recurring="1.weeks" timezone="Asia/Calcutta" timezones="Europe/Paris|America/Los_Angeles"]' - ); + await fillIn( + ".d-editor-input", + '[date=2017-10-24 format="LL" timezone="Asia/Calcutta" timezones="Europe/Paris|America/Los_Angeles"]' + ); - assert.equal(getAttr("date"), "2017-10-23", "it has the correct date"); - assert.equal(getAttr("time"), "01:30:00", "it has the correct time"); - assert.equal( - getAttr("displayed-timezone"), - "America/Chicago", - "it has the correct displayed timezone" - ); - assert.equal(getAttr("format"), "LLLL", "it has the correct format"); - assert.equal( - getAttr("timezones"), - "Europe/Paris|America/Los_Angeles", - "it has the correct timezones" - ); - assert.equal(getAttr("recurring"), "1.weeks", "it has the correct recurring"); - assert.equal( - getAttr("timezone"), - "Asia/Calcutta", - "it has the correct timezone" - ); - - await fillIn( - ".d-editor-input", - '[date=2017-10-24 format="LL" timezone="Asia/Calcutta" timezones="Europe/Paris|America/Los_Angeles"]' - ); - - assert.equal(getAttr("date"), "2017-10-24", "it has the correct date"); - assert.notOk(getAttr("time"), "it doesn’t have time"); + assert.equal(getAttr("date"), "2017-10-24", "it has the correct date"); + assert.notOk(getAttr("time"), "it doesn’t have time"); + }); }); diff --git a/plugins/poll/test/javascripts/acceptance/poll-breakdown-test.js.es6 b/plugins/poll/test/javascripts/acceptance/poll-breakdown-test.js.es6 index 521805ce2e8..c2d3edb385e 100644 --- a/plugins/poll/test/javascripts/acceptance/poll-breakdown-test.js.es6 +++ b/plugins/poll/test/javascripts/acceptance/poll-breakdown-test.js.es6 @@ -1,119 +1,115 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import { clearPopupMenuOptionsCallback } from "discourse/controllers/composer"; -import { Promise } from "rsvp"; -acceptance("Poll breakdown", { - loggedIn: true, - settings: { poll_enabled: true, poll_groupable_user_fields: "something" }, - beforeEach() { - clearPopupMenuOptionsCallback(); - }, - pretend(server, helper) { - server.get("/polls/grouped_poll_results.json", () => { - return new Promise((resolve) => { - resolve( - helper.response({ - grouped_results: [ +acceptance("Poll breakdown", function (needs) { + needs.user(); + needs.settings({ + poll_enabled: true, + poll_groupable_user_fields: "something", + }); + needs.hooks.beforeEach(() => clearPopupMenuOptionsCallback()); + needs.pretender((server, helper) => { + server.get("/polls/grouped_poll_results.json", () => + helper.response({ + grouped_results: [ + { + group: "Engineering", + options: [ { - group: "Engineering", - options: [ - { - digest: "687a1ccf3c6a260f9aeeb7f68a1d463c", - html: "This Is", - votes: 1, - }, - { - digest: "9377906763a1221d31d656ea0c4a4495", - html: "A test for sure", - votes: 1, - }, - { - digest: "ecf47c65a85a0bb20029072b1b721977", - html: "Why not give it some more", - votes: 1, - }, - ], + digest: "687a1ccf3c6a260f9aeeb7f68a1d463c", + html: "This Is", + votes: 1, }, { - group: "Marketing", - options: [ - { - digest: "687a1ccf3c6a260f9aeeb7f68a1d463c", - html: "This Is", - votes: 1, - }, - { - digest: "9377906763a1221d31d656ea0c4a4495", - html: "A test for sure", - votes: 1, - }, - { - digest: "ecf47c65a85a0bb20029072b1b721977", - html: "Why not give it some more", - votes: 1, - }, - ], + digest: "9377906763a1221d31d656ea0c4a4495", + html: "A test for sure", + votes: 1, + }, + { + digest: "ecf47c65a85a0bb20029072b1b721977", + html: "Why not give it some more", + votes: 1, }, ], - }) - ); - }); - }); - }, -}); - -test("Displaying the poll breakdown modal", async (assert) => { - await visit("/t/-/topic_with_pie_chart_poll"); - - assert.equal( - find(".poll-show-breakdown").text(), - "Show breakdown", - "shows the breakdown button when poll_groupable_user_fields is non-empty" - ); - - await click(".poll-show-breakdown:first"); - - assert.equal( - find(".poll-breakdown-total-votes")[0].textContent.trim(), - "2 votes", - "display the correct total vote count" - ); - - assert.equal( - find(".poll-breakdown-chart-container").length, - 2, - "renders a chart for each of the groups in group_results response" - ); - - assert.ok( - find(".poll-breakdown-chart-container > canvas")[0].$chartjs, - "$chartjs is defined on the pie charts" - ); -}); - -test("Changing the display mode from percentage to count", async (assert) => { - await visit("/t/-/topic_with_pie_chart_poll"); - await click(".poll-show-breakdown:first"); - - assert.equal( - find(".poll-breakdown-option-count:first")[0].textContent.trim(), - "40.0%", - "displays the correct vote percentage" - ); - - await click(".modal-tabs .count"); - - assert.equal( - find(".poll-breakdown-option-count:first")[0].textContent.trim(), - "2", - "displays the correct vote count" - ); - - await click(".modal-tabs .percentage"); - - assert.equal( - find(".poll-breakdown-option-count:last")[0].textContent.trim(), - "20.0%", - "displays the percentage again" - ); + }, + { + group: "Marketing", + options: [ + { + digest: "687a1ccf3c6a260f9aeeb7f68a1d463c", + html: "This Is", + votes: 1, + }, + { + digest: "9377906763a1221d31d656ea0c4a4495", + html: "A test for sure", + votes: 1, + }, + { + digest: "ecf47c65a85a0bb20029072b1b721977", + html: "Why not give it some more", + votes: 1, + }, + ], + }, + ], + }) + ); + }); + + test("Displaying the poll breakdown modal", async (assert) => { + await visit("/t/-/topic_with_pie_chart_poll"); + + assert.equal( + find(".poll-show-breakdown").text(), + "Show breakdown", + "shows the breakdown button when poll_groupable_user_fields is non-empty" + ); + + await click(".poll-show-breakdown:first"); + + assert.equal( + find(".poll-breakdown-total-votes")[0].textContent.trim(), + "2 votes", + "display the correct total vote count" + ); + + assert.equal( + find(".poll-breakdown-chart-container").length, + 2, + "renders a chart for each of the groups in group_results response" + ); + + assert.ok( + find(".poll-breakdown-chart-container > canvas")[0].$chartjs, + "$chartjs is defined on the pie charts" + ); + }); + + test("Changing the display mode from percentage to count", async (assert) => { + await visit("/t/-/topic_with_pie_chart_poll"); + await click(".poll-show-breakdown:first"); + + assert.equal( + find(".poll-breakdown-option-count:first")[0].textContent.trim(), + "40.0%", + "displays the correct vote percentage" + ); + + await click(".modal-tabs .count"); + + assert.equal( + find(".poll-breakdown-option-count:first")[0].textContent.trim(), + "2", + "displays the correct vote count" + ); + + await click(".modal-tabs .percentage"); + + assert.equal( + find(".poll-breakdown-option-count:last")[0].textContent.trim(), + "20.0%", + "displays the percentage again" + ); + }); }); diff --git a/plugins/poll/test/javascripts/acceptance/poll-builder-disabled-test.js.es6 b/plugins/poll/test/javascripts/acceptance/poll-builder-disabled-test.js.es6 index f91c492dbfa..a2be400d0c9 100644 --- a/plugins/poll/test/javascripts/acceptance/poll-builder-disabled-test.js.es6 +++ b/plugins/poll/test/javascripts/acceptance/poll-builder-disabled-test.js.es6 @@ -1,47 +1,48 @@ -import { acceptance, updateCurrentUser } from "discourse/tests/helpers/qunit-helpers"; +import { + acceptance, + updateCurrentUser, +} from "discourse/tests/helpers/qunit-helpers"; import { displayPollBuilderButton } from "discourse/plugins/poll/helpers/display-poll-builder-button"; import { clearPopupMenuOptionsCallback } from "discourse/controllers/composer"; -acceptance("Poll Builder - polls are disabled", { - loggedIn: true, - settings: { +acceptance("Poll Builder - polls are disabled", function (needs) { + needs.user(); + needs.settings({ poll_enabled: false, poll_minimum_trust_level_to_create: 2, - }, - beforeEach: function () { - clearPopupMenuOptionsCallback(); - }, -}); - -test("regular user - sufficient trust level", async (assert) => { - updateCurrentUser({ moderator: false, admin: false, trust_level: 3 }); - - await displayPollBuilderButton(); - - assert.ok( - !exists(".select-kit-row[title='Build Poll']"), - "it hides the builder button" - ); -}); - -test("regular user - insufficient trust level", async (assert) => { - updateCurrentUser({ moderator: false, admin: false, trust_level: 1 }); - - await displayPollBuilderButton(); - - assert.ok( - !exists(".select-kit-row[title='Build Poll']"), - "it hides the builder button" - ); -}); - -test("staff", async (assert) => { - updateCurrentUser({ moderator: true }); - - await displayPollBuilderButton(); - - assert.ok( - !exists(".select-kit-row[title='Build Poll']"), - "it hides the builder button" - ); + }); + needs.hooks.beforeEach(() => clearPopupMenuOptionsCallback()); + + test("regular user - sufficient trust level", async (assert) => { + updateCurrentUser({ moderator: false, admin: false, trust_level: 3 }); + + await displayPollBuilderButton(); + + assert.ok( + !exists(".select-kit-row[title='Build Poll']"), + "it hides the builder button" + ); + }); + + test("regular user - insufficient trust level", async (assert) => { + updateCurrentUser({ moderator: false, admin: false, trust_level: 1 }); + + await displayPollBuilderButton(); + + assert.ok( + !exists(".select-kit-row[title='Build Poll']"), + "it hides the builder button" + ); + }); + + test("staff", async (assert) => { + updateCurrentUser({ moderator: true }); + + await displayPollBuilderButton(); + + assert.ok( + !exists(".select-kit-row[title='Build Poll']"), + "it hides the builder button" + ); + }); }); diff --git a/plugins/poll/test/javascripts/acceptance/poll-builder-enabled-test.js.es6 b/plugins/poll/test/javascripts/acceptance/poll-builder-enabled-test.js.es6 index ea632322054..4e4025dd42c 100644 --- a/plugins/poll/test/javascripts/acceptance/poll-builder-enabled-test.js.es6 +++ b/plugins/poll/test/javascripts/acceptance/poll-builder-enabled-test.js.es6 @@ -1,60 +1,67 @@ import selectKit from "discourse/tests/helpers/select-kit-helper"; -import { acceptance, updateCurrentUser } from "discourse/tests/helpers/qunit-helpers"; +import { + acceptance, + updateCurrentUser, +} from "discourse/tests/helpers/qunit-helpers"; import { displayPollBuilderButton } from "discourse/plugins/poll/helpers/display-poll-builder-button"; import { clearPopupMenuOptionsCallback } from "discourse/controllers/composer"; -acceptance("Poll Builder - polls are enabled", { - loggedIn: true, - settings: { +acceptance("Poll Builder - polls are enabled", function (needs) { + needs.user(); + needs.settings({ poll_enabled: true, poll_minimum_trust_level_to_create: 1, - }, - beforeEach() { - clearPopupMenuOptionsCallback(); - }, -}); - -test("regular user - sufficient trust level", async (assert) => { - updateCurrentUser({ moderator: false, admin: false, trust_level: 1 }); - - await displayPollBuilderButton(); - - assert.ok( - exists(".select-kit-row[title='Build Poll']"), - "it shows the builder button" - ); -}); - -test("regular user - insufficient trust level", async (assert) => { - updateCurrentUser({ moderator: false, admin: false, trust_level: 0 }); - - await displayPollBuilderButton(); - - assert.ok( - !exists(".select-kit-row[title='Build Poll']"), - "it hides the builder button" - ); -}); - -test("staff - with insufficient trust level", async (assert) => { - updateCurrentUser({ moderator: true, trust_level: 0 }); - - await displayPollBuilderButton(); - - assert.ok( - exists(".select-kit-row[title='Build Poll']"), - "it shows the builder button" - ); -}); - -test("poll preview", async (assert) => { - await displayPollBuilderButton(); - - const popupMenu = selectKit(".toolbar-popup-menu-options"); - await popupMenu.selectRowByValue("showPollBuilder"); - - await fillIn(".poll-textarea textarea", "First option\nSecond option"); - - assert.equal(find(".d-editor-preview li:first-child").text(), "First option"); - assert.equal(find(".d-editor-preview li:last-child").text(), "Second option"); + }); + needs.hooks.beforeEach(() => clearPopupMenuOptionsCallback()); + + test("regular user - sufficient trust level", async (assert) => { + updateCurrentUser({ moderator: false, admin: false, trust_level: 1 }); + + await displayPollBuilderButton(); + + assert.ok( + exists(".select-kit-row[title='Build Poll']"), + "it shows the builder button" + ); + }); + + test("regular user - insufficient trust level", async (assert) => { + updateCurrentUser({ moderator: false, admin: false, trust_level: 0 }); + + await displayPollBuilderButton(); + + assert.ok( + !exists(".select-kit-row[title='Build Poll']"), + "it hides the builder button" + ); + }); + + test("staff - with insufficient trust level", async (assert) => { + updateCurrentUser({ moderator: true, trust_level: 0 }); + + await displayPollBuilderButton(); + + assert.ok( + exists(".select-kit-row[title='Build Poll']"), + "it shows the builder button" + ); + }); + + test("poll preview", async (assert) => { + await displayPollBuilderButton(); + + const popupMenu = selectKit(".toolbar-popup-menu-options"); + await popupMenu.selectRowByValue("showPollBuilder"); + + await fillIn(".poll-textarea textarea", "First option\nSecond option"); + + assert.equal( + find(".d-editor-preview li:first-child").text(), + "First option" + ); + assert.equal( + find(".d-editor-preview li:last-child").text(), + "Second option" + ); + }); }); diff --git a/plugins/poll/test/javascripts/acceptance/poll-pie-chart-test.js.es6 b/plugins/poll/test/javascripts/acceptance/poll-pie-chart-test.js.es6 index e3f3d32128b..7c40e200c7d 100644 --- a/plugins/poll/test/javascripts/acceptance/poll-pie-chart-test.js.es6 +++ b/plugins/poll/test/javascripts/acceptance/poll-pie-chart-test.js.es6 @@ -1,36 +1,39 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -acceptance("Rendering polls with pie charts", { - loggedIn: true, - settings: { poll_enabled: true, poll_groupable_user_fields: "something" }, -}); - -test("Displays the pie chart", async (assert) => { - await visit("/t/-/topic_with_pie_chart_poll"); - - const poll = find(".poll")[0]; - - assert.equal( - find(".info-number", poll)[0].innerHTML, - "2", - "it should display the right number of voters" - ); - - assert.equal( - find(".info-number", poll)[1].innerHTML, - "5", - "it should display the right number of votes" - ); - - assert.equal( - poll.classList.contains("pie"), - true, - "pie class is present on poll div" - ); - - assert.equal( - find(".poll-results-chart", poll).length, - 1, - "Renders the chart div instead of bar container" - ); +acceptance("Rendering polls with pie charts", function (needs) { + needs.user(); + needs.settings({ + poll_enabled: true, + poll_groupable_user_fields: "something", + }); + + test("Displays the pie chart", async (assert) => { + await visit("/t/-/topic_with_pie_chart_poll"); + + const poll = find(".poll")[0]; + + assert.equal( + find(".info-number", poll)[0].innerHTML, + "2", + "it should display the right number of voters" + ); + + assert.equal( + find(".info-number", poll)[1].innerHTML, + "5", + "it should display the right number of votes" + ); + + assert.equal( + poll.classList.contains("pie"), + true, + "pie class is present on poll div" + ); + + assert.equal( + find(".poll-results-chart", poll).length, + 1, + "Renders the chart div instead of bar container" + ); + }); }); diff --git a/plugins/poll/test/javascripts/acceptance/poll-quote-test.js.es6 b/plugins/poll/test/javascripts/acceptance/poll-quote-test.js.es6 index ffee71a0d3b..1617451db4f 100644 --- a/plugins/poll/test/javascripts/acceptance/poll-quote-test.js.es6 +++ b/plugins/poll/test/javascripts/acceptance/poll-quote-test.js.es6 @@ -1,697 +1,683 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import { clearPopupMenuOptionsCallback } from "discourse/controllers/composer"; -import { Promise } from "rsvp"; -acceptance("Poll quote", { - loggedIn: true, - settings: { poll_enabled: true }, - beforeEach() { +acceptance("Poll quote", function (needs) { + needs.user(); + needs.settings({ poll_enabled: true }); + needs.hooks.beforeEach(() => { clearPopupMenuOptionsCallback(); - }, - pretend(server, helper) { + }); + + needs.pretender((server, helper) => { server.get("/t/topic_with_two_polls.json", () => { - return new Promise((resolve) => { - resolve( - helper.response({ - post_stream: { - posts: [ - { - id: 133, - name: null, - username: "bianca", - avatar_template: - "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", - created_at: "2020-08-17T12:05:24.577Z", - cooked: - '
\n
\n
\n
    \n
  • Alpha
  • \n
  • Beta
  • \n
\n
\n
\n

\n0\nvoters\n

\n
\n
\n
\n
\n
\n
\n
    \n
  • First
  • \n
  • Second
  • \n
\n
\n
\n

\n0\nvoters\n

\n
\n
\n
', - post_number: 1, - post_type: 1, - updated_at: "2020-08-17T12:05:24.577Z", - reply_count: 0, - reply_to_post_number: null, - quote_count: 0, - incoming_link_count: 0, - reads: 1, - readers_count: 0, - score: 0, - yours: true, - topic_id: 130, - topic_slug: "topic-with-two-polls", - display_username: null, - primary_group_name: null, - primary_group_flair_url: null, - primary_group_flair_bg_color: null, - primary_group_flair_color: null, - version: 1, - can_edit: true, - can_delete: false, - can_recover: false, - can_wiki: true, - link_counts: [ - { - url: - "http://forum.example.com/t/topic-with-two-quoted-polls/129", - internal: true, - reflection: true, - title: "Topic with two quoted polls", - clicks: 0, - }, - ], - read: true, - user_title: "Tester", - title_is_group: false, - bookmarked: false, - actions_summary: [ - { - id: 3, - can_act: true, - }, - { - id: 4, - can_act: true, - }, - { - id: 8, - can_act: true, - }, - { - id: 7, - can_act: true, - }, - ], - moderator: false, - admin: true, - staff: true, - user_id: 1, - hidden: false, - trust_level: 0, - deleted_at: null, - user_deleted: false, - edit_reason: null, - can_view_edit_history: true, - wiki: false, - reviewable_id: 0, - reviewable_score_count: 0, - reviewable_score_pending_count: 0, - calendar_details: [], - polls: [ - { - name: "poll1", - type: "regular", - status: "open", - results: "always", - options: [ - { - id: "bf48cd4958a17180e2a298e246988f94", - html: "Alpha", - votes: 0, - }, - { - id: "c19aa835729ab0413a84a2c9850c4005", - html: "Beta", - votes: 0, - }, - ], - voters: 0, - chart_type: "bar", - }, - { - name: "poll2", - type: "regular", - status: "open", - results: "always", - options: [ - { - id: "def034c6770c6fd3754c054ef9ec4721", - html: "First", - votes: 0, - }, - { - id: "e0f55d1a981683789bec2a0b05eb70ef", - html: "Second", - votes: 0, - }, - ], - voters: 0, - chart_type: "bar", - }, - ], - }, - ], - stream: [133], - }, - timeline_lookup: [[1, 0]], - suggested_topics: [], - tags: [], - id: 130, - title: "Topic with two polls", - fancy_title: "Topic with two polls", - posts_count: 1, - created_at: "2020-08-17T12:05:24.500Z", - views: 1, - reply_count: 0, - like_count: 0, - last_posted_at: "2020-08-17T12:05:24.577Z", - visible: true, - closed: false, - archived: false, - has_summary: false, - archetype: "regular", - slug: "topic-with-two-polls", - category_id: 1, - word_count: 24, - deleted_at: null, - user_id: 1, - featured_link: null, - pinned_globally: false, - pinned_at: null, - pinned_until: null, - image_url: null, - draft: null, - draft_key: "topic_130", - draft_sequence: 0, - posted: true, - unpinned: null, - pinned: false, - current_post_number: 1, - highest_post_number: 1, - last_read_post_number: 1, - last_read_post_id: 133, - deleted_by: null, - has_deleted: false, - actions_summary: [ - { - id: 4, - count: 0, - hidden: false, - can_act: true, - }, - { - id: 8, - count: 0, - hidden: false, - can_act: true, - }, - { - id: 7, - count: 0, - hidden: false, - can_act: true, - }, - ], - chunk_size: 20, - bookmarked: false, - topic_timer: null, - message_bus_last_id: 1, - participant_count: 1, - queued_posts_count: 0, - show_read_indicator: false, - thumbnails: null, - can_vote: false, - vote_count: null, - user_voted: false, - details: { - notification_level: 3, - notifications_reason_id: 1, - can_move_posts: true, + return helper.response({ + post_stream: { + posts: [ + { + id: 133, + name: null, + username: "bianca", + avatar_template: + "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", + created_at: "2020-08-17T12:05:24.577Z", + cooked: + '
\n
\n
\n
    \n
  • Alpha
  • \n
  • Beta
  • \n
\n
\n
\n

\n0\nvoters\n

\n
\n
\n
\n
\n
\n
\n
    \n
  • First
  • \n
  • Second
  • \n
\n
\n
\n

\n0\nvoters\n

\n
\n
\n
', + post_number: 1, + post_type: 1, + updated_at: "2020-08-17T12:05:24.577Z", + reply_count: 0, + reply_to_post_number: null, + quote_count: 0, + incoming_link_count: 0, + reads: 1, + readers_count: 0, + score: 0, + yours: true, + topic_id: 130, + topic_slug: "topic-with-two-polls", + display_username: null, + primary_group_name: null, + primary_group_flair_url: null, + primary_group_flair_bg_color: null, + primary_group_flair_color: null, + version: 1, can_edit: true, - can_delete: true, - can_remove_allowed_users: true, - can_invite_to: true, - can_invite_via_email: true, - can_create_post: true, - can_reply_as_new_topic: true, - can_flag_topic: true, - can_convert_topic: true, - can_review_topic: true, - can_close_topic: true, - can_archive_topic: true, - can_split_merge_topic: true, - can_edit_staff_notes: true, - can_remove_self_id: 1, - participants: [ + can_delete: false, + can_recover: false, + can_wiki: true, + link_counts: [ { - id: 1, - username: "bianca", - name: null, - avatar_template: - "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", - post_count: 1, - primary_group_name: null, - primary_group_flair_url: null, - primary_group_flair_color: null, - primary_group_flair_bg_color: null, + url: + "http://forum.example.com/t/topic-with-two-quoted-polls/129", + internal: true, + reflection: true, + title: "Topic with two quoted polls", + clicks: 0, + }, + ], + read: true, + user_title: "Tester", + title_is_group: false, + bookmarked: false, + actions_summary: [ + { + id: 3, + can_act: true, + }, + { + id: 4, + can_act: true, + }, + { + id: 8, + can_act: true, + }, + { + id: 7, + can_act: true, + }, + ], + moderator: false, + admin: true, + staff: true, + user_id: 1, + hidden: false, + trust_level: 0, + deleted_at: null, + user_deleted: false, + edit_reason: null, + can_view_edit_history: true, + wiki: false, + reviewable_id: 0, + reviewable_score_count: 0, + reviewable_score_pending_count: 0, + calendar_details: [], + polls: [ + { + name: "poll1", + type: "regular", + status: "open", + results: "always", + options: [ + { + id: "bf48cd4958a17180e2a298e246988f94", + html: "Alpha", + votes: 0, + }, + { + id: "c19aa835729ab0413a84a2c9850c4005", + html: "Beta", + votes: 0, + }, + ], + voters: 0, + chart_type: "bar", + }, + { + name: "poll2", + type: "regular", + status: "open", + results: "always", + options: [ + { + id: "def034c6770c6fd3754c054ef9ec4721", + html: "First", + votes: 0, + }, + { + id: "e0f55d1a981683789bec2a0b05eb70ef", + html: "Second", + votes: 0, + }, + ], + voters: 0, + chart_type: "bar", }, ], - created_by: { - id: 1, - username: "bianca", - name: null, - avatar_template: - "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", - }, - last_poster: { - id: 1, - username: "bianca", - name: null, - avatar_template: - "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", - }, }, - pending_posts: [], - }) - ); + ], + stream: [133], + }, + timeline_lookup: [[1, 0]], + suggested_topics: [], + tags: [], + id: 130, + title: "Topic with two polls", + fancy_title: "Topic with two polls", + posts_count: 1, + created_at: "2020-08-17T12:05:24.500Z", + views: 1, + reply_count: 0, + like_count: 0, + last_posted_at: "2020-08-17T12:05:24.577Z", + visible: true, + closed: false, + archived: false, + has_summary: false, + archetype: "regular", + slug: "topic-with-two-polls", + category_id: 1, + word_count: 24, + deleted_at: null, + user_id: 1, + featured_link: null, + pinned_globally: false, + pinned_at: null, + pinned_until: null, + image_url: null, + draft: null, + draft_key: "topic_130", + draft_sequence: 0, + posted: true, + unpinned: null, + pinned: false, + current_post_number: 1, + highest_post_number: 1, + last_read_post_number: 1, + last_read_post_id: 133, + deleted_by: null, + has_deleted: false, + actions_summary: [ + { + id: 4, + count: 0, + hidden: false, + can_act: true, + }, + { + id: 8, + count: 0, + hidden: false, + can_act: true, + }, + { + id: 7, + count: 0, + hidden: false, + can_act: true, + }, + ], + chunk_size: 20, + bookmarked: false, + topic_timer: null, + message_bus_last_id: 1, + participant_count: 1, + queued_posts_count: 0, + show_read_indicator: false, + thumbnails: null, + can_vote: false, + vote_count: null, + user_voted: false, + details: { + notification_level: 3, + notifications_reason_id: 1, + can_move_posts: true, + can_edit: true, + can_delete: true, + can_remove_allowed_users: true, + can_invite_to: true, + can_invite_via_email: true, + can_create_post: true, + can_reply_as_new_topic: true, + can_flag_topic: true, + can_convert_topic: true, + can_review_topic: true, + can_close_topic: true, + can_archive_topic: true, + can_split_merge_topic: true, + can_edit_staff_notes: true, + can_remove_self_id: 1, + participants: [ + { + id: 1, + username: "bianca", + name: null, + avatar_template: + "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", + post_count: 1, + primary_group_name: null, + primary_group_flair_url: null, + primary_group_flair_color: null, + primary_group_flair_bg_color: null, + }, + ], + created_by: { + id: 1, + username: "bianca", + name: null, + avatar_template: + "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", + }, + last_poster: { + id: 1, + username: "bianca", + name: null, + avatar_template: + "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", + }, + }, + pending_posts: [], }); }); server.get("/posts/by_number/130/1", () => { - return new Promise((resolve) => { - resolve( - helper.response({ - id: 133, - name: null, - username: "bianca", - avatar_template: - "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", - created_at: "2020-08-17T12:05:24.577Z", - cooked: - '
\n
\n
\n
    \n
  • Alpha
  • \n
  • Beta
  • \n
\n
\n
\n

\n0\nvoters\n

\n
\n
\n
\n
\n
\n
\n
    \n
  • First
  • \n
  • Second
  • \n
\n
\n
\n

\n0\nvoters\n

\n
\n
\n
', - post_number: 1, - post_type: 1, - updated_at: "2020-08-17T12:05:24.577Z", - reply_count: 0, - reply_to_post_number: null, - quote_count: 0, - incoming_link_count: 0, - reads: 1, - readers_count: 0, - score: 0.2, - yours: true, - topic_id: 130, - topic_slug: "topic-with-two-polls", - display_username: null, - primary_group_name: null, - primary_group_flair_url: null, - primary_group_flair_bg_color: null, - primary_group_flair_color: null, - version: 1, - can_edit: true, - can_delete: false, - can_recover: false, - can_wiki: true, - user_title: "Tester", - title_is_group: false, - bookmarked: false, - raw: - "[poll name=poll1 type=regular results=always chartType=bar]\n* Alpha\n* Beta\n[/poll]\n\n[poll name=poll2 type=regular results=always chartType=bar]\n* First\n* Second\n[/poll]", - actions_summary: [ + return helper.response({ + id: 133, + name: null, + username: "bianca", + avatar_template: "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", + created_at: "2020-08-17T12:05:24.577Z", + cooked: + '
\n
\n
\n
    \n
  • Alpha
  • \n
  • Beta
  • \n
\n
\n
\n

\n0\nvoters\n

\n
\n
\n
\n
\n
\n
\n
    \n
  • First
  • \n
  • Second
  • \n
\n
\n
\n

\n0\nvoters\n

\n
\n
\n
', + post_number: 1, + post_type: 1, + updated_at: "2020-08-17T12:05:24.577Z", + reply_count: 0, + reply_to_post_number: null, + quote_count: 0, + incoming_link_count: 0, + reads: 1, + readers_count: 0, + score: 0.2, + yours: true, + topic_id: 130, + topic_slug: "topic-with-two-polls", + display_username: null, + primary_group_name: null, + primary_group_flair_url: null, + primary_group_flair_bg_color: null, + primary_group_flair_color: null, + version: 1, + can_edit: true, + can_delete: false, + can_recover: false, + can_wiki: true, + user_title: "Tester", + title_is_group: false, + bookmarked: false, + raw: + "[poll name=poll1 type=regular results=always chartType=bar]\n* Alpha\n* Beta\n[/poll]\n\n[poll name=poll2 type=regular results=always chartType=bar]\n* First\n* Second\n[/poll]", + actions_summary: [ + { + id: 3, + can_act: true, + }, + { + id: 4, + can_act: true, + }, + { + id: 8, + can_act: true, + }, + { + id: 7, + can_act: true, + }, + ], + moderator: false, + admin: true, + staff: true, + user_id: 1, + hidden: false, + trust_level: 0, + deleted_at: null, + user_deleted: false, + edit_reason: null, + can_view_edit_history: true, + wiki: false, + reviewable_id: null, + reviewable_score_count: 0, + reviewable_score_pending_count: 0, + calendar_details: [], + polls: [ + { + name: "poll1", + type: "regular", + status: "open", + results: "always", + options: [ { - id: 3, - can_act: true, + id: "bf48cd4958a17180e2a298e246988f94", + html: "Alpha", + votes: 0, }, { - id: 4, - can_act: true, - }, - { - id: 8, - can_act: true, - }, - { - id: 7, - can_act: true, + id: "c19aa835729ab0413a84a2c9850c4005", + html: "Beta", + votes: 0, }, ], - moderator: false, - admin: true, - staff: true, - user_id: 1, - hidden: false, - trust_level: 0, - deleted_at: null, - user_deleted: false, - edit_reason: null, - can_view_edit_history: true, - wiki: false, - reviewable_id: null, - reviewable_score_count: 0, - reviewable_score_pending_count: 0, - calendar_details: [], - polls: [ + voters: 0, + chart_type: "bar", + }, + { + name: "poll2", + type: "regular", + status: "open", + results: "always", + options: [ { - name: "poll1", - type: "regular", - status: "open", - results: "always", - options: [ - { - id: "bf48cd4958a17180e2a298e246988f94", - html: "Alpha", - votes: 0, - }, - { - id: "c19aa835729ab0413a84a2c9850c4005", - html: "Beta", - votes: 0, - }, - ], - voters: 0, - chart_type: "bar", + id: "def034c6770c6fd3754c054ef9ec4721", + html: "First", + votes: 0, }, { - name: "poll2", - type: "regular", - status: "open", - results: "always", - options: [ - { - id: "def034c6770c6fd3754c054ef9ec4721", - html: "First", - votes: 0, - }, - { - id: "e0f55d1a981683789bec2a0b05eb70ef", - html: "Second", - votes: 0, - }, - ], - voters: 0, - chart_type: "bar", + id: "e0f55d1a981683789bec2a0b05eb70ef", + html: "Second", + votes: 0, }, ], - }) - ); + voters: 0, + chart_type: "bar", + }, + ], }); }); server.get("/t/topic_with_two_quoted_polls.json", () => { - return new Promise((resolve) => { - resolve( - helper.response({ - post_stream: { - posts: [ + return helper.response({ + post_stream: { + posts: [ + { + id: 134, + name: null, + username: "bianca", + avatar_template: + "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", + created_at: "2020-08-17T12:08:24.043Z", + cooked: + '\n', + post_number: 1, + post_type: 1, + updated_at: "2020-08-17T12:08:24.043Z", + reply_count: 0, + reply_to_post_number: null, + quote_count: 0, + incoming_link_count: 0, + reads: 1, + readers_count: 0, + score: 0, + yours: true, + topic_id: 131, + topic_slug: "topic-with-two-quoted-polls", + display_username: null, + primary_group_name: null, + primary_group_flair_url: null, + primary_group_flair_bg_color: null, + primary_group_flair_color: null, + version: 1, + can_edit: true, + can_delete: false, + can_recover: false, + can_wiki: true, + link_counts: [ { - id: 134, - name: null, - username: "bianca", - avatar_template: - "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", - created_at: "2020-08-17T12:08:24.043Z", - cooked: - '\n', - post_number: 1, - post_type: 1, - updated_at: "2020-08-17T12:08:24.043Z", - reply_count: 0, - reply_to_post_number: null, - quote_count: 0, - incoming_link_count: 0, - reads: 1, - readers_count: 0, - score: 0, - yours: true, - topic_id: 131, - topic_slug: "topic-with-two-quoted-polls", - display_username: null, - primary_group_name: null, - primary_group_flair_url: null, - primary_group_flair_bg_color: null, - primary_group_flair_color: null, - version: 1, - can_edit: true, - can_delete: false, - can_recover: false, - can_wiki: true, - link_counts: [ - { - url: - "http://forum.example.com/t/topic-with-two-polls/130", - internal: true, - reflection: false, - title: "Topic with two polls", - clicks: 0, - }, - ], - read: true, - user_title: "Tester", - title_is_group: false, - bookmarked: false, - actions_summary: [ - { - id: 3, - can_act: true, - }, - { - id: 4, - can_act: true, - }, - { - id: 8, - can_act: true, - }, - { - id: 7, - can_act: true, - }, - ], - moderator: false, - admin: true, - staff: true, - user_id: 1, - hidden: false, - trust_level: 0, - deleted_at: null, - user_deleted: false, - edit_reason: null, - can_view_edit_history: true, - wiki: false, - reviewable_id: 0, - reviewable_score_count: 0, - reviewable_score_pending_count: 0, - calendar_details: [], + url: "http://forum.example.com/t/topic-with-two-polls/130", + internal: true, + reflection: false, + title: "Topic with two polls", + clicks: 0, }, ], - stream: [134], + read: true, + user_title: "Tester", + title_is_group: false, + bookmarked: false, + actions_summary: [ + { + id: 3, + can_act: true, + }, + { + id: 4, + can_act: true, + }, + { + id: 8, + can_act: true, + }, + { + id: 7, + can_act: true, + }, + ], + moderator: false, + admin: true, + staff: true, + user_id: 1, + hidden: false, + trust_level: 0, + deleted_at: null, + user_deleted: false, + edit_reason: null, + can_view_edit_history: true, + wiki: false, + reviewable_id: 0, + reviewable_score_count: 0, + reviewable_score_pending_count: 0, + calendar_details: [], }, - timeline_lookup: [[1, 0]], - suggested_topics: [ - { - id: 7, - title: "Welcome to Discourse", - fancy_title: "Welcome to Discourse", - slug: "welcome-to-discourse", - posts_count: 1, - reply_count: 0, - highest_post_number: 1, - image_url: null, - created_at: "2020-08-11T12:43:04.894Z", - last_posted_at: "2020-08-11T12:43:04.959Z", - bumped: true, - bumped_at: "2020-08-11T12:43:04.959Z", - archetype: "regular", - unseen: false, - last_read_post_number: 1, - unread: 0, - new_posts: 0, - pinned: false, - unpinned: true, - visible: true, - closed: false, - archived: false, - notification_level: 1, - bookmarked: false, - liked: false, - tags: [], - like_count: 0, - views: 1, - category_id: 1, - featured_link: null, - posters: [ - { - extras: "latest single", - description: "Original Poster, Most Recent Poster", - user: { - id: 5, - username: "foo2", - name: null, - avatar_template: - "/letter_avatar_proxy/v4/letter/f/8edcca/{size}.png", - }, - }, - ], - }, - { - id: 130, - title: "Topic with two polls", - fancy_title: "Topic with two polls", - slug: "topic-with-two-polls", - posts_count: 1, - reply_count: 0, - highest_post_number: 1, - image_url: null, - created_at: "2020-08-17T12:05:24.500Z", - last_posted_at: "2020-08-17T12:05:24.577Z", - bumped: true, - bumped_at: "2020-08-17T12:05:24.577Z", - archetype: "regular", - unseen: false, - last_read_post_number: 1, - unread: 0, - new_posts: 0, - pinned: false, - unpinned: null, - visible: true, - closed: false, - archived: false, - notification_level: 3, - bookmarked: false, - liked: false, - tags: [], - like_count: 0, - views: 1, - category_id: 1, - featured_link: null, - posters: [ - { - extras: "latest single", - description: "Original Poster, Most Recent Poster", - user: { - id: 1, - username: "bianca", - name: null, - avatar_template: - "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", - }, - }, - ], - }, - ], - tags: [], - id: 131, - title: "Topic with two quoted polls", - fancy_title: "Topic with two quoted polls", + ], + stream: [134], + }, + timeline_lookup: [[1, 0]], + suggested_topics: [ + { + id: 7, + title: "Welcome to Discourse", + fancy_title: "Welcome to Discourse", + slug: "welcome-to-discourse", posts_count: 1, - created_at: "2020-08-17T12:08:23.918Z", - views: 1, reply_count: 0, - like_count: 0, - last_posted_at: "2020-08-17T12:08:24.043Z", + highest_post_number: 1, + image_url: null, + created_at: "2020-08-11T12:43:04.894Z", + last_posted_at: "2020-08-11T12:43:04.959Z", + bumped: true, + bumped_at: "2020-08-11T12:43:04.959Z", + archetype: "regular", + unseen: false, + last_read_post_number: 1, + unread: 0, + new_posts: 0, + pinned: false, + unpinned: true, visible: true, closed: false, archived: false, - has_summary: false, - archetype: "regular", - slug: "topic-with-two-quoted-polls", + notification_level: 1, + bookmarked: false, + liked: false, + tags: [], + like_count: 0, + views: 1, category_id: 1, - word_count: 9, - deleted_at: null, - user_id: 1, featured_link: null, - pinned_globally: false, - pinned_at: null, - pinned_until: null, - image_url: null, - draft: null, - draft_key: "topic_131", - draft_sequence: 0, - posted: true, - unpinned: null, - pinned: false, - current_post_number: 1, - highest_post_number: 1, - last_read_post_number: 1, - last_read_post_id: 134, - deleted_by: null, - has_deleted: false, - actions_summary: [ + posters: [ { - id: 4, - count: 0, - hidden: false, - can_act: true, - }, - { - id: 8, - count: 0, - hidden: false, - can_act: true, - }, - { - id: 7, - count: 0, - hidden: false, - can_act: true, + extras: "latest single", + description: "Original Poster, Most Recent Poster", + user: { + id: 5, + username: "foo2", + name: null, + avatar_template: + "/letter_avatar_proxy/v4/letter/f/8edcca/{size}.png", + }, }, ], - chunk_size: 20, + }, + { + id: 130, + title: "Topic with two polls", + fancy_title: "Topic with two polls", + slug: "topic-with-two-polls", + posts_count: 1, + reply_count: 0, + highest_post_number: 1, + image_url: null, + created_at: "2020-08-17T12:05:24.500Z", + last_posted_at: "2020-08-17T12:05:24.577Z", + bumped: true, + bumped_at: "2020-08-17T12:05:24.577Z", + archetype: "regular", + unseen: false, + last_read_post_number: 1, + unread: 0, + new_posts: 0, + pinned: false, + unpinned: null, + visible: true, + closed: false, + archived: false, + notification_level: 3, bookmarked: false, - topic_timer: null, - message_bus_last_id: 2, - participant_count: 1, - queued_posts_count: 0, - show_read_indicator: false, - thumbnails: null, - can_vote: false, - vote_count: null, - user_voted: false, - details: { - notification_level: 3, - notifications_reason_id: 1, - can_move_posts: true, - can_edit: true, - can_delete: true, - can_remove_allowed_users: true, - can_invite_to: true, - can_invite_via_email: true, - can_create_post: true, - can_reply_as_new_topic: true, - can_flag_topic: true, - can_convert_topic: true, - can_review_topic: true, - can_close_topic: true, - can_archive_topic: true, - can_split_merge_topic: true, - can_edit_staff_notes: true, - can_remove_self_id: 1, - participants: [ - { + liked: false, + tags: [], + like_count: 0, + views: 1, + category_id: 1, + featured_link: null, + posters: [ + { + extras: "latest single", + description: "Original Poster, Most Recent Poster", + user: { id: 1, username: "bianca", name: null, avatar_template: "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", - post_count: 1, - primary_group_name: null, - primary_group_flair_url: null, - primary_group_flair_color: null, - primary_group_flair_bg_color: null, }, - ], - created_by: { - id: 1, - username: "bianca", - name: null, - avatar_template: - "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", - }, - last_poster: { - id: 1, - username: "bianca", - name: null, - avatar_template: - "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", }, + ], + }, + ], + tags: [], + id: 131, + title: "Topic with two quoted polls", + fancy_title: "Topic with two quoted polls", + posts_count: 1, + created_at: "2020-08-17T12:08:23.918Z", + views: 1, + reply_count: 0, + like_count: 0, + last_posted_at: "2020-08-17T12:08:24.043Z", + visible: true, + closed: false, + archived: false, + has_summary: false, + archetype: "regular", + slug: "topic-with-two-quoted-polls", + category_id: 1, + word_count: 9, + deleted_at: null, + user_id: 1, + featured_link: null, + pinned_globally: false, + pinned_at: null, + pinned_until: null, + image_url: null, + draft: null, + draft_key: "topic_131", + draft_sequence: 0, + posted: true, + unpinned: null, + pinned: false, + current_post_number: 1, + highest_post_number: 1, + last_read_post_number: 1, + last_read_post_id: 134, + deleted_by: null, + has_deleted: false, + actions_summary: [ + { + id: 4, + count: 0, + hidden: false, + can_act: true, + }, + { + id: 8, + count: 0, + hidden: false, + can_act: true, + }, + { + id: 7, + count: 0, + hidden: false, + can_act: true, + }, + ], + chunk_size: 20, + bookmarked: false, + topic_timer: null, + message_bus_last_id: 2, + participant_count: 1, + queued_posts_count: 0, + show_read_indicator: false, + thumbnails: null, + can_vote: false, + vote_count: null, + user_voted: false, + details: { + notification_level: 3, + notifications_reason_id: 1, + can_move_posts: true, + can_edit: true, + can_delete: true, + can_remove_allowed_users: true, + can_invite_to: true, + can_invite_via_email: true, + can_create_post: true, + can_reply_as_new_topic: true, + can_flag_topic: true, + can_convert_topic: true, + can_review_topic: true, + can_close_topic: true, + can_archive_topic: true, + can_split_merge_topic: true, + can_edit_staff_notes: true, + can_remove_self_id: 1, + participants: [ + { + id: 1, + username: "bianca", + name: null, + avatar_template: + "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", + post_count: 1, + primary_group_name: null, + primary_group_flair_url: null, + primary_group_flair_color: null, + primary_group_flair_bg_color: null, }, - pending_posts: [], - }) - ); + ], + created_by: { + id: 1, + username: "bianca", + name: null, + avatar_template: + "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", + }, + last_poster: { + id: 1, + username: "bianca", + name: null, + avatar_template: + "/letter_avatar_proxy/v4/letter/b/3be4f8/{size}.png", + }, + }, + pending_posts: [], }); }); - }, -}); + }); -test("Quoted polls", async (assert) => { - await visit("/t/-/topic_with_two_quoted_polls"); - await click(".quote-controls"); - assert.equal(find(".poll").length, 2); + test("Quoted polls", async (assert) => { + await visit("/t/-/topic_with_two_quoted_polls"); + await click(".quote-controls"); + assert.equal(find(".poll").length, 2); + }); }); diff --git a/plugins/poll/test/javascripts/acceptance/polls-bar-chart-test-desktop.js.es6 b/plugins/poll/test/javascripts/acceptance/polls-bar-chart-test-desktop.js.es6 index 30db0ec80f6..df97eb23d48 100644 --- a/plugins/poll/test/javascripts/acceptance/polls-bar-chart-test-desktop.js.es6 +++ b/plugins/poll/test/javascripts/acceptance/polls-bar-chart-test-desktop.js.es6 @@ -1,13 +1,13 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import { clearPopupMenuOptionsCallback } from "discourse/controllers/composer"; -acceptance("Rendering polls with bar charts - desktop", { - loggedIn: true, - settings: { poll_enabled: true }, - beforeEach() { +acceptance("Rendering polls with bar charts - desktop", function (needs) { + needs.user(); + needs.settings({ poll_enabled: true }); + needs.hooks.beforeEach(() => { clearPopupMenuOptionsCallback(); - }, - pretend(server) { + }); + needs.pretender((server, helper) => { server.get("/polls/voters.json", (request) => { let body = {}; if ( @@ -35,78 +35,78 @@ acceptance("Rendering polls with bar charts - desktop", { })), }; } - return [200, { "Content-Type": "application/json" }, body]; + return helper.response(body); }); - }, -}); - -test("Polls", async (assert) => { - await visit("/t/-/15"); - - const polls = find(".poll"); - - assert.equal(polls.length, 2, "it should render the polls correctly"); - - assert.equal( - find(".info-number", polls[0]).text(), - "2", - "it should display the right number of votes" - ); - - assert.equal( - find(".info-number", polls[1]).text(), - "3", - "it should display the right number of votes" - ); -}); - -test("Public poll", async (assert) => { - await visit("/t/-/14"); - - const polls = find(".poll"); - assert.equal(polls.length, 1, "it should render the poll correctly"); - - await click("button.toggle-results"); - - assert.equal( - find(".poll-voters:first li").length, - 25, - "it should display the right number of voters" - ); - - await click(".poll-voters-toggle-expand:first a"); - - assert.equal( - find(".poll-voters:first li").length, - 26, - "it should display the right number of voters" - ); -}); - -test("Public number poll", async (assert) => { - await visit("/t/-/13"); - - const polls = find(".poll"); - assert.equal(polls.length, 1, "it should render the poll correctly"); - - await click("button.toggle-results"); - - assert.equal( - find(".poll-voters:first li").length, - 25, - "it should display the right number of voters" - ); - - assert.notOk( - find(".poll-voters:first li:first a").attr("href"), - "user URL does not exist" - ); - - await click(".poll-voters-toggle-expand:first a"); - - assert.equal( - find(".poll-voters:first li").length, - 30, - "it should display the right number of voters" - ); + }); + + test("Polls", async (assert) => { + await visit("/t/-/15"); + + const polls = find(".poll"); + + assert.equal(polls.length, 2, "it should render the polls correctly"); + + assert.equal( + find(".info-number", polls[0]).text(), + "2", + "it should display the right number of votes" + ); + + assert.equal( + find(".info-number", polls[1]).text(), + "3", + "it should display the right number of votes" + ); + }); + + test("Public poll", async (assert) => { + await visit("/t/-/14"); + + const polls = find(".poll"); + assert.equal(polls.length, 1, "it should render the poll correctly"); + + await click("button.toggle-results"); + + assert.equal( + find(".poll-voters:first li").length, + 25, + "it should display the right number of voters" + ); + + await click(".poll-voters-toggle-expand:first a"); + + assert.equal( + find(".poll-voters:first li").length, + 26, + "it should display the right number of voters" + ); + }); + + test("Public number poll", async (assert) => { + await visit("/t/-/13"); + + const polls = find(".poll"); + assert.equal(polls.length, 1, "it should render the poll correctly"); + + await click("button.toggle-results"); + + assert.equal( + find(".poll-voters:first li").length, + 25, + "it should display the right number of voters" + ); + + assert.notOk( + find(".poll-voters:first li:first a").attr("href"), + "user URL does not exist" + ); + + await click(".poll-voters-toggle-expand:first a"); + + assert.equal( + find(".poll-voters:first li").length, + 30, + "it should display the right number of voters" + ); + }); }); diff --git a/plugins/poll/test/javascripts/acceptance/polls-bar-chart-test-mobile.js.es6 b/plugins/poll/test/javascripts/acceptance/polls-bar-chart-test-mobile.js.es6 index 1ce4b5f483c..11da7d9a0e6 100644 --- a/plugins/poll/test/javascripts/acceptance/polls-bar-chart-test-mobile.js.es6 +++ b/plugins/poll/test/javascripts/acceptance/polls-bar-chart-test-mobile.js.es6 @@ -1,54 +1,51 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import { clearPopupMenuOptionsCallback } from "discourse/controllers/composer"; -acceptance("Rendering polls with bar charts - mobile", { - loggedIn: true, - mobileView: true, - settings: { poll_enabled: true }, - beforeEach() { - clearPopupMenuOptionsCallback(); - }, - pretend(server) { - // eslint-disable-next-line +acceptance("Rendering polls with bar charts - mobile", function (needs) { + needs.user(); + needs.mobileView(); + needs.settings({ poll_enabled: true }); + needs.pretender((server, helper) => { server.get("/polls/voters.json", () => { - const body = { + return helper.response({ voters: Array.from(new Array(10), (_, i) => ({ id: 500 + i, username: `bruce${500 + i}`, avatar_template: "/images/avatar.png", name: "Bruce Wayne", })), - }; - - return [200, { "Content-Type": "application/json" }, body]; + }); }); - }, -}); - -test("Public number poll", async (assert) => { - await visit("/t/-/13"); - - const polls = find(".poll"); - assert.equal(polls.length, 1, "it should render the poll correctly"); - - await click("button.toggle-results"); - - assert.equal( - find(".poll-voters:first li").length, - 25, - "it should display the right number of voters" - ); - - assert.notOk( - find(".poll-voters:first li:first a").attr("href"), - "user URL does not exist" - ); - - await click(".poll-voters-toggle-expand:first a"); - - assert.equal( - find(".poll-voters:first li").length, - 35, - "it should display the right number of voters" - ); + }); + needs.hooks.beforeEach(() => { + clearPopupMenuOptionsCallback(); + }); + + test("Public number poll", async (assert) => { + await visit("/t/-/13"); + + const polls = find(".poll"); + assert.equal(polls.length, 1, "it should render the poll correctly"); + + await click("button.toggle-results"); + + assert.equal( + find(".poll-voters:first li").length, + 25, + "it should display the right number of voters" + ); + + assert.notOk( + find(".poll-voters:first li:first a").attr("href"), + "user URL does not exist" + ); + + await click(".poll-voters-toggle-expand:first a"); + + assert.equal( + find(".poll-voters:first li").length, + 35, + "it should display the right number of voters" + ); + }); });