UNPKG

@defra-fish/gafl-webapp-service

Version:

The websales frontend for the GAFL service

588 lines (489 loc) • 25 kB
import { govUkPayApi, salesApi } from '@defra-fish/connectors-lib' import { GOVUK_PAY_ERROR_STATUS_CODES, PAYMENT_JOURNAL_STATUS_CODES } from '@defra-fish/business-rules-lib' import { initialize, injectWithCookies, start, stop, mockSalesApi } from '../../__mocks__/test-utils-system' import { ADULT_FULL_1_DAY_LICENCE, MOCK_PAYMENT_RESPONSE } from '../../__mocks__/mock-journeys.js' import { COMPLETION_STATUS } from '../../constants.js' import { AGREED, TEST_TRANSACTION, TEST_STATUS, PAYMENT_FAILED, PAYMENT_CANCELLED } from '../../uri.js' import agreedHandler from '../agreed-handler.js' import { getPaymentStatus, sendPayment } from '../../services/payment/govuk-pay-service.js' import { preparePayment } from '../../processors/payment.js' import { v4 as uuidv4 } from 'uuid' jest.mock('../../services/payment/govuk-pay-service.js') jest.mock('../../processors/payment.js') jest.mock('uuid', () => ({ v4: jest.fn(() => '') })) beforeAll(() => { process.env.ANALYTICS_PRIMARY_PROPERTY = 'GJDJKDKFJ' process.env.ANALYTICS_PROPERTY_API = 'XHHDjknw-sadcC' }) beforeAll(() => new Promise(resolve => start(resolve))) beforeAll(() => new Promise(resolve => initialize(resolve))) afterAll(d => stop(d)) afterAll(() => { delete process.env.ANALYTICS_PRIMARY_PROPERTY delete process.env.ANALYTICS_PROPERTY_API }) jest.mock('@defra-fish/connectors-lib') mockSalesApi() const TRY_AGAIN_STR = 'Try again' const paymentStatusCancelled = { state: { finished: true, status: 'cancelled', message: 'Payment cancelled', code: 'P0030' } } const paymentStatusRejected = { state: { finished: true, status: 'failed', message: 'Payment method rejected', code: 'P0010' } } const paymentStatusExpired = { state: { finished: true, status: 'failed', message: 'Payment expired', code: 'P0020' } } const paymentGeneralError = { state: { finished: true, status: 'error', message: 'Payment provider returned an error', code: 'P0050' } } const paymentTooManyRequests = { state: { finished: true, status: 'failed', message: 'Too many requests', code: 'P0900' } } const paymentIdNotFound = { state: { finished: true, code: 'P0200', description: 'paymentId not found' } } const paymentGovUkPayUnavailable = { code: 'P0999', description: 'GOV.UK Pay is unavailable' } const paymentIncomplete = { state: { status: 'started', finished: false } } const getMockRequest = () => ({ cache: () => ({ helpers: { transaction: { get: async () => ({ cost: 100, payment: { payment_id: 'abc-123' } }) }, status: { get: async () => ({ [COMPLETION_STATUS.agreed]: true, [COMPLETION_STATUS.posted]: true, [COMPLETION_STATUS.paymentCreated]: true }), set: async () => ({}) } } }), headers: { 'x-forwarded-proto': 'https' }, info: { host: 'localhost:1234' }, server: { info: { protocol: '' } } }) const getRequestToolkit = () => ({ redirectWithLanguageCode: jest.fn() }) const getSendPaymentMockImplementation = () => ({ payment_id: '', created_date: '', state: '', payment_provider: '', _links: { next_url: { href: '' }, self: { href: '' } } }) describe('The agreed handler', () => { beforeEach(() => { jest.clearAllMocks() uuidv4.mockReset() uuidv4.mockReturnValue('') const { sendPayment: realSendPayment, getPaymentStatus: realGetPaymentStatus } = jest.requireActual( '../../services/payment/govuk-pay-service.js' ) const { preparePayment: realPreparePayment } = jest.requireActual('../../processors/payment.js') getPaymentStatus.mockImplementation(paymentId => realGetPaymentStatus(paymentId)) preparePayment.mockImplementation((request, transaction) => realPreparePayment(request, transaction)) sendPayment.mockImplementation(preparedPayment => realSendPayment(preparedPayment)) }) it.each([ ['rejected', paymentStatusRejected], ['expired', paymentStatusExpired], ['general-error', paymentGeneralError] ])('redirects to the payment-failed page if the GOV.UK Pay returns %s on payment status fetch', async (desc, pstat) => { uuidv4.mockReturnValue(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id) await ADULT_FULL_1_DAY_LICENCE.setup() salesApi.createTransaction.mockResolvedValue(ADULT_FULL_1_DAY_LICENCE.transactionResponse) salesApi.finaliseTransaction.mockResolvedValue(ADULT_FULL_1_DAY_LICENCE.transactionResponse) govUkPayApi.createPayment = jest.fn( async () => new Promise(resolve => resolve({ json: () => MOCK_PAYMENT_RESPONSE, ok: true, status: 201 })) ) govUkPayApi.fetchPaymentStatus = jest.fn(async () => new Promise(resolve => resolve({ json: () => pstat, ok: true, status: 201 }))) const data1 = await injectWithCookies('GET', AGREED.uri) expect(data1.statusCode).toBe(302) expect(data1.headers.location).toBe(MOCK_PAYMENT_RESPONSE._links.next_url.href) // Return after payment rejected salesApi.updatePaymentJournal = jest.fn() const data2 = await injectWithCookies('GET', AGREED.uri) expect(data2.statusCode).toBe(302) expect(data2.headers.location).toHaveValidPathFor(PAYMENT_FAILED.uri) // Ensure that the journal status has been updated correctly expect(salesApi.updatePaymentJournal).toHaveBeenCalledWith(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id, { paymentStatus: PAYMENT_JOURNAL_STATUS_CODES.Failed }) // Ensure correctness of transaction const { payload } = await injectWithCookies('GET', TEST_TRANSACTION.uri) expect(JSON.parse(payload).id).toBe(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id) // Test states const { payload: status } = await injectWithCookies('GET', TEST_STATUS.uri) const parsedStatus = JSON.parse(status) expect(parsedStatus[COMPLETION_STATUS.agreed]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.posted]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCreated]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCompleted]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.finalised]).not.toBeTruthy() await injectWithCookies('GET', PAYMENT_FAILED.uri) const data4 = await injectWithCookies('POST', PAYMENT_FAILED.uri, {}) expect(data4.statusCode).toBe(302) expect(data4.headers.location).toHaveValidPathFor(AGREED.uri) // Test that the status has been updated correctly const { payload: status2 } = await injectWithCookies('GET', TEST_STATUS.uri) const parsedStatus2 = JSON.parse(status2) expect(parsedStatus2[COMPLETION_STATUS.agreed]).toBeTruthy() expect(parsedStatus2[COMPLETION_STATUS.posted]).toBeTruthy() expect(parsedStatus2[COMPLETION_STATUS.paymentCreated]).not.toBeTruthy() expect(parsedStatus2[COMPLETION_STATUS.paymentCompleted]).not.toBeTruthy() expect(parsedStatus2[COMPLETION_STATUS.finalised]).not.toBeTruthy() }) describe('GOV.UK returns an expired response', () => { beforeEach(() => { getPaymentStatus.mockReturnValueOnce({ state: { finished: true, status: 'failed', code: GOVUK_PAY_ERROR_STATUS_CODES.EXPIRED } }) }) it('calls redirect correctly', async () => { preparePayment.mockImplementation(() => {}) sendPayment.mockImplementation(() => getSendPaymentMockImplementation()) const requestToolkit = getRequestToolkit() const mockRequest = getMockRequest() await agreedHandler(mockRequest, requestToolkit) expect(requestToolkit.redirectWithLanguageCode).toHaveBeenCalledWith(PAYMENT_FAILED.uri) }) }) describe('GOV.UK returns a rejected response', () => { beforeEach(() => { getPaymentStatus.mockReturnValueOnce({ state: { finished: true, status: 'failed', code: GOVUK_PAY_ERROR_STATUS_CODES.REJECTED } }) }) it('calls redirect correctly', async () => { preparePayment.mockImplementation(() => {}) sendPayment.mockImplementation(() => getSendPaymentMockImplementation()) const requestToolkit = getRequestToolkit() const mockRequest = getMockRequest() await agreedHandler(mockRequest, requestToolkit) expect(requestToolkit.redirectWithLanguageCode).toHaveBeenCalledWith(PAYMENT_FAILED.uri) }) }) it('redirects to the payment-cancelled page if the GOV.UK Pay returns cancelled', async () => { uuidv4.mockReturnValue(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id) await ADULT_FULL_1_DAY_LICENCE.setup() salesApi.createTransaction = jest.fn(async () => new Promise(resolve => resolve(ADULT_FULL_1_DAY_LICENCE.transactionResponse))) govUkPayApi.createPayment = jest.fn( async () => new Promise(resolve => resolve({ json: () => MOCK_PAYMENT_RESPONSE, ok: true, status: 201 })) ) govUkPayApi.fetchPaymentStatus = jest.fn( async () => new Promise(resolve => resolve({ json: () => paymentStatusCancelled, ok: true, status: 201 })) ) const data1 = await injectWithCookies('GET', AGREED.uri) expect(data1.statusCode).toBe(302) expect(data1.headers.location).toBe(MOCK_PAYMENT_RESPONSE._links.next_url.href) // Return after payment cancelled salesApi.updatePaymentJournal = jest.fn() const data2 = await injectWithCookies('GET', AGREED.uri) expect(data2.statusCode).toBe(302) expect(data2.headers.location).toHaveValidPathFor(PAYMENT_CANCELLED.uri) // Ensure the the jounal status is set to cancelled expect(salesApi.updatePaymentJournal).toHaveBeenCalledWith(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id, { paymentStatus: PAYMENT_JOURNAL_STATUS_CODES.Cancelled }) // Ensure correctness of transaction const { payload } = await injectWithCookies('GET', TEST_TRANSACTION.uri) expect(JSON.parse(payload).id).toBe(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id) // Test states const { payload: status } = await injectWithCookies('GET', TEST_STATUS.uri) const parsedStatus = JSON.parse(status) expect(parsedStatus[COMPLETION_STATUS.agreed]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.posted]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCreated]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCompleted]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.finalised]).not.toBeTruthy() // Perform the redirect to the payment failed screen and attempt payment again await injectWithCookies('GET', PAYMENT_CANCELLED.uri) const data3 = await injectWithCookies('POST', PAYMENT_CANCELLED.uri, {}) expect(data3.statusCode).toBe(302) expect(data3.headers.location).toHaveValidPathFor(AGREED.uri) // Test that the status has been updated correctly const { payload: status2 } = await injectWithCookies('GET', TEST_STATUS.uri) const parsedStatus2 = JSON.parse(status2) expect(parsedStatus2[COMPLETION_STATUS.agreed]).toBeTruthy() expect(parsedStatus2[COMPLETION_STATUS.posted]).toBeTruthy() expect(parsedStatus2[COMPLETION_STATUS.paymentCreated]).not.toBeTruthy() expect(parsedStatus2[COMPLETION_STATUS.paymentCompleted]).not.toBeTruthy() expect(parsedStatus2[COMPLETION_STATUS.finalised]).not.toBeTruthy() // The agree handler (again) - ensure an update of the sales journal is created - to In progress salesApi.getPaymentJournal = jest.fn(async () => true) salesApi.updatePaymentJournal = jest.fn() await injectWithCookies('GET', AGREED.uri) expect(salesApi.updatePaymentJournal).toHaveBeenCalledWith(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id, { paymentReference: MOCK_PAYMENT_RESPONSE.payment_id, paymentTimestamp: MOCK_PAYMENT_RESPONSE.created_date, paymentStatus: PAYMENT_JOURNAL_STATUS_CODES.InProgress }) }) describe('GOV.UK returns a cancelled response', () => { beforeEach(() => { getPaymentStatus.mockReturnValueOnce({ state: { finished: true, status: 'failed', code: GOVUK_PAY_ERROR_STATUS_CODES.USER_CANCELLED } }) }) it('calls redirect correctly', async () => { preparePayment.mockImplementation(() => {}) sendPayment.mockImplementation(() => getSendPaymentMockImplementation()) const requestToolkit = getRequestToolkit() const mockRequest = getMockRequest() await agreedHandler(mockRequest, requestToolkit) expect(requestToolkit.redirectWithLanguageCode).toHaveBeenCalledWith(PAYMENT_CANCELLED.uri) }) }) it('posts a 500 (server) error with the retry flag set if the GOV.UK Pay API throws a (recoverable) exception on payment creation', async () => { uuidv4.mockReturnValueOnce(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id) await ADULT_FULL_1_DAY_LICENCE.setup() salesApi.createTransaction = jest.fn(async () => new Promise(resolve => resolve(ADULT_FULL_1_DAY_LICENCE.transactionResponse))) govUkPayApi.createPayment = jest.fn(async () => new Promise((resolve, reject) => reject(new Error('Time out')))) salesApi.getPaymentJournal = jest.fn() salesApi.updatePaymentJournal = jest.fn() salesApi.createPaymentJournal = jest.fn() const data = await injectWithCookies('GET', AGREED.uri) expect(data.statusCode).toBe(500) const { payload } = await injectWithCookies('GET', TEST_TRANSACTION.uri) expect(JSON.parse(payload).id).toBe(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id) const { payload: status } = await injectWithCookies('GET', TEST_STATUS.uri) const parsedStatus = JSON.parse(status) expect(parsedStatus[COMPLETION_STATUS.agreed]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.posted]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCreated]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCompleted]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.finalised]).not.toBeTruthy() // The journal is entry is not created where the API throws an exception expect(salesApi.getPaymentJournal).not.toHaveBeenCalled() expect(salesApi.updatePaymentJournal).not.toHaveBeenCalled() expect(salesApi.createPaymentJournal).not.toHaveBeenCalled() }) it('posts a 500 (server) error with the retry flag set if the GOV.UK Pay API rate limit is exceeded on create payment', async () => { uuidv4.mockReturnValueOnce(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id) await ADULT_FULL_1_DAY_LICENCE.setup() salesApi.createTransaction = jest.fn(async () => new Promise(resolve => resolve(ADULT_FULL_1_DAY_LICENCE.transactionResponse))) govUkPayApi.createPayment = jest.fn( async () => new Promise(resolve => resolve({ json: () => paymentTooManyRequests, ok: false, status: 429 })) ) salesApi.createPaymentJournal = jest.fn() const data = await injectWithCookies('GET', AGREED.uri) // No journal entry is created expect(salesApi.createPaymentJournal).not.toHaveBeenCalled() expect(data.statusCode).toBe(500) const { payload } = await injectWithCookies('GET', TEST_TRANSACTION.uri) expect(JSON.parse(payload).id).toBe(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id) const { payload: status } = await injectWithCookies('GET', TEST_STATUS.uri) const parsedStatus = JSON.parse(status) expect(parsedStatus[COMPLETION_STATUS.agreed]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.posted]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCreated]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCompleted]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.finalised]).not.toBeTruthy() }) it('posts a 500 error without the retry flag set if the GOV.UK Pay API returns any arbitrary 400 error on payment creation', async () => { await ADULT_FULL_1_DAY_LICENCE.setup() uuidv4.mockReturnValueOnce(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id) salesApi.createTransaction = jest.fn(async () => new Promise(resolve => resolve(ADULT_FULL_1_DAY_LICENCE.transactionResponse))) govUkPayApi.createPayment = jest.fn( async () => new Promise(resolve => resolve({ json: () => paymentIdNotFound, ok: false, status: 404 })) ) salesApi.createPaymentJournal = jest.fn() const data = await injectWithCookies('GET', AGREED.uri) expect(salesApi.createPaymentJournal).not.toHaveBeenCalled() expect(data.statusCode).toBe(500) expect(data.payload.includes(TRY_AGAIN_STR)).not.toBeTruthy() const { payload } = await injectWithCookies('GET', TEST_TRANSACTION.uri) expect(JSON.parse(payload).id).toBe(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id) const { payload: status } = await injectWithCookies('GET', TEST_STATUS.uri) const parsedStatus = JSON.parse(status) expect(parsedStatus[COMPLETION_STATUS.agreed]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.posted]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCreated]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.payed]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.finalised]).not.toBeTruthy() }) it('posts a 500 error without the retry flag set if the GOV.UK Pay API returns any arbitrary 500 error on payment creation', async () => { await ADULT_FULL_1_DAY_LICENCE.setup() uuidv4.mockReturnValueOnce(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id) salesApi.createTransaction = jest.fn(async () => new Promise(resolve => resolve(ADULT_FULL_1_DAY_LICENCE.transactionResponse))) govUkPayApi.createPayment = jest.fn( async () => new Promise(resolve => resolve({ json: () => paymentGovUkPayUnavailable, ok: false, status: 500 })) ) salesApi.createPaymentJournal = jest.fn() const data = await injectWithCookies('GET', AGREED.uri) expect(salesApi.createPaymentJournal).not.toHaveBeenCalled() expect(data.statusCode).toBe(500) expect(data.payload.includes(TRY_AGAIN_STR)).not.toBeTruthy() const { payload } = await injectWithCookies('GET', TEST_TRANSACTION.uri) expect(JSON.parse(payload).id).toBe(ADULT_FULL_1_DAY_LICENCE.transactionResponse.id) const { payload: status } = await injectWithCookies('GET', TEST_STATUS.uri) const parsedStatus = JSON.parse(status) expect(parsedStatus[COMPLETION_STATUS.agreed]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.posted]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCreated]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.payed]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.finalised]).not.toBeTruthy() }) it('posts a 400 (forbidden) error if requested where if the GOV.UK Pay API returns an incomplete payment status', async () => { await ADULT_FULL_1_DAY_LICENCE.setup() salesApi.createTransaction = jest.fn(async () => new Promise(resolve => resolve(ADULT_FULL_1_DAY_LICENCE.transactionResponse))) govUkPayApi.createPayment = jest.fn( async () => new Promise(resolve => resolve({ json: () => MOCK_PAYMENT_RESPONSE, ok: true, status: 201 })) ) govUkPayApi.fetchPaymentStatus = jest.fn( async () => new Promise((resolve, reject) => resolve({ json: () => paymentIncomplete, ok: true, status: 201 })) ) const data = await injectWithCookies('GET', AGREED.uri) expect(data.statusCode).toBe(302) expect(data.headers.location).toBe(MOCK_PAYMENT_RESPONSE._links.next_url.href) salesApi.updatePaymentJournal = jest.fn() const data2 = await injectWithCookies('GET', AGREED.uri) expect(data2.statusCode).toBe(403) // In this scenario - incomplete payment we may have hit the handler during payment (in another tab?) // This booms, the payment may still complete so do not interfere with the payment journal expect(salesApi.updatePaymentJournal).not.toHaveBeenCalledWith() const { payload: status } = await injectWithCookies('GET', TEST_STATUS.uri) const parsedStatus = JSON.parse(status) expect(parsedStatus[COMPLETION_STATUS.agreed]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.posted]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCreated]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCompleted]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.finalised]).not.toBeTruthy() }) it('posts a 500 (server) error if the GOV.UK Pay API throws en exception on fetching status', async () => { await ADULT_FULL_1_DAY_LICENCE.setup() salesApi.createTransaction = jest.fn(async () => new Promise(resolve => resolve(ADULT_FULL_1_DAY_LICENCE.transactionResponse))) govUkPayApi.createPayment = jest.fn( async () => new Promise(resolve => resolve({ json: () => MOCK_PAYMENT_RESPONSE, ok: true, status: 201 })) ) govUkPayApi.fetchPaymentStatus = jest.fn(async () => new Promise((resolve, reject) => reject(new Error('Timeout')))) const data1 = await injectWithCookies('GET', AGREED.uri) expect(data1.statusCode).toBe(302) expect(data1.headers.location).toBe(MOCK_PAYMENT_RESPONSE._links.next_url.href) salesApi.updatePaymentJournal = jest.fn() const data = await injectWithCookies('GET', AGREED.uri) expect(data.statusCode).toBe(500) expect(data.payload.includes(TRY_AGAIN_STR)).toBeTruthy() expect(salesApi.updatePaymentJournal).not.toHaveBeenCalledWith() const { payload: status } = await injectWithCookies('GET', TEST_STATUS.uri) const parsedStatus = JSON.parse(status) expect(parsedStatus[COMPLETION_STATUS.agreed]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.posted]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCreated]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCompleted]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.finalised]).not.toBeTruthy() }) it('posts a 500 (server) error if the GOV.UK Pay API returns an the rate limit response getting status', async () => { await ADULT_FULL_1_DAY_LICENCE.setup() salesApi.createTransaction = jest.fn(async () => new Promise(resolve => resolve(ADULT_FULL_1_DAY_LICENCE.transactionResponse))) govUkPayApi.createPayment = jest.fn( async () => new Promise(resolve => resolve({ json: () => MOCK_PAYMENT_RESPONSE, ok: true, status: 201 })) ) govUkPayApi.fetchPaymentStatus = jest.fn( async () => new Promise(resolve => resolve({ json: () => paymentTooManyRequests, ok: false, status: 429 })) ) const data1 = await injectWithCookies('GET', AGREED.uri) expect(data1.statusCode).toBe(302) expect(data1.headers.location).toBe(MOCK_PAYMENT_RESPONSE._links.next_url.href) salesApi.updatePaymentJournal = jest.fn() const data = await injectWithCookies('GET', AGREED.uri) expect(data.statusCode).toBe(500) expect(salesApi.updatePaymentJournal).not.toHaveBeenCalledWith() const { payload: status } = await injectWithCookies('GET', TEST_STATUS.uri) const parsedStatus = JSON.parse(status) expect(parsedStatus[COMPLETION_STATUS.agreed]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.posted]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCreated]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCompleted]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.finalised]).not.toBeTruthy() }) it('posts a 500 (server) error if the GOV.UK Pay API returns an arbituary error response', async () => { await ADULT_FULL_1_DAY_LICENCE.setup() salesApi.createTransaction = jest.fn(async () => new Promise(resolve => resolve(ADULT_FULL_1_DAY_LICENCE.transactionResponse))) govUkPayApi.createPayment = jest.fn( async () => new Promise(resolve => resolve({ json: () => MOCK_PAYMENT_RESPONSE, ok: true, status: 201 })) ) govUkPayApi.fetchPaymentStatus = jest.fn(async () => new Promise(resolve => resolve({ json: () => ({}), ok: false, status: 599 }))) const data1 = await injectWithCookies('GET', AGREED.uri) expect(data1.statusCode).toBe(302) expect(data1.headers.location).toBe(MOCK_PAYMENT_RESPONSE._links.next_url.href) salesApi.updatePaymentJournal = jest.fn() const data = await injectWithCookies('GET', AGREED.uri) expect(data.statusCode).toBe(500) expect(salesApi.updatePaymentJournal).not.toHaveBeenCalledWith() const { payload: status } = await injectWithCookies('GET', TEST_STATUS.uri) const parsedStatus = JSON.parse(status) expect(parsedStatus[COMPLETION_STATUS.agreed]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.posted]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCreated]).toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.paymentCompleted]).not.toBeTruthy() expect(parsedStatus[COMPLETION_STATUS.finalised]).not.toBeTruthy() }) })