Skip to content

Commit 5df5757

Browse files
committed
Automatically open the "Testing" pane when running tests depending on the testing.automaticallyOpenTestResults setting
1 parent a82df05 commit 5df5757

3 files changed

Lines changed: 100 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## [0.86.0]
4+
5+
* Automatically open the "Testing" pane when running tests depending on the `testing.automaticallyOpenTestResults` setting
6+
37
## [0.85.4]
48

59
* Fix bug where variable renaming would fail to update all occurrences of the variable in the presence of character code notation (0'Char)

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "logtalk-for-vscode",
33
"displayName": "Logtalk for VSCode",
44
"description": "Logtalk programming support",
5-
"version": "0.85.4",
5+
"version": "0.86.0",
66
"publisher": "LogtalkDotOrg",
77
"icon": "images/logtalk.png",
88
"license": "MIT",
@@ -1338,7 +1338,7 @@
13381338
"compile": "tsc -watch -p ./",
13391339
"test": "tsc ./tests/runTest.ts",
13401340
"vsix:make": "vsce package --baseImagesUrl https://raw.githubusercontent.com/llvm/llvm-project/master/clang-tools-extra/clangd/clients/clangd-vscode/",
1341-
"vsix:install": "code --install-extension logtalk-for-vscode-0.85.4.vsix"
1341+
"vsix:install": "code --install-extension logtalk-for-vscode-0.86.0.vsix"
13421342
},
13431343
"devDependencies": {
13441344
"@types/bluebird": "^3.5.38",

src/features/testsExplorer.ts

Lines changed: 94 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,17 @@ export class LogtalkTestsExplorerProvider implements Disposable {
323323
);
324324
this.logger.debug('Created test run');
325325

326+
// Open the Testing pane if configured to do so
327+
const testingSettings = workspace.getConfiguration('testing');
328+
const autoOpenSetting = testingSettings.get<string>('automaticallyOpenTestResults', 'neverOpen');
329+
if (autoOpenSetting === 'openOnTestStart' || autoOpenSetting === 'openExplorerOnTestStart') {
330+
await commands.executeCommand('workbench.view.extension.test');
331+
}
332+
326333
// Track directories where tests were run for Allure report generation
327334
const testDirectories = new Set<string>();
335+
// Track whether any tests failed for openOnTestFailure setting
336+
let hasFailures = false;
328337

329338
try {
330339
// If no specific tests are selected, run all tests via the tester file
@@ -348,13 +357,18 @@ export class LogtalkTestsExplorerProvider implements Disposable {
348357
const resultsFilePath = path.join(testerDir, '.vscode_test_results');
349358
if (fs.existsSync(resultsFilePath)) {
350359
this.logger.debug(`Parsing results from: ${resultsFilePath}`);
351-
await this.parseTestResultFile(Uri.file(resultsFilePath), testRun, withCoverage);
360+
hasFailures = await this.parseTestResultFile(Uri.file(resultsFilePath), testRun, withCoverage) || hasFailures;
352361
} else {
353362
this.logger.warn(`Results file not found: ${resultsFilePath}`);
354363
}
355364

356365
this.runAllureReportIfEnabled(testDirectories);
357366
testRun.end();
367+
368+
// Open the Testing pane if there were failures and setting is configured to do so
369+
if (hasFailures && autoOpenSetting === 'openOnTestFailure') {
370+
await commands.executeCommand('workbench.view.extension.test');
371+
}
358372
return;
359373
}
360374

@@ -379,14 +393,19 @@ export class LogtalkTestsExplorerProvider implements Disposable {
379393
const resultsFilePath = path.join(testerDir, '.vscode_test_results');
380394
if (fs.existsSync(resultsFilePath)) {
381395
this.logger.debug(`Parsing results from: ${resultsFilePath}`);
382-
await this.parseTestResultFile(Uri.file(resultsFilePath), testRun, withCoverage);
396+
hasFailures = await this.parseTestResultFile(Uri.file(resultsFilePath), testRun, withCoverage) || hasFailures;
383397
} else {
384398
this.logger.warn(`Results file not found: ${resultsFilePath}`);
385399
}
386400
}
387401
}
388402
this.runAllureReportIfEnabled(testDirectories);
389403
testRun.end();
404+
405+
// Open the Testing pane if there were failures and setting is configured to do so
406+
if (hasFailures && autoOpenSetting === 'openOnTestFailure') {
407+
await commands.executeCommand('workbench.view.extension.test');
408+
}
390409
return;
391410
}
392411

