Add tests for ReactionToggleButton

This commit is contained in:
Half-Shot
2024-11-05 17:00:58 +00:00
parent 2eb62d8e6f
commit 9ff8197987
5 changed files with 1077 additions and 26 deletions

View File

@@ -0,0 +1,195 @@
import { act, render } from "@testing-library/react";
import { expect, test } from "vitest";
import {
MockRoom,
MockRTCSession,
TestReactionsWrapper,
} from "../utils/testReactions";
import { ReactionToggleButton } from "./ReactionToggleButton";
import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc";
import { TooltipProvider } from "@vector-im/compound-web";
import { ElementCallReactionEventType } from "../reactions";
import { userEvent } from "@testing-library/user-event";
const memberUserIdAlice = "@alice:example.org";
const memberEventAlice = "$membership-alice:example.org";
const membership: Record<string, string> = {
[memberEventAlice]: memberUserIdAlice,
};
function TestComponent({
rtcSession,
room,
}: {
rtcSession: MockRTCSession;
room: MockRoom;
}) {
return (
<TooltipProvider>
<TestReactionsWrapper rtcSession={rtcSession}>
<ReactionToggleButton
rtcSession={rtcSession as unknown as MatrixRTCSession}
client={room.client}
></ReactionToggleButton>
</TestReactionsWrapper>
</TooltipProvider>
);
}
test("Can open menu", async () => {
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { getByRole, container } = render(
<TestComponent rtcSession={rtcSession} room={room} />,
);
act(() => getByRole("button").click());
expect(container).toMatchSnapshot();
});
test("Can close menu", async () => {
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { getByRole, container } = render(
<TestComponent rtcSession={rtcSession} room={room} />,
);
act(() => {
getByRole("button").click();
});
act(() => getByRole("button", { expanded: true }).click());
expect(container).toMatchSnapshot();
});
test("Can raise hand", async () => {
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { getByRole, getByText, container } = render(
<TestComponent rtcSession={rtcSession} room={room} />,
);
act(() => {
getByRole("button").click();
});
act(() => {
getByText("🖐️").click();
});
expect(room.testSentEvents).toEqual([
[
undefined,
"m.reaction",
{
"m.relates_to": {
event_id: memberEventAlice,
key: "🖐️",
rel_type: "m.annotation",
},
},
],
]);
expect(container).toMatchSnapshot();
});
test("Can can lower hand", async () => {
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { getByRole, getByText, container } = render(
<TestComponent rtcSession={rtcSession} room={room} />,
);
const reactionEvent = room.testSendReaction(memberEventAlice, membership);
act(() => {
getByRole("button").click();
});
act(() => {
getByText("🖐️").click();
});
expect(room.testRedactedEvents).toEqual([[undefined, reactionEvent]]);
expect(container).toMatchSnapshot();
});
test("Can react with emoji", async () => {
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { getByRole, getByText } = render(
<TestComponent rtcSession={rtcSession} room={room} />,
);
act(() => {
getByRole("button").click();
});
act(() => {
getByText("🐶").click();
});
expect(room.testSentEvents).toEqual([
[
undefined,
ElementCallReactionEventType,
{
"m.relates_to": {
event_id: memberEventAlice,
rel_type: "m.reference",
},
name: "dog",
emoji: "🐶",
},
],
]);
});
test("Can search for and send emoji", async () => {
const user = userEvent.setup();
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { getByText, getByRole, getByPlaceholderText, container } = render(
<TestComponent rtcSession={rtcSession} room={room} />,
);
act(() => {
getByRole("button").click();
});
act(() => {
getByRole("button", {
name: "Search",
}).click();
});
await act(async () => {
getByPlaceholderText("Search reactions…").focus();
await user.keyboard("crickets");
});
expect(container).toMatchSnapshot();
act(() => {
getByText("🦗").click();
});
expect(room.testSentEvents).toEqual([
[
undefined,
ElementCallReactionEventType,
{
"m.relates_to": {
event_id: memberEventAlice,
rel_type: "m.reference",
},
name: "crickets",
emoji: "🦗",
},
],
]);
});
test("Can close search", async () => {
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { getByRole, container } = render(
<TestComponent rtcSession={rtcSession} room={room} />,
);
act(() => {
getByRole("button").click();
});
act(() => {
getByRole("button", {
name: "Search",
}).click();
});
act(() => {
getByRole("button", {
name: "close search",
}).click();
});
expect(container).toMatchSnapshot();
});

