/** * @fileOverview End-to-end testing of the swagger API endpoint to pay to a saved worldpay merchant. */ 'use strict'; // eslint-disable-next-line no-unused-vars const testGlobals = require('../../tools/test/testGlobals.js'); const request = require('supertest'); const express = require('express'); const _ = require('lodash'); const initDevApi = require('../dev_server.js'); function respondsWithValue(thisApp, instrumentID, params, header, value) { return request(thisApp) .post('/dev/v0/payment-instruments/worldpay-merchants/' + instrumentID + '/payments') .set('Accept', 'application/json') .set('Authorization', header) .send(params) .expect(value); } /** * Test values */ // Correct auth method (Bearer), correct token const TOKEN_VALID = 'YTM2ZGQ1NzUtOWFmNS01MjMyLTg5MjYtM2NkZjA5ZDU2ZGU1'; const HEADER_VALID = 'Bearer ' + TOKEN_VALID; const INSTRUMENT_ID = '0123456789abcdefghijklmn'; // Standard errored values const TOO_LONG = '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' + '012345678901234567890123456789012345678901234567890123456789'; const BAD_DATE_FMT = '12?18'; const BAD_DATE_MON = '34-18'; const BAD_EMAIL = 'a@b@example.com'; const BAD_PANA = '123A 1234 1234 1234'; const BAD_PANB = '147100001111222 '; const BAD_CVV = '12C'; const BAD_POSTCODE = 'AB12 &CD'; const BAD_PHONENUM = '012345G 67890'; const BAD_ENCRYPTION_KEY = '00112233-0000-1111-54321-990000123456 00112233-0000-1111-54321-990000123456'; const BAD_AMOUNT = 'ABC'; const BAD_INSTRUMENT_ID = '0123456789'; // Valid test data const correctParameters = { paymentInstrument: { payer: { email: 'john.doe@example.com', firstName: 'John', lastName: 'Doe' }, card: { nameOnCard: 'John E Doe', PAN: '4444 3333 2222 1111', expiryDate: '11-22', startDate: '11-20', issueNumber: 1, CV2: '012', address: { address1: 'First line of address', address2: 'Second line of address', address3: 'Third line of addresst', town: 'Christchurch', county: 'Dorset', postcode: 'BH23 6AA', phoneNumber: '+44 123 1110000' } } }, receiveInstrument: { encryptionKey: '00112233-0000-1111-54321-990000123456' }, amount: { value: 100 }, transactionDetails: { worldpay: { orderDescription: '2 Calling Birds, 1 Partridge in a Pear tree' } } }; let badParameters; describe('E2E: dev api Worldpay payment for saved merchant request', () => { let app; /** * Load the dev API router to handle `/dev/*` routes */ before(() => { app = express(); const devApiRouter = initDevApi.init(); app.use('/dev', devApiRouter); }); describe('tests with missing required parameters', () => { /* * Tests where required top level attributes are missing. * ====================================================== * * No paymentInstrument object */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument; it('with no paymentInstrument parameters', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No payee receiveInstrument */ badParameters = _.cloneDeep(correctParameters); delete badParameters.receiveInstrument; it('with no receiveInstrument parameters', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No amount */ badParameters = _.cloneDeep(correctParameters); delete badParameters.amount; it('with no amount parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No transactionDetails */ badParameters = _.cloneDeep(correctParameters); delete badParameters.transactionDetails; it('with no transactionDetails parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Missing child elements */ /* * No paymentInstrument.payer object */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.payer; it('with no paymentInstrument.payer parameters', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No paymentInstrument.payer.email */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.payer.email; it('with no paymentInstrument.payer.email parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No paymentInstrument.payer.firstName */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.payer.firstName; it('with no paymentInstrument.payer.firstName parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No paymentInstrument.payer.lastName */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.payer.lastName; it('with no paymentInstrument.payer.lastName parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No paymentInstrument.card object */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.card; it('with no paymentInstrument.card parameters', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No paymentInstrument.card.nameOnCard */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.card.nameOnCard; it('with no paymentInstrument.card.nameOnCard parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No paymentInstrument.card.PAN */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.card.PAN; it('with no paymentInstrument.card.PAN parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No paymentInstrument.card.expiryDate */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.card.expiryDate; it('with no paymentInstrument.card.expiryDate parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No paymentInstrument.card.CV2 */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.card.CV2; it('with no paymentInstrument.card.CV2 parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No paymentInstrument.card.address */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.card.address; it('with no paymentInstrument.card.address parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No paymentInstrument.card.address.address1 */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.card.address.address1; it('with no paymentInstrument.card.address.address1 parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No paymentInstrument.card.address.town */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.card.address.town; it('with no paymentInstrument.card.address.town parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No paymentInstrument.card.address.postcode */ badParameters = _.cloneDeep(correctParameters); delete badParameters.paymentInstrument.card.address.postcode; it('with no paymentInstrument.card.address.postcode parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No transactionDetails.worldpay object */ badParameters = _.cloneDeep(correctParameters); delete badParameters.transactionDetails.worldpay; it('with no transactionDetails.worldpay parameters', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * No receiving account encryption key */ badParameters = _.cloneDeep(correctParameters); delete badParameters.receiveInstrument.encryptionKey; it('with no receiving account encryption key', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); }); describe('bad data format tests', () => { /* * Invalid data format errors * ========================== * * Bad paymentInstrument.payer.email */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.payer.email = BAD_EMAIL; it('with an invalid paymentInstrument email parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.payer.firstName */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.payer.firstName = 'Axel Rose'; it('with an invalid payer first name parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.payer.lastName */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.payer.lastName = 'Axel Rose'; it('with an invalid payer last name parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.PAN */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.PAN = BAD_PANA; it('with a bad card PAN parameter containing a letter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.PAN = BAD_PANB; it('with a bad card PAN parameter with a trailing space', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.expiryDate 1 */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.expiryDate = BAD_DATE_FMT; it('with a bad character in the payment card expiry date parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.expiryDate 2 */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.expiryDate = BAD_DATE_MON; it('with a bad month number in the payment card expiry date parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.startDate */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.startDate = BAD_DATE_FMT; it('with a badly formatted payment card start date parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.startDate */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.startDate = BAD_DATE_MON; it('with a bad month number in the payment card start date parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.issueNumber */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.issueNumber = 'Z'; it('with a badly formatted payment card issue number parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.CV2 */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.CV2 = BAD_CVV; it('with a badly formatted payment card CV2 parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.address.address1: too long */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.address.address1 = TOO_LONG; it('with a card address line 1 too long', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.address.address1: too short */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.address.address1 = ''; it('with a card address line 1 too short', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.address.address2 */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.address.address2 = TOO_LONG; it('with a badly formatted card address line 2 parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.address.address3 */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.address.address3 = TOO_LONG; it('with a badly formatted card address line 3 parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.address.town */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.address.town = TOO_LONG; it('with a badly formatted card address town name parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad paymentInstrument.card.address.county */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.address.county = TOO_LONG; it('with a badly formatted card address county name parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad card.address.postcode */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.address.postcode = BAD_POSTCODE; it('with a badly formatted card address postcode parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad card.address.phoneNumber */ badParameters = _.cloneDeep(correctParameters); badParameters.paymentInstrument.card.address.phoneNumber = BAD_PHONENUM; it('with a badly formatted card address phone number parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad orderDescription */ badParameters = _.cloneDeep(correctParameters); badParameters.transactionDetails.worldpay.orderDescription = TOO_LONG; it('with a badly formatted order description parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * ) Bad receiving account decryption key */ badParameters = _.cloneDeep(correctParameters); badParameters.receiveInstrument.encryptionKey = BAD_ENCRYPTION_KEY; it('with a badly formatted receiving account encryption key parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * ) Bad amount.value */ badParameters = _.cloneDeep(correctParameters); badParameters.amount.value = BAD_AMOUNT; it('with a badly formatted amount value parameter', () => { return respondsWithValue(app, INSTRUMENT_ID, badParameters, HEADER_VALID, 400); }); /* * Bad instrument ID. */ it('with a badly formatted instrument ID', () => { return respondsWithValue(app, BAD_INSTRUMENT_ID, correctParameters, HEADER_VALID, 400); }); }); /* Skip these tests for two reasons: the return will change and they fail. */ describe.skip('Good parameter data tests', () => { /* * Verify that the command works with the minimum set of correctly formatted parameters. */ const minimumValidSet = _.cloneDeep(correctParameters); delete minimumValidSet.paymentInstrument.card.startDate; delete minimumValidSet.paymentInstrument.card.issueNumber; delete minimumValidSet.paymentInstrument.card.address.address2; delete minimumValidSet.paymentInstrument.card.address.address3; delete minimumValidSet.paymentInstrument.card.address.county; delete minimumValidSet.paymentInstrument.card.address.phoneNumber; it('with the minimum set of correct parameters', () => { return respondsWithValue(app, INSTRUMENT_ID, minimumValidSet, HEADER_VALID, 400); }); /* * Verify that the command works with correctly formatted full set of parameters. */ it('with a full set of correct parameters', () => { return respondsWithValue(app, INSTRUMENT_ID, correctParameters, HEADER_VALID, 400); }); }); });