@git.zone/tstest 2.6.1 → 2.7.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.6.1',
6
+ version: '2.7.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,42 @@
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
+ * Docker runtime adapter
7
+ * Executes shell test files inside Docker containers
8
+ * Pattern: test.{variant}.docker.sh
9
+ * Variants map to Dockerfiles: latest -> Dockerfile, others -> Dockerfile_{variant}
10
+ */
11
+ export declare class DockerRuntimeAdapter extends RuntimeAdapter {
12
+ private logger;
13
+ private smartshellInstance;
14
+ private timeoutSeconds;
15
+ private cwd;
16
+ readonly id: Runtime;
17
+ readonly displayName: string;
18
+ private builtImages;
19
+ constructor(logger: TsTestLogger, smartshellInstance: any, // SmartShell instance from @push.rocks/smartshell
20
+ timeoutSeconds: number | null, cwd: string);
21
+ /**
22
+ * Check if Docker CLI is available
23
+ */
24
+ checkAvailable(): Promise<RuntimeAvailability>;
25
+ /**
26
+ * Create command configuration for Docker test execution
27
+ * This is used for informational purposes
28
+ */
29
+ createCommand(testFile: string, options?: RuntimeOptions): RuntimeCommand;
30
+ /**
31
+ * Build a Docker image from the specified Dockerfile
32
+ */
33
+ private buildDockerImage;
34
+ /**
35
+ * Execute a Docker test file
36
+ */
37
+ run(testFile: string, index: number, total: number, options?: RuntimeOptions): Promise<TapParser>;
38
+ /**
39
+ * Clean up built Docker images (optional, can be called at end of test suite)
40
+ */
41
+ cleanup(): Promise<void>;
42
+ }
@@ -0,0 +1,199 @@
1
+ import * as plugins from './tstest.plugins.js';
2
+ import { coloredString as cs } from '@push.rocks/consolecolor';
3
+ import { RuntimeAdapter, } from './tstest.classes.runtime.adapter.js';
4
+ import { TapParser } from './tstest.classes.tap.parser.js';
5
+ import { TsTestLogger } from './tstest.logging.js';
6
+ import { parseDockerTestFilename, mapVariantToDockerfile, isDockerTestFile } from './tstest.classes.runtime.parser.js';
7
+ /**
8
+ * Docker runtime adapter
9
+ * Executes shell test files inside Docker containers
10
+ * Pattern: test.{variant}.docker.sh
11
+ * Variants map to Dockerfiles: latest -> Dockerfile, others -> Dockerfile_{variant}
12
+ */
13
+ export class DockerRuntimeAdapter extends RuntimeAdapter {
14
+ constructor(logger, smartshellInstance, // SmartShell instance from @push.rocks/smartshell
15
+ timeoutSeconds, cwd) {
16
+ super();
17
+ this.logger = logger;
18
+ this.smartshellInstance = smartshellInstance;
19
+ this.timeoutSeconds = timeoutSeconds;
20
+ this.cwd = cwd;
21
+ this.id = 'node'; // Using 'node' temporarily as Runtime type doesn't include 'docker'
22
+ this.displayName = 'Docker';
23
+ this.builtImages = new Set(); // Track built images to avoid rebuilding
24
+ }
25
+ /**
26
+ * Check if Docker CLI is available
27
+ */
28
+ async checkAvailable() {
29
+ try {
30
+ const result = await this.smartshellInstance.exec('docker --version');
31
+ if (result.exitCode !== 0) {
32
+ return {
33
+ available: false,
34
+ error: 'Docker command failed',
35
+ };
36
+ }
37
+ // Extract version from output like "Docker version 24.0.5, build ced0996"
38
+ const versionMatch = result.stdout.match(/Docker version ([^,]+)/);
39
+ const version = versionMatch ? versionMatch[1] : 'unknown';
40
+ return {
41
+ available: true,
42
+ version,
43
+ };
44
+ }
45
+ catch (error) {
46
+ return {
47
+ available: false,
48
+ error: `Docker not found: ${error.message}`,
49
+ };
50
+ }
51
+ }
52
+ /**
53
+ * Create command configuration for Docker test execution
54
+ * This is used for informational purposes
55
+ */
56
+ createCommand(testFile, options) {
57
+ const parsed = parseDockerTestFilename(testFile);
58
+ const dockerfilePath = mapVariantToDockerfile(parsed.variant, this.cwd);
59
+ const imageName = `tstest-${parsed.variant}`;
60
+ return {
61
+ command: 'docker',
62
+ args: [
63
+ 'run',
64
+ '--rm',
65
+ '-v',
66
+ `${this.cwd}/test:/test`,
67
+ imageName,
68
+ 'taprun',
69
+ `/test/${plugins.path.basename(testFile)}`
70
+ ],
71
+ env: {},
72
+ cwd: this.cwd,
73
+ };
74
+ }
75
+ /**
76
+ * Build a Docker image from the specified Dockerfile
77
+ */
78
+ async buildDockerImage(dockerfilePath, imageName) {
79
+ // Check if image is already built
80
+ if (this.builtImages.has(imageName)) {
81
+ this.logger.tapOutput(`Using cached Docker image: ${imageName}`);
82
+ return;
83
+ }
84
+ // Check if Dockerfile exists
85
+ if (!await plugins.smartfile.fs.fileExists(dockerfilePath)) {
86
+ throw new Error(`Dockerfile not found: ${dockerfilePath}\n` +
87
+ `Expected Dockerfile for Docker test variant.`);
88
+ }
89
+ this.logger.tapOutput(`Building Docker image: ${imageName} from ${dockerfilePath}`);
90
+ try {
91
+ const buildResult = await this.smartshellInstance.exec(`docker build -f ${dockerfilePath} -t ${imageName} ${this.cwd}`, {
92
+ cwd: this.cwd,
93
+ });
94
+ if (buildResult.exitCode !== 0) {
95
+ throw new Error(`Docker build failed:\n${buildResult.stderr}`);
96
+ }
97
+ this.builtImages.add(imageName);
98
+ this.logger.tapOutput(`✅ Docker image built successfully: ${imageName}`);
99
+ }
100
+ catch (error) {
101
+ throw new Error(`Failed to build Docker image: ${error.message}`);
102
+ }
103
+ }
104
+ /**
105
+ * Execute a Docker test file
106
+ */
107
+ async run(testFile, index, total, options) {
108
+ this.logger.testFileStart(testFile, this.displayName, index, total);
109
+ // Parse the Docker test filename
110
+ const parsed = parseDockerTestFilename(testFile);
111
+ const dockerfilePath = mapVariantToDockerfile(parsed.variant, this.cwd);
112
+ const imageName = `tstest-${parsed.variant}`;
113
+ // Build the Docker image
114
+ await this.buildDockerImage(dockerfilePath, imageName);
115
+ // Prepare the test file path relative to the mounted directory
116
+ // We need to get the path relative to cwd
117
+ const absoluteTestPath = plugins.path.isAbsolute(testFile)
118
+ ? testFile
119
+ : plugins.path.join(this.cwd, testFile);
120
+ const relativeTestPath = plugins.path.relative(this.cwd, absoluteTestPath);
121
+ // Create TAP parser
122
+ const tapParser = new TapParser(testFile + ':docker', this.logger);
123
+ try {
124
+ // Build docker run command
125
+ const dockerArgs = [
126
+ 'run',
127
+ '--rm',
128
+ '-v',
129
+ `${this.cwd}/test:/test`,
130
+ imageName,
131
+ 'taprun',
132
+ `/test/${plugins.path.basename(testFile)}`
133
+ ];
134
+ this.logger.tapOutput(`Executing: docker ${dockerArgs.join(' ')}`);
135
+ // Execute the Docker container
136
+ const execPromise = this.smartshellInstance.execStreaming(`docker ${dockerArgs.join(' ')}`, {
137
+ cwd: this.cwd,
138
+ });
139
+ // Set up timeout if configured
140
+ let timeoutHandle = null;
141
+ if (this.timeoutSeconds) {
142
+ timeoutHandle = setTimeout(() => {
143
+ this.logger.tapOutput(`⏱️ Test timeout (${this.timeoutSeconds}s) - killing container`);
144
+ // Try to kill any running containers with this image
145
+ this.smartshellInstance.exec(`docker ps -q --filter ancestor=${imageName} | xargs -r docker kill`);
146
+ }, this.timeoutSeconds * 1000);
147
+ }
148
+ // Stream output to TAP parser line by line
149
+ execPromise.childProcess.stdout.on('data', (data) => {
150
+ const output = data.toString();
151
+ const lines = output.split('\n');
152
+ for (const line of lines) {
153
+ if (line.trim()) {
154
+ tapParser.handleTapLog(line);
155
+ }
156
+ }
157
+ });
158
+ execPromise.childProcess.stderr.on('data', (data) => {
159
+ const output = data.toString();
160
+ this.logger.tapOutput(cs(`[stderr] ${output}`, 'orange'));
161
+ });
162
+ // Wait for completion
163
+ const result = await execPromise;
164
+ // Clear timeout
165
+ if (timeoutHandle) {
166
+ clearTimeout(timeoutHandle);
167
+ }
168
+ if (result.exitCode !== 0) {
169
+ this.logger.tapOutput(cs(`❌ Docker test failed with exit code ${result.exitCode}`, 'red'));
170
+ }
171
+ // Evaluate final result
172
+ await tapParser.evaluateFinalResult();
173
+ }
174
+ catch (error) {
175
+ this.logger.tapOutput(cs(`❌ Error running Docker test: ${error.message}`, 'red'));
176
+ // Add a failing test result to the parser
177
+ tapParser.handleTapLog('not ok 1 - Docker test execution failed');
178
+ await tapParser.evaluateFinalResult();
179
+ }
180
+ return tapParser;
181
+ }
182
+ /**
183
+ * Clean up built Docker images (optional, can be called at end of test suite)
184
+ */
185
+ async cleanup() {
186
+ for (const imageName of this.builtImages) {
187
+ try {
188
+ this.logger.tapOutput(`Removing Docker image: ${imageName}`);
189
+ await this.smartshellInstance.exec(`docker rmi ${imageName}`);
190
+ }
191
+ catch (error) {
192
+ // Ignore cleanup errors
193
+ this.logger.tapOutput(cs(`Warning: Failed to remove image ${imageName}: ${error.message}`, 'orange'));
194
+ }
195
+ }
196
+ this.builtImages.clear();
197
+ }
198
+ }
199
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN0ZXN0LmNsYXNzZXMucnVudGltZS5kb2NrZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy90c3Rlc3QuY2xhc3Nlcy5ydW50aW1lLmRvY2tlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHFCQUFxQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxhQUFhLElBQUksRUFBRSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDL0QsT0FBTyxFQUNMLGNBQWMsR0FJZixNQUFNLHFDQUFxQyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUMzRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFbkQsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixzQkFBc0IsRUFDdEIsZ0JBQWdCLEVBQ2pCLE1BQU0sb0NBQW9DLENBQUM7QUFFNUM7Ozs7O0dBS0c7QUFDSCxNQUFNLE9BQU8sb0JBQXFCLFNBQVEsY0FBYztJQU10RCxZQUNVLE1BQW9CLEVBQ3BCLGtCQUF1QixFQUFFLGtEQUFrRDtJQUMzRSxjQUE2QixFQUM3QixHQUFXO1FBRW5CLEtBQUssRUFBRSxDQUFDO1FBTEEsV0FBTSxHQUFOLE1BQU0sQ0FBYztRQUNwQix1QkFBa0IsR0FBbEIsa0JBQWtCLENBQUs7UUFDdkIsbUJBQWMsR0FBZCxjQUFjLENBQWU7UUFDN0IsUUFBRyxHQUFILEdBQUcsQ0FBUTtRQVRaLE9BQUUsR0FBWSxNQUFNLENBQUMsQ0FBQyxvRUFBb0U7UUFDMUYsZ0JBQVcsR0FBVyxRQUFRLENBQUM7UUFFaEMsZ0JBQVcsR0FBZ0IsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDLHlDQUF5QztJQVN2RixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsY0FBYztRQUNsQixJQUFJLENBQUM7WUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJ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
@@ -36,3 +36,31 @@ export declare function isLegacyFilename(fileName: string): boolean;
36
36
  * Get the suggested new filename for a legacy filename
