import * as assert from 'assert' ; import * as fse from 'fs-extra' ; import * as os from 'os' ; import * as path from 'path' ; import * as vscode from 'vscode' ; import { createTestActionContext , runWithTestActionContext , TestOutputChannel , TestUserInput } from 'vscode-azureextensiondev' ; import { CentralTemplateProvider , deploySubpathSetting , envUtils , ext , FuncVersion , funcVersionSetting , getGlobalSetting , getRandomHexString , IActionContext , parseError , preDeployTaskSetting , ProjectLanguage , projectLanguageSetting , pythonVenvSetting , registerOnActionStartHandler , TemplateFilter , templateFilterSetting , TemplateSource , updateGlobalSetting , updateWorkspaceSetting } from '../extension.bundle' ; /**
 * Folder for most tests that do not need a workspace open
 */ export const testFolderPath = path . join ( os . tmpdir ( ) , `azFuncTest${ getRandomHexString ( ) }` ) ; export const longRunningTestsEnabled = envUtils . isEnvironmentVariableSet ( process . env . ENABLE_LONG_RUNNING_TESTS ) ; export const updateBackupTemplates = envUtils . isEnvironmentVariableSet ( process . env . AZFUNC_UPDATE_BACKUP_TEMPLATES ) ; export const skipStagingTemplateSource = envUtils . isEnvironmentVariableSet ( process . env . SKIP_STAGING_TEMPLATE_SOURCE ) ; const templateProviderMap = new Map < TemplateSource , CentralTemplateProvider > ( ) ; const requestTimeoutKey = 'requestTimeout' ; let oldRequestTimeout ; let testWorkspaceFolders ; let workspaceFolderIndex = 0 ; export function getTestWorkspaceFolder ( ) { if ( workspaceFolderIndex >= testWorkspaceFolders . length ) { throw new Error ( 'Not enough workspace folders. Add more in "test/test.code-workspace".' ) ; } const result = testWorkspaceFolders [ workspaceFolderIndex ] ; workspaceFolderIndex += 1 ; return result ; } suiteSetup ( async function ( this ) : Promise < void > { this . timeout ( 4 * 60 * 1000 ) ; oldRequestTimeout = getGlobalSetting ( requestTimeoutKey ) ; await updateGlobalSetting ( requestTimeoutKey , 45 ) ; await fse . ensureDir ( testFolderPath ) ; testWorkspaceFolders = await initTestWorkspaceFolders ( ) ; await vscode . commands . executeCommand ( 'azureFunctions.refresh' ) ; ext . outputChannel = new TestOutputChannel ( ) ; registerOnActionStartHandler ( context => { context . ui = new TestUserInput ( vscode ) ; } ) ; ext . defaultFuncCliPath = process . env . FUNC_PATH || path . join ( os . homedir ( ) , 'tools' , 'func' , 'func' ) ; if ( ! updateBackupTemplates ) { await preLoadTemplates ( ) ; } process . env . AzureWebJobsStorage = 'ignore' ; } ) ; suiteTeardown ( async function ( this ) : Promise < void > { this . timeout ( 90 * 1000 ) ; try { await fse . remove ( testFolderPath ) ; await cleanTestWorkspace ( ) ; } catch ( error ) { console . warn ( `Failed to delete test folder path: ${ parseError ( error ) . message }` ) ; } await updateGlobalSetting ( requestTimeoutKey , oldRequestTimeout ) ; } ) ; /**
 * Pre-load templates so that the first related unit test doesn't time out
 */ async function preLoadTemplates ( ) { const providers = [ ext . templateProvider . get ( await createTestActionContext ( ) ) ] ; for ( const source of allTemplateSources ) { if ( ! ( source === TemplateSource . Staging && skipStagingTemplateSource ) ) { const provider = new CentralTemplateProvider ( source ) ; templateProviderMap . set ( source , provider ) ; providers . push ( provider ) ; } } const tasks = [ ] ; for ( const provider of providers ) { await runWithTestActionContext ( 'preLoadTemplates' , async ( context ) => { ext . templateProvider . registerActionVariable ( provider , context ) ; for ( const version of Object . values ( FuncVersion ) ) { if ( version === FuncVersion . v4 ) { continue ; } for ( const language of [ ProjectLanguage . JavaScript , ProjectLanguage . CSharp ] ) { tasks . push ( provider . getFunctionTemplates ( context , testWorkspaceFolders [ 0 ] , language , version , TemplateFilter . Verified , undefined ) ) ; } } } ) ; } await Promise . all ( tasks ) ; } /**
 * Not worth testing older versions for every build
 */ export function isLongRunningVersion ( version ) { return version === FuncVersion . v1 || version === FuncVersion . v2 ; } export function shouldSkipVersion ( version ) { return isLongRunningVersion ( version ) && ! longRunningTestsEnabled ; } export const allTemplateSources = Object . values ( TemplateSource ) ; export async function runForTemplateSource ( context , source , callback ) { let templateProvider ; if ( source === undefined ) { templateProvider = ext . templateProvider . get ( context ) ; } else { templateProvider = templateProviderMap . get ( source ) ; if ( ! templateProvider ) { throw new Error ( `Unrecognized source ${ source }` ) ; } ext . templateProvider . registerActionVariable ( templateProvider , context ) ; } await callback ( templateProvider ) ; } export async function cleanTestWorkspace ( ) { for ( const folder of testWorkspaceFolders ) { const settings = [ projectLanguageSetting , funcVersionSetting , templateFilterSetting , deploySubpathSetting , preDeployTaskSetting , pythonVenvSetting ] ; for ( const setting of settings ) { await updateWorkspaceSetting ( setting , undefined , folder ) ; await updateGlobalSetting ( setting , undefined ) ; } await fse . emptyDir ( folder ) ; } workspaceFolderIndex = 0 ; } async function initTestWorkspaceFolders ( ) { const workspaceFolders = vscode . workspace . workspaceFolders ; if ( ! workspaceFolders ) { throw new Error ( "No workspace is open" ) ; } else { const folders = [ ] ; for ( let i = 0 ; i < workspaceFolders . length ; i ++ ) { const workspacePath = workspaceFolders [ i ] . uri . fsPath ; const folderName = path . basename ( workspacePath ) ; assert . equal ( folderName , String ( i ) , `Unexpected workspace folder name "${ folderName }".` ) ; await fse . ensureDir ( workspacePath ) ; await fse . emptyDir ( workspacePath ) ; folders . push ( workspacePath ) ; } return folders ; } }