Skip to content

Commit

Permalink
use playwright fixtures instead of hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
kentcdodds committed Sep 13, 2023
1 parent f6f1245 commit 85465db
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 127 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ module.exports = {
'prettier',
],
rules: {
// playwright requires destructuring in fixtures even if you don't use anything 🤷‍♂️
'no-empty-pattern': 'off',
'@typescript-eslint/consistent-type-imports': [
'warn',
{
Expand Down
27 changes: 0 additions & 27 deletions tests/db-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import fs from 'node:fs'
import { faker } from '@faker-js/faker'
import bcrypt from 'bcryptjs'
import { UniqueEnforcer } from 'enforce-unique'
import { getPasswordHash } from '#app/utils/auth.server.ts'
import { prisma } from '#app/utils/db.server.ts'

const uniqueUsernameEnforcer = new UniqueEnforcer()

Expand Down Expand Up @@ -38,31 +36,6 @@ export function createPassword(password: string = faker.internet.password()) {
}
}

export const insertedUsers = new Set<string>()

export async function insertNewUser({
username,
password,
email,
}: { username?: string; password?: string; email?: string } = {}) {
const userData = createUser()
username ??= userData.username
password ??= userData.username
email ??= userData.email
const user = await prisma.user.create({
select: { id: true, name: true, username: true, email: true },
data: {
...userData,
email,
username,
roles: { connect: { name: 'user' } },
password: { create: { hash: await getPasswordHash(password) } },
},
})
insertedUsers.add(user.id)
return user as typeof user & { name: string }
}

let noteImages: Array<Awaited<ReturnType<typeof img>>> | undefined
export async function getNoteImages() {
if (noteImages) return noteImages
Expand Down
13 changes: 7 additions & 6 deletions tests/e2e/2fa.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { generateTOTP } from '@epic-web/totp'
import { faker } from '@faker-js/faker'
import { expect, test } from '@playwright/test'
import { insertNewUser, loginPage } from '#tests/playwright-utils.ts'
import { expect, test } from '#tests/playwright-utils.ts'

test('Users can add 2FA to their account and use it when logging in', async ({
page,
login,
}) => {
const password = faker.internet.password()
const user = await insertNewUser({ password })
await loginPage({ page, user })
const user = await login({ password })
await page.goto('/settings/profile')

await page.getByRole('link', { name: /enable 2fa/i }).click()
Expand All @@ -31,7 +30,7 @@ test('Users can add 2FA to their account and use it when logging in', async ({
await expect(main).toHaveText(/You have enabled two-factor authentication./i)
await expect(main.getByRole('link', { name: /disable 2fa/i })).toBeVisible()

await page.getByRole('link', { name: user.name }).click()
await page.getByRole('link', { name: user.name ?? user.username }).click()
await page.getByRole('button', { name: /logout/i }).click()
await expect(page).toHaveURL(`/`)

Expand All @@ -47,5 +46,7 @@ test('Users can add 2FA to their account and use it when logging in', async ({

await page.getByRole('button', { name: /submit/i }).click()

await expect(page.getByRole('link', { name: user.name })).toBeVisible()
await expect(
page.getByRole('link', { name: user.name ?? user.username }),
).toBeVisible()
})
2 changes: 1 addition & 1 deletion tests/e2e/error-boundary.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expect, test } from '@playwright/test'
import { expect, test } from '#tests/playwright-utils.ts'

test('Test root error boundary caught', async ({ page }) => {
await page.goto('/does-not-exist')
Expand Down
15 changes: 7 additions & 8 deletions tests/e2e/notes.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { faker } from '@faker-js/faker'
import { expect, test } from '@playwright/test'
import { prisma } from '#app/utils/db.server.ts'
import { loginPage } from '#tests/playwright-utils.ts'
import { expect, test } from '#tests/playwright-utils.ts'

test('Users can create notes', async ({ page }) => {
const user = await loginPage({ page })
test('Users can create notes', async ({ page, login }) => {
const user = await login()
await page.goto(`/users/${user.username}/notes`)

const newNote = createNote()
Expand All @@ -18,8 +17,8 @@ test('Users can create notes', async ({ page }) => {
await expect(page).toHaveURL(new RegExp(`/users/${user.username}/notes/.*`))
})

test('Users can edit notes', async ({ page }) => {
const user = await loginPage({ page })
test('Users can edit notes', async ({ page, login }) => {
const user = await login()

const note = await prisma.note.create({
select: { id: true },
Expand All @@ -42,8 +41,8 @@ test('Users can edit notes', async ({ page }) => {
).toBeVisible()
})

test('Users can delete notes', async ({ page }) => {
const user = await loginPage({ page })
test('Users can delete notes', async ({ page, login }) => {
const user = await login()

const note = await prisma.note.create({
select: { id: true },
Expand Down
49 changes: 26 additions & 23 deletions tests/e2e/onboarding.test.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,39 @@
import { faker } from '@faker-js/faker'
import { expect, test } from '@playwright/test'
import { prisma } from '#app/utils/db.server.ts'
import { invariant } from '#app/utils/misc.tsx'
import { readEmail } from '#tests/mocks/utils.ts'
import { createUser, insertNewUser } from '#tests/playwright-utils.ts'
import { createUser, expect, test as base } from '#tests/playwright-utils.ts'

const urlRegex = /(?<url>https?:\/\/[^\s$.?#].[^\s]*)/
function extractUrl(text: string) {
const match = text.match(urlRegex)
return match?.groups?.url
}

function getOnboardingData() {
const userData = createUser()
const onboardingData = {
...userData,
password: faker.internet.password(),
const test = base.extend<{
getOnboardingData(): {
username: string
name: string
email: string
password: string
}
return onboardingData
}

const usernamesToDelete = new Set<string>()

test.afterEach(async () => {
for (const username of usernamesToDelete) {
await prisma.user.delete({ where: { username } })
}
usernamesToDelete.clear()
}>({
getOnboardingData: async ({}, use) => {
const userData = createUser()
await use(() => {
const onboardingData = {
...userData,
password: faker.internet.password(),
}
return onboardingData
})
await prisma.user
.delete({ where: { username: userData.username } })
.catch(() => {})
},
})

test('onboarding with link', async ({ page }) => {
test('onboarding with link', async ({ page, getOnboardingData }) => {
const onboardingData = getOnboardingData()

await page.goto('/')
Expand Down Expand Up @@ -78,7 +82,6 @@ test('onboarding with link', async ({ page }) => {

await page.getByLabel(/remember me/i).check()

usernamesToDelete.add(onboardingData.username)
await page.getByRole('button', { name: /Create an account/i }).click()

await expect(page).toHaveURL(`/`)
Expand All @@ -93,7 +96,7 @@ test('onboarding with link', async ({ page }) => {
await expect(page).toHaveURL(`/`)
})

test('onboarding with a short code', async ({ page }) => {
test('onboarding with a short code', async ({ page, getOnboardingData }) => {
const onboardingData = getOnboardingData()

await page.goto('/signup')
Expand Down Expand Up @@ -124,7 +127,7 @@ test('onboarding with a short code', async ({ page }) => {
await expect(page).toHaveURL(`/onboarding`)
})

test('login as existing user', async ({ page }) => {
test('login as existing user', async ({ page, insertNewUser }) => {
const password = faker.internet.password()
const user = await insertNewUser({ password })
invariant(user.name, 'User name not found')
Expand All @@ -137,7 +140,7 @@ test('login as existing user', async ({ page }) => {
await expect(page.getByRole('link', { name: user.name })).toBeVisible()
})

test('reset password with a link', async ({ page }) => {
test('reset password with a link', async ({ page, insertNewUser }) => {
const originalPassword = faker.internet.password()
const user = await insertNewUser({ password: originalPassword })
invariant(user.name, 'User name not found')
Expand Down Expand Up @@ -190,7 +193,7 @@ test('reset password with a link', async ({ page }) => {
await expect(page.getByRole('link', { name: user.name })).toBeVisible()
})

test('reset password with a short code', async ({ page }) => {
test('reset password with a short code', async ({ page, insertNewUser }) => {
const user = await insertNewUser()
await page.goto('/login')

Expand Down
7 changes: 4 additions & 3 deletions tests/e2e/search.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, test } from '@playwright/test'
import { insertNewUser } from '#tests/playwright-utils.ts'
import { invariant } from '#app/utils/misc.tsx'
import { expect, test } from '#tests/playwright-utils.ts'

test('Search from home page', async ({ page }) => {
test('Search from home page', async ({ page, insertNewUser }) => {
const newUser = await insertNewUser()
await page.goto('/')

Expand All @@ -14,6 +14,7 @@ test('Search from home page', async ({ page }) => {
await expect(page.getByText('Epic Notes Users')).toBeVisible()
const userList = page.getByRole('main').getByRole('list')
await expect(userList.getByRole('listitem')).toHaveCount(1)
invariant(newUser.name, 'User name not found')
await expect(page.getByAltText(newUser.name)).toBeVisible()

await page.getByRole('searchbox', { name: /search/i }).fill('__nonexistent__')
Expand Down
27 changes: 10 additions & 17 deletions tests/e2e/settings-profile.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { faker } from '@faker-js/faker'
import { expect, test } from '@playwright/test'
import { verifyUserPassword } from '#app/utils/auth.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { invariant } from '#app/utils/misc.tsx'
import { readEmail } from '#tests/mocks/utils.ts'
import {
createUser,
insertNewUser,
loginPage,
waitFor,
} from '#tests/playwright-utils.ts'

test('Users can update their basic info', async ({ page }) => {
await loginPage({ page })
import { expect, test , createUser, waitFor } from '#tests/playwright-utils.ts'

test('Users can update their basic info', async ({ page, login }) => {
await login()
await page.goto('/settings/profile')

const newUserData = createUser()
Expand All @@ -25,11 +19,10 @@ test('Users can update their basic info', async ({ page }) => {
await page.getByRole('button', { name: /^save/i }).click()
})

test('Users can update their password', async ({ page }) => {
test('Users can update their password', async ({ page, login }) => {
const oldPassword = faker.internet.password()
const newPassword = faker.internet.password()
const user = await insertNewUser({ password: oldPassword })
await loginPage({ page, user })
const user = await login({ password: oldPassword })
await page.goto('/settings/profile')

await page.getByRole('link', { name: /change password/i }).click()
Expand Down Expand Up @@ -57,8 +50,8 @@ test('Users can update their password', async ({ page }) => {
).toEqual({ id: user.id })
})

test('Users can update their profile photo', async ({ page }) => {
const user = await loginPage({ page })
test('Users can update their profile photo', async ({ page, login }) => {
const user = await login()
await page.goto('/settings/profile')

const beforeSrc = await page
Expand Down Expand Up @@ -87,8 +80,8 @@ test('Users can update their profile photo', async ({ page }) => {
expect(beforeSrc).not.toEqual(afterSrc)
})

test('Users can change their email address', async ({ page }) => {
const preUpdateUser = await loginPage({ page })
test('Users can change their email address', async ({ page, login }) => {
const preUpdateUser = await login()
const newEmailAddress = faker.internet.email().toLowerCase()
expect(preUpdateUser.email).not.toEqual(newEmailAddress)
await page.goto('/settings/profile')
Expand Down
Loading

0 comments on commit 85465db

Please sign in to comment.