element-web/apps/web/test/viewmodels/message-body/ReactionsRowViewModel-test.tsx
Zack fe84501e95
Move ReactionRow To Shared Components MVVM (#32634)
* Init shared component structure

* Storybook implementation

* Add snapshots of storybook examples

* ViewModel Creation + Implementation In EventTile.tsx

* Prettier

* Update HTML snapshot

* Add onhover pointer on bottons

* Added compound web tooltip

* Removed possible of undefined on label

* Update snapshots

* Update setters to use merge instead of updating full snapshot

* adapt view model test for setters change

* Actions should be passed to viewmodel fix

* replace ReactionsRowWrapper forceRender with explicit reaction state

* Update snapshot
2026-03-02 13:59:04 +00:00

107 lines
3.4 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 MouseEvent } from "react";
import { ReactionsRowViewModel } from "../../../src/viewmodels/message-body/ReactionsRowViewModel";
describe("ReactionsRowViewModel", () => {
const createVm = (
overrides?: Partial<ConstructorParameters<typeof ReactionsRowViewModel>[0]>,
): ReactionsRowViewModel =>
new ReactionsRowViewModel({
isActionable: true,
reactionGroupCount: 10,
canReact: true,
addReactionButtonActive: false,
...overrides,
});
it("computes initial snapshot from props", () => {
const vm = createVm();
const snapshot = vm.getSnapshot();
expect(snapshot.isVisible).toBe(true);
expect(snapshot.showAllButtonVisible).toBe(true);
expect(snapshot.showAddReactionButton).toBe(true);
expect(snapshot.addReactionButtonActive).toBe(false);
expect(snapshot.className).toContain("mx_ReactionsRow");
});
it("hides show-all after onShowAllClick", () => {
const vm = createVm();
const listener = jest.fn();
vm.subscribe(listener);
vm.onShowAllClick();
expect(vm.getSnapshot().showAllButtonVisible).toBe(false);
expect(listener).toHaveBeenCalledTimes(1);
});
it("updates visibility when reaction group count changes", () => {
const vm = createVm();
vm.setReactionGroupCount(0);
expect(vm.getSnapshot().isVisible).toBe(false);
});
it("updates add-reaction button visibility from canReact", () => {
const vm = createVm();
vm.setCanReact(false);
expect(vm.getSnapshot().showAddReactionButton).toBe(false);
});
it("updates add-reaction active state", () => {
const vm = createVm();
vm.setAddReactionButtonActive(true);
expect(vm.getSnapshot().addReactionButtonActive).toBe(true);
});
it("forwards add-reaction handlers", () => {
const vm = createVm();
const onAddReactionClick = jest.fn();
const onAddReactionContextMenu = jest.fn();
vm.setAddReactionHandlers({
onAddReactionClick,
onAddReactionContextMenu,
});
const clickEvent = {
currentTarget: document.createElement("button"),
} as unknown as MouseEvent<HTMLButtonElement>;
vm.onAddReactionClick(clickEvent);
vm.onAddReactionContextMenu(clickEvent);
expect(onAddReactionClick).toHaveBeenCalledWith(clickEvent);
expect(onAddReactionContextMenu).toHaveBeenCalledWith(clickEvent);
});
it("emits only for setters that always merge when values are unchanged", () => {
const vm = createVm();
const previousSnapshot = vm.getSnapshot();
const listener = jest.fn();
vm.subscribe(listener);
vm.setCanReact(true);
vm.setReactionGroupCount(10);
vm.setActionable(true);
vm.setAddReactionButtonActive(false);
// `setReactionGroupCount` is optimized and skips emit for unchanged derived values.
// The other setters always merge and therefore emit.
expect(listener).toHaveBeenCalledTimes(3);
expect(vm.getSnapshot()).toEqual(previousSnapshot);
});
});