← full-stack-fastapi-template  /  frontend/tests/login.spec.ts

1
import { expect, type Page, test } from "@playwright/test"
2
import { firstSuperuser, firstSuperuserPassword } from "./config.ts"
3
import { randomPassword } from "./utils/random.ts"
4
5
test.use({ storageState: { cookies: [], origins: [] } })
6
7
const fillForm = async (page: Page, email: string, password: string) => {
8
  await page.getByTestId("email-input").fill(email)
9
  await page.getByTestId("password-input").fill(password)
10
}
11
12
const verifyInput = async (page: Page, testId: string) => {
13
  const input = page.getByTestId(testId)
14
  await expect(input).toBeVisible()
15
  await expect(input).toHaveText("")
16
  await expect(input).toBeEditable()
17
}
18
19
test("Inputs are visible, empty and editable", async ({ page }) => {
20
  await page.goto("/login")
21
22
  await verifyInput(page, "email-input")
23
  await verifyInput(page, "password-input")
24
})
25
26
test("Log In button is visible", async ({ page }) => {
27
  await page.goto("/login")
28
29
  await expect(page.getByRole("button", { name: "Log In" })).toBeVisible()
30
})
31
32
test("Forgot Password link is visible", async ({ page }) => {
33
  await page.goto("/login")
34
35
  await expect(
36
    page.getByRole("link", { name: "Forgot your password?" }),
37
  ).toBeVisible()
38
})
39
40
test("Log in with valid email and password ", async ({ page }) => {
41
  await page.goto("/login")
42
43
  await fillForm(page, firstSuperuser, firstSuperuserPassword)
44
  await page.getByRole("button", { name: "Log In" }).click()
45
46
  await page.waitForURL("/")
47
48
  await expect(
49
    page.getByText("Welcome back, nice to see you again!"),
50
  ).toBeVisible()
51
})
52
53
test("Log in with invalid email", async ({ page }) => {
54
  await page.goto("/login")
55
56
  await fillForm(page, "invalidemail", firstSuperuserPassword)
57
  await page.getByRole("button", { name: "Log In" }).click()
58
59
  await expect(page.getByText("Invalid email address")).toBeVisible()
60
})
61
62
test("Log in with invalid password", async ({ page }) => {
63
  const password = randomPassword()
64
65
  await page.goto("/login")
66
  await fillForm(page, firstSuperuser, password)
67
  await page.getByRole("button", { name: "Log In" }).click()
68
69
  await expect(page.getByText("Incorrect email or password")).toBeVisible()
70
})
71
72
test("Successful log out", async ({ page }) => {
73
  await page.goto("/login")
74
75
  await fillForm(page, firstSuperuser, firstSuperuserPassword)
76
  await page.getByRole("button", { name: "Log In" }).click()
77
78
  await page.waitForURL("/")
79
80
  await expect(
81
    page.getByText("Welcome back, nice to see you again!"),
82
  ).toBeVisible()
83
84
  await page.getByTestId("user-menu").click()
85
  await page.getByRole("menuitem", { name: "Log out" }).click()
86
  await page.waitForURL("/login")
87
})
88
89
test("Logged-out user cannot access protected routes", async ({ page }) => {
90
  await page.goto("/login")
91
92
  await fillForm(page, firstSuperuser, firstSuperuserPassword)
93
  await page.getByRole("button", { name: "Log In" }).click()
94
95
  await page.waitForURL("/")
96
97
  await expect(
98
    page.getByText("Welcome back, nice to see you again!"),
99
  ).toBeVisible()
100
101
  await page.getByTestId("user-menu").click()
102
  await page.getByRole("menuitem", { name: "Log out" }).click()
103
  await page.waitForURL("/login")
104
105
  await page.goto("/settings")
106
  await page.waitForURL("/login")
107
})
108
109
test("Redirects to /login when token is wrong", async ({ page }) => {
110
  await page.goto("/settings")
111
  await page.evaluate(() => {
112
    localStorage.setItem("access_token", "invalid_token")
113
  })
114
  await page.goto("/settings")
115
  await page.waitForURL("/login")
116
  await expect(page).toHaveURL("/login")
117
})
118