'use strict' ; import * as vscode from 'vscode' ; import * as chai from 'chai' ; import * as sinon from 'sinon' ; import * as sinonChai from 'sinon-chai' ; import * as path from 'path' ; import { FabricGatewayConnection } from 'ibm-blockchain-platform-gateway-v1' ; import { BlockchainTreeItem } from '../../extension/explorer/model/BlockchainTreeItem' ; import { BlockchainGatewayExplorerProvider } from '../../extension/explorer/gatewayExplorer' ; import { ChannelTreeItem } from '../../extension/explorer/model/ChannelTreeItem' ; import { FabricGatewayConnectionManager } from '../../extension/fabric/FabricGatewayConnectionManager' ; import { ExtensionUtil } from '../../extension/util/ExtensionUtil' ; import { TestUtil } from '../TestUtil' ; import { TransactionTreeItem } from '../../extension/explorer/model/TransactionTreeItem' ; import { InstantiatedContractTreeItem } from '../../extension/explorer/model/InstantiatedContractTreeItem' ; import { ConnectedTreeItem } from '../../extension/explorer/model/ConnectedTreeItem' ; import { ContractTreeItem } from '../../extension/explorer/model/ContractTreeItem' ; import { LocalGatewayTreeItem } from '../../extension/explorer/model/LocalGatewayTreeItem' ; import { VSCodeBlockchainOutputAdapter } from '../../extension/logging/VSCodeBlockchainOutputAdapter' ; import { ExtensionCommands } from '../../ExtensionCommands' ; import { InstantiatedChaincodeTreeItem } from '../../extension/explorer/model/InstantiatedChaincodeTreeItem' ; import { GatewayTreeItem } from '../../extension/explorer/model/GatewayTreeItem' ; import { GatewayDissociatedTreeItem } from '../../extension/explorer/model/GatewayDissociatedTreeItem' ; import { GatewayAssociatedTreeItem } from '../../extension/explorer/model/GatewayAssociatedTreeItem' ; import { FabricRuntimeUtil , LogType , FabricGatewayRegistryEntry , FabricGatewayRegistry , FabricEnvironmentRegistry , FabricWalletRegistry , FabricEnvironmentRegistryEntry , EnvironmentType } from 'ibm-blockchain-platform-common' ; import { InstantiatedUnknownTreeItem } from '../../extension/explorer/model/InstantiatedUnknownTreeItem' ; import { GatewayGroupTreeItem } from '../../extension/explorer/model/GatewayGroupTreeItem' ; import { LocalMicroEnvironmentManager } from '../../extension/fabric/environments/LocalMicroEnvironmentManager' ; import { UserInputUtil } from '../../extension/commands/UserInputUtil' ; chai . use ( sinonChai ) ; const should = chai . should ( ) ; describe ( 'gatewayExplorer' , ( ) => { const mySandBox = sinon . createSandbox ( ) ; let logSpy ; before ( async ( ) => { await TestUtil . setupTests ( mySandBox ) ; } ) ; beforeEach ( async ( ) => { logSpy = mySandBox . spy ( VSCodeBlockchainOutputAdapter . instance ( ) , 'log' ) ; } ) ; afterEach ( ( ) => { mySandBox . restore ( ) ; } ) ; describe ( 'constructor' , ( ) => { it ( 'should register for connected events from the connection manager' , async ( ) => { const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; mySandBox . stub ( blockchainGatewayExplorerProvider , 'connect' ) . resolves ( ) ; mySandBox . stub ( blockchainGatewayExplorerProvider , 'disconnect' ) . resolves ( ) ; const mockConnection = mySandBox . createStubInstance ( FabricGatewayConnection ) ; const connectionManager = FabricGatewayConnectionManager . instance ( ) ; connectionManager . emit ( 'connected' , mockConnection ) ; blockchainGatewayExplorerProvider . connect . should . have . been . calledOnce ; } ) ; it ( 'should display errors from connected events' , async ( ) => { const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; mySandBox . stub ( blockchainGatewayExplorerProvider , 'connect' ) . rejects ( new Error ( 'wow such error' ) ) ; mySandBox . stub ( blockchainGatewayExplorerProvider , 'disconnect' ) . resolves ( ) ; const mockConnection = mySandBox . createStubInstance ( FabricGatewayConnection ) ; const connectionManager = FabricGatewayConnectionManager . instance ( ) ; connectionManager . emit ( 'connected' , mockConnection ) ; await new Promise ( ( resolve ) : any => setTimeout ( resolve , 50 ) ) ; blockchainGatewayExplorerProvider . connect . should . have . been . calledOnce ; logSpy . should . have . been . calledOnceWithExactly ( LogType . ERROR , 'Error handling connected event: wow such error' , 'Error handling connected event: Error: wow such error' ) ; } ) ; it ( 'should register for disconnected events from the connection manager' , async ( ) => { const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; mySandBox . stub ( blockchainGatewayExplorerProvider , 'connect' ) . resolves ( ) ; mySandBox . stub ( blockchainGatewayExplorerProvider , 'disconnect' ) . resolves ( ) ; const connectionManager = FabricGatewayConnectionManager . instance ( ) ; connectionManager . emit ( 'disconnected' ) ; blockchainGatewayExplorerProvider . disconnect . should . have . been . calledOnceWithExactly ( ) ; } ) ; it ( 'should display errors from disconnected events' , async ( ) => { const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; mySandBox . stub ( blockchainGatewayExplorerProvider , 'connect' ) . resolves ( ) ; mySandBox . stub ( blockchainGatewayExplorerProvider , 'disconnect' ) . rejects ( new Error ( 'wow such error' ) ) ; const connectionManager = FabricGatewayConnectionManager . instance ( ) ; connectionManager . emit ( 'disconnected' ) ; await new Promise ( ( resolve ) : any => setTimeout ( resolve , 50 ) ) ; blockchainGatewayExplorerProvider . disconnect . should . have . been . calledOnceWithExactly ( ) ; logSpy . should . have . been . calledOnceWithExactly ( LogType . ERROR , 'Error handling disconnected event: wow such error' , 'Error handling disconnected event: Error: wow such error' ) ; } ) ; } ) ; describe ( 'getChildren' , ( ) => { describe ( 'unconnected tree' , ( ) => { let getConnectionStub ; beforeEach ( async ( ) => { await TestUtil . startLocalFabric ( ) ; getConnectionStub = mySandBox . stub ( FabricGatewayConnectionManager . instance ( ) , 'getConnection' ) ; } ) ; it ( 'should display gateway that has been added in alphabetical order' , async ( ) => { const gatewayB = new FabricGatewayRegistryEntry ( { name : 'myGatewayB' , associatedWallet : '' , connectionProfilePath : path . join ( 'blockchain' , 'extension' , 'directory' , 'gatewayOne' , 'connection.json' ) } ) ; const gatewayC = new FabricGatewayRegistryEntry ( { name : 'myGatewayC' , associatedWallet : 'some_wallet' , connectionProfilePath : path . join ( 'blockchain' , 'extension' , 'directory' , 'gatewayOne' , 'connection.json' ) } ) ; const gatewayA = new FabricGatewayRegistryEntry ( { name : 'myGatewayA' , associatedWallet : 'some_other_wallet' , connectionProfilePath : path . join ( 'blockchain' , 'extension' , 'directory' , 'gatewayOne' , 'connection.json' ) } ) ; await FabricEnvironmentRegistry . instance ( ) . clear ( ) ; await FabricGatewayRegistry . instance ( ) . clear ( ) ; await TestUtil . startLocalFabric ( ) ; await FabricGatewayRegistry . instance ( ) . add ( gatewayB ) ; await FabricGatewayRegistry . instance ( ) . add ( gatewayC ) ; await FabricGatewayRegistry . instance ( ) . add ( gatewayA ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; allChildren . length . should . equal ( 2 ) ; const groupOne = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 0 ] ) ; ( groupOne [ 0 ] as LocalGatewayTreeItem ) . name . should . equal ( 'Org1 Gateway' ) ; groupOne [ 0 ] . tooltip . should . include ( `ⓘ Associated wallet:\n${ FabricRuntimeUtil . LOCAL_FABRIC } - Org1 Wallet` ) ; groupOne [ 0 ] . should . be . an . instanceOf ( LocalGatewayTreeItem ) ; const groupTwo = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 1 ] ) ; groupTwo [ 0 ] . label . should . equal ( 'myGatewayA ⧉' ) ; groupTwo [ 0 ] . tooltip . should . equal ( 'ⓘ Associated wallet:\n    some_other_wallet' ) ; groupTwo [ 0 ] . should . be . an . instanceOf ( GatewayAssociatedTreeItem ) ; groupTwo [ 1 ] . label . should . equal ( 'myGatewayB' ) ; groupTwo [ 1 ] . tooltip . should . equal ( 'No associated wallet' ) ; groupTwo [ 1 ] . should . be . an . instanceOf ( GatewayDissociatedTreeItem ) ; groupTwo [ 2 ] . label . should . equal ( 'myGatewayC ⧉' ) ; groupTwo [ 2 ] . tooltip . should . equal ( 'ⓘ Associated wallet:\n    some_wallet' ) ; groupTwo [ 2 ] . should . be . an . instanceOf ( GatewayAssociatedTreeItem ) ; } ) ; it ( 'should say that there are no gateways' , async ( ) => { await FabricEnvironmentRegistry . instance ( ) . clear ( ) ; await FabricGatewayRegistry . instance ( ) . clear ( ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const gateways = await blockchainGatewayExplorerProvider . getChildren ( ) ; gateways . length . should . equal ( 1 ) ; gateways [ 0 ] . label . should . equal ( `No gateways found` ) ; } ) ; it ( 'should handle error with tree' , async ( ) => { const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; mySandBox . stub ( blockchainGatewayExplorerProvider , 'createConnectionTree' ) . rejects ( { message : 'some error' } ) ; await blockchainGatewayExplorerProvider . getChildren ( ) ; logSpy . should . have . been . calledWith ( LogType . ERROR , 'some error' ) ; } ) ; it ( 'should display the managed runtime' , async ( ) => { await FabricGatewayRegistry . instance ( ) . clear ( ) ; mySandBox . stub ( LocalMicroEnvironmentManager . instance ( ) . getRuntime ( FabricRuntimeUtil . LOCAL_FABRIC ) , 'isRunning' ) . resolves ( true ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; const groupChildren = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 0 ] ) ; const gateway = await FabricGatewayRegistry . instance ( ) . get ( `${ FabricRuntimeUtil . LOCAL_FABRIC } - Org1 Gateway` ) ; const myCommand = { command : ExtensionCommands . CONNECT_TO_GATEWAY , title : '' , arguments : [ gateway ] } ; allChildren . length . should . equal ( 1 ) ; groupChildren . length . should . equal ( 1 ) ; groupChildren [ 0 ] . should . be . an . instanceOf ( LocalGatewayTreeItem ) ; const localGatewayTreeItem = groupChildren [ 0 ] as LocalGatewayTreeItem ; localGatewayTreeItem . label . should . equal ( 'Org1 Gateway  ●' ) ; localGatewayTreeItem . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; localGatewayTreeItem . gateway . should . deep . equal ( gateway ) ; localGatewayTreeItem . command . should . deep . equal ( myCommand ) ; localGatewayTreeItem . tooltip . should . deep . equal ( `Org1 Gateway is running
ⓘ Associated wallet:
${ FabricRuntimeUtil . LOCAL_FABRIC } - Org1 Wallet` ) ; } ) ; it ( 'should display multi-org gateways' , async ( ) => { await FabricGatewayRegistry . instance ( ) . clear ( ) ; await FabricEnvironmentRegistry . instance ( ) . clear ( ) ; await FabricWalletRegistry . instance ( ) . clear ( ) ; const twoOrgEntry = { name : 'twoOrgEnvironment' , managedRuntime : true , environmentType : EnvironmentType . LOCAL_MICROFAB_ENVIRONMENT , numberOfOrgs : 2 , environmentDirectory : '' , url : 'http://someurl:9001' } ; await FabricEnvironmentRegistry . instance ( ) . add ( twoOrgEntry ) ; const gatewayOne = new FabricGatewayRegistryEntry ( { name : 'twoOrgEnvironment - Org1 Gateway' , fromEnvironment : 'twoOrgEnvironment' , associatedWallet : 'Org1' , displayName : `Org1 Gateway` , connectionProfilePath : path . join ( 'blockchain' , 'extension' , 'directory' , 'gatewayOne' , 'connection.json' ) } ) ; const gatewayTwo = new FabricGatewayRegistryEntry ( { name : 'twoOrgEnvironment - Org2 Gateway' , fromEnvironment : 'twoOrgEnvironment' , associatedWallet : 'Org2' , displayName : `Org2 Gateway` , connectionProfilePath : path . join ( 'blockchain' , 'extension' , 'directory' , 'gatewayTwo' , 'connection.json' ) } ) ; await FabricGatewayRegistry . instance ( ) . add ( gatewayOne ) ; await FabricGatewayRegistry . instance ( ) . add ( gatewayTwo ) ; const anotherOrgEntry = { name : 'anotherOrgEnvironment' , managedRuntime : true , environmentType : EnvironmentType . LOCAL_MICROFAB_ENVIRONMENT , numberOfOrgs : 2 , environmentDirectory : '' , url : 'http://someurl:9002' } ; const anotherAnotherOrgEntry = { name : 'otherEnvironment' , managedRuntime : true , environmentType : EnvironmentType . LOCAL_MICROFAB_ENVIRONMENT , numberOfOrgs : 2 , environmentDirectory : '' , url : 'http://someurl:9002' } ; await FabricEnvironmentRegistry . instance ( ) . add ( anotherOrgEntry ) ; await FabricEnvironmentRegistry . instance ( ) . add ( anotherAnotherOrgEntry ) ; const gatewayThree = new FabricGatewayRegistryEntry ( { name : 'anotherOrgEnvironment - Org1 Gateway' , fromEnvironment : 'otherEnvironment' , environmentGroup : 'anotherOrgEnvironment' , associatedWallet : 'Org1' , displayName : `Org1 Gateway` , connectionProfilePath : path . join ( 'blockchain' , 'extension' , 'directory' , 'gatewayThree' , 'connection.json' ) } ) ; await FabricGatewayRegistry . instance ( ) . add ( gatewayThree ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; const myCommandOne = { command : ExtensionCommands . CONNECT_TO_GATEWAY , title : '' , arguments : [ gatewayOne ] } ; const myCommandTwo = { command : ExtensionCommands . CONNECT_TO_GATEWAY , title : '' , arguments : [ gatewayTwo ] } ; allChildren . length . should . equal ( 2 ) ; allChildren [ 1 ] . should . be . an . instanceOf ( GatewayGroupTreeItem ) ; const groupOne = allChildren [ 1 ] as GatewayGroupTreeItem ; groupOne . label . should . equal ( 'twoOrgEnvironment' ) ; groupOne . gateways . should . deep . equal ( [ gatewayOne , gatewayTwo ] ) ; const groupGateways = await blockchainGatewayExplorerProvider . getChildren ( groupOne ) as LocalGatewayTreeItem [ ] ; groupGateways [ 0 ] . label . should . equal ( `Org1 Gateway  ○` ) ; groupGateways [ 0 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; groupGateways [ 0 ] . gateway . should . deep . equal ( gatewayOne ) ; groupGateways [ 0 ] . command . should . deep . equal ( myCommandOne ) ; groupGateways [ 0 ] . tooltip . should . deep . equal ( `Org1 Gateway is not running\nⓘ Associated wallet:\ntwoOrgEnvironment - Org1 Wallet` ) ; groupGateways [ 1 ] . label . should . equal ( `Org2 Gateway  ○` ) ; groupGateways [ 1 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; groupGateways [ 1 ] . gateway . should . deep . equal ( gatewayTwo ) ; groupGateways [ 1 ] . command . should . deep . equal ( myCommandTwo ) ; groupGateways [ 1 ] . tooltip . should . deep . equal ( `Org2 Gateway is not running\nⓘ Associated wallet:\ntwoOrgEnvironment - Org2 Wallet` ) ; } ) ; it ( 'should display ops tools gateway' , async ( ) => { await FabricGatewayRegistry . instance ( ) . clear ( ) ; await FabricEnvironmentRegistry . instance ( ) . clear ( ) ; await FabricWalletRegistry . instance ( ) . clear ( ) ; const opsToolsEnv = new FabricEnvironmentRegistryEntry ( ) ; opsToolsEnv . name = 'opsToolsEnv' ; opsToolsEnv . environmentType = EnvironmentType . OPS_TOOLS_ENVIRONMENT ; await FabricEnvironmentRegistry . instance ( ) . add ( opsToolsEnv ) ; const opsToolsGateway = new FabricGatewayRegistryEntry ( { name : 'someGateway' , environmentGroup : 'opsToolsEnv' , associatedWallet : 'Org1 Wallet' , displayName : `Org1` , connectionProfilePath : 'some/file/path' } ) ; await FabricGatewayRegistry . instance ( ) . add ( opsToolsGateway ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; const myCommand = { command : ExtensionCommands . CONNECT_TO_GATEWAY , title : '' , arguments : [ opsToolsGateway ] } ; allChildren . length . should . equal ( 1 ) ; allChildren [ 0 ] . should . be . an . instanceOf ( GatewayGroupTreeItem ) ; const group = allChildren [ 0 ] as GatewayGroupTreeItem ; group . label . should . equal ( opsToolsEnv . name ) ; group . gateways . should . deep . equal ( [ opsToolsGateway ] ) ; const groupGateways = await blockchainGatewayExplorerProvider . getChildren ( group ) as LocalGatewayTreeItem [ ] ; groupGateways [ 0 ] . label . should . equal ( `Org1 ⧉` ) ; groupGateways [ 0 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; groupGateways [ 0 ] . gateway . should . deep . equal ( opsToolsGateway ) ; groupGateways [ 0 ] . command . should . deep . equal ( myCommand ) ; groupGateways [ 0 ] . tooltip . should . deep . equal ( `ⓘ Associated wallet:\n    Org1 Wallet` ) ; } ) ; it ( 'should display saas ops tools gateway' , async ( ) => { await FabricGatewayRegistry . instance ( ) . clear ( ) ; await FabricEnvironmentRegistry . instance ( ) . clear ( ) ; await FabricWalletRegistry . instance ( ) . clear ( ) ; const saasEnv = new FabricEnvironmentRegistryEntry ( ) ; saasEnv . name = 'saasEnv' ; saasEnv . environmentType = EnvironmentType . SAAS_OPS_TOOLS_ENVIRONMENT ; await FabricEnvironmentRegistry . instance ( ) . add ( saasEnv ) ; const saasGateway = new FabricGatewayRegistryEntry ( { name : 'someGateway' , environmentGroup : 'saasEnv' , associatedWallet : 'Org1 Wallet' , displayName : `Org1` , connectionProfilePath : 'some/file/path' } ) ; await FabricGatewayRegistry . instance ( ) . add ( saasGateway ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; const myCommand = { command : ExtensionCommands . CONNECT_TO_GATEWAY , title : '' , arguments : [ saasGateway ] } ; allChildren . length . should . equal ( 1 ) ; allChildren [ 0 ] . should . be . an . instanceOf ( GatewayGroupTreeItem ) ; const group = allChildren [ 0 ] as GatewayGroupTreeItem ; group . label . should . equal ( saasEnv . name ) ; group . gateways . should . deep . equal ( [ saasGateway ] ) ; const groupGateways = await blockchainGatewayExplorerProvider . getChildren ( group ) as LocalGatewayTreeItem [ ] ; groupGateways [ 0 ] . label . should . equal ( `Org1 ⧉` ) ; groupGateways [ 0 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; groupGateways [ 0 ] . gateway . should . deep . equal ( saasGateway ) ; groupGateways [ 0 ] . command . should . deep . equal ( myCommand ) ; groupGateways [ 0 ] . tooltip . should . deep . equal ( `ⓘ Associated wallet:\n    Org1 Wallet` ) ; } ) ; it ( 'should still display gateway if its environment has been deleted' , async ( ) => { await FabricGatewayRegistry . instance ( ) . clear ( ) ; await FabricEnvironmentRegistry . instance ( ) . clear ( ) ; await FabricWalletRegistry . instance ( ) . clear ( ) ; const opsToolsGateway = new FabricGatewayRegistryEntry ( { name : 'someGateway' , environmentGroup : 'opsToolsEnv' , associatedWallet : 'Org1 Wallet' , displayName : `Org1` , connectionProfilePath : 'some/file/path' } ) ; await FabricGatewayRegistry . instance ( ) . add ( opsToolsGateway ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; const myCommand = { command : ExtensionCommands . CONNECT_TO_GATEWAY , title : '' , arguments : [ { name : 'someGateway' , associatedWallet : 'Org1 Wallet' , displayName : `Org1` , connectionProfilePath : 'some/file/path' } ] } ; allChildren . length . should . equal ( 1 ) ; allChildren [ 0 ] . should . be . an . instanceOf ( GatewayGroupTreeItem ) ; const group = allChildren [ 0 ] as GatewayGroupTreeItem ; group . label . should . equal ( 'Other gateways' ) ; const groupGateways = await blockchainGatewayExplorerProvider . getChildren ( group ) as LocalGatewayTreeItem [ ] ; groupGateways [ 0 ] . label . should . equal ( `Org1 ⧉` ) ; groupGateways [ 0 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; groupGateways [ 0 ] . gateway . should . deep . equal ( { name : 'someGateway' , associatedWallet : 'Org1 Wallet' , displayName : `Org1` , connectionProfilePath : 'some/file/path' } ) ; groupGateways [ 0 ] . command . should . deep . equal ( myCommand ) ; groupGateways [ 0 ] . tooltip . should . deep . equal ( `ⓘ Associated wallet:\n    Org1 Wallet` ) ; } ) ; it ( 'should display multiple gateway groups' , async ( ) => { await FabricGatewayRegistry . instance ( ) . clear ( ) ; await FabricEnvironmentRegistry . instance ( ) . clear ( ) ; await FabricWalletRegistry . instance ( ) . clear ( ) ; const gateway1 = new FabricGatewayRegistryEntry ( { name : 'gateway1' , environmentGroup : 'someEnvironment' , associatedWallet : 'Org1 Wallet' , displayName : 'Org1' , connectionProfilePath : 'some/file/path' } ) ; const gateway2 = new FabricGatewayRegistryEntry ( { name : 'gateway2' , environmentGroup : 'someOtherEnvironment' , associatedWallet : 'Org1 Wallet' , displayName : 'Org1' , connectionProfilePath : 'some/file/path' } ) ; const gateway3 = new FabricGatewayRegistryEntry ( { name : 'gateway3' , associatedWallet : 'Org1 Wallet' , displayName : 'Org1' , connectionProfilePath : 'some/file/path' } ) ; await FabricGatewayRegistry . instance ( ) . add ( gateway1 ) ; await FabricGatewayRegistry . instance ( ) . add ( gateway2 ) ; await FabricGatewayRegistry . instance ( ) . add ( gateway3 ) ; mySandBox . stub ( FabricEnvironmentRegistry . instance ( ) , 'exists' ) . resolves ( true ) ; const getEnvironmentStub = mySandBox . stub ( FabricEnvironmentRegistry . instance ( ) , 'get' ) ; getEnvironmentStub . withArgs ( 'someEnvironment' ) . resolves ( { name : 'someEnvironment' } ) ; getEnvironmentStub . withArgs ( 'someOtherEnvironment' ) . resolves ( { name : 'someOtherEnvironment' } ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; allChildren . length . should . equal ( 3 ) ; allChildren [ 0 ] . should . be . an . instanceOf ( GatewayGroupTreeItem ) ; const group1 = allChildren [ 0 ] as GatewayGroupTreeItem ; group1 . label . should . equal ( 'someEnvironment' ) ; group1 . gateways . should . deep . equal ( [ gateway1 ] ) ; allChildren [ 1 ] . should . be . an . instanceOf ( GatewayGroupTreeItem ) ; const group2 = allChildren [ 1 ] as GatewayGroupTreeItem ; group2 . label . should . equal ( 'someOtherEnvironment' ) ; group2 . gateways . should . deep . equal ( [ gateway2 ] ) ; allChildren [ 2 ] . should . be . an . instanceOf ( GatewayGroupTreeItem ) ; const group3 = allChildren [ 2 ] as GatewayGroupTreeItem ; group3 . label . should . equal ( 'Other gateways' ) ; group3 . gateways . should . deep . equal ( [ gateway3 ] ) ; } ) ; it ( 'should handle errors thrown when connection fails' , async ( ) => { const fabricConnection = mySandBox . createStubInstance ( FabricGatewayConnection ) ; const fabricConnectionManager = FabricGatewayConnectionManager . instance ( ) ; getConnectionStub . returns ( fabricConnection ) ; getConnectionStub . onCall ( 1 ) . throws ( { message : 'cannot connect' } ) ; const disconnnectStub = mySandBox . stub ( fabricConnectionManager , 'disconnect' ) . returns ( undefined ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; await blockchainGatewayExplorerProvider . getChildren ( ) ; disconnnectStub . should . have . been . calledOnce ; logSpy . should . have . been . calledWith ( LogType . ERROR , `cannot connect` ) ; } ) ; it ( 'should error if createChannelMap fails' , async ( ) => { const fabricConnection = mySandBox . createStubInstance ( FabricGatewayConnection ) ; getConnectionStub . returns ( fabricConnection ) ; fabricConnection . getAllPeerNames . returns ( [ 'peerOne' ] ) ; fabricConnection . createChannelMap . callThrough ( ) ; fabricConnection . getAllChannelsForPeer . throws ( { message : 'some error' } ) ; const registryEntry = new FabricGatewayRegistryEntry ( ) ; registryEntry . name = 'myGateway' ; mySandBox . stub ( FabricGatewayConnectionManager . instance ( ) , 'getGatewayRegistryEntry' ) . resolves ( registryEntry ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const disconnectSpy = mySandBox . spy ( blockchainGatewayExplorerProvider , 'disconnect' ) ; const allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) ; disconnectSpy . should . have . been . called ; logSpy . should . have . been . calledWith ( LogType . ERROR , `Could not connect to gateway: Error querying channel list: some error` ) ; } ) ; it ( 'should error if gRPC cant connect to Fabric' , async ( ) => { const fabricConnection = mySandBox . createStubInstance ( FabricGatewayConnection ) ; getConnectionStub . returns ( fabricConnection ) ; fabricConnection . getAllPeerNames . returns ( [ 'peerOne' ] ) ; fabricConnection . createChannelMap . callThrough ( ) ; fabricConnection . getAllChannelsForPeer . throws ( { message : 'Received http2 header with status: 503' } ) ; const registryEntry = new FabricGatewayRegistryEntry ( ) ; registryEntry . name = 'myGateway' ; registryEntry . associatedWallet = 'some_wallet' ; mySandBox . stub ( FabricGatewayConnectionManager . instance ( ) , 'getGatewayRegistryEntry' ) . resolves ( registryEntry ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const disconnectSpy = mySandBox . spy ( blockchainGatewayExplorerProvider , 'disconnect' ) ; const allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) ; disconnectSpy . should . have . been . called ; logSpy . should . have . been . calledWith ( LogType . ERROR , `Could not connect to gateway: Cannot connect to Fabric: Received http2 header with status: 503` ) ; } ) ; } ) ; describe ( 'connected tree' , ( ) => { let allChildren ; let blockchainGatewayExplorerProvider ; let fabricConnection ; let registryEntry ; let getGatewayRegistryEntryStub ; beforeEach ( async ( ) => { fabricConnection = mySandBox . createStubInstance ( FabricGatewayConnection ) ; fabricConnection . getAllPeerNames . returns ( [ 'peerOne' , 'peerTwo' ] ) ; fabricConnection . getAllChannelsForPeer . withArgs ( 'peerOne' ) . resolves ( [ 'channelOne' , 'channelTwo' ] ) ; fabricConnection . getAllChannelsForPeer . withArgs ( 'peerTwo' ) . resolves ( [ 'channelTwo' ] ) ; fabricConnection . getInstantiatedChaincode . withArgs ( 'channelOne' ) . resolves ( [ { name : 'biscuit-network' , version : '0.7' } ] ) ; fabricConnection . getInstantiatedChaincode . withArgs ( 'channelTwo' ) . resolves ( [ { name : 'cake-network' , version : '0.10' } , { name : 'legacy-network' , version : '2.34' } , { name : 'biscuit-network' , version : '0.7' } ] ) ; fabricConnection . getMetadata . withArgs ( 'biscuit-network' , 'channelOne' ) . resolves ( { contracts : { 'my-contract' : { name : 'my-contract' , transactions : [ { name : 'tradeBiscuits' } , { name : 'bourbons' } ] , } , 'someOtherContract' : { name : 'someOtherContract' , transactions : [ { name : 'shortbread' } , { name : 'hobnobs' } ] , } } } ) ; fabricConnection . getMetadata . withArgs ( 'biscuit-network' , 'channelTwo' ) . resolves ( { contracts : { 'my-contract' : { name : 'my-contract' , transactions : [ { name : 'tradeBiscuits' } , { name : 'bourbons' } ] , } , 'someOtherContract' : { name : 'someOtherContract' , transactions : [ { name : 'shortbread' } , { name : 'hobnobs' } ] , } } } ) ; fabricConnection . getMetadata . withArgs ( 'cake-network' , 'channelTwo' ) . resolves ( { contracts : { 'my-contract' : { name : 'my-contract' , transactions : [ ] , } } } ) ; const map = new Map < string , Array < string > > ( ) ; map . set ( 'channelOne' , [ 'peerOne' ] ) ; map . set ( 'channelTwo' , [ 'peerOne' , 'peerTwo' ] ) ; fabricConnection . getAllChannelsForPeer . withArgs ( 'peerTwo' ) . resolves ( [ 'channelTwo' ] ) ; fabricConnection . createChannelMap . resolves ( map ) ; fabricConnection . identityName = 'pigeon' ; fabricConnection . getChannelCapabilityFromPeer . resolves ( [ UserInputUtil . V2_0 ] ) ; fabricConnection . getMetadata . withArgs ( 'legacy-network' , 'channelTwo' ) . resolves ( null ) ; blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const fabricConnectionManager = FabricGatewayConnectionManager . instance ( ) ; mySandBox . stub ( fabricConnectionManager , 'getConnection' ) . returns ( ( fabricConnection as any ) as FabricGatewayConnection ) ; registryEntry = new FabricGatewayRegistryEntry ( ) ; registryEntry . name = 'myGateway' ; registryEntry . associatedWallet = 'some_wallet' ; getGatewayRegistryEntryStub = mySandBox . stub ( FabricGatewayConnectionManager . instance ( ) , 'getGatewayRegistryEntry' ) . resolves ( registryEntry ) ; allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; } ) ; afterEach ( ( ) => { mySandBox . restore ( ) ; } ) ; it ( 'should create a connected tree if there is a connection' , async ( ) => { allChildren . length . should . equal ( 3 ) ; const connectedItem1 = allChildren [ 0 ] as ConnectedTreeItem ; connectedItem1 . label . should . equal ( 'Connected via gateway: myGateway' ) ; connectedItem1 . contextValue . should . equal ( 'blockchain-connected-item' ) ; connectedItem1 . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; connectedItem1 . connection . name . should . equal ( 'myGateway' ) ; const connectedItem2 = allChildren [ 1 ] as ConnectedTreeItem ; connectedItem2 . label . should . equal ( 'Using ID: pigeon' ) ; connectedItem2 . contextValue . should . equal ( 'blockchain-connected-item' ) ; connectedItem2 . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; connectedItem2 . connection . name . should . equal ( 'myGateway' ) ; const connectedItem3 = allChildren [ 2 ] as ConnectedTreeItem ; connectedItem3 . label . should . equal ( 'Channels' ) ; connectedItem3 . contextValue . should . equal ( 'blockchain-connected-item' ) ; connectedItem3 . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Expanded ) ; connectedItem3 . connection . name . should . equal ( 'myGateway' ) ; const channels = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) as Array < ChannelTreeItem > ; const channelOne = channels [ 0 ] ; channelOne . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; channelOne . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; channelOne . contextValue . should . equal ( 'blockchain-channel-item' ) ; channelOne . label . should . equal ( 'channelOne' ) ; channelOne . peers . should . deep . equal ( [ 'peerOne' ] ) ; const channelTwo = channels [ 1 ] ; channelTwo . tooltip . should . equal ( `Associated peers: peerOne, peerTwo\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; channelTwo . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; channelTwo . contextValue . should . equal ( 'blockchain-channel-item' ) ; channelTwo . label . should . equal ( 'channelTwo' ) ; channelTwo . peers . should . deep . equal ( [ 'peerOne' , 'peerTwo' ] ) ; } ) ; it ( 'should update connected to context value if managed runtime' , async ( ) => { await TestUtil . startLocalFabric ( ) ; registryEntry = await FabricGatewayRegistry . instance ( ) . get ( `${ FabricRuntimeUtil . LOCAL_FABRIC } - Org1 Gateway` ) ; getGatewayRegistryEntryStub . resolves ( registryEntry ) ; allChildren = await ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) . getChildren ( ) ; allChildren . length . should . equal ( 3 ) ; const connectedItem = allChildren [ 0 ] as ConnectedTreeItem ; connectedItem . label . should . equal ( `Connected via gateway: ${ registryEntry . name }` ) ; connectedItem . contextValue . should . equal ( 'blockchain-connected-runtime-item' ) ; connectedItem . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; connectedItem . connection . name . should . equal ( registryEntry . name ) ; const channels = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) as Array < ChannelTreeItem > ; const channelOne = channels [ 0 ] ; channelOne . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; channelOne . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; channelOne . contextValue . should . equal ( 'blockchain-channel-item' ) ; channelOne . label . should . equal ( 'channelOne' ) ; channelOne . peers . should . deep . equal ( [ 'peerOne' ] ) ; const channelTwo = channels [ 1 ] ; channelTwo . tooltip . should . equal ( `Associated peers: peerOne, peerTwo\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; channelTwo . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; channelTwo . contextValue . should . equal ( 'blockchain-channel-item' ) ; channelTwo . label . should . equal ( 'channelTwo' ) ; channelTwo . peers . should . deep . equal ( [ 'peerOne' , 'peerTwo' ] ) ; } ) ; it ( 'should create channel children correctly' , async ( ) => { allChildren . length . should . equal ( 3 ) ; const channels = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) as Array < ChannelTreeItem > ; channels [ 0 ] . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; channels [ 1 ] . tooltip . should . equal ( `Associated peers: peerOne, peerTwo\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; let instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channels [ 0 ] ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 1 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; const channelChildrenOne = await blockchainGatewayExplorerProvider . getChildren ( channels [ 0 ] ) ; channelChildrenOne . length . should . equal ( 1 ) ; const instantiatedTreeItemOne = channelChildrenOne [ 0 ] as InstantiatedContractTreeItem ; instantiatedTreeItemOne . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; instantiatedTreeItemOne . name . should . equal ( 'biscuit-network' ) ; instantiatedTreeItemOne . version . should . equal ( '0.7' ) ; instantiatedTreeItemOne . label . should . equal ( 'biscuit-network@0.7' ) ; instantiatedTreeItemOne . contextValue . should . equal ( 'blockchain-instantiated-multi-contract-item' ) ; instantiatedTreeItemOne . channels [ 0 ] . label . should . equal ( 'channelOne' ) ; instantiatedTreeItemOne . channels . length . should . equal ( 1 ) ; instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channels [ 1 ] ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 3 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 1 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 2 ] ) ; const channelChildrenTwo = await blockchainGatewayExplorerProvider . getChildren ( channels [ 1 ] ) ; channelChildrenTwo . length . should . equal ( 3 ) ; const instantiatedTreeItemTwo = channelChildrenTwo [ 0 ] as InstantiatedContractTreeItem ; instantiatedTreeItemTwo . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; instantiatedTreeItemTwo . name . should . equal ( 'cake-network' ) ; instantiatedTreeItemTwo . version . should . equal ( '0.10' ) ; instantiatedTreeItemTwo . label . should . equal ( 'cake-network@0.10' ) ; instantiatedTreeItemTwo . contextValue . should . equal ( 'blockchain-instantiated-contract-item' ) ; instantiatedTreeItemTwo . channels [ 0 ] . label . should . equal ( 'channelTwo' ) ; instantiatedTreeItemTwo . channels . length . should . equal ( 1 ) ; const instantiatedTreeItemThree = channelChildrenTwo [ 1 ] as InstantiatedChaincodeTreeItem ; instantiatedTreeItemThree . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; instantiatedTreeItemThree . name . should . equal ( 'legacy-network' ) ; instantiatedTreeItemThree . version . should . equal ( '2.34' ) ; instantiatedTreeItemThree . label . should . equal ( 'legacy-network@2.34' ) ; instantiatedTreeItemThree . contextValue . should . equal ( 'blockchain-instantiated-chaincode-item' ) ; instantiatedTreeItemThree . channels [ 0 ] . label . should . equal ( 'channelTwo' ) ; instantiatedTreeItemThree . channels . length . should . equal ( 1 ) ; const instantiatedTreeItemFour = channelChildrenTwo [ 2 ] as InstantiatedContractTreeItem ; instantiatedTreeItemFour . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; instantiatedTreeItemFour . name . should . equal ( 'biscuit-network' ) ; instantiatedTreeItemFour . version . should . equal ( '0.7' ) ; instantiatedTreeItemFour . label . should . equal ( 'biscuit-network@0.7' ) ; instantiatedTreeItemFour . contextValue . should . equal ( 'blockchain-instantiated-multi-contract-item' ) ; instantiatedTreeItemFour . channels [ 0 ] . label . should . equal ( 'channelTwo' ) ; instantiatedTreeItemFour . channels . length . should . equal ( 1 ) ; } ) ; it ( 'should not create anything if no peers' , async ( ) => { fabricConnection . getAllPeerNames . returns ( [ ] ) ; allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; allChildren . length . should . equal ( 3 ) ; allChildren [ 0 ] . label . should . equal ( 'Connected via gateway: myGateway' ) ; } ) ; it ( 'should error if problem with instantiate chaincodes' , async ( ) => { fabricConnection . getInstantiatedChaincode . withArgs ( 'channelOne' ) . rejects ( { message : 'some error' } ) ; allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; allChildren . length . should . equal ( 3 ) ; const channels = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) as Array < ChannelTreeItem > ; channels . length . should . equal ( 2 ) ; logSpy . should . have . been . calledWith ( LogType . ERROR , 'Error getting instantiated smart contracts for channel channelOne some error' ) ; const channelOne = channels [ 0 ] ; channelOne . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; channelOne . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; channelOne . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; const channelChildrenOne = await blockchainGatewayExplorerProvider . getChildren ( channelOne ) ; channelChildrenOne . length . should . equal ( 0 ) ; } ) ; it ( 'should handle no instantiated chaincodes' , async ( ) => { fabricConnection . getInstantiatedChaincode . withArgs ( 'channelOne' ) . resolves ( [ ] ) ; allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; allChildren . length . should . equal ( 3 ) ; const channels = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) as Array < ChannelTreeItem > ; channels . length . should . equal ( 2 ) ; const channelOne = channels [ 0 ] ; channelOne . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; channelOne . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; channelOne . contextValue . should . equal ( 'blockchain-channel-item' ) ; channelOne . label . should . equal ( 'channelOne' ) ; channelOne . peers . should . deep . equal ( [ 'peerOne' ] ) ; const channelChildrenOne = await blockchainGatewayExplorerProvider . getChildren ( channelOne ) ; channelChildrenOne . length . should . equal ( 0 ) ; const channelTwo = channels [ 1 ] ; channelTwo . tooltip . should . equal ( `Associated peers: peerOne, peerTwo\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; channelTwo . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; channelTwo . contextValue . should . equal ( 'blockchain-channel-item' ) ; channelTwo . label . should . equal ( 'channelTwo' ) ; channelTwo . peers . should . deep . equal ( [ 'peerOne' , 'peerTwo' ] ) ; const instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channelTwo ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 3 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 1 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 2 ] ) ; const channelChildrenTwo = await blockchainGatewayExplorerProvider . getChildren ( channelTwo ) ; channelChildrenTwo . length . should . equal ( 3 ) ; const instantiatedTreeItemTwo = channelChildrenTwo [ 0 ] as InstantiatedContractTreeItem ; instantiatedTreeItemTwo . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; instantiatedTreeItemTwo . name . should . equal ( 'cake-network' ) ; instantiatedTreeItemTwo . version . should . equal ( '0.10' ) ; instantiatedTreeItemTwo . label . should . equal ( 'cake-network@0.10' ) ; instantiatedTreeItemTwo . contextValue . should . equal ( 'blockchain-instantiated-contract-item' ) ; instantiatedTreeItemTwo . channels [ 0 ] . label . should . equal ( 'channelTwo' ) ; instantiatedTreeItemTwo . channels . length . should . equal ( 1 ) ; const instantiatedTreeItemThree = channelChildrenTwo [ 1 ] as InstantiatedChaincodeTreeItem ; instantiatedTreeItemThree . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; instantiatedTreeItemThree . name . should . equal ( 'legacy-network' ) ; instantiatedTreeItemThree . version . should . equal ( '2.34' ) ; instantiatedTreeItemThree . label . should . equal ( 'legacy-network@2.34' ) ; instantiatedTreeItemThree . contextValue . should . equal ( 'blockchain-instantiated-chaincode-item' ) ; instantiatedTreeItemThree . channels [ 0 ] . label . should . equal ( 'channelTwo' ) ; instantiatedTreeItemThree . channels . length . should . equal ( 1 ) ; const instantiatedTreeItemFour = channelChildrenTwo [ 2 ] as InstantiatedContractTreeItem ; instantiatedTreeItemFour . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; instantiatedTreeItemFour . name . should . equal ( 'biscuit-network' ) ; instantiatedTreeItemFour . version . should . equal ( '0.7' ) ; instantiatedTreeItemFour . label . should . equal ( 'biscuit-network@0.7' ) ; instantiatedTreeItemFour . contextValue . should . equal ( 'blockchain-instantiated-multi-contract-item' ) ; instantiatedTreeItemFour . channels [ 0 ] . label . should . equal ( 'channelTwo' ) ; instantiatedTreeItemFour . channels . length . should . equal ( 1 ) ; logSpy . should . not . have . been . calledWith ( LogType . ERROR ) ; } ) ; it ( 'should create instantiated chaincode correctly' , async ( ) => { allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; allChildren . length . should . equal ( 3 ) ; const channels = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) as Array < ChannelTreeItem > ; let instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channels [ 0 ] ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 1 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; const channelOne = channels [ 0 ] ; channelOne . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; const channelChildrenOne = await blockchainGatewayExplorerProvider . getChildren ( channelOne ) ; channelChildrenOne . length . should . equal ( 1 ) ; const instantiatedChaincodeItemOne = channelChildrenOne [ 0 ] as InstantiatedContractTreeItem ; instantiatedChaincodeItemOne . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; instantiatedChaincodeItemOne . contextValue . should . equal ( 'blockchain-instantiated-multi-contract-item' ) ; instantiatedChaincodeItemOne . label . should . equal ( 'biscuit-network@0.7' ) ; instantiatedChaincodeItemOne . channels [ 0 ] . should . equal ( channelOne ) ; instantiatedChaincodeItemOne . channels . length . should . equal ( 1 ) ; instantiatedChaincodeItemOne . version . should . equal ( '0.7' ) ; instantiatedChaincodeItemOne . contracts . should . deep . equal ( [ 'my-contract' , 'someOtherContract' ] ) ; const channelTwo = channels [ 1 ] ; channelTwo . tooltip . should . equal ( `Associated peers: peerOne, peerTwo\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channels [ 1 ] ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 3 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 1 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 2 ] ) ; const channelChildrenTwo = await blockchainGatewayExplorerProvider . getChildren ( channelTwo ) ; channelChildrenTwo . length . should . equal ( 3 ) ; const instantiatedChaincodeItemTwo = channelChildrenTwo [ 0 ] as InstantiatedContractTreeItem ; instantiatedChaincodeItemTwo . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; instantiatedChaincodeItemTwo . contextValue . should . equal ( 'blockchain-instantiated-contract-item' ) ; instantiatedChaincodeItemTwo . label . should . equal ( 'cake-network@0.10' ) ; instantiatedChaincodeItemTwo . channels [ 0 ] . should . equal ( channelTwo ) ; instantiatedChaincodeItemTwo . channels . length . should . equal ( 1 ) ; instantiatedChaincodeItemTwo . version . should . equal ( '0.10' ) ; instantiatedChaincodeItemTwo . contracts . should . deep . equal ( [ ] ) ; const instantiatedChaincodeItemThree = channelChildrenTwo [ 1 ] as InstantiatedChaincodeTreeItem ; instantiatedChaincodeItemThree . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; instantiatedChaincodeItemThree . contextValue . should . equal ( 'blockchain-instantiated-chaincode-item' ) ; instantiatedChaincodeItemThree . label . should . equal ( 'legacy-network@2.34' ) ; instantiatedChaincodeItemThree . channels [ 0 ] . should . equal ( channelTwo ) ; instantiatedChaincodeItemThree . channels . length . should . equal ( 1 ) ; instantiatedChaincodeItemThree . version . should . equal ( '2.34' ) ; should . equal ( instantiatedChaincodeItemThree . contracts , undefined ) ; const instantiatedTreeItemFour = channelChildrenTwo [ 2 ] as InstantiatedContractTreeItem ; instantiatedTreeItemFour . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; instantiatedTreeItemFour . name . should . equal ( 'biscuit-network' ) ; instantiatedTreeItemFour . version . should . equal ( '0.7' ) ; instantiatedTreeItemFour . label . should . equal ( 'biscuit-network@0.7' ) ; instantiatedTreeItemFour . contextValue . should . equal ( 'blockchain-instantiated-multi-contract-item' ) ; instantiatedTreeItemFour . channels [ 0 ] . label . should . equal ( 'channelTwo' ) ; instantiatedTreeItemFour . channels . length . should . equal ( 1 ) ; logSpy . should . not . have . been . calledWith ( LogType . ERROR ) ; } ) ; it ( 'should create the contract tree correctly' , async ( ) => { allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; allChildren . length . should . equal ( 3 ) ; const channels = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) as Array < ChannelTreeItem > ; const channelOne = channels [ 0 ] ; channelOne . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; let instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channelOne ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 1 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; const channelChildrenOne = await blockchainGatewayExplorerProvider . getChildren ( channelOne ) ; channelChildrenOne . length . should . equal ( 1 ) ; const instantiatedChaincodeItemOne = channelChildrenOne [ 0 ] as InstantiatedContractTreeItem ; const contractsOne = await blockchainGatewayExplorerProvider . getChildren ( instantiatedChaincodeItemOne ) as Array < ContractTreeItem > ; contractsOne . length . should . equal ( 2 ) ; contractsOne [ 0 ] . label . should . equal ( 'my-contract' ) ; contractsOne [ 0 ] . instantiatedChaincode . name . should . equal ( 'biscuit-network' ) ; contractsOne [ 0 ] . instantiatedChaincode . channels [ 0 ] . label . should . equal ( 'channelOne' ) ; contractsOne [ 0 ] . instantiatedChaincode . channels . length . should . equal ( 1 ) ; contractsOne [ 0 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; contractsOne [ 1 ] . label . should . equal ( 'someOtherContract' ) ; contractsOne [ 1 ] . instantiatedChaincode . name . should . equal ( 'biscuit-network' ) ; contractsOne [ 1 ] . instantiatedChaincode . channels [ 0 ] . label . should . equal ( 'channelOne' ) ; contractsOne [ 1 ] . instantiatedChaincode . channels . length . should . equal ( 1 ) ; contractsOne [ 1 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; const channelTwo = channels [ 1 ] ; channelTwo . tooltip . should . equal ( `Associated peers: peerOne, peerTwo\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channelTwo ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 3 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; const channelChildrenTwo = await blockchainGatewayExplorerProvider . getChildren ( channelTwo ) ; channelChildrenTwo . length . should . equal ( 3 ) ; const instantiatedChaincodeItemTwo = channelChildrenTwo [ 0 ] as InstantiatedContractTreeItem ; const contractsTwo = await blockchainGatewayExplorerProvider . getChildren ( instantiatedChaincodeItemTwo ) as Array < ContractTreeItem > ; contractsTwo . should . deep . equal ( [ ] ) ; instantiatedChaincodeItemTwo . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; logSpy . should . not . have . been . calledWith ( LogType . ERROR ) ; } ) ; it ( 'should show the transactions and not contracts if the contract name is empty' , async ( ) => { fabricConnection . getMetadata . withArgs ( 'biscuit-network' , 'channelOne' ) . resolves ( { contracts : { '' : { name : '' , transactions : [ { name : 'tradeBiscuits' } , { name : 'bourbons' } ] , } } } ) ; allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; allChildren . length . should . equal ( 3 ) ; const channels = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) as Array < ChannelTreeItem > ; const channelOne = channels [ 0 ] ; channelOne . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; const instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channelOne ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 1 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; const channelChildrenOne = await blockchainGatewayExplorerProvider . getChildren ( channelOne ) ; channelChildrenOne . length . should . equal ( 1 ) ; const instantiatedChaincodeItemOne = channelChildrenOne [ 0 ] as InstantiatedContractTreeItem ; const transactions = await blockchainGatewayExplorerProvider . getChildren ( instantiatedChaincodeItemOne ) as Array < TransactionTreeItem > ; transactions . length . should . equal ( 2 ) ; transactions [ 0 ] . label . should . equal ( 'tradeBiscuits' ) ; transactions [ 0 ] . chaincodeName . should . equal ( 'biscuit-network' ) ; transactions [ 0 ] . channelName . should . equal ( 'channelOne' ) ; transactions [ 0 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; transactions [ 0 ] . contractName . should . equal ( '' ) ; transactions [ 1 ] . label . should . equal ( 'bourbons' ) ; transactions [ 1 ] . chaincodeName . should . equal ( 'biscuit-network' ) ; transactions [ 1 ] . channelName . should . equal ( 'channelOne' ) ; transactions [ 1 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; transactions [ 1 ] . contractName . should . equal ( '' ) ; logSpy . should . not . have . been . calledWith ( LogType . ERROR ) ; } ) ; it ( 'should show the transactions and not contracts if there is only one contract' , async ( ) => { fabricConnection . getMetadata . withArgs ( 'cake-network' , 'channelTwo' ) . resolves ( { contracts : { 'my-contract' : { name : 'my-contract' , transactions : [ { name : 'garabaldi' } , { name : 'shortbread' } ] , } } } ) ; const channels = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) as Array < ChannelTreeItem > ; channels [ 0 ] . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; channels [ 1 ] . tooltip . should . equal ( `Associated peers: peerOne, peerTwo\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; const instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channels [ 1 ] ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 3 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 1 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 2 ] ) ; const channelChildren = await blockchainGatewayExplorerProvider . getChildren ( channels [ 1 ] ) ; const instantiatedChaincodeItemOne = channelChildren [ 0 ] as InstantiatedContractTreeItem ; const transactions = await blockchainGatewayExplorerProvider . getChildren ( instantiatedChaincodeItemOne ) as Array < TransactionTreeItem > ; transactions . length . should . equal ( 2 ) ; transactions [ 0 ] . label . should . equal ( 'garabaldi' ) ; transactions [ 0 ] . chaincodeName . should . equal ( 'cake-network' ) ; transactions [ 0 ] . channelName . should . equal ( 'channelTwo' ) ; transactions [ 0 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; transactions [ 0 ] . contractName . should . equal ( 'my-contract' ) ; transactions [ 1 ] . label . should . equal ( 'shortbread' ) ; transactions [ 1 ] . chaincodeName . should . equal ( 'cake-network' ) ; transactions [ 1 ] . channelName . should . equal ( 'channelTwo' ) ; transactions [ 1 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; transactions [ 1 ] . contractName . should . equal ( 'my-contract' ) ; logSpy . should . not . have . been . calledWith ( LogType . ERROR ) ; } ) ; it ( 'should create the transactions correctly' , async ( ) => { allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; allChildren . length . should . equal ( 3 ) ; const channels = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) as Array < ChannelTreeItem > ; const channelOne = channels [ 0 ] ; channelOne . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; let instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channelOne ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 1 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; const channelChildrenOne = await blockchainGatewayExplorerProvider . getChildren ( channelOne ) ; channelChildrenOne . length . should . equal ( 1 ) ; const instantiatedChaincodeItemOne = channelChildrenOne [ 0 ] as InstantiatedContractTreeItem ; const contractsOne = await blockchainGatewayExplorerProvider . getChildren ( instantiatedChaincodeItemOne ) as Array < ContractTreeItem > ; const transactionsOneMyContract = await blockchainGatewayExplorerProvider . getChildren ( contractsOne [ 0 ] ) as Array < TransactionTreeItem > ; transactionsOneMyContract . length . should . equal ( 2 ) ; transactionsOneMyContract [ 0 ] . label . should . equal ( 'tradeBiscuits' ) ; transactionsOneMyContract [ 0 ] . chaincodeName . should . equal ( 'biscuit-network' ) ; transactionsOneMyContract [ 0 ] . channelName . should . equal ( 'channelOne' ) ; transactionsOneMyContract [ 0 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; transactionsOneMyContract [ 0 ] . contractName . should . equal ( 'my-contract' ) ; transactionsOneMyContract [ 1 ] . label . should . equal ( 'bourbons' ) ; transactionsOneMyContract [ 1 ] . chaincodeName . should . equal ( 'biscuit-network' ) ; transactionsOneMyContract [ 1 ] . channelName . should . equal ( 'channelOne' ) ; transactionsOneMyContract [ 1 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; transactionsOneMyContract [ 1 ] . contractName . should . equal ( 'my-contract' ) ; const transactionsOneSomeOtherContract = await blockchainGatewayExplorerProvider . getChildren ( contractsOne [ 1 ] ) as Array < TransactionTreeItem > ; transactionsOneSomeOtherContract . length . should . equal ( 2 ) ; transactionsOneSomeOtherContract [ 0 ] . label . should . equal ( 'shortbread' ) ; transactionsOneSomeOtherContract [ 0 ] . chaincodeName . should . equal ( 'biscuit-network' ) ; transactionsOneSomeOtherContract [ 0 ] . channelName . should . equal ( 'channelOne' ) ; transactionsOneSomeOtherContract [ 0 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; transactionsOneSomeOtherContract [ 0 ] . contractName . should . equal ( 'someOtherContract' ) ; transactionsOneSomeOtherContract [ 1 ] . label . should . equal ( 'hobnobs' ) ; transactionsOneSomeOtherContract [ 1 ] . chaincodeName . should . equal ( 'biscuit-network' ) ; transactionsOneSomeOtherContract [ 1 ] . channelName . should . equal ( 'channelOne' ) ; transactionsOneSomeOtherContract [ 1 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; transactionsOneSomeOtherContract [ 1 ] . contractName . should . equal ( 'someOtherContract' ) ; const channelTwo = channels [ 1 ] ; channelTwo . tooltip . should . equal ( `Associated peers: peerOne, peerTwo\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channelTwo ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 3 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 2 ] ) ; const channelChildrenTwo = await blockchainGatewayExplorerProvider . getChildren ( channelTwo ) ; channelChildrenTwo . length . should . equal ( 3 ) ; const instantiatedChaincodeItemTwo = channelChildrenTwo [ 0 ] as InstantiatedContractTreeItem ; instantiatedChaincodeItemTwo . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; const instantiatedChaincodeItemThree = channelChildrenTwo [ 2 ] as InstantiatedContractTreeItem ; const contractsTwo = await blockchainGatewayExplorerProvider . getChildren ( instantiatedChaincodeItemThree ) as Array < ContractTreeItem > ; const transactionsTwoMyContract = await blockchainGatewayExplorerProvider . getChildren ( contractsTwo [ 1 ] ) as Array < TransactionTreeItem > ; transactionsTwoMyContract . length . should . equal ( 2 ) ; transactionsTwoMyContract [ 0 ] . label . should . equal ( 'shortbread' ) ; transactionsTwoMyContract [ 0 ] . chaincodeName . should . equal ( 'biscuit-network' ) ; transactionsTwoMyContract [ 0 ] . channelName . should . equal ( 'channelTwo' ) ; transactionsTwoMyContract [ 0 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; transactionsTwoMyContract [ 0 ] . contractName . should . equal ( 'someOtherContract' ) ; transactionsTwoMyContract [ 1 ] . label . should . equal ( 'hobnobs' ) ; transactionsTwoMyContract [ 1 ] . chaincodeName . should . equal ( 'biscuit-network' ) ; transactionsTwoMyContract [ 1 ] . channelName . should . equal ( 'channelTwo' ) ; transactionsTwoMyContract [ 1 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; transactionsTwoMyContract [ 1 ] . contractName . should . equal ( 'someOtherContract' ) ; logSpy . should . not . have . been . calledWith ( LogType . ERROR ) ; } ) ; it ( `should create instantiated chaincode correctly when there are txdata associations` , async ( ) => { const gateway = new FabricGatewayRegistryEntry ( ) ; gateway . name = 'myGateway' ; gateway . associatedWallet = 'some_wallet' ; gateway . transactionDataDirectories = [ { chaincodeName : 'cake-network' , channelName : 'channelTwo' , transactionDataPath : 'some/file/path' } , { chaincodeName : 'legacy-network' , channelName : 'channelTwo' , transactionDataPath : 'some/other/file/path' } , { chaincodeName : 'biscuit-network' , channelName : 'channelOne' , transactionDataPath : 'different/file/path' } , { chaincodeName : 'biscuit-network' , channelName : 'channelTwo' , transactionDataPath : 'different/file/path' } ] ; getGatewayRegistryEntryStub . returns ( gateway ) ; allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; allChildren . length . should . equal ( 3 ) ; const channels = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) as Array < ChannelTreeItem > ; let instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channels [ 0 ] ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 1 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; const channelOne = channels [ 0 ] ; channelOne . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; const channelChildrenOne = await blockchainGatewayExplorerProvider . getChildren ( channelOne ) ; channelChildrenOne . length . should . equal ( 1 ) ; const instantiatedChaincodeItemOne = channelChildrenOne [ 0 ] as InstantiatedContractTreeItem ; instantiatedChaincodeItemOne . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; instantiatedChaincodeItemOne . contextValue . should . equal ( 'blockchain-instantiated-associated-multi-contract-item' ) ; instantiatedChaincodeItemOne . label . should . equal ( 'biscuit-network@0.7' ) ; instantiatedChaincodeItemOne . channels [ 0 ] . should . equal ( channelOne ) ; instantiatedChaincodeItemOne . channels . length . should . equal ( 1 ) ; instantiatedChaincodeItemOne . version . should . equal ( '0.7' ) ; instantiatedChaincodeItemOne . contracts . should . deep . equal ( [ 'my-contract' , 'someOtherContract' ] ) ; const channelTwo = channels [ 1 ] ; channelTwo . tooltip . should . equal ( `Associated peers: peerOne, peerTwo\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channels [ 1 ] ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 3 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 1 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 2 ] ) ; const channelChildrenTwo = await blockchainGatewayExplorerProvider . getChildren ( channelTwo ) ; channelChildrenTwo . length . should . equal ( 3 ) ; const instantiatedChaincodeItemTwo = channelChildrenTwo [ 0 ] as InstantiatedContractTreeItem ; instantiatedChaincodeItemTwo . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; instantiatedChaincodeItemTwo . contextValue . should . equal ( 'blockchain-instantiated-associated-contract-item' ) ; instantiatedChaincodeItemTwo . label . should . equal ( 'cake-network@0.10' ) ; instantiatedChaincodeItemTwo . channels [ 0 ] . should . equal ( channelTwo ) ; instantiatedChaincodeItemTwo . channels . length . should . equal ( 1 ) ; instantiatedChaincodeItemTwo . version . should . equal ( '0.10' ) ; instantiatedChaincodeItemTwo . contracts . should . deep . equal ( [ ] ) ; const instantiatedChaincodeItemThree = channelChildrenTwo [ 1 ] as InstantiatedChaincodeTreeItem ; instantiatedChaincodeItemThree . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; instantiatedChaincodeItemThree . contextValue . should . equal ( 'blockchain-instantiated-associated-chaincode-item' ) ; instantiatedChaincodeItemThree . label . should . equal ( 'legacy-network@2.34' ) ; instantiatedChaincodeItemThree . channels [ 0 ] . should . equal ( channelTwo ) ; instantiatedChaincodeItemThree . channels . length . should . equal ( 1 ) ; instantiatedChaincodeItemThree . version . should . equal ( '2.34' ) ; should . equal ( instantiatedChaincodeItemThree . contracts , undefined ) ; const instantiatedTreeItemFour = channelChildrenTwo [ 2 ] as InstantiatedContractTreeItem ; instantiatedTreeItemFour . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . Collapsed ) ; instantiatedTreeItemFour . name . should . equal ( 'biscuit-network' ) ; instantiatedTreeItemFour . version . should . equal ( '0.7' ) ; instantiatedTreeItemFour . label . should . equal ( 'biscuit-network@0.7' ) ; instantiatedTreeItemFour . contextValue . should . equal ( 'blockchain-instantiated-associated-multi-contract-item' ) ; instantiatedTreeItemFour . channels [ 0 ] . label . should . equal ( 'channelTwo' ) ; instantiatedTreeItemFour . channels . length . should . equal ( 1 ) ; logSpy . should . not . have . been . calledWith ( LogType . ERROR ) ; } ) ; it ( 'should show transactions correctly when there is a txdata association' , async ( ) => { const gateway = new FabricGatewayRegistryEntry ( ) ; gateway . name = 'myGateway' ; gateway . associatedWallet = 'some_wallet' ; gateway . transactionDataDirectories = [ { chaincodeName : 'cake-network' , channelName : 'channelTwo' , transactionDataPath : 'some/file/path' } ] ; getGatewayRegistryEntryStub . returns ( gateway ) ; fabricConnection . getMetadata . withArgs ( 'cake-network' , 'channelTwo' ) . resolves ( { contracts : { 'my-contract' : { name : 'my-contract' , transactions : [ { name : 'garabaldi' } , { name : 'shortbread' } ] , } } } ) ; const channels = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 2 ] ) as Array < ChannelTreeItem > ; channels [ 0 ] . tooltip . should . equal ( `Associated peers: peerOne\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; channels [ 1 ] . tooltip . should . equal ( `Associated peers: peerOne, peerTwo\nChannel capabilities: ${ UserInputUtil . V2_0 }` ) ; const instantiatedUnknownChainCodes = await blockchainGatewayExplorerProvider . getChildren ( channels [ 1 ] ) as Array < InstantiatedUnknownTreeItem > ; instantiatedUnknownChainCodes . length . should . equal ( 3 ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 0 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 1 ] ) ; await blockchainGatewayExplorerProvider . getChildren ( instantiatedUnknownChainCodes [ 2 ] ) ; const channelChildren = await blockchainGatewayExplorerProvider . getChildren ( channels [ 1 ] ) ; const instantiatedChaincodeItemOne = channelChildren [ 0 ] as InstantiatedContractTreeItem ; const transactions = await blockchainGatewayExplorerProvider . getChildren ( instantiatedChaincodeItemOne ) as Array < TransactionTreeItem > ; transactions . length . should . equal ( 2 ) ; transactions [ 0 ] . label . should . equal ( 'garabaldi' ) ; transactions [ 0 ] . chaincodeName . should . equal ( 'cake-network' ) ; transactions [ 0 ] . channelName . should . equal ( 'channelTwo' ) ; transactions [ 0 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; transactions [ 0 ] . contractName . should . equal ( 'my-contract' ) ; transactions [ 1 ] . label . should . equal ( 'shortbread' ) ; transactions [ 1 ] . chaincodeName . should . equal ( 'cake-network' ) ; transactions [ 1 ] . channelName . should . equal ( 'channelTwo' ) ; transactions [ 1 ] . collapsibleState . should . equal ( vscode . TreeItemCollapsibleState . None ) ; transactions [ 1 ] . contractName . should . equal ( 'my-contract' ) ; logSpy . should . not . have . been . calledWith ( LogType . ERROR ) ; } ) ; } ) ; } ) ; describe ( 'refresh' , ( ) => { beforeEach ( async ( ) => { await ExtensionUtil . activateExtension ( ) ; } ) ; afterEach ( ( ) => { mySandBox . restore ( ) ; } ) ; it ( 'should test the tree is refreshed when the refresh command is run' , async ( ) => { const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const onDidChangeTreeDataSpy = mySandBox . spy ( blockchainGatewayExplorerProvider [ '_onDidChangeTreeData' ] , 'fire' ) ; await vscode . commands . executeCommand ( ExtensionCommands . REFRESH_GATEWAYS ) ; onDidChangeTreeDataSpy . should . have . been . called ; } ) ; it ( 'should test the tree is refreshed when the refresh command is run' , async ( ) => { const mockTreeItem = mySandBox . createStubInstance ( GatewayTreeItem ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const onDidChangeTreeDataSpy = mySandBox . spy ( blockchainGatewayExplorerProvider [ '_onDidChangeTreeData' ] , 'fire' ) ; await vscode . commands . executeCommand ( ExtensionCommands . REFRESH_GATEWAYS , mockTreeItem ) ; onDidChangeTreeDataSpy . should . have . been . calledOnceWithExactly ( mockTreeItem ) ; } ) ; } ) ; describe ( 'connect' , ( ) => { beforeEach ( async ( ) => { await ExtensionUtil . activateExtension ( ) ; } ) ; afterEach ( ( ) => { mySandBox . restore ( ) ; } ) ; it ( 'should set the current client connection' , async ( ) => { const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const onDidChangeTreeDataSpy = mySandBox . spy ( blockchainGatewayExplorerProvider [ '_onDidChangeTreeData' ] , 'fire' ) ; const executeCommandSpy = mySandBox . spy ( vscode . commands , 'executeCommand' ) ; await blockchainGatewayExplorerProvider . connect ( ) ; onDidChangeTreeDataSpy . should . have . been . called ; executeCommandSpy . should . have . been . calledOnce ; executeCommandSpy . getCall ( 0 ) . should . have . been . calledWith ( 'setContext' , 'blockchain-gateway-connected' , true ) ; } ) ; } ) ; describe ( 'disconnect' , ( ) => { beforeEach ( async ( ) => { await ExtensionUtil . activateExtension ( ) ; } ) ; afterEach ( ( ) => { mySandBox . restore ( ) ; } ) ; it ( 'should disconnect the client connection' , async ( ) => { const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const onDidChangeTreeDataSpy = mySandBox . spy ( blockchainGatewayExplorerProvider [ '_onDidChangeTreeData' ] , 'fire' ) ; const executeCommandSpy = mySandBox . spy ( vscode . commands , 'executeCommand' ) ; await blockchainGatewayExplorerProvider . disconnect ( ) ; onDidChangeTreeDataSpy . should . have . been . called ; executeCommandSpy . should . have . been . calledOnce ; executeCommandSpy . getCall ( 0 ) . should . have . been . calledWith ( 'setContext' , 'blockchain-gateway-connected' , false ) ; } ) ; } ) ; describe ( 'getTreeItem' , ( ) => { it ( 'should get a tree item' , async ( ) => { const myGateway = new FabricGatewayRegistryEntry ( { name : 'myGateway' , associatedWallet : '' , connectionProfilePath : path . join ( 'blockchain' , 'extension' , 'directory' , 'gatewayOne' , 'connection.json' ) } ) ; await FabricEnvironmentRegistry . instance ( ) . clear ( ) ; await FabricGatewayRegistry . instance ( ) . clear ( ) ; await FabricGatewayRegistry . instance ( ) . add ( myGateway ) ; const blockchainGatewayExplorerProvider = ExtensionUtil . getBlockchainGatewayExplorerProvider ( ) ; const allChildren = await blockchainGatewayExplorerProvider . getChildren ( ) ; const groupChildren = await blockchainGatewayExplorerProvider . getChildren ( allChildren [ 0 ] ) ; const result = blockchainGatewayExplorerProvider . getTreeItem ( groupChildren [ 0 ] ) as GatewayTreeItem ; result . label . should . equal ( 'myGateway' ) ; } ) ; } ) ; } ) ;