From 9e01425815359d8a6edbf0c14a729358f8eb82e4 Mon Sep 17 00:00:00 2001 From: Paulius Date: Thu, 11 Jan 2024 09:44:54 +0000 Subject: [PATCH] HYP-72: unit tests transactions controller (#73) * HYP-72: unit tests transactions controller * HYP-72: version bump. --- package-lock.json | 4 +- package.json | 2 +- .../health/__tests__/index.test.ts | 35 ++++++- .../v1/certificate/__tests__/index.test.ts | 4 + .../v1/transaction/__tests__/index.test.ts | 97 +++++++++++++++++++ src/controllers/v1/transaction/index.ts | 7 +- 6 files changed, 140 insertions(+), 9 deletions(-) create mode 100644 src/controllers/v1/transaction/__tests__/index.test.ts diff --git a/package-lock.json b/package-lock.json index df3403e..9c11eb8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@digicatapult/dscp-hyproof-api", - "version": "0.7.23", + "version": "0.7.24", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@digicatapult/dscp-hyproof-api", - "version": "0.7.23", + "version": "0.7.24", "license": "Apache-2.0", "dependencies": { "@polkadot/api": "^10.11.2", diff --git a/package.json b/package.json index a06976e..e55ea21 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@digicatapult/dscp-hyproof-api", - "version": "0.7.23", + "version": "0.7.24", "description": "An OpenAPI API service for DSCP", "main": "src/index.ts", "type": "module", diff --git a/src/controllers/health/__tests__/index.test.ts b/src/controllers/health/__tests__/index.test.ts index f260df8..0c5cc53 100644 --- a/src/controllers/health/__tests__/index.test.ts +++ b/src/controllers/health/__tests__/index.test.ts @@ -1,7 +1,36 @@ import { expect } from 'chai' -describe('health controller', () => { - it('placeholder', () => { - expect(1).to.equal(1) +import Ipfs from '../../../lib/ipfs.js' +import Database from '../../../lib/db/index.js' +import Identity from '../../../lib/services/identity.js' +import ChainNode from '../../../lib/chainNode.js' +import { HealthController } from '../index.js' +import { Env } from '../../../env.js' +import { ServiceWatcher } from '../../../lib/service-watcher/index.js' +import { ServiceUnavailable } from '../../../lib/error-handler/index.js' + +describe('/health', () => { + let response: any + let controller: HealthController + + const database: Database = new Database() + const identity: Identity = new Identity(new Env()) + const node: ChainNode = new ChainNode(new Env(), database) + const ipfs: Ipfs = new Ipfs(new Env()) + const watcher: ServiceWatcher = new ServiceWatcher(new Env(), node, identity, ipfs) + + before(() => { + controller = new HealthController(watcher) + }) + + describe('get() - GET /', () => { + beforeEach(async () => { + response = await controller.get().catch((err) => err) + }) + + it('throws ServiceUnavailable error', () => { + expect(response).to.be.instanceOf(ServiceUnavailable) + expect(response.code).to.equal(503) + }) }) }) diff --git a/src/controllers/v1/certificate/__tests__/index.test.ts b/src/controllers/v1/certificate/__tests__/index.test.ts index d6e01ac..e5bb40a 100644 --- a/src/controllers/v1/certificate/__tests__/index.test.ts +++ b/src/controllers/v1/certificate/__tests__/index.test.ts @@ -49,6 +49,10 @@ describe('v1/certificate', () => { afterEach(() => { stubs.submitRunProcess.resetHistory() stubs.prepareRunProcess.resetHistory() + stubs.build.resetHistory() + stubs.getMemberByAlias.resetHistory() + stubs.getSelfAddress.resetHistory() + stubs.insert.resetHistory() }) describe('postDraft() - POST /', () => { diff --git a/src/controllers/v1/transaction/__tests__/index.test.ts b/src/controllers/v1/transaction/__tests__/index.test.ts new file mode 100644 index 0000000..7a32c43 --- /dev/null +++ b/src/controllers/v1/transaction/__tests__/index.test.ts @@ -0,0 +1,97 @@ +import { expect } from 'chai' +import sinon from 'sinon' + +import Database from '../../../../lib/db/index.js' +import { TransactionController } from '../index.js' +import { TransactionState } from '../../../../models/transaction.js' +import { NotFound } from '../../../../lib/error-handler/index.js' + +export const example = { + id: 'transaction-controller-test', + api_type: 'certificate', + local_id: 'test-cert-1', + state: 'submitted', + transaction_type: 'initiate_cert', +} + +describe('v1/transaction', () => { + let response: any + let controller: TransactionController + + const database: Database = new Database() + const getStub = sinon.stub(database, 'get' as any).callsFake(() => [{ ...example, id: 'test-1' }, example]) + + before(() => { + controller = new TransactionController(database) + }) + + afterEach(() => { + getStub.resetHistory() + }) + + describe('get() - GET /', () => { + describe('query by api_type', () => { + ;['certificate'].forEach((api_type: any) => { + it(` - [${api_type}]`, async () => { + response = await controller.get(api_type) + + expect(getStub.lastCall.args[0]).to.equal('transaction') + expect(getStub.lastCall.args[1]).to.to.deep.contain({ api_type }) + expect(response[1]).to.deep.contain(example) + }) + }) + }) + + describe('query by transaction state', () => { + ;['submitted', 'inBlock', 'finalised', 'failed'].forEach((state) => { + it(`returns transactions based on state - [${state}]`, async () => { + response = await controller.get(undefined, state as TransactionState) + + expect(getStub.lastCall.args[0]).to.equal('transaction') + expect(response[1]).to.deep.contain(example) + }) + }) + }) + + it('returns transactions by updated_since query param', async () => { + response = await controller.get(undefined, undefined, '2024-01-10') + + expect(getStub.lastCall.args[0]).to.equal('transaction') + }) + + it('returns all transactions without filters', () => { + expect(response.length).to.equal(2) + }) + }) + + describe('getById() - GET /{id}', () => { + beforeEach(async () => { + getStub.callsFake((_, args) => [{ ...example, ...args }]) + response = await controller.getById('test-id').catch((err) => err) + }) + + describe('if transaction can not be found', () => { + beforeEach(async () => { + getStub.callsFake(() => []) + + response = await controller.getById('not-found-transaction-id').catch((err) => err) + }) + + it('throws NotFound error', () => { + expect(response).to.be.instanceOf(NotFound) + expect(response.code).to.equal(404) + expect(response.message).to.equal('transaction [not-found-transaction-id] not found') + }) + }) + + it('returns transaction by id', async () => { + expect(response).to.deep.contain({ + id: 'test-id', + api_type: 'certificate', + local_id: 'test-cert-1', + state: 'submitted', + transaction_type: 'initiate_cert', + }) + }) + }) +}) diff --git a/src/controllers/v1/transaction/index.ts b/src/controllers/v1/transaction/index.ts index 769704b..3cbc29a 100644 --- a/src/controllers/v1/transaction/index.ts +++ b/src/controllers/v1/transaction/index.ts @@ -33,7 +33,7 @@ export class TransactionController extends Controller { @Response(400, 'Request was invalid') @Response(404, 'Item not found') @Get('/') - public async getAllTransactions( + public async get( @Query() api_type?: TransactionApiType, @Query() state?: TransactionState, @Query() updated_since?: DATE @@ -53,8 +53,9 @@ export class TransactionController extends Controller { */ @Response(404, 'Item not found') @Get('{id}') - public async getTransaction(@Path() id: UUID): Promise { - const transaction = await this.db.get('transaction', { id }).then((transactions) => transactions[0]) + public async getById(@Path() id: UUID): Promise { + const [transaction] = await this.db.get('transaction', { id }) + if (!transaction) throw new NotFound(`transaction [${id}]`) return transaction }