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:
parent
8b7f49e74e
commit
1b3f473c10
32 changed files with 861 additions and 961 deletions
251
playwright/e2e/settings/appearance-user-settings-tab.spec.ts
Normal file
251
playwright/e2e/settings/appearance-user-settings-tab.spec.ts
Normal file
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
Copyright 2023 Suguru Hirahara
|
||||
|
||||
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 { test, expect } from "../../element-web-test";
|
||||
import { SettingLevel } from "../../../src/settings/SettingLevel";
|
||||
|
||||
test.describe("Appearance user settings tab", () => {
|
||||
test.use({
|
||||
displayName: "Hanako",
|
||||
});
|
||||
|
||||
test("should be rendered properly", async ({ page, user, app }) => {
|
||||
const tab = await app.settings.openUserSettings("Appearance");
|
||||
|
||||
await expect(tab.getByRole("heading", { name: "Customise your appearance" })).toBeVisible();
|
||||
|
||||
// Click "Show advanced" link button
|
||||
await tab.getByRole("button", { name: "Show advanced" }).click();
|
||||
|
||||
// Assert that "Hide advanced" link button is rendered
|
||||
await expect(tab.getByRole("button", { name: "Hide advanced" })).toBeVisible();
|
||||
|
||||
await expect(tab).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test("should support switching layouts", async ({ page, user, app }) => {
|
||||
// Create and view a room first
|
||||
await app.createRoom({ name: "Test Room" });
|
||||
await app.viewRoomByName("Test Room");
|
||||
|
||||
await app.settings.openUserSettings("Appearance");
|
||||
|
||||
const buttons = page.locator(".mx_LayoutSwitcher_RadioButton");
|
||||
|
||||
// Assert that the layout selected by default is "Modern"
|
||||
await expect(
|
||||
buttons.locator(".mx_StyledRadioButton_enabled", {
|
||||
hasText: "Modern",
|
||||
}),
|
||||
).toBeVisible();
|
||||
|
||||
// Assert that the room layout is set to group (modern) layout
|
||||
await expect(page.locator(".mx_RoomView_body[data-layout='group']")).toBeVisible();
|
||||
|
||||
// Select the first layout
|
||||
await buttons.first().click();
|
||||
// Assert that the layout selected is "IRC (Experimental)"
|
||||
await expect(buttons.locator(".mx_StyledRadioButton_enabled", { hasText: "IRC (Experimental)" })).toBeVisible();
|
||||
|
||||
// Assert that the room layout is set to IRC layout
|
||||
await expect(page.locator(".mx_RoomView_body[data-layout='irc']")).toBeVisible();
|
||||
|
||||
// Select the last layout
|
||||
await buttons.last().click();
|
||||
|
||||
// Assert that the layout selected is "Message bubbles"
|
||||
await expect(buttons.locator(".mx_StyledRadioButton_enabled", { hasText: "Message bubbles" })).toBeVisible();
|
||||
|
||||
// Assert that the room layout is set to bubble layout
|
||||
await expect(page.locator(".mx_RoomView_body[data-layout='bubble']")).toBeVisible();
|
||||
});
|
||||
|
||||
test("should support changing font size by clicking the font slider", async ({ page, app, user }) => {
|
||||
await app.settings.openUserSettings("Appearance");
|
||||
|
||||
const tab = page.getByTestId("mx_AppearanceUserSettingsTab");
|
||||
const fontSliderSection = tab.locator(".mx_FontScalingPanel_fontSlider");
|
||||
|
||||
await expect(fontSliderSection.getByLabel("Font size")).toBeVisible();
|
||||
|
||||
const slider = fontSliderSection.getByRole("slider");
|
||||
// Click the left position of the slider
|
||||
await slider.click({ position: { x: 0, y: 10 } });
|
||||
|
||||
const MIN_FONT_SIZE = 11;
|
||||
// Assert that the smallest font size is selected
|
||||
await expect(fontSliderSection.locator(`input[value='${MIN_FONT_SIZE}']`)).toBeVisible();
|
||||
await expect(
|
||||
fontSliderSection.locator("output .mx_Slider_selection_label", { hasText: String(MIN_FONT_SIZE) }),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(fontSliderSection).toHaveScreenshot(`font-slider-${MIN_FONT_SIZE}.png`);
|
||||
|
||||
// Click the right position of the slider
|
||||
await slider.click({ position: { x: 572, y: 10 } });
|
||||
|
||||
const MAX_FONT_SIZE = 21;
|
||||
// Assert that the largest font size is selected
|
||||
await expect(fontSliderSection.locator(`input[value='${MAX_FONT_SIZE}']`)).toBeVisible();
|
||||
await expect(
|
||||
fontSliderSection.locator("output .mx_Slider_selection_label", { hasText: String(MAX_FONT_SIZE) }),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(fontSliderSection).toHaveScreenshot(`font-slider-${MAX_FONT_SIZE}.png`);
|
||||
});
|
||||
|
||||
test("should disable font size slider when custom font size is used", async ({ page, app, user }) => {
|
||||
await app.settings.openUserSettings("Appearance");
|
||||
|
||||
const panel = page.getByTestId("mx_FontScalingPanel");
|
||||
await panel.locator("label", { hasText: "Use custom size" }).click();
|
||||
|
||||
// Assert that the font slider is disabled
|
||||
await expect(panel.locator(".mx_FontScalingPanel_fontSlider input[disabled]")).toBeVisible();
|
||||
});
|
||||
|
||||
test("should support enabling compact group (modern) layout", async ({ page, app, user }) => {
|
||||
// Create and view a room first
|
||||
await app.createRoom({ name: "Test Room" });
|
||||
await app.viewRoomByName("Test Room");
|
||||
|
||||
await app.settings.openUserSettings("Appearance");
|
||||
|
||||
// Click "Show advanced" link button
|
||||
const tab = page.getByTestId("mx_AppearanceUserSettingsTab");
|
||||
await tab.getByRole("button", { name: "Show advanced" }).click();
|
||||
|
||||
await tab.locator("label", { hasText: "Use a more compact 'Modern' layout" }).click();
|
||||
|
||||
// Assert that the room layout is set to compact group (modern) layout
|
||||
await expect(page.locator("#matrixchat .mx_MatrixChat_wrapper.mx_MatrixChat_useCompactLayout")).toBeVisible();
|
||||
});
|
||||
|
||||
test("should disable compact group (modern) layout option on IRC layout and bubble layout", async ({
|
||||
page,
|
||||
app,
|
||||
user,
|
||||
}) => {
|
||||
await app.settings.openUserSettings("Appearance");
|
||||
const tab = page.getByTestId("mx_AppearanceUserSettingsTab");
|
||||
|
||||
const checkDisabled = async () => {
|
||||
await expect(tab.getByRole("checkbox", { name: "Use a more compact 'Modern' layout" })).toBeDisabled();
|
||||
};
|
||||
|
||||
// Click "Show advanced" link button
|
||||
await tab.getByRole("button", { name: "Show advanced" }).click();
|
||||
|
||||
const buttons = page.locator(".mx_LayoutSwitcher_RadioButton");
|
||||
|
||||
// Enable IRC layout
|
||||
await buttons.first().click();
|
||||
|
||||
// Assert that the layout selected is "IRC (Experimental)"
|
||||
await expect(buttons.locator(".mx_StyledRadioButton_enabled", { hasText: "IRC (Experimental)" })).toBeVisible();
|
||||
|
||||
await checkDisabled();
|
||||
|
||||
// Enable bubble layout
|
||||
await buttons.last().click();
|
||||
|
||||
// Assert that the layout selected is "IRC (Experimental)"
|
||||
await expect(buttons.locator(".mx_StyledRadioButton_enabled", { hasText: "Message bubbles" })).toBeVisible();
|
||||
|
||||
await checkDisabled();
|
||||
});
|
||||
|
||||
test("should support enabling system font", async ({ page, app, user }) => {
|
||||
await app.settings.openUserSettings("Appearance");
|
||||
const tab = page.getByTestId("mx_AppearanceUserSettingsTab");
|
||||
|
||||
// Click "Show advanced" link button
|
||||
await tab.getByRole("button", { name: "Show advanced" }).click();
|
||||
|
||||
await tab.locator(".mx_Checkbox", { hasText: "Use bundled emoji font" }).click();
|
||||
await tab.locator(".mx_Checkbox", { hasText: "Use a system font" }).click();
|
||||
|
||||
// Assert that the font-family value was removed
|
||||
await expect(page.locator("body")).toHaveCSS("font-family", '""');
|
||||
});
|
||||
|
||||
test.describe("Theme Choice Panel", () => {
|
||||
test.beforeEach(async ({ app, user }) => {
|
||||
// Disable the default theme for consistency in case ThemeWatcher automatically chooses it
|
||||
await app.settings.setValue("use_system_theme", null, SettingLevel.DEVICE, false);
|
||||
});
|
||||
|
||||
test("should be rendered with the light theme selected", async ({ page, app }) => {
|
||||
await app.settings.openUserSettings("Appearance");
|
||||
const themePanel = page.getByTestId("mx_ThemeChoicePanel");
|
||||
|
||||
const useSystemTheme = themePanel.getByTestId("checkbox-use-system-theme");
|
||||
await expect(useSystemTheme.getByText("Match system theme")).toBeVisible();
|
||||
// Assert that 'Match system theme' is not checked
|
||||
// Note that mx_Checkbox_checkmark exists and is hidden by CSS if it is not checked
|
||||
await expect(useSystemTheme.locator(".mx_Checkbox_checkmark")).not.toBeVisible();
|
||||
|
||||
const selectors = themePanel.getByTestId("theme-choice-panel-selectors");
|
||||
await expect(selectors.locator(".mx_ThemeSelector_light")).toBeVisible();
|
||||
await expect(selectors.locator(".mx_ThemeSelector_dark")).toBeVisible();
|
||||
// Assert that the light theme is selected
|
||||
await expect(selectors.locator(".mx_ThemeSelector_light.mx_StyledRadioButton_enabled")).toBeVisible();
|
||||
// Assert that the buttons for the light and dark theme are not enabled
|
||||
await expect(selectors.locator(".mx_ThemeSelector_light.mx_StyledRadioButton_disabled")).not.toBeVisible();
|
||||
await expect(selectors.locator(".mx_ThemeSelector_dark.mx_StyledRadioButton_disabled")).not.toBeVisible();
|
||||
|
||||
// Assert that the checkbox for the high contrast theme is rendered
|
||||
await expect(themePanel.locator(".mx_Checkbox", { hasText: "Use high contrast" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("should disable the labels for themes and the checkbox for the high contrast theme if the checkbox for the system theme is clicked", async ({
|
||||
page,
|
||||
app,
|
||||
}) => {
|
||||
await app.settings.openUserSettings("Appearance");
|
||||
const themePanel = page.getByTestId("mx_ThemeChoicePanel");
|
||||
|
||||
await themePanel.locator(".mx_Checkbox", { hasText: "Match system theme" }).click();
|
||||
|
||||
// Assert that the labels for the light theme and dark theme are disabled
|
||||
await expect(themePanel.locator(".mx_ThemeSelector_light.mx_StyledRadioButton_disabled")).toBeVisible();
|
||||
await expect(themePanel.locator(".mx_ThemeSelector_dark.mx_StyledRadioButton_disabled")).toBeVisible();
|
||||
|
||||
// Assert that there does not exist a label for an enabled theme
|
||||
await expect(themePanel.locator("label.mx_StyledRadioButton_enabled")).not.toBeVisible();
|
||||
|
||||
// Assert that the checkbox and label to enable the high contrast theme should not exist
|
||||
await expect(themePanel.locator(".mx_Checkbox", { hasText: "Use high contrast" })).not.toBeVisible();
|
||||
});
|
||||
|
||||
test("should not render the checkbox and the label for the high contrast theme if the dark theme is selected", async ({
|
||||
page,
|
||||
app,
|
||||
}) => {
|
||||
await app.settings.openUserSettings("Appearance");
|
||||
const themePanel = page.getByTestId("mx_ThemeChoicePanel");
|
||||
|
||||
// Assert that the checkbox and the label to enable the high contrast theme should exist
|
||||
await expect(themePanel.locator(".mx_Checkbox", { hasText: "Use high contrast" })).toBeVisible();
|
||||
|
||||
// Enable the dark theme
|
||||
await themePanel.locator(".mx_ThemeSelector_dark").click();
|
||||
|
||||
// Assert that the checkbox and the label should not exist
|
||||
await expect(themePanel.locator(".mx_Checkbox", { hasText: "Use high contrast" })).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
105
playwright/e2e/settings/device-management.spec.ts
Normal file
105
playwright/e2e/settings/device-management.spec.ts
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
Copyright 2022 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 { test, expect } from "../../element-web-test";
|
||||
|
||||
test.describe("Device manager", () => {
|
||||
test.use({
|
||||
displayName: "Alice",
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ homeserver, user }) => {
|
||||
// create 3 extra sessions to manage
|
||||
for (let i = 0; i < 3; i++) {
|
||||
await homeserver.loginUser(user.userId, user.password);
|
||||
}
|
||||
});
|
||||
|
||||
test("should display sessions", async ({ page, app }) => {
|
||||
await app.settings.openUserSettings("Sessions");
|
||||
const tab = page.locator(".mx_SettingsTab");
|
||||
|
||||
await expect(tab.getByText("Current session", { exact: true })).toBeVisible();
|
||||
|
||||
const currentSessionSection = tab.getByTestId("current-session-section");
|
||||
await expect(currentSessionSection.getByText("Unverified session")).toBeVisible();
|
||||
|
||||
// current session details opened
|
||||
await currentSessionSection.getByRole("button", { name: "Show details" }).click();
|
||||
await expect(currentSessionSection.getByText("Session details")).toBeVisible();
|
||||
|
||||
// close current session details
|
||||
await currentSessionSection.getByRole("button", { name: "Hide details" }).click();
|
||||
await expect(currentSessionSection.getByText("Session details")).not.toBeVisible();
|
||||
|
||||
const securityRecommendationsSection = tab.getByTestId("security-recommendations-section");
|
||||
await expect(securityRecommendationsSection.getByText("Security recommendations")).toBeVisible();
|
||||
await securityRecommendationsSection.getByRole("button", { name: "View all (3)" }).click();
|
||||
|
||||
/**
|
||||
* Other sessions section
|
||||
*/
|
||||
await expect(tab.getByText("Other sessions")).toBeVisible();
|
||||
// filter applied after clicking through from security recommendations
|
||||
await expect(tab.getByLabel("Filter devices")).toHaveText("Show: Unverified");
|
||||
const filteredDeviceListItems = tab.locator(".mx_FilteredDeviceList_listItem");
|
||||
await expect(filteredDeviceListItems).toHaveCount(3);
|
||||
|
||||
// select two sessions
|
||||
// force click as the input element itself is not visible (its size is zero)
|
||||
await filteredDeviceListItems.first().click({ force: true });
|
||||
await filteredDeviceListItems.last().click({ force: true });
|
||||
|
||||
// sign out from list selection action buttons
|
||||
await tab.getByRole("button", { name: "Sign out", exact: true }).click();
|
||||
await page.getByRole("dialog").getByTestId("dialog-primary-button").click();
|
||||
|
||||
// list updated after sign out
|
||||
await expect(filteredDeviceListItems).toHaveCount(1);
|
||||
// security recommendation count updated
|
||||
await expect(tab.getByRole("button", { name: "View all (1)" })).toBeVisible();
|
||||
|
||||
const sessionName = `Alice's device`;
|
||||
// open the first session
|
||||
const firstSession = filteredDeviceListItems.first();
|
||||
await firstSession.getByRole("button", { name: "Show details" }).click();
|
||||
|
||||
await expect(firstSession.getByText("Session details")).toBeVisible();
|
||||
|
||||
await firstSession.getByRole("button", { name: "Rename" }).click();
|
||||
await firstSession.getByTestId("device-rename-input").type(sessionName);
|
||||
await firstSession.getByRole("button", { name: "Save" }).click();
|
||||
// there should be a spinner while device updates
|
||||
await expect(firstSession.locator(".mx_Spinner")).toBeVisible();
|
||||
// wait for spinner to complete
|
||||
await expect(firstSession.locator(".mx_Spinner")).not.toBeVisible();
|
||||
|
||||
// session name updated in details
|
||||
await expect(firstSession.locator(".mx_DeviceDetailHeading h4").getByText(sessionName)).toBeVisible();
|
||||
// and main list item
|
||||
await expect(firstSession.locator(".mx_DeviceTile h4").getByText(sessionName)).toBeVisible();
|
||||
|
||||
// sign out using the device details sign out
|
||||
await firstSession.getByRole("button", { name: "Sign out of this session" }).click();
|
||||
|
||||
// confirm the signout
|
||||
await page.getByRole("dialog").getByTestId("dialog-primary-button").click();
|
||||
|
||||
// no other sessions or security recommendations sections when only one session
|
||||
await expect(tab.getByText("Other sessions")).not.toBeVisible();
|
||||
await expect(tab.getByTestId("security-recommendations-section")).not.toBeVisible();
|
||||
});
|
||||
});
|
63
playwright/e2e/settings/general-room-settings-tab.spec.ts
Normal file
63
playwright/e2e/settings/general-room-settings-tab.spec.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
Copyright 2023 Suguru Hirahara
|
||||
|
||||
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 { test, expect } from "../../element-web-test";
|
||||
|
||||
test.describe("General room settings tab", () => {
|
||||
const roomName = "Test Room";
|
||||
|
||||
test.use({
|
||||
displayName: "Hanako",
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ user, app }) => {
|
||||
await app.createRoom({ name: roomName });
|
||||
await app.viewRoomByName(roomName);
|
||||
});
|
||||
|
||||
test("should be rendered properly", async ({ page, app }) => {
|
||||
const settings = await app.settings.openRoomSettings("General");
|
||||
|
||||
// Assert that "Show less" details element is rendered
|
||||
await expect(settings.getByText("Show less")).toBeVisible();
|
||||
|
||||
await expect(settings).toHaveScreenshot();
|
||||
|
||||
// Click the "Show less" details element
|
||||
await settings.getByText("Show less").click();
|
||||
|
||||
// Assert that "Show more" details element is rendered instead of "Show more"
|
||||
await expect(settings.getByText("Show less")).not.toBeVisible();
|
||||
await expect(settings.getByText("Show more")).toBeVisible();
|
||||
});
|
||||
|
||||
test("long address should not cause dialog to overflow", async ({ page, app }) => {
|
||||
const settings = await app.settings.openRoomSettings("General");
|
||||
// 1. Set the room-address to be a really long string
|
||||
const longString = "abcasdhjasjhdaj1jh1asdhasjdhajsdhjavhjksd".repeat(4);
|
||||
await settings.locator("#roomAliases input[label='Room address']").fill(longString);
|
||||
await settings.locator("#roomAliases").getByText("Add", { exact: true }).click();
|
||||
|
||||
// 2. wait for the new setting to apply ...
|
||||
await expect(settings.locator("#canonicalAlias")).toHaveValue(`#${longString}:localhost`);
|
||||
|
||||
// 3. Check if the dialog overflows
|
||||
const dialogBoundingBox = await page.locator(".mx_Dialog").boundingBox();
|
||||
const inputBoundingBox = await settings.locator("#canonicalAlias").boundingBox();
|
||||
// Assert that the width of the select element is less than that of .mx_Dialog div.
|
||||
expect(inputBoundingBox.width).toBeLessThan(dialogBoundingBox.width);
|
||||
});
|
||||
});
|
189
playwright/e2e/settings/general-user-settings-tab.spec.ts
Normal file
189
playwright/e2e/settings/general-user-settings-tab.spec.ts
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
Copyright 2023 Suguru Hirahara
|
||||
|
||||
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 { test, expect } from "../../element-web-test";
|
||||
|
||||
const USER_NAME = "Bob";
|
||||
const USER_NAME_NEW = "Alice";
|
||||
const IntegrationManager = "scalar.vector.im";
|
||||
|
||||
test.describe("General user settings tab", () => {
|
||||
let userId: string;
|
||||
|
||||
test.use({
|
||||
displayName: USER_NAME,
|
||||
config: {
|
||||
default_country_code: "US", // For checking the international country calling code
|
||||
},
|
||||
uut: async ({ app, user }, use) => {
|
||||
const locator = await app.settings.openUserSettings("General");
|
||||
await use(locator);
|
||||
},
|
||||
});
|
||||
|
||||
test("should be rendered properly", async ({ uut }) => {
|
||||
await expect(uut).toHaveScreenshot("general.png", {
|
||||
// Exclude userId from snapshots
|
||||
mask: [uut.locator(".mx_ProfileSettings_profile_controls > p")],
|
||||
});
|
||||
|
||||
// Assert that the top heading is rendered
|
||||
await expect(uut.getByRole("heading", { name: "General" })).toBeVisible();
|
||||
|
||||
const profile = uut.locator(".mx_ProfileSettings_profile");
|
||||
await profile.scrollIntoViewIfNeeded();
|
||||
await expect(profile.getByRole("textbox", { name: "Display Name" })).toHaveValue(USER_NAME);
|
||||
|
||||
// Assert that a userId is rendered
|
||||
await expect(profile.locator(".mx_ProfileSettings_profile_controls_userId", { hasText: userId })).toBeVisible();
|
||||
|
||||
// Check avatar setting
|
||||
const avatar = profile.locator(".mx_AvatarSetting_avatar");
|
||||
await avatar.hover();
|
||||
|
||||
// Hover effect
|
||||
await expect(avatar.locator(".mx_AvatarSetting_hoverBg")).toBeVisible();
|
||||
await expect(avatar.locator(".mx_AvatarSetting_hover span").getByText("Upload")).toBeVisible();
|
||||
|
||||
// Wait until spinners disappear
|
||||
await expect(uut.getByTestId("accountSection").locator(".mx_Spinner")).not.toBeVisible();
|
||||
await expect(uut.getByTestId("discoverySection").locator(".mx_Spinner")).not.toBeVisible();
|
||||
|
||||
const accountSection = uut.getByTestId("accountSection");
|
||||
// Assert that input areas for changing a password exists
|
||||
const changePassword = accountSection.locator("form.mx_GeneralUserSettingsTab_section--account_changePassword");
|
||||
await changePassword.scrollIntoViewIfNeeded();
|
||||
await expect(changePassword.getByLabel("Current password")).toBeVisible();
|
||||
await expect(changePassword.getByLabel("New Password")).toBeVisible();
|
||||
await expect(changePassword.getByLabel("Confirm password")).toBeVisible();
|
||||
|
||||
// Check email addresses area
|
||||
const emailAddresses = uut.getByTestId("mx_AccountEmailAddresses");
|
||||
await emailAddresses.scrollIntoViewIfNeeded();
|
||||
// Assert that an input area for a new email address is rendered
|
||||
await expect(emailAddresses.getByRole("textbox", { name: "Email Address" })).toBeVisible();
|
||||
// Assert the add button is visible
|
||||
await expect(emailAddresses.getByRole("button", { name: "Add" })).toBeVisible();
|
||||
|
||||
// Check phone numbers area
|
||||
const phoneNumbers = uut.getByTestId("mx_AccountPhoneNumbers");
|
||||
await phoneNumbers.scrollIntoViewIfNeeded();
|
||||
// Assert that an input area for a new phone number is rendered
|
||||
await expect(phoneNumbers.getByRole("textbox", { name: "Phone Number" })).toBeVisible();
|
||||
// Assert that the add button is rendered
|
||||
await expect(phoneNumbers.getByRole("button", { name: "Add" })).toBeVisible();
|
||||
|
||||
// Check language and region setting dropdown
|
||||
const languageInput = uut.locator(".mx_GeneralUserSettingsTab_section_languageInput");
|
||||
await languageInput.scrollIntoViewIfNeeded();
|
||||
// Check the default value
|
||||
await expect(languageInput.getByText("English")).toBeVisible();
|
||||
// Click the button to display the dropdown menu
|
||||
await languageInput.getByRole("button", { name: "Language Dropdown" }).click();
|
||||
// Assert that the default option is rendered and highlighted
|
||||
languageInput.getByRole("option", { name: /Albanian/ });
|
||||
await expect(languageInput.getByRole("option", { name: /Albanian/ })).toHaveClass(
|
||||
/mx_Dropdown_option_highlight/,
|
||||
);
|
||||
await expect(languageInput.getByRole("option", { name: /Deutsch/ })).toBeVisible();
|
||||
// Click again to close the dropdown
|
||||
await languageInput.getByRole("button", { name: "Language Dropdown" }).click();
|
||||
// Assert that the default value is rendered again
|
||||
await expect(languageInput.getByText("English")).toBeVisible();
|
||||
|
||||
const setIdServer = uut.locator(".mx_SetIdServer");
|
||||
await setIdServer.scrollIntoViewIfNeeded();
|
||||
// Assert that an input area for identity server exists
|
||||
await expect(setIdServer.getByRole("textbox", { name: "Enter a new identity server" })).toBeVisible();
|
||||
|
||||
const setIntegrationManager = uut.locator(".mx_SetIntegrationManager");
|
||||
await setIntegrationManager.scrollIntoViewIfNeeded();
|
||||
await expect(
|
||||
setIntegrationManager.locator(".mx_SetIntegrationManager_heading_manager", { hasText: IntegrationManager }),
|
||||
).toBeVisible();
|
||||
// Make sure integration manager's toggle switch is enabled
|
||||
await expect(setIntegrationManager.locator(".mx_ToggleSwitch_enabled")).toBeVisible();
|
||||
await expect(setIntegrationManager.locator(".mx_SetIntegrationManager_heading_manager")).toHaveText(
|
||||
"Manage integrations(scalar.vector.im)",
|
||||
);
|
||||
|
||||
// Assert the account deactivation button is displayed
|
||||
const accountManagementSection = uut.getByTestId("account-management-section");
|
||||
await accountManagementSection.scrollIntoViewIfNeeded();
|
||||
await expect(accountManagementSection.getByRole("button", { name: "Deactivate Account" })).toHaveClass(
|
||||
/mx_AccessibleButton_kind_danger/,
|
||||
);
|
||||
});
|
||||
|
||||
test("should support adding and removing a profile picture", async ({ uut }) => {
|
||||
const profileSettings = uut.locator(".mx_ProfileSettings");
|
||||
// Upload a picture
|
||||
await profileSettings
|
||||
.locator(".mx_ProfileSettings_avatarUpload")
|
||||
.setInputFiles("playwright/sample-files/riot.png");
|
||||
|
||||
// Find and click "Remove" link button
|
||||
await profileSettings.locator(".mx_ProfileSettings_profile").getByRole("button", { name: "Remove" }).click();
|
||||
|
||||
// Assert that the link button disappeared
|
||||
await expect(
|
||||
profileSettings.locator(".mx_AvatarSetting_avatar .mx_AccessibleButton_kind_link_sm"),
|
||||
).not.toBeVisible();
|
||||
});
|
||||
|
||||
test("should set a country calling code based on default_country_code", async ({ uut }) => {
|
||||
// Check phone numbers area
|
||||
const accountPhoneNumbers = uut.getByTestId("mx_AccountPhoneNumbers");
|
||||
await accountPhoneNumbers.scrollIntoViewIfNeeded();
|
||||
// Assert that an input area for a new phone number is rendered
|
||||
await expect(accountPhoneNumbers.getByRole("textbox", { name: "Phone Number" })).toBeVisible();
|
||||
|
||||
// Check a new phone number dropdown menu
|
||||
const dropdown = accountPhoneNumbers.locator(".mx_PhoneNumbers_country");
|
||||
await dropdown.scrollIntoViewIfNeeded();
|
||||
// Assert that the country calling code of the United States is visible
|
||||
await expect(dropdown.getByText(/\+1/)).toBeVisible();
|
||||
|
||||
// Click the button to display the dropdown menu
|
||||
await dropdown.getByRole("button", { name: "Country Dropdown" }).click();
|
||||
|
||||
// Assert that the option for calling code of the United Kingdom is visible
|
||||
await expect(dropdown.getByRole("option", { name: /United Kingdom/ })).toBeVisible();
|
||||
|
||||
// Click again to close the dropdown
|
||||
await dropdown.getByRole("button", { name: "Country Dropdown" }).click();
|
||||
|
||||
// Assert that the default value is rendered again
|
||||
await expect(dropdown.getByText(/\+1/)).toBeVisible();
|
||||
|
||||
await expect(accountPhoneNumbers.getByRole("button", { name: "Add" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("should support changing a display name", async ({ uut, page, app }) => {
|
||||
// Change the diaplay name to USER_NAME_NEW
|
||||
const displayNameInput = uut
|
||||
.locator(".mx_SettingsTab .mx_ProfileSettings")
|
||||
.getByRole("textbox", { name: "Display Name" });
|
||||
await displayNameInput.fill(USER_NAME_NEW);
|
||||
await displayNameInput.press("Enter");
|
||||
|
||||
await app.closeDialog();
|
||||
|
||||
// Assert the avatar's initial characters are set
|
||||
await expect(page.locator(".mx_UserMenu .mx_BaseAvatar").getByText("A")).toBeVisible(); // Alice
|
||||
await expect(page.locator(".mx_RoomView_wrapper .mx_BaseAvatar").getByText("A")).toBeVisible(); // Alice
|
||||
});
|
||||
});
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Copyright 2023 Suguru Hirahara
|
||||
|
||||
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 { test, expect } from "../../element-web-test";
|
||||
|
||||
test.describe("Preferences user settings tab", () => {
|
||||
test.use({
|
||||
displayName: "Bob",
|
||||
});
|
||||
|
||||
test("should be rendered properly", async ({ app, user }) => {
|
||||
const tab = await app.settings.openUserSettings("Preferences");
|
||||
|
||||
// Assert that the top heading is rendered
|
||||
await expect(tab.getByRole("heading", { name: "Preferences" })).toBeVisible();
|
||||
await expect(tab).toHaveScreenshot();
|
||||
});
|
||||
});
|
51
playwright/e2e/settings/security-user-settings-tab.spec.ts
Normal file
51
playwright/e2e/settings/security-user-settings-tab.spec.ts
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright 2023 Suguru Hirahara
|
||||
|
||||
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 { test, expect } from "../../element-web-test";
|
||||
|
||||
test.describe("Security user settings tab", () => {
|
||||
test.describe("with posthog enabled", () => {
|
||||
test.use({
|
||||
displayName: "Hanako",
|
||||
// Enable posthog
|
||||
config: {
|
||||
posthog: {
|
||||
project_api_key: "foo",
|
||||
api_host: "bar",
|
||||
},
|
||||
privacy_policy_url: "example.tld", // Set privacy policy URL to enable privacyPolicyLink
|
||||
},
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, user }) => {
|
||||
// Dismiss "Notification" toast
|
||||
await page
|
||||
.locator(".mx_Toast_toast", { hasText: "Notifications" })
|
||||
.getByRole("button", { name: "Dismiss" })
|
||||
.click();
|
||||
|
||||
await page.locator(".mx_Toast_buttons").getByRole("button", { name: "Yes" }).click(); // Allow analytics
|
||||
});
|
||||
|
||||
test.describe("AnalyticsLearnMoreDialog", () => {
|
||||
test("should be rendered properly", async ({ app, page }) => {
|
||||
const tab = await app.settings.openUserSettings("Security");
|
||||
await tab.getByRole("button", { name: "Learn more" }).click();
|
||||
await expect(page.locator(".mx_AnalyticsLearnMoreDialog_wrapper .mx_Dialog")).toHaveScreenshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue