diff --git a/apps/web/components/security/ChangePasswordSection.tsx b/apps/web/components/security/ChangePasswordSection.tsx index aa68f8a4d2..e0cc2f2100 100644 --- a/apps/web/components/security/ChangePasswordSection.tsx +++ b/apps/web/components/security/ChangePasswordSection.tsx @@ -1,17 +1,20 @@ import React, { SyntheticEvent, useState } from "react"; +import { ErrorCode } from "@calcom/lib/auth"; +import { useLocale } from "@calcom/lib/hooks/useLocale"; import showToast from "@calcom/lib/notification"; import Button from "@calcom/ui/Button"; -import { ErrorCode } from "@lib/auth"; -import { useLocale } from "@lib/hooks/useLocale"; - const ChangePasswordSection = () => { const [oldPassword, setOldPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [errorMessage, setErrorMessage] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); - const { t } = useLocale(); + const { t, isLocaleReady } = useLocale(); + // hold display until the locale is loaded + if (!isLocaleReady) { + return null; + } const errorMessages: { [key: string]: string } = { [ErrorCode.IncorrectPassword]: t("current_incorrect_password"), diff --git a/apps/web/playwright/change-password.e2e.ts b/apps/web/playwright/change-password.e2e.ts index c76774ca60..f240ae1e6f 100644 --- a/apps/web/playwright/change-password.e2e.ts +++ b/apps/web/playwright/change-password.e2e.ts @@ -4,7 +4,7 @@ import { test } from "./lib/fixtures"; test.afterEach(({ users }) => users.deleteAll()); -test.describe("Change Passsword Test", () => { +test.describe("Change Password Test", () => { test("change password", async ({ page, users }) => { const pro = await users.create(); await pro.login(); @@ -14,6 +14,7 @@ test.describe("Change Passsword Test", () => { if (!pro.username) throw Error("Test user doesn't have a username"); // Fill form + await page.waitForSelector('[name="current_password"]'); await page.fill('[name="current_password"]', pro.username); await page.fill('[name="new_password"]', `${pro.username}1111`); await page.press('[name="new_password"]', "Enter"); diff --git a/apps/web/playwright/hash-my-url.e2e.ts b/apps/web/playwright/hash-my-url.e2e.ts index 15304faea9..3a0897827e 100644 --- a/apps/web/playwright/hash-my-url.e2e.ts +++ b/apps/web/playwright/hash-my-url.e2e.ts @@ -18,25 +18,20 @@ test.describe("hash my url", () => { await page.goto("/event-types"); // We wait until loading is finished await page.waitForSelector('[data-testid="event-types"]'); - await page.click('//ul[@data-testid="event-types"]/li[1]'); + await page.locator('//ul[@data-testid="event-types"]/li[1]').click(); // We wait for the page to load - await page.waitForSelector('//*[@data-testid="show-advanced-settings"]'); - await page.click('//*[@data-testid="show-advanced-settings"]'); - // we wait for the hashedLink setting to load - await page.waitForSelector('//*[@id="hashedLinkCheck"]'); + await page.locator('//*[@data-testid="show-advanced-settings"]').click(); // ignore if it is already checked, and click if unchecked - const isChecked = await page.isChecked('//*[@id="hashedLinkCheck"]'); - !isChecked && (await page.click('//*[@id="hashedLinkCheck"]')); - // we wait for the hashedLink setting to load - await page.waitForSelector('//*[@data-testid="generated-hash-url"]'); - const $url = await page.locator('//*[@data-testid="generated-hash-url"]').inputValue(); - // click update - await page.focus('//button[@type="submit"]'); - await page.keyboard.press("Enter"); + const hashedLinkCheck = await page.locator('[id="hashedLinkCheck"]'); - // To prevent an early 404 - // eslint-disable-next-line playwright/no-wait-for-timeout - await page.waitForTimeout(1000); + !(await hashedLinkCheck.isChecked()) && (await hashedLinkCheck.click()); + + // we wait for the hashedLink setting to load + const $url = await page.locator('//*[@data-testid="generated-hash-url"]').inputValue(); + + // click update + await page.locator('[data-testid="update-eventtype"]').press("Enter"); + await page.waitForURL("/event-types"); // book using generated url hash await page.goto($url); @@ -51,10 +46,8 @@ test.describe("hash my url", () => { await page.waitForSelector('[data-testid="event-types"]'); await page.click('//ul[@data-testid="event-types"]/li[1]'); // We wait for the page to load - await page.waitForSelector('//*[@data-testid="show-advanced-settings"]'); - await page.click('//*[@data-testid="show-advanced-settings"]'); + await page.locator('//*[@data-testid="show-advanced-settings"]').click(); // we wait for the hashedLink setting to load - await page.waitForSelector('//*[@data-testid="generated-hash-url"]'); const $newUrl = await page.locator('//*[@data-testid="generated-hash-url"]').inputValue(); expect($url !== $newUrl).toBeTruthy(); }); diff --git a/apps/web/playwright/login.e2e.ts b/apps/web/playwright/login.e2e.ts index d8c00ef54c..d780074667 100644 --- a/apps/web/playwright/login.e2e.ts +++ b/apps/web/playwright/login.e2e.ts @@ -7,12 +7,67 @@ import { localize } from "./lib/testUtils"; test.describe.configure({ mode: "parallel" }); -test.describe("Login and logout tests", () => { - test.afterEach(async ({ users }) => { +// a test to logout requires both a succesfull login as logout, to prevent +// a doubling of tests failing on logout & logout, we can group them. +test.describe("user can login & logout succesfully", async () => { + test.afterAll(async ({ users }) => { await users.deleteAll(); }); + test("login flow TRAIL user & logout using dashboard", async ({ page, users }) => { + // log in trail user + await test.step("Log in", async () => { + const user = await users.create({ plan: UserPlan.TRIAL }); + await user.login(); + + const shellLocator = page.locator(`[data-testid=dashboard-shell]`); + + // expects the home page for an authorized user + await page.goto("/"); + await expect(shellLocator).toBeVisible(); + + // Asserts to read the tested plan + const planLocator = shellLocator.locator(`[data-testid=plan-trial]`); + await expect(planLocator).toBeVisible(); + await expect(planLocator).toHaveText("-TRIAL"); + + await expect(page.locator(`[data-testid=trial-banner]`)).toBeVisible(); + }); + + // + await test.step("Log out", async () => { + const signOutLabel = (await localize("en"))("sign_out"); + const userDropdownDisclose = async () => page.locator("[data-testid=user-dropdown-trigger]").click(); + + // disclose and click the sign out button from the user dropdown + await userDropdownDisclose(); + const signOutBtn = await page.locator(`text=${signOutLabel}`); + await signOutBtn.click(); + + // 2s of delay to assure the session is cleared + await page.waitForURL("/auth/logout"); + + // Reroute to the home page to check if the login form shows up + await page.goto("/"); + await expect(page.locator(`[data-testid=login-form]`)).toBeVisible(); + }); + }); +}); + +test.describe("Login and logout tests", () => { + test.afterAll(async ({ users }) => { + await users.deleteAll(); + }); + + test.afterEach(async ({ users, page }) => { + await users.logout(); + + // check if we are at the login page + await page.goto("/"); + await expect(page.locator(`[data-testid=login-form]`)).toBeVisible(); + }); + // Test login with all plans - const plans = [UserPlan.PRO, UserPlan.FREE, UserPlan.TRIAL]; + const plans = [UserPlan.PRO, UserPlan.FREE]; plans.forEach((plan) => { test(`Should login with a ${plan} account`, async ({ page, users }) => { // Create user and login @@ -29,68 +84,31 @@ test.describe("Login and logout tests", () => { const planLocator = shellLocator.locator(`[data-testid=plan-${plan.toLowerCase()}]`); await expect(planLocator).toBeVisible(); await expect(planLocator).toHaveText(`-${plan}`); - - // When TRIAL check if the TRIAL banner is visible - if (plan === UserPlan.TRIAL) { - await expect(page.locator(`[data-testid=trial-banner]`)).toBeVisible(); - } }); }); - test("Should warn when user does not exist", async ({ page }) => { - const alertMessage = (await localize("en"))("no_account_exists"); + test.describe("Login flow validations", async () => { + test("Should warn when user does not exist", async ({ page }) => { + const alertMessage = (await localize("en"))("no_account_exists"); - // Login with a non-existent user - const never = "never"; - await login({ username: never }, page); + // Login with a non-existent user + const never = "never"; + await login({ username: never }, page); - // assert for the visibility of the localized alert message - await expect(page.locator(`text=${alertMessage}`)).toBeVisible(); - }); + // assert for the visibility of the localized alert message + await expect(page.locator(`text=${alertMessage}`)).toBeVisible(); + }); - test("Should warn when password is incorrect", async ({ page, users }) => { - const alertMessage = (await localize("en"))("incorrect_password"); - // by default password===username with the users fixture - const pro = await users.create({ username: "pro" }); + test("Should warn when password is incorrect", async ({ page, users }) => { + const alertMessage = (await localize("en"))("incorrect_password"); + // by default password===username with the users fixture + const pro = await users.create({ username: "pro" }); - // login with a wrong password - await login({ username: pro.username, password: "wrong" }, page); + // login with a wrong password + await login({ username: pro.username, password: "wrong" }, page); - // assert for the visibility of the localized alert message - await expect(page.locator(`text=${alertMessage}`)).toBeVisible(); - }); - - test("Should logout", async ({ page, users }) => { - const signOutLabel = (await localize("en"))("sign_out"); - const userDropdownDisclose = async () => page.locator("[data-testid=user-dropdown-trigger]").click(); - - // creates a user and login - const pro = await users.create(); - await pro.login(); - - // disclose and click the sign out button from the user dropdown - await userDropdownDisclose(); - const signOutBtn = page.locator(`text=${signOutLabel}`); - await signOutBtn.click(); - - // 2s of delay to assure the session is cleared - await page.waitForTimeout(2000); - - // Reroute to the home page to check if the login form shows up - await page.goto("/"); - await expect(page.locator(`[data-testid=login-form]`)).toBeVisible(); - }); - - test("Should logout using the logout route", async ({ page, users }) => { - // creates a user and login - const pro = await users.create(); - await pro.login(); - - // users.logout() action uses the logout route "/auth/logout" to clear the session - await users.logout(); - - // check if we are at the login page - await page.goto("/"); - await expect(page.locator(`[data-testid=login-form]`)).toBeVisible(); + // assert for the visibility of the localized alert message + await expect(page.locator(`text=${alertMessage}`)).toBeVisible(); + }); }); });