Skip to content

Commit 4641fd0

Browse files
authored
✅ Add login tests (#121)
1 parent d6a223e commit 4641fd0

File tree

3 files changed

+143
-4
lines changed

3 files changed

+143
-4
lines changed

frontend/src/routes/_layout/$team/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ function Dashboard() {
1818
return (
1919
<>
2020
<Container maxW="full" p={12}>
21-
<Box>
21+
<Box data-testid="result">
2222
<Box fontSize="2xl" isTruncated maxWidth="250px">
2323
Hi,{" "}
2424
<Suspense fallback={<SkeletonText noOfLines={1} width={20} />}>

frontend/src/routes/login.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
FormControl,
88
FormErrorMessage,
99
FormLabel,
10+
Heading,
1011
Icon,
1112
Input,
1213
InputGroup,
@@ -89,9 +90,7 @@ function Login() {
8990
gap={4}
9091
>
9192
<Box>
92-
<Text fontWeight="bolder" fontSize="2xl">
93-
Welcome!
94-
</Text>
93+
<Heading size="md">Welcome!</Heading>
9594
<Text fontSize="md" color="gray.500">
9695
Sign in to your account
9796
</Text>

frontend/tests/login.spec.ts

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import { type Page, expect, test } from "@playwright/test"
2+
3+
test.use({ storageState: { cookies: [], origins: [] } })
4+
5+
type OptionsType = {
6+
exact?: boolean
7+
}
8+
9+
const fillForm = async (page: Page, email: string, password: string) => {
10+
await page.getByPlaceholder("Email").fill(email)
11+
await page.getByPlaceholder("Password", { exact: true }).fill(password)
12+
}
13+
14+
const verifyInput = async (
15+
page: Page,
16+
placeholder: string,
17+
options?: OptionsType,
18+
) => {
19+
const input = page.getByPlaceholder(placeholder, options)
20+
await expect(input).toBeVisible()
21+
await expect(input).toHaveText("")
22+
await expect(input).toBeEditable()
23+
}
24+
25+
test("Title is visible", async ({ page }) => {
26+
await page.goto("/login")
27+
28+
await expect(page.getByRole("heading", { name: "Welcome!" })).toBeVisible()
29+
})
30+
31+
test("Inputs are visible, empty and editable", async ({ page }) => {
32+
await page.goto("/login")
33+
34+
await verifyInput(page, "Email")
35+
await verifyInput(page, "Password", { exact: true })
36+
})
37+
38+
test("Log In button is visible", async ({ page }) => {
39+
await page.goto("/login")
40+
41+
await expect(page.getByRole("button", { name: "Log In" })).toBeVisible()
42+
})
43+
44+
test("Forgot Password link is visible", async ({ page }) => {
45+
await page.goto("/login")
46+
47+
await expect(
48+
page.getByRole("link", { name: "Forgot password?" }),
49+
).toBeVisible()
50+
})
51+
52+
test("Sign Up link is visible", async ({ page }) => {
53+
await page.goto("/login")
54+
55+
await expect(page.getByRole("link", { name: "Sign Up" })).toBeVisible()
56+
})
57+
58+
test("Log in with valid email and password ", async ({ page }) => {
59+
await page.goto("/login")
60+
61+
await fillForm(page, "[email protected]", "changethis")
62+
await page.getByRole("button", { name: "Log In" }).click()
63+
64+
await page.waitForURL("/")
65+
66+
await expect(page.getByTestId("result")).toContainText(
67+
"Hi, fastapi admin 👋🏼",
68+
)
69+
})
70+
71+
test("Log in with invalid email", async ({ page }) => {
72+
await page.goto("/login")
73+
74+
await fillForm(page, "invalidemail", "changethis")
75+
await page.getByRole("button", { name: "Log In" }).click()
76+
77+
await expect(page.getByText("Invalid email address")).toBeVisible()
78+
})
79+
80+
test("Log in with invalid password", async ({ page }) => {
81+
await page.goto("/login")
82+
83+
await fillForm(page, "[email protected]", "changethat")
84+
await page.getByRole("button", { name: "Log In" }).click()
85+
86+
await expect(page.getByText("Incorrect email or password")).toBeVisible()
87+
})
88+
89+
test("User session is maintained after login", async ({ page }) => {
90+
await page.goto("/login")
91+
92+
await fillForm(page, "[email protected]", "changethis")
93+
await page.getByRole("button", { name: "Log In" }).click()
94+
95+
await page.waitForURL("/")
96+
await page.reload()
97+
await page.waitForURL("/")
98+
await expect(page.getByTestId("result")).toContainText(
99+
"Hi, fastapi admin 👋🏼",
100+
)
101+
})
102+
103+
// Log out
104+
105+
test("Successful log out", async ({ page }) => {
106+
await page.goto("/login")
107+
108+
await fillForm(page, "[email protected]", "changethis")
109+
await page.getByRole("button", { name: "Log In" }).click()
110+
111+
await page.waitForURL("/")
112+
113+
await expect(page.getByTestId("result")).toContainText(
114+
"Hi, fastapi admin 👋🏼",
115+
)
116+
117+
await page.getByRole('button', { name: 'fastapi admin' }).click();
118+
await page.getByRole('menuitem', { name: 'Log out' }).click();
119+
await page.waitForURL("/login")
120+
})
121+
122+
test("Logged-out user cannot access protected routes", async ({ page }) => {
123+
await page.goto("/login")
124+
125+
await fillForm(page, "[email protected]", "changethis")
126+
await page.getByRole("button", { name: "Log In" }).click()
127+
128+
await page.waitForURL("/")
129+
130+
await expect(page.getByTestId("result")).toContainText(
131+
"Hi, fastapi admin 👋🏼",
132+
)
133+
134+
await page.getByRole('button', { name: 'fastapi admin' }).click();
135+
await page.getByRole('menuitem', { name: 'Log out' }).click();
136+
await page.waitForURL("/login")
137+
138+
await page.goto("/settings")
139+
await page.waitForURL("/login?redirect=%2Fsettings")
140+
})

0 commit comments

Comments
 (0)