Skip to content

Commit 6d90892

Browse files
committed
make e2e tests more reliable
1 parent 55ead1d commit 6d90892

File tree

7 files changed

+61
-28
lines changed

7 files changed

+61
-28
lines changed

app/utils/user-validation.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export const UsernameSchema = z
88
message: 'Username can only include letters, numbers, and underscores',
99
})
1010
// users can type the username in any case, but we store it in lowercase
11-
.transform(value => value.toLowerCase())
11+
.transform(value => value.trim().toLowerCase())
1212

1313
export const PasswordSchema = z
1414
.string({ required_error: 'Password is required' })
@@ -22,7 +22,8 @@ export const NameSchema = z
2222
export const PhoneNumberSchema = z
2323
.string({ required_error: 'Phone number is required' })
2424
.min(3, { message: 'Phone number is too short' })
25-
.max(20, { message: 'Phone number is too long' })
25+
.max(30, { message: 'Phone number is too long' })
26+
.transform(value => value.trim())
2627

2728
export const PasswordAndConfirmPasswordSchema = z
2829
.object({ password: PasswordSchema, confirmPassword: PasswordSchema })

package-lock.json

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@
143143
"enforce-unique": "^1.3.0",
144144
"esbuild": "^0.21.4",
145145
"eslint": "^9.4.0",
146+
"filenamify": "^6.0.0",
146147
"fs-extra": "^11.2.0",
147148
"jsdom": "^24.1.0",
148149
"msw": "2.3.1",

tests/e2e/onboarding.test.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { invariant } from '@epic-web/invariant'
22
import { faker } from '@faker-js/faker'
33
import { prisma } from '#app/utils/db.server.ts'
4-
import { readText } from '#tests/mocks/utils.ts'
5-
import { createUser, expect, test as base } from '#tests/playwright-utils.ts'
4+
import { waitForText } from '#tests/mocks/utils.ts'
5+
import { test as base, createUser, expect } from '#tests/playwright-utils.ts'
66

