'use strict' ; import * as vscode from 'vscode' ; import * as sinon from 'sinon' ; import * as chai from 'chai' ; import * as sinonChai from 'sinon-chai' ; import * as path from 'path' ; import * as ejs from 'ejs' ; import { PreReqView } from '../../extension/webview/PreReqView' ; import { View } from '../../extension/webview/View' ; import { ExtensionCommands } from '../../ExtensionCommands' ; import { Reporter } from '../../extension/util/Reporter' ; import { ExtensionUtil } from '../../extension/util/ExtensionUtil' ; import { TestUtil } from '../TestUtil' ; import { DependencyManager } from '../../extension/dependencies/DependencyManager' ; import { GlobalState , DEFAULT_EXTENSION_DATA , ExtensionData } from '../../extension/util/GlobalState' ; import { SettingConfigurations } from '../../extension/configurations' ; import { VSCodeBlockchainOutputAdapter } from '../../extension/logging/VSCodeBlockchainOutputAdapter' ; import { defaultDependencies , Dependencies } from '../../extension/dependencies/Dependencies' ; import { LogType } from 'ibm-blockchain-platform-common' ; const should = chai . should ( ) ; chai . use ( sinonChai ) ; interface VersionOverrides { docker ? : string ; node ? : string ; npm ? : string ; go ? : string ; goExtension ? : string ; java ? : string ; javaLanguageExtension ? : string ; javaDebuggerExtension ? : string ; javaTestRunnerExtension ? : string ; systemRequirements ? : number ; openssl ? : string ; } interface CompleteOverrides { systemRequirements ? : boolean ; dockerForWindows ? : boolean ; } const generateDependencies = ( versions = { } , completes = { } ) : Dependencies => { const dependencies = { ... defaultDependencies . required , ... defaultDependencies . optional } ; dependencies . node . version = versions . hasOwnProperty ( 'node' ) ? versions . node : '10.15.3' ; dependencies . npm . version = versions . hasOwnProperty ( 'npm' ) ? versions . npm : '6.4.1' ; dependencies . docker . version = versions . hasOwnProperty ( 'docker' ) ? versions . docker : '17.7.0' ; dependencies . go . version = versions . hasOwnProperty ( 'go' ) ? versions . go : '1.13.0' ; dependencies . goExtension . version = versions . hasOwnProperty ( 'goExtension' ) ? versions . goExtension : '1.0.0' ; dependencies . java . version = versions . hasOwnProperty ( 'java' ) ? versions . java : '1.7.1' ; dependencies . javaLanguageExtension . version = versions . hasOwnProperty ( 'javaLanguageExtension' ) ? versions . javaLanguageExtension : '1.0.0' ; dependencies . javaDebuggerExtension . version = versions . hasOwnProperty ( 'javaDebuggerExtension' ) ? versions . javaDebuggerExtension : '1.0.0' ; dependencies . javaTestRunnerExtension . version = versions . hasOwnProperty ( 'javaTestRunnerExtension' ) ? versions . javaTestRunnerExtension : '1.0.0' ; dependencies . systemRequirements . version = versions . hasOwnProperty ( 'systemRequirements' ) ? versions . systemRequirements : 4 ; dependencies . openssl . version = versions . hasOwnProperty ( 'openssl' ) ? versions . openssl : '1.0.2' ; dependencies . dockerForWindows . complete = versions . hasOwnProperty ( 'dockerForWindows' ) ? completes . dockerForWindows : true ; dependencies . systemRequirements . complete = versions . hasOwnProperty ( 'systemRequirements' ) ? completes . systemRequirements : true ; dependencies . node . requiredVersion = '>=10.15.3 || >=12.13.1' ; return dependencies ; } ; describe ( 'PreReqView' , ( ) => { const mySandBox = sinon . createSandbox ( ) ; let context ; let createWebviewPanelStub ; let reporterStub ; let executeCommandStub ; before ( async ( ) => { await TestUtil . setupTests ( mySandBox ) ; } ) ; beforeEach ( async ( ) => { context = GlobalState . getExtensionContext ( ) ; executeCommandStub = mySandBox . stub ( vscode . commands , 'executeCommand' ) ; executeCommandStub . callThrough ( ) ; createWebviewPanelStub = mySandBox . stub ( vscode . window , 'createWebviewPanel' ) ; View [ 'openPanels' ] . splice ( 0 , View [ 'openPanels' ] . length ) ; reporterStub = mySandBox . stub ( Reporter . instance ( ) , 'sendTelemetryEvent' ) ; createWebviewPanelStub . returns ( { title : 'Prerequisites' , webview : { onDidReceiveMessage : mySandBox . stub ( ) , asWebviewUri : mySandBox . stub ( ) } , reveal : mySandBox . stub ( ) , dispose : mySandBox . stub ( ) , onDidDispose : mySandBox . stub ( ) , onDidChangeViewState : mySandBox . stub ( ) , _isDisposed : false } ) ; } ) ; afterEach ( ( ) => { mySandBox . restore ( ) ; } ) ; it ( 'should register and show prereq page' , async ( ) => { const preReqView = new PreReqView ( context ) ; await preReqView . openView ( false ) ; createWebviewPanelStub . should . have . been . called ; } ) ; it ( 'should reveal prereq page if already open' , async ( ) => { const preReqView = new PreReqView ( context ) ; await preReqView . openView ( true ) ; await preReqView . openView ( true ) ; createWebviewPanelStub . should . have . been . calledOnce ; should . equal ( createWebviewPanelStub . getCall ( 1 ) , null ) ; } ) ; describe ( 'getHTMLString' , ( ) => { it ( 'should show message that all prerequisites have been installed' , async ( ) => { const dependencies = generateDependencies ( ) ; const getPreReqVersionsStub = mySandBox . stub ( DependencyManager . instance ( ) , 'getPreReqVersions' ) . resolves ( dependencies ) ; const hasPreReqsInstalledStub = mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) . resolves ( true ) ; const preReqView = new PreReqView ( context ) ; const webview = { asWebviewUri : mySandBox . stub ( ) } ; const html = await preReqView . getHTMLString ( webview ) ; getPreReqVersionsStub . should . have . been . calledOnce ; hasPreReqsInstalledStub . should . have . been . calledOnceWith ( dependencies ) ; html . should . contain ( '<div id="complete-panel" class="large-panel">' ) ; html . should . contain ( `<div id="check-finish-button" class="finish" onclick="finish();">Let's Blockchain!</div>` ) ; html . should . contain ( '<span class="prereqs-number">(0)</span>' ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . node , version : '10.15.3' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . npm , version : '6.4.1' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . required . docker , version : '17.7.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . go , version : '1.13.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . goExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaLanguageExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaDebuggerExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaTestRunnerExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . required . systemRequirements , complete : true , version : 4 } ) ) ; } ) ; it ( `shouldn't show message that prerequisites have been installed` , async ( ) => { const dependencies = generateDependencies ( { node : undefined , docker : undefined , javaLanguageExtension : undefined } ) ; const getPreReqVersionsStub = mySandBox . stub ( DependencyManager . instance ( ) , 'getPreReqVersions' ) . resolves ( dependencies ) ; const hasPreReqsInstalledStub = mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) . resolves ( false ) ; const preReqView = new PreReqView ( context ) ; const webview = { asWebviewUri : mySandBox . stub ( ) } ; const html = await preReqView . getHTMLString ( webview ) ; getPreReqVersionsStub . should . have . been . calledOnce ; hasPreReqsInstalledStub . should . have . been . calledOnceWith ( dependencies ) ; html . should . contain ( '<div id="complete-panel" class="large-panel hidden">' ) ; html . should . contain ( `<div id="check-finish-button" class="check" onclick="check();">Check again</div>` ) ; html . should . contain ( '<span class="prereqs-number">(1)</span>' ) ; html . should . not . contain ( JSON . stringify ( { ... defaultDependencies . optional . node , version : '' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . npm , version : '6.4.1' } ) ) ; html . should . not . contain ( JSON . stringify ( { ... defaultDependencies . required . docker , version : '' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . go , version : '1.13.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . goExtension , version : '1.0.0' } ) ) ; html . should . not . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaLanguageExtension , version : '' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaDebuggerExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaTestRunnerExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . required . systemRequirements , complete : true , version : 4 } ) ) ; } ) ; it ( 'should be able to pass dependencies and if complete' , async ( ) => { const getPreReqVersionsSpy = mySandBox . spy ( DependencyManager . instance ( ) , 'getPreReqVersions' ) ; mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) . resolves ( true ) ; const preReqView = new PreReqView ( context ) ; const webview = { asWebviewUri : mySandBox . stub ( ) } ; const dependencies = generateDependencies ( ) ; const html = await preReqView . getHTMLString ( webview , dependencies , true ) ; getPreReqVersionsSpy . should . not . have . been . called ; html . should . contain ( '<div id="complete-panel" class="large-panel">' ) ; html . should . contain ( `<div id="check-finish-button" class="finish" onclick="finish();">Let's Blockchain!</div>` ) ; html . should . contain ( '<span class="prereqs-number">(0)</span>' ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . node , version : '10.15.3' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . npm , version : '6.4.1' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . required . docker , version : '17.7.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . go , version : '1.13.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . goExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaLanguageExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaDebuggerExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaTestRunnerExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . required . systemRequirements , complete : true , version : 4 } ) ) ; } ) ; it ( 'should be able to pass localFabricFunctionality flag' , async ( ) => { const getPreReqVersionsSpy = mySandBox . spy ( DependencyManager . instance ( ) , 'getPreReqVersions' ) ; mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) . resolves ( true ) ; const getSettingsStub = mySandBox . stub ( ) ; const updateSettingsStub = mySandBox . stub ( ) . resolves ( ) ; const getConfigurationStub = mySandBox . stub ( vscode . workspace , 'getConfiguration' ) ; getConfigurationStub . returns ( { get : getSettingsStub , update : updateSettingsStub } ) ; const preReqView = new PreReqView ( context ) ; const webview = { asWebviewUri : mySandBox . stub ( ) } ; const dependencies = generateDependencies ( ) ; const html = await preReqView . getHTMLString ( webview , dependencies , true , false ) ; getPreReqVersionsSpy . should . not . have . been . called ; getSettingsStub . should . not . have . been . calledWith ( SettingConfigurations . EXTENSION_LOCAL_FABRIC ) ; html . should . contain ( '<div id="complete-panel" class="large-panel">' ) ; html . should . contain ( `<div id="check-finish-button" class="finish" onclick="finish();">Let's Blockchain!</div>` ) ; html . should . contain ( '<span class="prereqs-number">(0)</span>' ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . node , version : '10.15.3' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . npm , version : '6.4.1' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . required . docker , version : '17.7.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . go , version : '1.13.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . goExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaLanguageExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaDebuggerExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaTestRunnerExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . required . systemRequirements , complete : true , version : 4 } ) ) ; } ) ; it ( 'should handle error rendering the webview' , async ( ) => { const getPreReqVersionsStub = mySandBox . stub ( DependencyManager . instance ( ) , 'getPreReqVersions' ) . resolves ( { ... defaultDependencies . required , ... defaultDependencies . optional , } ) ; mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) . resolves ( false ) ; const error = new Error ( 'error happened' ) ; mySandBox . stub ( ejs , 'renderFile' ) . yields ( error ) ; const preReqView = new PreReqView ( context ) ; const webview = { asWebviewUri : mySandBox . stub ( ) } ; await preReqView . getHTMLString ( webview ) . should . be . rejectedWith ( error ) ; getPreReqVersionsStub . should . have . been . calledOnce ; } ) ; it ( 'should use the dependencies passed in through the constructor when available' , async ( ) => { const getPreReqVersionsStub = mySandBox . stub ( DependencyManager . instance ( ) , 'getPreReqVersions' ) ; const hasPreReqsInstalledStub = mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) ; const dependencies = generateDependencies ( ) ; const preReqView = new PreReqView ( context , dependencies ) ; const webview = { asWebviewUri : mySandBox . stub ( ) } ; const html = await preReqView . getHTMLString ( webview ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . node , version : '10.15.3' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . npm , version : '6.4.1' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . required . docker , version : '17.7.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . go , version : '1.13.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . goExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaLanguageExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaDebuggerExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . optional . javaTestRunnerExtension , version : '1.0.0' } ) ) ; html . should . contain ( JSON . stringify ( { ... defaultDependencies . required . systemRequirements , complete : true , version : 4 } ) ) ; getPreReqVersionsStub . should . not . be . called ; hasPreReqsInstalledStub . should . be . calledWith ( dependencies ) ; } ) ; } ) ; describe ( 'openPanelInner' , ( ) => { let logSpy ; let setupCommandsStub ; let completeActivationStub ; beforeEach ( async ( ) => { await vscode . workspace . getConfiguration ( ) . update ( SettingConfigurations . EXTENSION_BYPASS_PREREQS , false , vscode . ConfigurationTarget . Global ) ; logSpy = mySandBox . stub ( VSCodeBlockchainOutputAdapter . instance ( ) , 'log' ) ; setupCommandsStub = mySandBox . stub ( ExtensionUtil , 'setupCommands' ) . resolves ( ) ; completeActivationStub = mySandBox . stub ( ExtensionUtil , 'completeActivation' ) . resolves ( ) ; } ) ; it ( 'should dispose prereq page if the user closes the tab' , async ( ) => { mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) . resolves ( false ) ; mySandBox . stub ( DependencyManager . instance ( ) , 'isValidDependency' ) . returns ( false ) ; const onDidDisposePromises = [ ] ; executeCommandStub . withArgs ( ExtensionCommands . OPEN_HOME_PAGE ) . resolves ( ) ; const onDidDisposeStub = mySandBox . stub ( ) ; onDidDisposePromises . push ( new Promise ( ( resolve ) : void => { onDidDisposeStub . onCall ( 0 ) . yields ( ) ; onDidDisposeStub . onCall ( 1 ) . callsFake ( async ( callback ) => { await callback ( ) ; resolve ( ) ; } ) ; } ) ) ; createWebviewPanelStub . returns ( { title : 'Prerequisites' , webview : { onDidReceiveMessage : mySandBox . stub ( ) , asWebviewUri : mySandBox . stub ( ) } , reveal : ( ) : void => { return ; } , onDidDispose : onDidDisposeStub , onDidChangeViewState : mySandBox . stub ( ) , _isDisposed : false } ) ; const preReqView = new PreReqView ( context ) ; await preReqView . openView ( true ) ; await Promise . all ( onDidDisposePromises ) ; reporterStub . should . have . been . calledOnceWithExactly ( 'openedView' , { name : 'Prerequisites' } ) ; logSpy . should . have . been . calledOnceWith ( LogType . WARNING , `Required prerequisites are missing. They must be installed before the extension can be used.` ) ; createWebviewPanelStub . should . have . been . calledOnceWith ( 'preReq' , 'Prerequisites' , vscode . ViewColumn . One , { enableScripts : true , retainContextWhenHidden : true , enableCommandUris : true , localResourceRoots : [ vscode . Uri . file ( path . join ( context . extensionPath , 'resources' ) ) , vscode . Uri . file ( path . join ( context . extensionPath , 'build' ) ) ] } ) ; } ) ; it ( 'should dispose prereq page and restore command hijacking' , async ( ) => { const hasPreReqsInstalledStub = mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) ; mySandBox . stub ( DependencyManager . instance ( ) , 'isValidDependency' ) . returns ( false ) ; const onDidDisposePromises = [ ] ; executeCommandStub . withArgs ( ExtensionCommands . OPEN_HOME_PAGE ) . resolves ( ) ; const onDidDisposeStub = mySandBox . stub ( ) ; onDidDisposePromises . push ( new Promise ( ( resolve ) : void => { onDidDisposeStub . onCall ( 0 ) . yields ( ) ; onDidDisposeStub . onCall ( 1 ) . callsFake ( async ( callback ) => { await callback ( ) ; resolve ( ) ; } ) ; } ) ) ; createWebviewPanelStub . returns ( { title : 'Prerequisites' , webview : { onDidReceiveMessage : mySandBox . stub ( ) , asWebviewUri : mySandBox . stub ( ) } , reveal : ( ) : void => { return ; } , onDidDispose : onDidDisposeStub , onDidChangeViewState : mySandBox . stub ( ) , _isDisposed : false } ) ; const preReqView = new PreReqView ( context ) ; preReqView . restoreCommandHijack = true ; await preReqView . openView ( true ) ; await Promise . all ( onDidDisposePromises ) ; hasPreReqsInstalledStub . should . have . been . calledOnce ; reporterStub . should . have . been . calledOnceWithExactly ( 'openedView' , { name : 'Prerequisites' } ) ; logSpy . should . not . have . been . calledOnceWith ( LogType . WARNING , `Required prerequisites are missing. They must be installed before the extension can be used.` ) ; setupCommandsStub . should . have . been . calledOnce ; completeActivationStub . should . have . been . calledOnce ; executeCommandStub . should . have . been . calledWith ( ExtensionCommands . OPEN_HOME_PAGE ) ; createWebviewPanelStub . should . have . been . calledOnceWith ( 'preReq' , 'Prerequisites' , vscode . ViewColumn . One , { enableScripts : true , retainContextWhenHidden : true , enableCommandUris : true , localResourceRoots : [ vscode . Uri . file ( path . join ( context . extensionPath , 'resources' ) ) , vscode . Uri . file ( path . join ( context . extensionPath , 'build' ) ) ] } ) ; } ) ; it ( 'should dispose prereq page if the user closes the tab, restore commands and open home page' , async ( ) => { mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) . resolves ( true ) ; mySandBox . stub ( DependencyManager . instance ( ) , 'isValidDependency' ) . returns ( true ) ; const onDidDisposePromises = [ ] ; executeCommandStub . withArgs ( ExtensionCommands . OPEN_HOME_PAGE ) . resolves ( ) ; const onDidDisposeStub = mySandBox . stub ( ) ; onDidDisposePromises . push ( new Promise ( ( resolve ) : void => { onDidDisposeStub . onCall ( 0 ) . yields ( ) ; onDidDisposeStub . onCall ( 1 ) . callsFake ( async ( callback ) => { await callback ( ) ; resolve ( ) ; } ) ; } ) ) ; createWebviewPanelStub . returns ( { title : 'Prerequisites' , webview : { onDidReceiveMessage : mySandBox . stub ( ) , asWebviewUri : mySandBox . stub ( ) } , reveal : ( ) : void => { return ; } , onDidDispose : onDidDisposeStub , onDidChangeViewState : mySandBox . stub ( ) , _isDisposed : false } ) ; const preReqView = new PreReqView ( context ) ; await preReqView . openView ( true ) ; await Promise . all ( onDidDisposePromises ) ; reporterStub . should . have . been . calledOnceWithExactly ( 'openedView' , { name : 'Prerequisites' } ) ; logSpy . should . not . have . been . calledOnceWith ( LogType . WARNING , `Required prerequisites are missing. They must be installed before the extension can be used.` ) ; setupCommandsStub . should . have . been . calledOnce ; completeActivationStub . should . have . been . calledOnce ; executeCommandStub . should . have . been . calledWith ( ExtensionCommands . OPEN_HOME_PAGE ) ; createWebviewPanelStub . should . have . been . calledOnceWith ( 'preReq' , 'Prerequisites' , vscode . ViewColumn . One , { enableScripts : true , retainContextWhenHidden : true , enableCommandUris : true , localResourceRoots : [ vscode . Uri . file ( path . join ( context . extensionPath , 'resources' ) ) , vscode . Uri . file ( path . join ( context . extensionPath , 'build' ) ) ] } ) ; } ) ; it ( 'should dispose prereq page if the user closes the tab, restore commands and open home page if bypass prereq setting is true' , async ( ) => { await vscode . workspace . getConfiguration ( ) . update ( SettingConfigurations . EXTENSION_BYPASS_PREREQS , true , vscode . ConfigurationTarget . Global ) ; mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) . resolves ( false ) ; mySandBox . stub ( DependencyManager . instance ( ) , 'isValidDependency' ) . returns ( false ) ; const onDidDisposePromises = [ ] ; executeCommandStub . withArgs ( ExtensionCommands . OPEN_HOME_PAGE ) . resolves ( ) ; const onDidDisposeStub = mySandBox . stub ( ) ; onDidDisposePromises . push ( new Promise ( ( resolve ) : void => { onDidDisposeStub . onCall ( 0 ) . yields ( ) ; onDidDisposeStub . onCall ( 1 ) . callsFake ( async ( callback ) => { await callback ( ) ; resolve ( ) ; } ) ; } ) ) ; createWebviewPanelStub . returns ( { title : 'Prerequisites' , webview : { onDidReceiveMessage : mySandBox . stub ( ) , asWebviewUri : mySandBox . stub ( ) } , reveal : ( ) : void => { return ; } , onDidDispose : onDidDisposeStub , onDidChangeViewState : mySandBox . stub ( ) , _isDisposed : false } ) ; const preReqView = new PreReqView ( context ) ; await preReqView . openView ( true ) ; await Promise . all ( onDidDisposePromises ) ; reporterStub . should . have . been . calledOnceWithExactly ( 'openedView' , { name : 'Prerequisites' } ) ; logSpy . should . not . have . been . calledOnceWith ( LogType . WARNING , `Required prerequisites are missing. They must be installed before the extension can be used.` ) ; setupCommandsStub . should . have . been . calledOnce ; completeActivationStub . should . have . been . calledOnce ; executeCommandStub . should . have . been . calledWith ( ExtensionCommands . OPEN_HOME_PAGE ) ; createWebviewPanelStub . should . have . been . calledOnceWith ( 'preReq' , 'Prerequisites' , vscode . ViewColumn . One , { enableScripts : true , retainContextWhenHidden : true , enableCommandUris : true , localResourceRoots : [ vscode . Uri . file ( path . join ( context . extensionPath , 'resources' ) ) , vscode . Uri . file ( path . join ( context . extensionPath , 'build' ) ) ] } ) ; } ) ; it ( `should handle 'finish' message` , async ( ) => { const disposeStub = mySandBox . stub ( ) . returns ( undefined ) ; const onDidDisposePromises = [ ] ; onDidDisposePromises . push ( new Promise ( ( resolve ) : void => { createWebviewPanelStub . returns ( { title : 'Prerequisites' , webview : { onDidReceiveMessage : async ( callback ) : Promise < void > => { await callback ( { command : 'finish' , localFabricFunctionality : true } ) ; resolve ( ) ; } , asWebviewUri : mySandBox . stub ( ) } , reveal : ( ) : void => { return ; } , dispose : disposeStub , onDidDispose : mySandBox . stub ( ) , onDidChangeViewState : mySandBox . stub ( ) , _isDisposed : false } ) ; } ) ) ; const getSettingsStub = mySandBox . stub ( ) ; const updateSettingsStub = mySandBox . stub ( ) . resolves ( ) ; const getConfigurationStub = mySandBox . stub ( vscode . workspace , 'getConfiguration' ) ; getConfigurationStub . returns ( { get : getSettingsStub , update : updateSettingsStub } ) ; const preReqView = new PreReqView ( context ) ; await preReqView . openView ( true ) ; await Promise . all ( onDidDisposePromises ) ; reporterStub . should . have . been . calledOnceWithExactly ( 'openedView' , { name : 'Prerequisites' } ) ; preReqView . restoreCommandHijack . should . equal ( true ) ; disposeStub . should . have . been . calledOnce ; updateSettingsStub . should . have . been . calledOnceWith ( SettingConfigurations . EXTENSION_LOCAL_FABRIC , true , vscode . ConfigurationTarget . Global ) ; } ) ; it ( `should handle 'check' message where Docker for Windows has been confirmed` , async ( ) => { const mockDependencies = generateDependencies ( { } , { systemRequirements : false , dockerForWindows : false } ) ; const hasPreReqsInstalledStub = mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) ; hasPreReqsInstalledStub . resolves ( true ) ; const getPreReqVersionsStub = mySandBox . stub ( DependencyManager . instance ( ) , 'getPreReqVersions' ) . resolves ( mockDependencies ) ; mySandBox . stub ( DependencyManager . instance ( ) , 'isValidDependency' ) . returns ( false ) ; const getGlobalStateStub = mySandBox . stub ( GlobalState , 'get' ) . returns ( DEFAULT_EXTENSION_DATA ) ; const updateGlobalStateStub = mySandBox . stub ( GlobalState , 'update' ) . resolves ( ) ; const expectedNewState = DEFAULT_EXTENSION_DATA ; expectedNewState . dockerForWindows = true ; const expectedMockDependencies = mockDependencies ; expectedMockDependencies . dockerForWindows . complete = true ; const onDidDisposePromises = [ ] ; onDidDisposePromises . push ( new Promise ( ( resolve ) : void => { createWebviewPanelStub . returns ( { title : 'Prerequisites' , webview : { onDidReceiveMessage : async ( callback ) : Promise < void > => { await callback ( { command : 'check' , dockerForWindows : true , localFabricFunctionality : true , toggle : undefined } ) ; resolve ( ) ; } , asWebviewUri : mySandBox . stub ( ) } , reveal : ( ) : void => { return ; } , onDidDispose : mySandBox . stub ( ) , onDidChangeViewState : mySandBox . stub ( ) , _isDisposed : false } ) ; } ) ) ; const getSettingsStub = mySandBox . stub ( ) ; const updateSettingsStub = mySandBox . stub ( ) . resolves ( ) ; const getConfigurationStub = mySandBox . stub ( vscode . workspace , 'getConfiguration' ) ; getConfigurationStub . returns ( { get : getSettingsStub , update : updateSettingsStub } ) ; const preReqView = new PreReqView ( context ) ; const getHTMLStringStub = mySandBox . stub ( preReqView , 'getHTMLString' ) . resolves ( ) ; await preReqView . openView ( true ) ; await Promise . all ( onDidDisposePromises ) ; updateSettingsStub . should . have . been . calledOnceWith ( SettingConfigurations . EXTENSION_LOCAL_FABRIC , true , vscode . ConfigurationTarget . Global ) ; reporterStub . should . have . been . calledOnceWithExactly ( 'openedView' , { name : 'Prerequisites' } ) ; getPreReqVersionsStub . should . have . been . called ; getGlobalStateStub . should . have . been . calledOnce ; updateGlobalStateStub . should . have . been . calledOnceWithExactly ( expectedNewState ) ; hasPreReqsInstalledStub . should . have . been . calledWith ( expectedMockDependencies ) ; getHTMLStringStub . should . have . been . calledWith ( sinon . match ( { asWebviewUri : sinon . match . any } ) , expectedMockDependencies , true , true ) ; logSpy . should . have . been . calledWith ( LogType . SUCCESS , undefined , 'Finished checking installed dependencies' ) ; logSpy . should . not . have . been . calledWith ( LogType . INFO , `Local Fabric functionality set to 'true'.` ) ; } ) ; it ( `should handle 'check' message where System Requirements has been confirmed` , async ( ) => { const mockDependencies = generateDependencies ( { } , { systemRequirements : false , dockerForWindows : false } ) ; const hasPreReqsInstalledStub = mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) ; hasPreReqsInstalledStub . resolves ( true ) ; const getPreReqVersionsStub = mySandBox . stub ( DependencyManager . instance ( ) , 'getPreReqVersions' ) . resolves ( mockDependencies ) ; mySandBox . stub ( DependencyManager . instance ( ) , 'isValidDependency' ) . returns ( false ) ; const getGlobalStateStub = mySandBox . stub ( GlobalState , 'get' ) . returns ( DEFAULT_EXTENSION_DATA ) ; const updateGlobalStateStub = mySandBox . stub ( GlobalState , 'update' ) . resolves ( ) ; const expectedNewState = DEFAULT_EXTENSION_DATA ; const expectedMockDependencies = mockDependencies ; expectedMockDependencies . systemRequirements . complete = true ; const onDidDisposePromises = [ ] ; onDidDisposePromises . push ( new Promise ( ( resolve ) : void => { createWebviewPanelStub . returns ( { title : 'Prerequisites' , webview : { onDidReceiveMessage : async ( callback ) : Promise < void > => { await callback ( { command : 'check' , systemRequirements : true , localFabricFunctionality : false , toggle : 'true' } ) ; resolve ( ) ; } , asWebviewUri : mySandBox . stub ( ) } , reveal : ( ) : void => { return ; } , onDidDispose : mySandBox . stub ( ) , onDidChangeViewState : mySandBox . stub ( ) , _isDisposed : false } ) ; } ) ) ; const getSettingsStub = mySandBox . stub ( ) ; const updateSettingsStub = mySandBox . stub ( ) . resolves ( ) ; const getConfigurationStub = mySandBox . stub ( vscode . workspace , 'getConfiguration' ) ; getConfigurationStub . returns ( { get : getSettingsStub , update : updateSettingsStub } ) ; const preReqView = new PreReqView ( context ) ; const getHTMLStringStub = mySandBox . stub ( preReqView , 'getHTMLString' ) . resolves ( ) ; await preReqView . openView ( true ) ; await Promise . all ( onDidDisposePromises ) ; updateSettingsStub . should . have . been . calledOnceWith ( SettingConfigurations . EXTENSION_LOCAL_FABRIC , false , vscode . ConfigurationTarget . Global ) ; reporterStub . should . have . been . calledOnceWithExactly ( 'openedView' , { name : 'Prerequisites' } ) ; getPreReqVersionsStub . should . have . been . called ; getGlobalStateStub . should . have . been . calledOnce ; updateGlobalStateStub . should . have . been . calledOnceWithExactly ( expectedNewState ) ; hasPreReqsInstalledStub . should . have . been . calledWith ( expectedMockDependencies ) ; getHTMLStringStub . should . have . been . calledWith ( sinon . match ( { asWebviewUri : sinon . match . any } ) , expectedMockDependencies , true , false ) ; logSpy . should . have . been . calledWith ( LogType . INFO , `Local Fabric functionality set to 'false'.` ) ; logSpy . should . have . been . calledWith ( LogType . SUCCESS , undefined , 'Finished checking installed dependencies' ) ; } ) ; it ( `should handle 'check' message where neither System Requirements nor Docker on Windows have been confirmed` , async ( ) => { const mockDependencies = generateDependencies ( { } , { systemRequirements : false , dockerForWindows : false } ) ; const hasPreReqsInstalledStub = mySandBox . stub ( DependencyManager . instance ( ) , 'hasPreReqsInstalled' ) ; hasPreReqsInstalledStub . resolves ( true ) ; const getPreReqVersionsStub = mySandBox . stub ( DependencyManager . instance ( ) , 'getPreReqVersions' ) . resolves ( mockDependencies ) ; mySandBox . stub ( DependencyManager . instance ( ) , 'isValidDependency' ) . returns ( false ) ; const getGlobalStateStub = mySandBox . stub ( GlobalState , 'get' ) . returns ( DEFAULT_EXTENSION_DATA ) ; const updateGlobalStateStub = mySandBox . stub ( GlobalState , 'update' ) . resolves ( ) ; const expectedMockDependencies = mockDependencies ; expectedMockDependencies . systemRequirements . complete = true ; const onDidDisposePromises = [ ] ; onDidDisposePromises . push ( new Promise ( ( resolve ) : void => { createWebviewPanelStub . returns ( { title : 'Prerequisites' , webview : { onDidReceiveMessage : async ( callback ) : Promise < void > => { await callback ( { command : 'check' , localFabricFunctionality : false , toggle : 'true' } ) ; resolve ( ) ; } , asWebviewUri : mySandBox . stub ( ) } , reveal : ( ) : void => { return ; } , onDidDispose : mySandBox . stub ( ) , onDidChangeViewState : mySandBox . stub ( ) , _isDisposed : false } ) ; } ) ) ; const getSettingsStub = mySandBox . stub ( ) ; const updateSettingsStub = mySandBox . stub ( ) . resolves ( ) ; const getConfigurationStub = mySandBox . stub ( vscode . workspace , 'getConfiguration' ) ; getConfigurationStub . returns ( { get : getSettingsStub , update : updateSettingsStub } ) ; const preReqView = new PreReqView ( context ) ; const getHTMLStringStub = mySandBox . stub ( preReqView , 'getHTMLString' ) . resolves ( ) ; await preReqView . openView ( true ) ; await Promise . all ( onDidDisposePromises ) ; updateSettingsStub . should . have . been . calledOnceWith ( SettingConfigurations . EXTENSION_LOCAL_FABRIC , false , vscode . ConfigurationTarget . Global ) ; reporterStub . should . have . been . calledOnceWithExactly ( 'openedView' , { name : 'Prerequisites' } ) ; getPreReqVersionsStub . should . have . been . called ; getGlobalStateStub . should . have . not . been . called ; updateGlobalStateStub . should . have . not . been . called ; hasPreReqsInstalledStub . should . have . been . calledWith ( expectedMockDependencies ) ; getHTMLStringStub . should . have . been . calledWith ( sinon . match ( { asWebviewUri : sinon . match . any } ) , expectedMockDependencies , true , false ) ; logSpy . should . have . been . calledWith ( LogType . INFO , `Local Fabric functionality set to 'false'.` ) ; logSpy . should . have . been . calledWith ( LogType . SUCCESS , undefined , 'Finished checking installed dependencies' ) ; } ) ; it ( `should handle 'skip' message where dependencies are missing` , async ( ) => { const mockDependencies = generateDependencies ( { node : undefined , npm : undefined } ) ; const getPreReqVersionsStub = mySandBox . stub ( DependencyManager . instance ( ) , 'getPreReqVersions' ) . resolves ( mockDependencies ) ; const isValidDependency = mySandBox . stub ( DependencyManager . instance ( ) , 'isValidDependency' ) ; isValidDependency . returns ( true ) ; isValidDependency . withArgs ( { ... defaultDependencies . optional . node } ) . returns ( false ) ; isValidDependency . withArgs ( { ... defaultDependencies . optional . npm } ) . returns ( false ) ; const disposeStub = mySandBox . stub ( ) ; const onDidDisposePromises = [ ] ; onDidDisposePromises . push ( new Promise ( ( resolve ) : void => { createWebviewPanelStub . returns ( { title : 'Prerequisites' , webview : { onDidReceiveMessage : async ( callback ) : Promise < void > => { await callback ( { command : 'skip' , localFabricFunctionality : true } ) ; resolve ( ) ; } , asWebviewUri : mySandBox . stub ( ) } , reveal : ( ) : void => { return ; } , dispose : disposeStub , onDidDispose : mySandBox . stub ( ) , onDidChangeViewState : mySandBox . stub ( ) , _isDisposed : false } ) ; } ) ) ; const preReqView = new PreReqView ( context ) ; const getHTMLStringStub = mySandBox . stub ( preReqView , 'getHTMLString' ) . resolves ( ) ; const getSettingsStub = mySandBox . stub ( ) ; const updateSettingsStub = mySandBox . stub ( ) . resolves ( ) ; const getConfigurationStub = mySandBox . stub ( vscode . workspace , 'getConfiguration' ) ; getConfigurationStub . returns ( { get : getSettingsStub , update : updateSettingsStub } ) ; await preReqView . openView ( true ) ; await Promise . all ( onDidDisposePromises ) ; preReqView . restoreCommandHijack . should . equal ( true ) ; reporterStub . getCall ( 0 ) . should . have . been . calledWithExactly ( 'openedView' , { name : 'Prerequisites' } ) ; reporterStub . getCall ( 1 ) . should . have . been . calledWithExactly ( 'skipPreReqs' , { node : 'missing' , npm : 'missing' } ) ; getHTMLStringStub . should . have . been . calledOnce ; disposeStub . should . have . been . calledOnce ; updateSettingsStub . getCall ( 0 ) . should . have . been . calledWithExactly ( SettingConfigurations . EXTENSION_BYPASS_PREREQS , true , vscode . ConfigurationTarget . Global ) ; updateSettingsStub . getCall ( 1 ) . should . have . been . calledWithExactly ( SettingConfigurations . EXTENSION_LOCAL_FABRIC , true , vscode . ConfigurationTarget . Global ) ; getPreReqVersionsStub . should . have . been . called ; } ) ; it ( `should handle 'skip' message where all dependencies are installed` , async ( ) => { const mockDependencies = generateDependencies ( ) ; const getPreReqVersionsStub = mySandBox . stub ( DependencyManager . instance ( ) , 'getPreReqVersions' ) . resolves ( mockDependencies ) ; const isValidDependency = mySandBox . stub ( DependencyManager . instance ( ) , 'isValidDependency' ) ; isValidDependency . returns ( true ) ; const disposeStub = mySandBox . stub ( ) ; const onDidDisposePromises = [ ] ; onDidDisposePromises . push ( new Promise ( ( resolve ) : void => { createWebviewPanelStub . returns ( { title : 'Prerequisites' , webview : { onDidReceiveMessage : async ( callback ) : Promise < void > => { await callback ( { command : 'skip' , localFabricFunctionality : false } ) ; resolve ( ) ; } , asWebviewUri : mySandBox . stub ( ) } , reveal : ( ) : void => { return ; } , dispose : disposeStub , onDidDispose : mySandBox . stub ( ) , onDidChangeViewState : mySandBox . stub ( ) , _isDisposed : false } ) ; } ) ) ; const preReqView = new PreReqView ( context ) ; const getHTMLStringStub = mySandBox . stub ( preReqView , 'getHTMLString' ) . resolves ( ) ; const getSettingsStub = mySandBox . stub ( ) ; const updateSettingsStub = mySandBox . stub ( ) . resolves ( ) ; const getConfigurationStub = mySandBox . stub ( vscode . workspace , 'getConfiguration' ) ; getConfigurationStub . returns ( { get : getSettingsStub , update : updateSettingsStub } ) ; await preReqView . openView ( true ) ; await Promise . all ( onDidDisposePromises ) ; preReqView . restoreCommandHijack . should . equal ( true ) ; reporterStub . should . have . been . calledOnceWithExactly ( 'openedView' , { name : 'Prerequisites' } ) ; getHTMLStringStub . should . have . been . calledOnce ; disposeStub . should . have . been . calledOnce ; updateSettingsStub . getCall ( 0 ) . should . have . been . calledWithExactly ( SettingConfigurations . EXTENSION_BYPASS_PREREQS , true , vscode . ConfigurationTarget . Global ) ; updateSettingsStub . getCall ( 1 ) . should . have . been . calledWithExactly ( SettingConfigurations . EXTENSION_LOCAL_FABRIC , false , vscode . ConfigurationTarget . Global ) ; getPreReqVersionsStub . should . have . been . called ; } ) ; it ( `should handle unknown command` , async ( ) => { const getPreReqVersionsStub = mySandBox . stub ( DependencyManager . instance ( ) , 'getPreReqVersions' ) ; const isValidDependency = mySandBox . stub ( DependencyManager . instance ( ) , 'isValidDependency' ) ; isValidDependency . returns ( true ) ; const onDidDisposePromises = [ ] ; onDidDisposePromises . push ( new Promise ( ( resolve ) : void => { createWebviewPanelStub . returns ( { title : 'Prerequisites' , webview : { onDidReceiveMessage : async ( callback ) : Promise < void > => { await callback ( { command : 'unknown-command' } ) ; resolve ( ) ; } , asWebviewUri : mySandBox . stub ( ) } , reveal : ( ) : void => { return ; } , onDidDispose : mySandBox . stub ( ) , onDidChangeViewState : mySandBox . stub ( ) , _isDisposed : false } ) ; } ) ) ; const preReqView = new PreReqView ( context ) ; const getHTMLStringStub = mySandBox . stub ( preReqView , 'getHTMLString' ) . resolves ( ) ; await preReqView . openView ( true ) ; await Promise . all ( onDidDisposePromises ) ; reporterStub . should . have . been . calledOnceWithExactly ( 'openedView' , { name : 'Prerequisites' } ) ; getHTMLStringStub . should . have . been . calledOnce ; getPreReqVersionsStub . should . not . have . been . called ; } ) ; } ) ; } ) ;