Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/components/user-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ export function UserDropdown() {
// this is for progressive enhancement
onClick={(e) => e.preventDefault()}
className="flex items-center gap-2"
aria-label="User menu"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using an explicit label will override whatever accessible text the element has inferred.

>
<Img
className="size-8 rounded-full object-cover"
alt={user.name ?? user.username}
src={getUserImgSrc(user.image?.objectKey)}
width={256}
height={256}
aria-hidden="true"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user avatar is a decorative element in this context and should be disregarded accessibility-wise. Even its alt is not needed, but I fear to anger eslint at this point.

/>
<span className="text-body-sm font-bold">
{user.name ?? user.username}
Expand Down
1 change: 1 addition & 0 deletions app/routes/users+/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default function UsersRoute({ loaderData }: Route.ComponentProps) {
<Link
to={user.username}
className="bg-muted flex h-36 w-44 flex-col items-center justify-center rounded-lg px-5 py-3"
aria-label={`${user.name || user.username} profile`}
>
<Img
alt={user.name ?? user.username}
Expand Down
6 changes: 2 additions & 4 deletions tests/e2e/2fa.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,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 ?? user.username }).click()
await page.getByRole('link', { name: 'User menu' }).click()
await page.getByRole('menuitem', { name: /logout/i }).click()
await expect(page).toHaveURL(`/`)

Expand All @@ -58,7 +58,5 @@ 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 ?? user.username }),
).toBeVisible()
await expect(page.getByRole('link', { name: 'User menu' })).toBeVisible()
})
8 changes: 4 additions & 4 deletions tests/e2e/onboarding.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ test('onboarding with link', async ({ page, getOnboardingData }) => {

await expect(page).toHaveURL(`/`)

await page.getByRole('link', { name: onboardingData.name }).click()
await page.getByRole('link', { name: 'User menu' }).click()
await page.getByRole('menuitem', { name: /profile/i }).click()

await expect(page).toHaveURL(`/users/${onboardingData.username}`)

await page.getByRole('link', { name: onboardingData.name }).click()
await page.getByRole('link', { name: 'User menu' }).click()
await page.getByRole('menuitem', { name: /logout/i }).click()
await expect(page).toHaveURL(`/`)
})
Expand Down Expand Up @@ -332,7 +332,7 @@ test('login as existing user', async ({ page, insertNewUser }) => {
await page.getByRole('button', { name: /log in/i }).click()
await expect(page).toHaveURL(`/`)

await expect(page.getByRole('link', { name: user.name })).toBeVisible()
await expect(page.getByRole('link', { name: 'User menu' })).toBeVisible()
})

test('reset password with a link', async ({ page, insertNewUser }) => {
Expand Down Expand Up @@ -386,7 +386,7 @@ test('reset password with a link', async ({ page, insertNewUser }) => {

await expect(page).toHaveURL(`/`)

await expect(page.getByRole('link', { name: user.name })).toBeVisible()
await expect(page.getByRole('link', { name: 'User menu' })).toBeVisible()
})

test('reset password with a short code', async ({ page, insertNewUser }) => {
Expand Down
8 changes: 3 additions & 5 deletions tests/e2e/passkey.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
}

test('Users can register and use passkeys', async ({ page, login }) => {
const user = await login()

Check warning on line 22 in tests/e2e/passkey.test.ts

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'user' is assigned a value but never used. Allowed unused vars must match /^ignored/u

const { client, authenticatorId } = await setupWebAuthn(page)

Expand Down Expand Up @@ -53,7 +53,7 @@
).toHaveLength(1)

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

Expand All @@ -76,9 +76,7 @@
await Promise.race([passkeyAssertedPromise, errorPromise])

// Verify successful login
await expect(
page.getByRole('link', { name: user.name ?? user.username }),
).toBeVisible()
await expect(page.getByRole('link', { name: 'User menu' })).toBeVisible()

// Verify the sign count increased
const afterLoginCredentials = await client.send('WebAuthn.getCredentials', {
Expand All @@ -104,7 +102,7 @@
expect(afterDeletionCredentials.credentials).toHaveLength(1)

// Logout again to test deleted passkey
await page.getByRole('link', { name: user.name ?? user.username }).click()
await page.getByRole('link', { name: 'User menu' }).click()
await page.getByRole('menuitem', { name: /logout/i }).click()
await expect(page).toHaveURL(`/`)

Expand Down
15 changes: 9 additions & 6 deletions tests/e2e/search.test.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import { invariant } from '@epic-web/invariant'
import { expect, test } from '#tests/playwright-utils.ts'

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

// Search for an existing user.
await page.getByRole('searchbox', { name: /search/i }).fill(newUser.username)
await page.getByRole('button', { name: /search/i }).click()

await page.waitForURL(
`/users?${new URLSearchParams({ search: newUser.username })}`,
)
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 expect(
userList
.getByRole('listitem')
.getByRole('link', {
name: `${newUser.name || newUser.username} profile`,
}),
).toBeVisible()

// Search for a non-existing user.
await page.getByRole('searchbox', { name: /search/i }).fill('__nonexistent__')
await page.getByRole('button', { name: /search/i }).click()
await page.waitForURL(`/users?search=__nonexistent__`)
Expand Down