Remove old component, tests and snapshot

This commit is contained in:
David Langley 2026-01-30 16:27:18 +00:00
parent fa1a874f2b
commit b21485fd9b
3 changed files with 0 additions and 385 deletions

View File

@ -1,89 +0,0 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
import React, { type HTMLProps, type JSX } from "react";
import {
MentionIcon,
ErrorIcon,
NotificationsOffSolidIcon,
VideoCallSolidIcon,
EmailSolidIcon,
VoiceCallSolidIcon,
} from "@vector-im/compound-design-tokens/assets/web/icons";
import { UnreadCounter, Unread } from "@vector-im/compound-web";
import { CallType } from "matrix-js-sdk/src/webrtc/call";
import { Flex } from "@element-hq/web-shared-components";
import { type RoomNotificationState } from "../../../stores/notifications/RoomNotificationState";
import { useTypedEventEmitterState } from "../../../hooks/useEventEmitter";
import { NotificationStateEvents } from "../../../stores/notifications/NotificationState";
interface NotificationDecorationProps extends HTMLProps<HTMLDivElement> {
/**
* The notification state of the room or thread.
*/
notificationState: RoomNotificationState;
/**
* Whether the room has a voice or video call.
*/
callType?: CallType;
}
/**
* Displays the notification decoration for a room or a thread.
*/
export function NotificationDecoration({
notificationState,
callType,
...props
}: NotificationDecorationProps): JSX.Element | null {
// Listen to the notification state and update the component when it changes
const {
hasAnyNotificationOrActivity,
isUnsentMessage,
invited,
isMention,
isActivityNotification,
isNotification,
count,
muted,
} = useTypedEventEmitterState(notificationState, NotificationStateEvents.Update, () => ({
hasAnyNotificationOrActivity: notificationState.hasAnyNotificationOrActivity,
isUnsentMessage: notificationState.isUnsentMessage,
invited: notificationState.invited,
isMention: notificationState.isMention,
isActivityNotification: notificationState.isActivityNotification,
isNotification: notificationState.isNotification,
count: notificationState.count,
muted: notificationState.muted,
}));
if (!hasAnyNotificationOrActivity && !muted && !callType) return null;
return (
<Flex
align="center"
justify="center"
gap="var(--cpd-space-1x)"
{...props}
data-testid="notification-decoration"
>
{isUnsentMessage && <ErrorIcon width="20px" height="20px" fill="var(--cpd-color-icon-critical-primary)" />}
{callType === CallType.Video && (
<VideoCallSolidIcon width="20px" height="20px" fill="var(--cpd-color-icon-accent-primary)" />
)}
{callType === CallType.Voice && (
<VoiceCallSolidIcon width="20px" height="20px" fill="var(--cpd-color-icon-accent-primary)" />
)}
{invited && <EmailSolidIcon width="20px" height="20px" fill="var(--cpd-color-icon-accent-primary)" />}
{isMention && <MentionIcon width="20px" height="20px" fill="var(--cpd-color-icon-accent-primary)" />}
{(isMention || isNotification) && <UnreadCounter count={count || null} />}
{isActivityNotification && <Unread />}
{muted && <NotificationsOffSolidIcon width="20px" height="20px" fill="var(--cpd-color-icon-tertiary)" />}
</Flex>
);
}

View File

