mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-08 08:28:15 -04:00
use mockImplementationOnce to define separate return vals for fetch
rather than having a gross if/else, we can define separately. This means we can separate the asserts and test setups for the first fetch (get) and the second fetch (post), which means we can arrange all the mocks in the order they're called in the function, significantly enhancing legibility of the tests
This commit is contained in:
@@ -36,6 +36,17 @@ describe('Register security key', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('creates a new credential and reloads', (done) => {
|
test('creates a new credential and reloads', (done) => {
|
||||||
|
|
||||||
|
jest.spyOn(window, 'fetch').mockImplementationOnce((_url) => {
|
||||||
|
// initial fetch of options from the server
|
||||||
|
// options from the server are CBOR-encoded
|
||||||
|
const webauthnOptions = window.CBOR.encode('options')
|
||||||
|
|
||||||
|
return Promise.resolve({
|
||||||
|
ok: true, arrayBuffer: () => webauthnOptions
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
jest.spyOn(window.navigator.credentials, 'create').mockImplementation((options) => {
|
jest.spyOn(window.navigator.credentials, 'create').mockImplementation((options) => {
|
||||||
expect(options).toEqual('options')
|
expect(options).toEqual('options')
|
||||||
|
|
||||||
@@ -49,29 +60,23 @@ describe('Register security key', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
jest.spyOn(window, 'fetch').mockImplementationOnce((_url, options) => {
|
||||||
|
// subsequent POST of credential data to server
|
||||||
|
const decodedData = window.CBOR.decode(options.body)
|
||||||
|
expect(decodedData.clientDataJSON).toEqual(new Uint8Array([4,5,6]))
|
||||||
|
expect(decodedData.attestationObject).toEqual(new Uint8Array([1,2,3]))
|
||||||
|
expect(options.headers['X-CSRFToken']).toBe()
|
||||||
|
return Promise.resolve({ ok: true })
|
||||||
|
});
|
||||||
|
|
||||||
jest.spyOn(window.location, 'reload').mockImplementation(() => {
|
jest.spyOn(window.location, 'reload').mockImplementation(() => {
|
||||||
// signal that the async promise chain was called
|
// signal that the async promise chain was called
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
jest.spyOn(window, 'fetch').mockImplementation((_url, options = {}) => {
|
// this will make the test fail if the alert is called
|
||||||
// initial fetch of options from the server
|
jest.spyOn(window, 'alert').mockImplementation((msg) => {
|
||||||
if (!options.method) {
|
done(msg)
|
||||||
// options from the server are CBOR-encoded
|
|
||||||
webauthnOptions = window.CBOR.encode('options')
|
|
||||||
|
|
||||||
return Promise.resolve({
|
|
||||||
ok: true, arrayBuffer: () => webauthnOptions
|
|
||||||
})
|
|
||||||
|
|
||||||
// subsequent POST of credential data to server
|
|
||||||
} else {
|
|
||||||
decodedData = window.CBOR.decode(options.body)
|
|
||||||
expect(decodedData.clientDataJSON).toEqual(new Uint8Array([4,5,6]))
|
|
||||||
expect(decodedData.attestationObject).toEqual(new Uint8Array([1,2,3]))
|
|
||||||
expect(options.headers['X-CSRFToken']).toBe()
|
|
||||||
return Promise.resolve({ ok: true })
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
button.click()
|
button.click()
|
||||||
@@ -81,7 +86,7 @@ describe('Register security key', () => {
|
|||||||
['network'],
|
['network'],
|
||||||
['server'],
|
['server'],
|
||||||
])('alerts if fetching WebAuthn options fails (%s error)', (errorType, done) => {
|
])('alerts if fetching WebAuthn options fails (%s error)', (errorType, done) => {
|
||||||
jest.spyOn(window, 'fetch').mockImplementation((_url, options = {}) => {
|
jest.spyOn(window, 'fetch').mockImplementation((_url) => {
|
||||||
if (errorType == 'network') {
|
if (errorType == 'network') {
|
||||||
return Promise.reject('error')
|
return Promise.reject('error')
|
||||||
} else {
|
} else {
|
||||||
@@ -102,32 +107,32 @@ describe('Register security key', () => {
|
|||||||
['internal server error'],
|
['internal server error'],
|
||||||
['bad request'],
|
['bad request'],
|
||||||
])('alerts if sending WebAuthn credentials fails (%s)', (errorType, done) => {
|
])('alerts if sending WebAuthn credentials fails (%s)', (errorType, done) => {
|
||||||
|
|
||||||
|
jest.spyOn(window, 'fetch').mockImplementationOnce((_url) => {
|
||||||
|
// initial fetch of options from the server
|
||||||
|
const webauthnOptions = window.CBOR.encode('options')
|
||||||
|
|
||||||
|
return Promise.resolve({
|
||||||
|
ok: true, arrayBuffer: () => webauthnOptions
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
jest.spyOn(window.navigator.credentials, 'create').mockImplementation(() => {
|
jest.spyOn(window.navigator.credentials, 'create').mockImplementation(() => {
|
||||||
// fake PublicKeyCredential response from WebAuthn API
|
// fake PublicKeyCredential response from WebAuthn API
|
||||||
return Promise.resolve({ response: {} })
|
return Promise.resolve({ response: {} })
|
||||||
})
|
})
|
||||||
|
|
||||||
jest.spyOn(window, 'fetch').mockImplementation((_url, options = {}) => {
|
jest.spyOn(window, 'fetch').mockImplementationOnce((_url) => {
|
||||||
// initial fetch of options from the server
|
|
||||||
if (!options.method) {
|
|
||||||
webauthnOptions = window.CBOR.encode('options')
|
|
||||||
|
|
||||||
return Promise.resolve({
|
|
||||||
ok: true, arrayBuffer: () => webauthnOptions
|
|
||||||
})
|
|
||||||
|
|
||||||
// subsequent POST of credential data to server
|
// subsequent POST of credential data to server
|
||||||
} else {
|
switch (errorType) {
|
||||||
switch (errorType) {
|
case 'network error':
|
||||||
case 'network error':
|
return Promise.reject('error')
|
||||||
return Promise.reject('error')
|
case 'bad request':
|
||||||
case 'bad request':
|
message = Promise.resolve(window.CBOR.encode('error'))
|
||||||
message = Promise.resolve(window.CBOR.encode('error'))
|
return Promise.resolve({ ok: false, arrayBuffer: () => message })
|
||||||
return Promise.resolve({ ok: false, arrayBuffer: () => message })
|
case 'internal server error':
|
||||||
case 'internal server error':
|
message = Promise.reject('encoding error')
|
||||||
message = Promise.reject('encoding error')
|
return Promise.resolve({ ok: false, arrayBuffer: () => message, statusText: 'error' })
|
||||||
return Promise.resolve({ ok: false, arrayBuffer: () => message, statusText: 'error' })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -144,9 +149,9 @@ describe('Register security key', () => {
|
|||||||
return Promise.reject(new DOMException('error'))
|
return Promise.reject(new DOMException('error'))
|
||||||
})
|
})
|
||||||
|
|
||||||
jest.spyOn(window, 'fetch').mockImplementation((_url, options) => {
|
jest.spyOn(window, 'fetch').mockImplementation((_url) => {
|
||||||
// initial fetch of options from the server
|
// initial fetch of options from the server
|
||||||
webauthnOptions = window.CBOR.encode('options')
|
const webauthnOptions = window.CBOR.encode('options')
|
||||||
|
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
ok: true, arrayBuffer: () => webauthnOptions
|
ok: true, arrayBuffer: () => webauthnOptions
|
||||||
|
|||||||
Reference in New Issue
Block a user