mirror of
https://github.com/vector-im/element-web.git
synced 2026-03-05 05:21:15 +01:00
mkdir apps/web/scripts
mv scripts/{cleanup.sh,ci_package.sh,copy-res.ts,deploy.py,package.sh} apps/web/scripts
And a couple of gitignore tweaks
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
173 lines
6.5 KiB
TypeScript
173 lines
6.5 KiB
TypeScript
/*
|
|
* Copyright 2026 Element Creations 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 { type MatrixClient, type MatrixEvent, type Room, type RoomMember } from "matrix-js-sdk/src/matrix";
|
|
|
|
import {
|
|
ReactionsRowButtonTooltipViewModel,
|
|
type ReactionsRowButtonTooltipViewModelProps,
|
|
} from "../../../src/viewmodels/message-body/ReactionsRowButtonTooltipViewModel";
|
|
import { stubClient, mkStubRoom, mkEvent } from "../../test-utils";
|
|
import { unicodeToShortcode } from "../../../src/HtmlUtils";
|
|
|
|
jest.mock("../../../src/HtmlUtils", () => ({
|
|
...jest.requireActual("../../../src/HtmlUtils"),
|
|
unicodeToShortcode: jest.fn(),
|
|
}));
|
|
|
|
const mockedUnicodeToShortcode = jest.mocked(unicodeToShortcode);
|
|
|
|
describe("ReactionsRowButtonTooltipViewModel", () => {
|
|
let client: MatrixClient;
|
|
let room: Room;
|
|
let mxEvent: MatrixEvent;
|
|
|
|
const createReactionEvent = (senderId: string, content?: Record<string, unknown>): MatrixEvent => {
|
|
return mkEvent({
|
|
event: true,
|
|
type: "m.reaction",
|
|
room: room.roomId,
|
|
user: senderId,
|
|
content: {
|
|
"m.relates_to": { rel_type: "m.annotation", event_id: mxEvent.getId(), key: "👍" },
|
|
...content,
|
|
},
|
|
});
|
|
};
|
|
|
|
const createProps = (
|
|
overrides?: Partial<ReactionsRowButtonTooltipViewModelProps>,
|
|
): ReactionsRowButtonTooltipViewModelProps => ({
|
|
client,
|
|
mxEvent,
|
|
content: "👍",
|
|
reactionEvents: [],
|
|
customReactionImagesEnabled: false,
|
|
...overrides,
|
|
});
|
|
|
|
beforeEach(() => {
|
|
client = stubClient();
|
|
room = mkStubRoom("!room:example.org", "Test Room", client);
|
|
jest.spyOn(client, "getRoom").mockReturnValue(room);
|
|
|
|
mxEvent = mkEvent({
|
|
event: true,
|
|
type: "m.room.message",
|
|
room: room.roomId,
|
|
user: "@sender:example.org",
|
|
content: { body: "Test message", msgtype: "m.text" },
|
|
});
|
|
|
|
mockedUnicodeToShortcode.mockImplementation((char: string) => {
|
|
if (char === "👍") return ":thumbsup:";
|
|
return "";
|
|
});
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.restoreAllMocks();
|
|
mockedUnicodeToShortcode.mockReset();
|
|
});
|
|
|
|
it("should return undefined snapshot when room is not found", () => {
|
|
jest.spyOn(client, "getRoom").mockReturnValue(null);
|
|
|
|
const vm = new ReactionsRowButtonTooltipViewModel(createProps());
|
|
const snapshot = vm.getSnapshot();
|
|
|
|
expect(snapshot.formattedSenders).toBeUndefined();
|
|
expect(snapshot.caption).toBeUndefined();
|
|
});
|
|
|
|
it("should return undefined snapshot when MatrixClient is unavailable", () => {
|
|
const vm = new ReactionsRowButtonTooltipViewModel(createProps({ client: null }));
|
|
const snapshot = vm.getSnapshot();
|
|
|
|
expect(snapshot.formattedSenders).toBeUndefined();
|
|
expect(snapshot.caption).toBeUndefined();
|
|
});
|
|
|
|
it("should compute formattedSenders and caption from reaction events", () => {
|
|
const reactionEvent = createReactionEvent("@alice:example.org");
|
|
jest.spyOn(room, "getMember").mockReturnValue({ name: "Alice", userId: "@alice:example.org" } as RoomMember);
|
|
|
|
const vm = new ReactionsRowButtonTooltipViewModel(createProps({ reactionEvents: [reactionEvent] }));
|
|
const snapshot = vm.getSnapshot();
|
|
|
|
expect(snapshot.formattedSenders).toBe("Alice");
|
|
expect(snapshot.caption).toContain(":thumbsup:");
|
|
});
|
|
|
|
it("should fall back to sender ID when member is not found", () => {
|
|
const reactionEvent = createReactionEvent("@unknown:example.org");
|
|
jest.spyOn(room, "getMember").mockReturnValue(null);
|
|
|
|
const vm = new ReactionsRowButtonTooltipViewModel(createProps({ reactionEvents: [reactionEvent] }));
|
|
|
|
expect(vm.getSnapshot().formattedSenders).toBe("@unknown:example.org");
|
|
});
|
|
|
|
it("should use custom reaction shortcode when customReactionImagesEnabled is true", () => {
|
|
mockedUnicodeToShortcode.mockReturnValue("");
|
|
const reactionEvent = createReactionEvent("@alice:example.org", {
|
|
"com.beeper.reaction.shortcode": "custom_emoji",
|
|
});
|
|
jest.spyOn(room, "getMember").mockReturnValue({ name: "Alice", userId: "@alice:example.org" } as RoomMember);
|
|
|
|
const vm = new ReactionsRowButtonTooltipViewModel(
|
|
createProps({
|
|
content: "mxc://custom/emoji",
|
|
reactionEvents: [reactionEvent],
|
|
customReactionImagesEnabled: true,
|
|
}),
|
|
);
|
|
|
|
expect(vm.getSnapshot().caption).toContain("custom_emoji");
|
|
});
|
|
|
|
it("should not use custom reaction shortcode when customReactionImagesEnabled is false", () => {
|
|
mockedUnicodeToShortcode.mockReturnValue("");
|
|
const reactionEvent = createReactionEvent("@alice:example.org", {
|
|
"com.beeper.reaction.shortcode": "custom_emoji",
|
|
});
|
|
jest.spyOn(room, "getMember").mockReturnValue({ name: "Alice", userId: "@alice:example.org" } as RoomMember);
|
|
|
|
const vm = new ReactionsRowButtonTooltipViewModel(
|
|
createProps({
|
|
content: "mxc://custom/emoji",
|
|
reactionEvents: [reactionEvent],
|
|
customReactionImagesEnabled: false,
|
|
}),
|
|
);
|
|
|
|
expect(vm.getSnapshot().caption).toBeUndefined();
|
|
});
|
|
|
|
it("should update snapshot and notify subscribers when setProps is called", () => {
|
|
const aliceReaction = createReactionEvent("@alice:example.org");
|
|
const bobReaction = createReactionEvent("@bob:example.org");
|
|
|
|
jest.spyOn(room, "getMember").mockImplementation((userId) => {
|
|
const names: Record<string, string> = { "@alice:example.org": "Alice", "@bob:example.org": "Bob" };
|
|
return names[userId!] ? ({ name: names[userId!], userId } as RoomMember) : null;
|
|
});
|
|
|
|
const vm = new ReactionsRowButtonTooltipViewModel(createProps({ reactionEvents: [aliceReaction] }));
|
|
expect(vm.getSnapshot().formattedSenders).toBe("Alice");
|
|
|
|
const subscriber = jest.fn();
|
|
vm.subscribe(subscriber);
|
|
|
|
vm.setProps({ reactionEvents: [aliceReaction, bobReaction] });
|
|
|
|
expect(subscriber).toHaveBeenCalled();
|
|
expect(vm.getSnapshot().formattedSenders).toContain("Alice");
|
|
expect(vm.getSnapshot().formattedSenders).toContain("Bob");
|
|
});
|
|
});
|