mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-02-06 03:13:42 -05:00
pass nextUrl through yubikey flow
the next url comes from sign in via a query param, and needs to go to the POST /webauthn/authenticate endpoint. That endpoint logs the user in and returns the redirect to the browser, and will take the next from the request query params to get there. also moving the window mocks to beforeEach/afterEach ensures that promise callbacks from previous tests aren't still associated in future tests to ensure good test isolation. unfortunately i couldn't get mocking location for a single js test to work, but by changing the global config i was able to add some query params that i can expect to be passed through. Don't love this at all but not quite sure of a good way round this. I think we're not practicing very good hygiene and best practices with our mocking and it's really confounding me here.
This commit is contained in:
@@ -8,18 +8,10 @@ beforeAll(() => {
|
||||
|
||||
// ensure window.alert() is implemented to simplify errors
|
||||
jest.spyOn(window, 'alert').mockImplementation(() => { })
|
||||
|
||||
// populate missing values to allow consistent jest.spyOn()
|
||||
window.fetch = () => { }
|
||||
window.navigator.credentials = { get: () => { } }
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
require('./support/teardown.js')
|
||||
|
||||
// restore window attributes to their original undefined state
|
||||
delete window.fetch
|
||||
delete window.navigator.credentials
|
||||
})
|
||||
|
||||
describe('Authenticate with security key', () => {
|
||||
@@ -30,10 +22,23 @@ describe('Authenticate with security key', () => {
|
||||
<button type="submit" data-module="authenticate-security-key" data-csrf-token="abc123"></button>
|
||||
`
|
||||
button = document.querySelector('[data-module="authenticate-security-key"]')
|
||||
|
||||
// populate missing values to allow consistent jest.spyOn()
|
||||
window.fetch = () => { }
|
||||
window.navigator.credentials = { get: () => { } }
|
||||
window.alert = () => { }
|
||||
|
||||
window.GOVUK.modules.start()
|
||||
})
|
||||
|
||||
test('authenticates a credential and redirects', (done) => {
|
||||
afterEach(() => {
|
||||
// restore window attributes to their original undefined state
|
||||
delete window.fetch
|
||||
delete window.navigator.credentials
|
||||
delete window.alert
|
||||
})
|
||||
|
||||
test('authenticates a credential and redirects based on the admin app response', (done) => {
|
||||
|
||||
jest.spyOn(window, 'fetch')
|
||||
.mockImplementationOnce((_url) => {
|
||||
@@ -93,6 +98,57 @@ describe('Authenticate with security key', () => {
|
||||
button.click()
|
||||
});
|
||||
|
||||
test('authenticates and passes a redirect url through to the authenticate admin endpoint', (done) => {
|
||||
jest.spyOn(window, 'fetch')
|
||||
.mockImplementationOnce((_url) => {
|
||||
// initial fetch of options from the server
|
||||
// fetch defaults to GET
|
||||
// options from the server are CBOR-encoded
|
||||
let webauthnOptions = window.CBOR.encode('someArbitraryOptions')
|
||||
|
||||
return Promise.resolve({
|
||||
ok: true, arrayBuffer: () => webauthnOptions
|
||||
})
|
||||
})
|
||||
|
||||
jest.spyOn(window.navigator.credentials, 'get').mockImplementation((options) => {
|
||||
let credentialsGetResponse = {
|
||||
response: {
|
||||
authenticatorData: [],
|
||||
signature: [],
|
||||
clientDataJSON: []
|
||||
},
|
||||
rawId: [],
|
||||
type: "public-key",
|
||||
}
|
||||
return Promise.resolve(credentialsGetResponse)
|
||||
})
|
||||
|
||||
jest.spyOn(window, 'fetch')
|
||||
.mockImplementationOnce((url, options = {}) => {
|
||||
// subsequent POST of credential data to server
|
||||
expect(url.toString()).toEqual(
|
||||
'https://www.notifications.service.gov.uk/webauthn/authenticate?next=%2Ffoo%3Fbar%3Dbaz'
|
||||
);
|
||||
|
||||
// mark the test as done here as we've finished all our asserts - if something goes wrong later and
|
||||
// we end up in the alert mock, that `done(msg)` will override this and mark the test as failed
|
||||
done();
|
||||
|
||||
const loginResponse = window.CBOR.encode({ redirect_url: '/foo' })
|
||||
return Promise.resolve({
|
||||
ok: true, arrayBuffer: () => Promise.resolve(loginResponse)
|
||||
})
|
||||
})
|
||||
|
||||
// make sure we error out if alert is called
|
||||
jest.spyOn(window, 'alert').mockImplementation((msg) => {
|
||||
done(msg)
|
||||
})
|
||||
|
||||
button.click()
|
||||
});
|
||||
|
||||
test.each([
|
||||
['network'],
|
||||
['server'],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
setupFiles: ['./support/setup.js'],
|
||||
testURL: 'https://www.notifications.service.gov.uk'
|
||||
testURL: 'https://www.notifications.service.gov.uk/?next=%2Ffoo%3Fbar%3Dbaz'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user