From 3e9f92b8a51c8f65d5367fbc705b71bf5da629d8 Mon Sep 17 00:00:00 2001 From: imcaizheng Date: Wed, 21 Apr 2021 19:04:48 +0800 Subject: [PATCH 1/2] Add ability to switch on/off actual payments via config --- app-constants.js | 8 +++- config/default.js | 3 +- package.json | 2 +- src/bootstrap.js | 13 +++++ .../WorkPeriodPaymentController.js | 3 +- src/services/WorkPeriodPaymentService.js | 13 +++-- test/unit/WorkPeriodPaymentService.test.js | 47 +++++++++++++++++++ test/unit/common/testData.js | 35 +++++++++++++- 8 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 test/unit/WorkPeriodPaymentService.test.js diff --git a/app-constants.js b/app-constants.js index 770ec967..7ee4c5f5 100644 --- a/app-constants.js +++ b/app-constants.js @@ -53,9 +53,15 @@ const ChallengeStatus = { COMPLETED: 'Completed' } +const PaymentProcessingSwitch = { + ON: 'ON', + OFF: 'OFF' +} + module.exports = { UserRoles, FullManagePermissionRoles, Scopes, - ChallengeStatus + ChallengeStatus, + PaymentProcessingSwitch } diff --git a/config/default.js b/config/default.js index c2ba03fe..32f53d41 100644 --- a/config/default.js +++ b/config/default.js @@ -148,5 +148,6 @@ module.exports = { DEFAULT_TRACK_ID: process.env.DEFAULT_TRACK_ID || '9b6fc876-f4d9-4ccb-9dfd-419247628825', // default time zone for Work Periods - WORK_PERIOD_TIME_ZONE: process.env.WORK_PERIOD_TIME_ZONE || 'America/New_York' + WORK_PERIOD_TIME_ZONE: process.env.WORK_PERIOD_TIME_ZONE || 'America/New_York', + PAYMENT_PROCESSING_SWITCH: process.env.PAYMENT_PROCESSING_SWITCH || 'OFF' } diff --git a/package.json b/package.json index 3625c1bf..1e89012d 100644 --- a/package.json +++ b/package.json @@ -87,4 +87,4 @@ "test/unit/**" ] } -} \ No newline at end of file +} diff --git a/src/bootstrap.js b/src/bootstrap.js index 337ace6b..bc5b0b47 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -2,6 +2,8 @@ const fs = require('fs') const Joi = require('joi') const path = require('path') const logger = require('./common/logger') +const constants = require('../app-constants') +const config = require('config') Joi.page = () => Joi.number().integer().min(1).default(1) Joi.perPage = () => Joi.number().integer().min(1).default(20) @@ -36,3 +38,14 @@ function buildServices (dir) { } buildServices(path.join(__dirname, 'services')) + +// validate some configurable parameters for the app +const paymentProcessingSwitchSchema = Joi.string().label('PAYMENT_PROCESSING_SWITCH').valid( + ...Object.values(constants.PaymentProcessingSwitch) +) +try { + Joi.attempt(config.PAYMENT_PROCESSING_SWITCH, paymentProcessingSwitchSchema) +} catch (err) { + console.error(err.message) + process.exit(1) +} diff --git a/src/controllers/WorkPeriodPaymentController.js b/src/controllers/WorkPeriodPaymentController.js index e20075fd..93f5c046 100644 --- a/src/controllers/WorkPeriodPaymentController.js +++ b/src/controllers/WorkPeriodPaymentController.js @@ -3,6 +3,7 @@ */ const service = require('../services/WorkPeriodPaymentService') const helper = require('../common/helper') +const config = require('config') /** * Get workPeriodPayment by id @@ -19,7 +20,7 @@ async function getWorkPeriodPayment (req, res) { * @param res the response */ async function createWorkPeriodPayment (req, res) { - res.send(await service.createWorkPeriodPayment(req.authUser, req.body)) + res.send(await service.createWorkPeriodPayment(req.authUser, req.body, { paymentProcessingSwitch: config.PAYMENT_PROCESSING_SWITCH })) } /** diff --git a/src/services/WorkPeriodPaymentService.js b/src/services/WorkPeriodPaymentService.js index 7336767a..7ecff048 100644 --- a/src/services/WorkPeriodPaymentService.js +++ b/src/services/WorkPeriodPaymentService.js @@ -12,8 +12,9 @@ const moment = require('moment') const helper = require('../common/helper') const logger = require('../common/logger') const errors = require('../common/errors') +const constants = require('../../app-constants') const models = require('../models') -const { createPayment } = require('./PaymentService') +const PaymentService = require('./PaymentService') const WorkPeriodPayment = models.WorkPeriodPayment const esClient = helper.getESClient() @@ -89,20 +90,21 @@ getWorkPeriodPayment.schema = Joi.object().keys({ * Create workPeriodPayment * @param {Object} currentUser the user who perform this operation * @param {Object} workPeriodPayment the workPeriodPayment to be created + * @param {Object} options the extra options to control the function * @returns {Object} the created workPeriodPayment */ -async function createWorkPeriodPayment (currentUser, workPeriodPayment) { +async function createWorkPeriodPayment (currentUser, workPeriodPayment, options = { paymentProcessingSwitch: 'OFF' }) { // check permission await _checkUserPermissionForCRUWorkPeriodPayment(currentUser) const { projectId, userHandle, endDate } = await helper.ensureWorkPeriodById(workPeriodPayment.workPeriodId) // ensure work period exists - const paymentChallenge = await createPayment({ + const paymentChallenge = options.paymentProcessingSwitch === constants.PaymentProcessingSwitch.ON ? (await PaymentService.createPayment({ projectId, userHandle, amount: workPeriodPayment.amount, name: `TaaS Payment - ${userHandle} - Week Ending ${moment(endDate).format('D/M/YYYY')}`, description: `TaaS Payment - ${userHandle} - Week Ending ${moment(endDate).format('D/M/YYYY')}` - }) + })) : ({ id: '00000000-0000-0000-0000-000000000000' }) workPeriodPayment.id = uuid.v4() workPeriodPayment.challengeId = paymentChallenge.id workPeriodPayment.createdBy = await helper.getUserId(currentUser.userId) @@ -128,7 +130,8 @@ createWorkPeriodPayment.schema = Joi.object().keys({ workPeriodId: Joi.string().uuid().required(), amount: Joi.number().greater(0).allow(null), status: Joi.workPeriodPaymentStatus().default('completed') - }).required() + }).required(), + options: Joi.object() }).required() /** diff --git a/test/unit/WorkPeriodPaymentService.test.js b/test/unit/WorkPeriodPaymentService.test.js new file mode 100644 index 00000000..79880026 --- /dev/null +++ b/test/unit/WorkPeriodPaymentService.test.js @@ -0,0 +1,47 @@ +/* eslint-disable no-unused-expressions */ +process.env.NODE_ENV = 'test' +require('../../src/bootstrap') + +// const _ = require('lodash') +const expect = require('chai').expect +const sinon = require('sinon') +const models = require('../../src/models') +const service = require('../../src/services/WorkPeriodPaymentService') +const paymentService = require('../../src/services/PaymentService') +const testData = require('./common/testData') +const helper = require('../../src/common/helper') +const eventHandlers = require('../../src/eventHandlers') +// const esClient = helper.getESClient() +const busApiClient = helper.getBusApiClient() +eventHandlers.init() +describe('workPeriod service test', () => { + beforeEach(() => { + sinon.stub(busApiClient, 'postEvent').callsFake(async () => {}) + }) + + afterEach(() => { + sinon.restore() + }) + + describe('create work period test', () => { + describe('when PAYMENT_PROCESSING_SWITCH is ON/OFF', async () => { + let stubCreatePaymentService + + beforeEach(async () => { + sinon.stub(helper, 'ensureWorkPeriodById').callsFake(async () => testData.workPeriodPayment01.ensureWorkPeriodByIdResponse) + sinon.stub(helper, 'getUserId').callsFake(async () => {}) + sinon.stub(models.WorkPeriodPayment, 'create').callsFake(() => testData.workPeriodPayment01.response) + stubCreatePaymentService = sinon.stub(paymentService, 'createPayment').callsFake(async () => testData.workPeriodPayment01.createPaymentResponse) + }) + + it('do not create payment if PAYMENT_PROCESSING_SWITCH is OFF', async () => { + await service.createWorkPeriodPayment(testData.currentUser, testData.workPeriodPayment01.request, { paymentProcessingSwitch: 'OFF' }) + expect(stubCreatePaymentService.calledOnce).to.be.false + }) + it('create payment if PAYMENT_PROCESSING_SWITCH is ON', async () => { + await service.createWorkPeriodPayment(testData.currentUser, testData.workPeriodPayment01.request, { paymentProcessingSwitch: 'ON' }) + expect(stubCreatePaymentService.calledOnce).to.be.true + }) + }) + }) +}) diff --git a/test/unit/common/testData.js b/test/unit/common/testData.js index 8c145247..49192716 100644 --- a/test/unit/common/testData.js +++ b/test/unit/common/testData.js @@ -496,10 +496,43 @@ resourceBookingUpdate.updateResponse4.toJSON = function () { resourceBookingUpdate.response4.update = function () { return resourceBookingUpdate.updateResponse4 } + +const workPeriodPayment01 = { + request: { + workPeriodId: '467b4df7-ced4-41b9-9710-b83808cddaf4', + amount: 600, + status: 'completed' + }, + response: { + workPeriodId: '467b4df7-ced4-41b9-9710-b83808cddaf4', + amount: 600, + status: 'completed', + id: '01971e6f-0f09-4a2a-bc2e-2adac0f00622', + challengeId: '00000000-0000-0000-0000-000000000000', + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + updatedAt: '2021-04-21T12:58:07.535Z', + createdAt: '2021-04-21T12:58:07.535Z', + updatedBy: null + }, + ensureWorkPeriodByIdResponse: { + projectId: 111, + userHandle: 'pshah_manager', + endDate: '2021-03-13' + }, + createPaymentResponse: { + id: 'c65f0cbf-b197-423d-91cc-db6e3bad9075' + } +} + +workPeriodPayment01.response.toJSON = function () { + return workPeriodPayment01.response +} + module.exports = { currentUser, UserTCConnCopilot, resourceBooking5Week, resourceBooking1Week, - resourceBookingUpdate + resourceBookingUpdate, + workPeriodPayment01 } From 700b68e3566464711f1df49b693691e23c0a1417 Mon Sep 17 00:00:00 2001 From: imcaizheng Date: Wed, 21 Apr 2021 23:53:42 +0800 Subject: [PATCH 2/2] fix: initialize eventHandlers only once during test --- package.json | 4 ++-- test/prepare.js | 7 +++++++ test/unit/ResourceBookingService.test.js | 4 ---- test/unit/WorkPeriodPaymentService.test.js | 4 ---- 4 files changed, 9 insertions(+), 10 deletions(-) create mode 100644 test/prepare.js diff --git a/package.json b/package.json index 1e89012d..0168b120 100644 --- a/package.json +++ b/package.json @@ -20,13 +20,13 @@ "data:import": "node scripts/data/importData.js", "migrate": "npx sequelize db:migrate", "migrate:undo": "npx sequelize db:migrate:undo", - "test": "mocha test/unit/*.test.js --timeout 30000 --exit", + "test": "mocha test/unit/*.test.js --timeout 30000 --require test/prepare.js --exit", "services:up": "docker-compose -f ./local/docker-compose.yml up -d", "services:down": "docker-compose -f ./local/docker-compose.yml down", "services:logs": "docker-compose -f ./local/docker-compose.yml logs", "local:init": "npm run local:reset && npm run data:import -- --force", "local:reset": "npm run delete-index -- --force || true && npm run create-index -- --force && npm run init-db force", - "cov": "nyc --reporter=html --reporter=text mocha test/unit/*.test.js --timeout 30000 --exit", + "cov": "nyc --reporter=html --reporter=text npm run test", "demo-payment": "node scripts/demo-payment" }, "keywords": [], diff --git a/test/prepare.js b/test/prepare.js new file mode 100644 index 00000000..42277c70 --- /dev/null +++ b/test/prepare.js @@ -0,0 +1,7 @@ +/* + * Prepare for tests. + */ + +process.env.NODE_ENV = 'test' +require('../src/bootstrap') +require('../src/eventHandlers').init() diff --git a/test/unit/ResourceBookingService.test.js b/test/unit/ResourceBookingService.test.js index 08d219ba..1af075e3 100644 --- a/test/unit/ResourceBookingService.test.js +++ b/test/unit/ResourceBookingService.test.js @@ -1,6 +1,4 @@ /* eslint-disable no-unused-expressions */ -process.env.NODE_ENV = 'test' -require('../../src/bootstrap') // const _ = require('lodash') const expect = require('chai').expect @@ -10,12 +8,10 @@ const service = require('../../src/services/ResourceBookingService') const workPeriodService = require('../../src/services/WorkPeriodService') const testData = require('./common/testData') const helper = require('../../src/common/helper') -const eventHandlers = require('../../src/eventHandlers') // const esClient = helper.getESClient() const busApiClient = helper.getBusApiClient() const ResourceBooking = models.ResourceBooking const WorkPeriod = models.WorkPeriod -eventHandlers.init() describe('resourceBooking service test', () => { let stubEnsureJobById let stubEnsureUserById diff --git a/test/unit/WorkPeriodPaymentService.test.js b/test/unit/WorkPeriodPaymentService.test.js index 79880026..347e8368 100644 --- a/test/unit/WorkPeriodPaymentService.test.js +++ b/test/unit/WorkPeriodPaymentService.test.js @@ -1,6 +1,4 @@ /* eslint-disable no-unused-expressions */ -process.env.NODE_ENV = 'test' -require('../../src/bootstrap') // const _ = require('lodash') const expect = require('chai').expect @@ -10,10 +8,8 @@ const service = require('../../src/services/WorkPeriodPaymentService') const paymentService = require('../../src/services/PaymentService') const testData = require('./common/testData') const helper = require('../../src/common/helper') -const eventHandlers = require('../../src/eventHandlers') // const esClient = helper.getESClient() const busApiClient = helper.getBusApiClient() -eventHandlers.init() describe('workPeriod service test', () => { beforeEach(() => { sinon.stub(busApiClient, 'postEvent').callsFake(async () => {})