/** * Transfer Service Unit Tests */ import { IAPIGatewayEvent, ISnsEvent, KushkiError, KushkiErrorAttr, } from "@kushki/core"; import { Context } from "aws-lambda"; import { QueryOutput } from "aws-sdk/clients/dynamodb"; import { expect, use } from "chai"; import { time } from "console"; import { IDENTIFIERS } from "constant/Identifiers"; import * as faker from "faker"; import { DynamoGateway } from "gateway/DynamoGateway"; import { LambdaGateway } from "gateway/LambdaGateway"; import { PseGateway } from "gateway/PseGateway"; import { SNSGateway } from "gateway/SNSGateway"; import { CONTAINER } from "infrastructure/Container"; import { ErrorCode, ERRORS } from "infrastructure/ErrorEnum"; import { ProcessorTypeEnum } from "infrastructure/ProcessorTypeEnum"; import { PseEnum } from "infrastructure/PseEnum"; import { TransactionColumnEnum } from "infrastructure/TransactionColumnEnum"; import { TransactionStatusEnum } from "infrastructure/TransactionStatusEnum"; import * as jsf from "json-schema-faker"; import * as path from "path"; import "reflect-metadata"; import { ITransferService } from "repository/ITransferService"; import { from, of, throwError } from "rxjs"; import { createSandbox, match, SinonFakeTimers, SinonSandbox, SinonStub, } from "sinon"; import * as sinonChai from "sinon-chai"; import { Mock } from "ts-mockery"; import { AgentRequestParameters } from "types/agent_request_parameters"; import { ChargeSnsMessage } from "types/charge_sns_message"; import { ExtraTaxes, InitRequest } from "types/init_request"; import { LambdaTransactionRuleResponse } from "types/lambda_transaction_rule_response"; import { MerchantObject } from "types/merchant_object"; import { PseCreateTransaction } from "types/pse_create_transaction"; // import { PseGetBankList } from "types/pse_get_bank_list"; import { PseGetTransactionInformationResponse } from "types/pse_get_transaction_information_response"; import { SnsEventTrigger } from "types/sns_event_trigger"; import { StatusRequestParameters } from "types/status_request_parameters"; import { TokenRequest } from "types/token_request"; import { TransactionFetch } from "types/transaction_fetch"; import * as url from "url"; use(sinonChai); let gLambdaTransactionRuleResponse: LambdaTransactionRuleResponse; let gChargeSnsMessage: ChargeSnsMessage; let gChargeEvent: ISnsEvent; let gSnsEventTrigger: SnsEventTrigger; let gGetTransactionInfoResponse: PseGetTransactionInformationResponse; let gAgentEvent: IAPIGatewayEvent; let gTokenRequest: TokenRequest; let gService: ITransferService; let gSandbox: SinonSandbox; let gTransactionFetchNew: TransactionFetch; let gMerchantObject: MerchantObject; // let gPseBankList: PseGetBankList; let gPseCreateTransaction: PseCreateTransaction; let gEvent: IAPIGatewayEvent; let gTokenEvent: IAPIGatewayEvent< TokenRequest, null, null, { merchantId: string } >; let gStatusEvent: IAPIGatewayEvent< null, StatusRequestParameters, null, { merchantId: string } >; let gDefaultEvent: IAPIGatewayEvent; process.env.RULE_MERCHANT_ID = "123"; let gExtraTaxes: ExtraTaxes; let gStatusRequestParams: StatusRequestParameters; let gSubtotalIva: number; let gSubtotalIva0: number; let gIva: number; let gToken: string; let gContext: Context; const MERCHANT_ID: string = "100000012938128182"; const SCHEMA_PATH: string = "src/schema"; const ERROR_MESSAGE: string = "this must throw an error"; let gTicketNumber: string; function getTime(): number { const t: number = new Date().getTime(); const real_time_stamp: string = t.toString(); return Number(real_time_stamp); } function buildEvents(): void { gDefaultEvent = Mock.of< IAPIGatewayEvent >({ headers: { "X-FORWARDED-FOR": "0.0.0.0", "PUBLIC-MERCHANT-ID": "123", }, requestContext: { authorizer: { merchantId: MERCHANT_ID }, }, }); gTokenEvent = Mock.of< IAPIGatewayEvent >({ body: gTokenRequest, headers: gDefaultEvent.headers, requestContext: { authorizer: { merchantId: MERCHANT_ID }, }, }); gEvent = Mock.of< IAPIGatewayEvent >({ body: { token: gToken, amount: { subtotalIva: gSubtotalIva, iva: gIva, subtotalIva0: gSubtotalIva0, }, }, requestContext: { authorizer: { merchantId: MERCHANT_ID } }, }); gStatusEvent = Mock.of< IAPIGatewayEvent< null, StatusRequestParameters, null, { merchantId: string } > >({ pathParameters: gStatusRequestParams, requestContext: { authorizer: { merchantId: MERCHANT_ID } }, }); } function tokenError( mockObj: TransactionFetch, errorCode: KushkiErrorAttr, done: Mocha.Done ): void { gSandbox .stub(DynamoGateway.prototype, "query") .returns(of({ Items: [mockObj], Count: 1 })); gAgentEvent.queryStringParameters = { token: "123asd", mid: "123" }; gTransactionFetchNew.created = 0; gSandbox.stub(DynamoGateway.prototype, "getItem").returns(from([mockObj])); gService.agent(gAgentEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(errorCode).code); done(); } ); } function agentError( mockObj: IAPIGatewayEvent, done: Mocha.Done ): void { gSandbox .stub(DynamoGateway.prototype, "query") .returns(of(Mock.of())); gService.agent(mockObj, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E004).code); done(); } ); } async function randomSchemas(): Promise { gToken = faker.lorem.word(); gSubtotalIva = faker.random.number({ min: 1, max: 5 }); gSubtotalIva0 = faker.random.number({ min: 1, max: 5 }); gIva = faker.random.number({ min: 1, max: 5 }); gTicketNumber = faker.random .number({ min: 100000, max: 999999999999 }) .toString(); gLambdaTransactionRuleResponse = await jsf.resolve( { $ref: "lambda_transaction_rule_response.json", }, null, path.resolve(SCHEMA_PATH) ); gExtraTaxes = await jsf.resolve( { $ref: "init_request.json", }, null, path.resolve(SCHEMA_PATH) ); // gPseBankList = await jsf.resolve( // { // $ref: "pse_get_bank_list.json", // }, // null, // path.resolve(SCHEMA_PATH) // ); gStatusRequestParams = await jsf.resolve( { $ref: "status_request_parameters.json", }, null, path.resolve(SCHEMA_PATH) ); gMerchantObject = await jsf.resolve( { $ref: "merchant_object.json", }, null, path.resolve(SCHEMA_PATH) ); gTransactionFetchNew = await jsf.resolve( { $ref: "transaction_fetch.json", }, null, path.resolve(SCHEMA_PATH) ); gPseCreateTransaction = await jsf.resolve( { $ref: "pse_create_transaction.json", }, null, path.resolve(SCHEMA_PATH) ); gService = CONTAINER.get(IDENTIFIERS.TransferService); gSandbox = createSandbox(); gTokenRequest = await jsf.resolve( { $ref: "token_request.json", }, null, path.resolve(SCHEMA_PATH) ); gSnsEventTrigger = await jsf.resolve( { $ref: "sns_event_trigger.json", }, null, path.resolve(SCHEMA_PATH) ); gMerchantObject.serviceCode = "0"; gMerchantObject.entityCode = "1"; } describe("TransferService -", () => { beforeEach(async () => { await randomSchemas(); }); beforeEach(() => { gContext = Mock.of(); buildEvents(); }); afterEach(() => { gSandbox.restore(); }); it("test getToken", (done: Mocha.Done) => { if (gTokenEvent.body === null) throw TypeError("body is null"); gTokenEvent.body.paymentDescription = undefined; gSandbox .stub(DynamoGateway.prototype, "getItem") .returns(from([gTransactionFetchNew])); gSandbox.stub(DynamoGateway.prototype, "put").returns(of(true)); gService.getToken(gTokenEvent, gContext).subscribe( (data: object) => { expect(data).to.have.property("token"); }, done, done ); }); it("test getToken fail", (done: Mocha.Done) => { if (gTokenEvent.body === null) throw TypeError("body is null"); gTokenEvent.body.paymentDescription = "credit-card"; gSandbox .stub(DynamoGateway.prototype, "getItem") .returns(from([gTransactionFetchNew])); gSandbox.stub(DynamoGateway.prototype, "put").returns(of(null)); gService.getToken(gTokenEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.getStatusCode()).to.be.eq(ERRORS.E002.statusCode); expect(error.getMessage()).to.be.eq(ERRORS.E002.message); done(); } ); }); it("test getToken fail - PublicMerchantId is undefined", (done: Mocha.Done) => { gSandbox .stub(DynamoGateway.prototype, "getItem") .returns(from([undefined])); gSandbox.stub(DynamoGateway.prototype, "put").returns(of(null)); gService.getToken(gTokenEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.equal("T007"); done(); } ); }); it("test getToken fail - publicMerchantId nor exist", (done: Mocha.Done) => { gSandbox.stub(DynamoGateway.prototype, "getItem").returns(from([{}])); gSandbox.stub(DynamoGateway.prototype, "put").returns(of(null)); gService.getToken(gTokenEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.equal("T007"); done(); } ); }); it("get transaction status, successful response", (done: Mocha.Done) => { gTransactionFetchNew.status = TransactionStatusEnum.ApprovedTransaction; gTransactionFetchNew.ticketNumber = gTicketNumber; gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(from([gMerchantObject])) .onSecondCall() .returns(from([gTransactionFetchNew])); gService.status(gStatusEvent, gContext).subscribe((data: object) => { expect(data).to.have.property("ticketNumber", gTicketNumber); done(); }); }); it("get transaction status, pending response", (done: Mocha.Done) => { gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(from([gTransactionFetchNew])); gTransactionFetchNew.status = TransactionStatusEnum.InitializedTransaction; gService.status(gStatusEvent, gContext).subscribe((data: object) => { expect(data).to.have.property("status", "initializedTransaction"); done(); }); }); it("get transaction status, invalid token", (done: Mocha.Done) => { gTransactionFetchNew = Mock.of(); gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(from([gTransactionFetchNew])); gService.status(gStatusEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E004).code); done(); } ); }); it("get transaction status, invalid transaction", (done: Mocha.Done) => { gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(of(undefined)); gService.status(gStatusEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E004).code); done(); } ); }); it("get transaction status, undefined merchant credentials", (done: Mocha.Done) => { gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(undefined)); gService.status(gStatusEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E007).code); done(); } ); }); it("get transaction status, merchant object incorrect", (done: Mocha.Done) => { gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)); delete gMerchantObject.publicMerchantId; gService.status(gStatusEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E007).code); done(); } ); }); it("call a gateway method, success", (done: Mocha.Done) => { gSandbox.stub(PseGateway.prototype, "call").returns( of({ qwerty: 123, }) ); gService .call({ method: "qwerty", args: { lorem: "ipsum", }, }) .subscribe((response: object) => { expect(response).to.have.property("qwerty", 123); done(); }, done); }); }); describe("TransferService - BankList", () => { beforeEach(async () => { await randomSchemas(); }); beforeEach(() => { gContext = Mock.of(); buildEvents(); }); afterEach(() => { gSandbox.restore(); }); it("get bankList, successful response", (done: Mocha.Done) => { gSandbox .stub(DynamoGateway.prototype, "getItem") .returns(from([gMerchantObject])); gSandbox .stub(PseGateway.prototype, "getBankListRequest") .returns(from([gPseBankList])); gService.bankList(gDefaultEvent, gContext).subscribe((data: object) => { expect(data).to.be.a("array"); done(); }); }); it("get bankList, error response", (done: Mocha.Done) => { gMerchantObject = Mock.of(); gSandbox .stub(DynamoGateway.prototype, "getItem") .returns(of(gMerchantObject)); gService.bankList(gDefaultEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E007).code); done(); } ); }); it("get bankList, error response with merchant object as undefined", (done: Mocha.Done) => { gSandbox.stub(DynamoGateway.prototype, "getItem").returns(of(undefined)); gService.bankList(gDefaultEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E007).code); done(); } ); }); }); function invokeFunctionStub(): void { gSandbox .stub(LambdaGateway.prototype, "invokeFunction") .returns(of({ body: gLambdaTransactionRuleResponse })); } describe("TransferService - Init", () => { beforeEach(async () => { await randomSchemas(); invokeFunctionStub(); }); beforeEach(() => { gContext = Mock.of(); buildEvents(); }); afterEach(() => { gSandbox.restore(); }); it("init transaction - successful response with extraTaxes", (done: Mocha.Done) => { gTransactionFetchNew.amount.extraTaxes = gExtraTaxes; gEvent.body.metadata = { isTransactionRestricted: false }; gTransactionFetchNew.created = getTime(); gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(from([gTransactionFetchNew])) .onThirdCall() .returns(from([gMerchantObject])); gSandbox .stub(PseGateway.prototype, "createTransactionRequest") .returns(from([gPseCreateTransaction])); gSandbox .stub(DynamoGateway.prototype, "query") .returns(of({ items: [gTransactionFetchNew], Count: 1, Length: 1 })); gSandbox.stub(DynamoGateway.prototype, "put").returns(of(true)); gService.init(gEvent, gContext).subscribe((data: object) => { expect(data).to.have.property("redirectUrl"); done(); }); }); // it("init transaction - successful response w/o extraTaxes", (done: Mocha.Done) => { // gSandbox.stub(DynamoGateway.prototype, "put").returns(of(true)); // gEvent.body.metadata = { isTransactionRestricted: false }; // gSandbox // .stub(DynamoGateway.prototype, "getItem") // .onFirstCall() // .returns(of(gMerchantObject)) // .onSecondCall() // .returns(from([gTransactionFetchNew])) // .onThirdCall() // .returns(from([gMerchantObject])); // gTransactionFetchNew.created = getTime(); // gSandbox // .stub(PseGateway.prototype, "createTransactionRequest") // .returns(from([gPseCreateTransaction])); // gSandbox // .stub(DynamoGateway.prototype, "query") // .returns(of({ items: [gTransactionFetchNew], Count: 1 })); // gService.init(gEvent, gContext).subscribe((data: object) => { // expect(data).to.have.property("redirectUrl"); // done(); // }); // }); it("init transaction - expired token", (done: Mocha.Done) => { gSandbox .stub(PseGateway.prototype, "createTransactionRequest") .returns(from([gPseCreateTransaction])); gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(from([gTransactionFetchNew])); gService.init(gEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E005).code); done(); } ); }); it("init transaction - error in transaction fetch", (done: Mocha.Done) => { gTransactionFetchNew = Mock.of(); gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(from([gTransactionFetchNew])); gService.init(gEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E004).code); done(); } ); }); it("init transaction - error with getItem from Merchants Table as undefined", (done: Mocha.Done) => { gTransactionFetchNew.created = Number(time.toString()) - 1800000; gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(from([gTransactionFetchNew])) .onThirdCall() .returns(of(undefined)); gService.init(gEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E007).code); done(); } ); }); it("init transaction - error with getItem from Merchants Table with invalid merchantId", (done: Mocha.Done) => { gTransactionFetchNew.created = Number(time.toString()) - 1800000; const first_call: SinonStub = gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(of(gTransactionFetchNew)); delete gTransactionFetchNew.publicMerchantId; first_call.onThirdCall().returns(of(gTransactionFetchNew)); gService.init(gEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E007).code); done(); } ); }); it("init transaction - error with transaction as undefined", (done: Mocha.Done) => { gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(of(undefined)); gService.init(gEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E004).code); done(); } ); }); }); describe("TransferService - Charge", () => { let clock: SinonFakeTimers; function chargeError( mockObj: TransactionFetch | undefined, errorCode: KushkiErrorAttr, done: Mocha.Done, merchantObj: MerchantObject | undefined ): void { gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(mockObj)) .returns(of(merchantObj)); gSandbox .stub(PseGateway.prototype, "getTransactionInformation") .returns(throwError(new KushkiError(errorCode))); gSandbox.stub(SNSGateway.prototype, "publish").returns(of(true)); gService = CONTAINER.get(IDENTIFIERS.TransferService); gService.charge(gChargeEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(errorCode).code); done(); }, done ); clock.tick(180000); } beforeEach(async () => { gSandbox = createSandbox(); gSnsEventTrigger = await jsf.resolve( { $ref: "sns_event_trigger.json", }, null, path.resolve(SCHEMA_PATH) ); gGetTransactionInfoResponse = await jsf.resolve( { $ref: "pse_get_transaction_information_response.json", }, null, path.resolve(SCHEMA_PATH) ); gChargeSnsMessage = await jsf.resolve( { $ref: "charge_sns_message.json", }, null, path.resolve(SCHEMA_PATH) ); gMerchantObject = await jsf.resolve( { $ref: "merchant_object.json", }, null, path.resolve(SCHEMA_PATH) ); gMerchantObject.serviceCode = "0"; gMerchantObject.entityCode = "1"; clock = gSandbox.useFakeTimers(); }); beforeEach(() => { gTransactionFetchNew = Mock.of({ bankId: "123", }); gSnsEventTrigger.Records[0].Sns.Message = JSON.stringify({ entityCode: "", trazabilityCode: "", token: "", }); gChargeEvent = { Records: [ { EventSource: "", EventSubscriptionArn: "", EventVersion: "", Sns: { Message: gChargeSnsMessage, MessageAttributes: { Test: { Type: "", Value: "", }, TestBinary: { Type: "", Value: "", }, }, MessageId: "", Signature: "", SignatureVersion: "", SigningCertUrl: "", Subject: "", Timestamp: "", TopicArn: "", Type: "", UnsubscribeUrl: "", }, }, ], }; gContext = Mock.of(); }); afterEach(() => { gSandbox.restore(); }); it("test charges success", (done: Mocha.Done) => { const put_stub: SinonStub = gSandbox .stub(DynamoGateway.prototype, "put") .returns(of(true)); gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gTransactionFetchNew)) .returns(of(gMerchantObject)); gSandbox.stub(SNSGateway.prototype, "publish").returns(of(true)); gGetTransactionInfoResponse.getTransactionInformationResponseBody.transactionState = PseEnum.OK; gSandbox .stub(PseGateway.prototype, "getTransactionInformation") .returns(of(gGetTransactionInfoResponse)); gSandbox .stub(PseGateway.prototype, "finalizeTransactionPayment") .returns(of(true)); gService = CONTAINER.get(IDENTIFIERS.TransferService); gService.charge(gChargeEvent, gContext).subscribe((data: boolean) => { expect(data).to.be.true; expect(put_stub).to.be.calledWith( match.has("processorState", "OK"), match.any ); done(); }, done); clock.tick(180000); }); it("test charges fail, status pending", (done: Mocha.Done) => { gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gTransactionFetchNew)) .returns(of(gMerchantObject)); gGetTransactionInfoResponse.getTransactionInformationResponseBody.transactionState = PseEnum.Pending; gSandbox .stub(PseGateway.prototype, "getTransactionInformation") .returns(from([gGetTransactionInfoResponse])); gSandbox.stub(SNSGateway.prototype, "publish").returns(of(true)); gService = CONTAINER.get(IDENTIFIERS.TransferService); gService.charge(gChargeEvent, gContext).subscribe((data: boolean) => { expect(data).to.be.true; done(); }, done); clock.tick(180000); }); it("test charges fail, pse error", (done: Mocha.Done) => { chargeError(gTransactionFetchNew, ERRORS.E006, done, gMerchantObject); }); it("test charges fail transaction not exits", (done: Mocha.Done) => { chargeError(undefined, ERRORS.E004, done, gMerchantObject); }); it("test charges fail with invalid transaction", (done: Mocha.Done) => { delete gTransactionFetchNew.bankId; chargeError(gTransactionFetchNew, ERRORS.E004, done, gMerchantObject); }); it("test charges fail merchant not exits", (done: Mocha.Done) => { chargeError(gTransactionFetchNew, ERRORS.E007, done, undefined); }); it("test charges fail invalid merchant", (done: Mocha.Done) => { delete gMerchantObject.publicMerchantId; chargeError(gTransactionFetchNew, ERRORS.E007, done, gMerchantObject); }); }); describe("TransferService - Agent", () => { beforeEach(async () => { gService = CONTAINER.get(IDENTIFIERS.TransferService); gSandbox = createSandbox(); await randomSchemas(); gGetTransactionInfoResponse = await jsf.resolve( { $ref: "pse_get_transaction_information_response.json", }, null, path.resolve(SCHEMA_PATH) ); }); beforeEach(() => { gAgentEvent = Mock.of< IAPIGatewayEvent >(); gContext = Mock.of(); }); afterEach(() => { gSandbox.restore(); }); it("test agent token", (done: Mocha.Done) => { gAgentEvent.queryStringParameters = { token: "123asd", mid: "123" }; gTransactionFetchNew.created = getTime(); gSandbox .stub(SNSGateway.prototype, "publish") .returns(from([{ expected: "test" }])); gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(from([gTransactionFetchNew])) .onSecondCall() .returns(from([gMerchantObject])); gSandbox .stub(DynamoGateway.prototype, "query") .returns(of({ Items: [gTransactionFetchNew], Count: 1 })); gService.agent(gAgentEvent, gContext).subscribe((data: object) => { expect(data).to.be.eql({ redirectUrl: gTransactionFetchNew.bankurl }); done(); }, done); }); it("test agent token no body- fail", (done: Mocha.Done) => { gSandbox.stub(DynamoGateway.prototype, "getItem").returns(of(undefined)); gAgentEvent.queryStringParameters = { token: "123asd", mid: "123" }; gSandbox .stub(DynamoGateway.prototype, "query") .returns(of({ Items: [gTransactionFetchNew], Count: 1 })); gService.agent(gAgentEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E004).code); done(); } ); }); it("test agent token - fail", (done: Mocha.Done) => { tokenError(gTransactionFetchNew, ERRORS.E005, done); }); it("test agent token - fail no bankId", (done: Mocha.Done) => { delete gTransactionFetchNew.bankId; tokenError(gTransactionFetchNew, ERRORS.E004, done); }); it("test agent token - fail getItem output as undefined", (done: Mocha.Done) => { gSandbox .stub(DynamoGateway.prototype, "query") .returns(of({ Items: [gTransactionFetchNew], Count: 1 })); gAgentEvent.queryStringParameters = { token: "123asd", mid: "123" }; gTransactionFetchNew.created = Number(time.toString()) - 1800000; gSandbox .stub(DynamoGateway.prototype, "getItem") .returns(of(gTransactionFetchNew)) .onSecondCall() .returns(of(undefined)); gService.agent(gAgentEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E007).code); done(); } ); }); it("test agent token - fail no MerchantId", (done: Mocha.Done) => { gSandbox .stub(DynamoGateway.prototype, "query") .returns(of({ Items: [gTransactionFetchNew], Count: 1 })); gAgentEvent.queryStringParameters = { token: "123asd", mid: "123" }; gTransactionFetchNew.created = Number(time.toString()) - 1800000; const first_call: SinonStub = gSandbox .stub(DynamoGateway.prototype, "getItem") .returns(of(gTransactionFetchNew)); delete gTransactionFetchNew.publicMerchantId; first_call.onSecondCall().returns(of(gTransactionFetchNew)); gService.agent(gAgentEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E007).code); done(); } ); }); it("test agent ticketNumber", (done: Mocha.Done) => { gAgentEvent.queryStringParameters = { ticketId: "123asd" }; gSandbox .stub(DynamoGateway.prototype, "query") .returns(of({ Items: [gTransactionFetchNew], Count: 1 })); gGetTransactionInfoResponse.getTransactionInformationResponseBody.transactionState = "PENDING"; gSandbox .stub(PseGateway.prototype, "getTransactionInformation") .returns(of(gGetTransactionInfoResponse)); gTransactionFetchNew.created = getTime(); const url_parse: url.UrlWithParsedQuery = url.parse( gTransactionFetchNew.callbackUrl, true ); gSandbox .stub(DynamoGateway.prototype, "getItem") .returns(from([gTransactionFetchNew])); url_parse.search = undefined; url_parse.query = { ...url_parse.query, token: gTransactionFetchNew.token, }; const url_response: string = url.format(url_parse); gService.agent(gAgentEvent, gContext).subscribe((data: object) => { expect(data).to.be.eql({ redirectUrl: url_response }); done(); }, done); }); it("test agent ticketNumber - fail", (done: Mocha.Done) => { gAgentEvent.queryStringParameters = { ticketId: "123asd" }; agentError(gAgentEvent, done); }); it("test agent token and ticketNumber - fail", (done: Mocha.Done) => { delete gAgentEvent.queryStringParameters; gSandbox.stub(DynamoGateway.prototype, "query").returns(from([null])); gService.agent(gAgentEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E004).code); done(); } ); }); }); describe("TransferService - Init TRX Rules ", () => { beforeEach(async () => { await randomSchemas(); gSandbox .stub(LambdaGateway.prototype, "invokeFunction") .returns(of({ body: gLambdaTransactionRuleResponse })); }); beforeEach(() => { gContext = Mock.of(); buildEvents(); }); afterEach(() => { gSandbox.restore(); }); it("init transaction - validateTransactionRulesMonth - transactionRestricted - error query ", (done: Mocha.Done) => { gTransactionFetchNew = Mock.of(); gTransactionFetchNew.bankId = "00"; gMerchantObject.type = ProcessorTypeEnum.GATEWAY; gTransactionFetchNew.amount = { iva: 900, subtotalIva: 9000, subtotalIva0: 0, }; gEvent.body.metadata = { isTransactionRestricted: true }; process.env.RULE_MAX_AMOUNT = "100000000000"; gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(of(gTransactionFetchNew)) .onThirdCall() .returns(of(gMerchantObject)); gSandbox .stub(PseGateway.prototype, "createTransactionRequest") .returns(of(gPseCreateTransaction)); gSandbox.stub(DynamoGateway.prototype, "query").returns(of({ Items: [] })); gTransactionFetchNew.created = getTime(); gService.init(gEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E008).code); done(); } ); }); it("init transaction - validateTransactionRulesMonth - transactionRestricted - error validate ", (done: Mocha.Done) => { gTransactionFetchNew.amount.extraTaxes = gExtraTaxes; process.env.RULE_MERCHANT_ID = "1022284606566211841332467"; gEvent.body.metadata = { isTransactionRestricted: true }; gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(of(gTransactionFetchNew)) .onThirdCall() .returns(of(gMerchantObject)); gSandbox .stub(PseGateway.prototype, "createTransactionRequest") .returns(of(gPseCreateTransaction)); gSandbox.stub(DynamoGateway.prototype, "query").returns( of( Mock.of({ Items: [gTransactionFetchNew], }) ) ); gTransactionFetchNew.created = getTime(); gService.init(gEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E008).code); done(); } ); }); it("init transaction - validateTransactionRulesMonth - transactionRestricted - fail amount validate without extraTaxes ", (done: Mocha.Done) => { process.env.RULE_MERCHANT_ID = "123"; process.env.RULE_MAX_AMOUNT = "100000000000"; process.env.RULE_NUM_TRX = "0"; process.env.RULE_DAYS_RULE = "60"; gTransactionFetchNew.bankId = "00"; gTransactionFetchNew.publicMerchantId = "123"; gTransactionFetchNew.amount = { iva: 90000000000000, subtotalIva: 12, subtotalIva0: 0, }; gEvent.body.metadata = { isTransactionRestricted: true }; gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(from([gTransactionFetchNew])) .onThirdCall() .returns(from([gMerchantObject])); gSandbox .stub(PseGateway.prototype, "createTransactionRequest") .returns(from([gPseCreateTransaction])); gSandbox.stub(DynamoGateway.prototype, "query").returns( of( Mock.of({ Items: [gTransactionFetchNew], }) ) ); gTransactionFetchNew.created = getTime(); gService.init(gEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E008).code); done(); } ); }); // it("init transaction - validateTransactionRulesMonth - transactionRestricted - other ok ", (done: Mocha.Done) => { // gEvent.body.metadata = { mokasan: 10 }; // gSandbox // .stub(DynamoGateway.prototype, "getItem") // .onFirstCall() // .returns(of(gMerchantObject)) // .onSecondCall() // .returns(from([gTransactionFetchNew])) // .onThirdCall() // .returns(from([gMerchantObject])); // gSandbox // .stub(PseGateway.prototype, "createTransactionRequest") // .returns(from([gPseCreateTransaction])); // gSandbox.stub(DynamoGateway.prototype, "put").returns(of(true)); // gSandbox.stub(DynamoGateway.prototype, "query").returns(of({ Items: [] })); // gTransactionFetchNew.created = getTime(); // gService.init(gEvent, gContext).subscribe((data: object) => { // expect(data).to.have.property("redirectUrl"); // done(); // }); // }); it("init transaction - validateTransactionRulesMonth - transactionRestricted - fail amount validate ", (done: Mocha.Done) => { gTransactionFetchNew.amount.iva = 90000000000000; gTokenEvent.body.amount.extraTaxes = { propina: 1299, tasaAeroportuaria: 12, iac: 100, agenciaDeViajes: 12, }; gTokenEvent.body.amount.subtotalIva0 = 9000000000; gTransactionFetchNew.amount.extraTaxes = gExtraTaxes; gTransactionFetchNew.publicMerchantId = "123"; process.env.RULE_MERCHANT_ID = "123"; process.env.RULE_MAX_AMOUNT = "10"; process.env.RULE_NUM_TRX = "0"; process.env.RULE_DAYS_RULE = "60"; gEvent.body.metadata = { isTransactionRestricted: true }; gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(from([gTransactionFetchNew])) .onThirdCall() .returns(from([gMerchantObject])); gSandbox .stub(PseGateway.prototype, "createTransactionRequest") .returns(from([gPseCreateTransaction])); gSandbox.stub(DynamoGateway.prototype, "query").returns( of( Mock.of({ Items: [gTransactionFetchNew], }) ) ); gTransactionFetchNew.created = getTime(); gService.init(gEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E008).code); done(); } ); }); }); describe("TransferService - Init TRX Rules - UserIp", () => { beforeEach(async () => { await randomSchemas(); gSandbox .stub(LambdaGateway.prototype, "invokeFunction") .returns(of({ body: gLambdaTransactionRuleResponse })); }); beforeEach(() => { gContext = Mock.of(); buildEvents(); }); afterEach(() => { gSandbox.restore(); }); it("test rule - fail", (done: Mocha.Done) => { gTransactionFetchNew.publicMerchantId = "123"; gEvent.body.metadata = { isTransactionRestricted: true }; gTransactionFetchNew.status = TransactionStatusEnum.ApprovedTransaction; gTransactionFetchNew.created = getTime(); process.env.RULE_MERCHANT_ID = "123"; process.env.RULE_MAX_AMOUNT = "10000"; process.env.RULE_NUM_TRX = "2"; process.env.RULE_DAYS_RULE = "60"; gTransactionFetchNew.amount = { iva: 900, subtotalIva: 9000, subtotalIva0: 0, }; gSandbox .stub(DynamoGateway.prototype, "getItem") .onFirstCall() .returns(of(gMerchantObject)) .onSecondCall() .returns(of(gTransactionFetchNew)) .onThirdCall() .returns(of(gMerchantObject)); gSandbox .stub(DynamoGateway.prototype, "query") .withArgs(match.has("IndexName", TransactionColumnEnum.DOCUMENT_ID)) .returns( of( Mock.of({ Items: [gTransactionFetchNew], }) ) ) .withArgs(match.has("IndexName", TransactionColumnEnum.USER_IP)) .returns( of( Mock.of({ Items: [gTransactionFetchNew, gTransactionFetchNew], }) ) ); gService.init(gEvent, gContext).subscribe( () => { done(ERROR_MESSAGE); }, (error: KushkiError) => { expect(error.code).to.be.eq(new KushkiError(ERRORS.E008).code); done(); } ); }); });