From f4f142dc484fa229c4c4b0160973404e71a48025 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Sat, 28 Oct 2023 09:17:48 -0700 Subject: [PATCH] fix(tests): Increased test coverage to 100% --- src/adapters/ipfs/index.js | 2 +- src/controllers/rest-api/ipfs/controller.js | 20 +- src/controllers/rest-api/ipfs/index.js | 4 +- test/unit/adapters/ipfs-index.adapter.unit.js | 76 ++++++++ .../ipfs/ipfs.rest.controller.unit.js | 179 ++++++++++++++++++ .../rest-api/ipfs/ipfs.rest.router.unit.js | 78 ++++++++ test/unit/mocks/adapters/index.js | 5 +- 7 files changed, 351 insertions(+), 13 deletions(-) create mode 100644 test/unit/controllers/rest-api/ipfs/ipfs.rest.controller.unit.js create mode 100644 test/unit/controllers/rest-api/ipfs/ipfs.rest.router.unit.js diff --git a/src/adapters/ipfs/index.js b/src/adapters/ipfs/index.js index 3998303..62cdeb1 100644 --- a/src/adapters/ipfs/index.js +++ b/src/adapters/ipfs/index.js @@ -174,10 +174,10 @@ class IPFS { // If the peer couldn't be found, skip. if (!thisPeer.length) { thisRelay.name = '' + thisRelay.description = '' continue } - thisRelay.name = thisPeer[0].data.jsonLd.name thisRelay.description = thisPeer[0].data.jsonLd.description } diff --git a/src/controllers/rest-api/ipfs/controller.js b/src/controllers/rest-api/ipfs/controller.js index 5300f4a..e919331 100644 --- a/src/controllers/rest-api/ipfs/controller.js +++ b/src/controllers/rest-api/ipfs/controller.js @@ -4,8 +4,6 @@ import wlogger from '../../../adapters/wlogger.js' -let _this - class IpfsRESTControllerLib { constructor (localConfig = {}) { // Dependency Injection. @@ -26,7 +24,11 @@ class IpfsRESTControllerLib { // this.UserModel = this.adapters.localdb.Users // this.userUseCases = this.useCases.user - _this = this + // Bind 'this' object to all subfunctions + this.getStatus = this.getStatus.bind(this) + this.getPeers = this.getPeers.bind(this) + this.getRelays = this.getRelays.bind(this) + this.handleError = this.handleError.bind(this) } /** @@ -41,13 +43,13 @@ class IpfsRESTControllerLib { */ async getStatus (ctx) { try { - const status = await _this.adapters.ipfs.getStatus() + const status = await this.adapters.ipfs.getStatus() ctx.body = { status } } catch (err) { wlogger.error('Error in ipfs/controller.js/getStatus(): ') // ctx.throw(422, err.message) - _this.handleError(ctx, err) + this.handleError(ctx, err) } } @@ -56,26 +58,26 @@ class IpfsRESTControllerLib { try { const showAll = ctx.request.body.showAll - const peers = await _this.adapters.ipfs.getPeers(showAll) + const peers = await this.adapters.ipfs.getPeers(showAll) ctx.body = { peers } } catch (err) { wlogger.error('Error in ipfs/controller.js/getPeers(): ') // ctx.throw(422, err.message) - _this.handleError(ctx, err) + this.handleError(ctx, err) } } // Get data about the known Circuit Relays. Hydrate with data from peers list. async getRelays (ctx) { try { - const relays = await _this.adapters.ipfs.getRelays() + const relays = await this.adapters.ipfs.getRelays() ctx.body = { relays } } catch (err) { wlogger.error('Error in ipfs/controller.js/getRelays(): ') // ctx.throw(422, err.message) - _this.handleError(ctx, err) + this.handleError(ctx, err) } } diff --git a/src/controllers/rest-api/ipfs/index.js b/src/controllers/rest-api/ipfs/index.js index c3b65e4..3e3b14f 100644 --- a/src/controllers/rest-api/ipfs/index.js +++ b/src/controllers/rest-api/ipfs/index.js @@ -11,7 +11,7 @@ import Validators from '../middleware/validators.js' // let _this -class BchRouter { +class IpfsRouter { constructor (localConfig = {}) { // Dependency Injection. this.adapters = localConfig.adapters @@ -66,4 +66,4 @@ class BchRouter { } // module.exports = BchRouter -export default BchRouter +export default IpfsRouter diff --git a/test/unit/adapters/ipfs-index.adapter.unit.js b/test/unit/adapters/ipfs-index.adapter.unit.js index 2d2f8b0..8557fef 100644 --- a/test/unit/adapters/ipfs-index.adapter.unit.js +++ b/test/unit/adapters/ipfs-index.adapter.unit.js @@ -141,4 +141,80 @@ describe('#IPFS-adapter-index', () => { assert.equal(result.length, inArray.length - 2) }) }) + + describe('#getPeers', () => { + it('should return an array of current JSON data about each peer when showAll is true', async () => { + // Mock dependencies + uut.ipfsCoordAdapter.ipfsCoord = { + thisNode: { + peerData: [{ from: 'a', data: { jsonLd: { name: 'a', protocol: 'test', version: '1' } } }, { from: 'b' }] + }, + adapters: { + ipfs: { + getPeers: async () => ['a', 'b'] + } + } + } + + const result = await uut.getPeers(true) + + assert.isArray(result) + }) + + it('should catch, report, and throw errors', async () => { + try { + // Force an error + uut.ipfsCoordAdapter.ipfsCoord = { + thisNode: {}, + adapters: { + ipfs: { + getPeers: async () => { throw new Error('test error') } + } + } + } + + await uut.getPeers() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err.message: ', err.message) + assert.include(err.message, 'test error') + } + }) + }) + + describe('#getRelays', () => { + it('should return known relays', () => { + uut.ipfsCoordAdapter.ipfsCoord = { + thisNode: { + peerData: [{ from: 'a', data: { jsonLd: { name: 'a', description: 'test' } } }, { from: 'b' }], + relayData: [{ ipfsId: 'c' }, { ipfsId: 'a' }] + } + } + + const result = uut.getRelays() + // console.log('result: ', result) + + assert.isArray(result) + assert.equal(result.length, 2) + assert.property(result[0], 'name') + assert.property(result[0], 'description') + assert.property(result[1], 'name') + assert.property(result[1], 'description') + }) + + it('should catch, report, and throw errors', () => { + try { + // Force an error + uut.ipfsCoordAdapter.ipfsCoord = { thisNode: {} } + + uut.getRelays() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err.message: ', err.message) + assert.include(err.message, 'Cannot read') + } + }) + }) }) diff --git a/test/unit/controllers/rest-api/ipfs/ipfs.rest.controller.unit.js b/test/unit/controllers/rest-api/ipfs/ipfs.rest.controller.unit.js new file mode 100644 index 0000000..132f950 --- /dev/null +++ b/test/unit/controllers/rest-api/ipfs/ipfs.rest.controller.unit.js @@ -0,0 +1,179 @@ +/* + Unit tests for the REST API handler for the /ipfs endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local libraries +import IpfsApiController from '../../../../../src/controllers/rest-api/ipfs/controller.js' +import adapters from '../../../mocks/adapters/index.js' +import UseCasesMock from '../../../mocks/use-cases/index.js' + +import { context as mockContext } from '../../../mocks/ctx-mock.js' +let uut +let sandbox +let ctx + +describe('#IPFS REST API', () => { + before(async () => { + }) + + beforeEach(() => { + const useCases = new UseCasesMock() + + uut = new IpfsApiController({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new IpfsApiController() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating /ipfs REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new IpfsApiController({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating /ipfs REST Controller.' + ) + } + }) + }) + + describe('#GET /status', () => { + it('should return 422 status on biz logic error', async () => { + try { + // Force an error + sandbox.stub(uut.adapters.ipfs, 'getStatus').rejects(new Error('test error')) + + await uut.getStatus(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(err.status, 422) + assert.include(err.message, 'test error') + } + }) + + it('should return 200 status on success', async () => { + // Mock dependencies + sandbox.stub(uut.adapters.ipfs, 'getStatus').resolves({ a: 'b' }) + + await uut.getStatus(ctx) + // console.log('ctx.body: ', ctx.body) + + assert.property(ctx.body, 'status') + assert.equal(ctx.body.status.a, 'b') + }) + }) + + describe('#POST /peers', () => { + it('should return 422 status on biz logic error', async () => { + try { + // Force an error + sandbox.stub(uut.adapters.ipfs, 'getPeers').rejects(new Error('test error')) + + ctx.request.body = { + showAll: true + } + + await uut.getPeers(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(err.status, 422) + assert.include(err.message, 'test error') + } + }) + + it('should return 200 status on success', async () => { + // Mock dependencies + sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves({ a: 'b' }) + + ctx.request.body = { + showAll: true + } + + await uut.getPeers(ctx) + // console.log('ctx.body: ', ctx.body) + + assert.property(ctx.body, 'peers') + assert.equal(ctx.body.peers.a, 'b') + }) + }) + + describe('#POST /relays', () => { + it('should return 422 status on biz logic error', async () => { + try { + // Force an error + sandbox.stub(uut.adapters.ipfs, 'getRelays').rejects(new Error('test error')) + + await uut.getRelays(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(err.status, 422) + assert.include(err.message, 'test error') + } + }) + + it('should return 200 status on success', async () => { + // Mock dependencies + sandbox.stub(uut.adapters.ipfs, 'getRelays').resolves({ a: 'b' }) + + await uut.getRelays(ctx) + // console.log('ctx.body: ', ctx.body) + + assert.property(ctx.body, 'relays') + assert.equal(ctx.body.relays.a, 'b') + }) + }) + + describe('#handleError', () => { + it('should still throw error if there is no message', () => { + try { + const err = { + status: 404 + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Not Found') + } + }) + + it('should throw error with message', () => { + try { + const err = { + status: 422, + message: 'test error' + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'test error') + } + }) + }) +}) diff --git a/test/unit/controllers/rest-api/ipfs/ipfs.rest.router.unit.js b/test/unit/controllers/rest-api/ipfs/ipfs.rest.router.unit.js new file mode 100644 index 0000000..b2b4f13 --- /dev/null +++ b/test/unit/controllers/rest-api/ipfs/ipfs.rest.router.unit.js @@ -0,0 +1,78 @@ +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' +import UseCasesMock from '../../../mocks/use-cases/index.js' +import IpfsRouter from '../../../../../src/controllers/rest-api/ipfs/index.js' +// const app = require('../../../mocks/app-mock') + +let uut +let sandbox +// let ctx + +// const mockContext = require('../../../../unit/mocks/ctx-mock').context + +describe('#IPFS-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new IpfsRouter({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + // ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new IpfsRouter() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating IPFS REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new IpfsRouter({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating IPFS REST Controller.' + ) + } + }) + }) + + describe('#attach', () => { + it('should throw an error if app is not passed in.', () => { + try { + uut.attach() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Must pass app object when attaching REST API controllers.' + ) + } + }) + }) +}) diff --git a/test/unit/mocks/adapters/index.js b/test/unit/mocks/adapters/index.js index ffa3ad6..f17772c 100644 --- a/test/unit/mocks/adapters/index.js +++ b/test/unit/mocks/adapters/index.js @@ -26,7 +26,10 @@ class IpfsCoordAdapter { const ipfs = { ipfsAdapter: new IpfsAdapter(), - ipfsCoordAdapter: new IpfsCoordAdapter() + ipfsCoordAdapter: new IpfsCoordAdapter(), + getStatus: async () => {}, + getPeers: async () => {}, + getRelays: async () => {} } ipfs.ipfs = ipfs.ipfsAdapter.ipfs