Room list: move sections out of labs to all the users (#33810)

* feat: remove section labs flag

* test: update tests

* feat: remove favourites and low prioriy filter in SC

* test: update screenshots

* test: update snapshots

* test: update playwright tests

* test: update playright screenshots

* test: update screenshot

* test: close release announcement

* test: fix skeleton screenshot

* test: fix sliding sync

* test: update room list tests

* test: update room list tests after section dnd

* test: update toast screenshot

* test: update again room list tests

* test: update screenshot
This commit is contained in:
Florian Duros
2026-06-29 16:30:27 +00:00
committed by GitHub
parent 219ca4a3e9
commit aed2009b9f
85 changed files with 131 additions and 846 deletions
@@ -929,7 +929,6 @@ describe("RoomListStoreV3", () => {
describe("Sections", () => {
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 === "RoomList.CustomSectionData") return {};
return false;
@@ -948,26 +947,7 @@ describe("RoomListStoreV3", () => {
return { client, rooms };
}
it("returns a single chats section when sections feature is disabled", async () => {
const { rooms } = getClientAndRooms();
// Mark some rooms as favourite so we can verify they are NOT split out
[0, 1, 2].forEach((i) => {
rooms[i].tags[DefaultTagID.Favourite] = {};
});
const store = new RoomListStoreV3Class(dispatcher);
await store.start();
const result = store.getSortedRoomsInActiveSpace();
expect(result.sections).toHaveLength(1);
expect(result.sections[0].tag).toBe(CHATS_TAG);
// All rooms, including favourites, are in the single section
for (const i of [0, 1, 2]) {
expect(result.sections[0].rooms).toContain(rooms[i]);
}
});
it("returns three sections in the correct order when enabled", async () => {
it("returns three sections in the correct order", async () => {
enableSections();
getClientAndRooms();
@@ -1229,7 +1209,6 @@ describe("RoomListStoreV3", () => {
const customTag = "element.io.section.custom";
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
if (setting === "feature_room_list_sections") return true;
if (setting === "RoomList.OrderedCustomSections") return [];
if (setting === "RoomList.CustomSectionData") return {};
return false;
@@ -1244,7 +1223,6 @@ describe("RoomListStoreV3", () => {
// Mark a room with the custom tag and update the settings
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 === "RoomList.CustomSectionData")
return { [customTag]: { tag: customTag, name: "Custom" } };
@@ -86,7 +86,6 @@ describe("RoomListHeaderViewModel", () => {
const snapshot = vm.getSnapshot();
expect(snapshot.title).toBe("Home");
expect(snapshot.displayComposeMenu).toBe(true);
expect(snapshot.displaySpaceMenu).toBe(false);
expect(snapshot.canCreateRoom).toBe(true);
expect(snapshot.canCreateVideoRoom).toBe(true);
@@ -123,28 +122,6 @@ describe("RoomListHeaderViewModel", () => {
expect(vm.getSnapshot().activeSortOption).toBe("alphabetical");
});
it("should hide compose menu when user cannot create rooms", () => {
mocked(hasCreateRoomRights).mockReturnValue(false);
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
const snapshot = vm.getSnapshot();
expect(snapshot.displayComposeMenu).toBe(false);
expect(snapshot.canCreateRoom).toBe(false);
});
it("should display compose menu when section feature is enabled@", () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
if (settingName === "feature_room_list_sections") return true;
return false;
});
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
const snapshot = vm.getSnapshot();
expect(snapshot.displayComposeMenu).toBe(true);
});
it("should show invite option when space is public", () => {
jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockReturnValue(mockSpace.roomId);
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(mockSpace);
@@ -179,28 +156,7 @@ describe("RoomListHeaderViewModel", () => {
expect(vm.getSnapshot().isMessagePreviewEnabled).toBe(true);
});
it.each([
[true, true, false],
[false, false, true],
])(
"when feature_room_list_sections is %s: canCreateSection=%s, useComposeIcon=%s",
(featureEnabled, expectedCanCreateSection, expectedUseComposeIcon) => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
if (settingName === "feature_room_list_sections") return featureEnabled;
return false;
});
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
expect(vm.getSnapshot().canCreateSection).toBe(expectedCanCreateSection);
expect(vm.getSnapshot().useComposeIcon).toBe(expectedUseComposeIcon);
},
);
it("should set displaySectionReleaseAnnouncement to true when sections feature is enabled and announcement is active", () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
if (settingName === "feature_room_list_sections") return true;
return false;
});
jest.spyOn(ReleaseAnnouncementStore.instance, "getReleaseAnnouncement").mockReturnValue(
"room_list_section",
);
@@ -208,15 +164,6 @@ describe("RoomListHeaderViewModel", () => {
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
expect(vm.getSnapshot().displaySectionReleaseAnnouncement).toBe(true);
});
it("should set displaySectionReleaseAnnouncement to false when sections feature is disabled", () => {
jest.spyOn(ReleaseAnnouncementStore.instance, "getReleaseAnnouncement").mockReturnValue(
"room_list_section",
);
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
expect(vm.getSnapshot().displaySectionReleaseAnnouncement).toBe(false);
});
});
describe("event listeners", () => {
@@ -509,20 +509,6 @@ describe("RoomListItemViewModel", () => {
});
});
describe("canMoveToSection", () => {
it.each([
[true, true],
[false, false],
])("should be %s when feature_room_list_sections is %s", (featureEnabled, expected) => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
if (setting === "feature_room_list_sections") return featureEnabled;
return false;
});
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
expect(viewModel.getSnapshot().canMoveToSection).toBe(expected);
});
});
describe("Actions", () => {
it("should dispatch view room action on openRoom", () => {
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
@@ -631,10 +617,6 @@ describe("RoomListItemViewModel", () => {
});
it("should include sections from orderedSectionTags excluding CHATS_TAG, favourite, and low priority", () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
if (setting === "feature_room_list_sections") return true;
return false;
});
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
const sections = viewModel.getSnapshot().sections;
@@ -643,10 +625,7 @@ describe("RoomListItemViewModel", () => {
it("should mark the room current section as selected", () => {
room.tags = { [customTag]: { order: 0 } };
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
if (setting === "feature_room_list_sections") return true;
return false;
});
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
const sections = viewModel.getSnapshot().sections;
@@ -655,7 +634,6 @@ 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 } };
return false;
@@ -672,10 +650,6 @@ describe("RoomListItemViewModel", () => {
if (setting === "RoomList.OrderedCustomSections") watchCallback = callback;
return "watcher-id";
});
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
if (setting === "feature_room_list_sections") return true;
return false;
});
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
expect(viewModel.getSnapshot().sections).toHaveLength(1);
@@ -480,20 +480,6 @@ describe("RoomListViewModel", () => {
});
});
describe("notifyCollapseState", () => {
it("should dispatch collapseSections=undefined when feature_room_list_sections is disabled", () => {
viewModel = new RoomListViewModel({ client: matrixClient });
const dispatchSpy = jest.spyOn(dispatcher, "dispatch");
RoomListStoreV3.instance.emit(RoomListStoreV3Event.ListsUpdate);
expect(dispatchSpy).toHaveBeenCalledWith({
action: Action.RoomListSectionsCollapseStateChanged,
collapseSections: undefined,
});
});
});
describe("Keyboard navigation (ViewRoomDelta)", () => {
beforeEach(() => {
// stubClient sets up MatrixClientPeg which is needed when ViewRoom action is dispatched
@@ -724,7 +710,7 @@ describe("RoomListViewModel", () => {
});
});
describe("Sections (feature_room_list_sections)", () => {
describe("Sections", () => {
let favRoom1: Room;
let favRoom2: Room;
let lowPriorityRoom: Room;
@@ -732,11 +718,6 @@ describe("RoomListViewModel", () => {
let regularRoom2: Room;
beforeEach(() => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
if (setting === "feature_room_list_sections") return true;
return false;
});
favRoom1 = mkStubRoom("!fav1:server", "Fav 1", matrixClient);
favRoom2 = mkStubRoom("!fav2:server", "Fav 2", matrixClient);
lowPriorityRoom = mkStubRoom("!low1:server", "Low 1", matrixClient);
@@ -1030,7 +1011,6 @@ describe("RoomListViewModel", () => {
mkStubRoom("!space:server", "My Space", matrixClient),
]);
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
if (setting === "feature_room_list_sections") return true;
if (setting === "RoomList.CustomSectionData")
return {
[customTag]: { tag: customTag, name: "My Section", spaceId: "!space:server" },
@@ -1041,7 +1021,6 @@ describe("RoomListViewModel", () => {
it("shows an empty custom section when viewing its originating space", () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
if (setting === "feature_room_list_sections") return true;
if (setting === "RoomList.CustomSectionData")
return { [customTag]: { tag: customTag, name: "My Section", spaceId: MetaSpace.Home } };
return false;