UNPKG

limepay

Version:

LimePay SDK is a node module for simplifying the consumption of LimePay API

672 lines (559 loc) 27.5 kB
const assert = require('assert'); const chai = require('chai'); const expect = chai.expect; const ConnectionClient = require('./../clients/connection-client/connection-client'); const ShoppersClient = require('./../clients/shoppers-client'); const PaymentsClient = require('./../clients/payment-clients/payments-client'); const FiatPaymentsClient = require('./../clients/payment-clients/fiat-payments-client'); const RelayedPaymentsClient = require('./../clients/payment-clients/relayed-payments-client'); const LimePay = require('./../index'); const nock = require('nock'); const shoppersMock = require('./mocks/shoppersMock.json'); const vendorsMock = require('./mocks/vendorsMock.json'); const paymentsMock = require('./mocks/paymentsMock.json'); const SDK_ERRORS = require('./../errors/sdk-errors'); const sinon = require('sinon'); describe('Clients', () => { const url = "http://localhost/v1"; let sdk; let executePOSTSpy; let executeGetSpy; beforeEach(async () => { nock(url) .get('/ping') .reply(200, { "response": "success" }); nock(url) .get('/shoppers') .reply(200, shoppersMock.getAll); nock(url) .get(`/shoppers/${shoppersMock.shopper._id}`) .reply(200, shoppersMock.shopper); nock(url) .patch(`/shoppers/${shoppersMock.shopper._id}`) .reply(200, shoppersMock.updatedShopper); nock(url) .delete(`/shoppers/${shoppersMock.shopper._id}`) .reply(200); nock(url) .get(`/shoppers/${shoppersMock.shopper._id}/walletToken`) .reply(404, shoppersMock.getWalletTokenForShopperWithoutLPWallet) nock(url) .get(`/shoppers/${shoppersMock.shopperWithLPWallet._id}/walletToken`) .reply(201, shoppersMock.getWalletToken); nock(url) .post('/shoppers') .reply(200, shoppersMock.shopper); nock(url) .get('/vendors') .reply(200, vendorsMock.vendors); nock(url) .get('/payments/metadata?shopperId=0&returnGasPrice=false') .reply(200, paymentsMock.shopperMetadata); nock(url) .get('/payments/metadata?shopperId=0&returnGasPrice=true') .reply(200, paymentsMock.shopperMetadata_with_gas_price); nock(url) .post('/payments') .reply(200, paymentsMock.new_payment); nock(url) .get('/payments/0/invoice/preview') .reply(200, paymentsMock.invoiceTemplate); nock(url) .get('/payments/0/receipt') .reply(200, paymentsMock.receiptTemplate); nock(url) .get('/payments/0/invoice/') .reply(200); nock(url) .post('/payments/relayed') .reply(200, paymentsMock.new_payment); nock(url) .get('/payments/0') .reply(200, paymentsMock.new_payment); nock(url) .get('/payments') .reply(200, paymentsMock.getAll); nock(url) .get('/payments/0/invoice') .reply(200); sdk = await LimePay.connect({ environment: url, apiKey: 'YOUR_API_KEY_HERE', secret: 'YOUR_API_SECRET_HERE' }); executeGetSpy = sinon.spy(sdk.connection.HTTPRequester, 'executeGETRequest'); executePOSTSpy = sinon.spy(sdk.connection.HTTPRequester, 'executePOSTRequest'); getSignatureMetadataSpy = sinon.spy(sdk.fiatPayment, '_getSignatureMetadata'); computeAuthorizationSignatureSpy = sinon.spy(sdk.fiatPayment, '_computeAuthorizationSignature'); }); describe('Clients initialization', () => { it('Should initialize successfully a Shoppers client', async () => { assert(sdk.shoppers instanceof ShoppersClient, "ShoppersClient has not been initialize correctly"); }); it('Should initialize successfully a Payments client', async () => { assert(sdk.payments instanceof PaymentsClient, "PaymentsClient has not been initialize correctly"); }); it('Should initialize successfully a FiatPayments client', async () => { assert(sdk.fiatPayment instanceof FiatPaymentsClient, "FiatPaymentsClient has not been initialize correctly"); }); it('Should initialize successfully a RelayedPayments client', async () => { assert(sdk.relayedPayment instanceof RelayedPaymentsClient, "RelayedPaymentsClient has not been initialize correctly"); }); it('Should initialize successfully a Connection client', async () => { assert(sdk.connection instanceof ConnectionClient, "ConnectionClient has not been initialize correctly"); }); }); describe('Shoppers client functionality', () => { it('Should get all shoppers successfully', async () => { //Arrange let expectedCount = 2 let expectedFirstShopperId = shoppersMock.getAll[0]._id let expectedFirstShopperFirstName = shoppersMock.getAll[0].firstName let expectedSecondShopperId = shoppersMock.getAll[1]._id let expectedSecondShopperFirstName = shoppersMock.getAll[1].firstName //Act let shoppers = await sdk.shoppers.getAll(); //Assert sinon.assert.calledOnce(executeGetSpy); assert(shoppers.length == expectedCount, "Shoppers get all returned wrong count of shoppers."); assert(shoppers[0].firstName == expectedFirstShopperFirstName, "First shopper firstName is wrong"); assert(shoppers[0]._id == expectedFirstShopperId, "First shopper id is wrong"); assert(shoppers[1].firstName == expectedSecondShopperFirstName, "Second shopper firstName is wrong"); assert(shoppers[1]._id == expectedSecondShopperId, "Second shopper id is wrong"); }); it('Create shopper successfully', async () => { //Arrange let expectedShopperId = 2 let expectedShopperVendor = shoppersMock.shopper.vendor let expectedShopperFirstName = shoppersMock.shopper.firstName let expectedShopperLastName = shoppersMock.shopper.lastName let expectedShopperEmail = shoppersMock.shopper.email let expectedShopperWalletAddress = shoppersMock.shopper.walletAddress //Act let shopper = await sdk.shoppers.create({ "vendor": expectedShopperVendor, "firstName": expectedShopperFirstName, "lastName": expectedShopperLastName, "email": expectedShopperEmail, "walletAddress": expectedShopperWalletAddress, }); //Assert assert(shopper._id == expectedShopperId, "Shopper id is wrong"); assert(shopper.vendor == expectedShopperVendor, "Shopper vendor is wrong"); assert(shopper.firstName == expectedShopperFirstName, "Shopper firstName is wrong"); assert(shopper.lastName == expectedShopperLastName, "Shopper lastName is wrong"); assert(shopper.email == expectedShopperEmail, "Shopper email is wrong"); assert(shopper.walletAddress == expectedShopperWalletAddress, "Shopper walletAddress is wrong"); }); it('Create shopper without vendor successfully', async () => { //Arrange let expectedShopperVendor = shoppersMock.shopper.vendor let expectedShopperFirstName = shoppersMock.shopper.firstName let expectedShopperLastName = shoppersMock.shopper.lastName let expectedShopperEmail = shoppersMock.shopper.email let expectedShopperWalletAddress = shoppersMock.shopper.walletAddress //Act let shopper = await sdk.shoppers.create({ "firstName": expectedShopperFirstName, "lastName": expectedShopperLastName, "email": expectedShopperEmail, "walletAddress": expectedShopperWalletAddress, }); //Assert sinon.assert.calledOnce(executeGetSpy); sinon.assert.calledOnce(executePOSTSpy); assert(shopper.vendor == expectedShopperVendor, "Shopper vendor is wrong"); assert(shopper.firstName == expectedShopperFirstName, "Shopper firstName is wrong"); assert(shopper.lastName == expectedShopperLastName, "Shopper lastName is wrong"); assert(shopper.email == expectedShopperEmail, "Shopper email is wrong"); assert(shopper.walletAddress == expectedShopperWalletAddress, "Shopper walletAddress is wrong"); }); it('[NEGATIVE] Create shopper when there are 0 vendors', async () => { //Arrange nock.cleanAll(); nock(url) .get('/vendors') .reply(200, []); let expectedShopperFirstName = shoppersMock.shopper.firstName let expectedShopperLastName = shoppersMock.shopper.lastName let expectedShopperEmail = shoppersMock.shopper.email let expectedShopperWalletAddress = shoppersMock.shopper.walletAddress let shopperData = { "firstName": expectedShopperFirstName, "lastName": expectedShopperLastName, "email": expectedShopperEmail, "walletAddress": expectedShopperWalletAddress, } //Act // Assert await expect(sdk.shoppers.create(shopperData)).to.be.rejectedWith(SDK_ERRORS.NO_VENDOR_ERROR) }); it('Get shopper successfully', async () => { //Arrange let expectedShopperId = shoppersMock.shopper._id let expectedShopperVendor = shoppersMock.shopper.vendor let expectedShopperFirstName = shoppersMock.shopper.firstName let expectedShopperLastName = shoppersMock.shopper.lastName let expectedShopperEmail = shoppersMock.shopper.email let expectedShopperWalletAddress = shoppersMock.shopper.walletAddress //Act let shopper = await sdk.shoppers.get(expectedShopperId); //Assert sinon.assert.calledOnce(executeGetSpy); assert(shopper._id == expectedShopperId, "Shopper id is wrong"); assert(shopper.vendor == expectedShopperVendor, "Shopper vendor is wrong"); assert(shopper.firstName == expectedShopperFirstName, "Shopper firstName is wrong"); assert(shopper.lastName == expectedShopperLastName, "Shopper lastName is wrong"); assert(shopper.email == expectedShopperEmail, "Shopper email is wrong"); assert(shopper.walletAddress == expectedShopperWalletAddress, "Shopper walletAddress is wrong"); }); it('Patch shopper successfully', async () => { //Arrange let shopperId = shoppersMock.shopper._id let expectedShopperFirstName = shoppersMock.updatedShopper.firstName let expectedShopperLastName = shoppersMock.updatedShopper.lastName let expectedShopperVendor = shoppersMock.shopper.vendor let expectedShopperEmail = shoppersMock.shopper.email let expectedShopperWalletAddress = shoppersMock.shopper.walletAddress //Act let shopper = await sdk.shoppers.update(shopperId, { "firstName": expectedShopperFirstName, "lastName": expectedShopperLastName, }); //Assert assert(shopper.firstName == expectedShopperFirstName, "Shopper firstName is wrong"); assert(shopper.lastName == expectedShopperLastName, "Shopper lastName is wrong"); assert(shopper.vendor == expectedShopperVendor, "Shopper vendor is wrong"); assert(shopper.email == expectedShopperEmail, "Shopper email is wrong"); assert(shopper.walletAddress == expectedShopperWalletAddress, "Shopper walletAddress is wrong"); }); it('Delete shopper successfully', async () => { //Arrange let shopperId = shoppersMock.shopper._id //Act let result = await sdk.shoppers.delete(shopperId); //todo fix it when delete returns proper result //Assert // assert(shopper.lastName == expectedShopperLastName, "Shopper lastName is wrong"); }); it('Should get Wallet Token for Shopper with LP Wallet', async () => { const shopperId = shoppersMock.shopperWithLPWallet._id; const result = await sdk.shoppers.getWalletToken(shopperId); assert.deepStrictEqual(result, shoppersMock.getWalletToken); }) it('[NEGATIVE] Should NOT Get Wallet Token for Shopper without LP Wallet', async () => { const shopperId = shoppersMock.shopper._id; await expect(sdk.shoppers.getWalletToken(shopperId)).to.be.rejectedWith(shoppersMock.getWalletTokenForShopperWithoutLPWallet); }) }); describe('Fiat payment client functionality', () => { it('Should create payment with correct data successfully', async () => { //Arrange let fiatPaymentData = { "currency": "bgn", "shopper": "0", "items": ["item1", "item2"], "fundTxData": { "weiAmount": "123", "tokenAmount": "123", "gasPrice": 15 }, "genericTransactions": { "to": "0x123", "gasPrice": "123", "gasLimit": "321", "functionName": "funcN", "functionParams": "parm123" } } let signerWalletConfig = { privateKey: 'A6B8FE6AC1322A67DB28626FFA23BD877880A49727045E9E4E470019BC56119D' } //Act let payment = await sdk.fiatPayment.create(fiatPaymentData, signerWalletConfig); //Assert sinon.assert.calledOnce(executePOSTSpy); assert(payment.currency == fiatPaymentData.currency, "Payment currency is not correct."); assert(payment.shopper == fiatPaymentData.shopper, "Payment shopper is not correct."); assert(payment.items[0] == fiatPaymentData.items[0], "Payment item1 is not correct."); assert(payment.items[1] == fiatPaymentData.items[1], "Payment item2 is not correct."); }); it('Should create payment without gas price provided successfully', async () => { //Arrange let fiatPaymentData = { "currency": "bgn", "shopper": "0", "items": ["item1", "item2"], "fundTxData": { "weiAmount": "123", "tokenAmount": "123", }, "genericTransactions": { "to": "0x123", "gasPrice": "123", "gasLimit": "321", "functionName": "funcN", "functionParams": "parm123" } } let signerWalletConfig = { privateKey: 'A6B8FE6AC1322A67DB28626FFA23BD877880A49727045E9E4E470019BC56119D' } //Act let payment = await sdk.fiatPayment.create(fiatPaymentData, signerWalletConfig); //Assert sinon.assert.calledOnce(executePOSTSpy); assert(payment.currency == fiatPaymentData.currency, "Payment currency is not correct."); assert(payment.shopper == fiatPaymentData.shopper, "Payment shopper is not correct."); assert(payment.items[0] == fiatPaymentData.items[0], "Payment item1 is not correct."); assert(payment.items[1] == fiatPaymentData.items[1], "Payment item2 is not correct."); }) it('Should get a single payment successfully', async () => { //Arrange let paymentId = paymentsMock.new_payment._id; let expectedShopper = paymentsMock.new_payment.shopper let expectedVendor = paymentsMock.new_payment.vendor let expectedType = paymentsMock.new_payment.type //Act let payment = await sdk.fiatPayment.get(paymentId); //Assert sinon.assert.calledOnce(executeGetSpy); assert(payment.shopper == expectedShopper, "Payment shopper is not correct."); assert(payment.vendor == expectedVendor, "Payment vendor is not correct."); assert(payment.type == expectedType, "Payment type is not correct."); }); it('Should get all payments successfully', async () => { //Arrange let expectedFirstId = paymentsMock.getAll[0]._id; let expectedFirstShopper = paymentsMock.getAll[0].shopper let expectedFirstVendor = paymentsMock.getAll[0].vendor let expectedFirstType = paymentsMock.getAll[0].type let expectedSecondId = paymentsMock.getAll[1]._id; let expectedSecondShopper = paymentsMock.getAll[1].shopper let expectedSecondVendor = paymentsMock.getAll[1].vendor let expectedSecondType = paymentsMock.getAll[1].type //Act let payments = await sdk.fiatPayment.getAll(); //Assert sinon.assert.calledOnce(executeGetSpy); assert(payments[0]._id == expectedFirstId, "Payment id is not correct."); assert(payments[0].shopper == expectedFirstShopper, "Payment shopper is not correct."); assert(payments[0].vendor == expectedFirstVendor, "Payment vendor is not correct."); assert(payments[0].type == expectedFirstType, "Payment type is not correct."); assert(payments[1]._id == expectedSecondId, "Payment id is not correct."); assert(payments[1].shopper == expectedSecondShopper, "Payment shopper is not correct."); assert(payments[1].vendor == expectedSecondVendor, "Payment vendor is not correct."); assert(payments[1].type == expectedSecondType, "Payment type is not correct."); }); it('[NEGATIVE] Shouldn\'t create payment with incorrect wei amount', async () => { //Arrange let fiatPaymentData = { "currency": "bgn", "shopper": "0", "items": ["item1", "item2"], "fundTxData": { "tokenAmount": "123" }, "genericTransactions": { "to": "0x123", "gasPrice": "123", "gasLimit": "321", "functionName": "funcN", "functionParams": "parm123" } } let signerWalletConfig = { privateKey: 'A6B8FE6AC1322A67DB28626FFA23BD877880A49727045E9E4E470019BC56119D' } //Act //Assert await expect(sdk.fiatPayment.create(fiatPaymentData, signerWalletConfig)).to.be.rejectedWith(SDK_ERRORS.INVALID_TOKEN_AND_WEI_AMOUNT_PROVIDED) }); it('[NEGATIVE] Shouldn\'t create payment without fundTxData', async () => { //Arrange let fiatPaymentData = { "currency": "bgn", "shopper": "0", "items": ["item1", "item2"], "genericTransactions": { "to": "0x123", "gasPrice": "123", "gasLimit": "321", "functionName": "funcN", "functionParams": "parm123" } } let signerWalletConfig = { privateKey: 'A6B8FE6AC1322A67DB28626FFA23BD877880A49727045E9E4E470019BC56119D' } //Act //Assert await expect(sdk.fiatPayment.create(fiatPaymentData, signerWalletConfig)).to.be.rejectedWith(SDK_ERRORS.INVALID_TOKEN_AND_WEI_AMOUNT_PROVIDED) }); it('[NEGATIVE] Should not compute authorizationSignature when already provided', async () => { //Arrange let fiatPaymentData = { "currency": "bgn", "shopper": "0", "items": ["item1", "item2"], "fundTxData": { "authorizationSignature": null }, "genericTransactions": { "to": "0x123", "gasPrice": "123", "gasLimit": "321", "functionName": "funcN", "functionParams": "parm123" } } let signerWalletConfig = { privateKey: 'A6B8FE6AC1322A67DB28626FFA23BD877880A49727045E9E4E470019BC56119D' } //Act //Assert await expect(sdk.fiatPayment.create(fiatPaymentData, signerWalletConfig)).to.be.rejectedWith(SDK_ERRORS.NO_FUND_TX_DATA_PROVIDED) sinon.assert.calledOnce(getSignatureMetadataSpy) sinon.assert.calledOnce(computeAuthorizationSignatureSpy) }); it('Should create payment with authorizationSignature', async () => { //Arrange let fiatPaymentData = { "currency": "bgn", "shopper": "0", "items": ["item1", "item2"], "fundTxData": { "authorizationSignature": true }, "genericTransactions": { "to": "0x123", "gasPrice": "123", "gasLimit": "321", "functionName": "funcN", "functionParams": "parm123" } } let signerWalletConfig = { privateKey: 'A6B8FE6AC1322A67DB28626FFA23BD877880A49727045E9E4E470019BC56119D' } //Act let payment = await sdk.fiatPayment.create(fiatPaymentData, signerWalletConfig); //Assert sinon.assert.calledOnce(executePOSTSpy); sinon.assert.notCalled(getSignatureMetadataSpy) sinon.assert.notCalled(computeAuthorizationSignatureSpy) assert(payment.currency == fiatPaymentData.currency, "Fiat payment currency is wrong"); assert(payment.shopper == fiatPaymentData.shopper, "Fiat payment shopper is wrong"); }); it('[NEGATIVE] Should throw sign error with invalid data', async () => { //Arrange let fiatPaymentData = { "currency": "bgn", "shopper": "0", "items": ["item1", "item2"], "fundTxData": { "weiAmount": "123", "tokenAmount": "123" }, "genericTransactions": { "to": "0x123", "gasPrice": "123", "gasLimit": "321", "functionName": "funcN", "functionParams": "parm123" } } let signerWalletConfig = { privateKey: 'A6B8FE6AC1322A67DB28626FFA23BD877880A49727045E9E4E470019BC56119D' } //Assert await expect(sdk.fiatPayment._computeAuthorizationSignature.bind(this, {}, fiatPaymentData.fundTxData, signerWalletConfig)).to.throw().and.deep.equal(SDK_ERRORS.SIGNING_ERROR); }); it('Send Invoice successfully', async () => { //Act //TODO: get a proper response let result = await sdk.fiatPayment.sendInvoice(paymentsMock.new_payment._id); //Assert console.log(result) }); it('Get Invoice', async () => { //Act let result = await sdk.fiatPayment.getInvoice(paymentsMock.new_payment._id); //Assert sinon.assert.calledOnce(executeGetSpy); assert(result.html == paymentsMock.invoiceTemplate.html, "Html is wrong"); }); it('Get Receipt', async () => { //Act let result = await sdk.fiatPayment.getReceipt(paymentsMock.new_payment._id); //Assert sinon.assert.calledOnce(executeGetSpy); assert(result.html == paymentsMock.receiptTemplate.html, "Html is wrong"); }); }); describe('Relayed payment client functionality', () => { it('Should create payment with correct data successfully', async () => { //Arrange let relayedPaymentData = { "shopper": "0", "fundTxData": { "weiAmount": "100" }, "items": ["item1", "item2"], "genericTransactions": { "to": "0x123", "gasPrice": "123", "gasLimit": "321", "functionName": "funcN", "functionParams": "parm123" } } let signerWalletConfig = { privateKey: 'A6B8FE6AC1322A67DB28626FFA23BD877880A49727045E9E4E470019BC56119D' } //Act let payment = await sdk.relayedPayment.create(relayedPaymentData, signerWalletConfig); //Assert sinon.assert.calledOnce(executePOSTSpy); assert(payment.shopper == relayedPaymentData.shopper, "Payment shopper is not correct."); assert(payment.items[0] == relayedPaymentData.items[0], "Payment item1 is not correct."); assert(payment.items[1] == relayedPaymentData.items[1], "Payment item2 is not correct."); }); it('[NEGATIVE] Shouldn\'t create payment without wei amount', async () => { //Arrange let relayedPaymentData = { "shopper": "0", "fundTxData": { }, "items": ["item1", "item2"], "genericTransactions": { "to": "0x123", "gasPrice": "123", "gasLimit": "321", "functionName": "funcN", "functionParams": "parm123" } } let signerWalletConfig = { privateKey: 'A6B8FE6AC1322A67DB28626FFA23BD877880A49727045E9E4E470019BC56119D' } //Act //Assert await expect(sdk.relayedPayment.create(relayedPaymentData, signerWalletConfig)).to.be.rejectedWith(SDK_ERRORS.INVALID_TOKEN_AND_WEI_AMOUNT_PROVIDED) }); it('[NEGATIVE] Shouldn\'t create payment invalid sign data', async () => { //Arrange let fundTxData = { "weiAmount": "100" }; let signerWalletConfig = { privateKey: 'A6B8FE6AC1322A67DB28626FFA23BD877880A49727045E9E4E470019BC56119D' } //Assert await expect(sdk.relayedPayment._computeAuthorizationSignature.bind(this, {}, fundTxData, signerWalletConfig)).to.throw().and.deep.equal(SDK_ERRORS.SIGNING_ERROR); }); }); });