fix(prototype): fix test suite and setting keys for variant-a space-scoped sections

- Rename setting keys to element.io.prototype.RoomList.* prefix
- Guard against legacy flat-array format in OrderedCustomSections
- Shallow-copy settings cache before mutation
- Update all tests to match new API: spaceId param on createSection(),
  Record<SpaceKey, string[]> for OrderedCustomSections, and full setting key names
This commit is contained in:
GD Element 2026-04-29 18:21:49 +02:00
parent a64e5f0d8f
commit 4bc83cf3e1
12 changed files with 124 additions and 77 deletions

3
.gitignore vendored
View File

@ -42,3 +42,6 @@ storybook-static
# vitepress
/docs/.vitepress/dist
/docs/.vitepress/cache
# Local Netlify folder
.netlify

View File

@ -368,8 +368,8 @@ export interface Settings {
"inviteRules": IBaseSetting<ComputedInviteConfig>;
"blockInvites": IBaseSetting<boolean>;
"Developer.elementCallUrl": IBaseSetting<string>;
"RoomList.CustomSectionData": IBaseSetting<CustomSectionsData>;
"RoomList.OrderedCustomSections": IBaseSetting<OrderedCustomSections>;
"element.io.prototype.RoomList.CustomSectionData": IBaseSetting<CustomSectionsData>;
"element.io.prototype.RoomList.OrderedCustomSections": IBaseSetting<OrderedCustomSections>;
}
export type SettingKey = keyof Settings;
@ -1379,7 +1379,7 @@ export const SETTINGS: Settings = {
* Managed by the {@link RoomListStoreV3}
* Store the custom section data for the room list
*/
"RoomList.CustomSectionData": {
"element.io.prototype.RoomList.CustomSectionData": {
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
default: {},
},
@ -1387,7 +1387,7 @@ export const SETTINGS: Settings = {
* Managed by the {@link RoomListStoreV3}
* Store the ordering of the custom sections for the room list, keyed by space/metaspace ID.
*/
"RoomList.OrderedCustomSections": {
"element.io.prototype.RoomList.OrderedCustomSections": {
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
default: {},
},

View File

@ -133,7 +133,7 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient<EmptyObject> {
this.onActiveSpaceChanged();
});
SpaceStore.instance.on(UPDATE_HOME_BEHAVIOUR, () => this.onActiveSpaceChanged());
SettingsStore.watchSetting("RoomList.OrderedCustomSections", null, () => this.onOrderedCustomSectionsChange());
SettingsStore.watchSetting("element.io.prototype.RoomList.OrderedCustomSections", null, () => this.onOrderedCustomSectionsChange());
this.loadCustomSections();
}
@ -532,7 +532,10 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient<EmptyObject> {
*/
private loadCustomSections(): void {
const activeSpace = SpaceStore.instance.activeSpace;
const orderedCustomSections: Record<string, string[]> = SettingsStore.getValue("RoomList.OrderedCustomSections") || {};
const storedSections = SettingsStore.getValue("element.io.prototype.RoomList.OrderedCustomSections");
// Guard against legacy flat-array format stored by the base branch
const orderedCustomSections: Record<string, string[]> =
storedSections && !Array.isArray(storedSections) ? storedSections : {};
const spaceSections = orderedCustomSections[activeSpace] ?? [];
this.sortedTags = [DefaultTagID.Favourite, ...spaceSections, CHATS_TAG, DefaultTagID.LowPriority];
}

View File

@ -65,17 +65,18 @@ export async function createSection(spaceId: SpaceKey): Promise<string | undefin
const tag = `${CUSTOM_SECTION_TAG_PREFIX}${window.crypto.randomUUID()}`;
const newSection: CustomSection = { tag, name: sectionName, spaceId };
// Save the new section data
const sectionData = SettingsStore.getValue("RoomList.CustomSectionData") || {};
// Save the new section data — shallow-copy to avoid mutating the settings cache reference
const sectionData = { ...(SettingsStore.getValue("element.io.prototype.RoomList.CustomSectionData") || {}) };
sectionData[tag] = newSection;
await SettingsStore.setValue("RoomList.CustomSectionData", null, SettingLevel.ACCOUNT, sectionData);
await SettingsStore.setValue("element.io.prototype.RoomList.CustomSectionData", null, SettingLevel.ACCOUNT, sectionData);
// Add the new section to the ordered list of sections for this space
const orderedSections: OrderedCustomSections = SettingsStore.getValue("RoomList.OrderedCustomSections") || {};
const spaceSections = orderedSections[spaceId] ?? [];
spaceSections.push(tag);
orderedSections[spaceId] = spaceSections;
await SettingsStore.setValue("RoomList.OrderedCustomSections", null, SettingLevel.ACCOUNT, orderedSections);
// Shallow-copy and guard against legacy flat-array format from the base branch
const storedSections = SettingsStore.getValue("element.io.prototype.RoomList.OrderedCustomSections");
const orderedSections: OrderedCustomSections =
storedSections && !Array.isArray(storedSections) ? { ...storedSections } : {};
orderedSections[spaceId] = [...(orderedSections[spaceId] ?? []), tag];
await SettingsStore.setValue("element.io.prototype.RoomList.OrderedCustomSections", null, SettingLevel.ACCOUNT, orderedSections);
return tag;
}
@ -84,7 +85,7 @@ export async function createSection(spaceId: SpaceKey): Promise<string | undefin
* @param tag - The tag of the section to edit.
*/
export async function editSection(tag: string): Promise<void> {
const sectionData = SettingsStore.getValue("RoomList.CustomSectionData") || {};
const sectionData = SettingsStore.getValue("element.io.prototype.RoomList.CustomSectionData") || {};
const section = sectionData[tag];
if (!section) {
logger.info("Unknown section tag, cannot edit section", tag);
@ -99,7 +100,7 @@ export async function editSection(tag: string): Promise<void> {
// Save the new name
sectionData[tag].name = newName;
await SettingsStore.setValue("RoomList.CustomSectionData", null, SettingLevel.ACCOUNT, sectionData);
await SettingsStore.setValue("element.io.prototype.RoomList.CustomSectionData", null, SettingLevel.ACCOUNT, sectionData);
}
/**
@ -108,7 +109,7 @@ export async function editSection(tag: string): Promise<void> {
* @param isEmpty - Whether the section is empty (has no rooms). If the section is not empty, the confirmation dialog will show a warning message.
*/
export async function deleteSection(tag: string, isEmpty: boolean): Promise<void> {
const sectionData = SettingsStore.getValue("RoomList.CustomSectionData");
const sectionData = SettingsStore.getValue("element.io.prototype.RoomList.CustomSectionData");
if (!sectionData[tag]) {
logger.info("Unknown section tag, cannot delete section", tag);
return;
@ -120,13 +121,16 @@ export async function deleteSection(tag: string, isEmpty: boolean): Promise<void
// Remove the section from the ordered list of sections for its space
const spaceId = sectionData[tag].spaceId;
const orderedSections: OrderedCustomSections = SettingsStore.getValue("RoomList.OrderedCustomSections") || {};
const storedSections = SettingsStore.getValue("element.io.prototype.RoomList.OrderedCustomSections");
const orderedSections: OrderedCustomSections =
storedSections && !Array.isArray(storedSections) ? { ...storedSections } : {};
if (orderedSections[spaceId]) {
orderedSections[spaceId] = orderedSections[spaceId].filter((sectionTag) => sectionTag !== tag);
}
await SettingsStore.setValue("RoomList.OrderedCustomSections", null, SettingLevel.ACCOUNT, orderedSections);
await SettingsStore.setValue("element.io.prototype.RoomList.OrderedCustomSections", null, SettingLevel.ACCOUNT, orderedSections);
// Remove the section data
delete sectionData[tag];
await SettingsStore.setValue("RoomList.CustomSectionData", null, SettingLevel.ACCOUNT, sectionData);
// Remove the section data — shallow-copy to avoid mutating the settings cache reference
const updatedSectionData = { ...sectionData };
delete updatedSectionData[tag];
await SettingsStore.setValue("element.io.prototype.RoomList.CustomSectionData", null, SettingLevel.ACCOUNT, updatedSectionData);
}

View File

@ -14,13 +14,17 @@ import RoomListActions from "../../actions/RoomListActions";
import dis from "../../dispatcher/dispatcher";
import { getTagsForRoom } from "./getTagsForRoom";
import { isCustomSectionTag } from "../../stores/room-list-v3/section";
import RoomListStoreV3 from "../../stores/room-list-v3/RoomListStoreV3";
/**
* Toggle tag for a given room.
* A room can only be in one section: either a custom section, Favourite, or LowPriority.
* Applying any of these will atomically replace the current section tag.
*
* - For custom section tags: replaces the active space's current custom section tag (if any),
* leaving tags from other spaces intact. A room can be in one custom section per space.
* - For Favourite/LowPriority: simple toggle of that specific tag, independent of custom sections.
*
* @param room The room to tag
* @param tagId The tag to invert
* @param tagId The tag to toggle
*/
export function tagRoom(room: Room, tagId: TagID): void {
if (tagId !== DefaultTagID.Favourite && tagId !== DefaultTagID.LowPriority && !isCustomSectionTag(tagId)) {
@ -28,14 +32,25 @@ export function tagRoom(room: Room, tagId: TagID): void {
return;
}
// Find the section tag currently applied (Fav, LowPriority, or custom) — at most one exists
const currentSectionTag =
getTagsForRoom(room).find(
(t) => t === DefaultTagID.Favourite || t === DefaultTagID.LowPriority || isCustomSectionTag(t),
) ?? null;
let removeTag: TagID | null;
let addTag: TagID | null;
if (isCustomSectionTag(tagId)) {
// For custom sections: only replace within the active space's custom sections.
// Tags from other spaces are left intact.
const activeSpaceCustomSectionTags = new Set(
RoomListStoreV3.instance.orderedSectionTags.filter((t) => isCustomSectionTag(t)),
);
const currentSectionTag = getTagsForRoom(room).find((t) => activeSpaceCustomSectionTags.has(t)) ?? null;
const isApplied = currentSectionTag === tagId;
removeTag = currentSectionTag;
addTag = isApplied ? null : tagId;
} else {
// For Favourite/LowPriority: simple toggle — independent of custom sections.
const isApplied = getTagsForRoom(room).includes(tagId);
removeTag = isApplied ? tagId : null;
addTag = isApplied ? null : tagId;
}
const isApplied = currentSectionTag === tagId;
const removeTag = currentSectionTag;
const addTag = isApplied ? null : tagId;
dis.dispatch(RoomListActions.tagRoom(room.client, room, removeTag, addTag));
}

View File

@ -38,7 +38,7 @@ import { Action } from "../../dispatcher/actions";
import type { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
import PosthogTrackers from "../../PosthogTrackers";
import { type Call, CallEvent } from "../../models/Call";
import RoomListStoreV3, { CHATS_TAG } from "../../stores/room-list-v3/RoomListStoreV3";
import RoomListStoreV3, { CHATS_TAG, LISTS_UPDATE_EVENT } from "../../stores/room-list-v3/RoomListStoreV3";
import { _t } from "../../languageHandler";
interface RoomItemProps {
@ -98,13 +98,18 @@ export class RoomListItemViewModel
this.disposables.trackListener(props.room, RoomEvent.Name, this.onRoomChanged);
this.disposables.trackListener(props.room, RoomEvent.Tags, this.onRoomChanged);
const orderSectionsRef = SettingsStore.watchSetting("RoomList.OrderedCustomSections", null, () =>
const orderSectionsRef = SettingsStore.watchSetting("element.io.prototype.RoomList.OrderedCustomSections", null, () =>
this.onOrderedCustomSectionsChange(),
);
this.disposables.track(() => {
SettingsStore.unwatchSetting(orderSectionsRef);
});
// Rebuild sections when the active space changes (variant-a: sections are scoped per space).
// Listen to LISTS_UPDATE_EVENT (not UPDATE_SELECTED_SPACE directly) to guarantee that
// RoomListStoreV3 has already called loadCustomSections() and updated orderedSectionTags.
this.disposables.trackListener(RoomListStoreV3.instance, LISTS_UPDATE_EVENT, this.onOrderedCustomSectionsChange);
// Load message preview asynchronously (sync data is already complete)
void this.loadAndSetMessagePreview();
}
@ -423,7 +428,7 @@ export class RoomListItemViewModel
* Order follows the canonical section order from RoomListStoreV3.
*/
private static buildSections(roomTags: Room["tags"]): Section[] {
const customSectionData = SettingsStore.getValue("RoomList.CustomSectionData") || {};
const customSectionData = SettingsStore.getValue("element.io.prototype.RoomList.CustomSectionData") || {};
return (
RoomListStoreV3.instance.orderedSectionTags

View File

@ -54,7 +54,7 @@ export class RoomListSectionHeaderViewModel
isUnread: false,
displaySectionMenu: !isDefaultSection,
});
const sectionWatherRef = SettingsStore.watchSetting("RoomList.CustomSectionData", null, () =>
const sectionWatherRef = SettingsStore.watchSetting("element.io.prototype.RoomList.CustomSectionData", null, () =>
this.onCustomSectionDataChange(),
);
this.disposables.track(() => SettingsStore.unwatchSetting(sectionWatherRef));
@ -140,7 +140,7 @@ export class RoomListSectionHeaderViewModel
* Handle changes to custom section data.
*/
private onCustomSectionDataChange(): void {
const customSectionData = SettingsStore.getValue("RoomList.CustomSectionData") || {};
const customSectionData = SettingsStore.getValue("element.io.prototype.RoomList.CustomSectionData") || {};
const sectionData = customSectionData[this.props.tag];
if (sectionData) {
this.snapshot.merge({ title: sectionData.name });

View File

@ -284,7 +284,7 @@ export class RoomListViewModel
public getSectionHeaderViewModel(tag: string): RoomListSectionHeaderViewModel {
if (this.roomSectionHeaderViewModels.has(tag)) return this.roomSectionHeaderViewModels.get(tag)!;
const customSections = SettingsStore.getValue("RoomList.CustomSectionData");
const customSections = SettingsStore.getValue("element.io.prototype.RoomList.CustomSectionData");
const title = TAG_TO_TITLE_MAP[tag] || customSections[tag]?.name || tag;
const viewModel = new RoomListSectionHeaderViewModel({
tag,
@ -637,7 +637,7 @@ function computeSections(
roomsResult: RoomsResult,
isSectionExpanded: (tag: string) => boolean,
): { sections: Section[]; isFlatList: boolean } {
const customSections = SettingsStore.getValue("RoomList.CustomSectionData");
const customSections = SettingsStore.getValue("element.io.prototype.RoomList.CustomSectionData");
const sections = roomsResult.sections
// Only include sections that have rooms or are custom sections (which may be empty but should still be shown)

View File

@ -832,7 +832,7 @@ describe("RoomListStoreV3", () => {
function enableSections(): void {
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
if (setting === "feature_room_list_sections") return true;
if (setting === "RoomList.OrderedCustomSections") return [];
if (setting === "element.io.prototype.RoomList.OrderedCustomSections") return {};
return false;
});
}
@ -1084,7 +1084,8 @@ describe("RoomListStoreV3", () => {
let settingsWatcher: (settingName: string) => void = () => {};
jest.spyOn(SettingsStore, "watchSetting").mockImplementation((settingName, _roomId, callback) => {
if (settingName === "RoomList.OrderedCustomSections") settingsWatcher = callback as () => void;
if (settingName === "element.io.prototype.RoomList.OrderedCustomSections")
settingsWatcher = callback as () => void;
return "watcher-id";
});
@ -1092,7 +1093,7 @@ describe("RoomListStoreV3", () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
if (setting === "feature_room_list_sections") return true;
if (setting === "RoomList.OrderedCustomSections") return [];
if (setting === "element.io.prototype.RoomList.OrderedCustomSections") return {};
return false;
});
@ -1106,12 +1107,13 @@ describe("RoomListStoreV3", () => {
rooms[0].tags = { [customTag]: { order: 0 } };
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
if (setting === "feature_room_list_sections") return true;
if (setting === "RoomList.OrderedCustomSections") return [customTag];
if (setting === "element.io.prototype.RoomList.OrderedCustomSections")
return { [MetaSpace.Home]: [customTag] };
return false;
});
// Trigger the settings watcher
settingsWatcher("RoomList.OrderedCustomSections");
settingsWatcher("element.io.prototype.RoomList.OrderedCustomSections");
// Now there should be 4 sections (Favourite, custom, Chats, LowPriority)
expect(store.getSortedRoomsInActiveSpace().sections).toHaveLength(4);

View File

@ -10,6 +10,7 @@ import SettingsStore from "../../../../src/settings/SettingsStore";
import { createSection, editSection, deleteSection } from "../../../../src/stores/room-list-v3/section";
import { CreateSectionDialog } from "../../../../src/components/views/dialogs/CreateSectionDialog";
import { RemoveSectionDialog } from "../../../../src/components/views/dialogs/RemoveSectionDialog";
import { MetaSpace } from "../../../../src/stores/spaces";
describe("section", () => {
afterEach(() => {
@ -23,8 +24,8 @@ describe("section", () => {
});
it.each([
[false, "", undefined],
[true, "", undefined],
[false, "", undefined] as const,
[true, "", undefined] as const,
[true, "My Section", expect.stringMatching(/^element\.io\.section\./)],
])("returns %s when shouldCreate=%s and name='%s'", async (shouldCreate, name, expected) => {
jest.spyOn(Modal, "createDialog").mockReturnValue({
@ -32,7 +33,7 @@ describe("section", () => {
close: jest.fn(),
} as any);
const result = await createSection();
const result = await createSection(MetaSpace.Home);
expect(result).toEqual(expected);
});
@ -42,7 +43,7 @@ describe("section", () => {
close: jest.fn(),
} as any);
const result = await createSection();
const result = await createSection(MetaSpace.Home);
expect(result).toMatch(/^element\.io\.section\./);
});
@ -52,14 +53,14 @@ describe("section", () => {
close: jest.fn(),
} as any);
await createSection();
await createSection(MetaSpace.Home);
expect(createDialogSpy).toHaveBeenCalledWith(CreateSectionDialog);
});
it("saves section data and ordered sections at ACCOUNT level when confirmed", async () => {
const existingTag = "element.io.section.existing";
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
if (setting === "RoomList.OrderedCustomSections") return [existingTag];
if (setting === "element.io.prototype.RoomList.OrderedCustomSections") return { [MetaSpace.Home]: [existingTag] };
return null;
});
jest.spyOn(Modal, "createDialog").mockReturnValue({
@ -68,23 +69,29 @@ describe("section", () => {
} as any);
const setValueSpy = jest.spyOn(SettingsStore, "setValue").mockResolvedValue(undefined);
await createSection();
await createSection(MetaSpace.Home);
const customDataCall = setValueSpy.mock.calls.find(([name]) => name === "RoomList.CustomSectionData");
const savedSection = Object.values(customDataCall![3] as Record<string, { tag: string; name: string }>)[0];
const customDataCall = setValueSpy.mock.calls.find(
([name]) => name === "element.io.prototype.RoomList.CustomSectionData",
);
const savedSection = Object.values(
customDataCall![3] as Record<string, { tag: string; name: string; spaceId: string }>,
)[0];
expect(savedSection.name).toBe("My Section");
expect(savedSection.tag).toMatch(/^element\.io\.section\./);
const orderedCall = setValueSpy.mock.calls.find(([name]) => name === "RoomList.OrderedCustomSections");
const savedOrder = orderedCall![3] as string[];
expect(savedOrder[0]).toBe(existingTag);
expect(savedOrder[1]).toMatch(/^element\.io\.section\./);
const orderedCall = setValueSpy.mock.calls.find(
([name]) => name === "element.io.prototype.RoomList.OrderedCustomSections",
);
const savedOrder = orderedCall![3] as Record<string, string[]>;
expect(savedOrder[MetaSpace.Home][0]).toBe(existingTag);
expect(savedOrder[MetaSpace.Home][1]).toMatch(/^element\.io\.section\./);
});
});
describe("editSection", () => {
const tag = "element.io.section.abc";
const existingSectionData = { [tag]: { tag, name: "Old Name" } };
const existingSectionData = { [tag]: { tag, name: "Old Name", spaceId: MetaSpace.Home } };
beforeEach(() => {
jest.spyOn(SettingsStore, "getValue").mockReturnValue(existingSectionData);
@ -134,10 +141,10 @@ describe("section", () => {
await editSection(tag);
expect(setValueSpy).toHaveBeenCalledWith(
"RoomList.CustomSectionData",
"element.io.prototype.RoomList.CustomSectionData",
null,
expect.anything(),
expect.objectContaining({ [tag]: { tag, name: "New Name" } }),
expect.objectContaining({ [tag]: { tag, name: "New Name", spaceId: MetaSpace.Home } }),
);
});
});
@ -147,11 +154,15 @@ describe("section", () => {
const otherTag = "element.io.section.other";
beforeEach(() => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
if (setting === "RoomList.CustomSectionData") return { [tag]: { tag, name: "My Section" } };
if (setting === "RoomList.OrderedCustomSections") return [otherTag, tag];
return null;
});
jest.spyOn(SettingsStore, "getValue").mockImplementation(
(setting): ReturnType<(typeof SettingsStore)["getValue"]> => {
if (setting === "element.io.prototype.RoomList.CustomSectionData")
return { [tag]: { tag, name: "My Section", spaceId: MetaSpace.Home } };
if (setting === "element.io.prototype.RoomList.OrderedCustomSections")
return { [MetaSpace.Home]: [otherTag, tag] };
return null;
},
);
jest.spyOn(SettingsStore, "setValue").mockResolvedValue(undefined);
});
@ -196,10 +207,14 @@ describe("section", () => {
await deleteSection(tag, false);
const orderedCall = setValueSpy.mock.calls.find(([name]) => name === "RoomList.OrderedCustomSections");
expect(orderedCall![3]).toEqual([otherTag]);
const orderedCall = setValueSpy.mock.calls.find(
([name]) => name === "element.io.prototype.RoomList.OrderedCustomSections",
);
expect(orderedCall![3]).toEqual({ [MetaSpace.Home]: [otherTag] });
const customDataCall = setValueSpy.mock.calls.find(([name]) => name === "RoomList.CustomSectionData");
const customDataCall = setValueSpy.mock.calls.find(
([name]) => name === "element.io.prototype.RoomList.CustomSectionData",
);
expect(customDataCall![3]).not.toHaveProperty(tag);
});
});

View File

@ -78,7 +78,7 @@ describe("RoomListItemViewModel", () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
if (setting === "RoomList.showMessagePreview") return false;
if (setting === "RoomList.OrderedCustomSections") return [];
if (setting === "element.io.prototype.RoomList.OrderedCustomSections") return {};
return false;
});
jest.spyOn(SettingsStore, "watchSetting").mockImplementation(() => "watcher-id");
@ -653,8 +653,8 @@ describe("RoomListItemViewModel", () => {
it("should use custom section name from CustomSectionData", () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
if (setting === "feature_room_list_sections") return true;
if (setting === "RoomList.CustomSectionData")
return { [customTag]: { name: "My Custom Section", tag: customTag } };
if (setting === "element.io.prototype.RoomList.CustomSectionData")
return { [customTag]: { name: "My Custom Section", tag: customTag, spaceId: "!space:server" } };
return false;
});
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
@ -666,7 +666,7 @@ describe("RoomListItemViewModel", () => {
it("should update sections when OrderedCustomSections setting changes", () => {
let watchCallback: CallbackFn<"RoomList.OrderedCustomSections"> = () => {};
jest.spyOn(SettingsStore, "watchSetting").mockImplementation((setting, _room, callback) => {
if (setting === "RoomList.OrderedCustomSections") watchCallback = callback;
if (setting === "element.io.prototype.RoomList.OrderedCustomSections") watchCallback = callback;
return "watcher-id";
});
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
@ -683,7 +683,7 @@ describe("RoomListItemViewModel", () => {
CHATS_TAG,
DefaultTagID.LowPriority,
]);
watchCallback("RoomList.OrderedCustomSections", null, null as any, null, null);
watchCallback("element.io.prototype.RoomList.OrderedCustomSections", null, null as any, null, null);
expect(viewModel.getSnapshot().sections.map((s) => s.tag)).toEqual([]);
});

View File

@ -26,7 +26,7 @@ describe("RoomListSectionHeaderViewModel", () => {
jest.spyOn(SettingsStore, "watchSetting").mockReturnValue("watcher-id");
jest.spyOn(SettingsStore, "unwatchSetting").mockReturnValue(undefined);
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
if (setting === "RoomList.OrderedCustomSections") return [];
if (setting === "element.io.prototype.RoomList.OrderedCustomSections") return {};
return null;
});
});
@ -118,7 +118,7 @@ describe("RoomListSectionHeaderViewModel", () => {
beforeEach(() => {
jest.spyOn(SettingsStore, "watchSetting").mockImplementation((settingName, _roomId, callback) => {
if (settingName === "RoomList.CustomSectionData") watchCallback = callback as () => void;
if (settingName === "element.io.prototype.RoomList.CustomSectionData") watchCallback = callback as () => void;
return "watcher-id";
});
});
@ -133,7 +133,7 @@ describe("RoomListSectionHeaderViewModel", () => {
});
expect(vm.getSnapshot().title).toBe("Old Title");
jest.spyOn(SettingsStore, "getValue").mockReturnValue({ [tag]: { tag, name: "New Title" } });
jest.spyOn(SettingsStore, "getValue").mockReturnValue({ [tag]: { tag, name: "New Title", spaceId: "!space:server" } });
watchCallback();
expect(vm.getSnapshot().title).toBe("New Title");