From 564f45f5476899f87f0bc24e6cd5a4dbb67f77a8 Mon Sep 17 00:00:00 2001 From: Raphael Flechtner Date: Fri, 17 Apr 2020 12:21:26 +0200 Subject: [PATCH 01/11] feat: better blockchain api mocking --- src/blockchain/Mocktest.spec.ts | 33 +++++ .../__mocks__/BlockchainApiConnection.ts | 138 +++++++++++++++++- 2 files changed, 166 insertions(+), 5 deletions(-) create mode 100644 src/blockchain/Mocktest.spec.ts diff --git a/src/blockchain/Mocktest.spec.ts b/src/blockchain/Mocktest.spec.ts new file mode 100644 index 000000000..c2765ed38 --- /dev/null +++ b/src/blockchain/Mocktest.spec.ts @@ -0,0 +1,33 @@ +import BN from 'bn.js' +import { Identity } from '..' +import { makeTransfer } from '../balance/Balance.chain' +import getCached from '../blockchainApiConnection/BlockchainApiConnection' + +jest.mock('../blockchainApiConnection/BlockchainApiConnection') + +it('succeeds', async () => { + require('../blockchainApiConnection/BlockchainApiConnection').__setDefaultResult( + true + ) + const alice = Identity.buildFromURI('//Alice') + const amount = new BN(1000) + const blockchain = await getCached() + const transfer = blockchain.api.tx.balances.transfer(alice.address, amount) + const result = await blockchain.submitTx(alice, transfer) + expect(result).toMatchObject({ isFinalized: true }) +}) + +it('succeeds then fails', async () => { + require('../blockchainApiConnection/BlockchainApiConnection').__queueResults([ + true, + false, + ]) + const alice = Identity.buildFromURI('//Alice') + const amount = new BN(1000) + expect(makeTransfer(alice, alice.address, amount)).resolves.toMatchObject({ + isFinalized: true, + }) + expect(makeTransfer(alice, alice.address, amount)).rejects.toThrow( + 'Transaction failed' + ) +}) diff --git a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts index da5d469d6..273385daf 100644 --- a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts +++ b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts @@ -5,12 +5,140 @@ /** * Dummy comment needed for correct doc display, do not remove */ -import Blockchain from '../../blockchain/Blockchain' +import Blockchain, { IBlockchainApi } from '../../blockchain/Blockchain' +import { ApiPromise, SubmittableResult } from '@polkadot/api' +import { Option, Tuple, Vec, Text } from '@polkadot/types' +import BN from 'bn.js' +import { SubmittableExtrinsic } from '@polkadot/api/promise/types' +import { ExtrinsicStatus } from '@polkadot/types/interfaces' -jest.mock('../../blockchain/Blockchain') +const BlockchainApiConnection = jest.requireActual('../BlockchainApiConnection') -export async function getCached() { - return Promise.resolve(Blockchain) +BlockchainApiConnection.getCached = getCached +BlockchainApiConnection.__queueResults = __queueResults +BlockchainApiConnection.__setDefaultResult = __setDefaultResult + +module.exports = BlockchainApiConnection +module.exports.default = BlockchainApiConnection.getCached + +async function getCached( + _: string = BlockchainApiConnection.DEFAULT_WS_ADDRESS +): Promise { + if (!BlockchainApiConnection.instance) { + BlockchainApiConnection.instance = Promise.resolve( + new Blockchain(mocked_api as ApiPromise) + ) + } + return BlockchainApiConnection.instance +} + +const TxresultsQueue: SubmittableResult[] = [] +let defaultTxResult: SubmittableResult = __makeSubmittableResult(true) + +class MockSubmittableExtrinsic { + result: SubmittableResult + method: string = 'mock tx' + + constructor(result: SubmittableResult) { + this.result = result + } + + public sign(_a: any, _b: any, _c: any) { + return this + } + + public send(callable: Function) { + if (callable) { + callable(this.result) + } + } +} + +function __getMockSubmittableExtrinsic(): SubmittableExtrinsic { + const result: SubmittableResult = TxresultsQueue.shift() || defaultTxResult + return (new MockSubmittableExtrinsic(result) as any) as SubmittableExtrinsic } -export default getCached +function __makeSubmittableResult(success: boolean): SubmittableResult { + const status: ExtrinsicStatus = { + type: success ? 'Finalized' : 'Invalid', + isFinalized: success, + isDropped: false, + isInvalid: !success, + isUsurped: false, + isFuture: false, + isReady: true, + } as any + + return new SubmittableResult({ + status, + }) +} + +function __queueResults(results: boolean[]) { + results.forEach(success => { + TxresultsQueue.push(__makeSubmittableResult(success)) + }) +} + +function __setDefaultResult(success: boolean) { + defaultTxResult = __makeSubmittableResult(success) +} + +const mocked_api: any = { + tx: { + attestation: { + add: jest.fn((claimHash, _cTypeHash) => { + return __getMockSubmittableExtrinsic() + }), + }, + balances: { + transfer: jest.fn(() => __getMockSubmittableExtrinsic()), + }, + ctype: { + add: jest.fn((hash, signature) => { + return __getMockSubmittableExtrinsic() + }), + }, + delegation: { + createRoot: jest.fn((rootId, _ctypeHash) => { + return __getMockSubmittableExtrinsic() + }), + revokeRoot: jest.fn(rootId => { + return __getMockSubmittableExtrinsic() + }), + revokeDelegation: jest.fn(delegationId => { + return __getMockSubmittableExtrinsic() + }), + }, + did: { + add: jest.fn((sign_key, box_key, doc_ref) => { + return __getMockSubmittableExtrinsic() + }), + remove: jest.fn(() => { + return __getMockSubmittableExtrinsic() + }), + }, + }, + query: { + system: { accountNonce: jest.fn(() => new Text('12345')) }, + attestation: { + delegatedAttestations: jest.fn(), + attestations: jest.fn(), + }, + balances: { + freeBalance: jest.fn((account: string) => new BN(0)), + }, + ctype: { + cTYPEs: jest.fn(hash => true), + }, + delegation: { + root: jest.fn((rootId: string) => new Option(Tuple, null)), + delegations: jest.fn((delegationId: string) => new Option(Tuple, null)), + children: jest.fn((id: string) => new Vec(Text, [])), + }, + did: { + dIDs: jest.fn(id => new Option(Tuple, null)), + }, + }, +} From 7fbe9842667cb879d6214625f94856a92917e40f Mon Sep 17 00:00:00 2001 From: Raphael Flechtner Date: Fri, 17 Apr 2020 13:22:18 +0200 Subject: [PATCH 02/11] feat: exporting mock_api for query return values --- src/blockchain/Mocktest.spec.ts | 78 +++++++++++++------ .../__mocks__/BlockchainApiConnection.ts | 25 +++--- 2 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/blockchain/Mocktest.spec.ts b/src/blockchain/Mocktest.spec.ts index c2765ed38..908b774a8 100644 --- a/src/blockchain/Mocktest.spec.ts +++ b/src/blockchain/Mocktest.spec.ts @@ -1,33 +1,67 @@ import BN from 'bn.js' +import { Tuple, Option, U8a, Text } from '@polkadot/types' import { Identity } from '..' import { makeTransfer } from '../balance/Balance.chain' import getCached from '../blockchainApiConnection/BlockchainApiConnection' +import { queryByAddress } from '../did/Did.chain' jest.mock('../blockchainApiConnection/BlockchainApiConnection') -it('succeeds', async () => { - require('../blockchainApiConnection/BlockchainApiConnection').__setDefaultResult( - true - ) - const alice = Identity.buildFromURI('//Alice') - const amount = new BN(1000) - const blockchain = await getCached() - const transfer = blockchain.api.tx.balances.transfer(alice.address, amount) - const result = await blockchain.submitTx(alice, transfer) - expect(result).toMatchObject({ isFinalized: true }) +describe('tx mocks', () => { + it('tx succeeds', async () => { + require('../blockchainApiConnection/BlockchainApiConnection').__setDefaultResult( + true + ) + const alice = Identity.buildFromURI('//Alice') + const amount = new BN(1000) + const blockchain = await getCached() + const transfer = blockchain.api.tx.balances.transfer(alice.address, amount) + const result = await blockchain.submitTx(alice, transfer) + expect(result).toMatchObject({ isFinalized: true }) + }) + + it('tx succeeds then fails', async () => { + require('../blockchainApiConnection/BlockchainApiConnection').__queueResults( + [true, false] + ) + const alice = Identity.buildFromURI('//Alice') + const amount = new BN(1000) + await expect( + makeTransfer(alice, alice.address, amount) + ).resolves.toMatchObject({ + isFinalized: true, + }) + await expect(makeTransfer(alice, alice.address, amount)).rejects.toThrow( + 'Transaction failed' + ) + }) }) -it('succeeds then fails', async () => { - require('../blockchainApiConnection/BlockchainApiConnection').__queueResults([ - true, - false, - ]) - const alice = Identity.buildFromURI('//Alice') - const amount = new BN(1000) - expect(makeTransfer(alice, alice.address, amount)).resolves.toMatchObject({ - isFinalized: true, +describe('mock query result', () => { + beforeAll(async () => { + require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api.query.did.dIDs.mockReturnValue( + new Option( + Tuple, + new Tuple( + // (publicBoxKey, publicSigningKey, documentStore?) + [Text, Text, U8a], + ['0x987', '0x123', '0x687474703a2f2f6d794449442e6b696c742e696f'] + ) + ) + ) + // would also work: + // ```ts + // const bc: any = await getCached() + // bc.api.query.did.dIDs.mockReturnValue(...) + // ``` + }) + + it('works', async () => { + await expect(queryByAddress('0xwertzui')).resolves.toMatchObject({ + documentStore: 'http://myDID.kilt.io', + identifier: 'did:kilt:0xwertzui', + publicBoxKey: '0x123', + publicSigningKey: '0x987', + }) }) - expect(makeTransfer(alice, alice.address, amount)).rejects.toThrow( - 'Transaction failed' - ) }) diff --git a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts index 273385daf..08915acc4 100644 --- a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts +++ b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts @@ -14,19 +14,12 @@ import { ExtrinsicStatus } from '@polkadot/types/interfaces' const BlockchainApiConnection = jest.requireActual('../BlockchainApiConnection') -BlockchainApiConnection.getCached = getCached -BlockchainApiConnection.__queueResults = __queueResults -BlockchainApiConnection.__setDefaultResult = __setDefaultResult - -module.exports = BlockchainApiConnection -module.exports.default = BlockchainApiConnection.getCached - async function getCached( _: string = BlockchainApiConnection.DEFAULT_WS_ADDRESS ): Promise { if (!BlockchainApiConnection.instance) { BlockchainApiConnection.instance = Promise.resolve( - new Blockchain(mocked_api as ApiPromise) + new Blockchain(__mocked_api as ApiPromise) ) } return BlockchainApiConnection.instance @@ -85,7 +78,7 @@ function __setDefaultResult(success: boolean) { defaultTxResult = __makeSubmittableResult(success) } -const mocked_api: any = { +const __mocked_api: any = { tx: { attestation: { add: jest.fn((claimHash, _cTypeHash) => { @@ -133,12 +126,20 @@ const mocked_api: any = { cTYPEs: jest.fn(hash => true), }, delegation: { - root: jest.fn((rootId: string) => new Option(Tuple, null)), - delegations: jest.fn((delegationId: string) => new Option(Tuple, null)), + root: jest.fn((rootId: string) => new Option(Tuple)), + delegations: jest.fn((delegationId: string) => new Option(Tuple)), children: jest.fn((id: string) => new Vec(Text, [])), }, did: { - dIDs: jest.fn(id => new Option(Tuple, null)), + dIDs: jest.fn(id => new Option(Tuple)), }, }, } + +BlockchainApiConnection.getCached = getCached +BlockchainApiConnection.__queueResults = __queueResults +BlockchainApiConnection.__setDefaultResult = __setDefaultResult +BlockchainApiConnection.__mocked_api = __mocked_api + +module.exports = BlockchainApiConnection +module.exports.default = BlockchainApiConnection.getCached From 4c55264b77ed650fb8cf9a811af526e626e8d13a Mon Sep 17 00:00:00 2001 From: wischli Date: Fri, 17 Apr 2020 16:31:06 +0200 Subject: [PATCH 03/11] fix: add runtimeMetadata to api mock --- .../__mocks__/BlockchainApiConnection.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts index 08915acc4..6fe9ec6ab 100644 --- a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts +++ b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts @@ -134,6 +134,11 @@ const __mocked_api: any = { dIDs: jest.fn(id => new Option(Tuple)), }, }, + runtimeMetadata: { + asV4: { + modules: [], + }, + }, } BlockchainApiConnection.getCached = getCached From dd34de858b182e96dbd36c812ce96bc650b4842d Mon Sep 17 00:00:00 2001 From: wischli Date: Fri, 17 Apr 2020 16:32:32 +0200 Subject: [PATCH 04/11] style: add camelCase to TxResultsQueue --- .../__mocks__/BlockchainApiConnection.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts index 6fe9ec6ab..466b8011e 100644 --- a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts +++ b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts @@ -25,7 +25,7 @@ async function getCached( return BlockchainApiConnection.instance } -const TxresultsQueue: SubmittableResult[] = [] +const TxResultsQueue: SubmittableResult[] = [] let defaultTxResult: SubmittableResult = __makeSubmittableResult(true) class MockSubmittableExtrinsic { @@ -48,7 +48,7 @@ class MockSubmittableExtrinsic { } function __getMockSubmittableExtrinsic(): SubmittableExtrinsic { - const result: SubmittableResult = TxresultsQueue.shift() || defaultTxResult + const result: SubmittableResult = TxResultsQueue.shift() || defaultTxResult return (new MockSubmittableExtrinsic(result) as any) as SubmittableExtrinsic } @@ -70,7 +70,7 @@ function __makeSubmittableResult(success: boolean): SubmittableResult { function __queueResults(results: boolean[]) { results.forEach(success => { - TxresultsQueue.push(__makeSubmittableResult(success)) + TxResultsQueue.push(__makeSubmittableResult(success)) }) } From 9bc9a85174f63ae1605727a896174bcc27b9e570 Mon Sep 17 00:00:00 2001 From: wischli Date: Fri, 17 Apr 2020 16:33:27 +0200 Subject: [PATCH 05/11] chore: add default did query mock --- .../__mocks__/BlockchainApiConnection.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts index 466b8011e..eb8ca2a71 100644 --- a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts +++ b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts @@ -7,10 +7,12 @@ */ import Blockchain, { IBlockchainApi } from '../../blockchain/Blockchain' import { ApiPromise, SubmittableResult } from '@polkadot/api' -import { Option, Tuple, Vec, Text } from '@polkadot/types' +import { Option, Tuple, Vec, Text, U8a } from '@polkadot/types' import BN from 'bn.js' import { SubmittableExtrinsic } from '@polkadot/api/promise/types' import { ExtrinsicStatus } from '@polkadot/types/interfaces' +import { Codec } from '@polkadot/types/types' +import { stringToHex } from '@polkadot/util' const BlockchainApiConnection = jest.requireActual('../BlockchainApiConnection') @@ -131,7 +133,20 @@ const __mocked_api: any = { children: jest.fn((id: string) => new Vec(Text, [])), }, did: { - dIDs: jest.fn(id => new Option(Tuple)), + dIDs: jest.fn( + (address: string): Option => + new Option( + Tuple, + new Tuple( + [Text, Text, U8a], + [ + 'publicSigningKey', // publicSigningKey + 'publicBoxKey', // publicBoxKey + stringToHex('http://myDID.kilt.io'), // document store + ] + ) + ) + ), }, }, runtimeMetadata: { From cb58b97624dbd5b5369f1fd1a7741a76942d292d Mon Sep 17 00:00:00 2001 From: wischli Date: Fri, 17 Apr 2020 16:36:07 +0200 Subject: [PATCH 06/11] refactor: propose test improvements --- src/blockchain/Mocktest.spec.ts | 70 +++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/src/blockchain/Mocktest.spec.ts b/src/blockchain/Mocktest.spec.ts index 908b774a8..41cf981a4 100644 --- a/src/blockchain/Mocktest.spec.ts +++ b/src/blockchain/Mocktest.spec.ts @@ -1,5 +1,6 @@ import BN from 'bn.js' import { Tuple, Option, U8a, Text } from '@polkadot/types' +import { stringToHex } from '@polkadot/util' import { Identity } from '..' import { makeTransfer } from '../balance/Balance.chain' import getCached from '../blockchainApiConnection/BlockchainApiConnection' @@ -8,24 +9,30 @@ import { queryByAddress } from '../did/Did.chain' jest.mock('../blockchainApiConnection/BlockchainApiConnection') describe('tx mocks', () => { + const alice = Identity.buildFromURI('//Alice') + const amount = new BN(1000) it('tx succeeds', async () => { require('../blockchainApiConnection/BlockchainApiConnection').__setDefaultResult( true ) - const alice = Identity.buildFromURI('//Alice') - const amount = new BN(1000) const blockchain = await getCached() const transfer = blockchain.api.tx.balances.transfer(alice.address, amount) const result = await blockchain.submitTx(alice, transfer) expect(result).toMatchObject({ isFinalized: true }) }) + it('tx fails', async () => { + require('../blockchainApiConnection/BlockchainApiConnection').__setDefaultResult( + false + ) + await expect(makeTransfer(alice, alice.address, amount)).rejects.toThrow( + 'Transaction failed' + ) + }) it('tx succeeds then fails', async () => { require('../blockchainApiConnection/BlockchainApiConnection').__queueResults( [true, false] ) - const alice = Identity.buildFromURI('//Alice') - const amount = new BN(1000) await expect( makeTransfer(alice, alice.address, amount) ).resolves.toMatchObject({ @@ -38,30 +45,41 @@ describe('tx mocks', () => { }) describe('mock query result', () => { - beforeAll(async () => { - require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api.query.did.dIDs.mockReturnValue( - new Option( - Tuple, - new Tuple( - // (publicBoxKey, publicSigningKey, documentStore?) - [Text, Text, U8a], - ['0x987', '0x123', '0x687474703a2f2f6d794449442e6b696c742e696f'] + describe('DID', () => { + const documentStore = 'http://myDID.kilt.io' + const identifier = 'did:kilt:0xwertzui' + + it('works for default DID mock', async () => { + const [publicBoxKey, publicSigningKey] = [ + 'publicBoxKey', + 'publicSigningKey', + ] + await getCached() + await expect(queryByAddress('0xwertzui')).resolves.toMatchObject({ + documentStore, + identifier, + publicBoxKey, + publicSigningKey, + }) + }) + it('works for custom DID mock', async () => { + const [publicBoxKey, publicSigningKey] = ['0x123', '0x321'] + require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api.query.did.dIDs.mockReturnValue( + new Option( + Tuple, + new Tuple( + // (publicSigningKey, publicBoxKey, documentStore?) + [Text, Text, U8a], + [publicSigningKey, publicBoxKey, stringToHex(documentStore)] + ) ) ) - ) - // would also work: - // ```ts - // const bc: any = await getCached() - // bc.api.query.did.dIDs.mockReturnValue(...) - // ``` - }) - - it('works', async () => { - await expect(queryByAddress('0xwertzui')).resolves.toMatchObject({ - documentStore: 'http://myDID.kilt.io', - identifier: 'did:kilt:0xwertzui', - publicBoxKey: '0x123', - publicSigningKey: '0x987', + await expect(queryByAddress('0xwertzui')).resolves.toMatchObject({ + documentStore, + identifier, + publicBoxKey, + publicSigningKey, + }) }) }) }) From 39179620009289b4f35d687f23e83180a5ae21c6 Mon Sep 17 00:00:00 2001 From: Raphael Flechtner Date: Wed, 22 Apr 2020 17:15:43 +0200 Subject: [PATCH 07/11] docs: proper inline documentation of mock, realistic types --- src/blockchain/Mocktest.spec.ts | 18 +-- .../__mocks__/BlockchainApiConnection.ts | 151 +++++++++++++++--- 2 files changed, 133 insertions(+), 36 deletions(-) diff --git a/src/blockchain/Mocktest.spec.ts b/src/blockchain/Mocktest.spec.ts index 41cf981a4..edee2bdcd 100644 --- a/src/blockchain/Mocktest.spec.ts +++ b/src/blockchain/Mocktest.spec.ts @@ -1,5 +1,5 @@ import BN from 'bn.js' -import { Tuple, Option, U8a, Text } from '@polkadot/types' +import { Tuple, Option, Text } from '@polkadot/types' import { stringToHex } from '@polkadot/util' import { Identity } from '..' import { makeTransfer } from '../balance/Balance.chain' @@ -11,6 +11,7 @@ jest.mock('../blockchainApiConnection/BlockchainApiConnection') describe('tx mocks', () => { const alice = Identity.buildFromURI('//Alice') const amount = new BN(1000) + it('tx succeeds', async () => { require('../blockchainApiConnection/BlockchainApiConnection').__setDefaultResult( true @@ -20,6 +21,7 @@ describe('tx mocks', () => { const result = await blockchain.submitTx(alice, transfer) expect(result).toMatchObject({ isFinalized: true }) }) + it('tx fails', async () => { require('../blockchainApiConnection/BlockchainApiConnection').__setDefaultResult( false @@ -50,18 +52,10 @@ describe('mock query result', () => { const identifier = 'did:kilt:0xwertzui' it('works for default DID mock', async () => { - const [publicBoxKey, publicSigningKey] = [ - 'publicBoxKey', - 'publicSigningKey', - ] await getCached() - await expect(queryByAddress('0xwertzui')).resolves.toMatchObject({ - documentStore, - identifier, - publicBoxKey, - publicSigningKey, - }) + await expect(queryByAddress('0xwertzui')).resolves.toBeNull() }) + it('works for custom DID mock', async () => { const [publicBoxKey, publicSigningKey] = ['0x123', '0x321'] require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api.query.did.dIDs.mockReturnValue( @@ -69,7 +63,7 @@ describe('mock query result', () => { Tuple, new Tuple( // (publicSigningKey, publicBoxKey, documentStore?) - [Text, Text, U8a], + [Text, Text, 'Option'], [publicSigningKey, publicBoxKey, stringToHex(documentStore)] ) ) diff --git a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts index eb8ca2a71..74466380b 100644 --- a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts +++ b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts @@ -5,14 +5,53 @@ /** * Dummy comment needed for correct doc display, do not remove */ + +/** + * Mock implementation of BlockchainApiConnection to specifically mock Substrate api calls that + * require a connection to a Substrate blockchain. + * + * Transaction (tx) calls will return a mocked SubmittableExtrinsic containing a SubmittableResult + * which will be returned when calling the `.send()` method. + * This result defaults to `Finalized`, a default which can be changed by means of the `__setDefaultResult()` function: + * ``` + * require('../blockchainApiConnection/BlockchainApiConnection').__setDefaultResult( + * false + * ) + * const transfer = blockchain.api.tx.balances.transfer(alice.address, amount) // returns a mock SubmittableExtrinsic that has a send() method + * const result = await blockchain.submitTx(alice, transfer) // calls transfer.send() internally + * ``` + * You can also queue results with + * ``` + * require('../blockchainApiConnection/BlockchainApiConnection').__queueResults( + * [true, false] + * ) + * ``` + * After queue results have been consumed via tx calls, the mock implementation will resume returning the default result. + * + * Mocked query methods return representations of 'not present' by default, such as Option(..., null) or Vec(..., []). + * You can set different return values during test execution by importing __mocked_api, then calling jest's return + * value setters `.mockReturnValue` or `.mockReturnValueOnce` on the method you want to modify: + * ``` + * const mocked_api = require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api + * mocked_api.query.delegation.children.mockReturnValue( + * new Vec( + * H256, + * ['0x123', '0x456', '0x789'] + * ) + * ) + * ``` + * `.mockReturnValue` changes the default return value for the scope of the current test file. + * `.mockReturnValueOnce()` can be called multiple times to build a queue of return values. After the queue has + * been emptied by calling the query in question repeatedly, jest will return the default value again. + * + */ + import Blockchain, { IBlockchainApi } from '../../blockchain/Blockchain' import { ApiPromise, SubmittableResult } from '@polkadot/api' -import { Option, Tuple, Vec, Text, U8a } from '@polkadot/types' -import BN from 'bn.js' +import { Option, Tuple, Vec, H256, u64 } from '@polkadot/types' import { SubmittableExtrinsic } from '@polkadot/api/promise/types' import { ExtrinsicStatus } from '@polkadot/types/interfaces' -import { Codec } from '@polkadot/types/types' -import { stringToHex } from '@polkadot/util' +import AccountId from '@polkadot/types/primitive/Generic/AccountId' const BlockchainApiConnection = jest.requireActual('../BlockchainApiConnection') @@ -116,37 +155,101 @@ const __mocked_api: any = { }, }, query: { - system: { accountNonce: jest.fn(() => new Text('12345')) }, + system: { + // default return value decodes to BN(0) + accountNonce: jest.fn(() => new u64()), + }, attestation: { - delegatedAttestations: jest.fn(), - attestations: jest.fn(), + // default return value decodes to [], represents no delegated attestations + delegatedAttestations: jest.fn((id: string) => new Vec(H256)), + /* example return value: + new Vec( + H256, + ['0x123', '0x456', '0x789'] + ) + */ + + // default return value decodes to null, represents attestation not found + attestations: jest.fn((claim_hash: string) => new Option(Tuple)), + /* example return value: + new Option( + Tuple, + new Tuple( + [H256, AccountId, 'Option', Bool], + [ + '0x1234', // ctype hash + '5FA9nQDVg267DEd8m1ZypXLBnvN7SFxYwV7ndqSYGiN9TTpu', // Account + null, // delegation-id? + true, // revoked flag + ] + ) + ) */ }, balances: { - freeBalance: jest.fn((account: string) => new BN(0)), + // default return value decodes to BN(0), represents unknown and broke accounts + freeBalance: jest.fn((account: string) => new u64()), }, ctype: { - cTYPEs: jest.fn(hash => true), + // default return value decodes to null, represents CTYPE not found + cTYPEs: jest.fn((hash: string) => new Option(AccountId)), }, delegation: { + // default return value decodes to null, represents delegation not found root: jest.fn((rootId: string) => new Option(Tuple)), + /* example return value: + new Option( + Tuple, + new Tuple( + [H256, AccountId, Bool], + [ + '0x1234', // ctype hash + '5FA9nQDVg267DEd8m1ZypXLBnvN7SFxYwV7ndqSYGiN9TTpu', // Account + false, // revoked flag + ] + ) + ) */ + + // default return value decodes to null, represents delegation not found delegations: jest.fn((delegationId: string) => new Option(Tuple)), - children: jest.fn((id: string) => new Vec(Text, [])), + /* example return value: + new Option( + Tuple, + new Tuple( + [H256,'Option',AccountId,U32,Bool], + [ + '0x1234', // root-id + null, // parent-id? + '5FA9nQDVg267DEd8m1ZypXLBnvN7SFxYwV7ndqSYGiN9TTpu', // Account + 0, // permissions + false, // revoked flag + ] + ) + ) */ + + // default return value decodes to [], represents: no children found + children: jest.fn((id: string) => new Vec(H256, [])), + /* example return value: + new Vec( + H256, + ['0x123', '0x456', '0x789'] + ) + */ }, did: { - dIDs: jest.fn( - (address: string): Option => - new Option( - Tuple, - new Tuple( - [Text, Text, U8a], - [ - 'publicSigningKey', // publicSigningKey - 'publicBoxKey', // publicBoxKey - stringToHex('http://myDID.kilt.io'), // document store - ] - ) - ) - ), + // default return value decodes to null, represents dID not found + dIDs: jest.fn((address: string) => new Option(Tuple)), + /* example return value: + new Option( + Tuple, + new Tuple( + [H256,H256,'Option'], + [ + 'publicSigningKey', // publicSigningKey + 'publicBoxKey', // publicBoxKey + stringToHex('http://myDID.kilt.io'), // document store + ] + ) + ) */ }, }, runtimeMetadata: { From 1c300883bdc1a821f547dedcdc317996662410ac Mon Sep 17 00:00:00 2001 From: Raphael Flechtner Date: Thu, 23 Apr 2020 11:56:16 +0200 Subject: [PATCH 08/11] test: correct mock type for balances, async functions for queries --- .../__mocks__/BlockchainApiConnection.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts index 74466380b..0e2a935ce 100644 --- a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts +++ b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts @@ -48,7 +48,7 @@ import Blockchain, { IBlockchainApi } from '../../blockchain/Blockchain' import { ApiPromise, SubmittableResult } from '@polkadot/api' -import { Option, Tuple, Vec, H256, u64 } from '@polkadot/types' +import { Option, Tuple, Vec, H256, u64, u128 } from '@polkadot/types' import { SubmittableExtrinsic } from '@polkadot/api/promise/types' import { ExtrinsicStatus } from '@polkadot/types/interfaces' import AccountId from '@polkadot/types/primitive/Generic/AccountId' @@ -157,11 +157,11 @@ const __mocked_api: any = { query: { system: { // default return value decodes to BN(0) - accountNonce: jest.fn(() => new u64()), + accountNonce: jest.fn(async () => new u64()), }, attestation: { // default return value decodes to [], represents no delegated attestations - delegatedAttestations: jest.fn((id: string) => new Vec(H256)), + delegatedAttestations: jest.fn(async (id: string) => new Vec(H256)), /* example return value: new Vec( H256, @@ -170,7 +170,7 @@ const __mocked_api: any = { */ // default return value decodes to null, represents attestation not found - attestations: jest.fn((claim_hash: string) => new Option(Tuple)), + attestations: jest.fn(async (claim_hash: string) => new Option(Tuple)), /* example return value: new Option( Tuple, @@ -187,15 +187,15 @@ const __mocked_api: any = { }, balances: { // default return value decodes to BN(0), represents unknown and broke accounts - freeBalance: jest.fn((account: string) => new u64()), + freeBalance: jest.fn(async (account: string) => new u128()), }, ctype: { // default return value decodes to null, represents CTYPE not found - cTYPEs: jest.fn((hash: string) => new Option(AccountId)), + cTYPEs: jest.fn(async (hash: string) => new Option(AccountId)), }, delegation: { // default return value decodes to null, represents delegation not found - root: jest.fn((rootId: string) => new Option(Tuple)), + root: jest.fn(async (rootId: string) => new Option(Tuple)), /* example return value: new Option( Tuple, @@ -210,7 +210,7 @@ const __mocked_api: any = { ) */ // default return value decodes to null, represents delegation not found - delegations: jest.fn((delegationId: string) => new Option(Tuple)), + delegations: jest.fn(async (delegationId: string) => new Option(Tuple)), /* example return value: new Option( Tuple, @@ -227,7 +227,7 @@ const __mocked_api: any = { ) */ // default return value decodes to [], represents: no children found - children: jest.fn((id: string) => new Vec(H256, [])), + children: jest.fn(async (id: string) => new Vec(H256, [])), /* example return value: new Vec( H256, @@ -237,7 +237,7 @@ const __mocked_api: any = { }, did: { // default return value decodes to null, represents dID not found - dIDs: jest.fn((address: string) => new Option(Tuple)), + dIDs: jest.fn(async (address: string) => new Option(Tuple)), /* example return value: new Option( Tuple, From 13325608c4ee175a123d238cc5fed4bebedd7d29 Mon Sep 17 00:00:00 2001 From: Raphael Flechtner Date: Tue, 28 Apr 2020 15:05:27 +0200 Subject: [PATCH 09/11] test: minimum effort test fixes (further refactoring advised) --- src/attestation/Attestation.spec.ts | 34 +++++++-------- src/balance/Balance.spec.ts | 23 +++++----- src/delegation/Delegation.spec.ts | 47 ++++++++++---------- src/delegation/DelegationNode.spec.ts | 37 +++++++--------- src/delegation/DelegationRootNode.spec.ts | 53 +++++++++-------------- src/did/Did.spec.ts | 10 ++--- src/identity/PublicIdentity.spec.ts | 20 ++++----- 7 files changed, 99 insertions(+), 125 deletions(-) diff --git a/src/attestation/Attestation.spec.ts b/src/attestation/Attestation.spec.ts index 4e670d74f..a8c89698c 100644 --- a/src/attestation/Attestation.spec.ts +++ b/src/attestation/Attestation.spec.ts @@ -17,7 +17,8 @@ describe('Attestation', () => { const identityAlice = Identity.buildFromURI('//Alice') const identityBob = Identity.buildFromURI('//Bob') - const Blockchain = require('../blockchain/Blockchain').default + const blockchainApi = require('../blockchainApiConnection/BlockchainApiConnection') + .__mocked_api const rawCType: ICType['schema'] = { $id: 'http://example.com/ctype-1', @@ -50,16 +51,15 @@ describe('Attestation', () => { ) it('stores attestation', async () => { - Blockchain.api.query.attestation.attestations = jest.fn(() => { - const tuple = new Option( + blockchainApi.query.attestation.attestations.mockReturnValue( + new Option( Tuple, new Tuple( [Text, AccountId, Text, Bool], [testCType.hash, identityAlice.address, undefined, false] ) ) - return Promise.resolve(tuple) - }) + ) const attestation: Attestation = Attestation.fromRequestAndPublicIdentity( requestForAttestation, @@ -69,9 +69,9 @@ describe('Attestation', () => { }) it('verify attestations not on chain', async () => { - Blockchain.api.query.attestation.attestations = jest.fn(() => { - return Promise.resolve(new Option(Tuple)) - }) + blockchainApi.query.attestation.attestations.mockReturnValue( + new Option(Tuple) + ) const attestation: Attestation = Attestation.fromAttestation({ claimHash: requestForAttestation.rootHash, @@ -84,18 +84,16 @@ describe('Attestation', () => { }) it('verify attestation revoked', async () => { - Blockchain.api.query.attestation.attestations = jest.fn(() => { - return Promise.resolve( - new Option( - Tuple, - new Tuple( - // Attestations: claim-hash -> (ctype-hash, account, delegation-id?, revoked) - [Text, AccountId, Text, Bool], - [testCType.hash, identityAlice.address, undefined, true] - ) + blockchainApi.query.attestation.attestations.mockReturnValue( + new Option( + Tuple, + new Tuple( + // Attestations: claim-hash -> (ctype-hash, account, delegation-id?, revoked) + [Text, AccountId, Text, Bool], + [testCType.hash, identityAlice.address, undefined, true] ) ) - }) + ) const attestation: Attestation = Attestation.fromRequestAndPublicIdentity( requestForAttestation, diff --git a/src/balance/Balance.spec.ts b/src/balance/Balance.spec.ts index b58cf2dc6..ae3e20e39 100644 --- a/src/balance/Balance.spec.ts +++ b/src/balance/Balance.spec.ts @@ -7,16 +7,19 @@ import { listenToBalanceChanges, makeTransfer } from './Balance.chain' jest.mock('../blockchainApiConnection/BlockchainApiConnection') describe('Balance', () => { - const blockchain = require('../blockchain/Blockchain').default - - blockchain.api.query.balances.freeBalance = jest.fn((accountAddress, cb) => { - if (cb) { - setTimeout(() => { - cb(new BN(42)) - }, 1) + const blockchainApi = require('../blockchainApiConnection/BlockchainApiConnection') + .__mocked_api + + blockchainApi.query.balances.freeBalance = jest.fn( + async (accountAddress, cb) => { + if (cb) { + setTimeout(() => { + cb(new BN(42)) + }, 1) + } + return new BN(12) } - return new BN(12) - }) + ) it('should listen to balance changes', async done => { const bob = Identity.buildFromURI('//Bob') @@ -33,8 +36,6 @@ describe('Balance', () => { expect(currentBalance.toString()).toEqual('12') }) - blockchain.__mockResultHash = '123' - it('should make transfer', async () => { const alice = Identity.buildFromURI('//Alice') const bob = Identity.buildFromURI('//Bob') diff --git a/src/delegation/Delegation.spec.ts b/src/delegation/Delegation.spec.ts index c00a61ea9..1cee82e9a 100644 --- a/src/delegation/Delegation.spec.ts +++ b/src/delegation/Delegation.spec.ts @@ -1,4 +1,4 @@ -import { Text, Tuple, Vec, Option } from '@polkadot/types' +import { Text, Tuple, Vec, Option, H256 } from '@polkadot/types' import Bool from '@polkadot/types/primitive/Bool' import U32 from '@polkadot/types/primitive/U32' import AccountId from '@polkadot/types/primitive/Generic/AccountId' @@ -13,20 +13,18 @@ describe('Delegation', () => { const identityAlice = Identity.buildFromURI('//Alice') const ctypeHash = Crypto.hashStr('testCtype') - const blockchain = require('../blockchain/Blockchain').default - blockchain.api.tx.delegation.createRoot = jest.fn(() => { - return Promise.resolve() - }) - blockchain.api.query.attestation.delegatedAttestations = jest.fn(() => { - const vector = new Vec( + const blockchainApi = require('../blockchainApiConnection/BlockchainApiConnection') + .__mocked_api + + blockchainApi.query.attestation.delegatedAttestations.mockReturnValue( + new Vec( // (claim-hash) Text, ['0x123', '0x456', '0x789'] ) - return Promise.resolve(vector) - }) - blockchain.api.query.delegation.root = jest.fn(() => { - const tuple = new Option( + ) + blockchainApi.query.delegation.root.mockReturnValue( + new Option( Tuple, new Tuple( // Root-Delegation: root-id -> (ctype-hash, account, revoked) @@ -34,12 +32,10 @@ describe('Delegation', () => { [[ctypeHash, identityAlice.address, false]] ) ) - return Promise.resolve(tuple) - }) - blockchain.api.query.delegation.delegations = jest.fn(delegationId => { - let result = null + ) + blockchainApi.query.delegation.delegations = jest.fn(async delegationId => { if (delegationId === 'firstChild') { - result = new Option( + return new Option( Tuple, new Tuple( // Delegation: delegation-id -> (root-id, parent-id?, account, permissions, revoked) @@ -53,8 +49,9 @@ describe('Delegation', () => { ] ) ) - } else if (delegationId === 'secondChild') { - result = new Option( + } + if (delegationId === 'secondChild') { + return new Option( Tuple, new Tuple( // Delegation: delegation-id -> (root-id, parent-id?, account, permissions, revoked) @@ -68,8 +65,9 @@ describe('Delegation', () => { ] ) ) - } else if (delegationId === 'thirdChild') { - result = new Option( + } + if (delegationId === 'thirdChild') { + return new Option( Tuple, new Tuple( // Delegation: delegation-id -> (root-id, parent-id?, account, permissions, revoked) @@ -84,16 +82,15 @@ describe('Delegation', () => { ) ) } - return Promise.resolve(result) + return new Option(Tuple.with([H256, 'Option', AccountId, U32, Bool])) }) - blockchain.api.query.delegation.children = jest.fn(() => { - const vector = new Vec( + blockchainApi.query.delegation.children.mockReturnValue( + new Vec( // Children: delegation-id -> [delegation-ids] Text, ['firstChild', 'secondChild', 'thirdChild'] ) - return Promise.resolve(vector) - }) + ) it('get children', async () => { const myDelegation = new DelegationNode( diff --git a/src/delegation/DelegationNode.spec.ts b/src/delegation/DelegationNode.spec.ts index b49d73aee..f0934888d 100644 --- a/src/delegation/DelegationNode.spec.ts +++ b/src/delegation/DelegationNode.spec.ts @@ -39,10 +39,10 @@ describe('Delegation', () => { }) it('delegation verify / revoke', async () => { - require('../blockchain/Blockchain').default.__mockQueryDelegationDelegations = jest.fn( - id => { + require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api.query.delegation.delegations = jest.fn( + async id => { if (id === 'success') { - const tuple = new Option( + return new Option( Tuple, new Tuple( // (root-id, parent-id?, account, permissions, revoked) @@ -50,9 +50,8 @@ describe('Delegation', () => { ['myRootId', null, 'myAccount', 1, false] ) ) - return Promise.resolve(tuple) } - const tuple = new Option( + return new Option( Tuple, new Tuple( // (root-id, parent-id?, account, permissions, revoked) @@ -60,7 +59,6 @@ describe('Delegation', () => { ['myRootId', null, 'myAccount', 1, true] ) ) - return Promise.resolve(tuple) } ) @@ -86,22 +84,19 @@ describe('Delegation', () => { it('get delegation root', async () => { const identityAlice = Identity.buildFromURI('//Alice') - require('../blockchain/Blockchain').default.__mockQueryDelegationRoot = jest.fn( - () => { - const tuple = new Option( - Tuple, - new Tuple( - // Root-Delegation: root-id -> (ctype-hash, account, revoked) - [H256, Text, Bool], - [ - '0x1234000000000000000000000000000000000000000000000000000000000000', - identityAlice.address, - false, - ] - ) + require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api.query.delegation.root.mockReturnValue( + new Option( + Tuple, + new Tuple( + // Root-Delegation: root-id -> (ctype-hash, account, revoked) + [H256, Text, Bool], + [ + '0x1234000000000000000000000000000000000000000000000000000000000000', + identityAlice.address, + false, + ] ) - return Promise.resolve(tuple) - } + ) ) const node: DelegationNode = new DelegationNode( diff --git a/src/delegation/DelegationRootNode.spec.ts b/src/delegation/DelegationRootNode.spec.ts index 95e06c5ed..dc3bb4b6b 100644 --- a/src/delegation/DelegationRootNode.spec.ts +++ b/src/delegation/DelegationRootNode.spec.ts @@ -3,37 +3,32 @@ import AccountId from '@polkadot/types/primitive/Generic/AccountId' import Bool from '@polkadot/types/primitive/Bool' import { Crypto, Identity } from '..' import DelegationRootNode from './DelegationRootNode' +import getCached from '../blockchainApiConnection' jest.mock('../blockchainApiConnection/BlockchainApiConnection') describe('Delegation', () => { const identityAlice = Identity.buildFromURI('//Alice') const ctypeHash = Crypto.hashStr('testCtype') - require('../blockchain/Blockchain').default.__mockQueryDelegationRoot = jest.fn( - () => { - const tuple = new Option( - Tuple, - new Tuple( - // Root-Delegation: root-id -> (ctype-hash, account, revoked) - [H256, AccountId, Bool], - [ctypeHash, identityAlice.address, false] - ) + require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api.query.delegation.root.mockReturnValue( + new Option( + Tuple, + new Tuple( + // Root-Delegation: root-id -> (ctype-hash, account, revoked) + [H256, AccountId, Bool], + [ctypeHash, identityAlice.address, false] ) - return Promise.resolve(tuple) - } + ) ) - require('../blockchain/Blockchain').default.__mockQueryDelegationDelegation = jest.fn( - () => { - const tuple = new Option( - Tuple, - new Tuple( - // Root-Delegation: delegation-id -> (root-id, parent-id?, account, permissions, revoked) - [H256, AccountId, Bool], - [ctypeHash, identityAlice.address, false] - ) + require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api.query.delegation.delegations.mockReturnValue( + new Option( + Tuple, + new Tuple( + // Root-Delegation: delegation-id -> (root-id, parent-id?, account, permissions, revoked) + [H256, AccountId, Bool], + [ctypeHash, identityAlice.address, false] ) - return Promise.resolve(tuple) - } + ) ) const ROOT_IDENTIFIER = 'abc123' @@ -62,8 +57,8 @@ describe('Delegation', () => { }) it('root delegation verify', async () => { - require('../blockchain/Blockchain').default.__mockQueryDelegationRoot = jest.fn( - rootId => { + require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api.query.delegation.root = jest.fn( + async rootId => { if (rootId === 'success') { const tuple = new Option( Tuple, @@ -105,13 +100,7 @@ describe('Delegation', () => { }) it('root delegation verify', async () => { - let calledRootId = '' - - require('../blockchain/Blockchain').default.__mockTxDelegationRoot = jest.fn( - rootId => { - calledRootId = rootId - } - ) + const blockchain = await getCached() const aDelegationRootNode = new DelegationRootNode( 'myRootId', @@ -119,7 +108,7 @@ describe('Delegation', () => { 'myAccount' ) const revokeStatus = await aDelegationRootNode.revoke(identityAlice) - expect(calledRootId).toBe('myRootId') + expect(blockchain.api.tx.delegation.revokeRoot).toBeCalledWith('myRootId') expect(revokeStatus).toBeDefined() }) }) diff --git a/src/did/Did.spec.ts b/src/did/Did.spec.ts index 2799e665d..4f844761a 100644 --- a/src/did/Did.spec.ts +++ b/src/did/Did.spec.ts @@ -7,10 +7,10 @@ import { getIdentifierFromAddress } from './Did.utils' jest.mock('../blockchainApiConnection/BlockchainApiConnection') describe('DID', () => { - require('../blockchain/Blockchain').default.__mockQueryDidDids = jest.fn( - address => { + require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api.query.did.dIDs = jest.fn( + async address => { if (address === 'withDocumentStore') { - const tuple = new Option( + return new Option( Tuple, new Tuple( // (publicBoxKey, publicSigningKey, documentStore?) @@ -18,9 +18,8 @@ describe('DID', () => { ['0x987', '0x123', '0x687474703a2f2f6d794449442e6b696c742e696f'] ) ) - return Promise.resolve(tuple) } - const tuple = new Option( + return new Option( Tuple, new Tuple( // (publicBoxKey, publicSigningKey, documentStore?) @@ -28,7 +27,6 @@ describe('DID', () => { ['0x987', '0x123', null] ) ) - return Promise.resolve(tuple) } ) diff --git a/src/identity/PublicIdentity.spec.ts b/src/identity/PublicIdentity.spec.ts index a95c32c9b..08aef4fb1 100644 --- a/src/identity/PublicIdentity.spec.ts +++ b/src/identity/PublicIdentity.spec.ts @@ -1,4 +1,4 @@ -import { Text, Tuple, U8a, Option } from '@polkadot/types' +import { Tuple, Option, H256, Text } from '@polkadot/types' import PublicIdentity, { IURLResolver } from './PublicIdentity' import IPublicIdentity from '../types/PublicIdentity' @@ -8,34 +8,30 @@ describe('PublicIdentity', () => { // https://polkadot.js.org/api/examples/promise/ // testing to create correct demo accounts - require('../blockchain/Blockchain').default.__mockQueryDidDids = jest.fn( - id => { - let tuple + require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api.query.did.dIDs = jest.fn( + async id => { switch (id) { case '1': - tuple = new Option( + return new Option( Tuple, new Tuple( // (public-signing-key, public-encryption-key, did-reference?) - [Text, Text, U8a], + [Text, Text, 'Option'], ['pub-key', 'box-key', [14, 75, 23, 14, 55]] ) ) - break case '2': - tuple = new Option( + return new Option( Tuple, new Tuple( // (public-signing-key, public-encryption-key, did-reference?) - [Text, Text, Text], + [Text, Text, 'Option'], ['pub-key', 'box-key', undefined] ) ) - break default: - tuple = undefined + return new Option(Tuple.with([H256, H256, 'Option'])) } - return Promise.resolve(tuple) } ) From 490f4ed1d371ad2c14fc48163b2e8cf0d3742858 Mon Sep 17 00:00:00 2001 From: Raphael Flechtner Date: Wed, 29 Apr 2020 14:33:10 +0200 Subject: [PATCH 10/11] chore: removed demo test & mock file no longer needed --- src/blockchain/Mocktest.spec.ts | 79 ------------------ src/blockchain/__mocks__/Blockchain.ts | 107 ------------------------- src/ctype/CType.utils.spec.ts | 2 - 3 files changed, 188 deletions(-) delete mode 100644 src/blockchain/Mocktest.spec.ts delete mode 100644 src/blockchain/__mocks__/Blockchain.ts diff --git a/src/blockchain/Mocktest.spec.ts b/src/blockchain/Mocktest.spec.ts deleted file mode 100644 index edee2bdcd..000000000 --- a/src/blockchain/Mocktest.spec.ts +++ /dev/null @@ -1,79 +0,0 @@ -import BN from 'bn.js' -import { Tuple, Option, Text } from '@polkadot/types' -import { stringToHex } from '@polkadot/util' -import { Identity } from '..' -import { makeTransfer } from '../balance/Balance.chain' -import getCached from '../blockchainApiConnection/BlockchainApiConnection' -import { queryByAddress } from '../did/Did.chain' - -jest.mock('../blockchainApiConnection/BlockchainApiConnection') - -describe('tx mocks', () => { - const alice = Identity.buildFromURI('//Alice') - const amount = new BN(1000) - - it('tx succeeds', async () => { - require('../blockchainApiConnection/BlockchainApiConnection').__setDefaultResult( - true - ) - const blockchain = await getCached() - const transfer = blockchain.api.tx.balances.transfer(alice.address, amount) - const result = await blockchain.submitTx(alice, transfer) - expect(result).toMatchObject({ isFinalized: true }) - }) - - it('tx fails', async () => { - require('../blockchainApiConnection/BlockchainApiConnection').__setDefaultResult( - false - ) - await expect(makeTransfer(alice, alice.address, amount)).rejects.toThrow( - 'Transaction failed' - ) - }) - - it('tx succeeds then fails', async () => { - require('../blockchainApiConnection/BlockchainApiConnection').__queueResults( - [true, false] - ) - await expect( - makeTransfer(alice, alice.address, amount) - ).resolves.toMatchObject({ - isFinalized: true, - }) - await expect(makeTransfer(alice, alice.address, amount)).rejects.toThrow( - 'Transaction failed' - ) - }) -}) - -describe('mock query result', () => { - describe('DID', () => { - const documentStore = 'http://myDID.kilt.io' - const identifier = 'did:kilt:0xwertzui' - - it('works for default DID mock', async () => { - await getCached() - await expect(queryByAddress('0xwertzui')).resolves.toBeNull() - }) - - it('works for custom DID mock', async () => { - const [publicBoxKey, publicSigningKey] = ['0x123', '0x321'] - require('../blockchainApiConnection/BlockchainApiConnection').__mocked_api.query.did.dIDs.mockReturnValue( - new Option( - Tuple, - new Tuple( - // (publicSigningKey, publicBoxKey, documentStore?) - [Text, Text, 'Option'], - [publicSigningKey, publicBoxKey, stringToHex(documentStore)] - ) - ) - ) - await expect(queryByAddress('0xwertzui')).resolves.toMatchObject({ - documentStore, - identifier, - publicBoxKey, - publicSigningKey, - }) - }) - }) -}) diff --git a/src/blockchain/__mocks__/Blockchain.ts b/src/blockchain/__mocks__/Blockchain.ts deleted file mode 100644 index 62a3a869d..000000000 --- a/src/blockchain/__mocks__/Blockchain.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { SubmittableResult } from '@polkadot/api' - -/** - * @module Blockchain - * @ignore - */ - -/** - * Dummy comment needed for correct doc display, do not remove - */ -const blockchain: any = { - __mockResultHash: '', - __mockTxStatus: { - payload: undefined, - type: 'Finalized', - isFinalized: true, - isError: false, - isDropped: false, - isInvalid: false, - isUsurped: false, - }, - __mockTxDelegationRoot: jest.fn(), - __mockQueryDelegationRoot: jest.fn(), - __mockQueryDelegationDelegation: jest.fn(), - __mockQueryDelegationDelegations: jest.fn(), - __mockQueryDidDids: jest.fn(), - asArray: jest.fn(result => { - return result.toJSON() - }), - api: { - tx: { - attestation: { - add: jest.fn((claimHash, _cTypeHash) => { - return Promise.resolve() - }), - }, - balances: { - transfer: jest.fn(), - }, - ctype: { - add: jest.fn((hash, signature) => { - return Promise.resolve({ hash, signature }) - }), - }, - delegation: { - createRoot: jest.fn((rootId, _ctypeHash) => { - return Promise.resolve() - }), - revokeRoot: jest.fn(rootId => { - return blockchain.__mockTxDelegationRoot(rootId) - }), - revokeDelegation: jest.fn(delegationId => { - return Promise.resolve() - }), - }, - did: { - add: jest.fn((sign_key, box_key, doc_ref) => { - return Promise.resolve() - }), - remove: jest.fn(() => { - return Promise.resolve() - }), - }, - }, - query: { - attestation: { - delegatedAttestations: jest.fn(), - attestations: jest.fn(), - }, - balances: { - freeBalance: jest.fn(), - }, - ctype: { - cTYPEs: jest.fn(hash => { - return true - }), - }, - delegation: { - root: jest.fn(rootId => { - return blockchain.__mockQueryDelegationRoot(rootId) - }), - delegation: jest.fn(delegationId => { - return blockchain.__mockQueryDelegationDelegation(delegationId) - }), - delegations: jest.fn(id => { - return blockchain.__mockQueryDelegationDelegations(id) - }), - children: jest.fn(), - }, - did: { - dIDs: jest.fn(id => { - return blockchain.__mockQueryDidDids(id) - }), - }, - }, - }, - getStats: jest.fn(), - listenToBlocks: jest.fn(), - listenToBalanceChanges: jest.fn(), - makeTransfer: jest.fn(), - submitTx: jest.fn((identity, tx) => { - return Promise.resolve(new SubmittableResult({status: blockchain.__mockTxStatus})) - }), - getNonce: jest.fn(), -} - -export default blockchain diff --git a/src/ctype/CType.utils.spec.ts b/src/ctype/CType.utils.spec.ts index 3c3ff683c..4cb64d96a 100644 --- a/src/ctype/CType.utils.spec.ts +++ b/src/ctype/CType.utils.spec.ts @@ -6,8 +6,6 @@ import { } from './CType.utils' import ICType from '../types/CType' -jest.mock('../blockchain/Blockchain') - const ctypeInput = ({ $id: 'http://example.com/ctype-1', $schema: 'http://kilt-protocol.org/draft-01/ctype-input#', From 2a39571001592a71b1acce5e997b2b439001fc32 Mon Sep 17 00:00:00 2001 From: Raphael Flechtner Date: Wed, 29 Apr 2020 18:34:14 +0200 Subject: [PATCH 11/11] fix: removing unused mock function arguments --- .../__mocks__/BlockchainApiConnection.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts index 0e2a935ce..e36116e99 100644 --- a/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts +++ b/src/blockchainApiConnection/__mocks__/BlockchainApiConnection.ts @@ -56,7 +56,6 @@ import AccountId from '@polkadot/types/primitive/Generic/AccountId' const BlockchainApiConnection = jest.requireActual('../BlockchainApiConnection') async function getCached( - _: string = BlockchainApiConnection.DEFAULT_WS_ADDRESS ): Promise { if (!BlockchainApiConnection.instance) { BlockchainApiConnection.instance = Promise.resolve( @@ -77,7 +76,7 @@ class MockSubmittableExtrinsic { this.result = result } - public sign(_a: any, _b: any, _c: any) { + public sign() { return this }