77
const URL_REGEX = /(?<url>https?:\/\/[^\s$.?#].[^\s]*)/
88
const CODE_REGEX = /code: (?<code>[\d\w]+)/
@@ -62,8 +62,7 @@ test('onboarding with link', async ({ page, getOnboardingData }) => {
6262
const sourceNumber = await prisma.sourceNumber.findFirstOrThrow({
6363
select: { phoneNumber: true },
6464
})
65-
const textMessage = await readText(onboardingData.phoneNumber)
66-
invariant(textMessage, 'Text message not found')
65+
const textMessage = await waitForText(onboardingData.phoneNumber)
6766
expect(textMessage.To).toBe(onboardingData.phoneNumber.toLowerCase())
6867
expect(textMessage.From).toBe(sourceNumber.phoneNumber)
6968
expect(textMessage.Body).toMatch(/welcome/i)
@@ -127,8 +126,9 @@ test('onboarding with a short code', async ({ page, getOnboardingData }) => {
127126
const sourceNumber = await prisma.sourceNumber.findFirstOrThrow({
128127
select: { phoneNumber: true },
129128
})
130-
const textMessage = await readText(onboardingData.phoneNumber)
131-
invariant(textMessage, 'Text message not found')
129+
const textMessage = await waitForText(onboardingData.phoneNumber, {
130+
errorMessage: 'Onboarding code not found',
131+
})
132132
expect(textMessage.To).toBe(onboardingData.phoneNumber)
133133
expect(textMessage.From).toBe(sourceNumber.phoneNumber)
134134
expect(textMessage.Body).toMatch(/welcome/i)
@@ -176,8 +176,7 @@ test('reset password with a link', async ({ page, insertNewUser }) => {
176176
const sourceNumber = await prisma.sourceNumber.findFirstOrThrow({
177177
select: { phoneNumber: true },
178178
})
179-
const textMessage = await readText(user.phoneNumber)
180-
invariant(textMessage, 'Text message not found')
179+
const textMessage = await waitForText(user.phoneNumber)
181180
expect(textMessage.Body).toMatch(/password reset/i)
182181
expect(textMessage.To).toBe(user.phoneNumber)
183182
expect(textMessage.From).toBe(sourceNumber.phoneNumber)
@@ -237,8 +236,7 @@ test('reset password with a short code', async ({ page, insertNewUser }) => {
237236
const sourceNumber = await prisma.sourceNumber.findFirstOrThrow({
238237
select: { phoneNumber: true },
239238
})
240-
const textMessage = await readText(user.phoneNumber)
241-
invariant(textMessage, 'Text message not found')
239+
const textMessage = await waitForText(user.phoneNumber)
242240
expect(textMessage.Body).toMatch(/password reset/i)
243241
expect(textMessage.To).toBe(user.phoneNumber)
244242
expect(textMessage.From).toBe(sourceNumber.phoneNumber)

tests/e2e/send.test.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import { invariant } from '@epic-web/invariant'
21
import { faker } from '@faker-js/faker'
32
import { prisma } from '#app/utils/db.server.ts'
4-
import { readText } from '#tests/mocks/utils.ts'
3+
import { waitForText } from '#tests/mocks/utils.ts'
54
import {
5+
createMessage,
6+
createRecipient,
67
expect,
78
test,
8-
createRecipient,
9-
createMessage,
109
waitFor,
1110
} from '#tests/playwright-utils.ts'
1211

@@ -48,8 +47,7 @@ test('Users can write and send a message immediately', async ({
4847
const sourceNumber = await prisma.sourceNumber.findFirstOrThrow({
4948
select: { phoneNumber: true },
5049
})
51-
const textMessage = await readText(recipient.phoneNumber)
52-
invariant(textMessage, 'Text message not found')
50+
const textMessage = await waitForText(recipient.phoneNumber)
5351
expect(textMessage.To).toBe(recipient.phoneNumber)
5452
expect(textMessage.From).toBe(sourceNumber.phoneNumber)
5553

@@ -116,8 +114,7 @@ test('Scheduled messages go out on schedule', async ({ page, login }) => {
116114
const sourceNumber = await prisma.sourceNumber.findFirstOrThrow({
117115
select: { phoneNumber: true },
118116
})
119-
const textMessage = await readText(recipient.phoneNumber)
120-
invariant(textMessage, 'Text message not found')
117+
const textMessage = await waitForText(recipient.phoneNumber)
121118
expect(textMessage.To).toBe(recipient.phoneNumber)
122119
expect(textMessage.From).toBe(sourceNumber.phoneNumber)
123120

tests/e2e/settings-profile.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { invariant } from '@epic-web/invariant'
22
import { faker } from '@faker-js/faker'
33
import { verifyUserPassword } from '#app/utils/auth.server.ts'
44
import { prisma } from '#app/utils/db.server.ts'
5-
import { readText } from '#tests/mocks/utils.ts'
6-
import { expect, test, createUser, waitFor } from '#tests/playwright-utils.ts'
5+
import { waitForText } from '#tests/mocks/utils.ts'
6+
import { createUser, expect, test } from '#tests/playwright-utils.ts'
77

88
const CODE_REGEX = /Here's your verification code: (?<code>[\d\w]+)/
99

@@ -63,7 +63,7 @@ test('Users can change their phone number', async ({ page, login }) => {
6363
.fill(newPhoneNumber)
6464
await page.getByRole('button', { name: /send confirmation/i }).click()
6565
await expect(page.getByText(/check your texts/i)).toBeVisible()
66-
const text = await waitFor(() => readText(newPhoneNumber), {
66+
const text = await waitForText(newPhoneNumber, {
6767
errorMessage: 'Confirmation text message was not sent',
6868
})
6969
invariant(text, 'Text was not sent')
@@ -80,7 +80,7 @@ test('Users can change their phone number', async ({ page, login }) => {
8080
})
8181
invariant(updatedUser, 'Updated user not found')
8282
expect(updatedUser.phoneNumber).toBe(newPhoneNumber)
83-
const noticeText = await waitFor(() => readText(preUpdateUser.phoneNumber), {
83+
const noticeText = await waitForText(preUpdateUser.phoneNumber, {
8484
errorMessage: 'Notice text was not sent',
8585
})
8686
expect(noticeText.Body).toContain('changed')

tests/mocks/utils.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import path from 'node:path'
22
import { fileURLToPath } from 'node:url'
3+
import filenamify from 'filenamify'
34
import fsExtra from 'fs-extra'
45
import { z } from 'zod'
6+
import { waitFor } from '#tests/playwright-utils.js'
57

68
const __dirname = path.dirname(fileURLToPath(import.meta.url))
79
const fixturesDirPath = path.join(__dirname, '..', 'fixtures')
@@ -28,7 +30,7 @@ export const TextMessageSchema = z.object({
2830

2931
export async function writeText(rawText: unknown) {
3032
const textMessage = TextMessageSchema.parse(rawText)
31-
await createFixture('texts', textMessage.To, textMessage)
33+
await createFixture('texts', filenamify(textMessage.To), textMessage)
3234
return textMessage
3335
}
3436

@@ -40,14 +42,20 @@ export async function requireText(recipient: string) {
4042

4143
export async function readText(recipient: string) {
4244
try {
43-
const textMessage = await readFixture('texts', recipient)
45+
const textMessage = await readFixture('texts', filenamify(recipient))
4446
return TextMessageSchema.parse(textMessage)
45-
} catch (error) {
46-
console.error(`Error reading text message to ${recipient}`, error)
47+
} catch {
4748
return null
4849
}
4950
}
5051

52+
export async function waitForText(
53+
recipient: string,
54+
options: Parameters<typeof waitFor>[1] = {},
55+
) {
56+
return waitFor(() => requireText(recipient), options)
57+
}
58+
5159
export function requireHeader(headers: Headers, header: string) {
5260
if (!headers.has(header)) {
5361
const headersString = JSON.stringify(

0 commit comments

Comments
 (0)