@@ -7,6 +7,7 @@ import { ErrorNotification, PrintNotification } from "../../shared/test_protocol
77import { disposeAll , notUndefined } from "../../shared/utils" ;
88import { fsPath } from "../../shared/utils/fs" ;
99import { config } from "../config" ;
10+ import { TestDiscoverer } from "../lsp/test_discoverer" ;
1011import { formatForTerminal } from "../utils/vscode/terminals" ;
1112
1213export class VsCodeTestController implements TestEventListener , IAmDisposable {
@@ -16,15 +17,17 @@ export class VsCodeTestController implements TestEventListener, IAmDisposable {
1617 private nodeForItem = new WeakMap < vs . TestItem , TreeNode > ( ) ;
1718 private testRuns : { [ key : string ] : vs . TestRun | undefined } = { } ;
1819
19-
20- constructor ( private readonly logger : Logger , private readonly model : TestModel ) {
20+ constructor ( private readonly logger : Logger , private readonly model : TestModel , private readonly discoverer : TestDiscoverer | undefined ) {
2121 const controller = vs . tests . createTestController ( "dart" , "Dart & Flutter" ) ;
2222 this . controller = controller ;
2323 this . disposables . push ( controller ) ;
2424 this . disposables . push ( model . onDidChangeTreeData . listen ( ( node ) => this . onDidChangeTreeData ( node ) ) ) ;
2525 this . disposables . push ( vs . debug . onDidTerminateDebugSession ( ( e ) => this . handleDebugSessionEnd ( e ) ) ) ;
2626 model . addTestEventListener ( this ) ;
2727
28+ if ( discoverer )
29+ controller . resolveHandler = ( item : vs . TestItem | undefined ) => this . resolveTestItem ( item ) ;
30+
2831 controller . createRunProfile ( "Run" , vs . TestRunProfileKind . Run , ( request , token ) => {
2932 this . runTests ( false , request , token ) ;
3033 } ) ;
@@ -34,6 +37,20 @@ export class VsCodeTestController implements TestEventListener, IAmDisposable {
3437 } ) ;
3538 }
3639
40+ private async resolveTestItem ( item : vs . TestItem | undefined ) : Promise < void > {
41+ if ( ! this . discoverer )
42+ return ;
43+
44+ if ( ! item ) {
45+ this . discoverer . beginTestDiscovery ( ) ;
46+ return ;
47+ }
48+
49+ const node = this . nodeForItem . get ( item ) ;
50+ if ( node instanceof SuiteNode )
51+ await this . discoverer . discoverTestsForSuite ( node ) ;
52+ }
53+
3754 public registerTestRun ( dartCodeDebugSessionID : string , run : vs . TestRun ) : void {
3855 this . testRuns [ dartCodeDebugSessionID ] = run ;
3956 }
@@ -140,6 +157,11 @@ export class VsCodeTestController implements TestEventListener, IAmDisposable {
140157 this . updateFields ( existingItem , node ) ;
141158 }
142159
160+ // For new suites without chilren, set canResolveChildren because we can
161+ // open the file and discover tests from the Outline if the user expands them.
162+ if ( node instanceof SuiteNode && node . children . length === 0 )
163+ existingItem . canResolveChildren = true ;
164+
143165 existingItem . children . replace (
144166 node . children . map ( ( c ) => this . createOrUpdateNode ( c ) ) . filter ( notUndefined ) ,
145167 ) ;
0 commit comments