@defra-fish/gafl-webapp-service
Version:
The websales frontend for the GAFL service
267 lines (221 loc) • 10.6 kB
JavaScript
import { preparePayment, prepareRecurringPaymentAgreement } from '../payment.js'
import { licenceTypeAndLengthDisplay } from '../licence-type-display.js'
import { addLanguageCodeToUri } from '../uri-helper.js'
import { AGREED } from '../../uri.js'
import db from 'debug'
const { value: debug } = db.mock.results[db.mock.calls.findIndex(c => c[0] === 'webapp:payment-processors')]
jest.mock('../uri-helper.js')
jest.mock('../licence-type-display.js')
licenceTypeAndLengthDisplay.mockReturnValue('Trout and coarse, up to 2 rods, 8 day')
jest.mock('debug', () => jest.fn(() => jest.fn()))
const createRequest = (opts = {}, catalog = {}) => ({
i18n: {
getCatalog: () => catalog
},
headers: opts.headers || { 'x-forwarded-proto': 'https' },
info: { host: opts.host || 'localhost:1234' },
server: { info: { protocol: opts.protocol || '' } }
})
const createTransaction = ({
isLicenceForYou = true,
additionalPermissions = [],
cost = 12,
licenseeOverrides = {},
agreementId
} = {}) => ({
id: 'transaction-id',
cost,
agreementId,
permissions: [
{
id: 'permission-id',
licensee: {
firstName: 'Lando',
lastName: 'Norris',
email: 'test@example.com',
premises: '4',
street: 'Buttercup lane',
locality: 'Clifton',
postcode: 'BS8 3TP',
town: 'Bristol',
country: 'GB-ENG',
...licenseeOverrides
},
isLicenceForYou
},
...additionalPermissions
]
})
describe('preparePayment', () => {
describe('provides the correct return url', () => {
it.each(['http', 'https'])('uses SSL when "x-forwarded-proto" header is present, proto "%s"', proto => {
addLanguageCodeToUri.mockReturnValue(proto + '://localhost:1234/buy/agreed')
const request = createRequest({ headers: { 'x-forwarded-proto': proto } })
const result = preparePayment(request, createTransaction(), false)
expect(result.return_url).toBe(`${proto}://localhost:1234/buy/agreed`)
})
it.each([
['http', 'localhost:4321'],
['https', 'otherhost:8888'],
['http', 'samplehost:4444']
])('uses request data when "x-forwarded-proto" header is not present, protocol "%s", host "%s"', (protocol, host) => {
addLanguageCodeToUri.mockReturnValue(protocol + '://' + host + '/buy/agreed')
const request = createRequest({ headers: {}, protocol, host })
const result = preparePayment(request, createTransaction())
expect(result.return_url).toBe(`${protocol}://${host}/buy/agreed`)
})
it('calls addLanguageCodeToUri with correct arguments', () => {
const request = createRequest()
preparePayment(request, createTransaction())
expect(addLanguageCodeToUri).toHaveBeenCalledWith(request, AGREED.uri)
})
})
it.each`
transaction | expectedAmount
${createTransaction()} | ${1200}
${createTransaction({ cost: 35.8 })} | ${3580}
`('provides the correct transaction amount of $expectedAmount when cost is $transaction.cost', ({ transaction, expectedAmount }) => {
const result = preparePayment(createRequest(), transaction)
expect(result.amount).toBe(expectedAmount)
})
it('provides the correct reference', () => {
const transaction = createTransaction()
const result = preparePayment(createRequest(), transaction)
expect(result.reference).toBe(transaction.id)
})
it('licenceTypeAndLengthDisplay is called with the expected arguments', () => {
const catalog = Symbol('mock catalog')
const request = createRequest({}, catalog)
const transaction = createTransaction()
const permission = transaction.permissions[0]
preparePayment(request, transaction)
expect(licenceTypeAndLengthDisplay).toHaveBeenCalledWith(permission, catalog)
})
it('return value of licenceTypeDisplay', () => {
const returnValue = Symbol('return value')
licenceTypeAndLengthDisplay.mockReturnValueOnce(returnValue)
const result = preparePayment(createRequest(), createTransaction())
const ret = result.description
expect(ret).toEqual(returnValue)
})
it.each([
['when the language is set to Welsh', 'https://localhost:1234/buy/agreed?lang=cy', 'cy'],
['when the language is set to English', 'https://localhost:1234/buy/agreed?lang=en', 'en'],
['when the language is not set', 'https://localhost:1234/buy/agreed', 'en']
])('provides the correct language %s', (_desc, decoratedUrl, expectedLanguageCode) => {
addLanguageCodeToUri.mockReturnValue(decoratedUrl)
const result = preparePayment(createRequest(), createTransaction())
expect(result.language).toEqual(expectedLanguageCode)
})
describe('provides the correct description', () => {
it('when there is only 1 permission', () => {
const result = preparePayment(createRequest(), createTransaction())
expect(result.description).toBe('Trout and coarse, up to 2 rods, 8 day')
})
it('when there are multiple permissions', () => {
const additionalPermissions = [{ licensee: { firstName: 'Test' } }]
const transaction = createTransaction({ additionalPermissions })
const result = preparePayment(createRequest(), transaction)
expect(result.description).toBe('Multiple permits')
})
})
describe('if there is only 1 permission and the user is buying for themselves, provides licensee info', () => {
it('provides the licensee name as cardholder name', () => {
const transaction = createTransaction()
const licensee = transaction.permissions[0].licensee
const result = preparePayment(createRequest(), transaction)
expect(result.prefilled_cardholder_details.cardholder_name).toBe(`${licensee.firstName} ${licensee.lastName}`)
})
describe('provides the licensee address correctly', () => {
it('line1 includes street name if provided', () => {
const transaction = createTransaction()
const licensee = transaction.permissions[0].licensee
const result = preparePayment(createRequest(), transaction)
expect(result.prefilled_cardholder_details.billing_address.line1).toBe(`${licensee.premises} ${licensee.street}`)
})
it('line1 does not include street name if not provided', () => {
const transaction = createTransaction({ licenseeOverrides: { street: null } })
const licensee = transaction.permissions[0].licensee
const result = preparePayment(createRequest(), transaction)
expect(result.prefilled_cardholder_details.billing_address.line1).toBe(licensee.premises)
})
it('postcode is provided', () => {
const transaction = createTransaction()
const licensee = transaction.permissions[0].licensee
const result = preparePayment(createRequest(), transaction)
expect(result.prefilled_cardholder_details.billing_address.postcode).toBe(licensee.postcode)
})
it('city is provided', () => {
const transaction = createTransaction()
const licensee = transaction.permissions[0].licensee
const result = preparePayment(createRequest(), transaction)
expect(result.prefilled_cardholder_details.billing_address.city).toBe(licensee.town)
})
it('country is provided', () => {
const transaction = createTransaction()
const licensee = transaction.permissions[0].licensee
const result = preparePayment(createRequest(), transaction)
expect(result.prefilled_cardholder_details.billing_address.country).toBe(licensee.countryCode)
})
it('line2 is provided if locality is present', () => {
const transaction = createTransaction()
const licensee = transaction.permissions[0].licensee
const result = preparePayment(createRequest(), transaction)
expect(result.prefilled_cardholder_details.billing_address.line2).toBe(licensee.locality)
})
it('line2 is undefined if locality is not present', () => {
const transaction = createTransaction({ licenseeOverrides: { locality: null } })
const result = preparePayment(createRequest(), transaction)
expect(result.prefilled_cardholder_details.billing_address.line2).toBe(undefined)
})
})
})
describe('if there is only 1 permission and the user is buying on behalf of another, does not provide licensee info', () => {
it('does not provide the prefilled_cardholder_details', () => {
const boboTransaction = createTransaction({ isLicenceForYou: false })
const result = preparePayment(createRequest(), boboTransaction)
expect(result.prefilled_cardholder_details).toBe(undefined)
})
it('does not provide the email', () => {
const boboTransaction = createTransaction({ isLicenceForYou: false })
const result = preparePayment(createRequest(), boboTransaction)
expect(result.email).toBe(undefined)
})
})
describe('if agreementId is not present', () => {
it('does not include set_up_agreement', () => {
const result = preparePayment(createRequest(), createTransaction())
expect(result.set_up_agreement).toBe(undefined)
})
})
describe('if agreementId is present', () => {
it('set_up_agreement is set to agreementId', () => {
const agreementId = 'foo'
const recurringPaymentTransaction = createTransaction({ agreementId })
const result = preparePayment(createRequest(), recurringPaymentTransaction)
expect(result.set_up_agreement).toBe(agreementId)
})
})
})
describe('prepareRecurringPaymentAgreement', () => {
it('reference equals transaction.id', async () => {
const transaction = createTransaction()
const result = await prepareRecurringPaymentAgreement(createRequest(), transaction)
expect(result.reference).toBe(transaction.id)
})
it('description equals the recurring payment description from catalog', async () => {
const mockCatalog = {
recurring_payment_description: 'The recurring card payment for your rod fishing licence'
}
const request = createRequest({}, mockCatalog)
const transaction = createTransaction()
const result = await prepareRecurringPaymentAgreement(request, transaction)
expect(result.description).toBe(mockCatalog.recurring_payment_description)
})
it('logs to debug for recurring payment', async () => {
const transaction = createTransaction()
const request = createRequest()
const result = await prepareRecurringPaymentAgreement(request, transaction)
expect(debug).toHaveBeenCalledWith('Creating prepared recurring payment agreement %o', result)
})
})