From 3142487dd25bf3fb36f0c979fe5232830b60a6a7 Mon Sep 17 00:00:00 2001 From: Berend Sliedrecht <berend@animo.id> Date: Thu, 18 Jan 2024 15:37:24 +0100 Subject: [PATCH] test(ssi): include unit test for credential functionality Signed-off-by: Berend Sliedrecht <berend@animo.id> --- apps/ssi-abstraction/jest.config.js | 1 + .../anoncredsCredentials.controller.spec.ts | 138 ++++++++----- .../anoncredsCredentials.controller.ts | 24 +++ .../test/anoncredsCredentials.e2e-spec.ts | 191 ++++++++++++++++-- 4 files changed, 282 insertions(+), 72 deletions(-) diff --git a/apps/ssi-abstraction/jest.config.js b/apps/ssi-abstraction/jest.config.js index 5ece9fc..b8e668f 100644 --- a/apps/ssi-abstraction/jest.config.js +++ b/apps/ssi-abstraction/jest.config.js @@ -17,6 +17,7 @@ export default { }, ], }, + testPathIgnorePatterns: ['<rootDir>/dist'], extensionsToTreatAsEsm: ['.ts'], moduleNameMapper: { // ESM modules require `.js` extension to be specified, but Jest doesn't work with them diff --git a/apps/ssi-abstraction/src/agent/anoncredsCredentials/__tests__/anoncredsCredentials.controller.spec.ts b/apps/ssi-abstraction/src/agent/anoncredsCredentials/__tests__/anoncredsCredentials.controller.spec.ts index 4652f57..89c6c84 100644 --- a/apps/ssi-abstraction/src/agent/anoncredsCredentials/__tests__/anoncredsCredentials.controller.spec.ts +++ b/apps/ssi-abstraction/src/agent/anoncredsCredentials/__tests__/anoncredsCredentials.controller.spec.ts @@ -24,75 +24,101 @@ describe('AnonCredsCredentialsController', () => { credentialsController = moduleRef.get(AnonCredsCredentialsController); }); - describe('get all', () => { - it('should get all the credential records of the agent', async () => { - const result: Array<CredentialExchangeRecord> = []; - jest.spyOn(credentialsService, 'getAll').mockResolvedValue(result); + it('get all', async () => { + const result: Array<CredentialExchangeRecord> = []; + jest.spyOn(credentialsService, 'getAll').mockResolvedValue(result); - const event = await credentialsController.getAll({ - tenantId: 'some-id', - }); + const event = await credentialsController.getAll({ + tenantId: 'some-id', + }); + + expect(event.data).toStrictEqual(result); + }); - expect(event.data).toStrictEqual(result); + it('get all offers', async () => { + const result: Array<CredentialExchangeRecord> = []; + jest.spyOn(credentialsService, 'getAllOffers').mockResolvedValue(result); + + const event = await credentialsController.getAllOffers({ + tenantId: 'some-id', }); + + expect(event.data).toStrictEqual(result); }); - describe('get by id', () => { - it('should get a credential record by id', async () => { - const result: CredentialExchangeRecord | null = null; - jest.spyOn(credentialsService, 'getById').mockResolvedValue(result); + it('get all requests', async () => { + const result: Array<CredentialExchangeRecord> = []; + jest.spyOn(credentialsService, 'getAllRequests').mockResolvedValue(result); - const event = await credentialsController.getById({ - tenantId: 'some-id', - credentialRecordId: 'some-id', - }); + const event = await credentialsController.getAllRequests({ + tenantId: 'some-id', + }); + + expect(event.data).toStrictEqual(result); + }); - expect(event.data).toStrictEqual(result); + it('get by id', async () => { + const result: CredentialExchangeRecord | null = null; + jest.spyOn(credentialsService, 'getById').mockResolvedValue(result); + + const event = await credentialsController.getById({ + tenantId: 'some-id', + credentialRecordId: 'some-id', }); + + expect(event.data).toStrictEqual(result); }); - describe('offer', () => { - it('should offer a credential', async () => { - const result: CredentialExchangeRecord = new CredentialExchangeRecord({ - state: CredentialState.Done, - threadId: 'some-id', - protocolVersion: 'v2', - }); - jest.spyOn(credentialsService, 'offer').mockResolvedValue(result); - - const event = await credentialsController.offer({ - tenantId: 'some-id', - connectionId: 'some-id', - credentialDefinitionId: 'some-id', - attributes: [ - { name: 'Name', value: 'Berend', mimeType: 'application/text' }, - { name: 'Age', value: '25' }, - ], - }); - - expect(event.data).toStrictEqual(result); + it('delete by id', async () => { + const result = {}; + jest.spyOn(credentialsService, 'deleteById').mockResolvedValue(result); + + const event = await credentialsController.deleteById({ + tenantId: 'some-id', + credentialRecordId: 'some-id-that-does-not-exist', }); + + expect(event.data).toStrictEqual(result); }); - describe('offer to self', () => { - it('should offer a credential to self', async () => { - const result: CredentialExchangeRecord = new CredentialExchangeRecord({ - state: CredentialState.Done, - threadId: 'some-id', - protocolVersion: 'v2', - }); - jest.spyOn(credentialsService, 'offerToSelf').mockResolvedValue(result); - - const event = await credentialsController.offerToSelf({ - tenantId: 'some-id', - credentialDefinitionId: 'some-id', - attributes: [ - { name: 'Name', value: 'Berend', mimeType: 'application/text' }, - { name: 'Age', value: '25' }, - ], - }); - - expect(event.data).toStrictEqual(result); + it('offer', async () => { + const result: CredentialExchangeRecord = new CredentialExchangeRecord({ + state: CredentialState.Done, + threadId: 'some-id', + protocolVersion: 'v2', + }); + jest.spyOn(credentialsService, 'offer').mockResolvedValue(result); + + const event = await credentialsController.offer({ + tenantId: 'some-id', + connectionId: 'some-id', + credentialDefinitionId: 'some-id', + attributes: [ + { name: 'Name', value: 'Berend', mimeType: 'application/text' }, + { name: 'Age', value: '25' }, + ], }); + + expect(event.data).toStrictEqual(result); + }); + + it('offer to self', async () => { + const result: CredentialExchangeRecord = new CredentialExchangeRecord({ + state: CredentialState.Done, + threadId: 'some-id', + protocolVersion: 'v2', + }); + jest.spyOn(credentialsService, 'offerToSelf').mockResolvedValue(result); + + const event = await credentialsController.offerToSelf({ + tenantId: 'some-id', + credentialDefinitionId: 'some-id', + attributes: [ + { name: 'Name', value: 'Berend', mimeType: 'application/text' }, + { name: 'Age', value: '25' }, + ], + }); + + expect(event.data).toStrictEqual(result); }); }); diff --git a/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.controller.ts b/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.controller.ts index c0caea3..a434e59 100644 --- a/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.controller.ts +++ b/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.controller.ts @@ -15,6 +15,10 @@ import { EventAnonCredsCredentialRequestGetAllInput, EventAnonCredsCredentialsDeleteById, EventAnonCredsCredentialsDeleteByIdInput, + EventAnonCredsCredentialOfferGetById, + EventAnonCredsCredentialOfferGetByIdInput, + EventAnonCredsCredentialRequestGetById, + EventAnonCredsCredentialRequestGetByIdInput, } from '@ocm/shared'; import { AnonCredsCredentialsService } from './anoncredsCredentials.service.js'; @@ -63,6 +67,26 @@ export class AnonCredsCredentialsController { ); } + @MessagePattern(EventAnonCredsCredentialOfferGetById.token) + public async getOfferById( + options: EventAnonCredsCredentialOfferGetByIdInput, + ): Promise<EventAnonCredsCredentialOfferGetById> { + return new EventAnonCredsCredentialOfferGetById( + await this.credentialsService.getOfferById(options), + options.tenantId, + ); + } + + @MessagePattern(EventAnonCredsCredentialRequestGetById.token) + public async getRequestById( + options: EventAnonCredsCredentialRequestGetByIdInput, + ): Promise<EventAnonCredsCredentialRequestGetById> { + return new EventAnonCredsCredentialRequestGetById( + await this.credentialsService.getRequestById(options), + options.tenantId, + ); + } + @MessagePattern(EventAnonCredsCredentialsDeleteById.token) public async deleteById( options: EventAnonCredsCredentialsDeleteByIdInput, diff --git a/apps/ssi-abstraction/test/anoncredsCredentials.e2e-spec.ts b/apps/ssi-abstraction/test/anoncredsCredentials.e2e-spec.ts index 12250e6..f63159f 100644 --- a/apps/ssi-abstraction/test/anoncredsCredentials.e2e-spec.ts +++ b/apps/ssi-abstraction/test/anoncredsCredentials.e2e-spec.ts @@ -1,17 +1,31 @@ import type { INestApplication } from '@nestjs/common'; import type { ClientProxy } from '@nestjs/microservices'; import type { - EventDidcommAnonCredsCredentialsGetAllInput, - EventDidcommAnonCredsCredentialsGetByIdInput, + EventAnonCredsCredentialRequestGetAllInput, + EventAnonCredsCredentialsGetAllInput, + EventAnonCredsCredentialsGetByIdInput, EventDidcommAnonCredsCredentialsOfferToSelfInput, + EventAnonCredsCredentialOfferGetAllInput, + EventAnonCredsCredentialOfferGetByIdInput, + EventAnonCredsCredentialRequestGetByIdInput, + EventAnonCredsCredentialsDeleteByIdInput, } from '@ocm/shared'; -import { AutoAcceptCredential } from '@aries-framework/core'; +import { + AutoAcceptCredential, + CredentialExchangeRecord, +} from '@aries-framework/core'; import { ClientsModule, Transport } from '@nestjs/microservices'; import { Test } from '@nestjs/testing'; import { - EventDidcommAnonCredsCredentialsGetAll, - EventDidcommAnonCredsCredentialsGetById, + EventAnonCredsCredentialsDeleteById, + EventAnonCredsCredentialOfferGetAll, + EventAnonCredsCredentialOfferGetById, + EventAnonCredsCredentialRequestGetAll, + EventAnonCredsCredentialRequestGetById, + EventAnonCredsCredentialsGetAll, + EventAnonCredsCredentialsGetById, + EventAnonCredsProofsDeleteById, EventDidcommAnonCredsCredentialsOfferToSelf, } from '@ocm/shared'; import { firstValueFrom } from 'rxjs'; @@ -104,29 +118,81 @@ describe('Credentials', () => { client.close(); }); - it(EventDidcommAnonCredsCredentialsGetAll.token, async () => { + it(EventAnonCredsCredentialsGetAll.token, async () => { + const response$ = client.send< + EventAnonCredsCredentialsGetAll, + EventAnonCredsCredentialsGetAllInput + >(EventAnonCredsCredentialsGetAll.token, { tenantId }); + const response = await firstValueFrom(response$); + const eventInstance = EventAnonCredsCredentialsGetAll.fromEvent(response); + + expect(eventInstance.instance).toEqual(expect.arrayContaining([])); + }); + + it(EventAnonCredsCredentialOfferGetAll.token, async () => { const response$ = client.send< - EventDidcommAnonCredsCredentialsGetAll, - EventDidcommAnonCredsCredentialsGetAllInput - >(EventDidcommAnonCredsCredentialsGetAll.token, { tenantId }); + EventAnonCredsCredentialOfferGetAll, + EventAnonCredsCredentialOfferGetAllInput + >(EventAnonCredsCredentialOfferGetAll.token, { tenantId }); const response = await firstValueFrom(response$); const eventInstance = - EventDidcommAnonCredsCredentialsGetAll.fromEvent(response); + EventAnonCredsCredentialOfferGetAll.fromEvent(response); expect(eventInstance.instance).toEqual(expect.arrayContaining([])); }); - it(EventDidcommAnonCredsCredentialsGetById.token, async () => { + it(EventAnonCredsCredentialOfferGetById.token, async () => { const response$ = client.send< - EventDidcommAnonCredsCredentialsGetById, - EventDidcommAnonCredsCredentialsGetByIdInput - >(EventDidcommAnonCredsCredentialsGetById.token, { + EventAnonCredsCredentialOfferGetById, + EventAnonCredsCredentialOfferGetByIdInput + >(EventAnonCredsCredentialOfferGetById.token, { tenantId, - credentialRecordId: 'some-id', + credentialOfferId: 'some-id-that-does-not-exist', + }); + const response = await firstValueFrom(response$); + const eventInstance = + EventAnonCredsCredentialOfferGetById.fromEvent(response); + + expect(eventInstance.instance).toBeNull(); + }); + + it(EventAnonCredsCredentialRequestGetAll.token, async () => { + const response$ = client.send< + EventAnonCredsCredentialRequestGetAll, + EventAnonCredsCredentialRequestGetAllInput + >(EventAnonCredsCredentialRequestGetAll.token, { tenantId }); + const response = await firstValueFrom(response$); + const eventInstance = + EventAnonCredsCredentialRequestGetAll.fromEvent(response); + + expect(eventInstance.instance).toEqual(expect.arrayContaining([])); + }); + + it(EventAnonCredsCredentialRequestGetById.token, async () => { + const response$ = client.send< + EventAnonCredsCredentialRequestGetById, + EventAnonCredsCredentialRequestGetByIdInput + >(EventAnonCredsCredentialRequestGetById.token, { + tenantId, + credentialRequestId: 'some-id-that-does-not-exist', }); const response = await firstValueFrom(response$); const eventInstance = - EventDidcommAnonCredsCredentialsGetById.fromEvent(response); + EventAnonCredsCredentialRequestGetById.fromEvent(response); + + expect(eventInstance.instance).toBeNull(); + }); + + it(EventAnonCredsCredentialsGetById.token, async () => { + const response$ = client.send< + EventAnonCredsCredentialsGetById, + EventAnonCredsCredentialsGetByIdInput + >(EventAnonCredsCredentialsGetById.token, { + tenantId, + credentialRecordId: 'some-id', + }); + const response = await firstValueFrom(response$); + const eventInstance = EventAnonCredsCredentialsGetById.fromEvent(response); expect(eventInstance.instance).toEqual(null); }); @@ -154,4 +220,97 @@ describe('Credentials', () => { autoAcceptCredential: AutoAcceptCredential.Always, }); }); + + it(EventAnonCredsProofsDeleteById.token, async () => { + let credentialExchangeRecord: CredentialExchangeRecord | undefined = + undefined; + + // GET ALL + { + const response$ = client.send< + EventAnonCredsCredentialsGetAll, + EventAnonCredsCredentialsGetAllInput + >(EventAnonCredsCredentialsGetAll.token, { tenantId }); + const response = await firstValueFrom(response$); + const eventInstance = EventAnonCredsCredentialsGetAll.fromEvent(response); + + expect(eventInstance.instance).toEqual(expect.arrayContaining([])); + } + + // Offer a credential + + { + const attributes = [ + { name: 'Name', value: 'Berend' }, + { name: 'Age', value: '25' }, + ]; + + const response$ = client.send< + EventDidcommAnonCredsCredentialsOfferToSelf, + EventDidcommAnonCredsCredentialsOfferToSelfInput + >(EventDidcommAnonCredsCredentialsOfferToSelf.token, { + tenantId, + credentialDefinitionId, + attributes, + }); + + const response = await firstValueFrom(response$); + const eventInstance = + EventDidcommAnonCredsCredentialsOfferToSelf.fromEvent(response); + + expect(eventInstance.instance).toMatchObject({ + autoAcceptCredential: AutoAcceptCredential.Always, + }); + + credentialExchangeRecord = eventInstance.instance; + } + + // GET THE CREDENTIAL BY ID + { + const response$ = client.send< + EventAnonCredsCredentialsGetById, + EventAnonCredsCredentialsGetByIdInput + >(EventAnonCredsCredentialsGetById.token, { + tenantId, + credentialRecordId: credentialExchangeRecord.id, + }); + const response = await firstValueFrom(response$); + const eventInstance = + EventAnonCredsCredentialsGetById.fromEvent(response); + + expect(eventInstance.instance).toBeInstanceOf(CredentialExchangeRecord); + } + + // DELETE THE CREDENTIAL + { + const response$ = client.send< + EventAnonCredsCredentialsDeleteById, + EventAnonCredsCredentialsDeleteByIdInput + >(EventAnonCredsCredentialsDeleteById.token, { + tenantId, + credentialRecordId: credentialExchangeRecord.id, + }); + const response = await firstValueFrom(response$); + const eventInstance = + EventAnonCredsCredentialsDeleteById.fromEvent(response); + + expect(eventInstance).toMatchObject({}); + } + + // GET THE CREDENTIAL BY ID + { + const response$ = client.send< + EventAnonCredsCredentialsGetById, + EventAnonCredsCredentialsGetByIdInput + >(EventAnonCredsCredentialsGetById.token, { + tenantId, + credentialRecordId: credentialExchangeRecord.id, + }); + const response = await firstValueFrom(response$); + const eventInstance = + EventAnonCredsCredentialsGetById.fromEvent(response); + + expect(eventInstance.instance).toBeNull(); + } + }); }); -- GitLab