@git.zone/tstest 3.1.8 → 3.3.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.
- package/dist_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/tstest.classes.migration.js +4 -4
- package/dist_ts/tstest.classes.runtime.bun.js +5 -5
- package/dist_ts/tstest.classes.runtime.chromium.js +12 -10
- package/dist_ts/tstest.classes.runtime.deno.d.ts +4 -0
- package/dist_ts/tstest.classes.runtime.deno.js +22 -27
- package/dist_ts/tstest.classes.runtime.docker.js +2 -2
- package/dist_ts/tstest.classes.runtime.node.js +5 -5
- package/dist_ts/tstest.classes.tap.parser.js +6 -7
- package/dist_ts/tstest.classes.testdirectory.d.ts +1 -1
- package/dist_ts/tstest.classes.testdirectory.js +11 -12
- package/dist_ts/tstest.classes.testfile.directives.d.ts +38 -0
- package/dist_ts/tstest.classes.testfile.directives.js +191 -0
- package/dist_ts/tstest.classes.tstest.js +48 -33
- package/dist_ts/tstest.plugins.d.ts +6 -3
- package/dist_ts/tstest.plugins.js +7 -4
- package/dist_ts_tapbundle_serverside/classes.tapnodetools.d.ts +30 -0
- package/dist_ts_tapbundle_serverside/classes.tapnodetools.js +100 -3
- package/dist_ts_tapbundle_serverside/classes.testfileprovider.js +3 -3
- package/dist_ts_tapbundle_serverside/plugins.d.ts +4 -1
- package/dist_ts_tapbundle_serverside/plugins.js +5 -2
- package/npmextra.json +1 -1
- package/package.json +17 -16
- package/readme.hints.md +1 -1
- package/readme.md +329 -860
- package/ts/00_commitinfo_data.ts +2 -2
- package/ts/tstest.classes.migration.ts +3 -6
- package/ts/tstest.classes.runtime.bun.ts +4 -4
- package/ts/tstest.classes.runtime.chromium.ts +8 -12
- package/ts/tstest.classes.runtime.deno.ts +22 -26
- package/ts/tstest.classes.runtime.docker.ts +1 -1
- package/ts/tstest.classes.runtime.node.ts +4 -4
- package/ts/tstest.classes.tap.parser.ts +5 -7
- package/ts/tstest.classes.testdirectory.ts +19 -20
- package/ts/tstest.classes.testfile.directives.ts +226 -0
- package/ts/tstest.classes.tstest.ts +60 -43
- package/ts/tstest.plugins.ts +8 -3
|
@@ -19,6 +19,14 @@ import { DenoRuntimeAdapter } from './tstest.classes.runtime.deno.js';
|
|
|
19
19
|
import { BunRuntimeAdapter } from './tstest.classes.runtime.bun.js';
|
|
20
20
|
import { DockerRuntimeAdapter } from './tstest.classes.runtime.docker.js';
|
|
21
21
|
|
|
22
|
+
// Test file directives
|
|
23
|
+
import {
|
|
24
|
+
parseDirectivesFromFile,
|
|
25
|
+
mergeDirectives,
|
|
26
|
+
directivesToRuntimeOptions,
|
|
27
|
+
hasDirectives,
|
|
28
|
+
} from './tstest.classes.testfile.directives.js';
|
|
29
|
+
|
|
22
30
|
export class TsTest {
|
|
23
31
|
public testDir: TestDirectory;
|
|
24
32
|
public executionMode: TestExecutionMode;
|
|
@@ -132,7 +140,7 @@ export class TsTest {
|
|
|
132
140
|
}
|
|
133
141
|
|
|
134
142
|
public async runWatch(ignorePatterns: string[] = []) {
|
|
135
|
-
const
|
|
143
|
+
const smartwatchInstance = new plugins.smartwatch.Smartwatch([this.testDir.cwd]);
|
|
136
144
|
|
|
137
145
|
console.clear();
|
|
138
146
|
this.logger.watchModeStart();
|
|
@@ -155,12 +163,12 @@ export class TsTest {
|
|
|
155
163
|
};
|
|
156
164
|
|
|
157
165
|
// Start watching before subscribing to events
|
|
158
|
-
await
|
|
159
|
-
|
|
166
|
+
await smartwatchInstance.start();
|
|
167
|
+
|
|
160
168
|
// Subscribe to file change events
|
|
161
|
-
const changeObservable = await
|
|
162
|
-
const addObservable = await
|
|
163
|
-
const unlinkObservable = await
|
|
169
|
+
const changeObservable = await smartwatchInstance.getObservableFor('change');
|
|
170
|
+
const addObservable = await smartwatchInstance.getObservableFor('add');
|
|
171
|
+
const unlinkObservable = await smartwatchInstance.getObservableFor('unlink');
|
|
164
172
|
|
|
165
173
|
const handleFileChange = (changedPath: string) => {
|
|
166
174
|
// Skip if path matches ignore patterns
|
|
@@ -194,7 +202,7 @@ export class TsTest {
|
|
|
194
202
|
// Handle Ctrl+C to exit gracefully
|
|
195
203
|
process.on('SIGINT', async () => {
|
|
196
204
|
this.logger.watchModeStop();
|
|
197
|
-
await
|
|
205
|
+
await smartwatchInstance.stop();
|
|
198
206
|
process.exit(0);
|
|
199
207
|
});
|
|
200
208
|
|
|
@@ -256,18 +264,32 @@ export class TsTest {
|
|
|
256
264
|
return;
|
|
257
265
|
}
|
|
258
266
|
|
|
267
|
+
// Parse directives from the test file (e.g., // tstest:deno:allowAll)
|
|
268
|
+
let directives = await parseDirectivesFromFile(fileNameArg);
|
|
269
|
+
|
|
270
|
+
// Also check for directives in 00init.ts
|
|
271
|
+
const testDir = plugins.path.dirname(fileNameArg);
|
|
272
|
+
const initFile = plugins.path.join(testDir, '00init.ts');
|
|
273
|
+
const initFileExists = await plugins.smartfsInstance.file(initFile).exists();
|
|
274
|
+
if (initFileExists) {
|
|
275
|
+
const initDirectives = await parseDirectivesFromFile(initFile);
|
|
276
|
+
directives = mergeDirectives(initDirectives, directives);
|
|
277
|
+
}
|
|
278
|
+
|
|
259
279
|
// Execute tests for each runtime
|
|
260
280
|
if (adapters.length === 1) {
|
|
261
281
|
// Single runtime - no sections needed
|
|
262
282
|
const adapter = adapters[0];
|
|
263
|
-
const
|
|
283
|
+
const options = hasDirectives(directives) ? directivesToRuntimeOptions(directives, adapter.id) : undefined;
|
|
284
|
+
const tapParser = await adapter.run(fileNameArg, fileIndex, totalFiles, options);
|
|
264
285
|
tapCombinator.addTapParser(tapParser);
|
|
265
286
|
} else {
|
|
266
287
|
// Multiple runtimes - use sections
|
|
267
288
|
for (let i = 0; i < adapters.length; i++) {
|
|
268
289
|
const adapter = adapters[i];
|
|
269
290
|
this.logger.sectionStart(`Part ${i + 1}: ${adapter.displayName}`);
|
|
270
|
-
const
|
|
291
|
+
const options = hasDirectives(directives) ? directivesToRuntimeOptions(directives, adapter.id) : undefined;
|
|
292
|
+
const tapParser = await adapter.run(fileNameArg, fileIndex, totalFiles, options);
|
|
271
293
|
tapCombinator.addTapParser(tapParser);
|
|
272
294
|
this.logger.sectionEnd();
|
|
273
295
|
}
|
|
@@ -316,8 +338,8 @@ export class TsTest {
|
|
|
316
338
|
const initFile = plugins.path.join(testDir, '00init.ts');
|
|
317
339
|
let runCommand = `tsrun ${fileNameArg}${tsrunOptions}`;
|
|
318
340
|
|
|
319
|
-
const initFileExists = await plugins.
|
|
320
|
-
|
|
341
|
+
const initFileExists = await plugins.smartfsInstance.file(initFile).exists();
|
|
342
|
+
|
|
321
343
|
// If 00init.ts exists, run it first
|
|
322
344
|
if (initFileExists) {
|
|
323
345
|
// Create a temporary loader file that imports both 00init.ts and the test file
|
|
@@ -328,7 +350,7 @@ import '${absoluteInitFile.replace(/\\/g, '/')}';
|
|
|
328
350
|
import '${absoluteTestFile.replace(/\\/g, '/')}';
|
|
329
351
|
`;
|
|
330
352
|
const loaderPath = plugins.path.join(testDir, `.loader_${plugins.path.basename(fileNameArg)}`);
|
|
331
|
-
await plugins.
|
|
353
|
+
await plugins.smartfsInstance.file(loaderPath).write(loaderContent);
|
|
332
354
|
runCommand = `tsrun ${loaderPath}${tsrunOptions}`;
|
|
333
355
|
}
|
|
334
356
|
|
|
@@ -339,14 +361,14 @@ import '${absoluteTestFile.replace(/\\/g, '/')}';
|
|
|
339
361
|
const loaderPath = plugins.path.join(testDir, `.loader_${plugins.path.basename(fileNameArg)}`);
|
|
340
362
|
const cleanup = () => {
|
|
341
363
|
try {
|
|
342
|
-
if (plugins.
|
|
343
|
-
plugins.
|
|
364
|
+
if (plugins.fs.existsSync(loaderPath)) {
|
|
365
|
+
plugins.fs.rmSync(loaderPath, { force: true });
|
|
344
366
|
}
|
|
345
367
|
} catch (e) {
|
|
346
368
|
// Ignore cleanup errors
|
|
347
369
|
}
|
|
348
370
|
};
|
|
349
|
-
|
|
371
|
+
|
|
350
372
|
execResultStreaming.childProcess.on('exit', cleanup);
|
|
351
373
|
execResultStreaming.childProcess.on('error', cleanup);
|
|
352
374
|
}
|
|
@@ -445,7 +467,8 @@ import '${absoluteTestFile.replace(/\\/g, '/')}';
|
|
|
445
467
|
const bundleFilePath = plugins.path.join(tsbundleCacheDirPath, bundleFileName);
|
|
446
468
|
|
|
447
469
|
// lets bundle the test
|
|
448
|
-
await plugins.
|
|
470
|
+
try { await plugins.smartfsInstance.directory(tsbundleCacheDirPath).recursive().delete(); } catch (e) { /* may not exist */ }
|
|
471
|
+
await plugins.smartfsInstance.directory(tsbundleCacheDirPath).recursive().create();
|
|
449
472
|
await this.tsbundleInstance.build(process.cwd(), fileNameArg, bundleFilePath, {
|
|
450
473
|
bundler: 'esbuild',
|
|
451
474
|
});
|
|
@@ -454,15 +477,13 @@ import '${absoluteTestFile.replace(/\\/g, '/')}';
|
|
|
454
477
|
const { httpPort, wsPort } = await this.findFreePorts();
|
|
455
478
|
|
|
456
479
|
// lets create a server
|
|
457
|
-
const server = new plugins.typedserver.
|
|
480
|
+
const server = new plugins.typedserver.TypedServer({
|
|
458
481
|
cors: true,
|
|
459
482
|
port: httpPort,
|
|
483
|
+
serveDir: tsbundleCacheDirPath,
|
|
460
484
|
});
|
|
461
|
-
server.addRoute(
|
|
462
|
-
|
|
463
|
-
new plugins.typedserver.servertools.Handler('GET', async (_req, res) => {
|
|
464
|
-
res.type('.html');
|
|
465
|
-
res.write(`
|
|
485
|
+
server.addRoute('/test', 'GET', async () => {
|
|
486
|
+
return new Response(`
|
|
466
487
|
<html>
|
|
467
488
|
<head>
|
|
468
489
|
<script>
|
|
@@ -472,11 +493,8 @@ import '${absoluteTestFile.replace(/\\/g, '/')}';
|
|
|
472
493
|
</head>
|
|
473
494
|
<body></body>
|
|
474
495
|
</html>
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
})
|
|
478
|
-
);
|
|
479
|
-
server.addRoute('/*splat', new plugins.typedserver.servertools.HandlerStatic(tsbundleCacheDirPath));
|
|
496
|
+
`, { headers: { 'Content-Type': 'text/html' } });
|
|
497
|
+
});
|
|
480
498
|
await server.start();
|
|
481
499
|
|
|
482
500
|
// lets handle realtime comms
|
|
@@ -640,34 +658,33 @@ import '${absoluteTestFile.replace(/\\/g, '/')}';
|
|
|
640
658
|
|
|
641
659
|
try {
|
|
642
660
|
// Delete 00err and 00diff directories if they exist
|
|
643
|
-
if (plugins.
|
|
644
|
-
plugins.
|
|
661
|
+
if (plugins.fs.existsSync(errDir) && plugins.fs.statSync(errDir).isDirectory()) {
|
|
662
|
+
plugins.fs.rmSync(errDir, { recursive: true, force: true });
|
|
645
663
|
}
|
|
646
|
-
if (plugins.
|
|
647
|
-
plugins.
|
|
664
|
+
if (plugins.fs.existsSync(diffDir) && plugins.fs.statSync(diffDir).isDirectory()) {
|
|
665
|
+
plugins.fs.rmSync(diffDir, { recursive: true, force: true });
|
|
648
666
|
}
|
|
649
|
-
|
|
667
|
+
|
|
650
668
|
// Get all .log files in log directory (not in subdirectories)
|
|
651
|
-
const
|
|
652
|
-
const logFiles =
|
|
653
|
-
|
|
669
|
+
const entries = await plugins.smartfsInstance.directory(logDir).filter('*.log').list();
|
|
670
|
+
const logFiles = entries.filter((entry) => entry.isFile).map((entry) => entry.name);
|
|
671
|
+
|
|
654
672
|
if (logFiles.length === 0) {
|
|
655
673
|
return;
|
|
656
674
|
}
|
|
657
|
-
|
|
675
|
+
|
|
658
676
|
// Ensure previous directory exists
|
|
659
|
-
await plugins.
|
|
660
|
-
|
|
677
|
+
await plugins.smartfsInstance.directory(previousDir).recursive().create();
|
|
678
|
+
|
|
661
679
|
// Move each log file to previous directory
|
|
662
|
-
for (const
|
|
663
|
-
const filename = plugins.path.basename(file);
|
|
680
|
+
for (const filename of logFiles) {
|
|
664
681
|
const sourcePath = plugins.path.join(logDir, filename);
|
|
665
682
|
const destPath = plugins.path.join(previousDir, filename);
|
|
666
|
-
|
|
683
|
+
|
|
667
684
|
try {
|
|
668
685
|
// Copy file to new location and remove original
|
|
669
|
-
await plugins.
|
|
670
|
-
await plugins.
|
|
686
|
+
await plugins.smartfsInstance.file(sourcePath).copy(destPath);
|
|
687
|
+
await plugins.smartfsInstance.file(sourcePath).delete();
|
|
671
688
|
} catch (error) {
|
|
672
689
|
// Silently continue if a file can't be moved
|
|
673
690
|
}
|
package/ts/tstest.plugins.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// node native
|
|
2
|
+
import * as fs from 'fs';
|
|
2
3
|
import * as path from 'path';
|
|
3
4
|
|
|
4
|
-
export { path };
|
|
5
|
+
export { fs, path };
|
|
5
6
|
|
|
6
7
|
// @apiglobal scope
|
|
7
8
|
import * as typedserver from '@api.global/typedserver';
|
|
@@ -13,25 +14,29 @@ export {
|
|
|
13
14
|
// @push.rocks scope
|
|
14
15
|
import * as consolecolor from '@push.rocks/consolecolor';
|
|
15
16
|
import * as smartbrowser from '@push.rocks/smartbrowser';
|
|
16
|
-
import * as smartchok from '@push.rocks/smartchok';
|
|
17
17
|
import * as smartdelay from '@push.rocks/smartdelay';
|
|
18
18
|
import * as smartfile from '@push.rocks/smartfile';
|
|
19
|
+
import * as smartfs from '@push.rocks/smartfs';
|
|
20
|
+
const smartfsInstance = new smartfs.SmartFs(new smartfs.SmartFsProviderNode());
|
|
19
21
|
import * as smartlog from '@push.rocks/smartlog';
|
|
20
22
|
import * as smartnetwork from '@push.rocks/smartnetwork';
|
|
21
23
|
import * as smartpromise from '@push.rocks/smartpromise';
|
|
22
24
|
import * as smartshell from '@push.rocks/smartshell';
|
|
25
|
+
import * as smartwatch from '@push.rocks/smartwatch';
|
|
23
26
|
import * as tapbundle from '../dist_ts_tapbundle/index.js';
|
|
24
27
|
|
|
25
28
|
export {
|
|
26
29
|
consolecolor,
|
|
27
30
|
smartbrowser,
|
|
28
|
-
smartchok,
|
|
29
31
|
smartdelay,
|
|
30
32
|
smartfile,
|
|
33
|
+
smartfs,
|
|
34
|
+
smartfsInstance,
|
|
31
35
|
smartlog,
|
|
32
36
|
smartnetwork,
|
|
33
37
|
smartpromise,
|
|
34
38
|
smartshell,
|
|
39
|
+
smartwatch,
|
|
35
40
|
tapbundle,
|
|
36
41
|
};
|
|
37
42
|
|