View File

@@ -53,6 +53,7 @@ const InnerButton: FC<InnerButtonProps> = ({ raised, ...props }) => {
<Tooltip label={t("action.raise_hand_or_send_reaction")}>
<CpdButton
className={classNames(raised && styles.raisedButton)}
aria-expanded={raised}
kind={raised ? "primary" : "secondary"}
iconOnly
Icon={RaisedHandSolidIcon}
@@ -99,6 +100,8 @@ export function ReactionPopupMenu({
<Tooltip label={t("common.raise_hand")}>
<CpdButton
kind={isHandRaised ? "primary" : "secondary"}
aria-pressed={isHandRaised}
aria-label="Toggle hand raised"
className={styles.reactionButton}
key="raise-hand"
onClick={() => toggleRaisedHand()}
@@ -124,6 +127,7 @@ export function ReactionPopupMenu({
/>
<CpdButton
Icon={CloseIcon}
aria-label="close search"
size="sm"
kind="destructive"
onClick={() => setIsSearching(false)}
@@ -134,12 +138,11 @@ export function ReactionPopupMenu({
) : null}
<menu>
{filteredReactionSet.map((reaction) => (
<li className={styles.reactionPopupMenuItem}>
<li className={styles.reactionPopupMenuItem} key={reaction.name}>
<Tooltip label={reaction.name}>
<CpdButton
kind="secondary"
className={styles.reactionButton}
key={reaction.name}
disabled={!canReact}
onClick={() => sendRelation(reaction)}
>
@@ -153,6 +156,7 @@ export function ReactionPopupMenu({
<Tooltip label="Search">
<CpdButton
iconOnly
aria-label="Open reactions search"
Icon={SearchIcon}
kind="tertiary"
onClick={() => setIsSearching(true)}
@@ -196,7 +200,6 @@ export function ReactionToggleButton({
setBusy(true);
await client.sendEvent(
rtcSession.room.roomId,
null,
ElementCallReactionEventType,
{
"m.relates_to": {
@@ -206,7 +209,6 @@ export function ReactionToggleButton({
emoji: reaction.emoji,
name: reaction.name,
},
undefined,
);
// Do NOT close the menu after this.
} catch (ex) {

View File

@@ -0,0 +1,839 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Can can lower hand 1`] = `
<div>
<button
aria-disabled="true"
aria-expanded="true"
aria-labelledby=":r52:"
class="_button_i91xf_17 raisedButton _has-icon_i91xf_66 _icon-only_i91xf_59"
data-kind="primary"
data-size="lg"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 3a1 1 0 1 1 2 0v8.5a.5.5 0 0 0 1 0V4a1 1 0 1 1 2 0v10.2l3.284-2.597a1.081 1.081 0 0 1 1.47 1.577c-.613.673-1.214 1.367-1.818 2.064-1.267 1.463-2.541 2.934-3.944 4.235A6 6 0 0 1 5 15V7a1 1 0 0 1 2 0v5.5a.5.5 0 0 0 1 0V4a1 1 0 0 1 2 0v7.5a.5.5 0 0 0 1 0V3Z"
/>
</svg>
</button>
<div
class="reactionPopupMenu"
>
<section
class="handRaiseSection"
>
<button
aria-label="Toggle hand raised"
aria-labelledby=":r58:"
aria-pressed="true"
class="_button_i91xf_17 reactionButton"
data-kind="primary"
data-size="lg"
role="button"
tabindex="0"
>
🖐️
</button>
</section>
<div
class="verticalSeperator"
/>
<section>
<menu>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r5d:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
👍
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r5i:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🎉
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r5n:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
👏
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r5s:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🐶
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r61:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🐱
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r66:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
💡
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-label="Open reactions search"
aria-labelledby=":r6b:"
class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59"
data-kind="tertiary"
data-size="lg"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.05 16.463a7.5 7.5 0 1 1 1.414-1.414l3.243 3.244a1 1 0 0 1-1.414 1.414l-3.244-3.244ZM16 10.5a5.5 5.5 0 1 0-11 0 5.5 5.5 0 0 0 11 0Z"
/>
</svg>
</button>
</li>
</menu>
</section>
</div>
</div>
`;
exports[`Can close menu 1`] = `
<div>
<button
aria-disabled="false"
aria-expanded="false"
aria-labelledby=":r1m:"
class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 3a1 1 0 1 1 2 0v8.5a.5.5 0 0 0 1 0V4a1 1 0 1 1 2 0v10.2l3.284-2.597a1.081 1.081 0 0 1 1.47 1.577c-.613.673-1.214 1.367-1.818 2.064-1.267 1.463-2.541 2.934-3.944 4.235A6 6 0 0 1 5 15V7a1 1 0 0 1 2 0v5.5a.5.5 0 0 0 1 0V4a1 1 0 0 1 2 0v7.5a.5.5 0 0 0 1 0V3Z"
/>
</svg>
</button>
</div>
`;
exports[`Can close search 1`] = `
<div>
<button
aria-disabled="false"
aria-expanded="true"
aria-labelledby=":rba:"
class="_button_i91xf_17 raisedButton _has-icon_i91xf_66 _icon-only_i91xf_59"
data-kind="primary"
data-size="lg"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 3a1 1 0 1 1 2 0v8.5a.5.5 0 0 0 1 0V4a1 1 0 1 1 2 0v10.2l3.284-2.597a1.081 1.081 0 0 1 1.47 1.577c-.613.673-1.214 1.367-1.818 2.064-1.267 1.463-2.541 2.934-3.944 4.235A6 6 0 0 1 5 15V7a1 1 0 0 1 2 0v5.5a.5.5 0 0 0 1 0V4a1 1 0 0 1 2 0v7.5a.5.5 0 0 0 1 0V3Z"
/>
</svg>
</button>
<div
class="reactionPopupMenu"
>
<section
class="handRaiseSection"
>
<button
aria-label="Toggle hand raised"
aria-labelledby=":rbg:"
aria-pressed="false"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🖐️
</button>
</section>
<div
class="verticalSeperator"
/>
<section>
<menu>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":rd2:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
👍
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":rd7:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🎉
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":rdc:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
👏
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":rdh:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🐶
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":rdm:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🐱
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":rdr:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
💡
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-label="Open reactions search"
aria-labelledby=":re0:"
class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59"
data-kind="tertiary"
data-size="lg"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.05 16.463a7.5 7.5 0 1 1 1.414-1.414l3.243 3.244a1 1 0 0 1-1.414 1.414l-3.244-3.244ZM16 10.5a5.5 5.5 0 1 0-11 0 5.5 5.5 0 0 0 11 0Z"
/>
</svg>
</button>
</li>
</menu>
</section>
</div>
</div>
`;
exports[`Can open menu 1`] = `
<div>
<button
aria-disabled="false"
aria-expanded="true"
aria-labelledby=":r0:"
class="_button_i91xf_17 raisedButton _has-icon_i91xf_66 _icon-only_i91xf_59"
data-kind="primary"
data-size="lg"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 3a1 1 0 1 1 2 0v8.5a.5.5 0 0 0 1 0V4a1 1 0 1 1 2 0v10.2l3.284-2.597a1.081 1.081 0 0 1 1.47 1.577c-.613.673-1.214 1.367-1.818 2.064-1.267 1.463-2.541 2.934-3.944 4.235A6 6 0 0 1 5 15V7a1 1 0 0 1 2 0v5.5a.5.5 0 0 0 1 0V4a1 1 0 0 1 2 0v7.5a.5.5 0 0 0 1 0V3Z"
/>
</svg>
</button>
<div
class="reactionPopupMenu"
>
<section
class="handRaiseSection"
>
<button
aria-label="Toggle hand raised"
aria-labelledby=":r6:"
aria-pressed="false"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🖐️
</button>
</section>
<div
class="verticalSeperator"
/>
<section>
<menu>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":rb:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
👍
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":rg:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🎉
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":rl:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
👏
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":rq:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🐶
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":rv:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🐱
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r14:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
💡
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-label="Open reactions search"
aria-labelledby=":r19:"
class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59"
data-kind="tertiary"
data-size="lg"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.05 16.463a7.5 7.5 0 1 1 1.414-1.414l3.243 3.244a1 1 0 0 1-1.414 1.414l-3.244-3.244ZM16 10.5a5.5 5.5 0 1 0-11 0 5.5 5.5 0 0 0 11 0Z"
/>
</svg>
</button>
</li>
</menu>
</section>
</div>
</div>
`;
exports[`Can raise hand 1`] = `
<div>
<button
aria-disabled="true"
aria-expanded="true"
aria-labelledby=":r3c:"
class="_button_i91xf_17 raisedButton _has-icon_i91xf_66 _icon-only_i91xf_59"
data-kind="primary"
data-size="lg"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 3a1 1 0 1 1 2 0v8.5a.5.5 0 0 0 1 0V4a1 1 0 1 1 2 0v10.2l3.284-2.597a1.081 1.081 0 0 1 1.47 1.577c-.613.673-1.214 1.367-1.818 2.064-1.267 1.463-2.541 2.934-3.944 4.235A6 6 0 0 1 5 15V7a1 1 0 0 1 2 0v5.5a.5.5 0 0 0 1 0V4a1 1 0 0 1 2 0v7.5a.5.5 0 0 0 1 0V3Z"
/>
</svg>
</button>
<div
class="reactionPopupMenu"
>
<section
class="handRaiseSection"
>
<button
aria-label="Toggle hand raised"
aria-labelledby=":r3i:"
aria-pressed="false"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🖐️
</button>
</section>
<div
class="verticalSeperator"
/>
<section>
<menu>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r3n:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
👍
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r3s:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🎉
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r41:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
👏
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r46:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🐶
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r4b:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🐱
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":r4g:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
💡
</button>
</li>
<li
class="reactionPopupMenuItem"
>
<button
aria-label="Open reactions search"
aria-labelledby=":r4l:"
class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59"
data-kind="tertiary"
data-size="lg"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.05 16.463a7.5 7.5 0 1 1 1.414-1.414l3.243 3.244a1 1 0 0 1-1.414 1.414l-3.244-3.244ZM16 10.5a5.5 5.5 0 1 0-11 0 5.5 5.5 0 0 0 11 0Z"
/>
</svg>
</button>
</li>
</menu>
</section>
</div>
</div>
`;
exports[`Can search for and send emoji 1`] = `
<div>
<button
aria-disabled="false"
aria-expanded="true"
aria-labelledby=":r8e:"
class="_button_i91xf_17 raisedButton _has-icon_i91xf_66 _icon-only_i91xf_59"
data-kind="primary"
data-size="lg"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 3a1 1 0 1 1 2 0v8.5a.5.5 0 0 0 1 0V4a1 1 0 1 1 2 0v10.2l3.284-2.597a1.081 1.081 0 0 1 1.47 1.577c-.613.673-1.214 1.367-1.818 2.064-1.267 1.463-2.541 2.934-3.944 4.235A6 6 0 0 1 5 15V7a1 1 0 0 1 2 0v5.5a.5.5 0 0 0 1 0V4a1 1 0 0 1 2 0v7.5a.5.5 0 0 0 1 0V3Z"
/>
</svg>
</button>
<div
class="reactionPopupMenu"
>
<section
class="handRaiseSection"
>
<button
aria-label="Toggle hand raised"
aria-labelledby=":r8k:"
aria-pressed="false"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🖐️
</button>
</section>
<div
class="verticalSeperator"
/>
<section>
<form
class="_root_dgy0u_24 searchForm"
>
<label
class="_label_dgy0u_67 _field_dgy0u_34 _search_qztja_17"
for=":ra4:"
>
<svg
class="_icon_qztja_46"
fill="currentColor"
height="20"
viewBox="0 0 24 24"
width="20"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.05 16.463a7.5 7.5 0 1 1 1.414-1.414l3.243 3.244a1 1 0 0 1-1.414 1.414l-3.244-3.244ZM16 10.5a5.5 5.5 0 1 0-11 0 5.5 5.5 0 0 0 11 0Z"
/>
</svg>
<input
class="_input_qztja_61"
id=":ra4:"
name="reactionSearch"
placeholder="Search reactions…"
type="search"
value="crickets"
/>
</label>
<button
aria-label="close search"
class="_button_i91xf_17 _has-icon_i91xf_66 _destructive_i91xf_116"
data-kind="secondary"
data-size="sm"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
fill="currentColor"
height="20"
viewBox="0 0 24 24"
width="20"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6.293 6.293a1 1 0 0 1 1.414 0L12 10.586l4.293-4.293a1 1 0 1 1 1.414 1.414L13.414 12l4.293 4.293a1 1 0 0 1-1.414 1.414L12 13.414l-4.293 4.293a1 1 0 0 1-1.414-1.414L10.586 12 6.293 7.707a1 1 0 0 1 0-1.414Z"
/>
</svg>
</button>
</form>
<div
class="_separator_144s5_17"
data-kind="primary"
data-orientation="horizontal"
role="separator"
/>
<menu>
<li
class="reactionPopupMenuItem"
>
<button
aria-disabled="false"
aria-labelledby=":rag:"
class="_button_i91xf_17 reactionButton"
data-kind="secondary"
data-size="lg"
role="button"
tabindex="0"
>
🦗
</button>
</li>
</menu>
</section>
</div>
</div>
`;

View File

@@ -15,8 +15,8 @@ import {
createRedaction,
MockRoom,
MockRTCSession,
TestComponentWrapper,
} from "./utils/test-reactions";
TestReactionsWrapper,
} from "./utils/testReactions";
import { RoomEvent } from "matrix-js-sdk/src/matrix";
const memberUserIdAlice = "@alice:example.org";
@@ -61,9 +61,9 @@ describe("useReactions", () => {
membership,
);
const { queryByRole } = render(
<TestComponentWrapper rtcSession={rtcSession}>
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestComponentWrapper>,
</TestReactionsWrapper>,
);
expect(queryByRole("list")?.children).to.have.lengthOf(0);
});
@@ -71,9 +71,9 @@ describe("useReactions", () => {
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { queryByText } = render(
<TestComponentWrapper rtcSession={rtcSession}>
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestComponentWrapper>,
</TestReactionsWrapper>,
);
await act(() => room.testSendReaction(memberEventAlice, membership));
expect(queryByText("Local reaction")).toBeTruthy();
@@ -82,9 +82,9 @@ describe("useReactions", () => {
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { queryByRole } = render(
<TestComponentWrapper rtcSession={rtcSession}>
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestComponentWrapper>,
</TestReactionsWrapper>,
);
await act(() => room.testSendReaction(memberEventAlice, membership));
expect(queryByRole("list")?.children).to.have.lengthOf(1);
@@ -95,9 +95,9 @@ describe("useReactions", () => {
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { queryByRole } = render(
<TestComponentWrapper rtcSession={rtcSession}>
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestComponentWrapper>,
</TestReactionsWrapper>,
);
const reactionEventId = await act(() =>
room.testSendReaction(memberEventAlice, membership),
@@ -119,9 +119,9 @@ describe("useReactions", () => {
]);
const rtcSession = new MockRTCSession(room, membership);
const { queryByRole } = render(
<TestComponentWrapper rtcSession={rtcSession}>
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestComponentWrapper>,
</TestReactionsWrapper>,
);
expect(queryByRole("list")?.children).to.have.lengthOf(1);
});
@@ -133,9 +133,9 @@ describe("useReactions", () => {
]);
const rtcSession = new MockRTCSession(room, membership);
const { queryByRole } = render(
<TestComponentWrapper rtcSession={rtcSession}>
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestComponentWrapper>,
</TestReactionsWrapper>,
);
expect(queryByRole("list")?.children).to.have.lengthOf(1);
act(() => rtcSession.testRemoveMember(memberUserIdAlice));
@@ -147,9 +147,9 @@ describe("useReactions", () => {
]);
const rtcSession = new MockRTCSession(room, membership);
const { queryByRole } = render(
<TestComponentWrapper rtcSession={rtcSession}>
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestComponentWrapper>,
</TestReactionsWrapper>,
);
expect(queryByRole("list")?.children).to.have.lengthOf(1);
// Simulate leaving and rejoining
@@ -161,13 +161,13 @@ describe("useReactions", () => {
});
test("ignores invalid sender for historic event", () => {
const room = new MockRoom(memberUserIdAlice, [
createReaction(memberEventAlice, membership),
createReaction(memberEventAlice, memberUserIdBob),
]);
const rtcSession = new MockRTCSession(room, membership);
const { queryByRole } = render(
<TestComponentWrapper rtcSession={rtcSession}>
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestComponentWrapper>,
</TestReactionsWrapper>,
);
expect(queryByRole("list")?.children).to.have.lengthOf(0);
});
@@ -175,9 +175,9 @@ describe("useReactions", () => {
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { queryByRole } = render(
<TestComponentWrapper rtcSession={rtcSession}>
<TestReactionsWrapper rtcSession={rtcSession}>
<TestComponent />
</TestComponentWrapper>,
</TestReactionsWrapper>,
);
await act(() => room.testSendReaction(memberEventAlice, memberUserIdBob));
expect(queryByRole("list")?.children).to.have.lengthOf(0);

View File

@@ -15,7 +15,7 @@ import {
MatrixRTCSessionEvent,
} from "matrix-js-sdk/src/matrixrtc";
export const TestComponentWrapper = ({
export const TestReactionsWrapper = ({
rtcSession,
children,
}: PropsWithChildren<{
@@ -98,6 +98,9 @@ export function createRedaction(
}
export class MockRoom extends EventEmitter {
public readonly testSentEvents: Parameters<MatrixClient["sendEvent"]>[] = [];
public readonly testRedactedEvents: Parameters<MatrixClient["redactEvent"]>[] = [];
public constructor(
private readonly ownUserId: string,
private readonly existingRelations: MatrixEvent[] = [],
@@ -108,6 +111,18 @@ export class MockRoom extends EventEmitter {
public get client(): MatrixClient {
return {
getUserId: (): string => this.ownUserId,
sendEvent: async (
...props: Parameters<MatrixClient["sendEvent"]>
): ReturnType<MatrixClient["sendEvent"]> => {
this.testSentEvents.push(props);
return { event_id: randomUUID() };
},
redactEvent: async (
...props: Parameters<MatrixClient["redactEvent"]>
): ReturnType<MatrixClient["redactEvent"]> => {
this.testRedactedEvents.push(props);
return { event_id: randomUUID() };
},
} as unknown as MatrixClient;
}