* Refactoring of DisambiguatedProfile into shared components * correct values and refactoring * Add username color classes to Storybook and clean up DisambiguatedProfile stories * Refactor DisambiguatedProfileView to use class component and enhance props structure * Refactor DisambiguatedProfile components to use member object and enhance props structure * Update copyright year to 2026 and adjust the tests to fit the correct memberinfro interface * Add DisambiguatedProfileViewModel class * Refactor DisambiguatedProfileViewModel to use member object and the rest of the props * Refactor SenderProfile to use DisambiguatedProfileViewModel and update DisambiguatedProfile styles * Refactor DisambiguatedProfileView to enhance interface documentation * Refactor DisambiguatedProfileView to use CSS modules for styling * Updated css + tests to fit the new changes * Update of the test snap to fit the current tests * Adjusted RoomMemberTitleView and SenderProfile to use the new viewmodel, removed the old component. * Implemented new viewmodel test for DisambiguatedProfileViewModel * Update copyright text * update css class names * update to correct snapshot after css name changes. * Apply suggestion from @florianduros Co-authored-by: Florian Duros <florian.duros@ormaz.fr> * Moved logic to viewmodel instead of having it in the view. Removed unessecery functions and css. * removed unessecery file that I copied from root folder, this is no longed needed as I use the root file instead in the viewmodel * Better Formatting * Fix issues after merging develop * FIxed issues with eslint * Added Visible, non-interactive elements with click handlers must have at least one keyboard listener from eslint docs * Updated snapshot the fit the latest update with eslint button requirment * Update snapshot screens for new tests. * Update tests to reflect snapshots * Update snapshot due of outdated CSS module classes * Add useEffect to call setProps on the DisambiguatedProfileViewModel when props change, ensuring the view updates with the correct display name. Update LayoutSwitcher snapshot for new CSS classes. * Fix Playwright editing tests by adding exact match for Edit button selector The DisambiguatedProfile refactoring added role="button" to the component, causing the selector { name: "Edit" } to match both the user "Edith" and the actual Edit button. * Fix ForwardDialog location tests for async hook rendering The SenderProfile component now uses hooks that trigger async state updates. * Fix SenderProfile useEffect to only update changeable props * Added letter spacing * Added ClassName prop * Update snapshot * Update letter-spacing * Update snapshot screenshots * Update Snapshots * Update snapshot * Removal of letter spacing to test CI * Apply suggestion from @florianduros Co-authored-by: Florian Duros <florian.duros@ormaz.fr> * Added closing brackets + added back letter-spacing * Update snapshots * Update snapshot * Update span to correctly apply to the CI tests, it wasn't possible to use classname as a prop * Update snapshot * Added comment to explain the span classNames * DisambiguatedProfileViewModel.setProps to runtime-changing props * replace DisambiguatedProfileViewModel setProps with explicit setters and update call sites * Update Setters * Prettier FIx * Update Setters * update DisambiguatedProfileViewModel setters and tests * Update SenderProfile to show connect display name * clone snapshot in setters to trigger reactive updates * use snapshot.merge in DisambiguatedProfileViewModel setters * emove duplicated logic in DisambiguatedProfileViewModel * Change snapshot name * Update viewmodel * Updated Tests * typo * Update src/viewmodels/profile/DisambiguatedProfileViewModel.ts Co-authored-by: Florian Duros <florian.duros@ormaz.fr> * Removal of unused function * Update snapshots * Update tests to pass coverage * Update Eslint --------- Co-authored-by: Florian Duros <florian.duros@ormaz.fr>
159 lines
4.9 KiB
TypeScript
159 lines
4.9 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 { DisambiguatedProfileViewModel } from "../../../src/viewmodels/profile/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",
|
|
className: undefined,
|
|
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,
|
|
className: undefined,
|
|
displayIdentifier: undefined,
|
|
title: undefined,
|
|
emphasizeDisplayName: undefined,
|
|
});
|
|
});
|
|
|
|
it("should pass through className prop", () => {
|
|
const vm = new DisambiguatedProfileViewModel({
|
|
member,
|
|
fallbackName: "Fallback",
|
|
className: "mx_DisambiguatedProfile",
|
|
});
|
|
|
|
expect(vm.getSnapshot().className).toBe("mx_DisambiguatedProfile");
|
|
});
|
|
|
|
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);
|
|
onClick({} as never);
|
|
|
|
expect(onClick).toHaveBeenCalledTimes(1);
|
|
expect(subscriber).not.toHaveBeenCalled();
|
|
expect(vm.getSnapshot()).toBe(prevSnapshot);
|
|
});
|
|
|
|
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);
|
|
});
|
|
});
|