import { expect } from 'chai' ; import * as path from 'path' ; import * as vscode from 'vscode' ; import { Disposable , Uri } from 'vscode' ; import * as extension from '../../src/extension' ; import { Observable } from '../../src/utils/observable' ; const fixtureDir = path . resolve ( path . join ( __dirname , '..' , '..' , '..' , 'fixtures' ) ) ; suite ( 'Extension Tests' , ( ) => { test ( 'cargo tasks are auto-detected' , async ( ) => { const ext = vscode . extensions . getExtension < extension . Api > ( 'rust-lang.rust' ) ! ; const { activeWorkspace } = await ext . activate ( ) ; const projects = [ path . join ( fixtureDir , 'bare-lib-project' ) , path . join ( fixtureDir , 'another-lib-project' ) , ] . map ( path => Uri . file ( path ) . fsPath ) ; const expected = [ { subcommand : 'build' , group : vscode . TaskGroup . Build , cwd : projects [ 0 ] } , { subcommand : 'build' , group : vscode . TaskGroup . Build , cwd : projects [ 1 ] } , { subcommand : 'check' , group : vscode . TaskGroup . Build , cwd : projects [ 0 ] } , { subcommand : 'check' , group : vscode . TaskGroup . Build , cwd : projects [ 1 ] } , { subcommand : 'test' , group : vscode . TaskGroup . Test , cwd : projects [ 1 ] } , { subcommand : 'clean' , group : vscode . TaskGroup . Clean , cwd : projects [ 1 ] } , { subcommand : 'run' , group : undefined , cwd : projects [ 1 ] } , ] ; const whenWorkspacesActive = projects . map ( path => whenWorkspaceActive ( activeWorkspace , path ) ) ; await vscode . commands . executeCommand ( 'workbench.action.quickOpen' , path . join ( projects [ 0 ] , 'src' , 'lib.rs' ) ) ; await waitForUI ( ) ; await vscode . commands . executeCommand ( 'workbench.action.acceptSelectedQuickOpenItem' ) ; await waitForUI ( ) ; await vscode . commands . executeCommand ( 'workbench.action.keepEditor' ) ; await whenWorkspacesActive [ 0 ] ; expect ( await fetchBriefTasks ( ) ) . to . include . deep . members ( [ expected [ 0 ] ] ) ; await vscode . commands . executeCommand ( 'workbench.action.quickOpen' , path . join ( projects [ 1 ] , 'src' , 'lib.rs' ) ) ; await waitForUI ( ) ; await vscode . commands . executeCommand ( 'workbench.action.acceptSelectedQuickOpenItem' ) ; await waitForUI ( ) ; await whenWorkspacesActive [ 1 ] ; expect ( await fetchBriefTasks ( ) ) . to . include . deep . members ( expected ) ; } ) . timeout ( 60000 ) ; } ) ; /** Fetches current VSCode tasks' partial objects for ease of assertion */ async function fetchBriefTasks ( ) { const tasks = await vscode . tasks . fetchTasks ( ) ; return tasks . map ( task => ( { subcommand : task . definition . subcommand , group : task . group , cwd : ( ( task . execution instanceof vscode . ProcessExecution || task . execution instanceof vscode . ShellExecution ) && task . execution ?. options ?. cwd ) || undefined , } ) ) ; } param fsPath function whenWorkspaceActive ( observable , fsPath ) { return new Promise ( resolve => { let disposable ; disposable = observable . observe ( value => { if ( value && value . folder . uri . fsPath === fsPath ) { if ( disposable ) { disposable . dispose ( ) ; disposable = undefined ; } resolve ( value ) ; } } ) ; } ) ; } const delay = ( ms ) => new Promise ( resolve => setTimeout ( resolve , ms ) ) ; /**
 * Returns a promise that resolves after executing the current call stack.
 * Sometimes we need to wait for the UI to catch up (since it's executed on the
 * same thread as JS) before and UI-dependent logic, such as a sequence of
 * user-like inputs. To avoid any races (which unfortunately *did* happen), it's
 * best if we interweave the delays between each UI action.
 */ const waitForUI = ( ) => delay ( process . env . CI === 'true' ? 500 : 0 ) ;