feat: password reset full design and flow
This commit is contained in:
1 parent
938263cd6a
commit
cb05b38f36
9 files changed
+1471
-4
No files matched your search
@@ -392,6 +392,51 @@ async function chooseArticleRowMenuItem(page: Page, label: string) {
|
||||
await page.getByRole('menuitem', { name: label, exact: true }).click()
|
||||
}
|
||||
|
||||
async function fillResetRequestEmail(page: Page, email: string) {
|
||||
await page.getByPlaceholder('you@example.com').fill(email)
|
||||
}
|
||||
|
||||
function submitResetRequest(email: string) {
|
||||
return async (page: Page) => {
|
||||
await fillResetRequestEmail(page, email)
|
||||
await page.getByRole('button', { name: 'Send reset link', exact: true }).click()
|
||||
await page.mouse.move(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
function resetRequestWith(response: ApiMock): Omit<VisualState, 'steps'> {
|
||||
return {
|
||||
path: '/register/reset/request',
|
||||
api: {
|
||||
'POST /v1/auth/password-reset': response,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const resetConfirmPath = '/register/reset/validate?c=abc123&email=marta%40renew.example'
|
||||
|
||||
async function fillResetConfirm(page: Page, password: string, confirmPassword: string) {
|
||||
await page.locator('#reset-new-password').fill(password)
|
||||
await page.locator('#reset-confirm-password').fill(confirmPassword)
|
||||
}
|
||||
|
||||
function submitResetConfirm(password: string, confirmPassword: string) {
|
||||
return async (page: Page) => {
|
||||
await fillResetConfirm(page, password, confirmPassword)
|
||||
await page.getByRole('button', { name: 'Change password', exact: true }).click()
|
||||
await page.mouse.move(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
function resetConfirmWith(response: ApiMock): Omit<VisualState, 'steps'> {
|
||||
return {
|
||||
path: resetConfirmPath,
|
||||
api: {
|
||||
'POST /v1/auth/password-reset/confirm': response,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const integrationOrigin = 'https://cms.renew.example'
|
||||
|
||||
async function clickBaseUrlCopy(page: Page) {
|
||||
@@ -1022,4 +1067,68 @@ export const visualStates: Record<string, Record<string, VisualState>> = {
|
||||
path: '/register/validate',
|
||||
},
|
||||
},
|
||||
'forgot-password': {
|
||||
Default: { path: '/register/reset/request' },
|
||||
'Validation error': {
|
||||
path: '/register/reset/request',
|
||||
steps: submitResetRequest('marta@renew'),
|
||||
},
|
||||
Submitting: {
|
||||
...resetRequestWith({ status: 200, hang: true }),
|
||||
steps: submitResetRequest('marta@renew.example'),
|
||||
},
|
||||
Sent: {
|
||||
...resetRequestWith({ status: 200, body: { message: 'ok' } }),
|
||||
steps: submitResetRequest('marta@renew.example'),
|
||||
},
|
||||
'Too many attempts (429)': {
|
||||
...resetRequestWith({ status: 429, headers: { 'Retry-After': '58' } }),
|
||||
steps: submitResetRequest('marta@renew.example'),
|
||||
},
|
||||
'Server error': {
|
||||
...resetRequestWith({ status: 500 }),
|
||||
steps: submitResetRequest('marta@renew.example'),
|
||||
},
|
||||
},
|
||||
'reset-password': {
|
||||
Default: { path: resetConfirmPath },
|
||||
'Too short': {
|
||||
path: resetConfirmPath,
|
||||
steps: submitResetConfirm('lime', 'lime'),
|
||||
},
|
||||
Mismatch: {
|
||||
path: resetConfirmPath,
|
||||
steps: async (page) => {
|
||||
await fillResetConfirm(page, 'limewash2026', 'limewash2025')
|
||||
await page.locator('#reset-confirm-password').blur()
|
||||
},
|
||||
},
|
||||
Submitting: {
|
||||
...resetConfirmWith({ status: 200, hang: true }),
|
||||
steps: submitResetConfirm('limewash2026', 'limewash2026'),
|
||||
},
|
||||
Success: {
|
||||
path: resetConfirmPath,
|
||||
api: {
|
||||
'POST /v1/auth/password-reset/confirm': { status: 200, body: { message: 'ok' } },
|
||||
'GET /v1/auth/registration': registrationClosed,
|
||||
},
|
||||
steps: async (page) => {
|
||||
await submitResetConfirm('limewash2026', 'limewash2026')(page)
|
||||
await page.waitForURL('**/login**')
|
||||
await page.getByText('Password changed').waitFor()
|
||||
},
|
||||
},
|
||||
'Invalid or expired (403)': {
|
||||
...resetConfirmWith({ status: 403 }),
|
||||
steps: submitResetConfirm('limewash2026', 'limewash2026'),
|
||||
},
|
||||
'Missing parameters': {
|
||||
path: '/register/reset/validate',
|
||||
},
|
||||
'Server error': {
|
||||
...resetConfirmWith({ status: 500 }),
|
||||
steps: submitResetConfirm('limewash2026', 'limewash2026'),
|
||||
},
|
||||
},
|
||||
}
|
||||
Reference in new issue
Block a user