-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PP-13312 Get controller, templates and unit tests
- Loading branch information
1 parent
e337a3b
commit 3b978eb
Showing
11 changed files
with
425 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 15 additions & 2 deletions
17
app/controllers/simplified-account/settings/card-types/card-types.controller.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
app/controllers/simplified-account/settings/card-types/card-types.controller.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
const sinon = require('sinon') | ||
const { expect } = require('chai') | ||
const User = require('@models/User.class') | ||
const userFixtures = require('@test/fixtures/user.fixtures') | ||
const proxyquire = require('proxyquire') | ||
|
||
const ACCOUNT_TYPE = 'live' | ||
const SERVICE_ID = 'service-id-123abc' | ||
|
||
const adminUser = new User(userFixtures.validUserResponse({ | ||
external_id: 'user-id-for-admin-user', | ||
service_roles: { | ||
service: { | ||
service: { external_id: SERVICE_ID }, | ||
role: { name: 'admin' } | ||
} | ||
} | ||
})) | ||
const viewOnlyUser = new User(userFixtures.validUserResponse( | ||
{ | ||
external_id: 'user-id-for-view-only-user', | ||
service_roles: { | ||
service: | ||
{ | ||
service: { external_id: SERVICE_ID }, | ||
role: { name: 'view-only' } | ||
} | ||
} | ||
})) | ||
|
||
const allCardTypes = [{ | ||
id: 'id-001', | ||
brand: 'visa', | ||
label: 'Visa', | ||
type: 'DEBIT', | ||
requires3ds: false | ||
}, | ||
{ | ||
id: 'id-002', | ||
brand: 'visa', | ||
label: 'Visa', | ||
type: 'CREDIT', | ||
requires3ds: false | ||
}] | ||
|
||
let req, res, responseStub, getAllCardTypesStub, getAcceptedCardTypesForServiceAndAccountTypeStub, cardTypesController | ||
|
||
const getController = (stubs = {}) => { | ||
return proxyquire('./card-types.controller', { | ||
'@utils/response': { response: stubs.response }, | ||
'@services/card-types.service': { | ||
getAllCardTypes: stubs.getAllCardTypes, | ||
getAcceptedCardTypesForServiceAndAccountType: stubs.getAcceptedCardTypesForServiceAndAccountType | ||
} | ||
}) | ||
} | ||
|
||
const setupTest = (method, user, additionalReqProps = {}, additionalStubs = {}) => { | ||
responseStub = sinon.spy() | ||
getAllCardTypesStub = sinon.stub().returns({ card_types: allCardTypes }) | ||
getAcceptedCardTypesForServiceAndAccountTypeStub = sinon.stub().resolves({ card_types: [allCardTypes[0]] }) | ||
|
||
cardTypesController = getController({ | ||
response: responseStub, | ||
getAllCardTypes: getAllCardTypesStub, | ||
getAcceptedCardTypesForServiceAndAccountType: getAcceptedCardTypesForServiceAndAccountTypeStub, | ||
...additionalStubs | ||
}) | ||
res = { | ||
redirect: sinon.spy() | ||
} | ||
req = { | ||
user: user, | ||
service: { | ||
externalId: SERVICE_ID | ||
}, | ||
account: { | ||
type: ACCOUNT_TYPE | ||
}, | ||
...additionalReqProps | ||
} | ||
cardTypesController[method](req, res) | ||
} | ||
|
||
describe('Controller: settings/card-types', () => { | ||
describe('get for admin user', () => { | ||
before(() => setupTest('get', adminUser)) | ||
|
||
it('should call the response method', () => { | ||
expect(responseStub.called).to.be.true // eslint-disable-line | ||
}) | ||
|
||
it('should pass req, res and template path to the response method', () => { | ||
expect(responseStub.args[0][0]).to.deep.equal(req) | ||
expect(responseStub.args[0][1]).to.deep.equal(res) | ||
expect(responseStub.args[0][2]).to.equal('simplified-account/settings/card-types/index') | ||
}) | ||
|
||
it('should pass context data to the response method', () => { | ||
expect(responseStub.args[0][3]).to.have.property('cardTypes').to.have.property('debitCards').length(1) | ||
expect(responseStub.args[0][3].cardTypes.debitCards[0]).to.have.property('text').to.equal('Visa debit') | ||
expect(responseStub.args[0][3].cardTypes.debitCards[0]).to.have.property('checked').to.equal(true) | ||
expect(responseStub.args[0][3]).to.have.property('cardTypes').to.have.property('creditCards').length(1) | ||
expect(responseStub.args[0][3].cardTypes.creditCards[0]).to.have.property('text').to.equal('Visa credit') | ||
expect(responseStub.args[0][3].cardTypes.creditCards[0]).to.have.property('checked').to.equal(false) | ||
expect(responseStub.args[0][3]).to.have.property('isAdminUser').to.equal(true) | ||
}) | ||
}) | ||
|
||
describe('get for non-admin user', () => { | ||
before(() => setupTest('get', viewOnlyUser)) | ||
|
||
it('should call the response method', () => { | ||
expect(responseStub.called).to.be.true // eslint-disable-line | ||
}) | ||
|
||
it('should pass req, res and template path to the response method', () => { | ||
expect(responseStub.args[0][0]).to.deep.equal(req) | ||
expect(responseStub.args[0][1]).to.deep.equal(res) | ||
expect(responseStub.args[0][2]).to.equal('simplified-account/settings/card-types/index') | ||
}) | ||
|
||
it('should pass context data to the response method', () => { | ||
expect(responseStub.args[0][3]).to.have.property('cardTypes').to.have.property('Enabled debit cards').to.have.length(1) | ||
expect(responseStub.args[0][3].cardTypes).to.have.property('Not enabled debit cards').to.have.length(0) | ||
expect(responseStub.args[0][3].cardTypes).to.have.property('Enabled credit cards').to.have.length(0) | ||
expect(responseStub.args[0][3].cardTypes).to.have.property('Not enabled credit cards').to.have.length(1) | ||
expect(responseStub.args[0][3]).to.have.property('isAdminUser').to.equal(false) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
'use strict' | ||
|
||
const ConnectorClient = require('./clients/connector.client.js').ConnectorClient | ||
const connectorClient = new ConnectorClient(process.env.CONNECTOR_URL) | ||
|
||
async function getAllCardTypes () { | ||
return connectorClient.getAllCardTypes() | ||
} | ||
|
||
async function getAcceptedCardTypesForServiceAndAccountType (serviceId, accountType) { | ||
return connectorClient.getAcceptedCardsForServiceAndAccountType(serviceId, accountType) | ||
} | ||
|
||
module.exports = { | ||
getAllCardTypes, | ||
getAcceptedCardTypesForServiceAndAccountType | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
const formatLabel = (card) => { | ||
if (card.brand === 'visa' || card.brand === 'master-card') { | ||
return `${card.label} ${card.type.toLowerCase()}` | ||
} else { | ||
return card.brand === 'jcb' ? card.label.toUpperCase() : card.label | ||
} | ||
} | ||
|
||
const formatCardTypesForAdminTemplate = (allCards, acceptedCards, account) => { | ||
const cardDataChecklistItem = (card) => { | ||
return { | ||
value: card.id, | ||
text: formatLabel(card), | ||
checked: acceptedCards.filter(accepted => accepted.id === card.id).length !== 0, | ||
requires3ds: card.requires3ds | ||
} | ||
} | ||
const disableCheckboxIf3dsRequiredButNotEnabled = (cardTypeChecklistItem) => { | ||
if (cardTypeChecklistItem.requires3ds && !account.requires3ds) { | ||
cardTypeChecklistItem.disabled = true | ||
cardTypeChecklistItem.hint = { | ||
html: account.type === 'test' ? `${cardTypeChecklistItem.text} is not available on test accounts` : `${cardTypeChecklistItem.text} cannot be used because 3D Secure is not available. Please contact support` | ||
} | ||
} | ||
return cardTypeChecklistItem | ||
} | ||
const addHintForAmexAndUnionpay = (cardTypeChecklistItem) => { | ||
if (['American Express', 'Union Pay'].includes(cardTypeChecklistItem.text)) { | ||
if (account.paymentProvider === 'worldpay') { | ||
cardTypeChecklistItem.hint = { | ||
html: 'You must have already enabled this with Worldpay' | ||
} | ||
} | ||
} | ||
return cardTypeChecklistItem | ||
} | ||
const debitCardChecklistItems = allCards.filter(card => card.type === 'DEBIT') | ||
.map(card => cardDataChecklistItem(card)) | ||
.map(cardTypeChecklistItem => disableCheckboxIf3dsRequiredButNotEnabled(cardTypeChecklistItem)) | ||
|
||
const creditCardChecklistItems = allCards.filter(card => card.type === 'CREDIT') | ||
.map(card => cardDataChecklistItem(card)) | ||
.map(cardTypeChecklistItem => addHintForAmexAndUnionpay(cardTypeChecklistItem)) | ||
|
||
return { debitCards: debitCardChecklistItems, creditCards: creditCardChecklistItems } | ||
} | ||
|
||
const formatCardTypesForNonAdminTemplate = (allCards, acceptedCards) => { | ||
const acceptedCardTypeIds = acceptedCards.map(card => card.id) | ||
const formattedCardTypes = { | ||
'Enabled debit cards': [], | ||
'Not enabled debit cards': [], | ||
'Enabled credit cards': [], | ||
'Not enabled credit cards': [] | ||
} | ||
allCards.forEach(card => { | ||
const cardIsEnabled = acceptedCardTypeIds.includes(card.id) ? 'Enabled' : 'Not enabled' | ||
formattedCardTypes[`${cardIsEnabled} ${card.type.toLowerCase()} cards`].push(formatLabel(card)) | ||
}) | ||
return formattedCardTypes | ||
} | ||
|
||
const formatCardTypesForTemplate = (allCards, acceptedCards, account, isAdminUser) => { | ||
if (isAdminUser) { | ||
return formatCardTypesForAdminTemplate(allCards, acceptedCards, account) | ||
} | ||
return formatCardTypesForNonAdminTemplate(allCards, acceptedCards) | ||
} | ||
|
||
module.exports = { | ||
formatCardTypesForTemplate | ||
} |
78 changes: 78 additions & 0 deletions
78
app/utils/simplified-account/format/format-card-types.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
const { expect } = require('chai') | ||
const { formatCardTypesForTemplate } = require('@utils/simplified-account/format/format-card-types') | ||
|
||
const allCards = [ | ||
{ | ||
id: 'id-001', | ||
brand: 'visa', | ||
label: 'Visa', | ||
type: 'DEBIT', | ||
requires3ds: false | ||
}, | ||
{ | ||
id: 'id-002', | ||
brand: 'visa', | ||
label: 'Visa', | ||
type: 'CREDIT', | ||
requires3ds: false | ||
}, | ||
{ | ||
id: 'id-003', | ||
brand: 'master-card', | ||
label: 'Mastercard', | ||
type: 'DEBIT', | ||
requires3ds: false | ||
}, | ||
{ | ||
id: 'id-004', | ||
brand: 'american-express', | ||
label: 'American Express', | ||
type: 'CREDIT', | ||
requires3ds: false | ||
}, | ||
{ | ||
id: 'id-005', | ||
brand: 'jcb', | ||
label: 'Jcb', | ||
type: 'CREDIT', | ||
requires3ds: false | ||
}, | ||
{ | ||
id: 'id-006', | ||
brand: 'maestro', | ||
label: 'Maestro', | ||
type: 'DEBIT', | ||
requires3ds: true | ||
} | ||
] | ||
describe('format-card-types for template', () => { | ||
describe('present checkboxes for admin user', () => { | ||
it('should return all card types if they are all enabled', () => { | ||
const acceptedCards = [...allCards] | ||
const account = { requires3ds: true } | ||
const cards = formatCardTypesForTemplate(allCards, acceptedCards, account, true) | ||
expect(cards.debitCards).to.have.length(3) | ||
expect(cards.creditCards).to.have.length(3) | ||
}) | ||
|
||
it('should set checkbox to disabled for requires3ds card types if 3ds not enabled on account', () => { | ||
const acceptedCards = [...allCards] | ||
const account = { requires3ds: false } | ||
const cards = formatCardTypesForTemplate(allCards, acceptedCards, account, true) | ||
expect(cards.debitCards.filter(card => card.disabled === true)).to.have.length(1) | ||
expect(cards.debitCards.filter(card => card.disabled === true)[0]).to.have.property('text').to.equal('Maestro') | ||
}) | ||
}) | ||
|
||
describe('present read-only list for non-admin user', () => { | ||
it('should return all card types arranged by type and whether accepted or not', () => { | ||
const acceptedCards = [...allCards].filter(card => card.id !== 'id-001' && card.id !== 'id-002') | ||
const account = { requires3ds: true } | ||
const cards = formatCardTypesForTemplate(allCards, acceptedCards, account, false) | ||
expect(cards['Enabled debit cards']).to.have.length(2).to.deep.equal(['Mastercard debit', 'Maestro']) | ||
expect(cards['Not enabled debit cards']).to.have.length(1).to.deep.equal(['Visa debit']) | ||
expect(cards['Enabled credit cards']).to.have.length(2).to.deep.equal(['American Express', 'JCB']) | ||
expect(cards['Not enabled credit cards']).to.have.length(1).to.deep.equal(['Visa credit']) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.