@testsmith/testblocks 0.8.3 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +126 -64
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -177,7 +177,7 @@ program
|
|
|
177
177
|
.argument('<patterns...>', 'Test file patterns (glob supported)')
|
|
178
178
|
.option('-H, --headed', 'Run tests in headed mode (show browser)', false)
|
|
179
179
|
.option('-t, --timeout <ms>', 'Test timeout in milliseconds', '30000')
|
|
180
|
-
.option('-r, --reporter <
|
|
180
|
+
.option('-r, --reporter <types>', 'Reporter types (comma-separated): console, json, junit, html', 'console')
|
|
181
181
|
.option('-o, --output <dir>', 'Output directory for reports', './testblocks-results')
|
|
182
182
|
.option('-b, --base-url <url>', 'Base URL for relative URLs')
|
|
183
183
|
.option('-v, --var <vars...>', 'Variables in key=value format')
|
|
@@ -275,57 +275,65 @@ program
|
|
|
275
275
|
variables,
|
|
276
276
|
procedures: globalProcedures,
|
|
277
277
|
};
|
|
278
|
-
// Create
|
|
279
|
-
const
|
|
278
|
+
// Create reporters (supports multiple, comma-separated)
|
|
279
|
+
const reporters = createReporters(options.reporter, options.output);
|
|
280
280
|
// Run tests
|
|
281
281
|
const allResults = [];
|
|
282
282
|
let hasFailures = false;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
283
|
+
try {
|
|
284
|
+
for (const file of files) {
|
|
285
|
+
// Skip _hooks.testblocks.json files - these are folder hooks, not test files
|
|
286
|
+
const basename = path.basename(file);
|
|
287
|
+
if (basename === '_hooks.testblocks.json') {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
console.log(`Running: ${basename}`);
|
|
291
|
+
const content = fs.readFileSync(file, 'utf-8');
|
|
292
|
+
let testFile = JSON.parse(content);
|
|
293
|
+
// Skip files that have no tests array (e.g., hooks-only files)
|
|
294
|
+
if (!testFile.tests || !Array.isArray(testFile.tests)) {
|
|
295
|
+
console.log(' (no tests in file)\n');
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
// Load and merge folder hooks
|
|
299
|
+
const globalsDir = fs.existsSync(globalsPath) ? path.dirname(globalsPath) : null;
|
|
300
|
+
const folderHooks = loadFolderHooks(file, globalsDir);
|
|
301
|
+
if (folderHooks.length > 0) {
|
|
302
|
+
testFile = mergeFolderHooksIntoTestFile(testFile, folderHooks);
|
|
303
|
+
}
|
|
304
|
+
// Apply filter if specified
|
|
305
|
+
if (options.filter) {
|
|
306
|
+
const filterRegex = new RegExp(options.filter, 'i');
|
|
307
|
+
testFile.tests = testFile.tests.filter(t => filterRegex.test(t.name));
|
|
308
|
+
}
|
|
309
|
+
if (testFile.tests.length === 0) {
|
|
310
|
+
console.log(' (no tests match filter)\n');
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
const executor = new executor_1.TestExecutor(executorOptions);
|
|
314
|
+
const results = await executor.runTestFile(testFile);
|
|
315
|
+
allResults.push({ file, results });
|
|
316
|
+
// Report results to all reporters
|
|
317
|
+
reporters.forEach(r => r.onTestFileComplete(file, testFile, results));
|
|
318
|
+
// Check for failures
|
|
319
|
+
const failed = results.some(r => r.status !== 'passed');
|
|
320
|
+
if (failed) {
|
|
321
|
+
hasFailures = true;
|
|
322
|
+
if (options.failFast) {
|
|
323
|
+
console.log('\nStopping due to --fail-fast\n');
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
324
326
|
}
|
|
325
327
|
}
|
|
326
328
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
+
catch (error) {
|
|
330
|
+
console.error('Error during test execution:', error.message);
|
|
331
|
+
hasFailures = true;
|
|
332
|
+
}
|
|
333
|
+
finally {
|
|
334
|
+
// Always generate final reports, even on errors
|
|
335
|
+
reporters.forEach(r => r.onComplete(allResults));
|
|
336
|
+
}
|
|
329
337
|
// Exit with appropriate code
|
|
330
338
|
process.exit(hasFailures ? 1 : 0);
|
|
331
339
|
}
|
|
@@ -432,9 +440,10 @@ program
|
|
|
432
440
|
'test:headed': 'testblocks run tests/**/*.testblocks.json --headed',
|
|
433
441
|
'test:html': 'testblocks run tests/**/*.testblocks.json -r html -o reports',
|
|
434
442
|
'test:junit': 'testblocks run tests/**/*.testblocks.json -r junit -o reports',
|
|
443
|
+
'test:ci': 'testblocks run tests/**/*.testblocks.json -r console,html,junit -o reports',
|
|
435
444
|
},
|
|
436
445
|
devDependencies: {
|
|
437
|
-
'@testsmith/testblocks': '^0.8.
|
|
446
|
+
'@testsmith/testblocks': '^0.8.5',
|
|
438
447
|
},
|
|
439
448
|
};
|
|
440
449
|
fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2));
|
|
@@ -574,18 +583,34 @@ jobs:
|
|
|
574
583
|
run: npm ci
|
|
575
584
|
|
|
576
585
|
- name: Install Playwright browsers
|
|
577
|
-
run: npx
|
|
586
|
+
run: npx testblocks install-browsers
|
|
578
587
|
|
|
579
588
|
- name: Run tests
|
|
580
|
-
run: npm test
|
|
589
|
+
run: npm run test:ci
|
|
590
|
+
|
|
591
|
+
- name: Upload HTML report
|
|
592
|
+
uses: actions/upload-artifact@v4
|
|
593
|
+
if: always()
|
|
594
|
+
with:
|
|
595
|
+
name: html-report
|
|
596
|
+
path: reports/*.html
|
|
597
|
+
retention-days: 30
|
|
581
598
|
|
|
582
|
-
- name: Upload
|
|
599
|
+
- name: Upload JUnit report
|
|
583
600
|
uses: actions/upload-artifact@v4
|
|
584
601
|
if: always()
|
|
585
602
|
with:
|
|
586
|
-
name:
|
|
587
|
-
path: reports
|
|
603
|
+
name: junit-report
|
|
604
|
+
path: reports/*.xml
|
|
588
605
|
retention-days: 30
|
|
606
|
+
|
|
607
|
+
- name: Publish Test Results
|
|
608
|
+
uses: dorny/test-reporter@v1
|
|
609
|
+
if: always()
|
|
610
|
+
with:
|
|
611
|
+
name: Test Results
|
|
612
|
+
path: reports/*.xml
|
|
613
|
+
reporter: java-junit
|
|
589
614
|
`;
|
|
590
615
|
fs.writeFileSync(workflowPath, workflow);
|
|
591
616
|
console.log(' Created: .github/workflows/testblocks.yml');
|
|
@@ -594,10 +619,30 @@ jobs:
|
|
|
594
619
|
console.log('Next steps:');
|
|
595
620
|
console.log(' 1. cd ' + (directory === '.' ? '' : directory));
|
|
596
621
|
console.log(' 2. npm install');
|
|
597
|
-
console.log(' 3.
|
|
622
|
+
console.log(' 3. npx testblocks install-browsers');
|
|
623
|
+
console.log(' 4. npm test\n');
|
|
598
624
|
console.log('To open the visual test editor:');
|
|
599
625
|
console.log(' testblocks serve\n');
|
|
600
626
|
});
|
|
627
|
+
program
|
|
628
|
+
.command('install-browsers')
|
|
629
|
+
.description('Install Playwright browsers for running web tests')
|
|
630
|
+
.option('--browser <browser>', 'Browser to install (chromium, firefox, webkit, all)', 'chromium')
|
|
631
|
+
.action(async (options) => {
|
|
632
|
+
const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
633
|
+
const browser = options.browser === 'all' ? '' : options.browser;
|
|
634
|
+
console.log(`Installing Playwright browser${browser ? `: ${browser}` : 's'}...`);
|
|
635
|
+
try {
|
|
636
|
+
// Use execSync to run playwright install with inherited stdio
|
|
637
|
+
const command = `npx playwright install${browser ? ` ${browser}` : ''} --with-deps`;
|
|
638
|
+
execSync(command, { stdio: 'inherit' });
|
|
639
|
+
console.log('\n✓ Browsers installed successfully!');
|
|
640
|
+
}
|
|
641
|
+
catch (error) {
|
|
642
|
+
console.error('\nFailed to install browsers:', error instanceof Error ? error.message : error);
|
|
643
|
+
process.exit(1);
|
|
644
|
+
}
|
|
645
|
+
});
|
|
601
646
|
program
|
|
602
647
|
.command('list')
|
|
603
648
|
.description('List tests in test files')
|
|
@@ -655,18 +700,35 @@ program
|
|
|
655
700
|
open: options.open,
|
|
656
701
|
});
|
|
657
702
|
});
|
|
658
|
-
function
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
703
|
+
function createReporters(types, outputDir) {
|
|
704
|
+
const reporterTypes = types.split(',').map(t => t.trim().toLowerCase());
|
|
705
|
+
const reporters = [];
|
|
706
|
+
for (const type of reporterTypes) {
|
|
707
|
+
switch (type) {
|
|
708
|
+
case 'json':
|
|
709
|
+
reporters.push(new reporters_1.JSONReporter(outputDir));
|
|
710
|
+
break;
|
|
711
|
+
case 'junit':
|
|
712
|
+
reporters.push(new reporters_1.JUnitReporter(outputDir));
|
|
713
|
+
break;
|
|
714
|
+
case 'html':
|
|
715
|
+
reporters.push(new reporters_1.HTMLReporter(outputDir));
|
|
716
|
+
break;
|
|
717
|
+
case 'console':
|
|
718
|
+
reporters.push(new reporters_1.ConsoleReporter());
|
|
719
|
+
break;
|
|
720
|
+
default:
|
|
721
|
+
console.warn(`Unknown reporter type: ${type}, using console`);
|
|
722
|
+
if (!reporters.some(r => r instanceof reporters_1.ConsoleReporter)) {
|
|
723
|
+
reporters.push(new reporters_1.ConsoleReporter());
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
// Always include console reporter if not already included
|
|
728
|
+
if (!reporters.some(r => r instanceof reporters_1.ConsoleReporter)) {
|
|
729
|
+
reporters.unshift(new reporters_1.ConsoleReporter());
|
|
669
730
|
}
|
|
731
|
+
return reporters;
|
|
670
732
|
}
|
|
671
733
|
function validateTestFile(testFile) {
|
|
672
734
|
const errors = [];
|