This repository was archived by the owner on Jan 5, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Unit test controller and service of each core Module #75
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
34060de
test: messaging,ctypes,contacts module tests and fixes 721,718
c9fee3e
refac: remove deprecated email property
14b823c
refac: remove deprecated email property
db3e677
test: faucet
6286091
chore: reset lockfile
f9f5bbe
fix: await for promise based tests
d81f1de
chore: update to jest 26 , ts-jest 26
9d6e735
Update src/contacts/contacts.module.spec.ts
LeonFLK 5610a59
Update src/ctypes/ctypes.module.spec.ts
LeonFLK 1293a01
Update src/ctypes/ctypes.module.spec.ts
LeonFLK 7bc2fe2
test: mocking consistency
b6cd4b6
chore: reset upgrades
9cba8bb
chore: upgrades
2d4fbc8
chore: requested changes
f2110d0
test: mock handling and split of positive
3510310
test: updated integration
6ac29ee
chore: changed key
b8aa825
chore:updated log
5b162ee
fix: updated mongoose scheman
1573942
test: integration test for invalid address handling
rflechtner File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,378 @@ | ||
| import { Test } from '@nestjs/testing' | ||
| import { AuthGuard } from '../auth/auth.guard' | ||
| import { | ||
| BadRequestException, | ||
| NotFoundException, | ||
| } from '@nestjs/common/exceptions' | ||
| import { getModelToken } from '@nestjs/mongoose' | ||
| import { ContactsController } from './contacts.controller' | ||
| import { | ||
| ContactsService, | ||
| ContactDB, | ||
| Contact, | ||
| } from './interfaces/contacts.interfaces' | ||
| import { MongoDbMContactsService } from './mongodb-contacts.service' | ||
| import Optional from 'typescript-optional' | ||
|
|
||
| jest.mock('@kiltprotocol/sdk-js/build/crypto/Crypto', () => { | ||
| return { | ||
| hashStr: jest.fn((): string => '0x1'), | ||
| verify: jest.fn((): boolean => true), | ||
| } | ||
| }) | ||
|
|
||
| describe('Contact Module', () => { | ||
| const testContact: Contact = { | ||
| metaData: { | ||
| name: 'Test', | ||
| }, | ||
| publicIdentity: { | ||
| address: '5CKq9ovoHUFb5Qg2q7YmQ2waNhgQm4C22qwb1Wgehnn2eBcb', | ||
| boxPublicKeyAsHex: | ||
| '0x5640c86ce5a99b1caf37882197b17572fa8ac33db8387861ef24dd2b497edd43', | ||
| serviceAddress: 'https://services.devnet.kilt.io:443/messaging', | ||
| }, | ||
| } | ||
| const testDID: object = { | ||
| id: 'did:kilt:5CKq9ovoHUFb5Qg2q7YmQ2waNhgQm4C22qwb1Wgehnn2eBcb', | ||
| '@context': 'https://w3id.org/did/v1', | ||
| authentication: [ | ||
| { | ||
| type: 'Ed25519SignatureAuthentication2018', | ||
| publicKey: [ | ||
| 'did:kilt:5CKq9ovoHUFb5Qg2q7YmQ2waNhgQm4C22qwb1Wgehnn2eBcb#key-1', | ||
| ], | ||
| }, | ||
| ], | ||
| publicKey: [ | ||
| { | ||
| id: 'did:kilt:5CKq9ovoHUFb5Qg2q7YmQ2waNhgQm4C22qwb1Wgehnn2eBcb#key-1', | ||
| type: 'Ed25519VerificationKey2018', | ||
| controller: 'did:kilt:5CKq9ovoHUFb5Qg2q7YmQ2waNhgQm4C22qwb1Wgehnn2eBcb', | ||
| publicKeyHex: | ||
| '0x0b893d72cdfb31a60af86f9519ab6892f2a3ced3cc5a36763ff2c60feb28fbad', | ||
| }, | ||
| { | ||
| id: 'did:kilt:5CKq9ovoHUFb5Qg2q7YmQ2waNhgQm4C22qwb1Wgehnn2eBcb#key-2', | ||
| type: 'X25519Salsa20Poly1305Key2018', | ||
| controller: 'did:kilt:5CKq9ovoHUFb5Qg2q7YmQ2waNhgQm4C22qwb1Wgehnn2eBcb', | ||
| publicKeyHex: | ||
| '0x5640c86ce5a99b1caf37882197b17572fa8ac33db8387861ef24dd2b497edd43', | ||
| }, | ||
| ], | ||
| service: [ | ||
| { | ||
| type: 'KiltMessagingService', | ||
| serviceEndpoint: 'https://services.devnet.kilt.io:443/messaging', | ||
| }, | ||
| ], | ||
| } | ||
| const signature = | ||
| '0x00aad52336444c0263a22c22f2b99bbcdfc3a6912b5d085c11df01de2bb13dae7c9adf89ecb58f9a32dd021c1c0c1ff0ed39ba361a85f350714b58f15cbd617607' | ||
| const contactWithDid: Contact = { | ||
| ...testContact, | ||
| did: testDID, | ||
| signature, | ||
| } | ||
| const noSigContact: Contact = { | ||
| ...testContact, | ||
| did: testDID, | ||
| } | ||
| const badSigContact: Contact = { ...contactWithDid, signature: '0x1' } | ||
|
|
||
| const address = testContact.publicIdentity.address | ||
| describe('Controller', () => { | ||
| let contactsController: ContactsController | ||
| let contactsService: ContactsService | ||
|
|
||
| const mockedHashStr = require('@kiltprotocol/sdk-js/build/crypto/Crypto') | ||
| .hashStr | ||
| const mockedVerify = require('@kiltprotocol/sdk-js/build/crypto/Crypto') | ||
| .verify | ||
|
|
||
| const fakeContactService: ContactsService = { | ||
| add: jest.fn( | ||
| async (): Promise<void> => { | ||
| return | ||
| } | ||
| ), | ||
| findByAddress: jest.fn( | ||
| async (): Promise<Optional<Contact>> => | ||
| Optional.ofNullable<Contact>(null) | ||
| ), | ||
| list: jest.fn(async (): Promise<Contact[]> => []), | ||
| removeAll: jest.fn( | ||
| async (): Promise<void> => { | ||
| return | ||
| } | ||
| ), | ||
| } | ||
|
|
||
| beforeEach(async () => { | ||
| const moduleRef = await Test.createTestingModule({ | ||
| controllers: [ContactsController], | ||
| providers: [ | ||
| { | ||
| provide: 'ContactsService', | ||
| useValue: fakeContactService, | ||
| }, | ||
| ], | ||
| }) | ||
| .overrideGuard(AuthGuard) | ||
| .useValue({ canActivate: () => true }) | ||
| .compile() | ||
| contactsController = moduleRef.get(ContactsController) | ||
| contactsService = moduleRef.get('ContactsService') | ||
| }) | ||
|
|
||
| afterEach(() => jest.clearAllMocks()) | ||
|
|
||
| describe('add', () => { | ||
| it('calls contactService.add on valid Contact without Did', async () => { | ||
| const addSpy = jest.spyOn(contactsService, 'add') | ||
| expect(await contactsController.add(testContact)).toEqual(undefined) | ||
| expect(mockedHashStr).not.toHaveBeenCalled() | ||
| expect(mockedVerify).not.toHaveBeenCalled() | ||
| expect(addSpy).toHaveBeenCalledTimes(1) | ||
| expect(addSpy).toHaveBeenCalledWith(testContact) | ||
| }) | ||
| it('calls throws Exception on invalid Contact', async () => { | ||
| const addSpy = jest.spyOn(contactsService, 'add') | ||
| const noAddressContact: Contact = { | ||
| ...testContact, | ||
| publicIdentity: { ...testContact.publicIdentity, address: '' }, | ||
| } | ||
| const noPubKeyContact: Contact = { | ||
| ...testContact, | ||
| publicIdentity: { | ||
| ...testContact.publicIdentity, | ||
| boxPublicKeyAsHex: '', | ||
| }, | ||
| } | ||
| const noNameContact: Contact = { | ||
| ...testContact, | ||
| metaData: { | ||
| ...testContact.metaData, | ||
| name: '', | ||
| }, | ||
| } | ||
| await expect(contactsController.add(noAddressContact)).rejects.toThrow( | ||
| BadRequestException | ||
| ) | ||
| await expect(contactsController.add(noPubKeyContact)).rejects.toThrow( | ||
| BadRequestException | ||
| ) | ||
| await expect(contactsController.add(noNameContact)).rejects.toThrow( | ||
| BadRequestException | ||
| ) | ||
| expect(mockedHashStr).not.toHaveBeenCalled() | ||
| expect(mockedVerify).not.toHaveBeenCalled() | ||
| expect(addSpy).not.toHaveBeenCalled() | ||
| }) | ||
|
|
||
| it('calls contactService.add on valid Contact with Did', async () => { | ||
| const addSpy = jest.spyOn(contactsService, 'add') | ||
| expect(await contactsController.add(contactWithDid)).toEqual(undefined) | ||
| expect(addSpy).toHaveBeenCalledTimes(1) | ||
| expect(addSpy).toHaveBeenCalledWith(contactWithDid) | ||
| expect(mockedHashStr).toHaveBeenCalledTimes(1) | ||
| expect(mockedVerify).toHaveBeenCalledTimes(1) | ||
| expect(mockedHashStr).toHaveBeenCalledWith(JSON.stringify(testDID)) | ||
| expect(mockedVerify).toHaveBeenCalledWith( | ||
| '0x1', | ||
| contactWithDid.signature, | ||
| contactWithDid.publicIdentity.address | ||
| ) | ||
| }) | ||
| it('rejects contact with did if signature is missing or invalid', async () => { | ||
| const addSpy = jest.spyOn(contactsService, 'add') | ||
| mockedVerify.mockReturnValue(false) | ||
| await expect(contactsController.add(noSigContact)).rejects.toThrow( | ||
| BadRequestException | ||
| ) | ||
| await expect(contactsController.add(badSigContact)).rejects.toThrow( | ||
| BadRequestException | ||
| ) | ||
| expect(addSpy).not.toHaveBeenCalled() | ||
| expect(mockedHashStr).toHaveBeenCalledTimes(1) | ||
| expect(mockedVerify).toHaveBeenCalledTimes(1) | ||
| }) | ||
| }) | ||
| describe('list', () => { | ||
| it('returns all registered Contacts', async () => { | ||
| const serviceListSpy = jest | ||
| .spyOn(contactsService, 'list') | ||
| .mockResolvedValue([testContact]) | ||
| await expect(contactsController.list()).resolves.toEqual([testContact]) | ||
| expect(serviceListSpy).toHaveBeenCalledTimes(1) | ||
| expect(serviceListSpy).toHaveBeenCalledWith() | ||
| serviceListSpy.mockRestore() | ||
| }) | ||
| }) | ||
| describe('findByKey', () => { | ||
| it('gets the Contact for the given address', async () => { | ||
| const findByAddressSpy = jest | ||
| .spyOn(contactsService, 'findByAddress') | ||
| .mockResolvedValue(Optional.ofNullable(testContact)) | ||
| expect( | ||
| await contactsController.findByKey(testContact.publicIdentity.address) | ||
| ).toEqual(testContact) | ||
| expect(findByAddressSpy).toHaveBeenCalledTimes(1) | ||
| expect(findByAddressSpy).toHaveBeenCalledWith( | ||
| testContact.publicIdentity.address | ||
| ) | ||
| findByAddressSpy.mockRestore() | ||
| }) | ||
| }) | ||
| describe('removeAll', () => { | ||
| it('calls contactService.removeAll()', async () => { | ||
| contactsController.removeAll() | ||
| expect(contactsService.removeAll).toHaveBeenCalledTimes(1) | ||
| }) | ||
| }) | ||
| describe('getDidDocument', () => { | ||
| it('gets the contact for the given address and returns the did', async () => { | ||
| const findByAddressSpy = jest | ||
| .spyOn(contactsService, 'findByAddress') | ||
| .mockResolvedValue(Optional.ofNullable(contactWithDid)) | ||
| expect(await contactsController.getDidDocument(address)).toEqual( | ||
| contactWithDid.did | ||
| ) | ||
| expect(findByAddressSpy).toHaveBeenCalledWith(address) | ||
| findByAddressSpy.mockResolvedValue(Optional.ofNullable(testContact)) | ||
| await expect( | ||
| contactsController.getDidDocument(address) | ||
| ).rejects.toThrow(NotFoundException) | ||
| expect(findByAddressSpy).toHaveBeenCalledWith(address) | ||
| findByAddressSpy.mockRestore() | ||
| }) | ||
| }) | ||
| }) | ||
|
|
||
| class ContactModel { | ||
| public static find = jest | ||
| .fn() | ||
| .mockReturnValue({ exec: async (): Promise<ContactDB[]> => [] }) | ||
| public static findOne = jest | ||
| .fn() | ||
| .mockReturnValue({ exec: async (): Promise<ContactDB> => null }) | ||
| public static deleteMany = jest.fn().mockReturnValue({ | ||
| exec: async () => { | ||
| return | ||
| }, | ||
| }) | ||
| public static save = jest.fn().mockImplementation(async object => object) | ||
| public save = jest | ||
| .fn() | ||
| .mockImplementation(async () => ContactModel.save(this)) | ||
|
|
||
| constructor(data: Contact) { | ||
| return Object.assign(this, data as ContactDB) | ||
| } | ||
| } | ||
| describe('Contacts Service', () => { | ||
| let contactsService: ContactsService | ||
|
|
||
| beforeEach(async () => { | ||
| const contactServiceProvider = { | ||
| provide: 'ContactService', | ||
| useClass: MongoDbMContactsService, | ||
| } | ||
|
|
||
| const moduleRef = await Test.createTestingModule({ | ||
| providers: [ | ||
| contactServiceProvider, | ||
| { provide: getModelToken('Contact'), useValue: ContactModel }, | ||
| ], | ||
| }).compile() | ||
|
|
||
| contactsService = moduleRef.get('ContactService') | ||
| }) | ||
| afterEach(() => jest.clearAllMocks()) | ||
|
|
||
| describe('add', () => { | ||
| it('creates a Contact and saves it', async () => { | ||
| const saveSpy = jest.spyOn(contactsService['contactModel'], 'save') | ||
| const findOneSpy = jest.spyOn( | ||
| contactsService['contactModel'], | ||
| 'findOne' | ||
| ) | ||
| await contactsService.add(testContact) | ||
| expect(findOneSpy).toHaveBeenCalledWith({ | ||
| 'publicIdentity.address': testContact.publicIdentity.address, | ||
| }) | ||
| expect(saveSpy).toHaveBeenCalledTimes(1) | ||
| }) | ||
| it('updates a Contact and saves it', async () => { | ||
| const saveSpy = jest.spyOn(contactsService['contactModel'], 'save') | ||
| const findOneSpy = jest.spyOn( | ||
| contactsService['contactModel'], | ||
| 'findOne' | ||
| ) | ||
| await contactsService.add(contactWithDid) | ||
| expect(findOneSpy).toHaveBeenCalledWith({ | ||
| 'publicIdentity.address': testContact.publicIdentity.address, | ||
| }) | ||
| expect(saveSpy).toHaveBeenCalledTimes(1) | ||
| }) | ||
| }) | ||
| describe('findByAddress', () => { | ||
| it('queries database and converts match', async () => { | ||
| const findOneSpy = jest | ||
| .spyOn(contactsService['contactModel'], 'findOne') | ||
| .mockReturnValue({ exec: async (): Promise<ContactDB> => null }) | ||
| expect(await contactsService.findByAddress(address)).toEqual( | ||
| Optional.ofNullable<Contact>(null) | ||
| ) | ||
| expect(findOneSpy).toHaveBeenCalledWith({ | ||
| 'publicIdentity.address': address, | ||
| }) | ||
| findOneSpy.mockReturnValue({ | ||
| exec: async (): Promise<ContactDB> => { | ||
| return testContact as ContactDB | ||
| }, | ||
| }) | ||
| expect(await contactsService.findByAddress(address)).toEqual( | ||
| Optional.ofNullable<Contact>(testContact) | ||
| ) | ||
| expect(findOneSpy).toHaveBeenCalledWith({ | ||
| 'publicIdentity.address': address, | ||
| }) | ||
| expect(findOneSpy).toHaveBeenCalledTimes(2) | ||
| findOneSpy.mockRestore() | ||
| }) | ||
| }) | ||
| describe('list', () => { | ||
| it('queries database with inclusive parameter and converts matches', async () => { | ||
| const findSpy = jest | ||
| .spyOn(contactsService['contactModel'], 'find') | ||
| .mockReturnValue({ | ||
| exec: async (): Promise<ContactDB[]> => { | ||
| return [testContact as ContactDB] | ||
| }, | ||
| }) | ||
| expect(await contactsService.list()).toEqual([testContact]) | ||
| expect(findSpy).toHaveBeenCalledWith() | ||
| findSpy.mockReturnValue({ | ||
| exec: async (): Promise<ContactDB[]> => { | ||
| return [] | ||
| }, | ||
| }) | ||
| expect(await contactsService.list()).toEqual([]) | ||
| expect(findSpy).toHaveBeenCalledTimes(2) | ||
| findSpy.mockRestore() | ||
| }) | ||
| }) | ||
| describe('removeAll', () => { | ||
| it('calls deleteMany with inclusive parameter', async () => { | ||
| const deleteManySpy = jest.spyOn( | ||
| contactsService['contactModel'], | ||
| 'deleteMany' | ||
| ) | ||
| await contactsService.removeAll() | ||
| expect(deleteManySpy).toHaveBeenCalledTimes(1) | ||
| expect(deleteManySpy).toHaveBeenCalledWith({}) | ||
| }) | ||
| }) | ||
| }) | ||
| }) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.