Implement new memberlist design with MVVM architecture (#28874)
* Add new e2e icon for the member tile * Add new presence icon for member tile * Implement new member tile * Implement memberlist view model * Implement new memberlist header view * Support the new memberlist in Diasambiguated profile 1. Use MemberInfo instead of RoomMember 2. CSS changes to reflect the new design * Implement new memberlist view * Add and use a new overflow component We used the EntityTile component as a pretend overflow tile in some places. This new lighter component is added so that we can remove the complex EntityTile component. * Remove old code * Add/remove css files from _components.pcss * Increase minimum width as per design * Actually use the new memberlist view * Fix broken jest tests * Add jest tests * Playwright: Make it possible to disable presence * Add playwright tests * Fix lint error * Undo translation changes that must be done via localazy * Update license header * Use waitFor instead of setTimeout * Remove comment * Switch over from template to container hs * Revert unintended change * Move config to top level
This commit is contained in:
@@ -16,7 +16,7 @@ const ROOM_NAME = "Test room";
|
||||
const NAME = "Alice";
|
||||
|
||||
function getMemberTileByName(page: Page, name: string): Locator {
|
||||
return page.locator(`.mx_EntityTile, [title="${name}"]`);
|
||||
return page.locator(`.mx_MemberTileView, [title="${name}"]`);
|
||||
}
|
||||
|
||||
test.use({
|
||||
@@ -88,7 +88,7 @@ test.describe("Dehydration", () => {
|
||||
await viewRoomSummaryByName(page, app, ROOM_NAME);
|
||||
|
||||
await page.locator(".mx_RightPanel").getByRole("menuitem", { name: "People" }).click();
|
||||
await expect(page.locator(".mx_MemberList")).toBeVisible();
|
||||
await expect(page.locator(".mx_MemberListView")).toBeVisible();
|
||||
|
||||
await getMemberTileByName(page, NAME).click();
|
||||
await page.locator(".mx_UserInfo_devices .mx_UserInfo_expand").click();
|
||||
|
||||
@@ -78,7 +78,7 @@ test.describe("Lazy Loading", () => {
|
||||
}
|
||||
|
||||
function getMemberInMemberlist(page: Page, name: string): Locator {
|
||||
return page.locator(".mx_MemberList .mx_EntityTile_name").filter({ hasText: name });
|
||||
return page.locator(".mx_MemberListView .mx_MemberTileView_name").filter({ hasText: name });
|
||||
}
|
||||
|
||||
async function checkMemberList(page: Page, charlies: Bot[]) {
|
||||
|
||||
48
playwright/e2e/right-panel/memberlist.spec.ts
Normal file
48
playwright/e2e/right-panel/memberlist.spec.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright 2024 New Vector 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 { test, expect } from "../../element-web-test";
|
||||
import { Bot } from "../../pages/bot";
|
||||
|
||||
const ROOM_NAME = "Test room";
|
||||
const NAME = "Alice";
|
||||
|
||||
test.use({
|
||||
synapseConfigOptions: {
|
||||
presence: {
|
||||
enabled: false,
|
||||
include_offline_users_on_sync: false,
|
||||
},
|
||||
},
|
||||
displayName: NAME,
|
||||
disablePresence: true,
|
||||
});
|
||||
|
||||
test.describe("Memberlist", () => {
|
||||
test.beforeEach(async ({ app, user, page, homeserver }, testInfo) => {
|
||||
testInfo.setTimeout(testInfo.timeout + 30_000);
|
||||
const id = await app.client.createRoom({ name: ROOM_NAME });
|
||||
const newBots: Bot[] = [];
|
||||
const names = ["Bob", "Bob", "Susan"];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const displayName = names[i];
|
||||
const autoAcceptInvites = displayName !== "Susan";
|
||||
const bot = new Bot(page, homeserver, { displayName, startClient: true, autoAcceptInvites });
|
||||
await bot.prepareClient();
|
||||
await app.client.inviteUser(id, bot.credentials?.userId);
|
||||
newBots.push(bot);
|
||||
}
|
||||
});
|
||||
|
||||
test("Renders correctly", { tag: "@screenshot" }, async ({ page, app }) => {
|
||||
await app.viewRoomByName(ROOM_NAME);
|
||||
const memberlist = await app.toggleMemberlistPanel();
|
||||
await expect(memberlist.locator(".mx_MemberTileView")).toHaveCount(4);
|
||||
await expect(memberlist.getByText("(Invited)")).toHaveCount(1);
|
||||
await expect(page.locator(".mx_MemberListView")).toMatchScreenshot("with-four-members.png");
|
||||
});
|
||||
});
|
||||
@@ -24,7 +24,7 @@ const ROOM_ADDRESS_LONG =
|
||||
"loremIpsumDolorSitAmetConsecteturAdipisicingElitSedDoEiusmodTemporIncididuntUtLaboreEtDoloreMagnaAliqua";
|
||||
|
||||
function getMemberTileByName(page: Page, name: string): Locator {
|
||||
return page.locator(`.mx_EntityTile, [title="${name}"]`);
|
||||
return page.locator(`.mx_MemberTileView, [title="${name}"]`);
|
||||
}
|
||||
|
||||
test.describe("RightPanel", () => {
|
||||
@@ -107,14 +107,14 @@ test.describe("RightPanel", () => {
|
||||
await viewRoomSummaryByName(page, app, ROOM_NAME);
|
||||
|
||||
await page.locator(".mx_RightPanel").getByRole("menuitem", { name: "People" }).click();
|
||||
await expect(page.locator(".mx_MemberList")).toBeVisible();
|
||||
await expect(page.locator(".mx_MemberListView")).toBeVisible();
|
||||
|
||||
await getMemberTileByName(page, NAME).click();
|
||||
await expect(page.locator(".mx_UserInfo")).toBeVisible();
|
||||
await expect(page.locator(".mx_UserInfo_profile").getByText(NAME)).toBeVisible();
|
||||
|
||||
await page.getByTestId("base-card-back-button").click();
|
||||
await expect(page.locator(".mx_MemberList")).toBeVisible();
|
||||
await expect(page.locator(".mx_MemberListView")).toBeVisible();
|
||||
|
||||
await page.getByLabel("Room info").nth(1).click();
|
||||
await checkRoomSummaryCard(page, ROOM_NAME);
|
||||
@@ -130,14 +130,14 @@ test.describe("RightPanel", () => {
|
||||
.locator(".mx_RoomInfoLine_private")
|
||||
.getByRole("button", { name: /\d member/ })
|
||||
.click();
|
||||
await expect(page.locator(".mx_MemberList")).toBeVisible();
|
||||
await expect(page.locator(".mx_MemberListView")).toBeVisible();
|
||||
|
||||
await getMemberTileByName(page, NAME).click();
|
||||
await expect(page.locator(".mx_UserInfo")).toBeVisible();
|
||||
await expect(page.locator(".mx_UserInfo_profile").getByText(NAME)).toBeVisible();
|
||||
|
||||
await page.getByTestId("base-card-back-button").click();
|
||||
await expect(page.locator(".mx_MemberList")).toBeVisible();
|
||||
await expect(page.locator(".mx_MemberListView")).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -99,6 +99,7 @@ export interface Fixtures {
|
||||
bot: Bot;
|
||||
labsFlags: string[];
|
||||
webserver: Webserver;
|
||||
disablePresence: boolean;
|
||||
}
|
||||
|
||||
export const test = base.extend<Fixtures>({
|
||||
@@ -110,8 +111,9 @@ export const test = base.extend<Fixtures>({
|
||||
);
|
||||
await use(context);
|
||||
},
|
||||
disablePresence: false,
|
||||
config: {}, // We merge this atop the default CONFIG_JSON in the page fixture to make extending it easier
|
||||
page: async ({ homeserver, context, page, config, labsFlags }, use) => {
|
||||
page: async ({ homeserver, context, page, config, labsFlags, disablePresence }, use) => {
|
||||
await context.route(`http://localhost:8080/config.json*`, async (route) => {
|
||||
const json = {
|
||||
...CONFIG_JSON,
|
||||
@@ -131,6 +133,11 @@ export const test = base.extend<Fixtures>({
|
||||
return obj;
|
||||
}, {}),
|
||||
};
|
||||
if (disablePresence) {
|
||||
json["enable_presence_by_hs_url"] = {
|
||||
[homeserver.baseUrl]: false,
|
||||
};
|
||||
}
|
||||
await route.fulfill({ json });
|
||||
});
|
||||
await use(page);
|
||||
|
||||
@@ -177,6 +177,18 @@ export class ElementAppPage {
|
||||
return this.page.locator(".mx_RightPanel");
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens/closes the memberlist panel
|
||||
* @returns locator to the memberlist panel
|
||||
*/
|
||||
public async toggleMemberlistPanel(): Promise<Locator> {
|
||||
const locator = this.page.locator(".mx_FacePile");
|
||||
await locator.click();
|
||||
const memberlist = this.page.locator(".mx_MemberListView");
|
||||
await memberlist.waitFor();
|
||||
return memberlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a locator for the tooltip associated with an element
|
||||
* @param e The element with the tooltip
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -132,6 +132,10 @@ const DEFAULT_CONFIG = {
|
||||
experimental_features: {},
|
||||
oidc_providers: [],
|
||||
serve_server_wellknown: true,
|
||||
presence: {
|
||||
enabled: true,
|
||||
include_offline_users_on_sync: true,
|
||||
},
|
||||
};
|
||||
|
||||
export type SynapseConfigOptions = Partial<typeof DEFAULT_CONFIG>;
|
||||
|
||||
Reference in New Issue
Block a user