11import { strict as assert } from "assert" ;
22import { writeFileSync } from "fs" ;
33import * as path from "path" ;
4+ import { SinonStub } from "sinon" ;
45import * as vs from "vscode" ;
56import { URI } from "vscode-uri" ;
67import { DebuggerType } from "../../shared/enums" ;
@@ -9,9 +10,10 @@ import { fsPath } from "../../shared/utils/fs";
910import { TestOutlineVisitor } from "../../shared/utils/outline" ;
1011import { waitFor } from "../../shared/utils/promises" ;
1112import * as testUtils from "../../shared/utils/test" ;
13+ import { DartFileCoverage } from "../../shared/vscode/coverage" ;
1214import { DartDebugClient } from "../dart_debug_client" ;
1315import { createDebugClient , startDebugger , waitAllThrowIfTerminates } from "../debug_helpers" ;
14- import { activateWithoutAnalysis , captureDebugSessionCustomEvents , checkTreeNodeResults , clearTestTree , currentEditor , customScriptExt , delay , ensureHasRunWithArgsStarting , fakeCancellationToken , getCodeLens , getExpectedResults , getPackages , getResolvedDebugConfiguration , helloWorldExampleSubFolderProjectTestFile , helloWorldFolder , helloWorldProjectTestFile , helloWorldTestBrokenFile , helloWorldTestDupeNameFile , helloWorldTestDynamicFile , helloWorldTestEmptyFile , helloWorldTestEnvironmentFile , helloWorldTestMainFile , helloWorldTestSelective1File , helloWorldTestSelective2File , helloWorldTestShortFile , helloWorldTestTreeFile , isTestDoneSuccessNotification , logger , makeTestTextTree , openFile as openFileBasic , positionOf , prepareHasRunFile , privateApi , setConfigForTest , setTestContent , waitForResult } from "../helpers" ;
16+ import { activateWithoutAnalysis , captureDebugSessionCustomEvents , checkTreeNodeResults , clearTestTree , currentEditor , customScriptExt , delay , ensureHasRunWithArgsStarting , fakeCancellationToken , getCodeLens , getExpectedResults , getPackages , getResolvedDebugConfiguration , helloWorldExampleSubFolderProjectTestFile , helloWorldFolder , helloWorldMainLibFile , helloWorldProjectTestFile , helloWorldTestBrokenFile , helloWorldTestDupeNameFile , helloWorldTestDynamicFile , helloWorldTestEmptyFile , helloWorldTestEnvironmentFile , helloWorldTestMainFile , helloWorldTestSelective1File , helloWorldTestSelective2File , helloWorldTestShortFile , helloWorldTestTreeFile , isTestDoneSuccessNotification , logger , makeTestTextTree , openFile as openFileBasic , positionOf , prepareHasRunFile , privateApi , sb , setConfigForTest , setTestContent , waitForResult } from "../helpers" ;
1517
1618describe ( "dart test debugger" , ( ) => {
1719 // We have tests that require external packages.
@@ -636,6 +638,102 @@ test/empty_test.dart
636638 ) ;
637639 } ) ;
638640
641+ describe ( "collects coverage" , ( ) => {
642+ let addCoverageStub : SinonStub | undefined ;
643+
644+ beforeEach ( ( ) => {
645+ const controller = privateApi . testController ;
646+ const createTestRunOriginal = controller . controller . createTestRun . bind ( controller . controller ) ;
647+ const createTestRunStub = sb . stub ( controller . controller , "createTestRun" ) ;
648+ createTestRunStub . callsFake ( ( request : vs . TestRunRequest ) => {
649+ const originalResult = createTestRunOriginal ( request ) ;
650+ addCoverageStub = sb . stub ( originalResult , "addCoverage" ) . returns ( null ) ;
651+ return originalResult ;
652+ } ) ;
653+ } ) ;
654+
655+ it ( "for a basic test" , async ( ) => {
656+ // Discover tests.
657+ await openFile ( helloWorldTestMainFile ) ;
658+ await waitForResult ( ( ) => ! ! privateApi . fileTracker . getOutlineFor ( helloWorldTestMainFile ) ) ;
659+ const controller = privateApi . testController ;
660+
661+ const suiteNode = controller . controller . items . get ( `SUITE:${ fsPath ( helloWorldTestMainFile ) } ` ) ! ;
662+ const testRequest = new vs . TestRunRequest ( [ suiteNode ] ) ;
663+
664+ await controller . runTests ( false , true , testRequest , fakeCancellationToken ) ;
665+
666+ assert ( addCoverageStub ?. calledOnce ) ;
667+ const coverage = addCoverageStub . firstCall . args [ 0 ] as DartFileCoverage ;
668+ assert . equal ( fsPath ( coverage . uri ) , fsPath ( helloWorldMainLibFile ) ) ; // App file, not test file.
669+ assert . ok ( coverage . statementCoverage . covered > 0 ) ;
670+ assert . ok ( coverage . statementCoverage . total > 0 ) ;
671+ } ) ;
672+
673+ it . skip ( "and includes dependencies" , async ( ) => {
674+ // Requires --coverage-package for Dart
675+ // // Discover tests.
676+ // await openFile(helloWorldExampleTestFile);
677+ // await waitForResult(() => !!privateApi.fileTracker.getOutlineFor(helloWorldExampleTestFile));
678+
679+ // const controller = privateApi.testController;
680+ // const suiteNode = controller.controller.items.get(`SUITE:${fsPath(helloWorldExampleTestFile)}`)!;
681+ // const testRequest = new vs.TestRunRequest([suiteNode]);
682+
683+ // await controller.runTests(false, true, testRequest, fakeCancellationToken);
684+
685+ // assert(addCoverageStub?.called);
686+ // const coverageFiles = addCoverageStub.getCalls().map((call) => fsPath((call.args[0] as DartFileCoverage).uri));
687+ // assert.deepStrictEqual(coverageFiles, [fsPath(helloWorldExamplePrinterFile), fsPath(helloWorldPrinterFile)]);
688+ } ) ;
689+
690+ it . skip ( "and excludes configured paths" , async ( ) => {
691+ // Requires --coverage-package for Dart
692+ // await setConfigForTest("dart", "coverageExcludePatterns", ["**/example/**"]);
693+
694+ // // Discover tests.
695+ // await openFile(helloWorldExampleSubFolderProjectTestFile);
696+ // await waitForResult(() => !!privateApi.fileTracker.getOutlineFor(helloWorldExampleSubFolderProjectTestFile));
697+
698+ // const controller = privateApi.testController;
699+ // const suiteNode = controller.controller.items.get(`SUITE:${fsPath(helloWorldExampleSubFolderProjectTestFile)}`)!;
700+ // const testRequest = new vs.TestRunRequest([suiteNode]);
701+
702+ // await controller.runTests(false, true, testRequest, fakeCancellationToken);
703+
704+ // assert(addCoverageStub?.called);
705+ // const coverageFiles = addCoverageStub.getCalls().map((call) => fsPath((call.args[0] as DartFileCoverage).uri));
706+ // assert.deepStrictEqual(coverageFiles, [fsPath(helloWorldPrinterFile)]);
707+ } ) ;
708+
709+ it . skip ( "uses correct regex for --coverage-package" , ( ) => {
710+ // Requires --coverage-package for Dart
711+ // const config = testUtils.getLaunchConfig(
712+ // false, // noDebug
713+ // true, // includeCoverage
714+ // true, // isFlutter
715+ // fsPath(helloWorldExampleTestFile),
716+ // undefined, // testSelection
717+ // false, // shouldRunTestByLine
718+ // undefined, // runSkipped
719+ // undefined, // template
720+ // ["hello_world", "hello_world_example"], // workspacePackageNames
721+ // );
722+
723+ // const toolArgs = (config as { toolArgs?: string[] }).toolArgs ?? [];
724+ // const coveragePackages: string[] = [];
725+ // for (let i = 0; i < toolArgs.length - 1; i++) {
726+ // if (toolArgs[i] === "--coverage-package")
727+ // coveragePackages.push(toolArgs[i + 1]);
728+ // }
729+
730+ // assert.deepStrictEqual(
731+ // coveragePackages,
732+ // [`^flutter_hello_world$`, `^flutter_hello_world_example$`],
733+ // );
734+ } ) ;
735+ } ) ;
736+
639737 function getTestRanges ( testSuiteUri : vs . Uri ) {
640738 const lines : string [ ] = [ ] ;
641739 function appendNode ( item : vs . TestItem , indent = 0 ) {
0 commit comments