'use strict' ; import * as sinon from 'sinon' ; import * as vscode from 'vscode' ; import * as sinonChai from 'sinon-chai' ; import * as chai from 'chai' ; import * as path from 'path' ; import { TestUtil } from '../TestUtil' ; import { ExtensionCommands } from '../../ExtensionCommands' ; import { VSCodeBlockchainOutputAdapter } from '../../extension/logging/VSCodeBlockchainOutputAdapter' ; import { LogType , FileSystemUtil , FabricEnvironmentRegistry } from 'ibm-blockchain-platform-common' ; import { UserInputUtil } from '../../extension/commands/UserInputUtil' ; import { FabricWalletRegistry , FabricWalletRegistryEntry , FabricGatewayRegistry , FabricGatewayRegistryEntry } from 'ibm-blockchain-platform-common' ; import { BlockchainWalletExplorerProvider } from '../../extension/explorer/walletExplorer' ; import { WalletTreeItem } from '../../extension/explorer/wallets/WalletTreeItem' ; import { SettingConfigurations } from '../../extension/configurations' ; import { ExtensionUtil } from '../../extension/util/ExtensionUtil' ; chai . should ( ) ; chai . use ( sinonChai ) ; describe ( 'removeWalletCommand' , ( ) => { const mySandBox = sinon . createSandbox ( ) ; let logSpy ; let warningStub ; let showWalletsQuickPickStub ; let purpleWallet ; let blueWallet ; let createdWallet ; before ( async ( ) => { await TestUtil . setupTests ( mySandBox ) ; } ) ; beforeEach ( async ( ) => { logSpy = mySandBox . stub ( VSCodeBlockchainOutputAdapter . instance ( ) , 'log' ) ; warningStub = mySandBox . stub ( vscode . window , 'showWarningMessage' ) ; warningStub . resolves ( 'No' ) ; showWalletsQuickPickStub = mySandBox . stub ( UserInputUtil , 'showWalletsQuickPickBox' ) ; await FabricEnvironmentRegistry . instance ( ) . clear ( ) ; await FabricWalletRegistry . instance ( ) . clear ( ) ; purpleWallet = new FabricWalletRegistryEntry ( { name : 'purpleWallet' , walletPath : path . join ( __dirname , '../../test/tmp/v2/wallets/purpleWallet' ) } ) ; blueWallet = new FabricWalletRegistryEntry ( { name : 'blueWallet' , walletPath : path . join ( __dirname , '../../test/tmp/v2/wallets/blueWallet' ) } ) ; const extensionDirectory = SettingConfigurations . getExtensionDir ( ) ; const directoryPath = FileSystemUtil . getDirPath ( extensionDirectory ) ; createdWallet = new FabricWalletRegistryEntry ( { name : 'createdWallet' , walletPath : path . join ( directoryPath , 'wallets' , 'createdWallet' ) } ) ; await FabricWalletRegistry . instance ( ) . add ( purpleWallet ) ; await FabricWalletRegistry . instance ( ) . add ( blueWallet ) ; await FabricWalletRegistry . instance ( ) . add ( createdWallet ) ; await FabricGatewayRegistry . instance ( ) . clear ( ) ; await FabricGatewayRegistry . instance ( ) . add ( { name : 'gatewayA' , associatedWallet : 'blueWallet' , connectionProfilePath : path . join ( 'myPath' , 'connection.json' ) } ) ; await FabricGatewayRegistry . instance ( ) . add ( { name : 'gatewayB' , associatedWallet : 'blueWallet' , connectionProfilePath : path . join ( 'myPath' , 'connection.json' ) } ) ; await FabricGatewayRegistry . instance ( ) . add ( { name : 'gatewayC' , associatedWallet : 'greenWallet' , connectionProfilePath : path . join ( 'myPath' , 'connection.json' ) } ) ; } ) ; afterEach ( ( ) => { mySandBox . restore ( ) ; } ) ; it ( 'should remove a wallet when called from the command palette' , async ( ) => { showWalletsQuickPickStub . resolves ( [ { label : purpleWallet . name , data : purpleWallet } ] ) ; warningStub . resolves ( 'Yes' ) ; await vscode . commands . executeCommand ( ExtensionCommands . REMOVE_WALLET ) ; showWalletsQuickPickStub . should . be . calledWithExactly ( 'Choose the wallet(s) that you want to remove' , true , false ) ; const wallets = await FabricWalletRegistry . instance ( ) . getAll ( ) ; wallets . length . should . equal ( 2 ) ; wallets [ 0 ] . name . should . equal ( blueWallet . name ) ; wallets [ 1 ] . name . should . equal ( createdWallet . name ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWithExactly ( LogType . INFO , undefined , `removeWallet` ) ; logSpy . getCall ( 1 ) . should . have . been . calledWithExactly ( LogType . SUCCESS , `Successfully removed ${ purpleWallet . name } wallet` ) ; } ) ; it ( 'should allow user to remove mulitple wallets when called from the command palette' , async ( ) => { showWalletsQuickPickStub . resolves ( [ { label : purpleWallet . name , data : purpleWallet } , { label : blueWallet . name , data : blueWallet } ] ) ; warningStub . resolves ( 'Yes' ) ; await vscode . commands . executeCommand ( ExtensionCommands . REMOVE_WALLET ) ; showWalletsQuickPickStub . should . be . calledWithExactly ( 'Choose the wallet(s) that you want to remove' , true , false ) ; const wallets = await FabricWalletRegistry . instance ( ) . getAll ( ) ; wallets . length . should . equal ( 1 ) ; wallets [ 0 ] . name . should . equal ( createdWallet . name ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWithExactly ( LogType . INFO , undefined , `removeWallet` ) ; logSpy . getCall ( 1 ) . should . have . been . calledWithExactly ( LogType . SUCCESS , `Successfully removed wallets` ) ; } ) ; it ( 'should show an error if no other wallets have been added' , async ( ) => { await FabricWalletRegistry . instance ( ) . clear ( ) ; await vscode . commands . executeCommand ( ExtensionCommands . REMOVE_WALLET ) ; showWalletsQuickPickStub . should . not . have . been . called ; logSpy . getCall ( 0 ) . should . have . been . calledWithExactly ( LogType . INFO , undefined , `removeWallet` ) ; logSpy . getCall ( 1 ) . should . have . been . calledWithExactly ( LogType . ERROR , `No wallets to remove. Local wallets cannot be removed.` ) ; } ) ; it ( 'should handle the user cancelling selecting a wallet' , async ( ) => { showWalletsQuickPickStub . resolves ( undefined ) ; await vscode . commands . executeCommand ( ExtensionCommands . REMOVE_WALLET ) ; showWalletsQuickPickStub . should . be . calledWithExactly ( 'Choose the wallet(s) that you want to remove' , true , false ) ; const wallets = await FabricWalletRegistry . instance ( ) . getAll ( ) ; wallets . length . should . equal ( 3 ) ; wallets [ 0 ] . name . should . equal ( blueWallet . name ) ; wallets [ 1 ] . name . should . equal ( createdWallet . name ) ; wallets [ 2 ] . name . should . equal ( purpleWallet . name ) ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , `removeWallet` ) ; } ) ; it ( 'should handle the user not selecting a wallet' , async ( ) => { showWalletsQuickPickStub . resolves ( [ ] ) ; await vscode . commands . executeCommand ( ExtensionCommands . REMOVE_WALLET ) ; showWalletsQuickPickStub . should . be . calledWithExactly ( 'Choose the wallet(s) that you want to remove' , true , false ) ; const wallets = await FabricWalletRegistry . instance ( ) . getAll ( ) ; wallets . length . should . equal ( 3 ) ; wallets [ 0 ] . name . should . equal ( blueWallet . name ) ; wallets [ 1 ] . name . should . equal ( createdWallet . name ) ; wallets [ 2 ] . name . should . equal ( purpleWallet . name ) ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , `removeWallet` ) ; } ) ; it ( 'should delete a created wallet and an existing wallet from the file system if the user selects yes' , async ( ) => { showWalletsQuickPickStub . resolves ( [ { label : createdWallet . name , data : createdWallet } , { label : blueWallet . name , data : blueWallet } ] ) ; warningStub . resolves ( 'Yes' ) ; await vscode . commands . executeCommand ( ExtensionCommands . REMOVE_WALLET ) ; showWalletsQuickPickStub . should . be . calledWithExactly ( 'Choose the wallet(s) that you want to remove' , true , false ) ; const wallets = await FabricWalletRegistry . instance ( ) . getAll ( ) ; wallets . length . should . equal ( 1 ) ; wallets [ 0 ] . name . should . equal ( purpleWallet . name ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWithExactly ( LogType . INFO , undefined , `removeWallet` ) ; logSpy . getCall ( 1 ) . should . have . been . calledWithExactly ( LogType . SUCCESS , `Successfully removed wallets` ) ; } ) ; it ( 'should handle the user cancelling the warning box' , async ( ) => { showWalletsQuickPickStub . resolves ( [ { label : blueWallet . name , data : blueWallet } ] ) ; warningStub . resolves ( undefined ) ; await vscode . commands . executeCommand ( ExtensionCommands . REMOVE_WALLET ) ; showWalletsQuickPickStub . should . be . calledWithExactly ( 'Choose the wallet(s) that you want to remove' , true , false ) ; const wallets = await FabricWalletRegistry . instance ( ) . getAll ( ) ; wallets . length . should . equal ( 3 ) ; wallets [ 0 ] . name . should . equal ( blueWallet . name ) ; wallets [ 1 ] . name . should . equal ( createdWallet . name ) ; wallets [ 2 ] . name . should . equal ( purpleWallet . name ) ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , `removeWallet` ) ; } ) ; it ( "should handle the user selecting 'No' for the warning box" , async ( ) => { showWalletsQuickPickStub . resolves ( [ { label : blueWallet . name , data : blueWallet } ] ) ; await vscode . commands . executeCommand ( ExtensionCommands . REMOVE_WALLET ) ; showWalletsQuickPickStub . should . be . calledWithExactly ( 'Choose the wallet(s) that you want to remove' , true , false ) ; const wallets = await FabricWalletRegistry . instance ( ) . getAll ( ) ; wallets . length . should . equal ( 3 ) ; wallets [ 0 ] . name . should . equal ( blueWallet . name ) ; wallets [ 1 ] . name . should . equal ( createdWallet . name ) ; wallets [ 2 ] . name . should . equal ( purpleWallet . name ) ; logSpy . should . have . been . calledOnceWithExactly ( LogType . INFO , undefined , `removeWallet` ) ; } ) ; it ( 'should remove the wallet association from any gateways' , async ( ) => { showWalletsQuickPickStub . resolves ( [ { label : blueWallet . name , data : blueWallet } ] ) ; warningStub . resolves ( 'Yes' ) ; await vscode . commands . executeCommand ( ExtensionCommands . REMOVE_WALLET ) ; showWalletsQuickPickStub . should . be . calledWithExactly ( 'Choose the wallet(s) that you want to remove' , true , false ) ; const wallets = await FabricWalletRegistry . instance ( ) . getAll ( ) ; wallets . length . should . equal ( 2 ) ; wallets [ 0 ] . name . should . equal ( createdWallet . name ) ; wallets [ 1 ] . name . should . equal ( purpleWallet . name ) ; let result = await FabricGatewayRegistry . instance ( ) . get ( 'gatewayA' ) ; result . associatedWallet . should . equal ( '' ) ; result = await FabricGatewayRegistry . instance ( ) . get ( 'gatewayB' ) ; result . associatedWallet . should . equal ( '' ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWithExactly ( LogType . INFO , undefined , `removeWallet` ) ; logSpy . getCall ( 1 ) . should . have . been . calledWithExactly ( LogType . SUCCESS , `Successfully removed ${ blueWallet . name } wallet` ) ; } ) ; it ( 'should remove the wallet association from any gateways when deleting multiple wallets' , async ( ) => { showWalletsQuickPickStub . resolves ( [ { label : blueWallet . name , data : blueWallet } , { label : purpleWallet . name , data : purpleWallet } ] ) ; warningStub . resolves ( 'Yes' ) ; await vscode . commands . executeCommand ( ExtensionCommands . REMOVE_WALLET ) ; showWalletsQuickPickStub . should . be . calledWithExactly ( 'Choose the wallet(s) that you want to remove' , true , false ) ; const wallets = await FabricWalletRegistry . instance ( ) . getAll ( ) ; wallets . length . should . equal ( 1 ) ; wallets [ 0 ] . name . should . equal ( createdWallet . name ) ; let result = await FabricGatewayRegistry . instance ( ) . get ( 'gatewayA' ) ; result . associatedWallet . should . equal ( '' ) ; result = await FabricGatewayRegistry . instance ( ) . get ( 'gatewayB' ) ; result . associatedWallet . should . equal ( '' ) ; result = await FabricGatewayRegistry . instance ( ) . get ( 'gatewayC' ) ; result . associatedWallet . should . equal ( 'greenWallet' ) ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWithExactly ( LogType . INFO , undefined , `removeWallet` ) ; logSpy . getCall ( 1 ) . should . have . been . calledWithExactly ( LogType . SUCCESS , `Successfully removed wallets` ) ; } ) ; describe ( 'called from the tree' , ( ) => { it ( 'should remove a wallet when called from the wallet tree' , async ( ) => { const blockchainWalletExplorerProvider = ExtensionUtil . getBlockchainWalletExplorerProvider ( ) ; const walletGroups = await blockchainWalletExplorerProvider . getChildren ( ) as WalletTreeItem [ ] ; const groupChildren = await blockchainWalletExplorerProvider . getChildren ( walletGroups [ 0 ] ) as WalletTreeItem [ ] ; const purpleWalletTreeItem = groupChildren [ groupChildren . length - 1 ] ; warningStub . resolves ( 'Yes' ) ; await vscode . commands . executeCommand ( ExtensionCommands . REMOVE_WALLET , purpleWalletTreeItem ) ; const wallets = await FabricWalletRegistry . instance ( ) . getAll ( ) ; wallets . length . should . equal ( 2 ) ; wallets [ 0 ] . name . should . equal ( blueWallet . name ) ; wallets [ 1 ] . name . should . equal ( createdWallet . name ) ; showWalletsQuickPickStub . should . not . have . been . called ; logSpy . should . have . been . calledTwice ; logSpy . getCall ( 0 ) . should . have . been . calledWithExactly ( LogType . INFO , undefined , `removeWallet` ) ; logSpy . getCall ( 1 ) . should . have . been . calledWithExactly ( LogType . SUCCESS , `Successfully removed ${ purpleWallet . name } wallet` ) ; } ) ; } ) ; } ) ;