testeranto 0.114.1 → 0.121.1

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 (87) hide show
  1. package/README.md +6 -1
  2. package/bundle.js +1 -1
  3. package/dist/common/Init.js +55 -61
  4. package/dist/common/PM/base.js +233 -0
  5. package/dist/common/PM/main.js +217 -434
  6. package/dist/common/build.js +113 -92
  7. package/dist/common/defaultConfig.js +2 -2
  8. package/dist/common/esbuildConfigs/index.js +1 -1
  9. package/dist/common/esbuildConfigs/inputFilesPlugin.js +7 -3
  10. package/dist/common/esbuildConfigs/node.js +5 -3
  11. package/dist/common/esbuildConfigs/web.js +3 -3
  12. package/dist/common/init-docs.js +2 -46
  13. package/dist/common/lib/abstractBase.js +60 -54
  14. package/dist/common/lib/basebuilder.js +7 -8
  15. package/dist/common/lib/classBuilder.js +8 -5
  16. package/dist/common/lib/core.js +6 -18
  17. package/dist/common/lib/index.js +6 -1
  18. package/dist/common/run.js +10 -2
  19. package/dist/common/tsconfig.common.tsbuildinfo +1 -1
  20. package/dist/common/utils.js +9 -21
  21. package/dist/module/Init.js +55 -61
  22. package/dist/module/PM/base.js +226 -0
  23. package/dist/module/PM/main.js +218 -435
  24. package/dist/module/Project.js +117 -0
  25. package/dist/module/TestReport.js +13 -4
  26. package/dist/module/build.js +113 -92
  27. package/dist/module/defaultConfig.js +2 -2
  28. package/dist/module/esbuildConfigs/index.js +1 -1
  29. package/dist/module/esbuildConfigs/inputFilesPlugin.js +7 -3
  30. package/dist/module/esbuildConfigs/node.js +5 -3
  31. package/dist/module/esbuildConfigs/web.js +3 -3
  32. package/dist/module/init-docs.js +2 -13
  33. package/dist/module/lib/abstractBase.js +60 -54
  34. package/dist/module/lib/basebuilder.js +7 -8
  35. package/dist/module/lib/classBuilder.js +8 -5
  36. package/dist/module/lib/core.js +6 -18
  37. package/dist/module/lib/index.js +6 -1
  38. package/dist/module/run.js +10 -2
  39. package/dist/module/tsconfig.module.tsbuildinfo +1 -1
  40. package/dist/module/utils.js +8 -17
  41. package/dist/prebuild/Project.css +11367 -0
  42. package/dist/prebuild/Project.js +24640 -0
  43. package/dist/prebuild/ReportClient.js +1 -1
  44. package/dist/prebuild/TestReport.js +9 -11
  45. package/dist/prebuild/build.mjs +142 -81
  46. package/dist/prebuild/init-docs.mjs +28 -83
  47. package/dist/prebuild/run.mjs +618 -537
  48. package/dist/tsconfig.tsbuildinfo +1 -1
  49. package/dist/types/Init.d.ts +1 -1
  50. package/dist/types/PM/base.d.ts +38 -0
  51. package/dist/types/PM/main.d.ts +20 -44
  52. package/dist/types/esbuildConfigs/inputFilesPlugin.d.ts +1 -1
  53. package/dist/types/esbuildConfigs/node.d.ts +1 -1
  54. package/dist/types/esbuildConfigs/web.d.ts +1 -1
  55. package/dist/types/lib/abstractBase.d.ts +19 -11
  56. package/dist/types/lib/basebuilder.d.ts +1 -2
  57. package/dist/types/lib/index.d.ts +3 -3
  58. package/dist/types/lib/types.d.ts +2 -5
  59. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  60. package/dist/types/utils.d.ts +4 -7
  61. package/package.json +6 -5
  62. package/src/Init.ts +60 -68
  63. package/src/PM/base.ts +301 -0
  64. package/src/PM/main.ts +276 -567
  65. package/src/Project.tsx +197 -0
  66. package/src/ReportClient.tsx +1 -1
  67. package/src/TestReport.tsx +30 -15
  68. package/src/build.ts +140 -104
  69. package/src/defaultConfig.ts +2 -2
  70. package/src/esbuildConfigs/index.ts +1 -1
  71. package/src/esbuildConfigs/inputFilesPlugin.ts +7 -6
  72. package/src/esbuildConfigs/node.ts +5 -3
  73. package/src/esbuildConfigs/web.ts +4 -3
  74. package/src/init-docs.ts +2 -15
  75. package/src/lib/abstractBase.ts +113 -93
  76. package/src/lib/basebuilder.ts +8 -9
  77. package/src/lib/classBuilder.ts +11 -10
  78. package/src/lib/core.ts +15 -27
  79. package/src/lib/index.ts +13 -6
  80. package/src/lib/types.ts +3 -8
  81. package/src/run.ts +21 -5
  82. package/src/utils.ts +27 -39
  83. package/tsc.log +12 -23
  84. package/dist/common/puppeteerConfiger.js +0 -24
  85. package/dist/module/puppeteerConfiger.js +0 -19
  86. package/dist/types/puppeteerConfiger.d.ts +0 -4
  87. package/src/puppeteerConfiger.ts +0 -26
@@ -6,16 +6,13 @@ import ansiC from "ansi-colors";
6
6
  import crypto from "node:crypto";
7
7
  import { ESLint } from "eslint";
8
8
  import tsc from "tsc-prog";
9
- import { lintPather, tscPather } from "../utils";
10
- import { PM } from "./index.js";
9
+ import { lintPather, promptPather, tscPather } from "../utils";
10
+ import { PM_Base } from "./base.js";
11
11
  const eslint = new ESLint();
12
12
  const formatter = await eslint.loadFormatter("./node_modules/testeranto/dist/prebuild/esbuildConfigs/eslint-formatter-testeranto.mjs");
13
13
  const changes = {};
14
14
  const fileHashes = {};
15
- const fileStreams3 = [];
16
- const fPaths = [];
17
15
  const files = {};
