From 098f5214e0d11e191dee90751d825ebe2c7f3498 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Fri, 6 Dec 2019 16:15:27 -0800 Subject: [PATCH] Fixed tests --- test/v3/block.js | 611 ---------------- test/v3/insight-address.js | 1348 ------------------------------------ test/v3/transaction.js | 333 --------- 3 files changed, 2292 deletions(-) delete mode 100644 test/v3/block.js delete mode 100644 test/v3/insight-address.js delete mode 100644 test/v3/transaction.js diff --git a/test/v3/block.js b/test/v3/block.js deleted file mode 100644 index 26477f4..0000000 --- a/test/v3/block.js +++ /dev/null @@ -1,611 +0,0 @@ -"use strict" - -const blockRoute = require("../../src/routes/v3/insight/block") -const chai = require("chai") -const assert = chai.assert -const nock = require("nock") // HTTP mocking - -let originalEnvVars // Used during transition from integration to unit tests. - -// Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/block-mock") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -describe("#Block", () => { - let req, res - - before(() => { - // Save existing environment variables. - originalEnvVars = { - BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, - RPC_BASEURL: process.env.RPC_BASEURL, - RPC_USERNAME: process.env.RPC_USERNAME, - RPC_PASSWORD: process.env.RPC_PASSWORD - } - - // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" - } - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - - // Explicitly reset the parmas and body. - req.params = {} - req.body = {} - - // Activate nock if it's inactive. - if (!nock.isActive()) nock.activate() - }) - - afterEach(() => { - // Clean up HTTP mocks. - nock.cleanAll() // clear interceptor list. - nock.restore() - }) - - after(() => { - // Restore any pre-existing environment variables. - process.env.BITCOINCOM_BASEURL = originalEnvVars.BITCOINCOM_BASEURL - process.env.RPC_BASEURL = originalEnvVars.RPC_BASEURL - process.env.RPC_USERNAME = originalEnvVars.RPC_USERNAME - process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD - }) - - describe("#root", () => { - // root route handler. - const root = blockRoute.testableComponents.root - - it("should respond to GET for base route", async () => { - const result = root(req, res) - - assert.equal(result.status, "block", "Returns static string") - }) - }) - - describe("#detailsByHashSingle", () => { - const detailsByHash = blockRoute.testableComponents.detailsByHashSingle - - it("should throw an error for an empty hash", async () => { - req.params.hash = "" - - const result = await detailsByHash(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "hash must not be empty", - "Proper error message" - ) - }) - - it("should throw 50X when network issues", async () => { - // Save the existing RPC URL. - const savedUrl = process.env.BITCOINCOM_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - req.params.hash = "abc123" - const result = await detailsByHash(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.isAbove(res.statusCode, 499, "HTTP status code 50X expected.") - //assert.include(result.error, "ENOTFOUND", "Error message expected") - }) - - it("should throw an error for invalid hash", async () => { - req.params.hash = "abc123" - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${req.params.hash}`) - .reply(404, "Not found") - } - - const result = await detailsByHash(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.include(result.error, "Not found", "Proper error message") - }) - - it("should GET /detailsByHash/:hash", async () => { - req.params.hash = - "0000000000000000009ff8b38118d540e33c262bf6f78fc6863cc444526dc086" - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${req.params.hash}`) - .reply(200, mockData.mockBlockDetails) - } - - const result = await detailsByHash(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAnyKeys(result, [ - "hash", - "size", - "height", - "version", - "merkleroot", - "tx", - "time", - "nonce", - "bits", - "difficulty", - "chainwork", - "confirmations", - "previousblockhash", - "nextblockhash", - "reward", - "isMainChain", - "poolInfo" - ]) - assert.isArray(result.tx) - }) - }) - - describe("#detailsByHashBulk", () => { - // details route handler. - const detailsByHashBulk = blockRoute.testableComponents.detailsByHashBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await detailsByHashBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "hashes needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single address", async () => { - req.body = { - hashes: - "0000000000000000009ff8b38118d540e33c262bf6f78fc6863cc444526dc086" - } - - const result = await detailsByHashBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "hashes needs to be an array", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.hashes = testArray - - const result = await detailsByHashBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw an error for an invalid hash", async () => { - req.body = { - hashes: [`abc123`] - } - - const result = await detailsByHashBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid hash", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body = { - hashes: [ - "00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79" - ] - } - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await detailsByHashBulk(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get details for a single hash", async () => { - req.body = { - hashes: [ - "0000000000000000009ff8b38118d540e33c262bf6f78fc6863cc444526dc086" - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${req.body.hashes[0]}`) - .reply(200, mockData.mockBlockDetails) - } - - // Call the details API. - const result = await detailsByHashBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.equal(result.length, 1, "Array with one entry") - assert.hasAllKeys(result[0], [ - "bits", - "chainwork", - "confirmations", - "difficulty", - "hash", - "height", - "isMainChain", - "merkleroot", - "nextblockhash", - "nonce", - "poolInfo", - "previousblockhash", - "reward", - "size", - "time", - "tx", - "version" - ]) - }) - - it("should get details for multiple hashes", async () => { - req.body = { - hashes: [ - `0000000000000000009ff8b38118d540e33c262bf6f78fc6863cc444526dc086`, - `0000000000000000009ff8b38118d540e33c262bf6f78fc6863cc444526dc086` - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${req.body.hashes[0]}`) - .reply(200, mockData.mockBlockDetails) - - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${req.body.hashes[1]}`) - .reply(200, mockData.mockBlockDetails) - } - - // Call the details API. - const result = await detailsByHashBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") - }) - - it("should throw an error if hash not found", async () => { - req.body = { - hashes: [ - `00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44abcdef` - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${req.body.hashes[0]}`) - //.reply(404, { error: { message: "Not Found" } }) - .reply(404, "Not found") - } - - const result = await detailsByHashBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 404, "HTTP status code 404 expected.") - assert.include(result.error, "Not found", "Proper error message") - }) - }) - - describe("Block Details By Height", () => { - // block route handler. - const detailsByHeight = blockRoute.testableComponents.detailsByHeightSingle - - it("should throw an error for an empty height", async () => { - req.params.height = "" - - const result = await detailsByHeight(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "height must not be empty", - "Proper error message" - ) - }) - - it("should throw 500 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl = process.env.BITCOINCOM_BASEURL - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api/" - - req.params.height = "abc123" - const result = await detailsByHeight(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - process.env.RPC_BASEURL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or great expected." - ) - //assert.include(result.error, "ENOTFOUND", "Error message expected") - }) - - it("should throw an error for invalid height", async () => { - req.params.height = "abc123" - - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - console.log(`process.env.RPC_BASEURL: ${process.env.RPC_BASEURL}`) - nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) - .reply(500, { - error: { - code: -1, - message: "JSON value is not an integer as expected" - } - }) - } - - const result = await detailsByHeight(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "JSON value is not an integer as expected", - "Proper error message" - ) - }) - - it("should GET /detailsByHeight/:height", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) - .reply(200, { result: mockData.mockBlockHash }) - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get( - `/block/00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79` - ) - .reply(200, mockData.mockBlockDetails) - } - - req.params.height = 500000 - - const result = await detailsByHeight(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAnyKeys(result, [ - "hash", - "size", - "height", - "version", - "merkleroot", - "tx", - "time", - "nonce", - "bits", - "difficulty", - "chainwork", - "confirmations", - "previousblockhash", - "nextblockhash", - "reward", - "isMainChain", - "poolInfo" - ]) - assert.isArray(result.tx) - }) - }) - - describe("#detailsByHeightBulk", () => { - // details route handler. - const detailsByHeightBulk = - blockRoute.testableComponents.detailsByHeightBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await detailsByHeightBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "heights needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single height", async () => { - req.body = { - heights: 500000 - } - - const result = await detailsByHeightBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "heights needs to be an array", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.heights = testArray - - const result = await detailsByHeightBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw error for an invalid height", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) - .reply(500, { - error: { - code: -1, - message: "JSON value is not an integer as expected" - } - }) - } - - req.body.heights = [`abc123`] - - const result = await detailsByHeightBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body.heights = [`500000`] - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await detailsByHeightBulk(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get details for a single height", async () => { - req.body.heights = [`500000`] - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) - .reply(200, { result: mockData.mockBlockHash }) - - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${mockData.mockBlockHash}`) - .reply(200, mockData.mockBlockDetails) - } - - // Call the details API. - const result = await detailsByHeightBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.equal(result.length, 1, "Array with one entry") - assert.hasAllKeys(result[0], [ - "bits", - "chainwork", - "confirmations", - "difficulty", - "hash", - "height", - "isMainChain", - "merkleroot", - "nextblockhash", - "nonce", - "poolInfo", - "previousblockhash", - "reward", - "size", - "time", - "tx", - "version" - ]) - }) - - it("should get details for multiple block heights", async () => { - req.body = { - heights: [`500000`, `500001`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) - .times(2) - .reply(200, { result: mockData.mockBlockHash }) - - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${mockData.mockBlockHash}`) - .times(2) - .reply(200, mockData.mockBlockDetails) - } - - // Call the details API. - const result = await detailsByHeightBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") - }) - }) -}) diff --git a/test/v3/insight-address.js b/test/v3/insight-address.js deleted file mode 100644 index 992141b..0000000 --- a/test/v3/insight-address.js +++ /dev/null @@ -1,1348 +0,0 @@ -/* - TESTS FOR THE ADDRESS.JS LIBRARY - - This test file uses the environment variable TEST to switch between unit - and integration tests. By default, TEST is set to 'unit'. Set this variable - to 'integration' to run the tests against BCH mainnet. - - To-Do: - -/details/:address - --Verify to/from query options work correctly. - -GET /unconfirmed/:address & POST /unconfirmed - --Should initiate a transfer of BCH to verify unconfirmed TX. - ---This would be more of an e2e test. -*/ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const addressRoute = require("../../src/routes/v3/insight/address") -const nock = require("nock") // HTTP mocking - -let originalUrl // Used during transition from integration to unit tests. - -// Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/address-mock") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -describe("#Insight Address", () => { - let req, res - - before(() => { - originalUrl = process.env.BITCOINCOM_BASEURL - - // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - // console.log(`Testing type is: ${process.env.TEST}`) - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - - // Explicitly reset the parmas and body. - req.params = {} - req.body = {} - req.query = {} - - // Activate nock if it's inactive. - if (!nock.isActive()) nock.activate() - }) - - afterEach(() => { - // Clean up HTTP mocks. - nock.cleanAll() // clear interceptor list. - nock.restore() - }) - - after(() => { - process.env.BITCOINCOM_BASEURL = originalUrl - }) - - describe("#root", () => { - // root route handler. - const root = addressRoute.testableComponents.root - - it("should respond to GET for base route", async () => { - const result = root(req, res) - - assert.equal(result.status, "address", "Returns static string") - }) - }) - - describe("#AddressDetailsBulk", () => { - // details route handler. - const detailsBulk = addressRoute.testableComponents.detailsBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single address", async () => { - req.body = { - address: `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - } - - const result = await detailsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid address", async () => { - req.body = { - addresses: [`02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - const result = await detailsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.addresses = testArray - - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should detect a network mismatch", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await detailsBulk(req, res) - //console.log(`network issue result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.isAbove(res.statusCode, 499, "HTTP status code 500 expected.") - //assert.include(result.error, "ENOTFOUND", "Error message expected") - assert.include( - result.error, - "Network error: Could not communicate", - "Error message expected" - ) - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should default to page 0", async () => { - req.body = { - addresses: [`bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - // Assert current page defaults to 0 - assert.equal(result[0].currentPage, 0) - }) - - it("should process the requested page", async () => { - req.body = { - addresses: [`bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`], - page: 5 - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert current page is same as requested - assert.equal(result[0].currentPage, 5) - }) - - it("should calculate the total number of pages", async () => { - req.body = { - addresses: [`bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(result[0].pagesTotal, 1) - }) - - it("should get details for a single address", async () => { - req.body = { - addresses: [`bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.equal(result.length, 1, "Array with one entry") - assert.hasAllKeys(result[0], [ - "balance", - "balanceSat", - "totalReceived", - "totalReceivedSat", - "totalSent", - "totalSentSat", - "unconfirmedBalance", - "unconfirmedBalanceSat", - "unconfirmedTxApperances", - "txApperances", - "transactions", - "legacyAddress", - "cashAddress", - "currentPage", - "pagesTotal" - ]) - }) - - it("should get details for multiple addresses", async () => { - req.body = { - addresses: [ - `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`, - `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .times(2) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") - }) - }) - - describe("#AddressDetailsSingle", () => { - // details route handler. - const detailsSingle = addressRoute.testableComponents.detailsSingle - - it("should throw 400 if address is empty", async () => { - const result = await detailsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") - }) - - it("should error on an array", async () => { - req.params.address = [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - - const result = await detailsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "address can not be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid address", async () => { - req.params.address = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - const result = await detailsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - - const result = await detailsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.params.address = `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await detailsSingle(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should default to page 0", async () => { - req.params.address = `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert current page defaults to 0 - assert.equal(result.currentPage, 0) - }) - - it("should process the requested page", async () => { - req.params.address = `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - req.query.page = 5 - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsSingle(req, res) - - // Assert current page is same as requested - assert.equal(result.currentPage, 5) - }) - - it("should calculate the total number of pages", async () => { - req.params.address = `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsSingle(req, res) - - assert.equal(result.pagesTotal, 1) - }) - - it("should get details for a single address", async () => { - req.params.address = `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.hasAllKeys(result, [ - "balance", - "balanceSat", - "totalReceived", - "totalReceivedSat", - "totalSent", - "totalSentSat", - "unconfirmedBalance", - "unconfirmedBalanceSat", - "unconfirmedTxApperances", - "txApperances", - "transactions", - "legacyAddress", - "cashAddress", - "currentPage", - "pagesTotal" - ]) - }) - }) - - describe("#AddressUtxoBulk", () => { - // utxo route handler. - const utxoBulk = addressRoute.testableComponents.utxoBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await utxoBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single address", async () => { - req.body = { - address: `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - } - - const result = await utxoBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid address", async () => { - req.body = { - addresses: [`02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - const result = await utxoBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - const result = await utxoBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body = { - addresses: [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api" - - const result = await utxoBulk(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get utxos for a single address", async () => { - req.body = { - addresses: [`bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockUtxoDetails) - } - - // Call the details API. - const result = await utxoBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result, "result should be an array") - - // Each element should have these primary properties. - assert.hasAllKeys(result[0], [ - "utxos", - "legacyAddress", - "cashAddress", - "scriptPubKey" - ]) - - // Validate the UTXO data structure. - assert.hasAnyKeys(result[0].utxos[0], [ - "txid", - "vout", - "amount", - "satoshis", - "height", - "confirmations" - ]) - }) - - it("should get utxos for mulitple addresses", async () => { - req.body = { - addresses: [ - `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`, - `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .times(2) - .reply(200, mockData.mockUtxoDetails) - } - - // Call the details API. - const result = await utxoBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.addresses = testArray - - const result = await utxoBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - }) - - describe("#AddressUtxoSingle", () => { - // details route handler. - const utxoSingle = addressRoute.testableComponents.utxoSingle - - it("should throw 400 if address is empty", async () => { - const result = await utxoSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") - }) - - it("should error on an array", async () => { - req.params.address = [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - - const result = await utxoSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "address can not be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid address", async () => { - req.params.address = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - const result = await utxoSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - - const result = await utxoSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.params.address = `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await utxoSingle(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get details for a single address", async () => { - req.params.address = `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockUtxoDetails) - } - - // Call the details API. - const result = await utxoSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Each element should have these primary properties. - assert.hasAllKeys(result, [ - "utxos", - "legacyAddress", - "cashAddress", - "scriptPubKey" - ]) - - // Validate the UTXO data structure. - assert.hasAnyKeys(result.utxos[0], [ - "txid", - "vout", - "amount", - "satoshis", - "height", - "confirmations" - ]) - }) - }) - - describe("#AddressUnconfirmedBulk", () => { - // unconfirmed route handler. - const unconfirmedBulk = addressRoute.testableComponents.unconfirmedBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await unconfirmedBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single address", async () => { - req.body = { - address: `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - } - - const result = await unconfirmedBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.addresses = testArray - - const result = await unconfirmedBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw an error for an invalid address", async () => { - req.body = { - addresses: [`02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - const result = await unconfirmedBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - const result = await unconfirmedBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body = { - addresses: [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api" - - const result = await unconfirmedBulk(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get unconfirmed data for a single address", async () => { - req.body = { - addresses: [`bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockUtxoDetails) - } - - // Call the details API. - const result = await unconfirmedBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - //console.log(`result[0].utxos: ${util.inspect(result[0].utxos)}`) - - assert.isArray(result, "result should be an array") - - // Dev note: Unconfirmed TXs are hard to test in an integration test because - // the nature of an unconfirmed transation is transient. It quickly becomes - // confirmed and thus should not show up. - }) - - it("should get unconfirmed data for an array of addresses", async () => { - req.body = { - addresses: [ - `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`, - `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockUtxoDetails) - - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockUtxoDetails) - } - - // Call the details API. - const result = await unconfirmedBulk(req, res) - - assert.isArray(result) - }) - }) - - describe("#AddressUnconfirmedSingle", () => { - // details route handler. - const unconfirmedSingle = addressRoute.testableComponents.unconfirmedSingle - - it("should throw 400 if address is empty", async () => { - const result = await unconfirmedSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") - }) - - it("should error on an array", async () => { - req.params.address = [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - - const result = await unconfirmedSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "address can not be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid address", async () => { - req.params.address = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - const result = await unconfirmedSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - - const result = await unconfirmedSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.params.address = `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await unconfirmedSingle(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get details for a single address", async () => { - req.params.address = `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockUtxoDetails) - } - - // Call the details API. - const result = await unconfirmedSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Each element should have these primary properties. - assert.hasAllKeys(result, [ - "utxos", - "legacyAddress", - "cashAddress", - "scriptPubKey" - ]) - - assert.isArray(result.utxos) - }) - }) - - describe("#AddressTransactionsBulk", () => { - // unconfirmed route handler. - const transactionsBulk = addressRoute.testableComponents.transactionsBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await transactionsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single address", async () => { - req.body = { - address: `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - } - - const result = await transactionsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.addresses = testArray - - const result = await transactionsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw an error for an invalid address", async () => { - req.body = { - addresses: [`02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - const result = await transactionsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - const result = await transactionsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body = { - addresses: [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api" - - const result = await transactionsBulk(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should default to page 0", async () => { - req.body = { - addresses: [`bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockTransactions) - } - - // Call the endpoint - const result = await transactionsBulk(req, res) - - // Assert current page defaults to 0 - assert.equal(result[0].currentPage, 0) - }) - - it("should process the requested page", async () => { - req.body = { - addresses: [`bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`], - page: 5 - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockTransactions) - } - - // Call the endpoint - const result = await transactionsBulk(req, res) - - // Assert current page is same as requested - assert.equal(result[0].currentPage, 5) - }) - - it("should get transactions for a single address", async () => { - req.body = { - addresses: [`bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockTransactions) - } - - // Call the details API. - const result = await transactionsBulk(req, res) - - assert.isArray(result, "result should be an array") - - assert.exists(result[0].pagesTotal) - assert.exists(result[0].currentPage) - assert.exists(result[0].txs) - assert.isArray(result[0].txs) - assert.exists(result[0].legacyAddress) - assert.exists(result[0].cashAddress) - }) - - it("should get transactions for an array of addresses", async () => { - req.body = { - addresses: [ - `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`, - `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .times(2) - .reply(200, mockData.mockTransactions) - } - - // Call the details API. - const result = await transactionsBulk(req, res) - - assert.isArray(result, "result should be an array") - - assert.equal(result.length, 2, "Array should have 2 elements") - }) - }) - - describe("#AddressTransactionsSingle", () => { - // details route handler. - const transactionsSingle = - addressRoute.testableComponents.transactionsSingle - - it("should throw 400 if address is empty", async () => { - const result = await transactionsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") - }) - - it("should error on an array", async () => { - req.params.address = [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - - const result = await transactionsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "address can not be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid address", async () => { - req.params.address = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - const result = await transactionsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - - const result = await transactionsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.params.address = `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await transactionsSingle(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should default to page 0", async () => { - req.params.address = `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockTransactions) - } - - // Call the endpoint - const result = await transactionsSingle(req, res) - - // Assert current page defaults to 0 - assert.equal(result.currentPage, 0) - }) - - it("should process the requested page", async () => { - req.params.address = `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - req.query.page = 5 - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockTransactions) - } - - // Call the endpoint - const result = await transactionsSingle(req, res) - - // Assert current page is same as requested - assert.equal(result.currentPage, 5) - }) - - it("should get details for a single address", async () => { - req.params.address = `bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockTransactions) - } - - // Call the details API. - const result = await transactionsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.exists(result.pagesTotal) - assert.exists(result.currentPage) - assert.exists(result.txs) - assert.isArray(result.txs) - assert.exists(result.legacyAddress) - assert.exists(result.cashAddress) - }) - }) - - describe("#AddressFromXPubSingle", () => { - // details route handler. - const fromXPubSingle = addressRoute.testableComponents.fromXPubSingle - - it("should throw 400 if xpub is empty", async () => { - const result = await fromXPubSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "xpub can not be empty") - }) - - it("should error on an array", async () => { - req.params.xpub = [ - `tpubDHTK2jqg73w3GwoiHfAMbMYML1HN8FhrUxD9rFgbSgHXdwwrY6pAFqKDfUHhqw7vreaZty5hPGjb1S7ZPQeMmu6TFHAKfY9tJpYbvaGjPRM` - ] - - const result = await fromXPubSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "xpub can not be an array", - "Proper error message" - ) - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.params.xpub = `tpubDHTK2jqg73w3GwoiHfAMbMYML1HN8FhrUxD9rFgbSgHXdwwrY6pAFqKDfUHhqw7vreaZty5hPGjb1S7ZPQeMmu6TFHAKfY9tJpYbvaGjPRM` - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await fromXPubSingle(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should create an address from xpub", async () => { - req.params.xpub = `tpubDHTK2jqg73w3GwoiHfAMbMYML1HN8FhrUxD9rFgbSgHXdwwrY6pAFqKDfUHhqw7vreaZty5hPGjb1S7ZPQeMmu6TFHAKfY9tJpYbvaGjPRM` - - // Mock the Insight URL for unit tests. - // TODO add unit test - // if (process.env.TEST === "unit") { - // nock(`${process.env.BITCOINCOM_BASEURL}`) - // .get( - // `/txs/?address=bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4&pageNum=0` - // ) - // .reply(200, mockData.mockTransactions) - // } - - // Call the details API. - const result = await fromXPubSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.exists(result.legacyAddress) - assert.exists(result.cashAddress) - }) - }) -}) diff --git a/test/v3/transaction.js b/test/v3/transaction.js deleted file mode 100644 index 2450134..0000000 --- a/test/v3/transaction.js +++ /dev/null @@ -1,333 +0,0 @@ -/* - TESTS FOR THE TRANSACTION.TS LIBRARY - - This test file uses the environment variable TEST to switch between unit - and integration tests. By default, TEST is set to 'unit'. Set this variable - to 'integration' to run the tests against BCH mainnet. - - TODO: - -See "should throw an error for an invalid txid" for detailsSingle: - --The error handler should be refactored to return an intelligent error message, - instead of the 503 error it is returning now. -*/ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const transactionRoute = require("../../src/routes/v3/insight/transaction") -const nock = require("nock") // HTTP mocking - -let originalEnvVars // Used during transition from integration to unit tests. - -// Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/transaction-mocks") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -describe("#Transactions", () => { - let req, res - - before(() => { - // Save existing environment variables. - originalEnvVars = { - BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, - RPC_BASEURL: process.env.RPC_BASEURL, - RPC_USERNAME: process.env.RPC_USERNAME, - RPC_PASSWORD: process.env.RPC_PASSWORD - } - - // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" - } - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - - // Explicitly reset the parmas and body. - req.params = {} - req.body = {} - req.query = {} - - // Activate nock if it's inactive. - if (!nock.isActive()) nock.activate() - }) - - afterEach(() => { - // Clean up HTTP mocks. - nock.cleanAll() // clear interceptor list. - nock.restore() - }) - - after(() => { - // Restore any pre-existing environment variables. - process.env.BITCOINCOM_BASEURL = originalEnvVars.BITCOINCOM_BASEURL - process.env.RPC_BASEURL = originalEnvVars.RPC_BASEURL - process.env.RPC_USERNAME = originalEnvVars.RPC_USERNAME - process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD - }) - - describe("#root", async () => { - // root route handler. - const root = transactionRoute.testableComponents.root - - it("should respond to GET for base route", async () => { - const result = root(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(result.status, "transaction", "Returns static string") - }) - }) - - describe("#detailsBulk", async () => { - const detailsBulk = transactionRoute.testableComponents.detailsBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await detailsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "txids needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single txid", async () => { - req.body = { - txids: `6f235bd3a689f03c11969cd649ccad592462ca958bc519a30194e7a67b349a40` - } - - const result = await detailsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "txids needs to be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid txid", async () => { - const fakeTXID = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/tx/${fakeTXID}`) - .reply(400, { - result: { error: "parameter 1 must be hexadecimal string" } - }) - } - - req.body = { - txids: [fakeTXID] - } - - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - }) - - it("should process a single txid", async () => { - const txid = `2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/tx/${txid}`) - .reply(200, mockData.mockDetails) - } - - req.body = { - txids: [txid] - } - - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAnyKeys(result[0], [ - "txid", - "version", - "locktime", - "vin", - "vout", - "blockhash", - "blockheight", - "confirmations", - "time", - "blocktime", - "valueOut", - "size", - "valueIn", - "fees" - ]) - }) - - it("should process a multiple txids", async () => { - const txid1 = `2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266` - const txid2 = `2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/tx/${txid1}`) - .reply(200, mockData.mockDetails) - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/tx/${txid2}`) - .reply(200, mockData.mockDetails) - } - - req.body = { - txids: [txid1, txid2] - } - - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAnyKeys(result[0], [ - "txid", - "version", - "locktime", - "vin", - "vout", - "blockhash", - "blockheight", - "confirmations", - "time", - "blocktime", - "valueOut", - "size", - "valueIn", - "fees" - ]) - }) - }) - - describe("#detailsSingle", () => { - // details route handler. - const detailsSingle = transactionRoute.testableComponents.detailsSingle - - it("should throw 400 if txid is empty", async () => { - const result = await detailsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") - }) - - it("should error on an array", async () => { - req.params.txid = [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - - const result = await detailsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "txid can not be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid txid", async () => { - if (process.env.TEST !== "unit") { - req.params.txid = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - const result = await detailsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // The error handling code should probably be updated to respond with a better - // error message. - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "parameter 1 must be hexadecimal string", - "Proper error message" - ) - } - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.params.txid = `6f235bd3a689f03c11969cd649ccad592462ca958bc519a30194e7a67b349a40` - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await detailsSingle(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get details for a single txid", async () => { - const txid = `2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266` - req.params.txid = txid - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/tx/${txid}`) - .reply(200, mockData.mockDetails) - } - - // Call the details API. - const result = await detailsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.hasAllKeys(result, [ - "txid", - "version", - "locktime", - "vin", - "vout", - "blockhash", - "blockheight", - "confirmations", - "time", - "blocktime", - "valueOut", - "size", - "valueIn", - "fees" - ]) - assert.isArray(result.vin) - assert.isArray(result.vout) - }) - }) -})