diff --git a/app/assets/javascripts/discourse/app/components/tap-tile.js b/app/assets/javascripts/discourse/app/components/tap-tile.js index 3a5203573d0..370415d826c 100644 --- a/app/assets/javascripts/discourse/app/components/tap-tile.js +++ b/app/assets/javascripts/discourse/app/components/tap-tile.js @@ -2,6 +2,10 @@ import Component from "@ember/component"; import { propertyEqual } from "discourse/lib/computed"; export default Component.extend({ + init() { + this._super(...arguments); + this.set("elementId", `tap_tile_${this.tileId}`); + }, classNames: ["tap-tile"], classNameBindings: ["active"], click() { diff --git a/app/assets/javascripts/discourse/app/templates/modal/bookmark.hbs b/app/assets/javascripts/discourse/app/templates/modal/bookmark.hbs index 3a5075ebc9e..d9e51fbbefc 100644 --- a/app/assets/javascripts/discourse/app/templates/modal/bookmark.hbs +++ b/app/assets/javascripts/discourse/app/templates/modal/bookmark.hbs @@ -71,11 +71,12 @@ {{date-picker-future value=customReminderDate onSelect=(action (mut customReminderDate)) + id="bookmark-custom-date" }}
{{d-icon "far-clock"}} - {{input placeholder="--:--" type="time" class="time-input" value=customReminderTime}} + {{input placeholder="--:--" id="bookmark-custom-time" type="time" class="time-input" value=customReminderTime}}
{{/if}} @@ -98,11 +99,11 @@
- {{d-button label="bookmarks.save" class="btn-primary" action=(action "saveAndClose")}} + {{d-button id="save-bookmark" label="bookmarks.save" class="btn-primary" action=(action "saveAndClose")}} {{d-modal-cancel close=(action "closeWithoutSavingBookmark")}} {{#if showDelete}}
- {{d-button icon="trash" class="btn-danger" action=(action "delete")}} + {{d-button id="delete-bookmark" icon="trash" class="btn-danger" action=(action "delete")}}
{{/if}}
diff --git a/test/javascripts/acceptance/bookmarks-test.js b/test/javascripts/acceptance/bookmarks-test.js new file mode 100644 index 00000000000..2c2008f3e2d --- /dev/null +++ b/test/javascripts/acceptance/bookmarks-test.js @@ -0,0 +1,161 @@ +import { acceptance, loggedInUser } from "helpers/qunit-helpers"; +import pretender from "helpers/create-pretender"; + +acceptance("Bookmarking", { + loggedIn: true, + + beforeEach() {} +}); + +function mockSuccessfulBookmarkPost() { + pretender.post("/bookmarks", () => [ + 200, + { + "Content-Type": "application/json" + }, + { + id: 999, + success: "OK" + } + ]); +} + +async function openBookmarkModal() { + await click(".topic-post:first-child button.show-more-actions"); + return await click(".topic-post:first-child button.bookmark"); +} +async function openEditBookmarkModal() { + return await click(".topic-post:first-child button.bookmarked"); +} + +test("Bookmarks modal opening", async assert => { + await visit("/t/internationalization-localization/280"); + await openBookmarkModal(); + assert.ok(exists("#bookmark-reminder-modal"), "it shows the bookmark modal"); +}); + +test("Bookmarks modal selecting reminder type", async assert => { + await visit("/t/internationalization-localization/280"); + await openBookmarkModal(); + await click("#tap_tile_tomorrow"); + assert.ok(exists("#tap_tile_tomorrow.active"), "it selects tomorrow"); + await click("#tap_tile_start_of_next_business_week"); + assert.ok( + exists("#tap_tile_start_of_next_business_week.active"), + "it selects next monday" + ); + await click("#tap_tile_next_week"); + assert.ok(exists("#tap_tile_next_week.active"), "it selects next week"); + await click("#tap_tile_next_month"); + assert.ok(exists("#tap_tile_next_month.active"), "it selects next month"); + await click("#tap_tile_custom"); + assert.ok(exists("#tap_tile_custom.active"), "it selects custom"); + assert.ok(exists(".tap-tile-date-input"), "it shows the custom date input"); + assert.ok(exists(".tap-tile-time-input"), "it shows the custom time input"); +}); + +test("Saving a bookmark with a reminder", async assert => { + mockSuccessfulBookmarkPost(); + await visit("/t/internationalization-localization/280"); + await openBookmarkModal(); + await fillIn("input#bookmark-name", "Check this out later"); + await click("#tap_tile_tomorrow"); + await click("#save-bookmark"); + assert.ok( + exists(".topic-post:first-child button.bookmark.bookmarked"), + "it shows the bookmarked icon on the post" + ); + assert.ok( + exists( + ".topic-post:first-child button.bookmark.bookmarked > .d-icon-discourse-bookmark-clock" + ), + "it shows the bookmark clock icon because of the reminder" + ); +}); + +test("Saving a bookmark with no reminder or name", async assert => { + mockSuccessfulBookmarkPost(); + await visit("/t/internationalization-localization/280"); + await openBookmarkModal(); + await click("#save-bookmark"); + assert.ok( + exists(".topic-post:first-child button.bookmark.bookmarked"), + "it shows the bookmarked icon on the post" + ); + assert.not( + exists( + ".topic-post:first-child button.bookmark.bookmarked > .d-icon-discourse-bookmark-clock" + ), + "it shows the regular bookmark active icon" + ); +}); + +test("Deleting a bookmark with a reminder", async assert => { + pretender.delete("/bookmarks/999", () => [ + 200, + { + "Content-Type": "application/json" + }, + { + success: "OK", + topic_bookmarked: false + } + ]); + mockSuccessfulBookmarkPost(); + await visit("/t/internationalization-localization/280"); + await openBookmarkModal(); + await click("#tap_tile_tomorrow"); + await click("#save-bookmark"); + await openEditBookmarkModal(); + assert.ok(exists("#bookmark-reminder-modal"), "it shows the bookmark modal"); + await click("#delete-bookmark"); + assert.ok(exists(".bootbox.modal"), "it asks for delete confirmation"); + assert.ok( + find(".bootbox.modal") + .text() + .includes(I18n.t("bookmarks.confirm_delete")), + "it shows delete confirmation message" + ); + await click(".bootbox.modal .btn-primary"); + assert.not( + exists(".topic-post:first-child button.bookmark.bookmarked"), + "it no longer shows the bookmarked icon on the post after bookmark is deleted" + ); +}); + +test("Cancelling saving a bookmark", async assert => { + await visit("/t/internationalization-localization/280"); + await openBookmarkModal(); + await click(".d-modal-cancel"); + assert.not( + exists(".topic-post:first-child button.bookmark.bookmarked"), + "it does not show the bookmarked icon on the post because it is not saved" + ); +}); + +test("Editing a bookmark", async assert => { + mockSuccessfulBookmarkPost(); + await visit("/t/internationalization-localization/280"); + let now = moment.tz(loggedInUser().resolvedTimezone()); + let tomorrow = now.add(1, "day").format("YYYY-MM-DD"); + await openBookmarkModal(); + await fillIn("input#bookmark-name", "Test name"); + await click("#tap_tile_tomorrow"); + await click("#save-bookmark"); + await openEditBookmarkModal(); + assert.equal( + find("#bookmark-name").val(), + "Test name", + "it should prefill the bookmark name" + ); + assert.equal( + find("#bookmark-custom-date > input").val(), + tomorrow, + "it should prefill the bookmark date" + ); + assert.equal( + find("#bookmark-custom-time").val(), + "08:00", + "it should prefill the bookmark time" + ); +}); diff --git a/test/javascripts/acceptance/topic-test.js b/test/javascripts/acceptance/topic-test.js index 94f3165dc96..ab271369c30 100644 --- a/test/javascripts/acceptance/topic-test.js +++ b/test/javascripts/acceptance/topic-test.js @@ -248,9 +248,9 @@ QUnit.test("remove featured link", async assert => { "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'); + await click(".title-wrapper .remove-featured-link"); + await click(".title-wrapper .submit-edit"); + assert.ok(!exists(".title-wrapper .topic-featured-link"), "link is gone"); }); QUnit.test("Converting to a public topic", async assert => { @@ -395,17 +395,6 @@ QUnit.test( } ); -acceptance("Topic + Post Bookmarks with Reminders", { - loggedIn: true -}); - -QUnit.test("Bookmarks Modal", async assert => { - await visit("/t/internationalization-localization/280"); - await click(".topic-post:first-child button.show-more-actions"); - await click(".topic-post:first-child button.bookmark"); - assert.ok(exists("#bookmark-reminder-modal"), "it shows the bookmark modal"); -}); - acceptance("Topic with title decorated", { loggedIn: true, beforeEach() { diff --git a/test/javascripts/helpers/qunit-helpers.js b/test/javascripts/helpers/qunit-helpers.js index e0621c294dd..0bc9eaece85 100644 --- a/test/javascripts/helpers/qunit-helpers.js +++ b/test/javascripts/helpers/qunit-helpers.js @@ -36,6 +36,11 @@ export function logIn() { User.resetCurrent(currentUser()); } +// Note: Only use if `loggedIn: true` has been used in an acceptance test +export function loggedInUser() { + return User.current(); +} + const Plugin = $.fn.modal; const Modal = Plugin.Constructor;