/* * 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 { DisambiguatedProfileViewModel } from "../../../src/viewmodels/room/timeline/event-tile/DisambiguatedProfileViewModel"; describe("DisambiguatedProfileViewModel", () => { const member = { userId: "@alice:example.org", roomId: "!room:example.org", rawDisplayName: "Alice", disambiguate: true, }; const nonDisambiguatedMember = { ...member, disambiguate: false, }; it("should return the snapshot from props", () => { const vm = new DisambiguatedProfileViewModel({ member, fallbackName: "Fallback", colored: true, emphasizeDisplayName: true, withTooltip: true, }); expect(vm.getSnapshot()).toEqual({ displayName: "Alice", colorClass: "mx_Username_color3", displayIdentifier: "@alice:example.org", title: "Alice (@alice:example.org)", emphasizeDisplayName: true, }); }); it("should default member fields when member is null", () => { const vm = new DisambiguatedProfileViewModel({ member: null, fallbackName: "Fallback", }); expect(vm.getSnapshot()).toMatchObject({ displayName: "Fallback", colorClass: undefined, displayIdentifier: undefined, title: undefined, emphasizeDisplayName: undefined, }); }); it("should delegate onClick without emitting a snapshot update", () => { const onClick = jest.fn(); const vm = new DisambiguatedProfileViewModel({ member, fallbackName: "Fallback", onClick, }); const prevSnapshot = vm.getSnapshot(); const subscriber = jest.fn(); vm.subscribe(subscriber); vm.onClick?.({} as never); expect(onClick).toHaveBeenCalledTimes(1); expect(subscriber).not.toHaveBeenCalled(); expect(vm.getSnapshot()).toBe(prevSnapshot); }); it("should keep onClick bound when extracted as a callback", () => { const onClick = jest.fn(); const vm = new DisambiguatedProfileViewModel({ member, fallbackName: "Fallback", onClick, }); const clickHandler = vm.onClick; expect(() => clickHandler?.({} as never)).not.toThrow(); expect(onClick).toHaveBeenCalledTimes(1); }); it("should emit snapshot update when fallbackName changes", () => { const vm = new DisambiguatedProfileViewModel({ member: null, fallbackName: "Fallback", }); const subscriber = jest.fn(); vm.subscribe(subscriber); vm.setMember("Updated"); expect(subscriber).toHaveBeenCalledTimes(1); expect(vm.getSnapshot().displayName).toBe("Updated"); }); it("should emit snapshot update when setMember is called even if fallbackName is unchanged", () => { const vm = new DisambiguatedProfileViewModel({ member: null, fallbackName: "Fallback", }); const subscriber = jest.fn(); vm.subscribe(subscriber); vm.setMember("Fallback"); expect(subscriber).toHaveBeenCalledTimes(1); }); it("should compute tooltip title from constructor props when withTooltip is true", () => { const vm = new DisambiguatedProfileViewModel({ member, fallbackName: "Fallback", withTooltip: true, }); expect(vm.getSnapshot().title).toBe("Alice (@alice:example.org)"); }); it("should compute tooltip title even when disambiguation is not needed", () => { const vm = new DisambiguatedProfileViewModel({ member: nonDisambiguatedMember, fallbackName: "Fallback", withTooltip: true, }); expect(vm.getSnapshot().title).toBe("Alice (@alice:example.org)"); }); it("should emit snapshot update when member changes via setMember", () => { const vm = new DisambiguatedProfileViewModel({ member: null, fallbackName: "Fallback", }); const subscriber = jest.fn(); vm.subscribe(subscriber); vm.setMember("Fallback", member); expect(subscriber).toHaveBeenCalledTimes(1); expect(vm.getSnapshot().displayName).toBe("Alice"); }); it("should emit snapshot update when setMember is called with unchanged member", () => { const vm = new DisambiguatedProfileViewModel({ member, fallbackName: "Fallback", }); const subscriber = jest.fn(); vm.subscribe(subscriber); vm.setMember("Fallback", member); expect(subscriber).toHaveBeenCalledTimes(1); }); });