@ -1,109 +0,0 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { render, screen } from "jest-matrix-react";
import { CallType } from "matrix-js-sdk/src/webrtc/call";
import { RoomNotificationState } from "../../../../../src/stores/notifications/RoomNotificationState";
import { NotificationDecoration } from "../../../../../src/components/views/rooms/NotificationDecoration";
import { createTestClient, mkStubRoom } from "../../../../test-utils";
describe("<NotificationDecoration />", () => {
let roomNotificationState: RoomNotificationState;
beforeEach(() => {
const matrixClient = createTestClient();
const room = mkStubRoom("roomId", "roomName", matrixClient);
roomNotificationState = new RoomNotificationState(room, false);
});
it("should not render if RoomNotificationState.hasAnyNotificationOrActivity=true", () => {
jest.spyOn(roomNotificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(false);
render(<NotificationDecoration notificationState={roomNotificationState} callType={undefined} />);
expect(screen.queryByTestId("notification-decoration")).toBeNull();
});
it("should render the unset message decoration", () => {
jest.spyOn(roomNotificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(true);
jest.spyOn(roomNotificationState, "isUnsentMessage", "get").mockReturnValue(true);
const { asFragment } = render(
<NotificationDecoration notificationState={roomNotificationState} callType={undefined} />,
);
expect(asFragment()).toMatchSnapshot();
});
it("should render the invitation decoration", () => {
jest.spyOn(roomNotificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(true);
jest.spyOn(roomNotificationState, "invited", "get").mockReturnValue(true);
const { asFragment } = render(
<NotificationDecoration notificationState={roomNotificationState} callType={undefined} />,
);
expect(asFragment()).toMatchSnapshot();
});
it("should render the mention decoration", () => {
jest.spyOn(roomNotificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(true);
jest.spyOn(roomNotificationState, "isMention", "get").mockReturnValue(true);
jest.spyOn(roomNotificationState, "count", "get").mockReturnValue(1);
const { asFragment } = render(
<NotificationDecoration notificationState={roomNotificationState} callType={undefined} />,
);
expect(asFragment()).toMatchSnapshot();
});
it("should render the notification decoration", () => {
jest.spyOn(roomNotificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(true);
jest.spyOn(roomNotificationState, "isNotification", "get").mockReturnValue(true);
jest.spyOn(roomNotificationState, "count", "get").mockReturnValue(1);
const { asFragment } = render(
<NotificationDecoration notificationState={roomNotificationState} callType={undefined} />,
);
expect(asFragment()).toMatchSnapshot();
});
it("should render the notification decoration without count", () => {
jest.spyOn(roomNotificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(true);
jest.spyOn(roomNotificationState, "isNotification", "get").mockReturnValue(true);
jest.spyOn(roomNotificationState, "count", "get").mockReturnValue(0);
const { asFragment } = render(
<NotificationDecoration notificationState={roomNotificationState} callType={undefined} />,
);
expect(asFragment()).toMatchSnapshot();
});
it("should render the activity decoration", () => {
jest.spyOn(roomNotificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(true);
jest.spyOn(roomNotificationState, "isActivityNotification", "get").mockReturnValue(true);
const { asFragment } = render(
<NotificationDecoration notificationState={roomNotificationState} callType={undefined} />,
);
expect(asFragment()).toMatchSnapshot();
});
it("should render the muted decoration", () => {
jest.spyOn(roomNotificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(true);
jest.spyOn(roomNotificationState, "muted", "get").mockReturnValue(true);
const { asFragment } = render(
<NotificationDecoration notificationState={roomNotificationState} callType={undefined} />,
);
expect(asFragment()).toMatchSnapshot();
});
it("should render the video call decoration", () => {
jest.spyOn(roomNotificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(false);
const { asFragment } = render(
<NotificationDecoration notificationState={roomNotificationState} callType={CallType.Video} />,
);
expect(asFragment()).toMatchSnapshot();
});
it("should render the audio call decoration", () => {
jest.spyOn(roomNotificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(false);
const { asFragment } = render(
<NotificationDecoration notificationState={roomNotificationState} callType={CallType.Voice} />,
);
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,187 +0,0 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`<NotificationDecoration /> should render the activity decoration 1`] = `
<DocumentFragment>
<div
class="_flex_4dswl_9"
data-testid="notification-decoration"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
>
<div
class="_unread_cti0f_8"
>
<div />
</div>
</div>
</DocumentFragment>
`;
exports[`<NotificationDecoration /> should render the audio call decoration 1`] = `
<DocumentFragment>
<div
class="_flex_4dswl_9"
data-testid="notification-decoration"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
>
<svg
fill="var(--cpd-color-icon-accent-primary)"
height="20px"
viewBox="0 0 24 24"
width="20px"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m20.958 16.374.039 3.527q0 .427-.33.756-.33.33-.756.33a16 16 0 0 1-6.57-1.105 16.2 16.2 0 0 1-5.563-3.663 16.1 16.1 0 0 1-3.653-5.573 16.3 16.3 0 0 1-1.115-6.56q0-.427.33-.757T4.095 3l3.528.039a1.07 1.07 0 0 1 1.085.93l.543 3.954q.039.271-.039.504a1.1 1.1 0 0 1-.271.426l-1.64 1.64q.505 1.008 1.154 1.909c.433.6 1.444 1.696 1.444 1.696s1.095 1.01 1.696 1.444q.9.65 1.909 1.153l1.64-1.64q.193-.193.426-.27t.504-.04l3.954.543q.406.059.668.359t.262.727"
/>
</svg>
</div>
</DocumentFragment>
`;
exports[`<NotificationDecoration /> should render the invitation decoration 1`] = `
<DocumentFragment>
<div
class="_flex_4dswl_9"
data-testid="notification-decoration"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
>
<svg
fill="var(--cpd-color-icon-accent-primary)"
height="20px"
viewBox="0 0 24 24"
width="20px"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2m0 5.111a1 1 0 0 0 .514.874l7 3.89a1 1 0 0 0 .972 0l7-3.89a1 1 0 1 0-.972-1.748L12 11.856 5.486 8.237A1 1 0 0 0 4 9.111"
/>
</svg>
</div>
</DocumentFragment>
`;
exports[`<NotificationDecoration /> should render the mention decoration 1`] = `
<DocumentFragment>
<div
class="_flex_4dswl_9"
data-testid="notification-decoration"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
>
<svg
fill="var(--cpd-color-icon-accent-primary)"
height="20px"
viewBox="0 0 24 24"
width="20px"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 4a8 8 0 1 0 0 16 1 1 0 1 1 0 2C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10v1.5a3.5 3.5 0 0 1-6.396 1.966A5 5 0 1 1 17 12v1.5a1.5 1.5 0 0 0 3 0V12a8 8 0 0 0-8-8m3 8a3 3 0 1 0-6 0 3 3 0 0 0 6 0"
/>
</svg>
<span
class="_unread-counter_1147r_8"
>
1
</span>
</div>
</DocumentFragment>
`;
exports[`<NotificationDecoration /> should render the muted decoration 1`] = `
<DocumentFragment>
<div
class="_flex_4dswl_9"
data-testid="notification-decoration"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
>
<svg
fill="var(--cpd-color-icon-tertiary)"
height="20px"
viewBox="0 0 24 24"
width="20px"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m4.917 2.083 17 17a1 1 0 0 1-1.414 1.414L19.006 19H4.414c-.89 0-1.337-1.077-.707-1.707L5 16v-6s0-2.034 1.096-3.91L3.504 3.498a1 1 0 0 1 1.414-1.414M19 13.35 9.136 3.484C9.93 3.181 10.874 3 12 3c7 0 7 7 7 7z"
/>
<path
d="M10 20h4a2 2 0 0 1-4 0"
/>
</svg>
</div>
</DocumentFragment>
`;
exports[`<NotificationDecoration /> should render the notification decoration 1`] = `
<DocumentFragment>
<div
class="_flex_4dswl_9"
data-testid="notification-decoration"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
>
<span
class="_unread-counter_1147r_8"
>
1
</span>
</div>
</DocumentFragment>
`;
exports[`<NotificationDecoration /> should render the notification decoration without count 1`] = `
<DocumentFragment>
<div
class="_flex_4dswl_9"
data-testid="notification-decoration"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
>
<div
class="_unread-counter_1147r_8"
/>
</div>
</DocumentFragment>
`;
exports[`<NotificationDecoration /> should render the unset message decoration 1`] = `
<DocumentFragment>
<div
class="_flex_4dswl_9"
data-testid="notification-decoration"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
>
<svg
fill="var(--cpd-color-icon-critical-primary)"
height="20px"
viewBox="0 0 24 24"
width="20px"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 17q.424 0 .713-.288A.97.97 0 0 0 13 16a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 15a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 16q0 .424.287.712.288.288.713.288m0-4q.424 0 .713-.287A.97.97 0 0 0 13 12V8a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 7a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 8v4q0 .424.287.713.288.287.713.287m0 9a9.7 9.7 0 0 1-3.9-.788 10.1 10.1 0 0 1-3.175-2.137q-1.35-1.35-2.137-3.175A9.7 9.7 0 0 1 2 12q0-2.075.788-3.9a10.1 10.1 0 0 1 2.137-3.175q1.35-1.35 3.175-2.137A9.7 9.7 0 0 1 12 2q2.075 0 3.9.788a10.1 10.1 0 0 1 3.175 2.137q1.35 1.35 2.137 3.175A9.7 9.7 0 0 1 22 12a9.7 9.7 0 0 1-.788 3.9 10.1 10.1 0 0 1-2.137 3.175q-1.35 1.35-3.175 2.137A9.7 9.7 0 0 1 12 22m0-2q3.35 0 5.675-2.325T20 12t-2.325-5.675T12 4 6.325 6.325 4 12t2.325 5.675T12 20"
/>
</svg>
</div>
</DocumentFragment>
`;
exports[`<NotificationDecoration /> should render the video call decoration 1`] = `
<DocumentFragment>
<div
class="_flex_4dswl_9"
data-testid="notification-decoration"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
>
<svg
fill="var(--cpd-color-icon-accent-primary)"
height="20px"
viewBox="0 0 24 24"
width="20px"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6 4h10a2 2 0 0 1 2 2v4.286l3.35-2.871a1 1 0 0 1 1.65.76v7.65a1 1 0 0 1-1.65.76L18 13.715V18a2 2 0 0 1-2 2H6a4 4 0 0 1-4-4V8a4 4 0 0 1 4-4"
/>
</svg>
</div>
</DocumentFragment>
`;