Refactor UnreadNotificationBadge to shared MVVM view (#33672)

* Refactor notification badge to shared MVVM view

* Bage icons Images

* Narrow unread notification badge refactor scope

* Align unread badge MVVM pattern

* Reduce unread badge viewmodel duplication

* Document unread badge viewmodel props

* Remove legacy badge classes from shared view

* Update css for knocked door

* Update thread badge e2e selector

* Update read receipt badge e2e selectors
This commit is contained in:
Zack
2026-06-15 10:20:27 +00:00
committed by GitHub
parent 5bcec9112e
commit 0f0f8c6ba2
19 changed files with 655 additions and 24 deletions
@@ -1007,21 +1007,25 @@ describe("EventTile", () => {
const { container } = getComponent({}, TimelineRenderingType.ThreadsList);
// By default, the thread will assume it is read.
expect(container.getElementsByClassName("mx_NotificationBadge")).toHaveLength(0);
expect(container.querySelectorAll('[data-testid="notification-badge"]')).toHaveLength(0);
act(() => {
room.setThreadUnreadNotificationCount(mxEvent.getId()!, NotificationCountType.Total, 3);
});
expect(container.getElementsByClassName("mx_NotificationBadge")).toHaveLength(1);
expect(container.getElementsByClassName("mx_NotificationBadge_level_highlight")).toHaveLength(0);
let badges = container.querySelectorAll('[data-testid="notification-badge"]');
expect(badges).toHaveLength(1);
expect(badges[0]).toHaveAttribute("data-badge-type", "dot");
expect(badges[0]).toHaveAttribute("data-notification-level", "notification");
act(() => {
room.setThreadUnreadNotificationCount(mxEvent.getId()!, NotificationCountType.Highlight, 1);
});
expect(container.getElementsByClassName("mx_NotificationBadge")).toHaveLength(1);
expect(container.getElementsByClassName("mx_NotificationBadge_level_highlight")).toHaveLength(1);
badges = container.querySelectorAll('[data-testid="notification-badge"]');
expect(badges).toHaveLength(1);
expect(badges[0]).toHaveAttribute("data-badge-type", "dot");
expect(badges[0]).toHaveAttribute("data-notification-level", "highlight");
});
});
@@ -38,6 +38,10 @@ describe("UnreadNotificationBadge", () => {
return <UnreadNotificationBadge room={room} threadId={threadId} />;
}
function getBadge(container: HTMLElement): Element | null {
return container.querySelector('[data-testid="notification-badge"]');
}
beforeEach(() => {
client = stubClient();
client.supportsThreads = () => true;
@@ -84,27 +88,27 @@ describe("UnreadNotificationBadge", () => {
it("renders unread notification badge", () => {
const { container } = render(getComponent());
expect(container.querySelector(".mx_NotificationBadge_visible")).toBeTruthy();
expect(container.querySelector(".mx_NotificationBadge_level_highlight")).toBeFalsy();
expect(getBadge(container)).toHaveTextContent("1");
expect(getBadge(container)).toHaveAttribute("data-notification-level", "notification");
act(() => {
room.setUnreadNotificationCount(NotificationCountType.Highlight, 1);
});
expect(container.querySelector(".mx_NotificationBadge_level_highlight")).toBeTruthy();
expect(getBadge(container)).toHaveAttribute("data-notification-level", "highlight");
});
it("renders unread thread notification badge", () => {
const { container } = render(getComponent(THREAD_ID));
expect(container.querySelector(".mx_NotificationBadge_visible")).toBeTruthy();
expect(container.querySelector(".mx_NotificationBadge_level_highlight")).toBeFalsy();
expect(getBadge(container)).toHaveTextContent("1");
expect(getBadge(container)).toHaveAttribute("data-notification-level", "notification");
act(() => {
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 1);
});
expect(container.querySelector(".mx_NotificationBadge_level_highlight")).toBeTruthy();
expect(getBadge(container)).toHaveAttribute("data-notification-level", "highlight");
});
it("hides unread notification badge", () => {
@@ -112,7 +116,7 @@ describe("UnreadNotificationBadge", () => {
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total, 0);
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 0);
const { container } = render(getComponent(THREAD_ID));
expect(container.querySelector(".mx_NotificationBadge_visible")).toBeFalsy();
expect(getBadge(container)).toBeNull();
});
});
@@ -142,7 +146,7 @@ describe("UnreadNotificationBadge", () => {
muteRoom(room);
const { container } = render(getComponent());
expect(container.querySelector(".mx_NotificationBadge")).toBeNull();
expect(getBadge(container)).toBeNull();
});
it("activity renders unread notification badge", () => {
@@ -168,8 +172,8 @@ describe("UnreadNotificationBadge", () => {
room.addLiveEvents([event], { addToState: true });
const { container } = render(getComponent(THREAD_ID));
expect(container.querySelector(".mx_NotificationBadge_dot")).toBeTruthy();
expect(container.querySelector(".mx_NotificationBadge_visible")).toBeTruthy();
expect(container.querySelector(".mx_NotificationBadge_level_highlight")).toBeFalsy();
expect(getBadge(container)).toBeInTheDocument();
expect(getBadge(container)).toHaveAttribute("data-badge-type", "dot");
expect(getBadge(container)).not.toHaveAttribute("data-notification-level", "highlight");
});
});