Migrate settings/* from Cypress to Playwright (#11949)

* Migrate location.spec.ts from Cypress to Playwright

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Migrate location.spec.ts from Cypress to Playwright

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Migrate appearance-user-settings-tab.spec.ts from Cypress to Playwright

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Migrate device-management.spec.ts from Cypress to Playwright

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Migrate general-room-settings-tab.spec.ts from Cypress to Playwright

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Migrate general-user-settings-tab.spec.ts from Cypress to Playwright

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Migrate preferences-user-settings-tab.spec.ts from Cypress to Playwright

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Migrate security-user-settings-tab.spec.ts from Cypress to Playwright

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Add screenshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Add screenshot

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Deflake

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update screenshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update screenshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Move settings into subclass

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2023-11-29 13:50:13 +00:00 committed by GitHub
parent 8b7f49e74e
commit 1b3f473c10
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 861 additions and 961 deletions

View file

@ -17,70 +17,18 @@ limitations under the License.
import { type Locator, type Page } from "@playwright/test";
import type { IContent, ICreateRoomOpts, ISendEventResponse } from "matrix-js-sdk/src/matrix";
import type { SettingLevel } from "../../src/settings/SettingLevel";
import { Settings } from "./settings";
export class ElementAppPage {
public constructor(private readonly page: Page) {}
/**
* Sets the value for a setting. The room ID is optional if the
* setting is not being set for a particular room, otherwise it
* should be supplied. The value may be null to indicate that the
* level should no longer have an override.
* @param {string} settingName The name of the setting to change.
* @param {String} roomId The room ID to change the value in, may be
* null.
* @param {SettingLevel} level The level to change the value at.
* @param {*} value The new value of the setting, may be null.
* @return {Promise} Resolves when the setting has been changed.
*/
public async setSettingValue(settingName: string, roomId: string, level: SettingLevel, value: any): Promise<void> {
return this.page.evaluate<
Promise<void>,
{
settingName: string;
roomId: string | null;
level: SettingLevel;
value: any;
}
>(
({ settingName, roomId, level, value }) => {
return window.mxSettingsStore.setValue(settingName, roomId, level, value);
},
{ settingName, roomId, level, value },
);
}
public settings = new Settings(this.page);
/**
* Open the top left user menu, returning a Locator to the resulting context menu.
*/
public async openUserMenu(): Promise<Locator> {
await this.page.getByRole("button", { name: "User menu" }).click();
const locator = this.page.locator(".mx_ContextualMenu");
await locator.waitFor();
return locator;
}
/**
* Switch settings tab to the one by the given name
* @param tab the name of the tab to switch to.
*/
public async switchTab(tab: string): Promise<void> {
await this.page
.locator(".mx_TabbedView_tabLabels")
.locator(".mx_TabbedView_tabLabel", { hasText: tab })
.click();
}
/**
* Open user settings (via user menu), returns a locator to the dialog
* @param tab the name of the tab to switch to after opening, optional.
*/
public async openUserSettings(tab?: string): Promise<Locator> {
const locator = await this.openUserMenu();
await locator.getByRole("menuitem", { name: "All settings", exact: true }).click();
if (tab) await this.switchTab(tab);
return this.page.locator(".mx_UserSettingsDialog");
return this.settings.openUserMenu();
}
/**
@ -96,7 +44,7 @@ export class ElementAppPage {
* Close dialog currently open dialog
*/
public async closeDialog(): Promise<void> {
return this.page.getByRole("button", { name: "Close dialog", exact: true }).click();
return this.settings.closeDialog();
}
/**
@ -113,6 +61,34 @@ export class ElementAppPage {
}, options);
}
/**
* Opens the given room by name. The room must be visible in the
* room list, but the room list may be folded horizontally, and the
* room may contain unread messages.
*
* @param name The exact room name to find and click on/open.
*/
public async viewRoomByName(name: string): Promise<void> {
// We look for the room inside the room list, which is a tree called Rooms.
//
// There are 3 cases:
// - the room list is folded:
// then the aria-label on the room tile is the name (with nothing extra)
// - the room list is unfolder and the room has messages:
// then the aria-label contains the unread count, but the title of the
// div inside the titleContainer equals the room name
// - the room list is unfolded and the room has no messages:
// then the aria-label is the name and so is the title of a div
//
// So by matching EITHER title=name OR aria-label=name we find this exact
// room in all three cases.
return this.page
.getByRole("tree", { name: "Rooms" })
.locator(`[title="${name}"],[aria-label="${name}"]`)
.first()
.click();
}
/**
* Get the composer element
* @param isRightPanel whether to select the right panel composer, otherwise the main timeline composer

View file

@ -0,0 +1,102 @@
/*
Copyright 2023 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { Locator, Page } from "@playwright/test";
import type { SettingLevel } from "../../src/settings/SettingLevel";
export class Settings {
public constructor(private readonly page: Page) {}
/**
* Open the top left user menu, returning a Locator to the resulting context menu.
*/
public async openUserMenu(): Promise<Locator> {
await this.page.getByRole("button", { name: "User menu" }).click();
const locator = this.page.locator(".mx_ContextualMenu");
await locator.waitFor();
return locator;
}
/**
* Close dialog currently open dialog
*/
public async closeDialog(): Promise<void> {
return this.page.getByRole("button", { name: "Close dialog", exact: true }).click();
}
/**
* Sets the value for a setting. The room ID is optional if the
* setting is not being set for a particular room, otherwise it
* should be supplied. The value may be null to indicate that the
* level should no longer have an override.
* @param {string} settingName The name of the setting to change.
* @param {String} roomId The room ID to change the value in, may be
* null.
* @param {SettingLevel} level The level to change the value at.
* @param {*} value The new value of the setting, may be null.
* @return {Promise} Resolves when the setting has been changed.
*/
public async setValue(settingName: string, roomId: string, level: SettingLevel, value: any): Promise<void> {
return this.page.evaluate<
Promise<void>,
{
settingName: string;
roomId: string | null;
level: SettingLevel;
value: any;
}
>(
({ settingName, roomId, level, value }) => {
return window.mxSettingsStore.setValue(settingName, roomId, level, value);
},
{ settingName, roomId, level, value },
);
}
/**
* Switch settings tab to the one by the given name
* @param tab the name of the tab to switch to.
*/
public async switchTab(tab: string): Promise<void> {
await this.page
.locator(".mx_TabbedView_tabLabels")
.locator(".mx_TabbedView_tabLabel", { hasText: tab })
.click();
}
/**
* Open user settings (via user menu), returns a locator to the dialog
* @param tab the name of the tab to switch to after opening, optional.
*/
public async openUserSettings(tab?: string): Promise<Locator> {
const locator = await this.openUserMenu();
await locator.getByRole("menuitem", { name: "All settings", exact: true }).click();
if (tab) await this.switchTab(tab);
return this.page.locator(".mx_Dialog").filter({ has: this.page.locator(".mx_UserSettingsDialog") });
}
/**
* Open room settings (via room menu), returns a locator to the dialog
* @param tab the name of the tab to switch to after opening, optional.
*/
public async openRoomSettings(tab?: string): Promise<Locator> {
await this.page.getByRole("main").getByRole("button", { name: "Room options", exact: true }).click();
await this.page.locator(".mx_RoomTile_contextMenu").getByRole("menuitem", { name: "Settings" }).click();
if (tab) await this.switchTab(tab);
return this.page.locator(".mx_Dialog").filter({ has: this.page.locator(".mx_RoomSettingsDialog") });
}
}