18
- const recorders = {};
19
16
  const screenshots = {};
20
17
  async function fileHash(filePath, algorithm = "md5") {
21
18
  return new Promise((resolve, reject) => {
@@ -33,23 +30,6 @@ async function fileHash(filePath, algorithm = "md5") {
33
30
  });
34
31
  });
35
32
  }
36
- const getRunnables = (tests, payload = {
37
- nodeEntryPoints: {},
38
- webEntryPoints: {},
39
- }) => {
40
- return tests.reduce((pt, cv, cndx, cry) => {
41
- if (cv[1] === "node") {
42
- pt.nodeEntryPoints[cv[0]] = path.resolve(`./docs/node/${cv[0].split(".").slice(0, -1).concat("mjs").join(".")}`);
43
- }
44
- else if (cv[1] === "web") {
45
- pt.webEntryPoints[cv[0]] = path.resolve(`./docs/web/${cv[0].split(".").slice(0, -1).concat("mjs").join(".")}`);
46
- }
47
- if (cv[3].length) {
48
- getRunnables(cv[3], payload);
49
- }
50
- return pt;
51
- }, payload);
52
- };
53
33
  const statusMessagePretty = (failures, test) => {
54
34
  if (failures === 0) {
55
35
  console.log(ansiC.green(ansiC.inverse(`> ${test} completed successfully`)));
@@ -84,27 +64,51 @@ function isValidUrl(string) {
84
64
  return false;
85
65
  }
86
66
  }
87
- export class PM_Main extends PM {
88
- constructor(configs) {
89
- super();
90
- this.shutdownMode = false;
67
+ export class PM_Main extends PM_Base {
68
+ constructor(configs, name, mode) {
69
+ super(configs);
91
70
  this.bigBoard = {};
92
71
  this.stop = () => {
93
72
  console.log(ansiC.inverse("Testeranto-Run is shutting down gracefully..."));
94
- this.mode = "PROD";
73
+ this.mode = "once";
95
74
  this.nodeMetafileWatcher.close();
96
75
  this.webMetafileWatcher.close();
97
76
  this.checkForShutdown();
98
77
  };
78
+ this.getRunnables = (tests, payload = {
79
+ nodeEntryPoints: {},
80
+ webEntryPoints: {},
81
+ }) => {
82
+ return tests.reduce((pt, cv, cndx, cry) => {
83
+ if (cv[1] === "node") {
84
+ pt.nodeEntryPoints[cv[0]] = path.resolve(`./testeranto/bundles/node/${this.name}/${cv[0]
85
+ .split(".")
86
+ .slice(0, -1)
87
+ .concat("mjs")
88
+ .join(".")}`);
89
+ }
90
+ else if (cv[1] === "web") {
91
+ pt.webEntryPoints[cv[0]] = path.resolve(`./testeranto/bundles/web/${this.name}/${cv[0]
92
+ .split(".")
93
+ .slice(0, -1)
94
+ .concat("mjs")
95
+ .join(".")}`);
96
+ }
97
+ if (cv[3].length) {
98
+ this.getRunnables(cv[3], payload);
99
+ }
100
+ return pt;
101
+ }, payload);
102
+ };
99
103
  this.tscCheck = async ({ entrypoint, addableFiles, platform, }) => {
100
104
  console.log(ansiC.green(ansiC.inverse(`tsc < ${entrypoint}`)));
101
- this.bigBoard[entrypoint].typeErrors = "?";
105
+ this.typeCheckIsRunning(entrypoint);
102
106
  const program = tsc.createProgramFromConfig({
103
107
  basePath: process.cwd(), // always required, used for relative paths
104
108
  configFilePath: "tsconfig.json", // config to inherit from (optional)
105
109
  compilerOptions: {
106
110
  rootDir: "src",
107
- outDir: tscPather(entrypoint, platform),
111
+ outDir: tscPather(entrypoint, platform, this.name),
108
112
  // declaration: true,
109
113
  // skipLibCheck: true,
110
114
  noEmit: true,
@@ -112,32 +116,25 @@ export class PM_Main extends PM {
112
116
  include: addableFiles, //["src/**/*"],
113
117
  // exclude: ["**/*.test.ts", "**/*.spec.ts"],
114
118
  });
115
- const tscPath = tscPather(entrypoint, platform);
119
+ const tscPath = tscPather(entrypoint, platform, this.name);
116
120
  let allDiagnostics = program.getSemanticDiagnostics();
117
- const d = [];
121
+ const results = [];
118
122
  allDiagnostics.forEach((diagnostic) => {
119
123
  if (diagnostic.file) {
120
124
  let { line, character } = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
121
125
  let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
122
- d.push(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
126
+ results.push(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
123
127
  }
124
128
  else {
125
- d.push(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"));
129
+ results.push(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"));
126
130
  }
127
131
  });
128
- fs.writeFileSync(tscPath, d.join("\n"));
129
- this.bigBoard[entrypoint].typeErrors = d.length;
130
- if (this.shutdownMode) {
131
- this.checkForShutdown();
132
- }
133
- // fs.writeFileSync(
134
- // tscExitCodePather(entrypoint, platform),
135
- // d.length.toString()
136
- // );
132
+ fs.writeFileSync(tscPath, results.join("\n"));
133
+ this.typeCheckIsNowDone(entrypoint, results.length);
137
134
  };
138
135
  this.eslintCheck = async (entrypoint, platform, addableFiles) => {
139
- this.bigBoard[entrypoint].staticErrors = "?";
140
136
  console.log(ansiC.green(ansiC.inverse(`eslint < ${entrypoint}`)));
137
+ this.lintIsRunning(entrypoint);
141
138
  const results = (await eslint.lintFiles(addableFiles))
142
139
  .filter((r) => r.messages.length)
143
140
  .filter((r) => {
@@ -147,21 +144,14 @@ export class PM_Main extends PM {
147
144
  delete r.source;
148
145
  return r;
149
146
  });
150
- fs.writeFileSync(lintPather(entrypoint, platform), await formatter.format(results));
151
- this.bigBoard[entrypoint].staticErrors = results.length;
152
- if (this.shutdownMode) {
153
- this.checkForShutdown();
154
- }
155
- // fs.writeFileSync(
156
- // lintExitCodePather(entrypoint, platform),
157
- // results.length.toString()
158
- // );
147
+ fs.writeFileSync(lintPather(entrypoint, platform, this.name), await formatter.format(results));
148
+ this.lintIsNowDone(entrypoint, results.length);
159
149
  };
160
150
  this.makePrompt = async (entryPoint, addableFiles, platform) => {
161
151
  this.bigBoard[entryPoint].prompt = "?";
162
- const promptPath = path.join("./docs/", platform, entryPoint.split(".").slice(0, -1).join("."), `prompt.txt`);
163
- const testPaths = path.join("./docs/", platform, entryPoint.split(".").slice(0, -1).join("."), `tests.json`);
164
- const featuresPath = path.join("./docs/", platform, entryPoint.split(".").slice(0, -1).join("."), `featurePrompt.txt`);
152
+ const promptPath = promptPather(entryPoint, platform, this.name);
153
+ const testPaths = path.join("testeranto", "reports", this.name, platform, entryPoint.split(".").slice(0, -1).join("."), `tests.json`);
154
+ const featuresPath = path.join("testeranto", "reports", this.name, platform, entryPoint.split(".").slice(0, -1).join("."), `featurePrompt.txt`);
165
155
  fs.writeFileSync(promptPath, `
166
156
  ${addableFiles
167
157
  .map((x) => {
@@ -169,55 +159,93 @@ ${addableFiles
169
159
  })
170
160
  .join("\n")}
171
161
 
172
- /read ${lintPather(entryPoint, platform)}
173
- /read ${tscPather(entryPoint, platform)}
162
+ /read ${lintPather(entryPoint, platform, this.name)}
163
+ /read ${tscPather(entryPoint, platform, this.name)}
174
164
  /read ${testPaths}
175
165
 
176
166
  /load ${featuresPath}
177
167
 
178
- /code Fix the failing tests described in ${testPaths}. Correct any type signature errors described in the files ${tscPather(entryPoint, platform)}. Implement any method which throws "Function not implemented. Resolve the lint errors described in ${lintPather(entryPoint, platform)}"
168
+ /code Fix the failing tests described in ${testPaths}. Correct any type signature errors described in the files ${tscPather(entryPoint, platform, this.name)}. Implement any method which throws "Function not implemented. Resolve the lint errors described in ${lintPather(entryPoint, platform, this.name)}"
179
169
  `);
180
- this.bigBoard[entryPoint].prompt = `aider --model deepseek/deepseek-chat --load docs/${platform}/${entryPoint
170
+ this.bigBoard[entryPoint].prompt = `aider --model deepseek/deepseek-chat --load testeranto/${this.name}/reports/${platform}/${entryPoint
181
171
  .split(".")
182
172
  .slice(0, -1)
183
173
  .join(".")}/prompt.txt`;
184
- if (this.shutdownMode) {
185
- this.checkForShutdown();
186
- }
174
+ this.checkForShutdown();
187
175
  };
188
176
  this.checkForShutdown = () => {
189
- const anyRunning = Object.values(this.bigBoard).filter((x) => x.prompt === "?").length +
190
- Object.values(this.bigBoard).filter((x) => x.runTimeError === "?")
191
- .length +
192
- Object.values(this.bigBoard).filter((x) => x.staticErrors === "?")
193
- .length +
194
- Object.values(this.bigBoard).filter((x) => x.typeErrors === "?")
195
- .length >
196
- 0;
197
- if (anyRunning) {
198
- console.log(ansiC.inverse("Shutting down. Please wait"));
199
- }
200
- else {
177
+ this.writeBigBoard();
178
+ if (this.mode === "dev")
179
+ return;
180
+ let inflight = false;
181
+ Object.keys(this.bigBoard).forEach((k) => {
182
+ if (this.bigBoard[k].prompt === "?") {
183
+ console.log(ansiC.blue(ansiC.inverse(`🕕 prompt ${k}`)));
184
+ inflight = true;
185
+ }
186
+ });
187
+ Object.keys(this.bigBoard).forEach((k) => {
188
+ if (this.bigBoard[k].runTimeError === "?") {
189
+ console.log(ansiC.blue(ansiC.inverse(`🕕 runTimeError ${k}`)));
190
+ inflight = true;
191
+ }
192
+ });
193
+ Object.keys(this.bigBoard).forEach((k) => {
194
+ if (this.bigBoard[k].staticErrors === "?") {
195
+ console.log(ansiC.blue(ansiC.inverse(`🕕 staticErrors ${k}`)));
196
+ inflight = true;
197
+ }
198
+ });
199
+ Object.keys(this.bigBoard).forEach((k) => {
200
+ if (this.bigBoard[k].typeErrors === "?") {
201
+ console.log(ansiC.blue(ansiC.inverse(`🕕 typeErrors ${k}`)));
202
+ inflight = true;
203
+ }
204
+ });
205
+ this.writeBigBoard();
206
+ if (!inflight) {
201
207
  this.browser.disconnect().then(() => {
202
- fs.writeFileSync("docs/summary.json", JSON.stringify(this.bigBoard, null, 2));
203
- console.log(ansiC.inverse("Goodbye"));
208
+ console.log(ansiC.inverse(`${this.name} has been tested. Goodbye.`));
204
209
  process.exit();
205
210
  });
206
211
  }
207
212
  };
208
- this.testIsNowRunning = (src) => {
209
- this.bigBoard[src].status = "running";
213
+ this.typeCheckIsRunning = (src) => {
214
+ this.bigBoard[src].typeErrors = "?";
210
215
  };
211
- this.testIsNowDone = (src) => {
212
- this.bigBoard[src].status = "waiting";
213
- if (this.shutdownMode) {
214
- this.checkForShutdown();
215
- }
216
+ this.typeCheckIsNowDone = (src, failures) => {
217
+ this.bigBoard[src].typeErrors = failures;
218
+ this.writeBigBoard();
219
+ this.checkForShutdown();
220
+ };
221
+ this.lintIsRunning = (src) => {
222
+ this.bigBoard[src].staticErrors = "?";
223
+ this.writeBigBoard();
224
+ };
225
+ this.lintIsNowDone = (src, failures) => {
226
+ this.bigBoard[src].staticErrors = failures;
227
+ this.writeBigBoard();
228
+ this.checkForShutdown();
229
+ };
230
+ this.bddTestIsRunning = (src) => {
231
+ this.bigBoard[src].runTimeError = "?";
232
+ this.writeBigBoard();
233
+ };
234
+ this.bddTestIsNowDone = (src, failures) => {
235
+ this.bigBoard[src].runTimeError = failures;
236
+ this.writeBigBoard();
237
+ this.checkForShutdown();
216
238
  };
217
239
  this.launchNode = async (src, dest) => {
218
- // console.log(ansiC.yellow(`! node, ${src}`));
219
240
  console.log(ansiC.green(ansiC.inverse(`! node, ${src}`)));
220
- this.testIsNowRunning(src);
241
+ this.bddTestIsRunning(src);
242
+ const reportDest = `testeranto/reports/${this.name}/${src
243
+ .split(".")
244
+ .slice(0, -1)
245
+ .join(".")}/node`;
246
+ if (!fs.existsSync(reportDest)) {
247
+ fs.mkdirSync(reportDest, { recursive: true });
248
+ }
221
249
  const destFolder = dest.replace(".mjs", "");
222
250
  let argz = "";
223
251
  const testConfig = this.configs.tests.find((t) => {
@@ -234,7 +262,7 @@ ${addableFiles
234
262
  scheduled: true,
235
263
  name: src,
236
264
  ports: portsToUse,
237
- fs: destFolder,
265
+ fs: reportDest,
238
266
  browserWSEndpoint: this.browser.wsEndpoint(),
239
267
  });
240
268
  }
@@ -290,18 +318,16 @@ ${addableFiles
290
318
  defaultModule
291
319
  .receiveTestResourceConfig(argz)
292
320
  .then(async ({ features, failed }) => {
293
- this.receiveFeatures(features, destFolder, src);
294
- // console.log(`${src} completed with ${failed} errors`);
321
+ this.receiveFeatures(features, destFolder, src, "node");
295
322
  statusMessagePretty(failed, src);
296
- this.receiveExitCode(src, failed);
323
+ this.bddTestIsNowDone(src, failed);
297
324
  })
298
325
  .catch((e) => {
299
326
  console.log(ansiC.red(ansiC.inverse(`${src} errored with: ${e}`)));
300
- // console.log(reset, `${src} errored with`, e);
327
+ this.bddTestIsNowDone(src, -1);
301
328
  })
302
329
  .finally(() => {
303
330
  webSideCares.forEach((webSideCar) => webSideCar.close());
304
- this.testIsNowDone(src);
305
331
  });
306
332
  });
307
333
  });
@@ -327,7 +353,6 @@ ${addableFiles
327
353
  // // console.log(`${i}: ${msg._args[i]}`);
328
354
  // });
329
355
  page.exposeFunction("custom-screenshot", async (ssOpts, testName) => {
330
- // console.log("main.ts browser custom-screenshot", testName);
331
356
  const p = ssOpts.path;
332
357
  const dir = path.dirname(p);
333
358
  fs.mkdirSync(dir, {
@@ -339,10 +364,8 @@ ${addableFiles
339
364
  screenshots[testName] = [];
340
365
  }
341
366
  screenshots[testName].push(sPromise);
342
- // sPromise.then(())
343
367
  await sPromise;
344
368
  return sPromise;
345
- // page.evaluate(`window["screenshot done"]`);
346
369
  });
347
370
  page.exposeFunction("writeFileSync", (fp, contents, testName) => {
348
371
  const dir = path.dirname(fp);
@@ -373,9 +396,6 @@ ${addableFiles
373
396
  });
374
397
  page.exposeFunction("createWriteStream", (fp, testName) => {
375
398
  const f = fs.createWriteStream(fp);
376
- // if (!files[testName]) {
377
- // files[testName] = new Set();
378
- // }
379
399
  files[testName].add(fp);
380
400
  const p = new Promise((res, rej) => {
381
401
  res(fp);
@@ -393,21 +413,11 @@ ${addableFiles
393
413
  page.exposeFunction("end", async (uid) => {
394
414
  return fileStreams2[uid].end();
395
415
  });
396
- // page.exposeFunction("customclose", (p: string, testName: string) => {
397
- // fs.writeFileSync(
398
- // p + "/manifest.json",
399
- // JSON.stringify(Array.from(files[testName]))
400
- // );
401
- // delete files[testName];
402
- // Promise.all(screenshots[testName] || []).then(() => {
403
- // delete screenshots[testName];
404
- // // page.close();
405
- // });
406
- // });
407
416
  return page;
408
417
  })
409
418
  .then(async (page) => {
410
419
  await page.goto(`file://${`${dest}.html`}`, {});
420
+ /* @ts-ignore:next-line */
411
421
  res(page);
412
422
  });
413
423
  });
@@ -478,10 +488,16 @@ ${addableFiles
478
488
  }
479
489
  }
480
490
  };
481
- this.launchWeb = (t, dest) => {
482
- // console.log(green, "! web", t);
483
- console.log(ansiC.green(ansiC.inverse(`! web ${t}`)));
484
- this.testIsNowRunning(t);
491
+ this.launchWeb = (src, dest) => {
492
+ console.log(ansiC.green(ansiC.inverse(`! web ${src}`)));
493
+ this.bddTestIsRunning(src);
494
+ const reportDest = `testeranto/reports/${this.name}/${src
495
+ .split(".")
496
+ .slice(0, -1)
497
+ .join(".")}/web`;
498
+ if (!fs.existsSync(reportDest)) {
499
+ fs.mkdirSync(reportDest, { recursive: true });
500
+ }
485
501
  // sidecars.map((sidecar) => {
486
502
  // if (sidecar[1] === "node") {
487
503
  // return this.launchNodeSideCar(
@@ -495,7 +511,7 @@ ${addableFiles
495
511
  const webArgz = JSON.stringify({
496
512
  name: dest,
497
513
  ports: [].toString(),
498
- fs: destFolder,
514
+ fs: reportDest,
499
515
  browserWSEndpoint: this.browser.wsEndpoint(),
500
516
  });
501
517
  const d = `${dest}?cacheBust=${Date.now()}`;
@@ -516,9 +532,9 @@ ${addableFiles
516
532
  this.browser
517
533
  .newPage()
518
534
  .then((page) => {
519
- // page.on("console", (msg) => {
520
- // // console.log("web > ", msg.args(), msg.text());
521
- // });
535
+ page.on("console", (msg) => {
536
+ console.log("web > ", msg.args(), msg.text());
537
+ });
522
538
  page.exposeFunction("screencast", async (ssOpts, testName) => {
523
539
  const p = ssOpts.path;
524
540
  const dir = path.dirname(p);
@@ -609,37 +625,6 @@ ${addableFiles
609
625
  page.exposeFunction("end", async (uid) => {
610
626
  return fileStreams2[uid].end();
611
627
  });
612
- // page.exposeFunction("customclose", (p: string, testName: string) => {
613
- // // console.log("closing", p);
614
- // console.log("\t GOODBYE customclose");
615
- // fs.writeFileSync(
616
- // p + "/manifest.json",
617
- // JSON.stringify(Array.from(files[testName]))
618
- // );
619
- // delete files[testName];
620
- // // console.log("screenshots[testName]", screenshots[testName]);
621
- // Promise.all(screenshots[testName] || []).then(() => {
622
- // delete screenshots[testName];
623
- // });
624
- // // globalThis["writeFileSync"](
625
- // // p + "/manifest.json",
626
- // // // files.entries()
627
- // // JSON.stringify(Array.from(files[testName]))
628
- // // );
629
- // // console.log("closing doneFileStream2", doneFileStream2);
630
- // // console.log("closing doneFileStream2", doneFileStream2);
631
- // // Promise.all([...doneFileStream2, ...screenshots2]).then(() => {
632
- // // page.close();
633
- // // });
634
- // // Promise.all(screenshots).then(() => {
635
- // // page.close();
636
- // // });
637
- // // setTimeout(() => {
638
- // // console.log("Delayed for 1 second.");
639
- // // page.close();
640
- // // }, 5000);
641
- // // return page.close();
642
- // });
643
628
  page.exposeFunction("page", () => {
644
629
  return page.mainFrame()._id;
645
630
  });
@@ -672,33 +657,33 @@ ${addableFiles
672
657
  })
673
658
  .then(async (page) => {
674
659
  const close = () => {
675
- if (!files[t]) {
676
- files[t] = new Set();
660
+ if (!files[src]) {
661
+ files[src] = new Set();
677
662
  }
678
663
  // files[t].add(filepath);
679
- fs.writeFileSync(destFolder + "/manifest.json", JSON.stringify(Array.from(files[t])));
680
- delete files[t];
681
- Promise.all(screenshots[t] || []).then(() => {
682
- delete screenshots[t];
664
+ fs.writeFileSync(destFolder + "/manifest.json", JSON.stringify(Array.from(files[src])));
665
+ delete files[src];
666
+ Promise.all(screenshots[src] || []).then(() => {
667
+ delete screenshots[src];
683
668
  page.close();
684
- this.testIsNowDone(t);
685
669
  stderrStream.close();
686
670
  stdoutStream.close();
687
671
  });
688
672
  };
689
673
  page.on("pageerror", (err) => {
690
- console.debug(`Error from ${t}: [${err.name}] `);
674
+ console.debug(`Error from ${src}: [${err.name}] `);
691
675
  stderrStream.write(err.name);
692
676
  if (err.cause) {
693
- console.debug(`Error from ${t} cause: [${err.cause}] `);
677
+ console.debug(`Error from ${src} cause: [${err.cause}] `);
694
678
  stderrStream.write(err.cause);
695
679
  }
696
680
  if (err.stack) {
697
- console.debug(`Error from stack ${t}: [${err.stack}] `);
681
+ console.debug(`Error from stack ${src}: [${err.stack}] `);
698
682
  stderrStream.write(err.stack);
699
683
  }
700
- console.debug(`Error from message ${t}: [${err.message}] `);
684
+ console.debug(`Error from message ${src}: [${err.message}] `);
701
685
  stderrStream.write(err.message);
686
+ this.bddTestIsNowDone(src, -1);
702
687
  close();
703
688
  });
704
689
  page.on("console", (log) => {
@@ -715,24 +700,24 @@ ${addableFiles
715
700
  await page
716
701
  .evaluate(evaluation)
717
702
  .then(async ({ failed, features }) => {
718
- this.receiveFeatures(features, destFolder, t);
703
+ this.receiveFeatures(features, destFolder, src, "web");
719
704
  // console.log(`${t} completed with ${failed} errors`);
720
- statusMessagePretty(failed, t);
721
- this.receiveExitCode(t, failed);
705
+ statusMessagePretty(failed, src);
706
+ this.bddTestIsNowDone(src, failed);
722
707
  })
723
708
  .catch((e) => {
724
709
  // console.log(red, `${t} errored with`, e);
725
- console.log(ansiC.red(ansiC.inverse(`${t} errored with: ${e}`)));
710
+ console.log(ansiC.red(ansiC.inverse(`${src} errored with: ${e}`)));
726
711
  })
727
712
  .finally(() => {
728
- // this.testIsNowDone(t);
713
+ this.bddTestIsNowDone(src, -1);
729
714
  close();
730
715
  });
731
716
  return page;
732
717
  });
733
718
  };
734
- this.receiveFeatures = (features, destFolder, srcTest) => {
735
- const featureDestination = path.resolve(process.cwd(), "docs", "features", "strings", srcTest.split(".").slice(0, -1).join(".") + ".features.txt");
719
+ this.receiveFeatures = (features, destFolder, srcTest, platform) => {
720
+ const featureDestination = path.resolve(process.cwd(), "reports", "features", "strings", srcTest.split(".").slice(0, -1).join(".") + ".features.txt");
736
721
  features
737
722
  .reduce(async (mm, featureStringKey) => {
738
723
  const accum = await mm;
@@ -740,7 +725,7 @@ ${addableFiles
740
725
  if (isUrl) {
741
726
  const u = new URL(featureStringKey);
742
727
  if (u.protocol === "file:") {
743
- const newPath = `${process.cwd()}/docs/features/internal/${path.relative(process.cwd(), u.pathname)}`;
728
+ const newPath = `${process.cwd()}/testeranto/features/internal/${path.relative(process.cwd(), u.pathname)}`;
744
729
  await fs.promises.mkdir(path.dirname(newPath), { recursive: true });
745
730
  try {
746
731
  await fs.unlinkSync(newPath);
@@ -761,7 +746,7 @@ ${addableFiles
761
746
  accum.files.push(newPath);
762
747
  }
763
748
  else if (u.protocol === "http:" || u.protocol === "https:") {
764
- const newPath = `${process.cwd()}/docs/features/external${u.hostname}${u.pathname}`;
749
+ const newPath = `${process.cwd()}/testeranto/features/external${u.hostname}${u.pathname}`;
765
750
  const body = await this.configs.featureIngestor(featureStringKey);
766
751
  writeFileAndCreateDir(newPath, body);
767
752
  accum.files.push(newPath);
@@ -777,7 +762,12 @@ ${addableFiles
777
762
  }, Promise.resolve({ files: [], strings: [] }))
778
763
  .then(({ files, strings }) => {
779
764
  // writeFileAndCreateDir(`${featureDestination}`, JSON.stringify(strings));
780
- fs.writeFileSync(`${destFolder}/featurePrompt.txt`, files
765
+ fs.writeFileSync(
766
+ // `${destFolder}/featurePrompt.txt`,
767
+ `testeranto/reports/${this.name}/${srcTest
768
+ .split(".")
769
+ .slice(0, -1)
770
+ .join(".")}/${platform}/featurePrompt.txt`, files
781
771
  .map((f) => {
782
772
  return `/read ${f}`;
783
773
  })
@@ -785,16 +775,11 @@ ${addableFiles
785
775
  });
786
776
  // this.writeBigBoard();
787
777
  };
788
- this.receiveExitCode = (srcTest, failures) => {
789
- this.bigBoard[srcTest].runTimeError = failures;
790
- this.writeBigBoard();
791
- };
792
778
  this.writeBigBoard = () => {
793
- fs.writeFileSync("./docs/summary.json", JSON.stringify(this.bigBoard, null, 2));
779
+ fs.writeFileSync(`./testeranto/reports/${this.name}/summary.json`, JSON.stringify(this.bigBoard, null, 2));
794
780
  };
795
- this.mode = configs.devMode ? "DEV" : "PROD";
796
- this.server = {};
797
- this.configs = configs;
781
+ this.name = name;
782
+ this.mode = mode;
798
783
  this.ports = {};
799
784
  this.configs.tests.forEach(([t]) => {
800
785
  this.bigBoard[t] = {
@@ -807,294 +792,52 @@ ${addableFiles
807
792
  this.configs.ports.forEach((element) => {
808
793
  this.ports[element] = "true"; // set ports as open
809
794
  });
810
- globalThis["waitForSelector"] = async (pageKey, sel) => {
811
- const page = (await this.browser.pages()).find(
812
- /* @ts-ignore:next-line */
813
- (p) => p.mainFrame()._id === pageKey);
814
- await (page === null || page === void 0 ? void 0 : page.waitForSelector(sel));
815
- };
816
- globalThis["screencastStop"] = async (path) => {
817
- return recorders[path].stop();
818
- };
819
- globalThis["closePage"] = async (pageKey) => {
820
- const page = (await this.browser.pages()).find(
821
- /* @ts-ignore:next-line */
822
- (p) => p.mainFrame()._id === pageKey);
823
- /* @ts-ignore:next-line */
824
- return page.close();
825
- };
826
- globalThis["goto"] = async (pageKey, url) => {
827
- const page = (await this.browser.pages()).find(
828
- /* @ts-ignore:next-line */
829
- (p) => p.mainFrame()._id === pageKey);
830
- await (page === null || page === void 0 ? void 0 : page.goto(url));
831
- return;
832
- };
833
- globalThis["newPage"] = () => {
834
- return this.browser.newPage();
835
- };
836
- globalThis["pages"] = () => {
837
- return this.browser.pages();
838
- };
839
- globalThis["mkdirSync"] = (fp) => {
840
- if (!fs.existsSync(fp)) {
841
- return fs.mkdirSync(fp, {
842
- recursive: true,
843
- });
844
- }
845
- return false;
846
- };
847
- globalThis["writeFileSync"] = (filepath, contents, testName) => {
848
- fs.mkdirSync(path.dirname(filepath), {
849
- recursive: true,
850
- });
851
- if (!files[testName]) {
852
- files[testName] = new Set();
853
- }
854
- files[testName].add(filepath);
855
- return fs.writeFileSync(filepath, contents);
856
- };
857
- globalThis["createWriteStream"] = (filepath, testName) => {
858
- const f = fs.createWriteStream(filepath);
859
- fileStreams3.push(f);
860
- // files.add(filepath);
861
- if (!files[testName]) {
862
- files[testName] = new Set();
863
- }
864
- files[testName].add(filepath);
865
- return Object.assign(Object.assign({}, JSON.parse(JSON.stringify(f))), { uid: fileStreams3.length - 1 });
866
- };
867
- globalThis["write"] = (uid, contents) => {
868
- fileStreams3[uid].write(contents);
869
- };
870
- globalThis["end"] = (uid) => {
871
- fileStreams3[uid].end();
872
- };
873
- globalThis["customScreenShot"] = async (opts, pageKey, testName) => {
874
- const page = (await this.browser.pages()).find(
875
- /* @ts-ignore:next-line */
876
- (p) => p.mainFrame()._id === pageKey);
877
- const p = opts.path;
878
- const dir = path.dirname(p);
879
- fs.mkdirSync(dir, {
880
- recursive: true,
881
- });
882
- if (!files[opts.path]) {
883
- files[opts.path] = new Set();
884
- }
885
- files[opts.path].add(opts.path);
886
- const sPromise = page.screenshot(Object.assign(Object.assign({}, opts), { path: p }));
887
- if (!screenshots[opts.path]) {
888
- screenshots[opts.path] = [];
889
- }
890
- screenshots[opts.path].push(sPromise);
891
- await sPromise;
892
- return sPromise;
893
- };
894
- globalThis["screencast"] = async (opts, pageKey) => {
895
- const page = (await this.browser.pages()).find(
896
- /* @ts-ignore:next-line */
897
- (p) => p.mainFrame()._id === pageKey);
898
- const p = opts.path;
899
- const dir = path.dirname(p);
900
- fs.mkdirSync(dir, {
901
- recursive: true,
902
- });
903
- const recorder = await (page === null || page === void 0 ? void 0 : page.screencast(Object.assign(Object.assign({}, opts), { path: p })));
904
- recorders[opts.path] = recorder;
905
- return opts.path;
906
- };
907
- }
908
- customclose() {
909
- throw new Error("Method not implemented.");
910
- }
911
- waitForSelector(p, s) {
912
- throw new Error("Method not implemented.");
913
- }
914
- closePage(p) {
915
- throw new Error("Method not implemented.");
916
- }
917
- newPage() {
918
- throw new Error("Method not implemented.");
919
- }
920
- goto(p, url) {
921
- throw new Error("Method not implemented.");
922
- }
923
- $(selector) {
924
- throw new Error("Method not implemented.");
925
- }
926
- screencast(opts) {
927
- throw new Error("Method not implemented.");
928
- }
929
- customScreenShot(opts, cdpPage) {
930
- throw new Error("Method not implemented.");
931
- }
932
- end(accessObject) {
933
- throw new Error("Method not implemented.");
934
- }
935
- existsSync(destFolder) {
936
- return fs.existsSync(destFolder);
937
- }
938
- async mkdirSync(fp) {
939
- if (!fs.existsSync(fp)) {
940
- return fs.mkdirSync(fp, {
941
- recursive: true,
942
- });
943
- }
944
- return false;
945
- }
946
- writeFileSync(fp, contents) {
947
- fs.writeFileSync(fp, contents);
948
- }
949
- createWriteStream(filepath) {
950
- return fs.createWriteStream(filepath);
951
- }
952
- testArtiFactoryfileWriter(tLog, callback) {
953
- return (fPath, value) => {
954
- callback(new Promise((res, rej) => {
955
- tLog("testArtiFactory =>", fPath);
956
- const cleanPath = path.resolve(fPath);
957
- fPaths.push(cleanPath.replace(process.cwd(), ``));
958
- const targetDir = cleanPath.split("/").slice(0, -1).join("/");
959
- fs.mkdir(targetDir, { recursive: true }, async (error) => {
960
- if (error) {
961
- console.error(`❗️testArtiFactory failed`, targetDir, error);
962
- }
963
- fs.writeFileSync(path.resolve(targetDir.split("/").slice(0, -1).join("/"), "manifest"), fPaths.join(`\n`), {
964
- encoding: "utf-8",
965
- });
966
- if (Buffer.isBuffer(value)) {
967
- fs.writeFileSync(fPath, value, "binary");
968
- res();
969
- }
970
- else if (`string` === typeof value) {
971
- fs.writeFileSync(fPath, value.toString(), {
972
- encoding: "utf-8",
973
- });
974
- res();
975
- }
976
- else {
977
- /* @ts-ignore:next-line */
978
- const pipeStream = value;
979
- const myFile = fs.createWriteStream(fPath);
980
- pipeStream.pipe(myFile);
981
- pipeStream.on("close", () => {
982
- myFile.close();
983
- res();
984
- });
985
- }
986
- });
987
- }));
988
- };
989
- }
990
- write(accessObject, contents) {
991
- throw new Error("Method not implemented.");
992
- }
993
- page() {
994
- throw new Error("Method not implemented.");
995
- }
996
- click(selector) {
997
- throw new Error("Method not implemented.");
998
- }
999
- focusOn(selector) {
1000
- throw new Error("Method not implemented.");
1001
- }
1002
- typeInto(value) {
1003
- throw new Error("Method not implemented.");
1004
- }
1005
- getValue(value) {
1006
- throw new Error("Method not implemented.");
1007
- }
1008
- getAttribute(selector, attribute) {
1009
- throw new Error("Method not implemented.");
1010
- }
1011
- isDisabled(selector) {
1012
- throw new Error("Method not implemented.");
1013
- }
1014
- screencastStop(s) {
1015
- throw new Error("Method not implemented.");
1016
- }
1017
- ////////////////////////////////////////////////////////////////////////////////
1018
- async metafileOutputs(platform) {
1019
- const metafile = JSON.parse(fs.readFileSync(`docs/${platform}/metafile.json`).toString()).metafile;
1020
- if (!metafile)
1021
- return;
1022
- const outputs = metafile.outputs;
1023
- Object.keys(outputs).forEach(async (k) => {
1024
- const addableFiles = Object.keys(outputs[k].inputs).filter((i) => {
1025
- if (!fs.existsSync(i))
1026
- return false;
1027
- if (i.startsWith("node_modules"))
1028
- return false;
1029
- return true;
1030
- });
1031
- const f = `${k.split(".").slice(0, -1).join(".")}/`;
1032
- if (!fs.existsSync(f)) {
1033
- fs.mkdirSync(f);
1034
- }
1035
- const entrypoint = outputs[k].entryPoint;
1036
- if (entrypoint) {
1037
- const changeDigest = await filesHash(addableFiles);
1038
- if (changeDigest === changes[entrypoint]) {
1039
- // skip
1040
- }
1041
- else {
1042
- changes[entrypoint] = changeDigest;
1043
- this.tscCheck({
1044
- platform,
1045
- addableFiles,
1046
- entrypoint: "./" + entrypoint,
1047
- });
1048
- this.eslintCheck("./" + entrypoint, platform, addableFiles);
1049
- this.makePrompt("./" + entrypoint, addableFiles, platform);
1050
- }
1051
- }
1052
- });
1053
795
  }
1054
796
  async start() {
797
+ if (!fs.existsSync(`testeranto/reports/${this.name}`)) {
798
+ fs.mkdirSync(`testeranto/reports/${this.name}`);
799
+ }
1055
800
  this.browser = (await puppeteer.launch({
1056
801
  slowMo: 1,
1057
- // timeout: 1,
1058
802
  waitForInitialPage: false,
1059
803
  executablePath:
1060
804
  // process.env.CHROMIUM_PATH || "/opt/homebrew/bin/chromium",
1061
805
  "/opt/homebrew/bin/chromium",
1062
806
  headless: true,
1063
- dumpio: true,
1064
- // timeout: 0,
1065
- devtools: true,
807
+ dumpio: false,
808
+ devtools: false,
1066
809
  args: [
1067
- "--auto-open-devtools-for-tabs",
1068
- `--remote-debugging-port=3234`,
1069
- // "--disable-features=IsolateOrigins,site-per-process",
1070
- "--disable-site-isolation-trials",
1071
- "--allow-insecure-localhost",
1072
810
  "--allow-file-access-from-files",
811
+ "--allow-insecure-localhost",
1073
812
  "--allow-running-insecure-content",
813
+ "--auto-open-devtools-for-tabs",
1074
814
  "--disable-dev-shm-usage",
1075
815
  "--disable-extensions",
1076
816
  "--disable-gpu",
1077
817
  "--disable-setuid-sandbox",
1078
818
  "--disable-site-isolation-trials",
819
+ "--disable-site-isolation-trials",
1079
820
  "--disable-web-security",
1080
821
  "--no-first-run",
1081
822
  "--no-sandbox",
1082
823
  "--no-startup-window",
1083
- // "--no-zygote",
1084
824
  "--reduce-security-for-testing",
1085
825
  "--remote-allow-origins=*",
826
+ `--remote-debugging-port=3234`,
1086
827
  "--unsafely-treat-insecure-origin-as-secure=*",
828
+ // "--disable-features=IsolateOrigins,site-per-process",
1087
829
  // "--disable-features=IsolateOrigins",
830
+ // "--disk-cache-dir=/dev/null",
831
+ // "--disk-cache-size=1",
832
+ // "--no-zygote",
1088
833
  // "--remote-allow-origins=ws://localhost:3234",
1089
834
  // "--single-process",
835
+ // "--start-maximized",
1090
836
  // "--unsafely-treat-insecure-origin-as-secure",
1091
837
  // "--unsafely-treat-insecure-origin-as-secure=ws://192.168.0.101:3234",
1092
- // "--disk-cache-dir=/dev/null",
1093
- // "--disk-cache-size=1",
1094
- // "--start-maximized",
1095
838
  ],
1096
839
  }));
1097
- const { nodeEntryPoints, webEntryPoints } = getRunnables(this.configs.tests);
840
+ const { nodeEntryPoints, webEntryPoints } = this.getRunnables(this.configs.tests);
1098
841
  Object.entries(nodeEntryPoints).forEach(([k, outputFile]) => {
1099
842
  this.launchNode(k, outputFile);
1100
843
  try {
@@ -1123,14 +866,54 @@ ${addableFiles
1123
866
  });
1124
867
  });
1125
868
  this.metafileOutputs("node");
1126
- this.nodeMetafileWatcher = watch("docs/node/metafile.json", async (e, filename) => {
869
+ const w = `./testeranto/bundles/node/${this.name}/metafile.json`;
870
+ console.log("w", w);
871
+ this.nodeMetafileWatcher = watch(w, async (e, filename) => {
1127
872
  console.log(ansiC.green(ansiC.inverse(`< ${e} ${filename} (node)`)));
1128
873
  this.metafileOutputs("node");
1129
874
  });
1130
875
  this.metafileOutputs("web");
1131
- this.webMetafileWatcher = watch("docs/web/metafile.json", async (e, filename) => {
876
+ this.webMetafileWatcher = watch(`./testeranto/bundles/web/${this.name}/metafile.json`, async (e, filename) => {
1132
877
  console.log(ansiC.green(ansiC.inverse(`< ${e} ${filename} (web)`)));
1133
878
  this.metafileOutputs("web");
1134
879
  });
1135
880
  }
881
+ async metafileOutputs(platform) {
882
+ const metafile = JSON.parse(fs
883
+ .readFileSync(`./testeranto/bundles/${platform}/${this.name}/metafile.json`)
884
+ .toString()).metafile;
885
+ if (!metafile)
886
+ return;
887
+ const outputs = metafile.outputs;
888
+ Object.keys(outputs).forEach(async (k) => {
889
+ const addableFiles = Object.keys(outputs[k].inputs).filter((i) => {
890
+ if (!fs.existsSync(i))
891
+ return false;
892
+ if (i.startsWith("node_modules"))
893
+ return false;
894
+ return true;
895
+ });
896
+ const f = `${k.split(".").slice(0, -1).join(".")}/`;
897
+ if (!fs.existsSync(f)) {
898
+ fs.mkdirSync(f);
899
+ }
900
+ const entrypoint = outputs[k].entryPoint;
901
+ if (entrypoint) {
902
+ const changeDigest = await filesHash(addableFiles);
903
+ if (changeDigest === changes[entrypoint]) {
904
+ // skip
905
+ }
906
+ else {
907
+ changes[entrypoint] = changeDigest;
908
+ this.tscCheck({
909
+ platform,
910
+ addableFiles,
911
+ entrypoint: "./" + entrypoint,
912
+ });
913
+ this.eslintCheck("./" + entrypoint, platform, addableFiles);
914
+ this.makePrompt("./" + entrypoint, addableFiles, platform);
915
+ }
916
+ }
917
+ });
918
+ }
1136
919
  }