mirror of
https://github.com/fastapi/full-stack-fastapi-template.git
synced 2026-11-03 12:29:42 +00:00
✅ Simplify password reset E2E tests (#2453)
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
import { expect, test } from "@playwright/test"
|
import { expect, test } from "@playwright/test"
|
||||||
import { emailUrl, findLastEmail } from "./utils/mailpit"
|
import { waitForEmailHtml } from "./utils/mailpit"
|
||||||
import { randomEmail, randomPassword } from "./utils/random"
|
import { randomEmail, randomPassword } from "./utils/random"
|
||||||
import { logInUser, signUpNewUser } from "./utils/user"
|
import { logInUser, signUpNewUser } from "./utils/user"
|
||||||
|
|
||||||
test.use({ storageState: { cookies: [], origins: [] } })
|
test.use({ storageState: { cookies: [], origins: [] } })
|
||||||
|
|
||||||
|
const resetPath = "/reset-password?token="
|
||||||
|
|
||||||
test("Password Recovery title is visible", async ({ page }) => {
|
test("Password Recovery title is visible", async ({ page }) => {
|
||||||
await page.goto("/recover-password")
|
await page.goto("/recover-password")
|
||||||
|
|
||||||
@@ -44,21 +46,17 @@ test("User can reset password successfully using the link", async ({
|
|||||||
|
|
||||||
await page.getByRole("button", { name: "Continue" }).click()
|
await page.getByRole("button", { name: "Continue" }).click()
|
||||||
|
|
||||||
const emailData = await findLastEmail({
|
const emailHtml = await waitForEmailHtml({
|
||||||
request,
|
request,
|
||||||
query: `to:${email}`,
|
query: `to:${email}`,
|
||||||
timeout: 5000,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await page.goto(emailUrl(emailData))
|
expect(emailHtml).toContain(resetPath)
|
||||||
|
const resetUrl = emailHtml.match(/\/reset-password\?token=[^"]+/)?.[0]
|
||||||
const selector = 'a[href*="/reset-password?token="]'
|
expect(resetUrl).toBeDefined()
|
||||||
|
|
||||||
const url = await page.getAttribute(selector, "href")
|
|
||||||
const resetUrl = new URL(url!)
|
|
||||||
|
|
||||||
// Set the new password and confirm it
|
// Set the new password and confirm it
|
||||||
await page.goto(`${resetUrl.pathname}${resetUrl.search}`)
|
await page.goto(resetUrl!)
|
||||||
|
|
||||||
await page.getByTestId("new-password-input").fill(newPassword)
|
await page.getByTestId("new-password-input").fill(newPassword)
|
||||||
await page.getByTestId("confirm-password-input").fill(newPassword)
|
await page.getByTestId("confirm-password-input").fill(newPassword)
|
||||||
@@ -95,20 +93,17 @@ test("Weak new password validation", async ({ page, request }) => {
|
|||||||
await page.getByTestId("email-input").fill(email)
|
await page.getByTestId("email-input").fill(email)
|
||||||
await page.getByRole("button", { name: "Continue" }).click()
|
await page.getByRole("button", { name: "Continue" }).click()
|
||||||
|
|
||||||
const emailData = await findLastEmail({
|
const emailHtml = await waitForEmailHtml({
|
||||||
request,
|
request,
|
||||||
query: `to:${email}`,
|
query: `to:${email}`,
|
||||||
timeout: 5000,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await page.goto(emailUrl(emailData))
|
expect(emailHtml).toContain(resetPath)
|
||||||
|
const resetUrl = emailHtml.match(/\/reset-password\?token=[^"]+/)?.[0]
|
||||||
const selector = 'a[href*="/reset-password?token="]'
|
expect(resetUrl).toBeDefined()
|
||||||
const url = await page.getAttribute(selector, "href")
|
|
||||||
const resetUrl = new URL(url!)
|
|
||||||
|
|
||||||
// Set a weak new password
|
// Set a weak new password
|
||||||
await page.goto(`${resetUrl.pathname}${resetUrl.search}`)
|
await page.goto(resetUrl!)
|
||||||
await page.getByTestId("new-password-input").fill(weakPassword)
|
await page.getByTestId("new-password-input").fill(weakPassword)
|
||||||
await page.getByTestId("confirm-password-input").fill(weakPassword)
|
await page.getByTestId("confirm-password-input").fill(weakPassword)
|
||||||
await page.getByRole("button", { name: "Reset Password" }).click()
|
await page.getByRole("button", { name: "Reset Password" }).click()
|
||||||
|
|||||||
@@ -1,36 +1,10 @@
|
|||||||
import type { APIRequestContext } from "@playwright/test"
|
import type { APIRequestContext } from "@playwright/test"
|
||||||
|
|
||||||
type Address = {
|
type EmailSummary = {
|
||||||
Name: string
|
|
||||||
Address: string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Email = {
|
|
||||||
ID: string
|
ID: string
|
||||||
To: Address[]
|
|
||||||
Subject: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findEmail({
|
export async function waitForEmailHtml({
|
||||||
request,
|
|
||||||
query,
|
|
||||||
}: {
|
|
||||||
request: APIRequestContext
|
|
||||||
query: string
|
|
||||||
}) {
|
|
||||||
const response = await request.get(
|
|
||||||
`${process.env.MAILPIT_HOST}/api/v1/search`,
|
|
||||||
{
|
|
||||||
params: { query, limit: 1 },
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
const { messages }: { messages: Email[] } = await response.json()
|
|
||||||
|
|
||||||
return messages[0] ?? null
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function findLastEmail({
|
|
||||||
request,
|
request,
|
||||||
query,
|
query,
|
||||||
timeout = 5000,
|
timeout = 5000,
|
||||||
@@ -42,10 +16,27 @@ export async function findLastEmail({
|
|||||||
const deadline = Date.now() + timeout
|
const deadline = Date.now() + timeout
|
||||||
|
|
||||||
while (Date.now() < deadline) {
|
while (Date.now() < deadline) {
|
||||||
const email = await findEmail({ request, query })
|
const response = await request.get(
|
||||||
|
`${process.env.MAILPIT_HOST}/api/v1/search`,
|
||||||
|
{
|
||||||
|
params: { query, limit: 1 },
|
||||||
|
},
|
||||||
|
)
|
||||||
|
const { messages }: { messages: EmailSummary[] } = await response.json()
|
||||||
|
const email = messages[0]
|
||||||
|
|
||||||
if (email) {
|
if (email) {
|
||||||
return email
|
const htmlResponse = await request.get(
|
||||||
|
`${process.env.MAILPIT_HOST}/view/${email.ID}.html`,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!htmlResponse.ok()) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not get the HTML for email "${email.ID}": ${htmlResponse.status()}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return htmlResponse.text()
|
||||||
}
|
}
|
||||||
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 100))
|
await new Promise((resolve) => setTimeout(resolve, 100))
|
||||||
@@ -53,7 +44,3 @@ export async function findLastEmail({
|
|||||||
|
|
||||||
throw new Error(`Timeout while trying to get the latest email for "${query}"`)
|
throw new Error(`Timeout while trying to get the latest email for "${query}"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function emailUrl(email: Email) {
|
|
||||||
return `${process.env.MAILPIT_HOST}/view/${email.ID}.html`
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user