37
37
  */
38
38
  export declare function getLegacyMigrationTarget(fileName: string): string | null;
39
+ /**
40
+ * Docker test file information
41
+ */
42
+ export interface DockerTestFileInfo {
43
+ baseName: string;
44
+ variant: string;
45
+ isDockerTest: true;
46
+ original: string;
47
+ }
48
+ /**
49
+ * Check if a filename matches the Docker test pattern: *.{variant}.docker.sh
50
+ * Examples: test.latest.docker.sh, test.integration.npmci.docker.sh
51
+ */
52
+ export declare function isDockerTestFile(fileName: string): boolean;
53
+ /**
54
+ * Parse a Docker test filename to extract variant and base name
55
+ * Pattern: test.{baseName}.{variant}.docker.sh
56
+ * Examples:
57
+ * - test.latest.docker.sh -> { baseName: 'test', variant: 'latest' }
58
+ * - test.integration.npmci.docker.sh -> { baseName: 'test.integration', variant: 'npmci' }
59
+ */
60
+ export declare function parseDockerTestFilename(filePath: string): DockerTestFileInfo;
61
+ /**
62
+ * Map a Docker variant to its corresponding Dockerfile path
63
+ * "latest" -> "Dockerfile"
64
+ * Other variants -> "Dockerfile_{variant}"
65
+ */
66
+ export declare function mapVariantToDockerfile(variant: string, baseDir: string): string;
@@ -11,7 +11,7 @@
11
11
  */
12
12
  const KNOWN_RUNTIMES = new Set(['node', 'chromium', 'deno', 'bun']);
13
13
  const KNOWN_MODIFIERS = new Set(['nonci']);
14
- const VALID_EXTENSIONS = new Set(['ts', 'tsx', 'mts', 'cts']);
14
+ const VALID_EXTENSIONS = new Set(['ts', 'tsx', 'mts', 'cts', 'sh']);
15
15
  const ALL_RUNTIMES = ['node', 'chromium', 'deno', 'bun'];
16
16
  // Legacy mappings for backwards compatibility
