'use strict' ; import * as vscode from 'vscode' ; import * as path from 'path' ; import * as fs from 'fs-extra' ; import * as chai from 'chai' ; import * as sinon from 'sinon' ; import * as sinonChai from 'sinon-chai' ; import { BlockchainTreeItem } from '../../extension/explorer/model/BlockchainTreeItem' ; import { TestUtil } from '../TestUtil' ; import { UserInputUtil } from '../../extension/commands/UserInputUtil' ; import { VSCodeBlockchainOutputAdapter } from '../../extension/logging/VSCodeBlockchainOutputAdapter' ; import { ExtensionCommands } from '../../ExtensionCommands' ; import { FabricWallet } from 'ibm-blockchain-platform-wallet' ; import { FabricCertificateAuthorityFactory } from '../../extension/fabric/FabricCertificateAuthorityFactory' ; import { FabricRuntimeUtil , FabricWalletRegistry , FabricWalletRegistryEntry , IFabricWallet , LogType , FabricGatewayRegistry , FabricGatewayRegistryEntry , FabricEnvironmentRegistryEntry , FabricEnvironmentRegistry , FabricIdentity } from 'ibm-blockchain-platform-common' ; import { FabricWalletGenerator } from 'ibm-blockchain-platform-wallet' ; import { BlockchainWalletExplorerProvider } from '../../extension/explorer/walletExplorer' ; import { WalletTreeItem } from '../../extension/explorer/wallets/WalletTreeItem' ; import { LocalWalletTreeItem } from '../../extension/explorer/wallets/LocalWalletTreeItem' ; import { Reporter } from '../../extension/util/Reporter' ; import { ExtensionUtil } from '../../extension/util/ExtensionUtil' ; import { FabricGatewayHelper } from '../../extension/fabric/FabricGatewayHelper' ; import { EnvironmentFactory } from '../../extension/fabric/environments/EnvironmentFactory' ; import { WalletGroupTreeItem } from '../../extension/explorer/model/WalletGroupTreeItem' ; import { LocalMicroEnvironment } from '../../extension/fabric/environments/LocalMicroEnvironment' ; import { LocalMicroEnvironmentManager } from '../../extension/fabric/environments/LocalMicroEnvironmentManager' ; import { FabricWalletHelper } from '../../extension/fabric/FabricWalletHelper' ; chai . use ( sinonChai ) ; const should = chai . should ( ) ; describe ( 'AddWalletIdentityCommand' , ( ) => { let mySandBox ; before ( async ( ) => { mySandBox = sinon . createSandbox ( ) ; await TestUtil . setupTests ( mySandBox ) ; } ) ; describe ( 'addWalletIdentity' , ( ) => { let inputBoxStub ; const rootPath = path . dirname ( __dirname ) ; const walletPath = path . join ( rootPath , '../../test/data/walletDir/wallet' ) ; let fsReadFile ; let logSpy ; let addIdentityMethodStub ; let getCertKeyStub ; let showGatewayQuickPickBoxStub ; let importIdentityStub ; let fabricWallet ; let getEnrollIdSecretStub ; let enrollStub ; let executeCommandStub ; let getWalletStub ; let showWalletsQuickPickStub ; let sendTelemetryEventStub ; let browseStub ; let connectionProfilePathStub ; let walletExistsStub ; let orgOneIdentities ; beforeEach ( async ( ) => { await FabricGatewayRegistry . instance ( ) . clear ( ) ; await FabricWalletRegistry . instance ( ) . clear ( ) ; await FabricEnvironmentRegistry . instance ( ) . clear ( ) ; await TestUtil . startLocalFabric ( ) ; const connectionOne = new FabricGatewayRegistryEntry ( { name : 'myGatewayA' , associatedWallet : '' , connectionProfilePath : path . join ( 'myPath' , 'connection.json' ) } ) ; const connectionTwo = new FabricGatewayRegistryEntry ( { name : 'myGatewayB' , associatedWallet : '' , connectionProfilePath : path . join ( 'myPath' , 'connection.json' ) } ) ; const connectionThree = new FabricGatewayRegistryEntry ( { name : 'myGatewayC' , associatedWallet : '' , connectionProfilePath : path . join ( 'myPath' , 'connection.json' ) } ) ; await FabricGatewayRegistry . instance ( ) . add ( connectionOne ) ; await FabricGatewayRegistry . instance ( ) . add ( connectionTwo ) ; await FabricGatewayRegistry . instance ( ) . add ( connectionThree ) ; connectionProfilePathStub = mySandBox . stub ( FabricGatewayHelper , 'getConnectionProfilePath' ) . resolves ( path . join ( 'myPath' , 'connection.json' ) ) ; const connectionOneWallet = new FabricWalletRegistryEntry ( { name : 'blueWallet' , walletPath : walletPath } ) ; const connectionTwoWallet = new FabricWalletRegistryEntry ( { name : 'externalWallet' , walletPath : walletPath } ) ; await FabricWalletRegistry . instance ( ) . add ( connectionOneWallet ) ; await FabricWalletRegistry . instance ( ) . add ( connectionTwoWallet ) ; const localEntry = await FabricEnvironmentRegistry . instance ( ) . get ( FabricRuntimeUtil . LOCAL_FABRIC ) ; const walletEntry = await FabricWalletRegistry . instance ( ) . get ( 'Org1' , FabricRuntimeUtil . LOCAL_FABRIC ) ; orgOneIdentities = await FabricWalletHelper . getVisibleIdentities ( localEntry , walletEntry ) ; inputBoxStub = mySandBox . stub ( UserInputUtil , 'showInputBox' ) ; fsReadFile = mySandBox . stub ( fs , 'readFile' ) ; logSpy = mySandBox . spy ( VSCodeBlockchainOutputAdapter . instance ( ) , 'log' ) ; addIdentityMethodStub = mySandBox . stub ( UserInputUtil , 'addIdentityMethod' ) ; getCertKeyStub = mySandBox . stub ( UserInputUtil , 'getCertKey' ) ; showGatewayQuickPickBoxStub = mySandBox . stub ( UserInputUtil , 'showGatewayQuickPickBox' ) ; getEnrollIdSecretStub = mySandBox . stub ( UserInputUtil , 'getEnrollIdSecret' ) ; enrollStub = mySandBox . stub ( FabricCertificateAuthorityFactory . createCertificateAuthority ( ) , 'enroll' ) ; executeCommandStub = mySandBox . stub ( vscode . commands , 'executeCommand' ) ; executeCommandStub . callThrough ( ) ; fabricWallet = await FabricWallet . newFabricWallet ( walletPath ) ; getWalletStub = mySandBox . stub ( FabricWalletGenerator . instance ( ) , 'getWallet' ) ; getWalletStub . returns ( fabricWallet ) ; importIdentityStub = mySandBox . stub ( fabricWallet , 'importIdentity' ) ; importIdentityStub . resolves ( ) ; showWalletsQuickPickStub = mySandBox . stub ( UserInputUtil , 'showWalletsQuickPickBox' ) ; sendTelemetryEventStub = mySandBox . stub ( Reporter . instance ( ) , 'sendTelemetryEvent' ) ; browseStub = mySandBox . stub ( UserInputUtil , 'browse' ) ; walletExistsStub = mySandBox . stub ( fabricWallet , 'exists' ) . resolves ( false ) ; } ) ; afterEach ( async ( ) => { mySandBox . restore ( ) ; } ) ; it ( 'should test an identity can be added with an enroll id and secret, when called from the command palette using a JSON file' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; fsReadFile . resolves ( `{
                "certificateAuthorities": {
                    "ca0": {
                        "url": "http://ca0url"
                    }
                }
            }` ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; const gatewayA = await FabricGatewayRegistry . instance ( ) . get ( 'myGatewayA' ) ; showGatewayQuickPickBoxStub . resolves ( { label : 'myGatewayA' , data : gatewayA } ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; result . should . equal ( 'greenConga' ) ; inputBoxStub . should . have . been . calledTwice ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , externalWallet . fromEnvironment ) ; fsReadFile . should . have . been . calledOnce ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . have . been . calledOnceWith ( 'http://ca0url' , 'enrollID' , 'enrollSecret' ) ; importIdentityStub . should . have . been . calledWith ( '---CERT---' , '---KEY---' , 'greenConga' , 'myMSPID' ) ; executeCommandStub . should . have . been . calledWith ( ExtensionCommands . REFRESH_WALLETS ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . SUCCESS , 'Successfully added identity' , `Successfully added identity to wallet` ) ; sendTelemetryEventStub . should . have . been . calledOnceWithExactly ( 'addWalletIdentityCommand' , { method : 'enrollmentID' } ) ; } ) ; it ( 'should test an identity can be added with an enroll id and secret, when called from the command palette using a JSON file and mspid passed in' , async ( ) => { connectionProfilePathStub . resolves ( path . join ( 'myPath' , 'connection.yml' ) ) ; const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; fsReadFile . resolves ( `{
                "certificateAuthorities": {
                    "ca0": {
                        "url": "http://ca0url"
                    }
                }
            }` ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'greyConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; const gatewayA = await FabricGatewayRegistry . instance ( ) . get ( 'myGatewayA' ) ; showGatewayQuickPickBoxStub . resolves ( { label : 'myGatewayA' , data : gatewayA } ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY , undefined , 'myMSPID' ) ; result . should . equal ( 'greyConga' ) ; inputBoxStub . should . have . been . calledOnce ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , externalWallet . fromEnvironment ) ; fsReadFile . should . have . been . calledOnce ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . have . been . calledOnceWith ( 'http://ca0url' , 'enrollID' , 'enrollSecret' ) ; importIdentityStub . should . have . been . calledWith ( '---CERT---' , '---KEY---' , 'greyConga' , 'myMSPID' ) ; executeCommandStub . should . have . been . calledWith ( ExtensionCommands . REFRESH_WALLETS ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . SUCCESS , 'Successfully added identity' , `Successfully added identity to wallet` ) ; sendTelemetryEventStub . should . have . been . calledOnceWithExactly ( 'addWalletIdentityCommand' , { method : 'enrollmentID' } ) ; } ) ; it ( 'should error when adding with ID and SECRET but no CA in the connction profile' , async ( ) => { connectionProfilePathStub . resolves ( path . join ( 'myPath' , 'connection.yml' ) ) ; const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; fsReadFile . resolves ( `{
            }` ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'greyConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; const gatewayA = await FabricGatewayRegistry . instance ( ) . get ( 'myGatewayA' ) ; showGatewayQuickPickBoxStub . resolves ( { label : 'myGatewayA' , data : gatewayA } ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; const expectedError = new Error ( 'No certificate authorities found in the connection profile' ) ; importIdentityStub . resetHistory ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY , undefined , 'myMSPID' ) ; should . equal ( undefined , result ) ; inputBoxStub . should . have . been . calledOnce ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , externalWallet . fromEnvironment ) ; fsReadFile . should . have . been . calledOnce ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . have . not . been . called ; importIdentityStub . should . have . not . been . called ; executeCommandStub . should . have . not . been . calledWith ( ExtensionCommands . REFRESH_WALLETS ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . ERROR , `Unable to add identity to wallet: ${ expectedError . message }` , `Unable to add identity to wallet: ${ expectedError . toString ( ) }` ) ; sendTelemetryEventStub . should . have . not . been . called ; } ) ; it ( 'should error when adding with ID and SECRET but empty CA in the connction profile' , async ( ) => { connectionProfilePathStub . resolves ( path . join ( 'myPath' , 'connection.yml' ) ) ; const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; fsReadFile . resolves ( `{
                "certificateAuthorities": {
                }
            }` ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'greyConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; const gatewayA = await FabricGatewayRegistry . instance ( ) . get ( 'myGatewayA' ) ; showGatewayQuickPickBoxStub . resolves ( { label : 'myGatewayA' , data : gatewayA } ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; const expectedError = new Error ( 'No certificate authorities found in the connection profile' ) ; importIdentityStub . resetHistory ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY , undefined , 'myMSPID' ) ; should . equal ( undefined , result ) ; inputBoxStub . should . have . been . calledOnce ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , externalWallet . fromEnvironment ) ; fsReadFile . should . have . been . calledOnce ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . have . not . been . called ; importIdentityStub . should . have . not . been . called ; executeCommandStub . should . have . not . been . calledWith ( ExtensionCommands . REFRESH_WALLETS ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . ERROR , `Unable to add identity to wallet: ${ expectedError . message }` , `Unable to add identity to wallet: ${ expectedError . toString ( ) }` ) ; sendTelemetryEventStub . should . have . not . been . called ; } ) ; it ( 'should test an identity can be added with an enroll id and secret, when called from the command palette using a yaml file' , async ( ) => { connectionProfilePathStub . resolves ( path . join ( 'myPath' , 'connection.yml' ) ) ; const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; fsReadFile . resolves ( `---
            certificateAuthorities:
              ca0:
                url: http://ca0url` ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; const myGatewayC = await FabricGatewayRegistry . instance ( ) . get ( 'myGatewayC' ) ; showGatewayQuickPickBoxStub . resolves ( { label : 'myGatewayC' , data : myGatewayC } ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; result . should . equal ( 'greenConga' ) ; inputBoxStub . should . have . been . calledTwice ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , externalWallet . fromEnvironment ) ; fsReadFile . should . have . been . calledOnce ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . have . been . calledOnceWith ( 'http://ca0url' , 'enrollID' , 'enrollSecret' ) ; importIdentityStub . should . have . been . calledWith ( '---CERT---' , '---KEY---' , 'greenConga' , 'myMSPID' ) ; executeCommandStub . should . have . been . calledWith ( ExtensionCommands . REFRESH_WALLETS ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . SUCCESS , 'Successfully added identity' , `Successfully added identity to wallet` ) ; sendTelemetryEventStub . should . have . been . calledOnceWithExactly ( 'addWalletIdentityCommand' , { method : 'enrollmentID' } ) ; } ) ; it ( 'should test an identity can be added with an enroll id and secret, when called from the command palette using a yaml file with caName' , async ( ) => { connectionProfilePathStub . resolves ( path . join ( 'myPath' , 'connection.yml' ) ) ; const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; fsReadFile . resolves ( `---
            certificateAuthorities:
              ca0:
                url: http://ca0url
                caName: clientCA` ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; const myGatewayC = await FabricGatewayRegistry . instance ( ) . get ( 'myGatewayC' ) ; showGatewayQuickPickBoxStub . resolves ( { label : 'myGatewayC' , data : myGatewayC } ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; result . should . equal ( 'greenConga' ) ; inputBoxStub . should . have . been . calledTwice ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , externalWallet . fromEnvironment ) ; fsReadFile . should . have . been . calledOnce ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . have . been . calledOnceWith ( 'http://ca0url' , 'enrollID' , 'enrollSecret' , 'clientCA' ) ; importIdentityStub . should . have . been . calledWith ( '---CERT---' , '---KEY---' , 'greenConga' , 'myMSPID' ) ; executeCommandStub . should . have . been . calledWith ( ExtensionCommands . REFRESH_WALLETS ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . SUCCESS , 'Successfully added identity' , `Successfully added identity to wallet` ) ; sendTelemetryEventStub . should . have . been . calledOnceWithExactly ( 'addWalletIdentityCommand' , { method : 'enrollmentID' } ) ; } ) ; it ( 'should error when user tries to add an identity using an enroll id and secret, with the same name as one that already exists ' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; const identityName = 'greenConga' ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( identityName ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; walletExistsStub . resolves ( true ) ; await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . ERROR , `An identity called ${ identityName } already exists` ) ; } ) ; it ( 'should error when user tries to add an identity using a certificate and private key, with the same name as one that already exists ' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; const identityName = 'greenConga' ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( identityName ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_CERT_KEY_OPTION ) ; walletExistsStub . resolves ( true ) ; await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . ERROR , `An identity called ${ identityName } already exists` ) ; } ) ; it ( 'should error when user tries to add an identity using a json file, with the same name as one that already exists ' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_JSON_ID_OPTION ) ; browseStub . resolves ( 'myTestPath' ) ; fsReadFile . resolves ( '{"name": "purpleConga","cert": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0", "private_key": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0"}' ) ; walletExistsStub . resolves ( true ) ; await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . ERROR , `An identity called purpleConga already exists` ) ; } ) ; it ( 'should error when user tries to add an identity using a json file, providing no name ' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_JSON_ID_OPTION ) ; browseStub . resolves ( 'myTestPath' ) ; fsReadFile . resolves ( '{"cert": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0", "private_key": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0"}' ) ; inputBoxStub . onSecondCall ( ) . resolves ( '' ) ; walletExistsStub . resolves ( true ) ; await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . ERROR , `An identity name cannot be empty` ) ; } ) ; it ( 'should ask user to enter an identity name and use it if none is provided in a json file ' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_JSON_ID_OPTION ) ; browseStub . resolves ( 'myTestPath' ) ; fsReadFile . resolves ( '{"cert": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0", "private_key": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0"}' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'biscuit' ) ; await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . SUCCESS , 'Successfully added identity' , `Successfully added identity to wallet` ) ; } ) ; it ( 'should return when user cancels when selecting a CA to enroll with' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; fsReadFile . resolves ( `{
                "certificateAuthorities": {
                    "ca0": {
                        "url": "http://ca0url"
                    },
                    "ca1": {
                        "url": "http://ca1url"
                    }
                }
            }` ) ; const showQuickPickCAStub = mySandBox . stub ( UserInputUtil , 'showQuickPickCA' ) . resolves ( ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'greenConga' ) ; importIdentityStub . resetHistory ( ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; const myGatewayA = await FabricGatewayRegistry . instance ( ) . get ( 'myGatewayA' ) ; showGatewayQuickPickBoxStub . resolves ( { label : 'myGatewayA' , data : myGatewayA } ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; inputBoxStub . should . have . been . calledTwice ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , externalWallet . fromEnvironment ) ; showQuickPickCAStub . should . have . been . calledOnce ; fsReadFile . should . have . been . calledOnce ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . not . have . been . called ; importIdentityStub . should . not . have . been . called ; logSpy . should . have . been . calledOnce ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; sendTelemetryEventStub . should . not . have . been . called ; } ) ; it ( 'should ask which ca if more than one' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; fsReadFile . resolves ( `{
                "certificateAuthorities": {
                    "ca0": {
                        "url": "http://ca0url"
                    },
                    "ca1": {
                        "url": "http://ca1url"
                    }
                }
            }` ) ; const showQuickPickCAStub = mySandBox . stub ( UserInputUtil , 'showQuickPickCA' ) . resolves ( 'ca1' ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; const myGatewayA = await FabricGatewayRegistry . instance ( ) . get ( 'myGatewayA' ) ; showGatewayQuickPickBoxStub . resolves ( { label : 'myGatewayA' , data : myGatewayA } ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; result . should . equal ( 'greenConga' ) ; inputBoxStub . should . have . been . calledTwice ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , externalWallet . fromEnvironment ) ; showQuickPickCAStub . should . have . been . calledOnce ; fsReadFile . should . have . been . calledOnce ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . have . been . calledOnceWith ( 'http://ca1url' , 'enrollID' , 'enrollSecret' ) ; importIdentityStub . should . have . been . calledWith ( '---CERT---' , '---KEY---' , 'greenConga' , 'myMSPID' ) ; executeCommandStub . should . have . been . calledWith ( ExtensionCommands . REFRESH_WALLETS ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . SUCCESS , 'Successfully added identity' , `Successfully added identity to wallet` ) ; sendTelemetryEventStub . should . have . been . calledOnceWithExactly ( 'addWalletIdentityCommand' , { method : 'enrollmentID' } ) ; } ) ; it ( 'should test adding an identity can be cancelled when choosing a wallet' , async ( ) => { showWalletsQuickPickStub . resolves ( ) ; importIdentityStub . resetHistory ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; showGatewayQuickPickBoxStub . should . not . have . been . called ; inputBoxStub . should . not . have . been . called ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , 'addWalletIdentity' ) ; sendTelemetryEventStub . should . not . have . been . called ; } ) ; it ( 'should test adding an identity can be cancelled when failing to give an identity name' , async ( ) => { const blueWallet = await FabricWalletRegistry . instance ( ) . get ( 'blueWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'blueWallet' , data : blueWallet } ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; inputBoxStub . resolves ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; showGatewayQuickPickBoxStub . should . not . have . been . called ; inputBoxStub . should . have . been . calledOnce ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , 'addWalletIdentity' ) ; sendTelemetryEventStub . should . not . have . been . called ; } ) ; it ( 'should test adding an identity can be cancelled when asked to select a method for adding an identity' , async ( ) => { const blueWallet = await FabricWalletRegistry . instance ( ) . get ( 'blueWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'blueWallet' , data : blueWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; addIdentityMethodStub . resolves ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; showGatewayQuickPickBoxStub . should . not . have . been . called ; inputBoxStub . should . have . been . calledOnce ; addIdentityMethodStub . should . have . been . calledOnce ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , 'addWalletIdentity' ) ; sendTelemetryEventStub . should . not . have . been . called ; } ) ; it ( 'should test adding an identity can be cancelled when asked to give an MSPID' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; showGatewayQuickPickBoxStub . should . not . have . been . called ; inputBoxStub . should . have . been . calledOnce ; addIdentityMethodStub . should . not . have . been . called ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , 'addWalletIdentity' ) ; } ) ; it ( 'should test adding an identity can be cancelled chosing a gateway to enroll with' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'greenConga' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'myMSPID' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; showGatewayQuickPickBoxStub . resolves ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , externalWallet . fromEnvironment ) ; inputBoxStub . should . have . been . calledTwice ; getEnrollIdSecretStub . should . not . have . been . called ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , 'addWalletIdentity' ) ; } ) ; it ( 'should test adding an identity can be cancelled when adding using an identity and secret' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; const myGatewayB = await FabricGatewayRegistry . instance ( ) . get ( 'myGatewayB' ) ; showGatewayQuickPickBoxStub . resolves ( { label : 'myGatewayB' , data : myGatewayB } ) ; getEnrollIdSecretStub . resolves ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , externalWallet . fromEnvironment ) ; inputBoxStub . should . have . been . calledTwice ; fsReadFile . should . not . have . been . called ; enrollStub . should . not . have . been . called ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , 'addWalletIdentity' ) ; } ) ; it ( 'should test an identity can be added using a certificate and private key' , async ( ) => { const blueWallet = await FabricWalletRegistry . instance ( ) . get ( 'blueWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'blueWallet' , data : blueWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'blueConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_CERT_KEY_OPTION ) ; getCertKeyStub . resolves ( { certificatePath : path . join ( rootPath , '../../test/data/connectionTwo/credentials/certificate' ) , privateKeyPath : path . join ( rootPath , '../../test/data/connectionTwo/credentials/privateKey' ) } ) ; fsReadFile . onFirstCall ( ) . resolves ( '---CERT---' ) ; fsReadFile . onSecondCall ( ) . resolves ( '---KEY---' ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; result . should . equal ( 'blueConga' ) ; inputBoxStub . should . have . been . calledTwice ; fsReadFile . should . have . been . calledTwice ; showGatewayQuickPickBoxStub . should . not . have . been . called ; getCertKeyStub . should . have . been . calledOnce ; importIdentityStub . should . have . been . calledWith ( '---CERT---' , '---KEY---' , 'blueConga' , 'myMSPID' ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . SUCCESS , 'Successfully added identity' , `Successfully added identity to wallet` ) ; sendTelemetryEventStub . should . have . been . calledOnceWithExactly ( 'addWalletIdentityCommand' , { method : 'Certificate' } ) ; } ) ; it ( 'should test adding an identity can be cancelled when adding using a certificate and private key' , async ( ) => { const blueWallet = await FabricWalletRegistry . instance ( ) . get ( 'blueWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'blueWallet' , data : blueWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_CERT_KEY_OPTION ) ; getCertKeyStub . resolves ( ) ; importIdentityStub . resetHistory ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; fsReadFile . should . not . have . been . called ; getCertKeyStub . should . have . been . calledOnce ; importIdentityStub . should . not . have . been . called ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , 'addWalletIdentity' ) ; } ) ; it ( 'should show an error if parsing the certificate file fails' , async ( ) => { const blueWallet = await FabricWalletRegistry . instance ( ) . get ( 'blueWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'blueWallet' , data : blueWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_CERT_KEY_OPTION ) ; const error = new Error ( 'certificate invalid' ) ; getCertKeyStub . throws ( error ) ; importIdentityStub . resetHistory ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; fsReadFile . should . not . have . been . called ; getCertKeyStub . should . have . been . calledOnce ; importIdentityStub . should . not . have . been . called ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . ERROR , `Unable to add identity to wallet: ${ error . message }` , `Unable to add identity to wallet: ${ error . toString ( ) }` ) ; sendTelemetryEventStub . should . not . have . been . called ; } ) ; it ( 'should error if an identity is unable to be imported' , async ( ) => { fsReadFile . resolves ( `{
                "certificateAuthorities": {
                    "ca0": {
                        "url": "http://ca0url"
                    }
                }
            }` ) ; const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; const myGatewayB = await FabricGatewayRegistry . instance ( ) . get ( 'myGatewayB' ) ; showGatewayQuickPickBoxStub . resolves ( { label : 'myGatewayB' , data : myGatewayB } ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; const error = new Error ( 'Already exists' ) ; importIdentityStub . throws ( error ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; inputBoxStub . should . have . been . calledTwice ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , externalWallet . fromEnvironment ) ; fsReadFile . should . have . been . calledOnce ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . have . been . calledOnceWith ( 'http://ca0url' , 'enrollID' , 'enrollSecret' ) ; importIdentityStub . should . have . been . calledWith ( '---CERT---' , '---KEY---' , 'greenConga' , 'myMSPID' ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . ERROR , `Unable to add identity to wallet: ${ error . message }` , `Unable to add identity to wallet: ${ error . toString ( ) }` ) ; sendTelemetryEventStub . should . not . have . been . called ; } ) ; it ( 'should test an error is thrown if trying to add an identity when no gateway doesnt exist' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; const error = new Error ( `Error when choosing gateway, no gateway found to choose from.` ) ; showGatewayQuickPickBoxStub . throws ( error ) ; await FabricGatewayRegistry . instance ( ) . clear ( ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; getEnrollIdSecretStub . resolves ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , externalWallet . fromEnvironment ) ; inputBoxStub . should . have . been . calledTwice ; fsReadFile . should . not . have . been . called ; enrollStub . should . not . have . been . called ; logSpy . getCall ( 0 ) . should . have . been . calledWithExactly ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWithExactly ( LogType . ERROR , `Unable to add identity to wallet: ${ error . message }` , `Unable to add identity to wallet: ${ error . toString ( ) }` ) ; } ) ; it ( 'should test an identity can be added via a json identity file' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_JSON_ID_OPTION ) ; browseStub . resolves ( 'myTestPath' ) ; fsReadFile . resolves ( '{"name": "purpleConga","cert": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0", "private_key": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0"}' ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; result . should . equal ( 'purpleConga' ) ; inputBoxStub . should . have . been . calledOnce ; browseStub . should . have . been . calledOnce ; fsReadFile . should . have . been . calledOnce ; showGatewayQuickPickBoxStub . should . not . have . been . called ; importIdentityStub . should . have . been . calledWith ( '-----BEGIN CERTIFICATE----' , '-----BEGIN PRIVATE KEY----' , 'purpleConga' , 'myMSPID' ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . SUCCESS , 'Successfully added identity' , `Successfully added identity to wallet` ) ; sendTelemetryEventStub . should . have . been . calledOnceWithExactly ( 'addWalletIdentityCommand' , { method : 'json' } ) ; } ) ; it ( 'should handle the user cancelling selecting a json file to create an identity' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_JSON_ID_OPTION ) ; browseStub . resolves ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; inputBoxStub . should . have . been . calledOnce ; browseStub . should . have . been . calledOnce ; fsReadFile . should . not . have . been . called ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , 'addWalletIdentity' ) ; sendTelemetryEventStub . should . not . have . been . called ; } ) ; it ( 'should display an error if the json file does not contain the correct properties' , async ( ) => { const externalWallet = await FabricWalletRegistry . instance ( ) . get ( 'externalWallet' ) ; showWalletsQuickPickStub . resolves ( { label : 'externalWallet' , data : externalWallet } ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_JSON_ID_OPTION ) ; browseStub . resolves ( 'myTestPath' ) ; fsReadFile . resolves ( '{"name": "purpleConga","certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0", "privateKEy": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0"}' ) ; importIdentityStub . resetHistory ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY ) ; should . not . exist ( result ) ; inputBoxStub . should . have . been . calledOnce ; browseStub . should . have . been . calledOnce ; fsReadFile . should . have . been . calledOnce ; showGatewayQuickPickBoxStub . should . not . have . been . called ; importIdentityStub . should . not . have . been . called ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . ERROR , `Unable to add identity to wallet: JSON file missing properties "cert" or "private_key"` , `Unable to add identity to wallet: Error: JSON file missing properties "cert" or "private_key"` ) ; sendTelemetryEventStub . should . not . have . been . called ; } ) ; describe ( 'called from WalletTreeItem' , ( ) => { it ( 'should test an identity can be added from a WalletTreeItem' , async ( ) => { fsReadFile . resolves ( `{
                    "certificateAuthorities": {
                        "ca0": {
                            "url": "http://ca0url"
                        }
                    }
                }` ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; const myGatewayA = await FabricGatewayRegistry . instance ( ) . get ( 'myGatewayA' ) ; showGatewayQuickPickBoxStub . resolves ( { label : 'myGatewayA' , data : myGatewayA } ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; importIdentityStub . resolves ( ) ; const mockRuntime = mySandBox . createStubInstance ( LocalMicroEnvironment ) ; mockRuntime . getNodes . resolves ( [ { wallet : 'Org1' } ] ) ; mySandBox . stub ( EnvironmentFactory , 'getEnvironment' ) . returns ( mockRuntime ) ; const blockchainWalletExplorerProvider = ExtensionUtil . getBlockchainWalletExplorerProvider ( ) ; const walletItems = await blockchainWalletExplorerProvider . getChildren ( ) ; const walletGroupItems = await blockchainWalletExplorerProvider . getChildren ( walletItems [ 1 ] ) ; const walletItem = walletGroupItems [ 1 ] as WalletTreeItem ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY , walletItem ) ; result . should . equal ( 'greenConga' ) ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , undefined ) ; showWalletsQuickPickStub . should . not . have . been . called ; inputBoxStub . should . have . been . calledTwice ; fsReadFile . should . have . been . called ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . have . been . calledOnceWith ( 'http://ca0url' , 'enrollID' , 'enrollSecret' ) ; importIdentityStub . should . have . been . calledWith ( '---CERT---' , '---KEY---' , 'greenConga' , 'myMSPID' ) ; executeCommandStub . should . have . been . calledWith ( ExtensionCommands . REFRESH_WALLETS ) ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . SUCCESS , 'Successfully added identity' , `Successfully added identity to wallet` ) ; sendTelemetryEventStub . should . have . been . calledOnceWithExactly ( 'addWalletIdentityCommand' , { method : 'enrollmentID' } ) ; } ) ; it ( `should test an identity can be enrolled to ${ FabricRuntimeUtil . LOCAL_FABRIC } - Org1 Wallet using ${ FabricRuntimeUtil . LOCAL_FABRIC }` , async ( ) => { fsReadFile . resolves ( `{
                    "certificateAuthorities": {
                        "ca0": {
                            "url": "http://ca0url"
                        }
                    }
                }` ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_LOCAL_ID_SECRET_OPTION ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; importIdentityStub . resolves ( ) ; const isRunning = mySandBox . stub ( LocalMicroEnvironment . prototype , 'isRunning' ) . resolves ( true ) ; const getNodes = mySandBox . stub ( LocalMicroEnvironment . prototype , 'getNodes' ) . resolves ( [ { wallet : 'Org1' } ] ) ; const getVisibleIdentities = mySandBox . stub ( LocalMicroEnvironment . prototype , 'getVisibleIdentities' ) . resolves ( orgOneIdentities ) ; mySandBox . stub ( LocalMicroEnvironmentManager . instance ( ) , 'getRuntime' ) . returns ( { isRunning , getNodes , getVisibleIdentities } ) ; const blockchainWalletExplorerProvider = ExtensionUtil . getBlockchainWalletExplorerProvider ( ) ; const walletItems = await blockchainWalletExplorerProvider . getChildren ( ) ; const walletGroup = walletItems [ 0 ] as WalletGroupTreeItem ; const walletTreeItems = await blockchainWalletExplorerProvider . getChildren ( walletGroup ) ; const walletItem = walletTreeItems [ 0 ] as LocalWalletTreeItem ; const showOrgQuickPickStub = mySandBox . stub ( UserInputUtil , 'showOrgQuickPick' ) . resolves ( { label : 'Org1MSP' , data : { api_url : 'grpc://localhost:17051' , chaincode_url : 'grpc://localhost:17052' , container_name : 'fabricvscodelocalfabric_peer0.org1.example.com' , identity : 'org1Admin' , msp_id : 'Org1MSP' , name : 'Org1Peer1' , short_name : 'Org1Peer1' , type : 'fabric-peer' , wallet : 'Org1' , } } ) ; mySandBox . stub ( EnvironmentFactory , 'getEnvironment' ) . returns ( new LocalMicroEnvironment ( FabricRuntimeUtil . LOCAL_FABRIC , undefined , 1 , UserInputUtil . V2_0 ) ) ; const localGatewayEntry = await FabricGatewayRegistry . instance ( ) . get ( `${ FabricRuntimeUtil . LOCAL_FABRIC } - Org1 Gateway` ) ; const localEnvironmentEntry = await FabricEnvironmentRegistry . instance ( ) . get ( `${ FabricRuntimeUtil . LOCAL_FABRIC }` ) ; showGatewayQuickPickBoxStub . resolves ( { label : localGatewayEntry . displayName , data : localGatewayEntry } ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY , walletItem ) ; result . should . equal ( 'greenConga' ) ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , FabricRuntimeUtil . LOCAL_FABRIC ) ; showOrgQuickPickStub . should . have . been . calledWith ( `Select the organization which the identity belongs to` , localEnvironmentEntry ) ; showWalletsQuickPickStub . should . not . have . been . called ; inputBoxStub . should . have . been . calledOnce ; fsReadFile . should . have . been . called ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . have . been . calledOnceWith ( 'http://ca0url' , 'enrollID' , 'enrollSecret' ) ; importIdentityStub . should . have . been . calledWith ( '---CERT---' , '---KEY---' , 'greenConga' , 'Org1MSP' ) ; executeCommandStub . should . have . been . calledWith ( ExtensionCommands . REFRESH_WALLETS ) ; executeCommandStub . should . not . have . been . calledWith ( ExtensionCommands . START_FABRIC ) ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . SUCCESS , 'Successfully added identity' , `Successfully added identity to wallet` ) ; sendTelemetryEventStub . should . have . been . calledOnceWithExactly ( 'addWalletIdentityCommand' , { method : 'enrollmentID' } ) ; } ) ; it ( `should start ${ FabricRuntimeUtil . LOCAL_FABRIC } before attempting to enroll an identity` , async ( ) => { fsReadFile . resolves ( `{
                    "certificateAuthorities": {
                        "ca0": {
                            "url": "http://ca0url"
                        }
                    }
                }` ) ; mySandBox . stub ( EnvironmentFactory , 'getEnvironment' ) . returns ( new LocalMicroEnvironment ( FabricRuntimeUtil . LOCAL_FABRIC , 8080 , 1 , UserInputUtil . V2_0 ) ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_LOCAL_ID_SECRET_OPTION ) ; mySandBox . stub ( LocalMicroEnvironment . prototype , 'getVisibleIdentities' ) . resolves ( orgOneIdentities ) ; const isRunning = mySandBox . stub ( LocalMicroEnvironment . prototype , 'isRunning' ) ; isRunning . onCall ( 0 ) . resolves ( false ) ; isRunning . onCall ( 1 ) . resolves ( true ) ; executeCommandStub . withArgs ( ExtensionCommands . START_FABRIC ) . resolves ( ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; importIdentityStub . resolves ( ) ; const showOrgQuickPickStub = mySandBox . stub ( UserInputUtil , 'showOrgQuickPick' ) . resolves ( { label : 'Org1MSP' , data : { api_url : 'grpc://localhost:17051' , chaincode_url : 'grpc://localhost:17052' , container_name : 'fabricvscodelocalfabric_peer0.org1.example.com' , identity : 'org1Admin' , msp_id : 'Org1MSP' , name : 'Org1Peer1' , short_name : 'Org1Peer1' , type : 'fabric-peer' , wallet : 'Org1' , } } ) ; const localGatewayEntry = await FabricGatewayRegistry . instance ( ) . get ( `${ FabricRuntimeUtil . LOCAL_FABRIC } - Org1 Gateway` ) ; const localEnvironmentEntry = await FabricEnvironmentRegistry . instance ( ) . get ( `${ FabricRuntimeUtil . LOCAL_FABRIC }` ) ; showGatewayQuickPickBoxStub . resolves ( { label : localGatewayEntry . displayName , data : localGatewayEntry } ) ; const blockchainWalletExplorerProvider = ExtensionUtil . getBlockchainWalletExplorerProvider ( ) ; const walletItems = await blockchainWalletExplorerProvider . getChildren ( ) ; const walletGroup = walletItems [ 0 ] as WalletGroupTreeItem ; const walletTreeItems = await blockchainWalletExplorerProvider . getChildren ( walletGroup ) ; const walletItem = walletTreeItems [ 0 ] as LocalWalletTreeItem ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY , walletItem ) ; result . should . equal ( 'greenConga' ) ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , FabricRuntimeUtil . LOCAL_FABRIC ) ; showOrgQuickPickStub . should . have . been . calledWith ( `Select the organization which the identity belongs to` , localEnvironmentEntry ) ; showWalletsQuickPickStub . should . not . have . been . called ; inputBoxStub . should . have . been . calledOnce ; fsReadFile . should . have . been . called ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . have . been . calledOnceWith ( 'http://ca0url' , 'enrollID' , 'enrollSecret' ) ; importIdentityStub . should . have . been . calledWith ( '---CERT---' , '---KEY---' , 'greenConga' , 'Org1MSP' ) ; executeCommandStub . should . have . been . calledWith ( ExtensionCommands . REFRESH_WALLETS ) ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . SUCCESS , 'Successfully added identity' , `Successfully added identity to wallet` ) ; sendTelemetryEventStub . should . have . been . calledOnceWithExactly ( 'addWalletIdentityCommand' , { method : 'enrollmentID' } ) ; } ) ; it ( `should handle ${ FabricRuntimeUtil . LOCAL_FABRIC } failing to start` , async ( ) => { inputBoxStub . onFirstCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_LOCAL_ID_SECRET_OPTION ) ; const showOrgQuickPickStub = mySandBox . stub ( UserInputUtil , 'showOrgQuickPick' ) . resolves ( { label : 'Org1MSP' , data : { api_url : 'grpc://localhost:17051' , chaincode_url : 'grpc://localhost:17052' , container_name : 'fabricvscodelocalfabric_peer0.org1.example.com' , identity : 'org1Admin' , msp_id : 'Org1MSP' , name : 'Org1Peer1' , short_name : 'Org1Peer1' , type : 'fabric-peer' , wallet : 'Org1' , } } ) ; const isRunning = mySandBox . stub ( LocalMicroEnvironment . prototype , 'isRunning' ) . resolves ( false ) ; const getWalletNames = mySandBox . stub ( LocalMicroEnvironment . prototype , 'getWalletNames' ) . resolves ( [ 'Org1' ] ) ; const getAllOrganizationNames = mySandBox . stub ( LocalMicroEnvironment . prototype , 'getAllOrganizationNames' ) . resolves ( [ 'myMSPID' ] ) ; const getNodes = mySandBox . stub ( LocalMicroEnvironment . prototype , 'getNodes' ) . resolves ( [ { wallet : 'Org1' } ] ) ; const getVisibleIdentities = mySandBox . stub ( LocalMicroEnvironment . prototype , 'getVisibleIdentities' ) . resolves ( orgOneIdentities ) ; mySandBox . stub ( LocalMicroEnvironmentManager . instance ( ) , 'getRuntime' ) . returns ( { isRunning , getWalletNames , getAllOrganizationNames , getNodes , getVisibleIdentities } ) ; const localEnvironmentEntry = await FabricEnvironmentRegistry . instance ( ) . get ( `${ FabricRuntimeUtil . LOCAL_FABRIC }` ) ; executeCommandStub . withArgs ( ExtensionCommands . START_FABRIC ) . resolves ( ) ; const blockchainWalletExplorerProvider = ExtensionUtil . getBlockchainWalletExplorerProvider ( ) ; const walletItems = await blockchainWalletExplorerProvider . getChildren ( ) ; const walletGroup = walletItems [ 0 ] as WalletGroupTreeItem ; const walletTreeItems = await blockchainWalletExplorerProvider . getChildren ( walletGroup ) ; const walletItem = walletTreeItems [ 0 ] as LocalWalletTreeItem ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY , walletItem ) ; should . not . exist ( result ) ; showOrgQuickPickStub . should . have . been . calledWith ( `Select the organization which the identity belongs to` , localEnvironmentEntry ) ; showWalletsQuickPickStub . should . not . have . been . called ; inputBoxStub . should . have . been . calledOnce ; fsReadFile . should . not . have . been . called ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , 'addWalletIdentity' ) ; sendTelemetryEventStub . should . not . have . been . called ; } ) ; it ( `should stop when cancelling selecting an organisation` , async ( ) => { inputBoxStub . onFirstCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_LOCAL_ID_SECRET_OPTION ) ; const showOrgQuickPickStub = mySandBox . stub ( UserInputUtil , 'showOrgQuickPick' ) . resolves ( ) ; const localEnvironmentEntry = await FabricEnvironmentRegistry . instance ( ) . get ( `${ FabricRuntimeUtil . LOCAL_FABRIC }` ) ; const mockRuntime = mySandBox . createStubInstance ( LocalMicroEnvironment ) ; mockRuntime . getNodes . resolves ( [ { wallet : 'Org1' } ] ) ; mockRuntime . getVisibleIdentities . resolves ( orgOneIdentities ) ; mySandBox . stub ( EnvironmentFactory , 'getEnvironment' ) . returns ( mockRuntime ) ; const blockchainWalletExplorerProvider = ExtensionUtil . getBlockchainWalletExplorerProvider ( ) ; const walletItems = await blockchainWalletExplorerProvider . getChildren ( ) ; const walletGroup = walletItems [ 0 ] as WalletGroupTreeItem ; const walletTreeItems = await blockchainWalletExplorerProvider . getChildren ( walletGroup ) ; const walletItem = walletTreeItems [ 0 ] as LocalWalletTreeItem ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY , walletItem ) ; should . not . exist ( result ) ; showOrgQuickPickStub . should . have . been . calledWith ( `Select the organization which the identity belongs to` , localEnvironmentEntry ) ; showWalletsQuickPickStub . should . not . have . been . called ; inputBoxStub . should . not . have . been . called ; fsReadFile . should . not . have . been . called ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , 'addWalletIdentity' ) ; sendTelemetryEventStub . should . not . have . been . called ; } ) ; } ) ; describe ( 'called from WalletRegistryEntry - addWallet command' , ( ) => { it ( 'should test an identity can be enrolled to a new wallet' , async ( ) => { const emptyWalletRegistryEntry = new FabricWalletRegistryEntry ( ) ; emptyWalletRegistryEntry . name = 'emptyWallet' ; emptyWalletRegistryEntry . walletPath = path . join ( rootPath , '../../test/data/walletDir/emptyWallet' ) ; await FabricWalletRegistry . instance ( ) . add ( emptyWalletRegistryEntry ) ; fsReadFile . resolves ( `{
                    "certificateAuthorities": {
                        "ca0": {
                            "url": "http://ca0url"
                        }
                    }
                }` ) ; inputBoxStub . onFirstCall ( ) . resolves ( 'myMSPID' ) ; inputBoxStub . onSecondCall ( ) . resolves ( 'greenConga' ) ; addIdentityMethodStub . resolves ( UserInputUtil . ADD_ID_SECRET_OPTION ) ; const myGatewayA = await FabricGatewayRegistry . instance ( ) . get ( 'myGatewayA' ) ; showGatewayQuickPickBoxStub . resolves ( { label : 'myGatewayA' , data : myGatewayA } ) ; getEnrollIdSecretStub . resolves ( { enrollmentID : 'enrollID' , enrollmentSecret : 'enrollSecret' } ) ; enrollStub . resolves ( { certificate : '---CERT---' , privateKey : '---KEY---' } ) ; importIdentityStub . resetHistory ( ) ; const result = await vscode . commands . executeCommand ( ExtensionCommands . ADD_WALLET_IDENTITY , emptyWalletRegistryEntry ) ; result . should . equal ( 'greenConga' ) ; showGatewayQuickPickBoxStub . should . have . been . calledOnceWith ( 'Choose a gateway to enroll the identity with' , false , true , undefined , undefined ) ; showWalletsQuickPickStub . should . not . have . been . called ; inputBoxStub . should . have . been . calledTwice ; fsReadFile . should . have . been . called ; getEnrollIdSecretStub . should . have . been . calledOnce ; enrollStub . should . have . been . calledOnceWith ( 'http://ca0url' , 'enrollID' , 'enrollSecret' ) ; importIdentityStub . should . have . been . calledOnceWith ( '---CERT---' , '---KEY---' , 'greenConga' , 'myMSPID' ) ; executeCommandStub . should . have . been . calledWith ( ExtensionCommands . REFRESH_WALLETS ) ; logSpy . getCall ( 0 ) . should . have . been . calledWith ( LogType . INFO , undefined , 'addWalletIdentity' ) ; logSpy . getCall ( 1 ) . should . have . been . calledWith ( LogType . SUCCESS , 'Successfully added identity' , `Successfully added identity to wallet` ) ; sendTelemetryEventStub . should . have . been . calledOnceWithExactly ( 'addWalletIdentityCommand' , { method : 'enrollmentID' } ) ; } ) ; } ) ; } ) ; } ) ;