From 8efef66c5cd745c169bc4f7deb448e3d9e4fee90 Mon Sep 17 00:00:00 2001 From: Alejandra <90076947+alejsdev@users.noreply.github.com> Date: Tue, 30 Jul 2024 12:48:36 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20User=20Settings=20e2e=20tests?= =?UTF-8?q?=20=20(#1271)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UserSettings/ChangePassword.tsx | 2 +- frontend/tests/user-settings.spec.ts | 288 ++++++++++++++++++ frontend/tests/utils/user.ts | 4 +- 3 files changed, 291 insertions(+), 3 deletions(-) create mode 100644 frontend/tests/user-settings.spec.ts diff --git a/frontend/src/components/UserSettings/ChangePassword.tsx b/frontend/src/components/UserSettings/ChangePassword.tsx index 0698e1a..439ee80 100644 --- a/frontend/src/components/UserSettings/ChangePassword.tsx +++ b/frontend/src/components/UserSettings/ChangePassword.tsx @@ -38,7 +38,7 @@ const ChangePassword = () => { mutationFn: (data: UpdatePassword) => UsersService.updatePasswordMe({ requestBody: data }), onSuccess: () => { - showToast("Success!", "Password updated.", "success") + showToast("Success!", "Password updated successfully.", "success") reset() }, onError: (err: ApiError) => { diff --git a/frontend/tests/user-settings.spec.ts b/frontend/tests/user-settings.spec.ts new file mode 100644 index 0000000..b24f1ec --- /dev/null +++ b/frontend/tests/user-settings.spec.ts @@ -0,0 +1,288 @@ +import { expect, test } from "@playwright/test" +import { randomEmail } from "./utils/random" +import { logInUser, logOutUser, signUpNewUser } from "./utils/user" +import { firstSuperuser, firstSuperuserPassword } from "./config.ts" + +const tabs = ["My profile", "Password", "Appearance"] + +// User Information + +test("My profile tab is active by default", async ({ page }) => { + await page.goto("/settings") + await expect(page.getByRole("tab", { name: "My profile" })).toHaveAttribute( + "aria-selected", + "true", + ) +}) + +test("All tabs are visible", async ({ page }) => { + await page.goto("/settings") + for (const tab of tabs) { + await expect(page.getByRole("tab", { name: tab })).toBeVisible() + } +}) + +test.describe("Edit user full name and email successfully", () => { + test.use({ storageState: { cookies: [], origins: [] } }) + + test("Edit user name with a valid name", async ({ page }) => { + const fullName = "Test User" + const email = randomEmail() + const updatedName = "Test User 2" + const password = "password" + + // Sign up a new user + await signUpNewUser(page, fullName, email, password) + + // Log in the user + await logInUser(page, email, password) + + await page.goto("/settings") + await page.getByRole("tab", { name: "My profile" }).click() + await page.getByRole("button", { name: "Edit" }).click() + await page.getByLabel("Full name").fill(updatedName) + await page.getByRole("button", { name: "Save" }).click() + await expect(page.getByText("User updated successfully")).toBeVisible() + // Check if the new name is displayed on the page + await expect( + page.getByLabel("My profile").getByText(updatedName, { exact: true }), + ).toBeVisible() + }) + + test("Edit user email with a valid email", async ({ page }) => { + const fullName = "Test User" + const email = randomEmail() + const updatedEmail = randomEmail() + const password = "password" + + // Sign up a new user + await signUpNewUser(page, fullName, email, password) + + // Log in the user + await logInUser(page, email, password) + + await page.goto("/settings") + await page.getByRole("tab", { name: "My profile" }).click() + await page.getByRole("button", { name: "Edit" }).click() + await page.getByLabel("Email").fill(updatedEmail) + await page.getByRole("button", { name: "Save" }).click() + await expect(page.getByText("User updated successfully")).toBeVisible() + await expect( + page.getByLabel("My profile").getByText(updatedEmail, { exact: true }), + ).toBeVisible() + }) +}) + +test.describe("Edit user with invalid data", () => { + test.use({ storageState: { cookies: [], origins: [] } }) + + test("Edit user email with an invalid email", async ({ page }) => { + const fullName = "Test User" + const email = randomEmail() + const password = "password" + const invalidEmail = "" + + // Sign up a new user + await signUpNewUser(page, fullName, email, password) + + // Log in the user + await logInUser(page, email, password) + + await page.goto("/settings") + await page.getByRole("tab", { name: "My profile" }).click() + await page.getByRole("button", { name: "Edit" }).click() + await page.getByLabel("Email").fill(invalidEmail) + await page.locator("body").click() + await expect(page.getByText("Email is required")).toBeVisible() + }) + + test("Cancel edit action restores original name", async ({ page }) => { + const fullName = "Test User" + const email = randomEmail() + const password = "password" + const updatedName = "Test User" + + // Sign up a new user + await signUpNewUser(page, fullName, email, password) + + // Log in the user + await logInUser(page, email, password) + + await page.goto("/settings") + await page.getByRole("tab", { name: "My profile" }).click() + await page.getByRole("button", { name: "Edit" }).click() + await page.getByLabel("Full name").fill(updatedName) + await page.getByRole("button", { name: "Cancel" }).first().click() + await expect( + page.getByLabel("My profile").getByText(fullName, { exact: true }), + ).toBeVisible() + }) + + test("Cancel edit action restores original email", async ({ page }) => { + const fullName = "Test User" + const email = randomEmail() + const password = "password" + const updatedEmail = randomEmail() + + // Sign up a new user + await signUpNewUser(page, fullName, email, password) + + // Log in the user + await logInUser(page, email, password) + + await page.goto("/settings") + await page.getByRole("tab", { name: "My profile" }).click() + await page.getByRole("button", { name: "Edit" }).click() + await page.getByLabel("Email").fill(updatedEmail) + await page.getByRole("button", { name: "Cancel" }).first().click() + await expect( + page.getByLabel("My profile").getByText(email, { exact: true }), + ).toBeVisible() + }) +}) + +// Change Password + +test.describe("Change password successfully", () => { + test.use({ storageState: { cookies: [], origins: [] } }) + + test("Update password successfully", async ({ page }) => { + const fullName = "Test User" + const email = randomEmail() + const password = "password" + const NewPassword = "newPassword" + + // Sign up a new user + await signUpNewUser(page, fullName, email, password) + + // Log in the user + await logInUser(page, email, password) + + await page.goto("/settings") + await page.getByRole("tab", { name: "Password" }).click() + await page.getByLabel("Current Password*").fill(password) + await page.getByLabel("Set Password*").fill(NewPassword) + await page.getByLabel("Confirm Password*").fill(NewPassword) + await page.getByRole("button", { name: "Save" }).click() + await expect(page.getByText("Password updated successfully.")).toBeVisible() + + await logOutUser(page) + + // Check if the user can log in with the new password + await logInUser(page, email, NewPassword) + }) +}) + +test.describe("Change password with invalid data", () => { + test.use({ storageState: { cookies: [], origins: [] } }) + + test("Update password with weak passwords", async ({ page }) => { + const fullName = "Test User" + const email = randomEmail() + const password = "password" + const weakPassword = "weak" + + // Sign up a new user + await signUpNewUser(page, fullName, email, password) + + // Log in the user + await logInUser(page, email, password) + + await page.goto("/settings") + await page.getByRole("tab", { name: "Password" }).click() + await page.getByLabel("Current Password*").fill(password) + await page.getByLabel("Set Password*").fill(weakPassword) + await page.getByLabel("Confirm Password*").fill(weakPassword) + await expect( + page.getByText("Password must be at least 8 characters"), + ).toBeVisible() + }) + + test("New password and confirmation password do not match", async ({ + page, + }) => { + const fullName = "Test User" + const email = randomEmail() + const password = "password" + const newPassword = "newPassword" + const confirmPassword = "confirmPassword" + + // Sign up a new user + await signUpNewUser(page, fullName, email, password) + + // Log in the user + await logInUser(page, email, password) + + await page.goto("/settings") + await page.getByRole("tab", { name: "Password" }).click() + await page.getByLabel("Current Password*").fill(password) + await page.getByLabel("Set Password*").fill(newPassword) + await page.getByLabel("Confirm Password*").fill(confirmPassword) + await page.getByRole("button", { name: "Save" }).click() + await expect(page.getByText("Passwords do not match")).toBeVisible() + }) + + test("Current password and new password are the same", async ({ page }) => { + const fullName = "Test User" + const email = randomEmail() + const password = "password" + + // Sign up a new user + await signUpNewUser(page, fullName, email, password) + + // Log in the user + await logInUser(page, email, password) + + await page.goto("/settings") + await page.getByRole("tab", { name: "Password" }).click() + await page.getByLabel("Current Password*").fill(password) + await page.getByLabel("Set Password*").fill(password) + await page.getByLabel("Confirm Password*").fill(password) + await page.getByRole("button", { name: "Save" }).click() + await expect( + page.getByText("New password cannot be the same as the current one"), + ).toBeVisible() + }) +}) + +// Appearance + +test("Appearance tab is visible", async ({ page }) => { + await page.goto("/settings") + await page.getByRole("tab", { name: "Appearance" }).click() + await expect(page.getByLabel("Appearance")).toBeVisible() +}) + +test("User can switch from light mode to dark mode", async ({ page }) => { + await page.goto("/settings") + await page.getByRole("tab", { name: "Appearance" }).click() + await page.getByLabel("Appearance").locator("span").nth(3).click() + const isDarkMode = await page.evaluate(() => + document.body.classList.contains("chakra-ui-dark"), + ) + expect(isDarkMode).toBe(true) +}) + +test("User can switch from dark mode to light mode", async ({ page }) => { + await page.goto("/settings") + await page.getByRole("tab", { name: "Appearance" }).click() + await page.getByLabel("Appearance").locator("span").first().click() + const isLightMode = await page.evaluate(() => + document.body.classList.contains("chakra-ui-light"), + ) + expect(isLightMode).toBe(true) +}) + +test("Selected mode is preserved across sessions", async ({ page }) => { + await page.goto("/settings") + await page.getByRole("tab", { name: "Appearance" }).click() + await page.getByLabel("Appearance").locator("span").nth(3).click() + + await logOutUser(page) + + await logInUser(page, firstSuperuser, firstSuperuserPassword) + const isDarkMode = await page.evaluate(() => + document.body.classList.contains("chakra-ui-dark"), + ) + expect(isDarkMode).toBe(true) +}) diff --git a/frontend/tests/utils/user.ts b/frontend/tests/utils/user.ts index 6f02c0e..8fcfd26 100644 --- a/frontend/tests/utils/user.ts +++ b/frontend/tests/utils/user.ts @@ -31,8 +31,8 @@ export async function logInUser(page: Page, email: string, password: string) { ).toBeVisible() } -export async function logOutUser(page: Page, name: string) { - await page.getByRole("button", { name: name }).click() +export async function logOutUser(page: Page) { + await page.getByTestId("user-menu").click() await page.getByRole("menuitem", { name: "Log out" }).click() await page.goto("/login") }