17
17
  const LEGACY_RUNTIME_MAP = {
@@ -174,4 +174,61 @@ export function getLegacyMigrationTarget(fileName) {
174
174
  parts.push(parsed.extension);
175
175
  return parts.join('.');
176
176
  }
177
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN0ZXN0LmNsYXNzZXMucnVudGltZS5wYXJzZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy90c3Rlc3QuY2xhc3Nlcy5ydW50aW1lLnBhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7OztHQVVHO0FBbUJILE1BQU0sY0FBYyxHQUFnQixJQUFJLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDakYsTUFBTSxlQUFlLEdBQWdCLElBQUksR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUN4RCxNQUFNLGdCQUFnQixHQUFnQixJQUFJLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDM0UsTUFBTSxZQUFZLEdBQWMsQ0FBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztBQUVwRSw4Q0FBOEM7QUFDOUMsTUFBTSxrQkFBa0IsR0FBOEI7SUFDcEQsT0FBTyxFQUFFLENBQUMsVUFBVSxDQUFDO0lBQ3JCLElBQUksRUFBRSxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUM7Q0FDM0IsQ0FBQztBQUVGOzs7R0FHRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FDL0IsUUFBZ0IsRUFDaEIsU0FBdUIsRUFBRTtJQUV6QixNQUFNLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxvQkFBb0IsSUFBSSxJQUFJLENBQUM7SUFDakUsTUFBTSxlQUFlLEdBQUcsTUFBTSxDQUFDLGVBQWUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRTNELDBDQUEwQztJQUMxQyxNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLFFBQVEsQ0FBQztJQUN2RCxNQUFNLFFBQVEsR0FBRyxR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
177
+ /**
178
+ * Check if a filename matches the Docker test pattern: *.{variant}.docker.sh
179
+ * Examples: test.latest.docker.sh, test.integration.npmci.docker.sh
180
+ */
181
+ export function isDockerTestFile(fileName) {
182
+ // Must end with .docker.sh
183
+ if (!fileName.endsWith('.docker.sh')) {
184
+ return false;
185
+ }
186
+ // Extract filename from path if needed
187
+ const name = fileName.split('/').pop() || fileName;
188
+ // Must have at least 3 parts: [baseName, variant, docker, sh]
189
+ const parts = name.split('.');
190
+ return parts.length >= 4 && parts[parts.length - 2] === 'docker' && parts[parts.length - 1] === 'sh';
191
+ }
192
+ /**
193
+ * Parse a Docker test filename to extract variant and base name
194
+ * Pattern: test.{baseName}.{variant}.docker.sh
195
+ * Examples:
196
+ * - test.latest.docker.sh -> { baseName: 'test', variant: 'latest' }
197
+ * - test.integration.npmci.docker.sh -> { baseName: 'test.integration', variant: 'npmci' }
198
+ */
199
+ export function parseDockerTestFilename(filePath) {
200
+ // Extract just the filename from the path
201
+ const fileName = filePath.split('/').pop() || filePath;
202
+ const original = fileName;
203
+ if (!isDockerTestFile(fileName)) {
204
+ throw new Error(`Not a valid Docker test file: "${fileName}". Expected pattern: *.{variant}.docker.sh`);
205
+ }
206
+ // Remove .docker.sh suffix
207
+ const withoutSuffix = fileName.slice(0, -10); // Remove '.docker.sh'
208
+ const tokens = withoutSuffix.split('.');
209
+ if (tokens.length === 0) {
210
+ throw new Error(`Invalid Docker test file: empty basename in "${fileName}"`);
211
+ }
212
+ // Last token before .docker.sh is the variant
213
+ const variant = tokens[tokens.length - 1];
214
+ // Everything else is the base name
215
+ const baseName = tokens.slice(0, -1).join('.');
216
+ return {
217
+ baseName: baseName || 'test',
218
+ variant,
219
+ isDockerTest: true,
220
+ original,
221
+ };
222
+ }
223
+ /**
224
+ * Map a Docker variant to its corresponding Dockerfile path
225
+ * "latest" -> "Dockerfile"
226
+ * Other variants -> "Dockerfile_{variant}"
227
+ */
228
+ export function mapVariantToDockerfile(variant, baseDir) {
229
+ if (variant === 'latest') {
230
+ return `${baseDir}/Dockerfile`;
231
+ }
232
+ return `${baseDir}/Dockerfile_${variant}`;
233
+ }
234
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN0ZXN0LmNsYXNzZXMucnVudGltZS5wYXJzZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy90c3Rlc3QuY2xhc3Nlcy5ydW50aW1lLnBhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7OztHQVVHO0FBbUJILE1BQU0sY0FBYyxHQUFnQixJQUFJLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDakYsTUFBTSxlQUFlLEdBQWdCLElBQUksR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUN4RCxNQUFNLGdCQUFnQixHQUFnQixJQUFJLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ2pGLE1BQU0sWUFBWSxHQUFjLENBQUMsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFFcEUsOENBQThDO0FBQzlDLE1BQU0sa0JBQWtCLEdBQThCO0lBQ3BELE9BQU8sRUFBRSxDQUFDLFVBQVUsQ0FBQztJQUNyQixJQUFJLEVBQUUsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDO0NBQzNCLENBQUM7QUFFRjs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsaUJBQWlCLENBQy9CLFFBQWdCLEVBQ2hCLFNBQXVCLEVBQUU7SUFFekIsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUMsb0JBQW9CLElBQUksSUFBSSxDQUFDO0lBQ2pFLE1BQU0sZUFBZSxHQUFHLE1BQU0sQ0FBQyxlQUFlLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUUzRCwwQ0FBMEM7SUFDMUMsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxRQUFRLENBQUM7SUFDdkQsTUFBTSxR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
@@ -50,9 +50,15 @@ export class TestDirectory {
50
50
  case TestExecutionMode.DIRECTORY:
51
51
  // Directory mode - now recursive with ** pattern
52
52
  const dirPath = plugins.path.join(this.cwd, this.testPath);
53
- const testPattern = '**/test*.ts';
54
- const testFiles = await plugins.smartfile.fs.listFileTree(dirPath, testPattern);
55
- this.testfileArray = await Promise.all(testFiles.map(async (filePath) => {
53
+ // Search for both TypeScript test files and Docker shell test files
54
+ const tsPattern = '**/test*.ts';
55
+ const dockerPattern = '**/*.docker.sh';
56
+ const [tsFiles, dockerFiles] = await Promise.all([
57
+ plugins.smartfile.fs.listFileTree(dirPath, tsPattern),
58
+ plugins.smartfile.fs.listFileTree(dirPath, dockerPattern),
59
+ ]);
60
+ const allTestFiles = [...tsFiles, ...dockerFiles];
61
+ this.testfileArray = await Promise.all(allTestFiles.map(async (filePath) => {
56
62
  const absolutePath = plugins.path.isAbsolute(filePath)
57
63
  ? filePath
58
64
  : plugins.path.join(dirPath, filePath);
@@ -101,4 +107,4 @@ export class TestDirectory {
101
107
  return result;
102
108
  }
103
109
  }
104
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN0ZXN0LmNsYXNzZXMudGVzdGRpcmVjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3RzdGVzdC5jbGFzc2VzLnRlc3RkaXJlY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEtBQUssS0FBSyxNQUFNLG1CQUFtQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNsRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFL0Msb0JBQW9CO0FBQ3BCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUNuRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDM0QsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBRW5FLE1BQU0sT0FBTyxhQUFhO0lBcUJ4Qjs7Ozs7T0FLRztJQUNILFlBQVksTUFBYyxFQUFFLFdBQW1CLEVBQUUsZ0JBQW1DO1FBWHBGOztXQUVHO1FBQ0gsa0JBQWEsR0FBZ0IsRUFBRSxDQUFDO1FBUzlCLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDO1FBQ2xCLElBQUksQ0FBQyxRQUFRLEdBQUcsV0FBVyxDQUFDO1FBQzVCLElBQUksQ0FBQyxhQUFhLEdBQUcsZ0JBQWdCLENBQUM7SUFDeEMsQ0FBQztJQUVPLEtBQUssQ0FBQyxLQUFLO1FBQ2pCLFFBQVEsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzNCLEtBQUssaUJBQWlCLENBQUMsSUFBSTtnQkFDekIsbUJBQW1CO2dCQUNuQixNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO29CQUNyRCxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVE7b0JBQ2YsQ0FBQyxDQUFD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
110
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN0ZXN0LmNsYXNzZXMudGVzdGRpcmVjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3RzdGVzdC5jbGFzc2VzLnRlc3RkaXJlY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEtBQUssS0FBSyxNQUFNLG1CQUFtQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNsRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFL0Msb0JBQW9CO0FBQ3BCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUNuRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDM0QsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBRW5FLE1BQU0sT0FBTyxhQUFhO0lBcUJ4Qjs7Ozs7T0FLRztJQUNILFlBQVksTUFBYyxFQUFFLFdBQW1CLEVBQUUsZ0JBQW1DO1FBWHBGOztXQUVHO1FBQ0gsa0JBQWEsR0FBZ0IsRUFBRSxDQUFDO1FBUzlCLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDO1FBQ2xCLElBQUksQ0FBQyxRQUFRLEdBQUcsV0FBVyxDQUFDO1FBQzVCLElBQUksQ0FBQyxhQUFhLEdBQUcsZ0JBQWdCLENBQUM7SUFDeEMsQ0FBQztJQUVPLEtBQUssQ0FBQyxLQUFLO1FBQ2pCLFFBQVEsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzNCLEtBQUssaUJBQWlCLENBQUMsSUFBSTtnQkFDekIsbUJBQW1CO2dCQUNuQixNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO29CQUNyRCxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVE7b0JBQ2YsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUUvQyxJQUFJLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7b0JBQ3BELElBQUksQ0FBQyxhQUFhLEdBQUcsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO2dCQUNsRixDQUFDO3FCQUFNLENBQUM7b0JBQ04sTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsUUFBUSxFQUFFLENBQUMsQ0FBQztnQkFDdEQsQ0FBQztnQkFDRCxNQUFNO1lBRVIsS0FBSyxpQkFBaUIsQ0FBQyxJQUFJO2dCQUN6QixvRUFBb0U7Z0JBQ3BFLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7Z0JBQ2xDLE1BQU0sWUFBWSxHQUFHLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsV0FBVyxDQUFDLENBQUM7Z0JBRXBGLElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUNwQyxZQUFZLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsRUFBRTtvQkFDbEMsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDO3dCQUNwRCxDQUFDLENBQUMsUUFBUTt3QkFDVixDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQztvQkFDMUMsT0FBTyxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFDdEUsQ0FBQyxDQUFDLENBQ0gsQ0FBQztnQkFDRixNQUFNO1lBRVIsS0FBSyxpQkFBaUIsQ0FBQyxTQUFTO2dCQUM5QixpREFBaUQ7Z0JBQ2pELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUUzRCxvRUFBb0U7Z0JBQ3BFLE1BQU0sU0FBUyxHQUFHLGFBQWEsQ0FBQztnQkFDaEMsTUFBTSxhQUFhLEdBQUcsZ0JBQWdCLENBQUM7Z0JBRXZDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDO29CQUMvQyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQztvQkFDckQsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUM7aUJBQzFELENBQUMsQ0FBQztnQkFFSCxNQUFNLFlBQVksR0FBRyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsV0FBVyxDQUFDLENBQUM7Z0JBRWxELElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUNwQyxZQUFZLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsRUFBRTtvQkFDbEMsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDO3dCQUNwRCxDQUFDLENBQUMsUUFBUTt3QkFDVixDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO29CQUN6QyxPQUFPLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUN0RSxDQUFDLENBQUMsQ0FDSCxDQUFDO2dCQUNGLE1BQU07UUFDVixDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxvQkFBb0I7UUFDeEIsTUFBTSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbkIsTUFBTSxhQUFhLEdBQWEsRUFBRSxDQUFDO1FBQ25DLEtBQUssTUFBTSxRQUFRLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzFDLDJDQUEyQztZQUMzQyxhQUFhLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNwQyxDQUFDO1FBQ0QsT0FBTyxhQUFhLENBQUM7SUFDdkIsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxpQkFBaUI7UUFJckIsTUFBTSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFFbkIsTUFBTSxNQUFNLEdBQUc7WUFDYixNQUFNLEVBQUUsRUFBYztZQUN0QixjQUFjLEVBQUUsRUFBdUM7U0FDeEQsQ0FBQztRQUVGLEtBQUssTUFBTSxRQUFRLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzFDLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUM7WUFDL0IsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7WUFFakQsMkNBQTJDO1lBQzNDLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUV4RCxJQUFJLGFBQWEsRUFBRSxDQUFDO2dCQUNsQixNQUFNLFdBQVcsR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3JDLE1BQU0sU0FBUyxHQUFHLFNBQVMsV0FBVyxFQUFFLENBQUM7Z0JBRXpDLElBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7b0JBQ3RDLE1BQU0sQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUN4QyxDQUFDO2dCQUNELE1BQU0sQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2xELENBQUM7aUJBQU0sQ0FBQztnQkFDTixxQkFBcUI7Z0JBQ3JCLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQy9CLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztDQUNGIn0=
@@ -5,6 +5,7 @@ import { TestExecutionMode } from './index.js';
5
5
  import { TsTestLogger } from './tstest.logging.js';
6
6
  import type { LogOptions } from './tstest.logging.js';
7
7
  import { RuntimeAdapterRegistry } from './tstest.classes.runtime.adapter.js';
8
+ import { DockerRuntimeAdapter } from './tstest.classes.runtime.docker.js';
8
9
  export declare class TsTest {
9
10
  testDir: TestDirectory;
10
11
  executionMode: TestExecutionMode;
@@ -17,6 +18,7 @@ export declare class TsTest {
17
18
  smartbrowserInstance: plugins.smartbrowser.SmartBrowser;
18
19
  tsbundleInstance: plugins.tsbundle.TsBundle;
19
20
  runtimeRegistry: RuntimeAdapterRegistry;
21
+ dockerAdapter: DockerRuntimeAdapter | null;
20
22
  constructor(cwdArg: string, testPathArg: string, executionModeArg: TestExecutionMode, logOptions?: LogOptions, tags?: string[], startFromFile?: number | null, stopAtFile?: number | null, timeoutSeconds?: number | null);
21
23
  /**
22
24
  * Check and display available runtimes
@@ -26,6 +28,10 @@ export declare class TsTest {
26
28
  runWatch(ignorePatterns?: string[]): Promise<void>;
27
29
  private runSingleTestOrSkip;
28
30
  private runSingleTest;
31
+ /**
32
+ * Execute a Docker test file
33
+ */
34
+ private runDockerTest;
29
35
  runInNode(fileNameArg: string, index: number, total: number): Promise<TapParser>;
30
36
  private findFreePorts;
31
37
  runInChrome(fileNameArg: string, index: number, total: number): Promise<TapParser>;
@@ -7,12 +7,13 @@ import { TapParser } from './tstest.classes.tap.parser.js';
7
7
  import { TestExecutionMode } from './index.js';
8
8
  import { TsTestLogger } from './tstest.logging.js';
9
9
  // Runtime adapters
10
- import { parseTestFilename } from './tstest.classes.runtime.parser.js';
10
+ import { parseTestFilename, isDockerTestFile, parseDockerTestFilename } from './tstest.classes.runtime.parser.js';
11
11
  import { RuntimeAdapterRegistry } from './tstest.classes.runtime.adapter.js';
12
12
  import { NodeRuntimeAdapter } from './tstest.classes.runtime.node.js';
13
13
  import { ChromiumRuntimeAdapter } from './tstest.classes.runtime.chromium.js';
14
14
  import { DenoRuntimeAdapter } from './tstest.classes.runtime.deno.js';
15
15
  import { BunRuntimeAdapter } from './tstest.classes.runtime.bun.js';
16
+ import { DockerRuntimeAdapter } from './tstest.classes.runtime.docker.js';
16
17
  export class TsTest {
17
18
  constructor(cwdArg, testPathArg, executionModeArg, logOptions = {}, tags = [], startFromFile = null, stopAtFile = null, timeoutSeconds = null) {
18
19
  this.smartshellInstance = new plugins.smartshell.Smartshell({
@@ -23,6 +24,7 @@ export class TsTest {
23
24
  this.smartbrowserInstance = new plugins.smartbrowser.SmartBrowser();
24
25
  this.tsbundleInstance = new plugins.tsbundle.TsBundle();
25
26
  this.runtimeRegistry = new RuntimeAdapterRegistry();
27
+ this.dockerAdapter = null;
26
28
  this.executionMode = executionModeArg;
27
29
  this.testDir = new TestDirectory(cwdArg, testPathArg, executionModeArg);
28
30
  this.logger = new TsTestLogger(logOptions);
@@ -35,6 +37,8 @@ export class TsTest {
35
37
  this.runtimeRegistry.register(new ChromiumRuntimeAdapter(this.logger, this.tsbundleInstance, this.smartbrowserInstance, this.timeoutSeconds));
36
38
  this.runtimeRegistry.register(new DenoRuntimeAdapter(this.logger, this.smartshellInstance, this.timeoutSeconds, this.filterTags));
37
39
  this.runtimeRegistry.register(new BunRuntimeAdapter(this.logger, this.smartshellInstance, this.timeoutSeconds, this.filterTags));
40
+ // Initialize Docker adapter
41
+ this.dockerAdapter = new DockerRuntimeAdapter(this.logger, this.smartshellInstance, this.timeoutSeconds, cwdArg);
38
42
  }
39
43
  /**
40
44
  * Check and display available runtimes
@@ -150,8 +154,12 @@ export class TsTest {
150
154
  await this.runSingleTest(fileNameArg, fileIndex, totalFiles, tapCombinator);
151
155
  }
152
156
  async runSingleTest(fileNameArg, fileIndex, totalFiles, tapCombinator) {
153
- // Parse the filename to determine runtimes and modifiers
154
157
  const fileName = plugins.path.basename(fileNameArg);
158
+ // Check if this is a Docker test file
159
+ if (isDockerTestFile(fileName)) {
160
+ return await this.runDockerTest(fileNameArg, fileIndex, totalFiles, tapCombinator);
161
+ }
162
+ // Parse the filename to determine runtimes and modifiers (for TypeScript tests)
155
163
  const parsed = parseTestFilename(fileName, { strictUnknownRuntime: false });
156
164
  // Check for nonci modifier in CI environment
157
165
  if (process.env.CI && parsed.modifiers.includes('nonci')) {
@@ -192,6 +200,22 @@ export class TsTest {
192
200
  }
193
201
  }
194
202
  }
203
+ /**
204
+ * Execute a Docker test file
205
+ */
206
+ async runDockerTest(fileNameArg, fileIndex, totalFiles, tapCombinator) {
207
+ if (!this.dockerAdapter) {
208
+ this.logger.tapOutput(cs('❌ Docker adapter not initialized', 'red'));
209
+ return;
210
+ }
211
+ try {
212
+ const tapParser = await this.dockerAdapter.run(fileNameArg, fileIndex, totalFiles);
213
+ tapCombinator.addTapParser(tapParser);
214
+ }
215
+ catch (error) {
216
+ this.logger.tapOutput(cs(`❌ Docker test failed: ${error.message}`, 'red'));
217
+ }
218
+ }
195
219
  async runInNode(fileNameArg, index, total) {
196
220
  this.logger.testFileStart(fileNameArg, 'node.js', index, total);
197
221
  const tapParser = new TapParser(fileNameArg + ':node', this.logger);
@@ -533,4 +557,4 @@ import '${absoluteTestFile.replace(/\\/g, '/')}';
533
557
  }
534
558
  }
535
559
  }
536
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN0ZXN0LmNsYXNzZXMudHN0ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvdHN0ZXN0LmNsYXNzZXMudHN0ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFDL0MsT0FBTyxLQUFLLEtBQUssTUFBTSxtQkFBbUIsQ0FBQztBQUUzQyxPQUFPLEVBQUUsYUFBYSxJQUFJLEVBQUUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRS9ELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNsRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDbkUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzNELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUMvQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFHbkQsbUJBQW1CO0FBQ25CLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQzdFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQzlFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBRXBFLE1BQU0sT0FBTyxNQUFNO0lBb0JqQixZQUFZLE1BQWMsRUFBRSxXQUFtQixFQUFFLGdCQUFtQyxFQUFFLGFBQXlCLEVBQUUsRUFBRSxPQUFpQixFQUFFLEVBQUUsZ0JBQStCLElBQUksRUFBRSxhQUE0QixJQUFJLEVBQUUsaUJBQWdDLElBQUk7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
560
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN0ZXN0LmNsYXNzZXMudHN0ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvdHN0ZXN0LmNsYXNzZXMudHN0ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFDL0MsT0FBTyxLQUFLLEtBQUssTUFBTSxtQkFBbUIsQ0FBQztBQUUzQyxPQUFPLEVBQUUsYUFBYSxJQUFJLEVBQUUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRS9ELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNsRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDbkUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzNELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUMvQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFHbkQsbUJBQW1CO0FBQ25CLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ2xILE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQzdFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQzlFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3BFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBRTFFLE1BQU0sT0FBTyxNQUFNO0lBcUJqQixZQUFZLE1BQWMsRUFBRSxXQUFtQixFQUFFLGdCQUFtQyxFQUFFLGFBQXlCLEVB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
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@git.zone/tstest",
3
- "version": "2.6.1",
3
+ "version": "2.7.0",
4
4
  "private": false,
5
5
  "description": "a test utility to run tests that match test/**/*.ts",
6
6
  "exports": {
7
7
  ".": "./dist_ts/index.js",
8
8
  "./tapbundle": "./dist_ts_tapbundle/index.js",
9
- "./tapbundle_node": "./dist_ts_tapbundle_node/index.js"
9
+ "./tapbundle_node": "./dist_ts_tapbundle_node/index.js",
10
+ "./tapbundle_protocol": "./dist_ts_tapbundle_protocol/index.js"
10
11
  },
11
12
  "type": "module",
12
13
  "author": "Lossless GmbH",
@@ -37,7 +38,7 @@
37
38
  "@push.rocks/smartnetwork": "^4.4.0",
38
39
  "@push.rocks/smartpath": "^6.0.0",
39
40
  "@push.rocks/smartpromise": "^4.2.3",
40
- "@push.rocks/smartrequest": "^4.3.1",
41
+ "@push.rocks/smartrequest": "^4.3.2",
41
42
  "@push.rocks/smarts3": "^2.2.6",
42
43
  "@push.rocks/smartshell": "^3.3.0",
43
44
  "@push.rocks/smarttime": "^4.1.1",
package/readme.md CHANGED
@@ -319,6 +319,129 @@ tstest provides multiple exports for different use cases:
319
319
  - `@git.zone/tstest` - Main CLI and test runner functionality
320
320
  - `@git.zone/tstest/tapbundle` - Browser-compatible test framework
321
321
  - `@git.zone/tstest/tapbundle_node` - Node.js-specific test utilities
322
+ - `@git.zone/tstest/tapbundle_protocol` - Protocol V2 emitter and parser for TAP extensions
323
+
324
+ ## tapbundle Protocol V2
325
+
326
+ tstest includes an enhanced TAP protocol (Protocol V2) that extends standard TAP 13 with additional metadata while maintaining backwards compatibility.
327
+
328
+ ### Overview
329
+
330
+ Protocol V2 adds structured metadata to TAP output using Unicode markers (`⟦TSTEST:...⟧`) that standard TAP parsers safely ignore. This allows for:
331
+
332
+ - **Timing information** - Test execution duration in milliseconds
333
+ - **Structured errors** - Stack traces, diffs, and detailed error data
334
+ - **Test events** - Real-time progress and lifecycle events
335
+ - **Snapshots** - Snapshot testing data exchange
336
+ - **Custom metadata** - Tags, retry counts, file locations
337
+
338
+ ### Using the Protocol
339
+
340
+ ```typescript
341
+ import {
342
+ ProtocolEmitter,
343
+ ProtocolParser,
344
+ PROTOCOL_MARKERS,
345
+ PROTOCOL_VERSION
346
+ } from '@git.zone/tstest/tapbundle_protocol';
347
+
348
+ // Create an emitter
349
+ const emitter = new ProtocolEmitter();
350
+
351
+ // Emit protocol header
352
+ console.log(emitter.emitProtocolHeader());
353
+ // Output: ⟦TSTEST:PROTOCOL:2.0.0⟧
354
+
355
+ // Emit TAP version
356
+ console.log(emitter.emitTapVersion(13));
357
+ // Output: TAP version 13
358
+
359
+ // Emit a test result with metadata
360
+ const testResult = {
361
+ ok: true,
362
+ testNumber: 1,
363
+ description: 'user authentication works',
364
+ metadata: {
365
+ time: 123,
366
+ tags: ['auth', 'unit']
367
+ }
368
+ };
369
+ console.log(emitter.emitTest(testResult).join('\n'));
370
+ // Output: ok 1 - user authentication works ⟦TSTEST:time:123⟧
371
+ // ⟦TSTEST:META:{"tags":["auth","unit"]}⟧
372
+ ```
373
+
374
+ ### Protocol Markers
375
+
376
+ ```typescript
377
+ PROTOCOL_MARKERS = {
378
+ START: '⟦TSTEST:',
379
+ END: '⟧',
380
+ META_PREFIX: 'META:',
381
+ ERROR_PREFIX: 'ERROR',
382
+ SNAPSHOT_PREFIX: 'SNAPSHOT:',
383
+ SKIP_PREFIX: 'SKIP:',
384
+ TODO_PREFIX: 'TODO:',
385
+ EVENT_PREFIX: 'EVENT:'
386
+ }
387
+ ```
388
+
389
+ ### Use Cases
390
+
391
+ #### Creating Custom Test Runners
392
+
393
+ ```typescript
394
+ import { ProtocolEmitter } from '@git.zone/tstest/tapbundle_protocol';
395
+
396
+ const emitter = new ProtocolEmitter();
397
+
398
+ // Emit header and version
399
+ console.log(emitter.emitProtocolHeader());
400
+ console.log(emitter.emitTapVersion(13));
401
+ console.log(emitter.emitPlan({ start: 1, end: 2 }));
402
+
403
+ // Run your tests and emit results
404
+ const startTime = Date.now();
405
+ // ... run test ...
406
+ const duration = Date.now() - startTime;
407
+
408
+ console.log(emitter.emitTest({
409
+ ok: true,
410
+ testNumber: 1,
411
+ description: 'my custom test',
412
+ metadata: { time: duration }
413
+ }).join('\n'));
414
+ ```
415
+
416
+ #### Parsing tapbundle Output
417
+
418
+ ```typescript
419
+ import { ProtocolParser } from '@git.zone/tstest/tapbundle_protocol';
420
+
421
+ const parser = new ProtocolParser();
422
+
423
+ // Parse TAP output line by line
424
+ parser.parseLine('⟦TSTEST:PROTOCOL:2.0.0⟧');
425
+ parser.parseLine('TAP version 13');
426
+ parser.parseLine('1..1');
427
+ parser.parseLine('ok 1 - test name ⟦TSTEST:time:123⟧');
428
+
429
+ // Get parsed results
430
+ const results = parser.getResults();
431
+ console.log(results);
432
+ ```
433
+
434
+ ### Backwards Compatibility
435
+
436
+ Protocol V2 is fully backwards compatible with standard TAP 13. The Unicode markers are treated as comments by standard TAP parsers, so Protocol V2 output can be consumed by any TAP-compliant tool:
437
+
438
+ ```
439
+ ⟦TSTEST:PROTOCOL:2.0.0⟧ ← Ignored by standard TAP parsers
440
+ TAP version 13 ← Standard TAP
441
+ 1..2 ← Standard TAP
442
+ ok 1 - test ⟦TSTEST:time:45⟧ ← TAP parsers see: "ok 1 - test"
443
+ ok 2 - another test ← Standard TAP
444
+ ```
322
445
 
323
446
  ## tapbundle Test Framework
324
447
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@git.zone/tstest',
6
- version: '2.6.1',
6
+ version: '2.7.0',
7
7
  description: 'a test utility to run tests that match test/**/*.ts'
8
8
  }
@@ -0,0 +1,251 @@
1
+ import * as plugins from './tstest.plugins.js';
2
+ import { coloredString as cs } from '@push.rocks/consolecolor';
3
+ import {
4
+ RuntimeAdapter,
5
+ type RuntimeOptions,
6
+ type RuntimeCommand,
7
+ type RuntimeAvailability,
8
+ } from './tstest.classes.runtime.adapter.js';
9
+ import { TapParser } from './tstest.classes.tap.parser.js';
10
+ import { TsTestLogger } from './tstest.logging.js';
11
+ import type { Runtime } from './tstest.classes.runtime.parser.js';
12
+ import {
13
+ parseDockerTestFilename,
14
+ mapVariantToDockerfile,
15
+ isDockerTestFile
16
+ } from './tstest.classes.runtime.parser.js';
17
+
18
+ /**
19
+ * Docker runtime adapter
20
+ * Executes shell test files inside Docker containers
21
+ * Pattern: test.{variant}.docker.sh
22
+ * Variants map to Dockerfiles: latest -> Dockerfile, others -> Dockerfile_{variant}
23
+ */
24
+ export class DockerRuntimeAdapter extends RuntimeAdapter {
25
+ readonly id: Runtime = 'node'; // Using 'node' temporarily as Runtime type doesn't include 'docker'
26
+ readonly displayName: string = 'Docker';
27
+
28
+ private builtImages: Set<string> = new Set(); // Track built images to avoid rebuilding
29
+
30
+ constructor(
31
+ private logger: TsTestLogger,
32
+ private smartshellInstance: any, // SmartShell instance from @push.rocks/smartshell
33
+ private timeoutSeconds: number | null,
34
+ private cwd: string
35
+ ) {
36
+ super();
37
+ }
38
+
39
+ /**
40
+ * Check if Docker CLI is available
41
+ */
42
+ async checkAvailable(): Promise<RuntimeAvailability> {
43
+ try {
44
+ const result = await this.smartshellInstance.exec('docker --version');
45
+
46
+ if (result.exitCode !== 0) {
47
+ return {
48
+ available: false,
49
+ error: 'Docker command failed',
50
+ };
51
+ }
52
+
53
+ // Extract version from output like "Docker version 24.0.5, build ced0996"
54
+ const versionMatch = result.stdout.match(/Docker version ([^,]+)/);
55
+ const version = versionMatch ? versionMatch[1] : 'unknown';
56
+
57
+ return {
58
+ available: true,
59
+ version,
60
+ };
61
+ } catch (error) {
62
+ return {
63
+ available: false,
64
+ error: `Docker not found: ${error.message}`,
65
+ };
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Create command configuration for Docker test execution
71
+ * This is used for informational purposes
72
+ */
73
+ createCommand(testFile: string, options?: RuntimeOptions): RuntimeCommand {
74
+ const parsed = parseDockerTestFilename(testFile);
75
+ const dockerfilePath = mapVariantToDockerfile(parsed.variant, this.cwd);
76
+ const imageName = `tstest-${parsed.variant}`;
77
+
78
+ return {
79
+ command: 'docker',
80
+ args: [
81
+ 'run',
82
+ '--rm',
83
+ '-v',
84
+ `${this.cwd}/test:/test`,
85
+ imageName,
86
+ 'taprun',
87
+ `/test/${plugins.path.basename(testFile)}`
88
+ ],
89
+ env: {},
90
+ cwd: this.cwd,
91
+ };
92
+ }
93
+
94
+ /**
95
+ * Build a Docker image from the specified Dockerfile
96
+ */
97
+ private async buildDockerImage(dockerfilePath: string, imageName: string): Promise<void> {
98
+ // Check if image is already built
99
+ if (this.builtImages.has(imageName)) {
100
+ this.logger.tapOutput(`Using cached Docker image: ${imageName}`);
101
+ return;
102
+ }
103
+
104
+ // Check if Dockerfile exists
105
+ if (!await plugins.smartfile.fs.fileExists(dockerfilePath)) {
106
+ throw new Error(
107
+ `Dockerfile not found: ${dockerfilePath}\n` +
108
+ `Expected Dockerfile for Docker test variant.`
109
+ );
110
+ }
111
+
112
+ this.logger.tapOutput(`Building Docker image: ${imageName} from ${dockerfilePath}`);
113
+
114
+ try {
115
+ const buildResult = await this.smartshellInstance.exec(
116
+ `docker build -f ${dockerfilePath} -t ${imageName} ${this.cwd}`,
117
+ {
118
+ cwd: this.cwd,
119
+ }
120
+ );
121
+
122
+ if (buildResult.exitCode !== 0) {
123
+ throw new Error(`Docker build failed:\n${buildResult.stderr}`);
124
+ }
125
+
126
+ this.builtImages.add(imageName);
127
+ this.logger.tapOutput(`✅ Docker image built successfully: ${imageName}`);
128
+ } catch (error) {
129
+ throw new Error(`Failed to build Docker image: ${error.message}`);
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Execute a Docker test file
135
+ */
136
+ async run(
137
+ testFile: string,
138
+ index: number,
139
+ total: number,
140
+ options?: RuntimeOptions
141
+ ): Promise<TapParser> {
142
+ this.logger.testFileStart(testFile, this.displayName, index, total);
143
+
144
+ // Parse the Docker test filename
145
+ const parsed = parseDockerTestFilename(testFile);
146
+ const dockerfilePath = mapVariantToDockerfile(parsed.variant, this.cwd);
147
+ const imageName = `tstest-${parsed.variant}`;
148
+
149
+ // Build the Docker image
150
+ await this.buildDockerImage(dockerfilePath, imageName);
151
+
152
+ // Prepare the test file path relative to the mounted directory
153
+ // We need to get the path relative to cwd
154
+ const absoluteTestPath = plugins.path.isAbsolute(testFile)
155
+ ? testFile
156
+ : plugins.path.join(this.cwd, testFile);
157
+
158
+ const relativeTestPath = plugins.path.relative(this.cwd, absoluteTestPath);
159
+
160
+ // Create TAP parser
161
+ const tapParser = new TapParser(testFile + ':docker', this.logger);
162
+
163
+ try {
164
+ // Build docker run command
165
+ const dockerArgs = [
166
+ 'run',
167
+ '--rm',
168
+ '-v',
169
+ `${this.cwd}/test:/test`,
170
+ imageName,
171
+ 'taprun',
172
+ `/test/${plugins.path.basename(testFile)}`
173
+ ];
174
+
175
+ this.logger.tapOutput(`Executing: docker ${dockerArgs.join(' ')}`);
176
+
177
+ // Execute the Docker container
178
+ const execPromise = this.smartshellInstance.execStreaming(
179
+ `docker ${dockerArgs.join(' ')}`,
180
+ {
181
+ cwd: this.cwd,
182
+ }
183
+ );
184
+
185
+ // Set up timeout if configured
186
+ let timeoutHandle: NodeJS.Timeout | null = null;
187
+ if (this.timeoutSeconds) {
188
+ timeoutHandle = setTimeout(() => {
189
+ this.logger.tapOutput(`⏱️ Test timeout (${this.timeoutSeconds}s) - killing container`);
190
+ // Try to kill any running containers with this image
191
+ this.smartshellInstance.exec(`docker ps -q --filter ancestor=${imageName} | xargs -r docker kill`);
192
+ }, this.timeoutSeconds * 1000);
193
+ }
194
+
195
+ // Stream output to TAP parser line by line
196
+ execPromise.childProcess.stdout.on('data', (data: Buffer) => {
197
+ const output = data.toString();
198
+ const lines = output.split('\n');
199
+ for (const line of lines) {
200
+ if (line.trim()) {
201
+ tapParser.handleTapLog(line);
202
+ }
203
+ }
204
+ });
205
+
206
+ execPromise.childProcess.stderr.on('data', (data: Buffer) => {
207
+ const output = data.toString();
208
+ this.logger.tapOutput(cs(`[stderr] ${output}`, 'orange'));
209
+ });
210
+
211
+ // Wait for completion
212
+ const result = await execPromise;
213
+
214
+ // Clear timeout
215
+ if (timeoutHandle) {
216
+ clearTimeout(timeoutHandle);
217
+ }
218
+
219
+ if (result.exitCode !== 0) {
220
+ this.logger.tapOutput(cs(`❌ Docker test failed with exit code ${result.exitCode}`, 'red'));
221
+ }
222
+
223
+ // Evaluate final result
224
+ await tapParser.evaluateFinalResult();
225
+
226
+ } catch (error) {
227
+ this.logger.tapOutput(cs(`❌ Error running Docker test: ${error.message}`, 'red'));
228
+ // Add a failing test result to the parser
229
+ tapParser.handleTapLog('not ok 1 - Docker test execution failed');
230
+ await tapParser.evaluateFinalResult();
231
+ }
232
+
233
+ return tapParser;
234
+ }
235
+
236
+ /**
237
+ * Clean up built Docker images (optional, can be called at end of test suite)
238
+ */
239
+ async cleanup(): Promise<void> {
240
+ for (const imageName of this.builtImages) {
241
+ try {
242
+ this.logger.tapOutput(`Removing Docker image: ${imageName}`);
243
+ await this.smartshellInstance.exec(`docker rmi ${imageName}`);
244
+ } catch (error) {
245
+ // Ignore cleanup errors
246
+ this.logger.tapOutput(cs(`Warning: Failed to remove image ${imageName}: ${error.message}`, 'orange'));
247
+ }
248
+ }
249
+ this.builtImages.clear();
250
+ }
251
+ }
@@ -29,7 +29,7 @@ export interface ParserConfig {
29
29
 
30
30
  const KNOWN_RUNTIMES: Set<string> = new Set(['node', 'chromium', 'deno', 'bun']);
31
31
  const KNOWN_MODIFIERS: Set<string> = new Set(['nonci']);
32
- const VALID_EXTENSIONS: Set<string> = new Set(['ts', 'tsx', 'mts', 'cts']);
32
+ const VALID_EXTENSIONS: Set<string> = new Set(['ts', 'tsx', 'mts', 'cts', 'sh']);
33
33
  const ALL_RUNTIMES: Runtime[] = ['node', 'chromium', 'deno', 'bun'];
34
34
 
35
35
  // Legacy mappings for backwards compatibility
@@ -228,3 +228,81 @@ export function getLegacyMigrationTarget(fileName: string): string | null {
228
228
 
229
229
  return parts.join('.');
230
230
  }
231
+
232
+ /**
233
+ * Docker test file information
234
+ */
235
+ export interface DockerTestFileInfo {
236
+ baseName: string;
237
+ variant: string;
238
+ isDockerTest: true;
239
+ original: string;
240
+ }
241
+
242
+ /**
243
+ * Check if a filename matches the Docker test pattern: *.{variant}.docker.sh
244
+ * Examples: test.latest.docker.sh, test.integration.npmci.docker.sh
245
+ */
246
+ export function isDockerTestFile(fileName: string): boolean {
247
+ // Must end with .docker.sh
248
+ if (!fileName.endsWith('.docker.sh')) {
249
+ return false;
250
+ }
251
+
252
+ // Extract filename from path if needed
253
+ const name = fileName.split('/').pop() || fileName;
254
+
255
+ // Must have at least 3 parts: [baseName, variant, docker, sh]
256
+ const parts = name.split('.');
257
+ return parts.length >= 4 && parts[parts.length - 2] === 'docker' && parts[parts.length - 1] === 'sh';
258
+ }
259
+
260
+ /**
261
+ * Parse a Docker test filename to extract variant and base name
262
+ * Pattern: test.{baseName}.{variant}.docker.sh
263
+ * Examples:
264
+ * - test.latest.docker.sh -> { baseName: 'test', variant: 'latest' }
265
+ * - test.integration.npmci.docker.sh -> { baseName: 'test.integration', variant: 'npmci' }
266
+ */
267
+ export function parseDockerTestFilename(filePath: string): DockerTestFileInfo {
268
+ // Extract just the filename from the path
269
+ const fileName = filePath.split('/').pop() || filePath;
270
+ const original = fileName;
271
+
272
+ if (!isDockerTestFile(fileName)) {
273
+ throw new Error(`Not a valid Docker test file: "${fileName}". Expected pattern: *.{variant}.docker.sh`);
274
+ }
275
+
276
+ // Remove .docker.sh suffix
277
+ const withoutSuffix = fileName.slice(0, -10); // Remove '.docker.sh'
278
+ const tokens = withoutSuffix.split('.');
279
+
280
+ if (tokens.length === 0) {
281
+ throw new Error(`Invalid Docker test file: empty basename in "${fileName}"`);
282
+ }
283
+
284
+ // Last token before .docker.sh is the variant
285
+ const variant = tokens[tokens.length - 1];
286
+
287
+ // Everything else is the base name
288
+ const baseName = tokens.slice(0, -1).join('.');
289
+
290
+ return {
291
+ baseName: baseName || 'test',
292
+ variant,
293
+ isDockerTest: true,
294
+ original,
295
+ };
296
+ }
297
+
298
+ /**
299
+ * Map a Docker variant to its corresponding Dockerfile path
300
+ * "latest" -> "Dockerfile"
301
+ * Other variants -> "Dockerfile_{variant}"
302
+ */
303
+ export function mapVariantToDockerfile(variant: string, baseDir: string): string {
304
+ if (variant === 'latest') {
305
+ return `${baseDir}/Dockerfile`;
306
+ }
307
+ return `${baseDir}/Dockerfile_${variant}`;
308
+ }
@@ -74,12 +74,20 @@ export class TestDirectory {
74
74
  case TestExecutionMode.DIRECTORY:
75
75
  // Directory mode - now recursive with ** pattern
76
76
  const dirPath = plugins.path.join(this.cwd, this.testPath);
77
- const testPattern = '**/test*.ts';
78
-
79
- const testFiles = await plugins.smartfile.fs.listFileTree(dirPath, testPattern);
80
-
77
+
78
+ // Search for both TypeScript test files and Docker shell test files
79
+ const tsPattern = '**/test*.ts';
80
+ const dockerPattern = '**/*.docker.sh';
81
+
82
+ const [tsFiles, dockerFiles] = await Promise.all([
83
+ plugins.smartfile.fs.listFileTree(dirPath, tsPattern),
84
+ plugins.smartfile.fs.listFileTree(dirPath, dockerPattern),
85
+ ]);
86
+
87
+ const allTestFiles = [...tsFiles, ...dockerFiles];
88
+
81
89
  this.testfileArray = await Promise.all(
82
- testFiles.map(async (filePath) => {
90
+ allTestFiles.map(async (filePath) => {
83
91
  const absolutePath = plugins.path.isAbsolute(filePath)
84
92
  ? filePath
85
93
  : plugins.path.join(dirPath, filePath);
@@ -11,12 +11,13 @@ import { TsTestLogger } from './tstest.logging.js';
11
11
  import type { LogOptions } from './tstest.logging.js';
12
12
 
13
13
  // Runtime adapters
14
- import { parseTestFilename } from './tstest.classes.runtime.parser.js';
14
+ import { parseTestFilename, isDockerTestFile, parseDockerTestFilename } from './tstest.classes.runtime.parser.js';
15
15
  import { RuntimeAdapterRegistry } from './tstest.classes.runtime.adapter.js';
16
16
  import { NodeRuntimeAdapter } from './tstest.classes.runtime.node.js';
17
17
  import { ChromiumRuntimeAdapter } from './tstest.classes.runtime.chromium.js';
18
18
  import { DenoRuntimeAdapter } from './tstest.classes.runtime.deno.js';
19
19
  import { BunRuntimeAdapter } from './tstest.classes.runtime.bun.js';
20
+ import { DockerRuntimeAdapter } from './tstest.classes.runtime.docker.js';
20
21
 
21
22
  export class TsTest {
22
23
  public testDir: TestDirectory;
@@ -37,6 +38,7 @@ export class TsTest {
37
38
  public tsbundleInstance = new plugins.tsbundle.TsBundle();
38
39
 
39
40
  public runtimeRegistry = new RuntimeAdapterRegistry();
41
+ public dockerAdapter: DockerRuntimeAdapter | null = null;
40
42
 
41
43
  constructor(cwdArg: string, testPathArg: string, executionModeArg: TestExecutionMode, logOptions: LogOptions = {}, tags: string[] = [], startFromFile: number | null = null, stopAtFile: number | null = null, timeoutSeconds: number | null = null) {
42
44
  this.executionMode = executionModeArg;
@@ -60,6 +62,14 @@ export class TsTest {
60
62
  this.runtimeRegistry.register(
61
63
  new BunRuntimeAdapter(this.logger, this.smartshellInstance, this.timeoutSeconds, this.filterTags)
62
64
  );
65
+
66
+ // Initialize Docker adapter
67
+ this.dockerAdapter = new DockerRuntimeAdapter(
68
+ this.logger,
69
+ this.smartshellInstance,
70
+ this.timeoutSeconds,
71
+ cwdArg
72
+ );
63
73
  }
64
74
 
65
75
  /**
@@ -211,8 +221,14 @@ export class TsTest {
211
221
  }
212
222
 
213
223
  private async runSingleTest(fileNameArg: string, fileIndex: number, totalFiles: number, tapCombinator: TapCombinator) {
214
- // Parse the filename to determine runtimes and modifiers
215
224
  const fileName = plugins.path.basename(fileNameArg);
225
+
226
+ // Check if this is a Docker test file
227
+ if (isDockerTestFile(fileName)) {
228
+ return await this.runDockerTest(fileNameArg, fileIndex, totalFiles, tapCombinator);
229
+ }
230
+
231
+ // Parse the filename to determine runtimes and modifiers (for TypeScript tests)
216
232
  const parsed = parseTestFilename(fileName, { strictUnknownRuntime: false });
217
233
 
218
234
  // Check for nonci modifier in CI environment
@@ -258,6 +274,28 @@ export class TsTest {
258
274
  }
259
275
  }
260
276
 
277
+ /**
278
+ * Execute a Docker test file
279
+ */
280
+ private async runDockerTest(
281
+ fileNameArg: string,
282
+ fileIndex: number,
283
+ totalFiles: number,
284
+ tapCombinator: TapCombinator
285
+ ): Promise<void> {
286
+ if (!this.dockerAdapter) {
287
+ this.logger.tapOutput(cs('❌ Docker adapter not initialized', 'red'));
288
+ return;
289
+ }
290
+
291
+ try {
292
+ const tapParser = await this.dockerAdapter.run(fileNameArg, fileIndex, totalFiles);
293
+ tapCombinator.addTapParser(tapParser);
294
+ } catch (error) {
295
+ this.logger.tapOutput(cs(`❌ Docker test failed: ${error.message}`, 'red'));
296
+ }
297
+ }
298
+
261
299
  public async runInNode(fileNameArg: string, index: number, total: number): Promise<TapParser> {
262
300
  this.logger.testFileStart(fileNameArg, 'node.js', index, total);
263
301
  const tapParser = new TapParser(fileNameArg + ':node', this.logger);