Files
element-call/src/useReactions.test.tsx
T

174 lines
5.9 KiB
TypeScript
Raw Normal View History

2024-11-04 08:54:13 -01:00
/*
Copyright 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
2024-11-08 17:36:40 +00:00
import { render } from "@testing-library/react";
import { act, FC } from "react";
2024-11-04 08:54:13 -01:00
import { describe, expect, test } from "vitest";
2024-11-08 17:36:40 +00:00
import { RoomEvent } from "matrix-js-sdk/src/matrix";
2024-11-04 08:54:13 -01:00
2024-11-08 17:36:40 +00:00
import { useReactions } from "./useReactions";
import {
createHandRaisedReaction,
createRedaction,
MockRoom,
MockRTCSession,
TestReactionsWrapper,
} from "./utils/testReactions";
2024-11-04 08:54:13 -01:00
const memberUserIdAlice = "@alice:example.org";
const memberEventAlice = "$membership-alice:example.org";
const memberUserIdBob = "@bob:example.org";
const memberEventBob = "$membership-bob:example.org";
const membership: Record<string, string> = {
[memberEventAlice]: memberUserIdAlice,
[memberEventBob]: memberUserIdBob,
"$membership-charlie:example.org": "@charlie:example.org",
};
2024-11-08 17:36:40 +00:00
/**
* Test explanation.
* This test suite checks that the useReactions hook appropriately reacts
* to new reactions, redactions and membership changesin the room. There is
* a large amount of test structure used to construct a mock environment.
*/
2024-11-04 08:54:13 -01:00
const TestComponent: FC = () => {
const { raisedHands } = useReactions();
2024-11-04 08:54:13 -01:00
return (
<div>
<ul>
{Object.entries(raisedHands).map(([userId, date]) => (
<li key={userId}>
<span>{userId}</span>
<time>{date.getTime()}</time>
</li>
))}
</ul>
</div>
);
};
describe("useReactions", () => {
test("starts with an empty list", () => {
2024-11-08 17:36:40 +00:00
const rtcSession = new MockRTCSession(
new MockRoom(memberUserIdAlice),
membership,
);
2024-11-04 08:54:13 -01:00
const { queryByRole } = render(
2024-11-08 17:36:40 +00:00
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestReactionsWrapper>,
2024-11-04 08:54:13 -01:00
);
expect(queryByRole("list")?.children).to.have.lengthOf(0);
});
test("handles incoming raised hand", async () => {
2024-11-08 17:36:40 +00:00
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
2024-11-04 08:54:13 -01:00
const { queryByRole } = render(
2024-11-08 17:36:40 +00:00
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestReactionsWrapper>,
2024-11-04 08:54:13 -01:00
);
2024-11-08 17:36:40 +00:00
await act(() => room.testSendHandRaise(memberEventAlice, membership));
2024-11-04 08:54:13 -01:00
expect(queryByRole("list")?.children).to.have.lengthOf(1);
2024-11-08 17:36:40 +00:00
await act(() => room.testSendHandRaise(memberEventBob, membership));
2024-11-04 08:54:13 -01:00
expect(queryByRole("list")?.children).to.have.lengthOf(2);
});
test("handles incoming unraised hand", async () => {
2024-11-08 17:36:40 +00:00
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
2024-11-04 08:54:13 -01:00
const { queryByRole } = render(
2024-11-08 17:36:40 +00:00
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestReactionsWrapper>,
2024-11-04 08:54:13 -01:00
);
const reactionEventId = await act(() =>
2024-11-08 17:36:40 +00:00
room.testSendHandRaise(memberEventAlice, membership),
2024-11-04 08:54:13 -01:00
);
expect(queryByRole("list")?.children).to.have.lengthOf(1);
await act(() =>
room.emit(
RoomEvent.Redaction,
createRedaction(memberUserIdAlice, reactionEventId),
room,
undefined,
),
);
expect(queryByRole("list")?.children).to.have.lengthOf(0);
});
test("handles loading prior raised hand events", () => {
2024-11-08 17:36:40 +00:00
const room = new MockRoom(memberUserIdAlice, [
createHandRaisedReaction(memberEventAlice, membership),
]);
const rtcSession = new MockRTCSession(room, membership);
2024-11-04 08:54:13 -01:00
const { queryByRole } = render(
2024-11-08 17:36:40 +00:00
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestReactionsWrapper>,
2024-11-04 08:54:13 -01:00
);
expect(queryByRole("list")?.children).to.have.lengthOf(1);
});
// If the membership event changes for a user, we want to remove
// the raised hand event.
test("will remove reaction when a member leaves the call", () => {
2024-11-08 17:36:40 +00:00
const room = new MockRoom(memberUserIdAlice, [
createHandRaisedReaction(memberEventAlice, membership),
]);
const rtcSession = new MockRTCSession(room, membership);
2024-11-04 08:54:13 -01:00
const { queryByRole } = render(
2024-11-08 17:36:40 +00:00
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestReactionsWrapper>,
2024-11-04 08:54:13 -01:00
);
expect(queryByRole("list")?.children).to.have.lengthOf(1);
act(() => rtcSession.testRemoveMember(memberUserIdAlice));
expect(queryByRole("list")?.children).to.have.lengthOf(0);
});
test("will remove reaction when a member joins via a new event", () => {
2024-11-08 17:36:40 +00:00
const room = new MockRoom(memberUserIdAlice, [
createHandRaisedReaction(memberEventAlice, membership),
]);
const rtcSession = new MockRTCSession(room, membership);
2024-11-04 08:54:13 -01:00
const { queryByRole } = render(
2024-11-08 17:36:40 +00:00
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestReactionsWrapper>,
2024-11-04 08:54:13 -01:00
);
expect(queryByRole("list")?.children).to.have.lengthOf(1);
// Simulate leaving and rejoining
act(() => {
rtcSession.testRemoveMember(memberUserIdAlice);
rtcSession.testAddMember(memberUserIdAlice);
});
expect(queryByRole("list")?.children).to.have.lengthOf(0);
});
test("ignores invalid sender for historic event", () => {
2024-11-08 17:36:40 +00:00
const room = new MockRoom(memberUserIdAlice, [
createHandRaisedReaction(memberEventAlice, memberUserIdBob),
2024-11-04 08:54:13 -01:00
]);
2024-11-08 17:36:40 +00:00
const rtcSession = new MockRTCSession(room, membership);
2024-11-04 08:54:13 -01:00
const { queryByRole } = render(
2024-11-08 17:36:40 +00:00
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestReactionsWrapper>,
2024-11-04 08:54:13 -01:00
);
expect(queryByRole("list")?.children).to.have.lengthOf(0);
});
test("ignores invalid sender for new event", async () => {
2024-11-08 17:36:40 +00:00
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
2024-11-04 08:54:13 -01:00
const { queryByRole } = render(
2024-11-08 17:36:40 +00:00
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestReactionsWrapper>,
2024-11-04 08:54:13 -01:00
);
2024-11-08 17:36:40 +00:00
await act(() => room.testSendHandRaise(memberEventAlice, memberUserIdBob));
2024-11-04 08:54:13 -01:00
expect(queryByRole("list")?.children).to.have.lengthOf(0);
});
});