@git.zone/tstest 2.3.7 → 2.4.0

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.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@git.zone/tstest',
6
- version: '2.3.7',
6
+ version: '2.4.0',
7
7
  description: 'a test utility to run tests that match test/**/*.ts'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxrQkFBa0I7SUFDeEIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHFEQUFxRDtDQUNuRSxDQUFBIn0=
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Migration result for a single file
3
+ */
4
+ export interface MigrationResult {
5
+ /**
6
+ * Original file path
7
+ */
8
+ oldPath: string;
9
+ /**
10
+ * New file path after migration
11
+ */
12
+ newPath: string;
13
+ /**
14
+ * Whether the migration was performed
15
+ */
16
+ migrated: boolean;
17
+ /**
18
+ * Error message if migration failed
19
+ */
20
+ error?: string;
21
+ }
22
+ /**
23
+ * Migration summary
24
+ */
25
+ export interface MigrationSummary {
26
+ /**
27
+ * Total number of legacy files found
28
+ */
29
+ totalLegacyFiles: number;
30
+ /**
31
+ * Number of files successfully migrated
32
+ */
33
+ migratedCount: number;
34
+ /**
35
+ * Number of files that failed to migrate
36
+ */
37
+ errorCount: number;
38
+ /**
39
+ * Individual migration results
40
+ */
41
+ results: MigrationResult[];
42
+ /**
43
+ * Whether this was a dry run
44
+ */
45
+ dryRun: boolean;
46
+ }
47
+ /**
48
+ * Migration options
49
+ */
50
+ export interface MigrationOptions {
51
+ /**
52
+ * Base directory to search for test files
53
+ * Default: process.cwd()
54
+ */
55
+ baseDir?: string;
56
+ /**
57
+ * Glob pattern for finding test files
58
+ * Default: '** /*test*.ts' (without space)
59
+ */
60
+ pattern?: string;
61
+ /**
62
+ * Dry run mode - don't actually rename files
63
+ * Default: true
64
+ */
65
+ dryRun?: boolean;
66
+ /**
67
+ * Verbose output
68
+ * Default: false
69
+ */
70
+ verbose?: boolean;
71
+ }
72
+ /**
73
+ * Migration class for renaming legacy test files to new naming convention
74
+ *
75
+ * Migrations:
76
+ * - .browser.ts → .chromium.ts
77
+ * - .both.ts → .node+chromium.ts
78
+ * - .both.nonci.ts → .node+chromium.nonci.ts
79
+ * - .browser.nonci.ts → .chromium.nonci.ts
80
+ */
81
+ export declare class Migration {
82
+ private options;
83
+ constructor(options?: MigrationOptions);
84
+ /**
85
+ * Find all legacy test files in the base directory
86
+ */
87
+ findLegacyFiles(): Promise<string[]>;
88
+ /**
89
+ * Migrate a single file
90
+ */
91
+ private migrateFile;
92
+ /**
93
+ * Check if a directory is a git repository
94
+ */
95
+ private isGitRepository;
96
+ /**
97
+ * Run the migration
98
+ */
99
+ run(): Promise<MigrationSummary>;
100
+ /**
101
+ * Create a migration report without performing the migration
102
+ */
103
+ generateReport(): Promise<string>;
104
+ }
@@ -0,0 +1,200 @@
1
+ import * as plugins from './tstest.plugins.js';
2
+ import { coloredString as cs } from '@push.rocks/consolecolor';
3
+ import { parseTestFilename, getLegacyMigrationTarget, isLegacyFilename } from './tstest.classes.runtime.parser.js';
4
+ /**
5
+ * Migration class for renaming legacy test files to new naming convention
6
+ *
7
+ * Migrations:
8
+ * - .browser.ts → .chromium.ts
9
+ * - .both.ts → .node+chromium.ts
10
+ * - .both.nonci.ts → .node+chromium.nonci.ts
11
+ * - .browser.nonci.ts → .chromium.nonci.ts
12
+ */
13
+ export class Migration {
14
+ constructor(options = {}) {
15
+ this.options = {
16
+ baseDir: options.baseDir || process.cwd(),
17
+ pattern: options.pattern || '**/test*.ts',
18
+ dryRun: options.dryRun !== undefined ? options.dryRun : true,
19
+ verbose: options.verbose || false,
20
+ };
21
+ }
22
+ /**
23
+ * Find all legacy test files in the base directory
24
+ */
25
+ async findLegacyFiles() {
26
+ const files = await plugins.smartfile.fs.listFileTree(this.options.baseDir, this.options.pattern);
27
+ const legacyFiles = [];
28
+ for (const file of files) {
29
+ const fileName = plugins.path.basename(file);
30
+ if (isLegacyFilename(fileName)) {
31
+ const absolutePath = plugins.path.isAbsolute(file)
32
+ ? file
33
+ : plugins.path.join(this.options.baseDir, file);
34
+ legacyFiles.push(absolutePath);
35
+ }
36
+ }
37
+ return legacyFiles;
38
+ }
39
+ /**
40
+ * Migrate a single file
41
+ */
42
+ async migrateFile(filePath) {
43
+ const fileName = plugins.path.basename(filePath);
44
+ const dirName = plugins.path.dirname(filePath);
45
+ try {
46
+ // Get the new filename
47
+ const newFileName = getLegacyMigrationTarget(fileName);
48
+ if (!newFileName) {
49
+ return {
50
+ oldPath: filePath,
51
+ newPath: filePath,
52
+ migrated: false,
53
+ error: 'File is not a legacy file',
54
+ };
55
+ }
56
+ const newPath = plugins.path.join(dirName, newFileName);
57
+ // Check if target file already exists
58
+ if (await plugins.smartfile.fs.fileExists(newPath)) {
59
+ return {
60
+ oldPath: filePath,
61
+ newPath,
62
+ migrated: false,
63
+ error: `Target file already exists: ${newPath}`,
64
+ };
65
+ }
66
+ if (!this.options.dryRun) {
67
+ // Check if we're in a git repository
68
+ const isGitRepo = await this.isGitRepository(this.options.baseDir);
69
+ if (isGitRepo) {
70
+ // Use git mv to preserve history
71
+ const smartshell = new plugins.smartshell.Smartshell({
72
+ executor: 'bash',
73
+ pathDirectories: [],
74
+ });
75
+ const gitCommand = `cd "${this.options.baseDir}" && git mv "${filePath}" "${newPath}"`;
76
+ const result = await smartshell.exec(gitCommand);
77
+ if (result.exitCode !== 0) {
78
+ throw new Error(`git mv failed: ${result.stderr}`);
79
+ }
80
+ }
81
+ else {
82
+ // Not a git repository - cannot migrate without git
83
+ throw new Error('Migration requires a git repository. We have git!');
84
+ }
85
+ }
86
+ return {
87
+ oldPath: filePath,
88
+ newPath,
89
+ migrated: true,
90
+ };
91
+ }
92
+ catch (error) {
93
+ return {
94
+ oldPath: filePath,
95
+ newPath: filePath,
96
+ migrated: false,
97
+ error: error.message,
98
+ };
99
+ }
100
+ }
101
+ /**
102
+ * Check if a directory is a git repository
103
+ */
104
+ async isGitRepository(dir) {
105
+ try {
106
+ const gitDir = plugins.path.join(dir, '.git');
107
+ return await plugins.smartfile.fs.isDirectory(gitDir);
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ }
113
+ /**
114
+ * Run the migration
115
+ */
116
+ async run() {
117
+ const legacyFiles = await this.findLegacyFiles();
118
+ console.log('');
119
+ console.log(cs('='.repeat(60), 'blue'));
120
+ console.log(cs('Test File Migration Tool', 'blue'));
121
+ console.log(cs('='.repeat(60), 'blue'));
122
+ console.log('');
123
+ if (this.options.dryRun) {
124
+ console.log(cs('🔍 DRY RUN MODE - No files will be modified', 'orange'));
125
+ console.log('');
126
+ }
127
+ console.log(`Found ${legacyFiles.length} legacy test file(s)`);
128
+ console.log('');
129
+ const results = [];
130
+ let migratedCount = 0;
131
+ let errorCount = 0;
132
+ for (const file of legacyFiles) {
133
+ const result = await this.migrateFile(file);
134
+ results.push(result);
135
+ if (result.migrated) {
136
+ migratedCount++;
137
+ const oldName = plugins.path.basename(result.oldPath);
138
+ const newName = plugins.path.basename(result.newPath);
139
+ if (this.options.dryRun) {
140
+ console.log(cs(` Would migrate:`, 'cyan'));
141
+ }
142
+ else {
143
+ console.log(cs(` ✓ Migrated:`, 'green'));
144
+ }
145
+ console.log(` ${oldName}`);
146
+ console.log(cs(` → ${newName}`, 'green'));
147
+ console.log('');
148
+ }
149
+ else if (result.error) {
150
+ errorCount++;
151
+ console.log(cs(` ✗ Failed: ${plugins.path.basename(result.oldPath)}`, 'red'));
152
+ console.log(cs(` ${result.error}`, 'red'));
153
+ console.log('');
154
+ }
155
+ }
156
+ console.log(cs('='.repeat(60), 'blue'));
157
+ console.log(`Summary:`);
158
+ console.log(` Total legacy files: ${legacyFiles.length}`);
159
+ console.log(` Successfully migrated: ${migratedCount}`);
160
+ console.log(` Errors: ${errorCount}`);
161
+ console.log(cs('='.repeat(60), 'blue'));
162
+ if (this.options.dryRun && legacyFiles.length > 0) {
163
+ console.log('');
164
+ console.log(cs('To apply these changes, run:', 'orange'));
165
+ console.log(cs(' tstest migrate --write', 'orange'));
166
+ }
167
+ console.log('');
168
+ return {
169
+ totalLegacyFiles: legacyFiles.length,
170
+ migratedCount,
171
+ errorCount,
172
+ results,
173
+ dryRun: this.options.dryRun,
174
+ };
175
+ }
176
+ /**
177
+ * Create a migration report without performing the migration
178
+ */
179
+ async generateReport() {
180
+ const legacyFiles = await this.findLegacyFiles();
181
+ let report = '';
182
+ report += 'Test File Migration Report\n';
183
+ report += '='.repeat(60) + '\n';
184
+ report += '\n';
185
+ report += `Found ${legacyFiles.length} legacy test file(s)\n`;
186
+ report += '\n';
187
+ for (const file of legacyFiles) {
188
+ const fileName = plugins.path.basename(file);
189
+ const newFileName = getLegacyMigrationTarget(fileName);
190
+ if (newFileName) {
191
+ report += `${fileName}\n`;
192
+ report += ` → ${newFileName}\n`;
193
+ report += '\n';
194
+ }
195
+ }
196
+ report += '='.repeat(60) + '\n';
197
+ return report;
198
+ }
199
+ }
200
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN0ZXN0LmNsYXNzZXMubWlncmF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvdHN0ZXN0LmNsYXNzZXMubWlncmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGFBQWEsSUFBSSxFQUFFLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsd0JBQXdCLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQXNGbkg7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLE9BQU8sU0FBUztJQUdwQixZQUFZLFVBQTRCLEVBQUU7UUFDeEMsSUFBSSxDQUFDLE9BQU8sR0FBRztZQUNiLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUU7WUFDekMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPLElBQUksYUFBYTtZQUN6QyxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU0sS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUk7WUFDNUQsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPLElBQUksS0FBSztTQUNsQyxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLGVBQWU7UUFDbkIsTUFBTSxLQUFLLEdBQUcsTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQ25ELElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUNwQixJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FDckIsQ0FBQztRQUVGLE1BQU0sV0FBVyxHQUFhLEVBQUUsQ0FBQztRQUVqQyxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ3pCLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxJ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
@@ -0,0 +1,172 @@
1
+ import type { Runtime } from './tstest.classes.runtime.parser.js';
2
+ import { TapParser } from './tstest.classes.tap.parser.js';
3
+ /**
4
+ * Runtime-specific configuration options
5
+ */
6
+ export interface RuntimeOptions {
7
+ /**
8
+ * Environment variables to pass to the runtime
9
+ */
10
+ env?: Record<string, string>;
11
+ /**
12
+ * Additional command-line arguments
13
+ */
14
+ extraArgs?: string[];
15
+ /**
16
+ * Working directory for test execution
17
+ */
18
+ cwd?: string;
19
+ /**
20
+ * Timeout in milliseconds (0 = no timeout)
21
+ */
22
+ timeout?: number;
23
+ }
24
+ /**
25
+ * Deno-specific configuration options
26
+ */
27
+ export interface DenoOptions extends RuntimeOptions {
28
+ /**
29
+ * Permissions to grant to Deno
30
+ * Default: ['--allow-read', '--allow-env']
31
+ */
32
+ permissions?: string[];
33
+ /**
34
+ * Path to deno.json config file
35
+ */
36
+ configPath?: string;
37
+ /**
38
+ * Path to import map file
39
+ */
40
+ importMap?: string;
41
+ }
42
+ /**
43
+ * Chromium-specific configuration options
44
+ */
45
+ export interface ChromiumOptions extends RuntimeOptions {
46
+ /**
47
+ * Chromium launch arguments
48
+ */
49
+ launchArgs?: string[];
50
+ /**
51
+ * Headless mode (default: true)
52
+ */
53
+ headless?: boolean;
54
+ /**
55
+ * Port range for HTTP server
56
+ */
57
+ portRange?: {
58
+ min: number;
59
+ max: number;
60
+ };
61
+ }
62
+ /**
63
+ * Command configuration returned by createCommand()
64
+ */
65
+ export interface RuntimeCommand {
66
+ /**
67
+ * The main command executable (e.g., 'node', 'deno', 'bun')
68
+ */
69
+ command: string;
70
+ /**
71
+ * Command-line arguments
72
+ */
73
+ args: string[];
74
+ /**
75
+ * Environment variables
76
+ */
77
+ env?: Record<string, string>;
78
+ /**
79
+ * Working directory
80
+ */
81
+ cwd?: string;
82
+ }
83
+ /**
84
+ * Runtime availability check result
85
+ */
86
+ export interface RuntimeAvailability {
87
+ /**
88
+ * Whether the runtime is available
89
+ */
90
+ available: boolean;
91
+ /**
92
+ * Version string if available
93
+ */
94
+ version?: string;
95
+ /**
96
+ * Error message if not available
97
+ */
98
+ error?: string;
99
+ }
100
+ /**
101
+ * Abstract base class for runtime adapters
102
+ * Each runtime (Node, Chromium, Deno, Bun) implements this interface
103
+ */
104
+ export declare abstract class RuntimeAdapter {
105
+ /**
106
+ * Runtime identifier
107
+ */
108
+ abstract readonly id: Runtime;
109
+ /**
110
+ * Human-readable display name
111
+ */
112
+ abstract readonly displayName: string;
113
+ /**
114
+ * Check if this runtime is available on the system
115
+ * @returns Availability information including version
116
+ */
117
+ abstract checkAvailable(): Promise<RuntimeAvailability>;
118
+ /**
119
+ * Create the command configuration for executing a test
120
+ * @param testFile - Absolute path to the test file
121
+ * @param options - Runtime-specific options
122
+ * @returns Command configuration
123
+ */
124
+ abstract createCommand(testFile: string, options?: RuntimeOptions): RuntimeCommand;
125
+ /**
126
+ * Execute a test file and return a TAP parser
127
+ * @param testFile - Absolute path to the test file
128
+ * @param index - Test index (for display)
129
+ * @param total - Total number of tests (for display)
130
+ * @param options - Runtime-specific options
131
+ * @returns TAP parser with test results
132
+ */
133
+ abstract run(testFile: string, index: number, total: number, options?: RuntimeOptions): Promise<TapParser>;
134
+ /**
135
+ * Get the default options for this runtime
136
+ * Can be overridden by subclasses
137
+ */
138
+ protected getDefaultOptions(): RuntimeOptions;
139
+ /**
140
+ * Merge user options with defaults
141
+ */
142
+ protected mergeOptions<T extends RuntimeOptions>(userOptions?: T): T;
143
+ }
144
+ /**
145
+ * Registry for runtime adapters
146
+ * Manages all available runtime implementations
147
+ */
148
+ export declare class RuntimeAdapterRegistry {
149
+ private adapters;
150
+ /**
151
+ * Register a runtime adapter
152
+ */
153
+ register(adapter: RuntimeAdapter): void;
154
+ /**
155
+ * Get an adapter by runtime ID
156
+ */
157
+ get(runtime: Runtime): RuntimeAdapter | undefined;
158
+ /**
159
+ * Get all registered adapters
160
+ */
161
+ getAll(): RuntimeAdapter[];
162
+ /**
163
+ * Check which runtimes are available on the system
164
+ */
165
+ checkAvailability(): Promise<Map<Runtime, RuntimeAvailability>>;
166
+ /**
167
+ * Get adapters for a list of runtimes, in order
168
+ * @param runtimes - Ordered list of runtimes
169
+ * @returns Adapters in the same order, skipping any that aren't registered
170
+ */
171
+ getAdaptersForRuntimes(runtimes: Runtime[]): RuntimeAdapter[];
172
+ }
@@ -0,0 +1,85 @@
1
+ import * as plugins from './tstest.plugins.js';
2
+ import { TapParser } from './tstest.classes.tap.parser.js';
3
+ /**
4
+ * Abstract base class for runtime adapters
5
+ * Each runtime (Node, Chromium, Deno, Bun) implements this interface
6
+ */
7
+ export class RuntimeAdapter {
8
+ /**
9
+ * Get the default options for this runtime
10
+ * Can be overridden by subclasses
11
+ */
12
+ getDefaultOptions() {
13
+ return {
14
+ timeout: 0,
15
+ extraArgs: [],
16
+ env: {},
17
+ };
18
+ }
19
+ /**
20
+ * Merge user options with defaults
21
+ */
22
+ mergeOptions(userOptions) {
23
+ const defaults = this.getDefaultOptions();
24
+ return {
25
+ ...defaults,
26
+ ...userOptions,
27
+ env: { ...defaults.env, ...userOptions?.env },
28
+ extraArgs: [...(defaults.extraArgs || []), ...(userOptions?.extraArgs || [])],
29
+ };
30
+ }
31
+ }
32
+ /**
33
+ * Registry for runtime adapters
34
+ * Manages all available runtime implementations
35
+ */
36
+ export class RuntimeAdapterRegistry {
37
+ constructor() {
38
+ this.adapters = new Map();
39
+ }
40
+ /**
41
+ * Register a runtime adapter
42
+ */
43
+ register(adapter) {
44
+ this.adapters.set(adapter.id, adapter);
45
+ }
46
+ /**
47
+ * Get an adapter by runtime ID
48
+ */
49
+ get(runtime) {
50
+ return this.adapters.get(runtime);
51
+ }
52
+ /**
53
+ * Get all registered adapters
54
+ */
55
+ getAll() {
56
+ return Array.from(this.adapters.values());
57
+ }
58
+ /**
59
+ * Check which runtimes are available on the system
60
+ */
61
+ async checkAvailability() {
62
+ const results = new Map();
63
+ for (const [runtime, adapter] of this.adapters) {
64
+ const availability = await adapter.checkAvailable();
65
+ results.set(runtime, availability);
66
+ }
67
+ return results;
68
+ }
69
+ /**
70
+ * Get adapters for a list of runtimes, in order
71
+ * @param runtimes - Ordered list of runtimes
72
+ * @returns Adapters in the same order, skipping any that aren't registered
73
+ */
74
+ getAdaptersForRuntimes(runtimes) {
75
+ const adapters = [];
76
+ for (const runtime of runtimes) {
77
+ const adapter = this.get(runtime);
78
+ if (adapter) {
79
+ adapters.push(adapter);
80
+ }
81
+ }
82
+ return adapters;
83
+ }
84
+ }
85
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN0ZXN0LmNsYXNzZXMucnVudGltZS5hZGFwdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvdHN0ZXN0LmNsYXNzZXMucnVudGltZS5hZGFwdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFFL0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBaUgzRDs7O0dBR0c7QUFDSCxNQUFNLE9BQWdCLGNBQWM7SUF3Q2xDOzs7T0FHRztJQUNPLGlCQUFpQjtRQUN6QixPQUFPO1lBQ0wsT0FBTyxFQUFFLENBQUM7WUFDVixTQUFTLEVBQUUsRUFBRTtZQUNiLEdBQUcsRUFBRSxFQUFFO1NBQ1IsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNPLFlBQVksQ0FBMkIsV0FBZTtRQUM5RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUMxQyxPQUFPO1lBQ0wsR0FBRyxRQUFRO1lBQ1gsR0FBRyxXQUFXO1lBQ2QsR0FBRyxFQUFFLEVBQUUsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLEdBQUcsV0FBVyxFQUFFLEdBQUcsRUFBRTtZQUM3QyxTQUFTLEVBQUUsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUMsRUFBRSxHQUFHLENBQUMsV0FBVyxFQUFFLFNBQVMsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUN6RSxDQUFDO0lBQ1QsQ0FBQztDQUNGO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLHNCQUFzQjtJQUFuQztRQUNVLGFBQVEsR0FBaUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQXNEN0QsQ0FBQztJQXBEQzs7T0FFRztJQUNILFFBQVEsQ0FBQyxPQUF1QjtRQUM5QixJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFRDs7T0FFRztJQUNILEdBQUcsQ0FBQyxPQUFnQjtRQUNsQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU07UUFDSixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxpQkFBaUI7UUFDckIsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQWdDLENBQUM7UUFFeEQsS0FBSyxNQUFNLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUMvQyxNQUFNLFlBQVksR0FBRyxNQUFNLE9BQU8sQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUNwRCxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxZQUFZLENBQUMsQ0FBQztRQUNyQyxDQUFDO1FBRUQsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxzQkFBc0IsQ0FBQyxRQUFtQjtRQUN4QyxNQUFNLFFBQVEsR0FBcUIsRUFBRSxDQUFDO1FBRXRDLEtBQUssTUFBTSxPQUFPLElBQUksUUFBUSxFQUFFLENBQUM7WUFDL0IsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNsQyxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNaLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDekIsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0NBQ0YifQ==
@@ -0,0 +1,30 @@
1
+ import { RuntimeAdapter, type RuntimeOptions, type RuntimeCommand, type RuntimeAvailability } from './tstest.classes.runtime.adapter.js';
2
+ import { TapParser } from './tstest.classes.tap.parser.js';
3
+ import { TsTestLogger } from './tstest.logging.js';
4
+ import type { Runtime } from './tstest.classes.runtime.parser.js';
5
+ /**
6
+ * Bun runtime adapter
7
+ * Executes tests using the Bun runtime with native TypeScript support
8
+ */
9
+ export declare class BunRuntimeAdapter extends RuntimeAdapter {
10
+ private logger;
11
+ private smartshellInstance;
12
+ private timeoutSeconds;
13
+ private filterTags;
14
+ readonly id: Runtime;
15
+ readonly displayName: string;
16
+ constructor(logger: TsTestLogger, smartshellInstance: any, // SmartShell instance from @push.rocks/smartshell
17
+ timeoutSeconds: number | null, filterTags: string[]);
18
+ /**
19
+ * Check if Bun is available
20
+ */
21
+ checkAvailable(): Promise<RuntimeAvailability>;
22
+ /**
23
+ * Create command configuration for Bun test execution
24
+ */
25
+ createCommand(testFile: string, options?: RuntimeOptions): RuntimeCommand;
26
+ /**
27
+ * Execute a test file in Bun
28
+ */
29
+ run(testFile: string, index: number, total: number, options?: RuntimeOptions): Promise<TapParser>;
30
+ }