@@ -412,7 +431,7 @@ export class LogtalkTestsExplorerProvider implements Disposable {
412431
const dirResultsFilePath = path.join(testerDir, '.vscode_test_results');
413432
if (fs.existsSync(dirResultsFilePath)) {
414433
this.logger.debug(`Parsing results from: ${dirResultsFilePath}`);
415-
await this.parseTestResultFile(Uri.file(dirResultsFilePath), testRun, withCoverage);
434+
hasFailures = await this.parseTestResultFile(Uri.file(dirResultsFilePath), testRun, withCoverage) || hasFailures;
416435
} else {
417436
this.logger.warn(`Results file not found: ${dirResultsFilePath}`);
418437
}
@@ -433,7 +452,7 @@ export class LogtalkTestsExplorerProvider implements Disposable {
433452
const dirResultsFilePath = path.join(testerDir, '.vscode_test_results');
434453
if (fs.existsSync(dirResultsFilePath)) {
435454
this.logger.debug(`Parsing results from: ${dirResultsFilePath}`);
436-
await this.parseTestResultFile(Uri.file(dirResultsFilePath), testRun, withCoverage);
455+
hasFailures = await this.parseTestResultFile(Uri.file(dirResultsFilePath), testRun, withCoverage) || hasFailures;
437456
} else {
438457
this.logger.warn(`Results file not found: ${dirResultsFilePath}`);
439458
}
@@ -443,6 +462,11 @@ export class LogtalkTestsExplorerProvider implements Disposable {
443462

444463
this.runAllureReportIfEnabled(testDirectories);
445464
testRun.end();
465+
466+
// Open the Testing pane if there were failures and setting is configured to do so
467+
if (hasFailures && autoOpenSetting === 'openOnTestFailure') {
468+
await commands.executeCommand('workbench.view.extension.test');
469+
}
446470
return;
447471
}
448472

@@ -486,7 +510,7 @@ export class LogtalkTestsExplorerProvider implements Disposable {
486510
this.logger.debug(`Looking for results file: ${dirResultsFilePath}`);
487511
if (fs.existsSync(dirResultsFilePath)) {
488512
this.logger.debug(`Parsing results from: ${dirResultsFilePath}`);
489-
await this.parseTestResultFile(Uri.file(dirResultsFilePath), testRun, withCoverage);
513+
hasFailures = await this.parseTestResultFile(Uri.file(dirResultsFilePath), testRun, withCoverage) || hasFailures;
490514
} else {
491515
this.logger.warn(`Results file not found: ${dirResultsFilePath}`);
492516
}
@@ -500,7 +524,7 @@ export class LogtalkTestsExplorerProvider implements Disposable {
500524
// Parse results
501525
if (fs.existsSync(resultsFilePath)) {
502526
this.logger.debug(`Parsing results from: ${resultsFilePath}`);
503-
await this.parseTestResultFile(Uri.file(resultsFilePath), testRun, withCoverage);
527+
hasFailures = await this.parseTestResultFile(Uri.file(resultsFilePath), testRun, withCoverage) || hasFailures;
504528
}
505529
break;
506530

@@ -512,7 +536,7 @@ export class LogtalkTestsExplorerProvider implements Disposable {
512536
// Parse results
513537
if (fs.existsSync(resultsFilePath)) {
514538
this.logger.debug(`Parsing results from: ${resultsFilePath}`);
515-
await this.parseTestResultFile(Uri.file(resultsFilePath), testRun, withCoverage);
539+
hasFailures = await this.parseTestResultFile(Uri.file(resultsFilePath), testRun, withCoverage) || hasFailures;
516540
}
517541
break;
518542

@@ -524,7 +548,7 @@ export class LogtalkTestsExplorerProvider implements Disposable {
524548
// Parse results
525549
if (fs.existsSync(resultsFilePath)) {
526550
this.logger.debug(`Parsing results from: ${resultsFilePath}`);
527-
await this.parseTestResultFile(Uri.file(resultsFilePath), testRun, withCoverage);
551+
hasFailures = await this.parseTestResultFile(Uri.file(resultsFilePath), testRun, withCoverage) || hasFailures;
528552
}
529553
break;
530554
}
@@ -535,8 +559,17 @@ export class LogtalkTestsExplorerProvider implements Disposable {
535559

536560
this.runAllureReportIfEnabled(testDirectories);
537561
testRun.end();
562+
563+
// Open the Testing pane if there were failures and setting is configured to do so
564+
if (hasFailures && autoOpenSetting === 'openOnTestFailure') {
565+
await commands.executeCommand('workbench.view.extension.test');
566+
}
538567
} catch (error) {
539568
this.logger.error('Error in runTests:', error);
569+
// Open the Testing pane if there were failures and setting is configured to do so
570+
if (hasFailures && autoOpenSetting === 'openOnTestFailure') {
571+
await commands.executeCommand('workbench.view.extension.test');
572+
}
540573
this.runAllureReportIfEnabled(testDirectories);
541574
testRun.end();
542575
}
@@ -560,6 +593,16 @@ export class LogtalkTestsExplorerProvider implements Disposable {
560593
);
561594
this.logger.debug('Created test run for testers');
562595

596+
// Open the Testing pane if configured to do so
597+
const testingSettings = workspace.getConfiguration('testing');
598+
const autoOpenSetting = testingSettings.get<string>('automaticallyOpenTestResults', 'neverOpen');
599+
if (autoOpenSetting === 'openOnTestStart' || autoOpenSetting === 'openExplorerOnTestStart') {
600+
await commands.executeCommand('workbench.view.extension.test');
601+
}
602+
603+
// Track whether any tests failed for openOnTestFailure setting
604+
let hasFailures = false;
605+
563606
try {
564607
// Get the workspace folder to run testers in
565608
let workspaceDir: string | undefined;
@@ -580,13 +623,25 @@ export class LogtalkTestsExplorerProvider implements Disposable {
580623
this.testsReporter,
581624
async (dir: string) => {
582625
// After testers complete, parse xUnit XML files and update test explorer
583-
await this.parseXUnitReportsInDirectory(dir, testRun);
626+
const failures = await this.parseXUnitReportsInDirectory(dir, testRun);
627+
if (failures) {
628+
hasFailures = true;
629+
}
584630
}
585631
);
586632

587633
testRun.end();
634+
635+
// Open the Testing pane if there were failures and setting is configured to do so
636+
if (hasFailures && autoOpenSetting === 'openOnTestFailure') {
637+
await commands.executeCommand('workbench.view.extension.test');
638+
}
588639
} catch (error) {
589640
this.logger.error('Error in runTestsWithTesters:', error);
641+
// Open the Testing pane if there were failures and setting is configured to do so
642+
if (hasFailures && autoOpenSetting === 'openOnTestFailure') {
643+
await commands.executeCommand('workbench.view.extension.test');
644+
}
590645
testRun.end();
591646
}
592647
}
@@ -608,9 +663,21 @@ export class LogtalkTestsExplorerProvider implements Disposable {
608663
true // persist = true for "Rerun Last Run" functionality
609664
);
610665

666+
// Open the Testing pane if configured to do so
667+
const testingSettings = workspace.getConfiguration('testing');
668+
const autoOpenSetting = testingSettings.get<string>('automaticallyOpenTestResults', 'neverOpen');
669+
if (autoOpenSetting === 'openOnTestStart' || autoOpenSetting === 'openExplorerOnTestStart') {
670+
await commands.executeCommand('workbench.view.extension.test');
671+
}
672+
611673
try {
612-
await this.parseXUnitReportsInDirectory(dir, testRun);
674+
const hasFailures = await this.parseXUnitReportsInDirectory(dir, testRun);
613675
testRun.end();
676+
677+
// Open the Testing pane if there were failures and setting is configured to do so
678+
if (hasFailures && autoOpenSetting === 'openOnTestFailure') {
679+
await commands.executeCommand('workbench.view.extension.test');
680+
}
614681
} catch (error) {
615682
this.logger.error('Error updating from project testers:', error);
616683
testRun.end();
@@ -622,7 +689,7 @@ export class LogtalkTestsExplorerProvider implements Disposable {
622689
* @param dir - The directory to search for xunit_report.xml files
623690
* @param testRun - Optional test run to update with results
624691
*/
625-
private async parseXUnitReportsInDirectory(dir: string, testRun?: TestRun): Promise<void> {
692+
private async parseXUnitReportsInDirectory(dir: string, testRun?: TestRun): Promise<boolean> {
626693
this.logger.debug(`Parsing xUnit reports in directory: ${dir}`);
627694

628695
// Find all xunit_report.xml files recursively in the directory
@@ -631,19 +698,22 @@ export class LogtalkTestsExplorerProvider implements Disposable {
631698

632699
this.logger.debug(`Found ${files.length} xUnit report files`);
633700

701+
let hasFailures = false;
634702
for (const file of files) {
635-
await this.parseXUnitReportFile(file, testRun);
703+
hasFailures = await this.parseXUnitReportFile(file, testRun) || hasFailures;
636704
}
705+
return hasFailures;
637706
}
638707

639708
/**
640709
* Parse a single xUnit XML report file and create/update test items
641710
* @param uri - URI of the xunit_report.xml file
642711
* @param testRun - Optional test run to update with results
712+
* @returns true if there were any failed tests, false otherwise
643713
*/
644-
private async parseXUnitReportFile(uri: Uri, testRun?: TestRun): Promise<void> {
714+
private async parseXUnitReportFile(uri: Uri, testRun?: TestRun): Promise<boolean> {
645715
if (!fs.existsSync(uri.fsPath)) {
646-
return;
716+
return false;
647717
}
648718

649719
try {
@@ -655,7 +725,7 @@ export class LogtalkTestsExplorerProvider implements Disposable {
655725

656726
if (testResults.length === 0) {
657727
this.logger.debug('No test results found in xUnit report');
658-
return;
728+
return false;
659729
}
660730

661731
// Get the directory containing the xunit_report.xml file
@@ -675,9 +745,11 @@ export class LogtalkTestsExplorerProvider implements Disposable {
675745
this.logger.debug(`Wrote test results to: ${resultsFilePath}`);
676746

677747
// Now parse the results file to update the test explorer
678-
await this.parseTestResultFile(Uri.file(resultsFilePath), testRun, false);
748+
const failures = await this.parseTestResultFile(Uri.file(resultsFilePath), testRun, false);
749+
return failures;
679750
} catch (error) {
680751
this.logger.error(`Error parsing xUnit report ${uri.fsPath}:`, error);
752+
return false;
681753
}
682754
}
683755

@@ -833,7 +905,7 @@ export class LogtalkTestsExplorerProvider implements Disposable {
833905
* @param testRun - Optional test run to update with results. If not provided, a new test run will be created.
834906
* @param withCoverage - Whether to process and report coverage data (default: false)
835907
*/
836-
private async parseTestResultFile(uri: Uri, testRun?: TestRun, withCoverage: boolean = false): Promise<void> {
908+
private async parseTestResultFile(uri: Uri, testRun?: TestRun, withCoverage: boolean = false): Promise<boolean> {
837909
if (!fs.existsSync(uri.fsPath)) {
838910
return;
839911
}
@@ -942,8 +1014,13 @@ export class LogtalkTestsExplorerProvider implements Disposable {
9421014
await this.updateTestRunFromResults(testResults, testRun);
9431015
}
9441016
}
1017+
1018+
// Check if there were any failures
1019+
const hasFailures = testResults.some(result => result.status.toLowerCase().startsWith('failed'));
1020+
return hasFailures;
9451021
} catch (error) {
9461022
this.logger.error(`Error parsing test results file ${uri.fsPath}:`, error);
1023+
return false;
9471024
}
9481025
}
9491026

0 commit comments

Comments
 (0)