@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.
Files changed (37) hide show
  1. package/dist_ts/00_commitinfo_data.js +3 -3
  2. package/dist_ts/tstest.classes.migration.js +4 -4
  3. package/dist_ts/tstest.classes.runtime.bun.js +5 -5
  4. package/dist_ts/tstest.classes.runtime.chromium.js +12 -10
  5. package/dist_ts/tstest.classes.runtime.deno.d.ts +4 -0
  6. package/dist_ts/tstest.classes.runtime.deno.js +22 -27
  7. package/dist_ts/tstest.classes.runtime.docker.js +2 -2
  8. package/dist_ts/tstest.classes.runtime.node.js +5 -5
  9. package/dist_ts/tstest.classes.tap.parser.js +6 -7
  10. package/dist_ts/tstest.classes.testdirectory.d.ts +1 -1
  11. package/dist_ts/tstest.classes.testdirectory.js +11 -12
  12. package/dist_ts/tstest.classes.testfile.directives.d.ts +38 -0
  13. package/dist_ts/tstest.classes.testfile.directives.js +191 -0
  14. package/dist_ts/tstest.classes.tstest.js +48 -33
  15. package/dist_ts/tstest.plugins.d.ts +6 -3
  16. package/dist_ts/tstest.plugins.js +7 -4
  17. package/dist_ts_tapbundle_serverside/classes.tapnodetools.d.ts +30 -0
  18. package/dist_ts_tapbundle_serverside/classes.tapnodetools.js +100 -3
  19. package/dist_ts_tapbundle_serverside/classes.testfileprovider.js +3 -3
  20. package/dist_ts_tapbundle_serverside/plugins.d.ts +4 -1
  21. package/dist_ts_tapbundle_serverside/plugins.js +5 -2
  22. package/npmextra.json +1 -1
  23. package/package.json +17 -16
  24. package/readme.hints.md +1 -1
  25. package/readme.md +329 -860
  26. package/ts/00_commitinfo_data.ts +2 -2
  27. package/ts/tstest.classes.migration.ts +3 -6
  28. package/ts/tstest.classes.runtime.bun.ts +4 -4
  29. package/ts/tstest.classes.runtime.chromium.ts +8 -12
  30. package/ts/tstest.classes.runtime.deno.ts +22 -26
  31. package/ts/tstest.classes.runtime.docker.ts +1 -1
  32. package/ts/tstest.classes.runtime.node.ts +4 -4
  33. package/ts/tstest.classes.tap.parser.ts +5 -7
  34. package/ts/tstest.classes.testdirectory.ts +19 -20
  35. package/ts/tstest.classes.testfile.directives.ts +226 -0
  36. package/ts/tstest.classes.tstest.ts +60 -43
  37. 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 smartchokInstance = new plugins.smartchok.Smartchok([this.testDir.cwd]);
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 smartchokInstance.start();
159
-
166
+ await smartwatchInstance.start();
167
+
160
168
  // Subscribe to file change events
161
- const changeObservable = await smartchokInstance.getObservableFor('change');
162
- const addObservable = await smartchokInstance.getObservableFor('add');
163
- const unlinkObservable = await smartchokInstance.getObservableFor('unlink');
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 smartchokInstance.stop();
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 tapParser = await adapter.run(fileNameArg, fileIndex, totalFiles);
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 tapParser = await adapter.run(fileNameArg, fileIndex, totalFiles);
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.smartfile.fs.fileExists(initFile);
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.smartfile.memory.toFs(loaderContent, loaderPath);
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.smartfile.fs.fileExistsSync(loaderPath)) {
343
- plugins.smartfile.fs.removeSync(loaderPath);
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.smartfile.fs.ensureEmptyDir(tsbundleCacheDirPath);
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.servertools.Server({
480
+ const server = new plugins.typedserver.TypedServer({
458
481
  cors: true,
459
482
  port: httpPort,
483
+ serveDir: tsbundleCacheDirPath,
460
484
  });
461
- server.addRoute(
462
- '/test',
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
- res.end();
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.smartfile.fs.isDirectorySync(errDir)) {
644
- plugins.smartfile.fs.removeSync(errDir);
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.smartfile.fs.isDirectorySync(diffDir)) {
647
- plugins.smartfile.fs.removeSync(diffDir);
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 files = await plugins.smartfile.fs.listFileTree(logDir, '*.log');
652
- const logFiles = files.filter((file: string) => !file.includes('/'));
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.smartfile.fs.ensureDir(previousDir);
660
-
677
+ await plugins.smartfsInstance.directory(previousDir).recursive().create();
678
+
661
679
  // Move each log file to previous directory
662
- for (const file of logFiles) {
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.smartfile.fs.copy(sourcePath, destPath);
670
- await plugins.smartfile.fs.remove(sourcePath);
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
  }
@@ -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