-
Notifications
You must be signed in to change notification settings - Fork 166
LG-6139: Handle and display password confirm errors #6337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
19f2126
7e21d8f
8d1da98
0dbf36c
f493376
d19e40c
f8c1730
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import FormError from './form-error'; | ||
|
|
||
| describe('FormError', () => { | ||
| it('constructs with a message', () => { | ||
| const error = new FormError('message'); | ||
|
|
||
| expect(error.message).to.equal('message'); | ||
| expect(error.isDetail).to.be.false(); | ||
| expect(error.field).to.be.undefined(); | ||
| }); | ||
|
|
||
| it('constructs as detailed error', () => { | ||
| const error = new FormError('message', { isDetail: true }); | ||
|
|
||
| expect(error.message).to.equal('message'); | ||
| expect(error.isDetail).to.be.true(); | ||
| expect(error.field).to.be.undefined(); | ||
| }); | ||
|
|
||
| it('constructs as associated with a field', () => { | ||
| const error = new FormError('message', { field: 'field' }); | ||
|
|
||
| expect(error.message).to.equal('message'); | ||
| expect(error.isDetail).to.be.false(); | ||
| expect(error.field).to.equal('field'); | ||
| }); | ||
|
|
||
| it('supports message on subclass property initializer', () => { | ||
| class ExampleFormError extends FormError { | ||
| message = 'message'; | ||
| } | ||
|
|
||
| const error = new ExampleFormError(); | ||
|
|
||
| expect(error.message).to.equal('message'); | ||
| expect(error.isDetail).to.be.false(); | ||
| expect(error.field).to.be.undefined(); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,7 @@ | ||
| export interface ErrorResponse<Field extends string> { | ||
| error: Record<Field, [string, ...string[]]>; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this this
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, exactly that. I don't know that it's strictly necessary here, but it seems reasonable to expect that if the response is an error response, there's at least one error message. |
||
| } | ||
|
|
||
| interface PostOptions { | ||
| /** | ||
| * Whether to send the request as a JSON request. | ||
|
|
@@ -41,3 +45,7 @@ export async function post<Response = any>( | |
|
|
||
| return options.json ? response.json() : response.text(); | ||
| } | ||
|
|
||
| export const isErrorResponse = <F extends string>( | ||
| response: object | ErrorResponse<F>, | ||
| ): response is ErrorResponse<F> => 'error' in response; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,53 @@ | ||
| import { FormError } from '@18f/identity-form-steps'; | ||
| import { useSandbox } from '@18f/identity-test-helpers'; | ||
| import submit, { API_ENDPOINT } from './submit'; | ||
|
|
||
| describe('submit', () => { | ||
| const sandbox = useSandbox(); | ||
|
|
||
| beforeEach(() => { | ||
| sandbox | ||
| .stub(window, 'fetch') | ||
| .withArgs( | ||
| API_ENDPOINT, | ||
| sandbox.match({ body: JSON.stringify({ user_bundle_token: '..', password: 'hunter2' }) }), | ||
| ) | ||
| .resolves({ | ||
| json: () => Promise.resolve({ personal_key: '0000-0000-0000-0000' }), | ||
| } as Response); | ||
| context('with successful submission', () => { | ||
| beforeEach(() => { | ||
| sandbox | ||
| .stub(window, 'fetch') | ||
| .withArgs( | ||
| API_ENDPOINT, | ||
| sandbox.match({ body: JSON.stringify({ user_bundle_token: '..', password: 'hunter2' }) }), | ||
| ) | ||
| .resolves({ | ||
| json: () => Promise.resolve({ personal_key: '0000-0000-0000-0000' }), | ||
| } as Response); | ||
| }); | ||
|
|
||
| it('sends with password confirmation values', async () => { | ||
| const patch = await submit({ userBundleToken: '..', password: 'hunter2' }); | ||
|
|
||
| expect(patch).to.deep.equal({ personalKey: '0000-0000-0000-0000' }); | ||
| }); | ||
| }); | ||
|
|
||
| it('sends with password confirmation values', async () => { | ||
| const patch = await submit({ userBundleToken: '..', password: 'hunter2' }); | ||
| context('error submission', () => { | ||
| beforeEach(() => { | ||
| sandbox | ||
| .stub(window, 'fetch') | ||
| .withArgs( | ||
| API_ENDPOINT, | ||
| sandbox.match({ body: JSON.stringify({ user_bundle_token: '..', password: 'hunter2' }) }), | ||
| ) | ||
| .resolves({ | ||
| json: () => Promise.resolve({ error: { password: ['incorrect password'] } }), | ||
| } as Response); | ||
| }); | ||
|
|
||
| it('throws error for the offending field', async () => { | ||
| const didError = await submit({ userBundleToken: '..', password: 'hunter2' }).catch( | ||
| (error: FormError) => { | ||
| expect(error.field).to.equal('password'); | ||
| expect(error.message).to.equal('incorrect password'); | ||
| return true; | ||
| }, | ||
| ); | ||
|
|
||
| expect(patch).to.deep.equal({ personalKey: '0000-0000-0000-0000' }); | ||
| expect(didError).to.be.true(); | ||
| }); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙂