From 832c1db63ba379653d36e3e2ca5341a158822ee3 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Mon, 6 May 2024 17:29:27 +0200 Subject: [PATCH] :sparkles: Add login page as Page Object Model --- .../get-profile-anonymous.json | 0 .../get-built-in-templates-empty.json | 0 .../get-font-variants-empty.json | 0 .../logged-in-user/get-profile-logged-in.json | 0 .../get-profiles-for-file-comments-empty.json | 0 .../logged-in-user/get-projects-default.json | 0 .../get-team-members-your-penpot.json | 0 .../get-team-recent-files-empty.json | 0 .../get-team-users-single-user.json | 0 .../logged-in-user/get-teams-default.json | 0 .../get-unread-comment-threads-empty.json | 0 .../login-with-password-success.json | 0 .../login-with-password-error.json | 0 frontend/playwright/helpers/index.js | 8 +- frontend/playwright/helpers/intercepts.js | 8 ++ frontend/playwright/login.spec.js | 80 ------------------- frontend/playwright/ui/pages/login-page.js | 76 ++++++++++++++++++ .../playwright/{ => ui/specs}/example.spec.js | 2 +- frontend/playwright/ui/specs/login.spec.js | 54 +++++++++++++ 19 files changed, 143 insertions(+), 85 deletions(-) rename frontend/playwright/{fixtures => data}/get-profile-anonymous.json (100%) rename frontend/playwright/{fixtures => data}/logged-in-user/get-built-in-templates-empty.json (100%) rename frontend/playwright/{fixtures => data}/logged-in-user/get-font-variants-empty.json (100%) rename frontend/playwright/{fixtures => data}/logged-in-user/get-profile-logged-in.json (100%) rename frontend/playwright/{fixtures => data}/logged-in-user/get-profiles-for-file-comments-empty.json (100%) rename frontend/playwright/{fixtures => data}/logged-in-user/get-projects-default.json (100%) rename frontend/playwright/{fixtures => data}/logged-in-user/get-team-members-your-penpot.json (100%) rename frontend/playwright/{fixtures => data}/logged-in-user/get-team-recent-files-empty.json (100%) rename frontend/playwright/{fixtures => data}/logged-in-user/get-team-users-single-user.json (100%) rename frontend/playwright/{fixtures => data}/logged-in-user/get-teams-default.json (100%) rename frontend/playwright/{fixtures => data}/logged-in-user/get-unread-comment-threads-empty.json (100%) rename frontend/playwright/{fixtures => data}/logged-in-user/login-with-password-success.json (100%) rename frontend/playwright/{fixtures => data}/login-with-password-error.json (100%) create mode 100644 frontend/playwright/helpers/intercepts.js delete mode 100644 frontend/playwright/login.spec.js create mode 100644 frontend/playwright/ui/pages/login-page.js rename frontend/playwright/{ => ui/specs}/example.spec.js (84%) create mode 100644 frontend/playwright/ui/specs/login.spec.js diff --git a/frontend/playwright/fixtures/get-profile-anonymous.json b/frontend/playwright/data/get-profile-anonymous.json similarity index 100% rename from frontend/playwright/fixtures/get-profile-anonymous.json rename to frontend/playwright/data/get-profile-anonymous.json diff --git a/frontend/playwright/fixtures/logged-in-user/get-built-in-templates-empty.json b/frontend/playwright/data/logged-in-user/get-built-in-templates-empty.json similarity index 100% rename from frontend/playwright/fixtures/logged-in-user/get-built-in-templates-empty.json rename to frontend/playwright/data/logged-in-user/get-built-in-templates-empty.json diff --git a/frontend/playwright/fixtures/logged-in-user/get-font-variants-empty.json b/frontend/playwright/data/logged-in-user/get-font-variants-empty.json similarity index 100% rename from frontend/playwright/fixtures/logged-in-user/get-font-variants-empty.json rename to frontend/playwright/data/logged-in-user/get-font-variants-empty.json diff --git a/frontend/playwright/fixtures/logged-in-user/get-profile-logged-in.json b/frontend/playwright/data/logged-in-user/get-profile-logged-in.json similarity index 100% rename from frontend/playwright/fixtures/logged-in-user/get-profile-logged-in.json rename to frontend/playwright/data/logged-in-user/get-profile-logged-in.json diff --git a/frontend/playwright/fixtures/logged-in-user/get-profiles-for-file-comments-empty.json b/frontend/playwright/data/logged-in-user/get-profiles-for-file-comments-empty.json similarity index 100% rename from frontend/playwright/fixtures/logged-in-user/get-profiles-for-file-comments-empty.json rename to frontend/playwright/data/logged-in-user/get-profiles-for-file-comments-empty.json diff --git a/frontend/playwright/fixtures/logged-in-user/get-projects-default.json b/frontend/playwright/data/logged-in-user/get-projects-default.json similarity index 100% rename from frontend/playwright/fixtures/logged-in-user/get-projects-default.json rename to frontend/playwright/data/logged-in-user/get-projects-default.json diff --git a/frontend/playwright/fixtures/logged-in-user/get-team-members-your-penpot.json b/frontend/playwright/data/logged-in-user/get-team-members-your-penpot.json similarity index 100% rename from frontend/playwright/fixtures/logged-in-user/get-team-members-your-penpot.json rename to frontend/playwright/data/logged-in-user/get-team-members-your-penpot.json diff --git a/frontend/playwright/fixtures/logged-in-user/get-team-recent-files-empty.json b/frontend/playwright/data/logged-in-user/get-team-recent-files-empty.json similarity index 100% rename from frontend/playwright/fixtures/logged-in-user/get-team-recent-files-empty.json rename to frontend/playwright/data/logged-in-user/get-team-recent-files-empty.json diff --git a/frontend/playwright/fixtures/logged-in-user/get-team-users-single-user.json b/frontend/playwright/data/logged-in-user/get-team-users-single-user.json similarity index 100% rename from frontend/playwright/fixtures/logged-in-user/get-team-users-single-user.json rename to frontend/playwright/data/logged-in-user/get-team-users-single-user.json diff --git a/frontend/playwright/fixtures/logged-in-user/get-teams-default.json b/frontend/playwright/data/logged-in-user/get-teams-default.json similarity index 100% rename from frontend/playwright/fixtures/logged-in-user/get-teams-default.json rename to frontend/playwright/data/logged-in-user/get-teams-default.json diff --git a/frontend/playwright/fixtures/logged-in-user/get-unread-comment-threads-empty.json b/frontend/playwright/data/logged-in-user/get-unread-comment-threads-empty.json similarity index 100% rename from frontend/playwright/fixtures/logged-in-user/get-unread-comment-threads-empty.json rename to frontend/playwright/data/logged-in-user/get-unread-comment-threads-empty.json diff --git a/frontend/playwright/fixtures/logged-in-user/login-with-password-success.json b/frontend/playwright/data/logged-in-user/login-with-password-success.json similarity index 100% rename from frontend/playwright/fixtures/logged-in-user/login-with-password-success.json rename to frontend/playwright/data/logged-in-user/login-with-password-success.json diff --git a/frontend/playwright/fixtures/login-with-password-error.json b/frontend/playwright/data/login-with-password-error.json similarity index 100% rename from frontend/playwright/fixtures/login-with-password-error.json rename to frontend/playwright/data/login-with-password-error.json diff --git a/frontend/playwright/helpers/index.js b/frontend/playwright/helpers/index.js index 419dfa918..ac8108f81 100644 --- a/frontend/playwright/helpers/index.js +++ b/frontend/playwright/helpers/index.js @@ -1,14 +1,14 @@ export const interceptRPC = async (page, path, jsonFilename, options = {}) => { const interceptConfig = { status: 200, - ...options + ...options, }; - await page.route(`**/api/rpc/command/${path}`, (route) => { - route.fulfill({ + await page.route(`**/api/rpc/command/${path}`, async (route) => { + await route.fulfill({ ...interceptConfig, contentType: "application/transit+json", - path: `playwright/fixtures/${jsonFilename}`, + path: `playwright/data/${jsonFilename}`, }); }); }; diff --git a/frontend/playwright/helpers/intercepts.js b/frontend/playwright/helpers/intercepts.js new file mode 100644 index 000000000..ecb46b817 --- /dev/null +++ b/frontend/playwright/helpers/intercepts.js @@ -0,0 +1,8 @@ +import { interceptRPC } from "./index"; + + +export const setupNotLogedIn = async (page) => { + await interceptRPC(page, "get-profile", "get-profile-anonymous.json"); + +}; + diff --git a/frontend/playwright/login.spec.js b/frontend/playwright/login.spec.js deleted file mode 100644 index 5b10ca2ce..000000000 --- a/frontend/playwright/login.spec.js +++ /dev/null @@ -1,80 +0,0 @@ -import { test, expect } from "@playwright/test"; -import { interceptRPC } from "./helpers"; - -const setupLoggedOutUser = async (page) => { - await interceptRPC(page, "get-profile", "get-profile-anonymous.json"); - await interceptRPC(page, "login-with-password", "logged-in-user/login-with-password-success.json"); -}; - -// TODO: maybe Playwright's fixtures are the right way to do this? -const setupDashboardUser = async (page) => { - await interceptRPC(page, "get-profile", "logged-in-user/get-profile-logged-in.json"); - await interceptRPC(page, "get-teams", "logged-in-user/get-teams-default.json"); - await interceptRPC(page, "get-font-variants?team-id=*", "logged-in-user/get-font-variants-empty.json"); - await interceptRPC(page, "get-projects?team-id=*", "logged-in-user/get-projects-default.json"); - await interceptRPC(page, "get-team-members?team-id=*", "logged-in-user/get-team-members-your-penpot.json"); - await interceptRPC(page, "get-team-users?team-id=*", "logged-in-user/get-team-users-single-user.json"); - await interceptRPC( - page, - "get-unread-comment-threads?team-id=*", - "logged-in-user/get-team-users-single-user.json", - ); - await interceptRPC( - page, - "get-team-recent-files?team-id=*", - "logged-in-user/get-team-recent-files-empty.json", - ); - await interceptRPC( - page, - "get-profiles-for-file-comments", - "logged-in-user/get-profiles-for-file-comments-empty.json", - ); -}; - -test("Shows login page when going to index and user is logged out", async ({ page }) => { - setupLoggedOutUser(page); - - await page.goto("/"); - - await expect(page).toHaveURL(/auth\/login$/); - await expect(page.getByRole("heading", { name: "Log into my account" } )).toBeVisible(); -}); - -test("User submit a wrong formated email ", async ({ page }) => { - await interceptRPC(page, "get-profile", "get-profile-anonymous.json"); - await page.goto("/"); - await page.getByLabel("Email").fill("foo"); - - await expect(page).toHaveURL(/auth\/login$/); - await expect(page.getByText("Enter a valid email please")).toBeVisible(); -}); - -test("User logs in by filling the login form", async ({ page }) => { - setupLoggedOutUser(page); - - await page.goto("/#/auth/login"); - - setupDashboardUser(page); - - await page.getByLabel("Email").fill("foo@example.com"); - await page.getByLabel("Password").fill("loremipsum"); - - await page.getByRole("button", { name: "Login" }).click(); - - await expect(page).toHaveURL(/dashboard/); -}); - -test("User submits wrong credentials", async ({ page }) => { - await interceptRPC(page, "get-profile", "get-profile-anonymous.json"); - await interceptRPC(page, "login-with-password", "login-with-password-error.json", { status: 400 }); - - await page.goto("/"); - - await page.getByLabel("Email").fill("foo123@example.com"); - await page.getByLabel("Password").fill("aaaa"); - - await page.getByRole("button", { name: "Login" }).click(); - - await expect(page.getByText("Email or password is incorrect")).toBeVisible(); - await expect(page).toHaveURL(/auth\/login$/); -}); diff --git a/frontend/playwright/ui/pages/login-page.js b/frontend/playwright/ui/pages/login-page.js new file mode 100644 index 000000000..1358f4ab3 --- /dev/null +++ b/frontend/playwright/ui/pages/login-page.js @@ -0,0 +1,76 @@ +import { interceptRPC } from "../../helpers/index"; + +class LoginPage { + constructor(page) { + this.page = page; + this.loginButton = page.getByRole("button", { name: "Login" }); + this.password = page.getByLabel("Password"); + this.userName = page.getByLabel("Email"); + this.message = page.getByText("Email or password is incorrect"); + this.badLoginMsg = page.getByText("Enter a valid email please"); + this.initialHeading = page.getByRole("heading", { name: "Log into my account" }); + } + + url() { + return this.page.url(); + } + + context() { + return this.page.context(); + } + + async fillEmailAndPasswordInputs(email, password) { + await this.userName.fill(email); + await this.password.fill(password); + } + + async clickLoginButton() { + await this.loginButton.click(); + } + + async setupAllowedUser() { + await interceptRPC(this.page, "get-profile", "logged-in-user/get-profile-logged-in.json"); + await interceptRPC(this.page, "get-teams", "logged-in-user/get-teams-default.json"); + await interceptRPC( + this.page, + "get-font-variants?team-id=*", + "logged-in-user/get-font-variants-empty.json", + ); + await interceptRPC(this.page, "get-projects?team-id=*", "logged-in-user/get-projects-default.json"); + await interceptRPC( + this.page, + "get-team-members?team-id=*", + "logged-in-user/get-team-members-your-penpot.json", + ); + await interceptRPC( + this.page, + "get-team-users?team-id=*", + "logged-in-user/get-team-users-single-user.json", + ); + await interceptRPC( + this.page, + "get-unread-comment-threads?team-id=*", + "logged-in-user/get-team-users-single-user.json", + ); + await interceptRPC( + this.page, + "get-team-recent-files?team-id=*", + "logged-in-user/get-team-recent-files-empty.json", + ); + await interceptRPC( + this.page, + "get-profiles-for-file-comments", + "logged-in-user/get-profiles-for-file-comments-empty.json", + ); + } + + async setupLoginSuccess() { + await interceptRPC(this.page, "login-with-password", "logged-in-user/login-with-password-success.json"); + } + + async setupLoginError() { + await interceptRPC(this.page, "login-with-password", "login-with-password-error.json", { status: 400 }); + } +} + +export default LoginPage; diff --git a/frontend/playwright/example.spec.js b/frontend/playwright/ui/specs/example.spec.js similarity index 84% rename from frontend/playwright/example.spec.js rename to frontend/playwright/ui/specs/example.spec.js index f2450fa36..ad5e4712d 100644 --- a/frontend/playwright/example.spec.js +++ b/frontend/playwright/ui/specs/example.spec.js @@ -5,7 +5,7 @@ test("Has title", async ({ page }) => { route.fulfill({ status: 200, contentType: "application/transit+json", - path: "playwright/fixtures/get-profile-anonymous.json", + path: "playwright/data/get-profile-anonymous.json", }); }); await page.goto("/"); diff --git a/frontend/playwright/ui/specs/login.spec.js b/frontend/playwright/ui/specs/login.spec.js new file mode 100644 index 000000000..08d3753c4 --- /dev/null +++ b/frontend/playwright/ui/specs/login.spec.js @@ -0,0 +1,54 @@ +import { test, expect } from "@playwright/test"; +import { setupNotLogedIn } from "../../helpers/intercepts"; + +import LoginPage from "../pages/login-page"; + +test.beforeEach(async ({ page }) => { + await setupNotLogedIn(page); + await page.goto("/#/auth/login"); +}); + +test("Shows login page when going to index and user is logged out", async ({ page }) => { + const loginPage = new LoginPage(page); + + await loginPage.setupAllowedUser(); + + await expect(loginPage.url()).toMatch(/auth\/login$/); + await expect(loginPage.initialHeading).toBeVisible(); +}); + +test("User submit a wrong formated email ", async ({ page }) => { + const loginPage = new LoginPage(page); + + await loginPage.setupLoginSuccess(); + + await loginPage.fillEmailAndPasswordInputs("foo", "lorenIpsum"); + + await expect(loginPage.badLoginMsg).toBeVisible(); +}); + +test("User logs in by filling the login form", async ({ page }) => { + const loginPage = new LoginPage(page); + + await loginPage.setupLoginSuccess(); + await loginPage.setupAllowedUser(); + + await loginPage.fillEmailAndPasswordInputs("foo@example.com", "loremipsum"); + await loginPage.clickLoginButton(); + + await page.waitForURL('**/dashboard/**'); + await expect(page).toHaveURL(/dashboard/); + // await expect(loginPage.url()).toMatch(/dashboard/); +}); + +test("User submits wrong credentials", async ({ page }) => { + const loginPage = new LoginPage(page); + + await loginPage.setupLoginError(); + + await loginPage.fillEmailAndPasswordInputs("test@example.com", "loremipsum"); + await loginPage.clickLoginButton(); + + await expect(loginPage.message).toBeVisible(); + await expect(loginPage.url()).toMatch(/auth\/login$/); +});