- Sign-up emails a confirmation link (24h); unconfirmed accounts see a banner on the web with "send it again", and status in Settings. - Change email (needs the password): the new address gets a confirmation link and only replaces the old one once clicked; the old address gets a heads-up with a reset-password link. Pending changes can be cancelled. - Change password (needs the current one): signs out other sessions. - Password fields have Show/Hide on web and mobile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MzFywujuH9TiuXbr9vjoX8
This commit is contained in:
@@ -7,10 +7,11 @@ beforeEach(() => {
|
||||
outbox.length = 0;
|
||||
});
|
||||
|
||||
/** The email is sent in the background; give it a moment. */
|
||||
/** The reset email is sent in the background; give it a moment. (Sign-up sends its own confirmation email.) */
|
||||
async function nextMail() {
|
||||
for (let i = 0; i < 50 && outbox.length === 0; i++) await new Promise((r) => setTimeout(r, 10));
|
||||
return outbox.at(-1);
|
||||
const reset = () => outbox.filter((m) => m.subject.startsWith('Reset')).at(-1);
|
||||
for (let i = 0; i < 50 && !reset(); i++) await new Promise((r) => setTimeout(r, 10));
|
||||
return reset();
|
||||
}
|
||||
|
||||
const tokenFrom = (text: string) => new URL(text.match(/http\S+/)![0]).searchParams.get('token')!;
|
||||
@@ -50,7 +51,7 @@ describe('password reset', () => {
|
||||
const res = await requestReset('nobody@example.com');
|
||||
expect(res.json()).toEqual({ ok: true });
|
||||
await new Promise((r) => setTimeout(r, 100));
|
||||
expect(outbox).toHaveLength(0);
|
||||
expect(outbox.filter((m) => m.subject.startsWith('Reset'))).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('links work once, and a new request replaces the old link', async () => {
|
||||
|
||||
Reference in New Issue
Block a user