This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/tests/acceptance/user-menu-test.js
Alan Guo Xiang Tan ce531913a8
FIX: Sync user's reviewables count when loading reviewables list (#20128)
1. What is the problem here?

When a user's reviewables count changes, the changes are published via
MessageBus in a background Sidekiq job which means there is a delay before the
client receives the MessageBus message with the updated count. During
the time the reviewables count for a user has been updated and the time
when the client receives the MessageBus message with the updated count,
a user may view the reviewables list in the user menu. When that happens, the number of
reviewables in the list may be out of sync with the count shown.

2. What is the fix?

Going forward, the response for the `ReviewablesController#user_menu_list` action will include the user's reviewables count as
the `reviewables_count` attribute. This is then used by the client side
to update the user's reviewables count to ensure that the reviewables
list and count are kept in sync.
2023-02-02 10:19:51 +08:00

973 lines
30 KiB
JavaScript

import { click, currentURL, visit } from "@ember/test-helpers";
import {
acceptance,
exists,
loggedInUser,
publishToMessageBus,
query,
queryAll,
updateCurrentUser,
} from "discourse/tests/helpers/qunit-helpers";
import { test } from "qunit";
import { cloneJSON } from "discourse-common/lib/object";
import { withPluginApi } from "discourse/lib/plugin-api";
import { NOTIFICATION_TYPES } from "discourse/tests/fixtures/concerns/notification-types";
import UserMenuFixtures from "discourse/tests/fixtures/user-menu";
import TopicFixtures from "discourse/tests/fixtures/topic";
import { Promise } from "rsvp";
import { later } from "@ember/runloop";
import I18n from "I18n";
acceptance("User menu", function (needs) {
needs.user({
redesigned_user_menu_enabled: true,
unread_high_priority_notifications: 73,
trust_level: 3,
grouped_unread_notifications: {
[NOTIFICATION_TYPES.replied]: 2,
},
});
needs.settings({
allow_anonymous_posting: true,
anonymous_posting_min_trust_level: 3,
});
let requestHeaders = {};
needs.pretender((server, helper) => {
server.get("/t/1234.json", (request) => {
const json = cloneJSON(TopicFixtures["/t/130.json"]);
json.id = 1234;
json.post_stream.posts.forEach((post) => {
post.topic_id = 1234;
});
requestHeaders = request.requestHeaders;
return helper.response(json);
});
});
needs.hooks.afterEach(() => {
requestHeaders = {};
});
test("notifications panel has a11y attributes", async function (assert) {
await visit("/");
await click(".d-header-icons .current-user");
const panel = query("#quick-access-all-notifications");
assert.strictEqual(panel.getAttribute("tabindex"), "-1");
assert.strictEqual(
panel.querySelector("ul").getAttribute("aria-labelledby"),
"user-menu-button-all-notifications"
);
});
test("replies notifications panel has a11y attributes", async function (assert) {
await visit("/");
await click(".d-header-icons .current-user");
await click("#user-menu-button-replies");
const panel = query("#quick-access-replies");
assert.strictEqual(panel.getAttribute("tabindex"), "-1");
assert.strictEqual(
panel.querySelector("ul").getAttribute("aria-labelledby"),
"user-menu-button-replies"
);
});
test("profile panel has a11y attributes", async function (assert) {
await visit("/");
await click(".d-header-icons .current-user");
await click("#user-menu-button-profile");
const panel = query("#quick-access-profile");
assert.strictEqual(panel.getAttribute("tabindex"), "-1");
assert.strictEqual(
panel.querySelector("ul").getAttribute("aria-labelledby"),
"user-menu-button-profile"
);
});
test("clicking on an unread notification", async function (assert) {
await visit("/");
await click(".d-header-icons .current-user");
let repliesBadgeNotification = query(
"#user-menu-button-replies .badge-notification"
);
assert.strictEqual(
repliesBadgeNotification.textContent.trim(),
"2",
"badge shows the right count"
);
await click(".user-menu ul li.replied a");
assert.strictEqual(
requestHeaders["Discourse-Clear-Notifications"],
123, // id is from the fixtures in fixtures/notification-fixtures.js
"the Discourse-Clear-Notifications request header is set to the notification id in the next ajax request"
);
await click(".d-header-icons .current-user");
repliesBadgeNotification = query(
"#user-menu-button-replies .badge-notification"
);
assert.strictEqual(
repliesBadgeNotification.textContent.trim(),
"1",
"badge shows count reduced by one"
);
});
test("clicking on user menu items", async function (assert) {
updateCurrentUser({ reviewable_count: 1 });
await visit("/");
await click(".d-header-icons .current-user");
await click("#user-menu-button-review-queue");
assert.strictEqual(
query(
"#user-menu-button-review-queue .badge-notification"
).textContent.trim(),
"8",
"updates user's reviewable count based on request's response"
);
await click("#quick-access-review-queue li.reviewable.pending a");
assert.strictEqual(
currentURL(),
"/review/17",
"clicking on an item results in navigation to the item's page"
);
assert.notOk(
exists(".user-menu"),
"clicking on an item closes the menu after navigating"
);
await click(".d-header-icons .current-user");
await click("#user-menu-button-review-queue");
await click("#quick-access-review-queue li.reviewable.pending a");
assert.strictEqual(
currentURL(),
"/review/17",
"clicking on the same item again keeps on the same page"
);
assert.notOk(
exists(".user-menu"),
"clicking on the same item again closes the menu"
);
});
test("tabs have title attributes", async function (assert) {
updateCurrentUser({ reviewable_count: 1 });
withPluginApi("0.1", (api) => {
api.registerUserMenuTab((UserMenuTab) => {
return class extends UserMenuTab {
get id() {
return "tiny-tab-1";
}
get count() {
return this.currentUser.get("unread_high_priority_notifications");
}
get icon() {
return "wrench";
}
get panelComponent() {
return "d-button";
}
get title() {
return `Custom title: ${this.count}`;
}
};
});
});
const expectedTitles = {
"user-menu-button-all-notifications": I18n.t(
"user_menu.tabs.all_notifications"
),
"user-menu-button-replies": I18n.t("user_menu.tabs.replies_with_unread", {
count: 2,
}),
"user-menu-button-likes": I18n.t("user_menu.tabs.likes"),
"user-menu-button-messages": I18n.t("user_menu.tabs.messages"),
"user-menu-button-bookmarks": I18n.t("user_menu.tabs.bookmarks"),
"user-menu-button-tiny-tab-1": "Custom title: 73",
"user-menu-button-review-queue": I18n.t(
"user_menu.tabs.review_queue_with_unread",
{ count: 1 }
),
"user-menu-button-other-notifications": I18n.t(
"user_menu.tabs.other_notifications"
),
"user-menu-button-profile": I18n.t("user_menu.tabs.profile"),
};
await visit("/");
await click(".d-header-icons .current-user");
for (const [key, title] of Object.entries(expectedTitles)) {
assert.strictEqual(
query(`#${key}`).title,
title,
`${key} tab has the right title`
);
}
await publishToMessageBus(`/notification/${loggedInUser().id}`, {
unread_high_priority_notifications: 22,
});
assert.strictEqual(
query("#user-menu-button-tiny-tab-1").title,
"Custom title: 22",
"tabs titles can update dynamically"
);
});
test("tabs added via the plugin API", async function (assert) {
updateCurrentUser({ reviewable_count: 1 });
withPluginApi("0.1", (api) => {
api.registerUserMenuTab((UserMenuTab) => {
return class extends UserMenuTab {
get id() {
return "custom-tab-1";
}
get count() {
return this.currentUser.get("unread_high_priority_notifications");
}
get icon() {
return "wrench";
}
get panelComponent() {
return "d-button";
}
};
});
api.registerUserMenuTab((UserMenuTab) => {
return class extends UserMenuTab {
get id() {
return "custom-tab-2";
}
get count() {
return 29;
}
get icon() {
return "plus";
}
get panelComponent() {
return "d-button";
}
};
});
});
const expectedTabOrder = {
"user-menu-button-all-notifications": "0",
"user-menu-button-replies": "1",
"user-menu-button-likes": "2",
"user-menu-button-messages": "3",
"user-menu-button-bookmarks": "4",
"user-menu-button-custom-tab-1": "5",
"user-menu-button-custom-tab-2": "6",
"user-menu-button-review-queue": "7",
"user-menu-button-other-notifications": "8",
};
await visit("/");
await click(".d-header-icons .current-user");
assert.ok(
exists("#user-menu-button-custom-tab-1"),
"first custom tab is rendered"
);
assert.ok(
exists("#user-menu-button-custom-tab-2"),
"second custom tab is rendered"
);
const tabs = [...queryAll(".tabs-list.top-tabs .btn")];
assert.deepEqual(
tabs.reduce((acc, tab) => {
acc[tab.id] = tab.dataset.tabNumber;
return acc;
}, {}),
expectedTabOrder,
"data-tab-number of the tabs has no gaps when custom tabs are added and the tabs are in the right order"
);
assert.strictEqual(
query(".tabs-list.bottom-tabs .btn").dataset.tabNumber,
"9",
"bottom tab has the correct data-tab-number"
);
let customTab1Bubble = query(
"#user-menu-button-custom-tab-1 .badge-notification"
);
assert.strictEqual(
customTab1Bubble.textContent.trim(),
"73",
"bubble shows the right count"
);
const customTab2Bubble = query(
"#user-menu-button-custom-tab-2 .badge-notification"
);
assert.strictEqual(
customTab2Bubble.textContent.trim(),
"29",
"bubble shows the right count"
);
await publishToMessageBus(`/notification/${loggedInUser().id}`, {
unread_high_priority_notifications: 18,
});
customTab1Bubble = query(
"#user-menu-button-custom-tab-1 .badge-notification"
);
assert.strictEqual(
customTab1Bubble.textContent.trim(),
"18",
"displayed bubble count updates when the value is changed"
);
await click("#user-menu-button-custom-tab-1");
assert.ok(
exists("#user-menu-button-custom-tab-1.active"),
"custom tabs can be clicked on and become active"
);
assert.ok(
exists("#quick-access-custom-tab-1 button.btn"),
"the tab's content is now displayed in the panel"
);
});
test("notifications tab applies model transformations registered by plugins", async function (assert) {
withPluginApi("0.1", (api) => {
api.registerModelTransformer("notification", (notifications) => {
notifications.forEach((notification, index) => {
if (notification.fancy_title) {
notification.fancy_title = `pluginNotificationTransformer ${index} ${notification.fancy_title}`;
}
});
});
});
await visit("/");
await click(".d-header-icons .current-user");
const notifications = queryAll(
"#quick-access-all-notifications ul li.notification"
);
assert.strictEqual(
notifications[0].textContent.replace(/\s+/g, " ").trim(),
"velesin pluginNotificationTransformer 0 edited topic 443"
);
assert.strictEqual(
notifications[1].textContent.replace(/\s+/g, " ").trim(),
"velesin pluginNotificationTransformer 1 some title"
);
});
test("bookmarks tab applies model transformations registered by plugins", async function (assert) {
withPluginApi("0.1", (api) => {
api.registerModelTransformer("bookmark", (bookmarks) => {
bookmarks.forEach((bookmark) => {
if (bookmark.title) {
bookmark.title = `pluginBookmarkTransformer ${bookmark.title}`;
}
});
});
});
await visit("/");
await click(".d-header-icons .current-user");
await click("#user-menu-button-bookmarks");
const bookmarks = queryAll("#quick-access-bookmarks ul li.bookmark");
assert.strictEqual(
bookmarks[0].textContent.replace(/\s+/g, " ").trim(),
"osama pluginBookmarkTransformer Test poll topic hello world"
);
});
test("messages tab applies model transformations registered by plugins", async function (assert) {
withPluginApi("0.1", (api) => {
api.registerModelTransformer("topic", (topics) => {
topics.forEach((topic) => {
topic.fancy_title = `pluginTransformer#1 ${topic.fancy_title}`;
});
});
api.registerModelTransformer("topic", async (topics) => {
// sleep 1 ms
await new Promise((resolve) => later(resolve, 1));
topics.forEach((topic) => {
topic.fancy_title = `pluginTransformer#2 ${topic.fancy_title}`;
});
});
});
await visit("/");
await click(".d-header-icons .current-user");
await click("#user-menu-button-messages");
const messages = queryAll("#quick-access-messages ul li.message");
assert.strictEqual(
messages[0].textContent.replace(/\s+/g, " ").trim(),
"mixtape pluginTransformer#2 pluginTransformer#1 BUG: Can not render emoji properly"
);
});
test("the profile tab", async function (assert) {
updateCurrentUser({ draft_count: 13 });
await visit("/");
await click(".d-header-icons .current-user");
await click("#user-menu-button-profile");
const summaryLink = query("#quick-access-profile ul li.summary a");
assert.ok(
summaryLink.href.endsWith("/u/eviltrout/summary"),
"has a link to the summary page of the user"
);
assert.strictEqual(
summaryLink.textContent.trim(),
I18n.t("user.summary.title"),
"summary link has the right label"
);
assert.ok(
summaryLink.querySelector(".d-icon-user"),
"summary link has the right icon"
);
const activityLink = query("#quick-access-profile ul li.activity a");
assert.ok(
activityLink.href.endsWith("/u/eviltrout/activity"),
"has a link to the activity page of the user"
);
assert.strictEqual(
activityLink.textContent.trim(),
I18n.t("user.activity_stream"),
"activity link has the right label"
);
assert.ok(
activityLink.querySelector(".d-icon-stream"),
"activity link has the right icon"
);
const invitesLink = query("#quick-access-profile ul li.invites a");
assert.ok(
invitesLink.href.endsWith("/u/eviltrout/invited"),
"has a link to the invites page of the user"
);
assert.strictEqual(
invitesLink.textContent.trim(),
I18n.t("user.invited.title"),
"invites link has the right label"
);
assert.ok(
invitesLink.querySelector(".d-icon-user-plus"),
"invites link has the right icon"
);
await click("header.d-header"); // close the menu
updateCurrentUser({ can_invite_to_forum: false });
await click(".d-header-icons .current-user");
await click("#user-menu-button-profile");
assert.notOk(
exists("#quick-access-profile ul li.invites"),
"invites link not shown when the user can't invite"
);
const dratsLink = query("#quick-access-profile ul li.drafts a");
assert.ok(
dratsLink.href.endsWith("/u/eviltrout/activity/drafts"),
"has a link to the drafts page of the user"
);
assert.strictEqual(
dratsLink.textContent.trim(),
I18n.t("drafts.label_with_count", { count: 13 }),
"drafts link has the right label with count of the user's drafts"
);
assert.ok(
dratsLink.querySelector(".d-icon-pencil-alt"),
"drafts link has the right icon"
);
const preferencesLink = query("#quick-access-profile ul li.preferences a");
assert.ok(
preferencesLink.href.endsWith("/u/eviltrout/preferences"),
"has a link to the preferences page of the user"
);
assert.strictEqual(
preferencesLink.textContent.trim(),
I18n.t("user.preferences"),
"preferences link has the right label"
);
assert.ok(
preferencesLink.querySelector(".d-icon-cog"),
"preferences link has the right icon"
);
let doNotDisturbButton = query(
"#quick-access-profile ul li.do-not-disturb .btn"
);
assert.strictEqual(
doNotDisturbButton.textContent
.replaceAll(/\s+/g, " ")
.replaceAll(/\u200B/g, "")
.trim(),
I18n.t("pause_notifications.label"),
"Do Not Disturb button has the right label"
);
assert.ok(
doNotDisturbButton.querySelector(".d-icon-toggle-off"),
"Do Not Disturb button has the right icon"
);
await click("header.d-header"); // close the menu
const date = new Date();
date.setHours(date.getHours() + 2);
updateCurrentUser({ do_not_disturb_until: date.toISOString() });
await click(".d-header-icons .current-user");
await click("#user-menu-button-profile");
doNotDisturbButton = query(
"#quick-access-profile ul li.do-not-disturb .btn"
);
assert.strictEqual(
doNotDisturbButton.textContent
.replaceAll(/\s+/g, " ")
.replaceAll(/\u200B/g, "")
.trim(),
`${I18n.t("pause_notifications.label")} 2h`,
"Do Not Disturb button has the right label when Do Not Disturb is enabled"
);
assert.ok(
doNotDisturbButton.querySelector(".d-icon-toggle-on"),
"Do Not Disturb button has the right icon when Do Not Disturb is enabled"
);
let toggleAnonButton = query(
"#quick-access-profile ul li.enable-anonymous .btn"
);
assert.strictEqual(
toggleAnonButton.textContent
.replaceAll(/\s+/g, " ")
.replaceAll(/\u200B/g, "")
.trim(),
I18n.t("switch_to_anon"),
"toggle anonymous button has the right label when the user isn't anonymous"
);
assert.ok(
toggleAnonButton.querySelector(".d-icon-user-secret"),
"toggle anonymous button has the right icon when the user isn't anonymous"
);
await click("header.d-header"); // close the menu
updateCurrentUser({ is_anonymous: true });
await click(".d-header-icons .current-user");
await click("#user-menu-button-profile");
toggleAnonButton = query(
"#quick-access-profile ul li.disable-anonymous .btn"
);
assert.strictEqual(
toggleAnonButton.textContent
.replaceAll(/\s+/g, " ")
.replaceAll(/\u200B/g, "")
.trim(),
I18n.t("switch_from_anon"),
"toggle anonymous button has the right label when the user is anonymous"
);
assert.ok(
toggleAnonButton.querySelector(".d-icon-ban"),
"toggle anonymous button has the right icon when the user is anonymous"
);
await click("header.d-header"); // close the menu
updateCurrentUser({ is_anonymous: false, trust_level: 2 });
await click(".d-header-icons .current-user");
await click("#user-menu-button-profile");
assert.notOk(
exists("#quick-access-profile ul li.enable-anonymous"),
"toggle anon button isn't shown when the user can't use it"
);
assert.notOk(
exists("#quick-access-profile ul li.disable-anonymous"),
"toggle anon button isn't shown when the user can't use it"
);
await click("header.d-header"); // close the menu
updateCurrentUser({ is_anonymous: true, trust_level: 2 });
this.siteSettings.allow_anonymous_posting = false;
this.siteSettings.anonymous_posting_min_trust_level = 3;
await click(".d-header-icons .current-user");
await click("#user-menu-button-profile");
assert.ok(
exists("#quick-access-profile ul li.disable-anonymous"),
"toggle anon button is always shown if the user is anonymous"
);
await click("header.d-header"); // close the menu
updateCurrentUser({ is_anonymous: false, trust_level: 4 });
this.siteSettings.allow_anonymous_posting = false;
this.siteSettings.anonymous_posting_min_trust_level = 3;
await click(".d-header-icons .current-user");
await click("#user-menu-button-profile");
assert.notOk(
exists("#quick-access-profile ul li.enable-anonymous"),
"toggle anon button is not shown if the allow_anonymous_posting setting is false"
);
await click("header.d-header"); // close the menu
updateCurrentUser({ is_anonymous: false, trust_level: 2 });
this.siteSettings.allow_anonymous_posting = true;
this.siteSettings.anonymous_posting_min_trust_level = 3;
await click(".d-header-icons .current-user");
await click("#user-menu-button-profile");
assert.notOk(
exists("#quick-access-profile ul li.enable-anonymous"),
"toggle anon button is not shown if the user doesn't have a high enough trust level"
);
const logoutButton = query("#quick-access-profile ul li.logout .btn");
assert.strictEqual(
logoutButton.textContent
.replaceAll(/\s+/g, " ")
.replaceAll(/\u200B/g, "")
.trim(),
I18n.t("user.log_out"),
"logout button has the right label"
);
assert.ok(
logoutButton.querySelector(".d-icon-sign-out-alt"),
"logout button has the right icon"
);
});
test("the active tab can be clicked again to navigate to a page", async function (assert) {
updateCurrentUser({ reviewable_count: 1 });
withPluginApi("0.1", (api) => {
api.registerUserMenuTab((UserMenuTab) => {
return class extends UserMenuTab {
get id() {
return "custom-tab-1";
}
get icon() {
return "wrench";
}
get panelComponent() {
return "d-button";
}
get linkWhenActive() {
return "/u/eviltrout/preferences";
}
};
});
api.registerUserMenuTab((UserMenuTab) => {
return class extends UserMenuTab {
get id() {
return "custom-tab-2";
}
get icon() {
return "plus";
}
get panelComponent() {
return "d-button";
}
};
});
});
await visit("/");
await click(".d-header-icons .current-user");
await click("#user-menu-button-all-notifications");
assert.strictEqual(
currentURL(),
"/u/eviltrout/notifications",
"clicking on active tab navigates to the page it links to"
);
assert.notOk(exists(".user-menu"), "user menu is closed after navigating");
const tabs = [
["#user-menu-button-custom-tab-1", "/u/eviltrout/preferences/account"],
["#user-menu-button-replies", "/u/eviltrout/notifications/responses"],
["#user-menu-button-messages", "/u/eviltrout/messages"],
["#user-menu-button-bookmarks", "/u/eviltrout/activity/bookmarks"],
["#user-menu-button-likes", "/u/eviltrout/notifications/likes-received"],
["#user-menu-button-custom-tab-2", null],
["#user-menu-button-review-queue", "/review"],
["#user-menu-button-profile", "/u/eviltrout/summary"],
];
for (const [id, expectedLink] of tabs) {
await click(".d-header-icons .current-user");
await click(id);
await click(id);
if (expectedLink) {
assert.strictEqual(
currentURL(),
expectedLink,
`clicking on the ${id} tab navigates to ${expectedLink}`
);
assert.notOk(
exists(".user-menu"),
"user menu is closed after navigating"
);
} else {
assert.ok(
exists(".user-menu"),
"user menu remains open if tab doesn't link to anywhere"
);
}
await click("#site-logo");
}
});
});
acceptance("User menu - Dismiss button", function (needs) {
needs.user({
redesigned_user_menu_enabled: true,
unread_high_priority_notifications: 10,
grouped_unread_notifications: {
[NOTIFICATION_TYPES.bookmark_reminder]: 103,
[NOTIFICATION_TYPES.private_message]: 89,
[NOTIFICATION_TYPES.votes_released]: 1,
[NOTIFICATION_TYPES.code_review_commit_approved]: 3,
},
});
let markRead = false;
let markReadRequestBody;
needs.pretender((server, helper) => {
server.put("/notifications/mark-read", (request) => {
markReadRequestBody = request.requestBody;
markRead = true;
return helper.response({ success: true });
});
server.get("/u/eviltrout/user-menu-bookmarks", () => {
if (markRead) {
const copy = cloneJSON(
UserMenuFixtures["/u/:username/user-menu-bookmarks"]
);
copy.notifications = [];
return helper.response(copy);
} else {
return helper.response(
UserMenuFixtures["/u/:username/user-menu-bookmarks"]
);
}
});
server.get("/u/eviltrout/user-menu-private-messages", () => {
if (markRead) {
const copy = cloneJSON(
UserMenuFixtures["/u/:username/user-menu-private-messages"]
);
copy.unread_notifications = [];
return helper.response(copy);
} else {
return helper.response(
UserMenuFixtures["/u/:username/user-menu-private-messages"]
);
}
});
});
needs.hooks.afterEach(() => {
markRead = false;
markReadRequestBody = null;
});
test("shows confirmation modal for the all-notifications list", async function (assert) {
await visit("/");
await click(".d-header-icons .current-user");
await click(".user-menu .notifications-dismiss");
assert.strictEqual(
query(".dismiss-notification-confirmation").textContent.trim(),
I18n.t("notifications.dismiss_confirmation.body.default", { count: 10 }),
"confirmation modal is shown when there are unread high pri notifications"
);
await click(".modal-footer .btn-default"); // click cancel on the dismiss modal
assert.notOk(markRead, "mark-read request isn't sent");
await click(".user-menu .notifications-dismiss");
await click(".modal-footer .btn-primary"); // click confirm on the dismiss modal
assert.ok(markRead, "mark-read request is sent");
});
test("shows confirmation modal for the bookmarks list", async function (assert) {
await visit("/");
await click(".d-header-icons .current-user");
assert.strictEqual(
query("#user-menu-button-bookmarks .badge-notification").textContent,
"103",
"bookmarks tab has bubble with count"
);
await click("#user-menu-button-bookmarks");
assert.ok(
exists("#quick-access-bookmarks ul li.notification"),
"bookmark reminder notifications are visible"
);
assert.ok(
exists("#quick-access-bookmarks ul li.bookmark"),
"bookmarks are visible"
);
await click(".user-menu .notifications-dismiss");
assert.strictEqual(
query(".dismiss-notification-confirmation").textContent.trim(),
I18n.t("notifications.dismiss_confirmation.body.bookmarks", {
count: 103,
}),
"confirmation modal is shown when there are unread bookmark reminder notifications"
);
assert.notOk(markRead, "mark-read request isn't sent");
await click(".modal-footer .btn-primary"); // confirm dismiss on the dismiss modal
assert.notOk(
exists("#quick-access-bookmarks ul li.notification"),
"bookmark reminder notifications are gone"
);
assert.ok(
exists("#quick-access-bookmarks ul li.bookmark"),
"bookmarks are still visible"
);
assert.notOk(
exists("#user-menu-button-bookmarks .badge-notification"),
"bookmarks tab no longer has bubble"
);
assert.ok(markRead, "mark-read request is sent");
assert.strictEqual(
markReadRequestBody,
"dismiss_types=bookmark_reminder",
"mark-read request specifies bookmark_reminder types"
);
assert.notOk(exists(".user-menu .notifications-dismiss"));
});
test("shows confirmation modal for the messages list", async function (assert) {
await visit("/");
await click(".d-header-icons .current-user");
assert.strictEqual(
query("#user-menu-button-messages .badge-notification").textContent,
"89",
"messages tab has bubble with count"
);
await click("#user-menu-button-messages");
assert.ok(
exists("#quick-access-messages ul li.notification"),
"messages notifications are visible"
);
assert.ok(
exists("#quick-access-messages ul li.message"),
"messages are visible"
);
await click(".user-menu .notifications-dismiss");
assert.strictEqual(
query(".dismiss-notification-confirmation").textContent.trim(),
I18n.t("notifications.dismiss_confirmation.body.messages", {
count: 89,
}),
"confirmation modal is shown when there are unread messages notifications"
);
assert.notOk(markRead, "mark-read request isn't sent");
await click(".modal-footer .btn-primary"); // confirm dismiss on the dismiss modal
assert.notOk(
exists("#quick-access-messages ul li.notification"),
"messages notifications are gone"
);
assert.ok(
exists("#quick-access-messages ul li.message"),
"messages are still visible"
);
assert.notOk(
exists("#user-menu-button-messages .badge-notification"),
"messages tab no longer has bubble"
);
assert.ok(markRead, "mark-read request is sent");
assert.strictEqual(
markReadRequestBody,
"dismiss_types=private_message%2Cgroup_message_summary",
"mark-read request specifies private_message types"
);
assert.notOk(exists(".user-menu .notifications-dismiss"));
});
test("doesn't show confirmation modal for the likes notifications list", async function (assert) {
await visit("/");
await click(".d-header-icons .current-user");
await click("#user-menu-button-likes");
await click(".user-menu .notifications-dismiss");
assert.ok(
markRead,
"mark-read request is sent without a confirmation modal"
);
});
test("doesn't show confirmation modal for the other notifications list", async function (assert) {
await visit("/");
await click(".d-header-icons .current-user");
await click("#user-menu-button-other-notifications");
let othersBadgeNotification = query(
"#user-menu-button-other-notifications .badge-notification"
);
assert.strictEqual(
othersBadgeNotification.textContent.trim(),
"4",
"badge shows the right count"
);
await click(".user-menu .notifications-dismiss");
assert.ok(
!exists("#user-menu-button-other-notifications .badge-notification")
);
assert.ok(
markRead,
"mark-read request is sent without a confirmation modal"
);
});
});