Implemented tests for rules; fixed applyRules logic #18

Merged
inga-lovinde merged 2 commits from feat-13-test-rules into main 10 months ago
  1. 20
      package-lock.json
  2. 2
      package.json
  3. 94
      src/transaction/transaction.controller.spec.ts
  4. 31
      src/transaction/transaction.controller.ts

20
package-lock.json generated

@ -17,6 +17,7 @@
"axios": "0.26.1", "axios": "0.26.1",
"chai-as-promised": "^7.1.1", "chai-as-promised": "^7.1.1",
"joi": "17.6.0", "joi": "17.6.0",
"lodash": "^4.17.21",
"reflect-metadata": "0.1.13", "reflect-metadata": "0.1.13",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"rxjs": "7.5.5", "rxjs": "7.5.5",
@ -29,6 +30,7 @@
"@types/express": "4.17.13", "@types/express": "4.17.13",
"@types/jest": "27.4.1", "@types/jest": "27.4.1",
"@types/joi": "17.2.3", "@types/joi": "17.2.3",
"@types/lodash": "^4.14.202",
"@types/node": "16.0.0", "@types/node": "16.0.0",
"@types/supertest": "2.0.11", "@types/supertest": "2.0.11",
"@typescript-eslint/eslint-plugin": "5.0.0", "@typescript-eslint/eslint-plugin": "5.0.0",
@ -2157,6 +2159,12 @@
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
"dev": true "dev": true
}, },
"node_modules/@types/lodash": {
"version": "4.14.202",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz",
"integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==",
"dev": true
},
"node_modules/@types/mime": { "node_modules/@types/mime": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
@ -7032,8 +7040,7 @@
"node_modules/lodash": { "node_modules/lodash": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"dev": true
}, },
"node_modules/lodash.merge": { "node_modules/lodash.merge": {
"version": "4.6.2", "version": "4.6.2",
@ -12381,6 +12388,12 @@
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
"dev": true "dev": true
}, },
"@types/lodash": {
"version": "4.14.202",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz",
"integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==",
"dev": true
},
"@types/mime": { "@types/mime": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
@ -16120,8 +16133,7 @@
"lodash": { "lodash": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"dev": true
}, },
"lodash.merge": { "lodash.merge": {
"version": "4.6.2", "version": "4.6.2",

@ -30,6 +30,7 @@
"axios": "0.26.1", "axios": "0.26.1",
"chai-as-promised": "^7.1.1", "chai-as-promised": "^7.1.1",
"joi": "17.6.0", "joi": "17.6.0",
"lodash": "^4.17.21",
"reflect-metadata": "0.1.13", "reflect-metadata": "0.1.13",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"rxjs": "7.5.5", "rxjs": "7.5.5",
@ -42,6 +43,7 @@
"@types/express": "4.17.13", "@types/express": "4.17.13",
"@types/jest": "27.4.1", "@types/jest": "27.4.1",
"@types/joi": "17.2.3", "@types/joi": "17.2.3",
"@types/lodash": "^4.14.202",
"@types/node": "16.0.0", "@types/node": "16.0.0",
"@types/supertest": "2.0.11", "@types/supertest": "2.0.11",
"@typescript-eslint/eslint-plugin": "5.0.0", "@typescript-eslint/eslint-plugin": "5.0.0",

@ -20,7 +20,7 @@ describe('TransactionController Unit Tests', () => {
Promise.reject(new Error('DatabaseNotReachable')), Promise.reject(new Error('DatabaseNotReachable')),
), ),
findByClientIdWithinActualMonth: jest.fn((clientId) => { findByClientIdWithinActualMonth: jest.fn((clientId) => {
if (clientId === 42) { if (clientId === 42 || clientId === 99) {
return [{ base_amount: 1500 }]; return [{ base_amount: 1500 }];
} }
return []; return [];
@ -70,19 +70,95 @@ describe('TransactionController Unit Tests', () => {
}); });
it('calling applyRules method minimum result of applied rules should be got', async () => { it('calling applyRules method minimum result of applied rules should be got', async () => {
const mockTransactionInput = { {
date: '2021-01-05', const result = await transactionController.applyRules(
base_amount: 1000.0, [
currency: 'EUR', transactionController.discountRule,
transactionController.turnoverRule,
],
{
base_amount: 1000,
client_id: 1, client_id: 1,
}; },
);
expect(result).to.eql(5);
}
{
const result = await transactionController.applyRules( const result = await transactionController.applyRules(
[transactionController.discountRule, transactionController.turnoverRule], [
mockTransactionInput, transactionController.discountRule,
transactionController.turnoverRule,
],
{
base_amount: 1,
client_id: 1,
},
); );
expect(result).to.eql(5); expect(result).to.eql(0.05);
}
{
const result = await transactionController.applyRules(
[
transactionController.discountRule,
transactionController.turnoverRule,
],
{
base_amount: 1000,
client_id: 42,
},
);
expect(result).to.eql(0.03);
}
{
const result = await transactionController.applyRules(
[
transactionController.discountRule,
transactionController.turnoverRule,
],
{
base_amount: 1,
client_id: 42,
},
);
expect(result).to.eql(0.03);
}
{
const result = await transactionController.applyRules(
[
transactionController.discountRule,
transactionController.turnoverRule,
],
{
base_amount: 1000,
client_id: 99,
},
);
expect(result).to.eql(0.03);
}
{
const result = await transactionController.applyRules(
[
transactionController.discountRule,
transactionController.turnoverRule,
],
{
base_amount: 1,
client_id: 99,
},
);
expect(result).to.eql(0.03);
}
}); });
it('calling commission method correct commission should be got', async () => { it('calling commission method correct commission should be got', async () => {

@ -1,5 +1,9 @@
import { Controller, Post, UsePipes, Body } from '@nestjs/common'; import { Controller, Post, UsePipes, Body } from '@nestjs/common';
import { ExchangeRateInput, ExchangeRateResponse } from 'src/exchange-rate/exchange-rate.dto'; import _ from 'lodash';
import {
ExchangeRateInput,
ExchangeRateResponse,
} from 'src/exchange-rate/exchange-rate.dto';
import { ExchangeRateService } from 'src/exchange-rate/exchange-rate.service'; import { ExchangeRateService } from 'src/exchange-rate/exchange-rate.service';
import { TransactionService } from './transaction.service'; import { TransactionService } from './transaction.service';
import { transactionBodySchema } from './transaction.validation'; import { transactionBodySchema } from './transaction.validation';
@ -31,12 +35,8 @@ export class TransactionController {
return JSON.stringify({ return JSON.stringify({
amount: amount:
transactionInput.currency !== Currency.EUR transactionInput.currency !== Currency.EUR
? parseFloat( ? (await this.getAmountWithExchange(transactionInput)).toFixed(2)
await this.getAmountWithExchange(transactionInput), : (await this.getAmountWithoutExchange(transactionInput)).toFixed(2),
).toFixed(2)
: parseFloat(
await this.getAmountWithoutExchange(transactionInput),
).toFixed(2),
currency: Currency.EUR, currency: Currency.EUR,
}); });
} }
@ -96,19 +96,10 @@ export class TransactionController {
) => number | false | undefined | Promise<number | false | undefined>)[], ) => number | false | undefined | Promise<number | false | undefined>)[],
transactionInput: TransactionRuleData, transactionInput: TransactionRuleData,
) { ) {
let commissionAmount; const commissions = await Promise.all(
for (let i = 0; i < rules.length; i++) { [...rules, this.defaultRule].map((rule) => rule(transactionInput)),
const ruleResult = await rules[i](transactionInput); );
if (ruleResult) { return Math.min(..._.compact(commissions));
commissionAmount = ruleResult;
break;
} else {
continue;
}
}
return commissionAmount
? commissionAmount
: this.defaultRule(transactionInput);
} }
getExchangeRate(exchangeRateInput: ExchangeRateInput) { getExchangeRate(exchangeRateInput: ExchangeRateInput) {

Loading…
Cancel
Save