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,8 +6,8 @@ import readline from "readline";
6
6
 
7
7
  // src/PM/main.ts
8
8
  import ts from "typescript";
9
- import fs, { watch } from "fs";
10
- import path2 from "path";
9
+ import fs2, { watch } from "fs";
10
+ import path3 from "path";
11
11
  import puppeteer from "puppeteer-core";
12
12
  import ansiC from "ansi-colors";
13
13
  import crypto from "node:crypto";
@@ -16,27 +16,286 @@ import tsc from "tsc-prog";
16
16
 
17
17
  // src/utils.ts
18
18
  import path from "path";
19
- var tscPather = (entryPoint, platform) => {
19
+ var tscPather = (entryPoint, platform, projectName) => {
20
20
  return path.join(
21
- "./docs/",
22
- platform,
21
+ "testeranto",
22
+ "reports",
23
+ projectName,
23
24
  entryPoint.split(".").slice(0, -1).join("."),
25
+ platform,
24
26
  `type_errors.txt`
25
27
  );
26
28
  };
27
- var lintPather = (entryPoint, platform) => {
29
+ var lintPather = (entryPoint, platform, projectName) => {
28
30
  return path.join(
29
- "./docs/",
30
- platform,
31
+ "testeranto",
32
+ "reports",
33
+ projectName,
31
34
  entryPoint.split(".").slice(0, -1).join("."),
35
+ platform,
32
36
  `lint_errors.json`
33
37
  );
34
38
  };
39
+ var promptPather = (entryPoint, platform, projectName) => {
40
+ return path.join(
41
+ "testeranto",
42
+ "reports",
43
+ projectName,
44
+ entryPoint.split(".").slice(0, -1).join("."),
45
+ platform,
46
+ `prompt.txt`
47
+ );
48
+ };
49
+
50
+ // src/PM/base.ts
51
+ import fs from "fs";
52
+ import path2 from "path";
35
53
 
36
54
  // src/PM/index.ts
37
55
  var PM = class {
38
56
  };
39
57
 
58
+ // src/PM/base.ts
59
+ var fileStreams3 = [];
60
+ var fPaths = [];
61
+ var files = {};
62
+ var recorders = {};
63
+ var screenshots = {};
64
+ var PM_Base = class extends PM {
65
+ constructor(configs) {
66
+ super();
67
+ this.server = {};
68
+ this.configs = configs;
69
+ globalThis["waitForSelector"] = async (pageKey, sel) => {
70
+ const page = (await this.browser.pages()).find(
71
+ /* @ts-ignore:next-line */
72
+ (p) => p.mainFrame()._id === pageKey
73
+ );
74
+ await page?.waitForSelector(sel);
75
+ };
76
+ globalThis["screencastStop"] = async (path4) => {
77
+ return recorders[path4].stop();
78
+ };
79
+ globalThis["closePage"] = async (pageKey) => {
80
+ const page = (await this.browser.pages()).find(
81
+ /* @ts-ignore:next-line */
82
+ (p) => p.mainFrame()._id === pageKey
83
+ );
84
+ return page.close();
85
+ };
86
+ globalThis["goto"] = async (pageKey, url) => {
87
+ const page = (await this.browser.pages()).find(
88
+ /* @ts-ignore:next-line */
89
+ (p) => p.mainFrame()._id === pageKey
90
+ );
91
+ await page?.goto(url);
92
+ return;
93
+ };
94
+ globalThis["newPage"] = () => {
95
+ return this.browser.newPage();
96
+ };
97
+ globalThis["pages"] = () => {
98
+ return this.browser.pages();
99
+ };
100
+ globalThis["mkdirSync"] = (fp) => {
101
+ if (!fs.existsSync(fp)) {
102
+ return fs.mkdirSync(fp, {
103
+ recursive: true
104
+ });
105
+ }
106
+ return false;
107
+ };
108
+ globalThis["writeFileSync"] = (filepath, contents, testName2) => {
109
+ fs.mkdirSync(path2.dirname(filepath), {
110
+ recursive: true
111
+ });
112
+ if (!files[testName2]) {
113
+ files[testName2] = /* @__PURE__ */ new Set();
114
+ }
115
+ files[testName2].add(filepath);
116
+ return fs.writeFileSync(filepath, contents);
117
+ };
118
+ globalThis["createWriteStream"] = (filepath, testName2) => {
119
+ const f = fs.createWriteStream(filepath);
120
+ fileStreams3.push(f);
121
+ if (!files[testName2]) {
122
+ files[testName2] = /* @__PURE__ */ new Set();
123
+ }
124
+ files[testName2].add(filepath);
125
+ return {
126
+ ...JSON.parse(JSON.stringify(f)),
127
+ uid: fileStreams3.length - 1
128
+ };
129
+ };
130
+ globalThis["write"] = (uid, contents) => {
131
+ fileStreams3[uid].write(contents);
132
+ };
133
+ globalThis["end"] = (uid) => {
134
+ fileStreams3[uid].end();
135
+ };
136
+ globalThis["customScreenShot"] = async (opts, pageKey, testName2) => {
137
+ const page = (await this.browser.pages()).find(
138
+ /* @ts-ignore:next-line */
139
+ (p2) => p2.mainFrame()._id === pageKey
140
+ );
141
+ const p = opts.path;
142
+ const dir = path2.dirname(p);
143
+ fs.mkdirSync(dir, {
144
+ recursive: true
145
+ });
146
+ if (!files[opts.path]) {
147
+ files[opts.path] = /* @__PURE__ */ new Set();
148
+ }
149
+ files[opts.path].add(opts.path);
150
+ const sPromise = page.screenshot({
151
+ ...opts,
152
+ path: p
153
+ });
154
+ if (!screenshots[opts.path]) {
155
+ screenshots[opts.path] = [];
156
+ }
157
+ screenshots[opts.path].push(sPromise);
158
+ await sPromise;
159
+ return sPromise;
160
+ };
161
+ globalThis["screencast"] = async (opts, pageKey) => {
162
+ const page = (await this.browser.pages()).find(
163
+ /* @ts-ignore:next-line */
164
+ (p2) => p2.mainFrame()._id === pageKey
165
+ );
166
+ const p = opts.path;
167
+ const dir = path2.dirname(p);
168
+ fs.mkdirSync(dir, {
169
+ recursive: true
170
+ });
171
+ const recorder = await page?.screencast({
172
+ ...opts,
173
+ /* @ts-ignore:next-line */
174
+ path: p
175
+ });
176
+ recorders[opts.path] = recorder;
177
+ return opts.path;
178
+ };
179
+ }
180
+ customclose() {
181
+ throw new Error("Method not implemented.");
182
+ }
183
+ waitForSelector(p, s) {
184
+ throw new Error("Method not implemented.");
185
+ }
186
+ closePage(p) {
187
+ throw new Error("Method not implemented.");
188
+ }
189
+ newPage() {
190
+ throw new Error("Method not implemented.");
191
+ }
192
+ goto(p, url) {
193
+ throw new Error("Method not implemented.");
194
+ }
195
+ $(selector) {
196
+ throw new Error("Method not implemented.");
197
+ }
198
+ screencast(opts) {
199
+ throw new Error("Method not implemented.");
200
+ }
201
+ /* @ts-ignore:next-line */
202
+ customScreenShot(opts, cdpPage) {
203
+ throw new Error("Method not implemented.");
204
+ }
205
+ end(accessObject) {
206
+ throw new Error("Method not implemented.");
207
+ }
208
+ existsSync(destFolder) {
209
+ return fs.existsSync(destFolder);
210
+ }
211
+ async mkdirSync(fp) {
212
+ if (!fs.existsSync(fp)) {
213
+ return fs.mkdirSync(fp, {
214
+ recursive: true
215
+ });
216
+ }
217
+ return false;
218
+ }
219
+ writeFileSync(fp, contents) {
220
+ fs.writeFileSync(fp, contents);
221
+ }
222
+ createWriteStream(filepath) {
223
+ return fs.createWriteStream(filepath);
224
+ }
225
+ testArtiFactoryfileWriter(tLog, callback) {
226
+ return (fPath, value) => {
227
+ callback(
228
+ new Promise((res, rej) => {
229
+ tLog("testArtiFactory =>", fPath);
230
+ const cleanPath = path2.resolve(fPath);
231
+ fPaths.push(cleanPath.replace(process.cwd(), ``));
232
+ const targetDir = cleanPath.split("/").slice(0, -1).join("/");
233
+ fs.mkdir(targetDir, { recursive: true }, async (error) => {
234
+ if (error) {
235
+ console.error(`\u2757\uFE0FtestArtiFactory failed`, targetDir, error);
236
+ }
237
+ fs.writeFileSync(
238
+ path2.resolve(
239
+ targetDir.split("/").slice(0, -1).join("/"),
240
+ "manifest"
241
+ ),
242
+ fPaths.join(`
243
+ `),
244
+ {
245
+ encoding: "utf-8"
246
+ }
247
+ );
248
+ if (Buffer.isBuffer(value)) {
249
+ fs.writeFileSync(fPath, value, "binary");
250
+ res();
251
+ } else if (`string` === typeof value) {
252
+ fs.writeFileSync(fPath, value.toString(), {
253
+ encoding: "utf-8"
254
+ });
255
+ res();
256
+ } else {
257
+ const pipeStream = value;
258
+ const myFile = fs.createWriteStream(fPath);
259
+ pipeStream.pipe(myFile);
260
+ pipeStream.on("close", () => {
261
+ myFile.close();
262
+ res();
263
+ });
264
+ }
265
+ });
266
+ })
267
+ );
268
+ };
269
+ }
270
+ write(accessObject, contents) {
271
+ throw new Error("Method not implemented.");
272
+ }
273
+ page() {
274
+ throw new Error("Method not implemented.");
275
+ }
276
+ click(selector) {
277
+ throw new Error("Method not implemented.");
278
+ }
279
+ focusOn(selector) {
280
+ throw new Error("Method not implemented.");
281
+ }
282
+ typeInto(value) {
283
+ throw new Error("Method not implemented.");
284
+ }
285
+ getValue(value) {
286
+ throw new Error("Method not implemented.");
287
+ }
288
+ getAttribute(selector, attribute) {
289
+ throw new Error("Method not implemented.");
290
+ }
291
+ isDisabled(selector) {
292
+ throw new Error("Method not implemented.");
293
+ }
294
+ screencastStop(s) {
295
+ throw new Error("Method not implemented.");
296
+ }
297
+ };
298
+
40
299
  // src/PM/main.ts
41
300
  var eslint = new ESLint();
42
301
  var formatter = await eslint.loadFormatter(
@@ -44,15 +303,12 @@ var formatter = await eslint.loadFormatter(
44
303
  );
45
304
  var changes = {};
46
305
  var fileHashes = {};
47
- var fileStreams3 = [];
48
- var fPaths = [];
49
- var files = {};
50
- var recorders = {};
51
- var screenshots = {};
306
+ var files2 = {};
307
+ var screenshots2 = {};
52
308
  async function fileHash(filePath, algorithm = "md5") {
53
309
  return new Promise((resolve, reject) => {
54
310
  const hash = crypto.createHash(algorithm);
55
- const fileStream = fs.createReadStream(filePath);
311
+ const fileStream = fs2.createReadStream(filePath);
56
312
  fileStream.on("data", (data) => {
57
313
  hash.update(data);
58
314
  });
@@ -65,26 +321,6 @@ async function fileHash(filePath, algorithm = "md5") {
65
321
  });
66
322
  });
67
323
  }
68
- var getRunnables = (tests, payload = {
69
- nodeEntryPoints: {},
70
- webEntryPoints: {}
71
- }) => {
72
- return tests.reduce((pt, cv, cndx, cry) => {
73
- if (cv[1] === "node") {
74
- pt.nodeEntryPoints[cv[0]] = path2.resolve(
75
- `./docs/node/${cv[0].split(".").slice(0, -1).concat("mjs").join(".")}`
76
- );
77
- } else if (cv[1] === "web") {
78
- pt.webEntryPoints[cv[0]] = path2.resolve(
79
- `./docs/web/${cv[0].split(".").slice(0, -1).concat("mjs").join(".")}`
80
- );
81
- }
82
- if (cv[3].length) {
83
- getRunnables(cv[3], payload);
84
- }
85
- return pt;
86
- }, payload);
87
- };
88
324
  var statusMessagePretty = (failures, test) => {
89
325
  if (failures === 0) {
90
326
  console.log(ansiC.green(ansiC.inverse(`> ${test} completed successfully`)));
@@ -93,18 +329,18 @@ var statusMessagePretty = (failures, test) => {
93
329
  }
94
330
  };
95
331
  async function writeFileAndCreateDir(filePath, data) {
96
- const dirPath = path2.dirname(filePath);
332
+ const dirPath = path3.dirname(filePath);
97
333
  try {
98
- await fs.promises.mkdir(dirPath, { recursive: true });
99
- await fs.appendFileSync(filePath, data);
334
+ await fs2.promises.mkdir(dirPath, { recursive: true });
335
+ await fs2.appendFileSync(filePath, data);
100
336
  } catch (error) {
101
337
  console.error(`Error writing file: ${error}`);
102
338
  }
103
339
  }
104
- var filesHash = async (files2, algorithm = "md5") => {
340
+ var filesHash = async (files3, algorithm = "md5") => {
105
341
  return new Promise((resolve, reject) => {
106
342
  resolve(
107
- files2.reduce(async (mm, f) => {
343
+ files3.reduce(async (mm, f) => {
108
344
  return await mm + await fileHash(f);
109
345
  }, Promise.resolve(""))
110
346
  );
@@ -118,25 +354,44 @@ function isValidUrl(string) {
118
354
  return false;
119
355
  }
120
356
  }
121
- var PM_Main = class extends PM {
122
- constructor(configs) {
123
- super();
124
- this.shutdownMode = false;
357
+ var PM_Main = class extends PM_Base {
358
+ constructor(configs, name, mode2) {
359
+ super(configs);
125
360
  this.bigBoard = {};
126
361
  this.stop = () => {
127
362
  console.log(ansiC.inverse("Testeranto-Run is shutting down gracefully..."));
128
- this.mode = "PROD";
363
+ this.mode = "once";
129
364
  this.nodeMetafileWatcher.close();
130
365
  this.webMetafileWatcher.close();
131
366
  this.checkForShutdown();
132
367
  };
368
+ this.getRunnables = (tests, payload = {
369
+ nodeEntryPoints: {},
370
+ webEntryPoints: {}
371
+ }) => {
372
+ return tests.reduce((pt, cv, cndx, cry) => {
373
+ if (cv[1] === "node") {
374
+ pt.nodeEntryPoints[cv[0]] = path3.resolve(
375
+ `./testeranto/bundles/node/${this.name}/${cv[0].split(".").slice(0, -1).concat("mjs").join(".")}`
376
+ );
377
+ } else if (cv[1] === "web") {
378
+ pt.webEntryPoints[cv[0]] = path3.resolve(
379
+ `./testeranto/bundles/web/${this.name}/${cv[0].split(".").slice(0, -1).concat("mjs").join(".")}`
380
+ );
381
+ }
382
+ if (cv[3].length) {
383
+ this.getRunnables(cv[3], payload);
384
+ }
385
+ return pt;
386
+ }, payload);
387
+ };
133
388
  this.tscCheck = async ({
134
389
  entrypoint,
135
390
  addableFiles,
136
391
  platform
137
392
  }) => {
138
393
  console.log(ansiC.green(ansiC.inverse(`tsc < ${entrypoint}`)));
139
- this.bigBoard[entrypoint].typeErrors = "?";
394
+ this.typeCheckIsRunning(entrypoint);
140
395
  const program = tsc.createProgramFromConfig({
141
396
  basePath: process.cwd(),
142
397
  // always required, used for relative paths
@@ -144,7 +399,7 @@ var PM_Main = class extends PM {
144
399
  // config to inherit from (optional)
145
400
  compilerOptions: {
146
401
  rootDir: "src",
147
- outDir: tscPather(entrypoint, platform),
402
+ outDir: tscPather(entrypoint, platform, this.name),
148
403
  // declaration: true,
149
404
  // skipLibCheck: true,
150
405
  noEmit: true
@@ -153,9 +408,9 @@ var PM_Main = class extends PM {
153
408
  //["src/**/*"],
154
409
  // exclude: ["**/*.test.ts", "**/*.spec.ts"],
155
410
  });
156
- const tscPath = tscPather(entrypoint, platform);
411
+ const tscPath = tscPather(entrypoint, platform, this.name);
157
412
  let allDiagnostics = program.getSemanticDiagnostics();
158
- const d = [];
413
+ const results = [];
159
414
  allDiagnostics.forEach((diagnostic) => {
160
415
  if (diagnostic.file) {
161
416
  let { line, character } = ts.getLineAndCharacterOfPosition(
@@ -166,111 +421,149 @@ var PM_Main = class extends PM {
166
421
  diagnostic.messageText,
167
422
  "\n"
168
423
  );
169
- d.push(
424
+ results.push(
170
425
  `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`
171
426
  );
172
427
  } else {
173
- d.push(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"));
428
+ results.push(
429
+ ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")
430
+ );
174
431
  }
175
432
  });
176
- fs.writeFileSync(tscPath, d.join("\n"));
177
- this.bigBoard[entrypoint].typeErrors = d.length;
178
- if (this.shutdownMode) {
179
- this.checkForShutdown();
180
- }
433
+ fs2.writeFileSync(tscPath, results.join("\n"));
434
+ this.typeCheckIsNowDone(entrypoint, results.length);
181
435
  };
182
436
  this.eslintCheck = async (entrypoint, platform, addableFiles) => {
183
- this.bigBoard[entrypoint].staticErrors = "?";
184
437
  console.log(ansiC.green(ansiC.inverse(`eslint < ${entrypoint}`)));
438
+ this.lintIsRunning(entrypoint);
185
439
  const results = (await eslint.lintFiles(addableFiles)).filter((r) => r.messages.length).filter((r) => {
186
440
  return r.messages[0].ruleId !== null;
187
441
  }).map((r) => {
188
442
  delete r.source;
189
443
  return r;
190
444
  });
191
- fs.writeFileSync(
192
- lintPather(entrypoint, platform),
445
+ fs2.writeFileSync(
446
+ lintPather(entrypoint, platform, this.name),
193
447
  await formatter.format(results)
194
448
  );
195
- this.bigBoard[entrypoint].staticErrors = results.length;
196
- if (this.shutdownMode) {
197
- this.checkForShutdown();
198
- }
449
+ this.lintIsNowDone(entrypoint, results.length);
199
450
  };
200
451
  this.makePrompt = async (entryPoint, addableFiles, platform) => {
201
452
  this.bigBoard[entryPoint].prompt = "?";
202
- const promptPath = path2.join(
203
- "./docs/",
204
- platform,
205
- entryPoint.split(".").slice(0, -1).join("."),
206
- `prompt.txt`
207
- );
208
- const testPaths = path2.join(
209
- "./docs/",
453
+ const promptPath = promptPather(entryPoint, platform, this.name);
454
+ const testPaths = path3.join(
455
+ "testeranto",
456
+ "reports",
457
+ this.name,
210
458
  platform,
211
459
  entryPoint.split(".").slice(0, -1).join("."),
212
460
  `tests.json`
213
461
  );
214
- const featuresPath = path2.join(
215
- "./docs/",
462
+ const featuresPath = path3.join(
463
+ "testeranto",
464
+ "reports",
465
+ this.name,
216
466
  platform,
217
467
  entryPoint.split(".").slice(0, -1).join("."),
218
468
  `featurePrompt.txt`
219
469
  );
220
- fs.writeFileSync(
470
+ fs2.writeFileSync(
221
471
  promptPath,
222
472
  `
223
473
  ${addableFiles.map((x) => {
224
474
  return `/add ${x}`;
225
475
  }).join("\n")}
226
476
 
227
- /read ${lintPather(entryPoint, platform)}
228
- /read ${tscPather(entryPoint, platform)}
477
+ /read ${lintPather(entryPoint, platform, this.name)}
478
+ /read ${tscPather(entryPoint, platform, this.name)}
229
479
  /read ${testPaths}
230
480
 
231
481
  /load ${featuresPath}
232
482
 
233
483
  /code Fix the failing tests described in ${testPaths}. Correct any type signature errors described in the files ${tscPather(
234
484
  entryPoint,
235
- platform
485
+ platform,
486
+ this.name
236
487
  )}. Implement any method which throws "Function not implemented. Resolve the lint errors described in ${lintPather(
237
488
  entryPoint,
238
- platform
489
+ platform,
490
+ this.name
239
491
  )}"
240
492
  `
241
493
  );
242
- this.bigBoard[entryPoint].prompt = `aider --model deepseek/deepseek-chat --load docs/${platform}/${entryPoint.split(".").slice(0, -1).join(".")}/prompt.txt`;
243
- if (this.shutdownMode) {
244
- this.checkForShutdown();
245
- }
494
+ this.bigBoard[entryPoint].prompt = `aider --model deepseek/deepseek-chat --load testeranto/${this.name}/reports/${platform}/${entryPoint.split(".").slice(0, -1).join(".")}/prompt.txt`;
495
+ this.checkForShutdown();
246
496
  };
247
497
  this.checkForShutdown = () => {
248
- const anyRunning = Object.values(this.bigBoard).filter((x) => x.prompt === "?").length + Object.values(this.bigBoard).filter((x) => x.runTimeError === "?").length + Object.values(this.bigBoard).filter((x) => x.staticErrors === "?").length + Object.values(this.bigBoard).filter((x) => x.typeErrors === "?").length > 0;
249
- if (anyRunning) {
250
- console.log(ansiC.inverse("Shutting down. Please wait"));
251
- } else {
498
+ this.writeBigBoard();
499
+ if (this.mode === "dev")
500
+ return;
501
+ let inflight = false;
502
+ Object.keys(this.bigBoard).forEach((k) => {
503
+ if (this.bigBoard[k].prompt === "?") {
504
+ console.log(ansiC.blue(ansiC.inverse(`\u{1F555} prompt ${k}`)));
505
+ inflight = true;
506
+ }
507
+ });
508
+ Object.keys(this.bigBoard).forEach((k) => {
509
+ if (this.bigBoard[k].runTimeError === "?") {
510
+ console.log(ansiC.blue(ansiC.inverse(`\u{1F555} runTimeError ${k}`)));
511
+ inflight = true;
512
+ }
513
+ });
514
+ Object.keys(this.bigBoard).forEach((k) => {
515
+ if (this.bigBoard[k].staticErrors === "?") {
516
+ console.log(ansiC.blue(ansiC.inverse(`\u{1F555} staticErrors ${k}`)));
517
+ inflight = true;
518
+ }
519
+ });
520
+ Object.keys(this.bigBoard).forEach((k) => {
521
+ if (this.bigBoard[k].typeErrors === "?") {
522
+ console.log(ansiC.blue(ansiC.inverse(`\u{1F555} typeErrors ${k}`)));
523
+ inflight = true;
524
+ }
525
+ });
526
+ this.writeBigBoard();
527
+ if (!inflight) {
252
528
  this.browser.disconnect().then(() => {
253
- fs.writeFileSync(
254
- "docs/summary.json",
255
- JSON.stringify(this.bigBoard, null, 2)
256
- );
257
- console.log(ansiC.inverse("Goodbye"));
529
+ console.log(ansiC.inverse(`${this.name} has been tested. Goodbye.`));
258
530
  process.exit();
259
531
  });
260
532
  }
261
533
  };
262
- this.testIsNowRunning = (src) => {
263
- this.bigBoard[src].status = "running";
534
+ this.typeCheckIsRunning = (src) => {
535
+ this.bigBoard[src].typeErrors = "?";
264
536
  };
265
- this.testIsNowDone = (src) => {
266
- this.bigBoard[src].status = "waiting";
267
- if (this.shutdownMode) {
268
- this.checkForShutdown();
269
- }
537
+ this.typeCheckIsNowDone = (src, failures) => {
538
+ this.bigBoard[src].typeErrors = failures;
539
+ this.writeBigBoard();
540
+ this.checkForShutdown();
541
+ };
542
+ this.lintIsRunning = (src) => {
543
+ this.bigBoard[src].staticErrors = "?";
544
+ this.writeBigBoard();
545
+ };
546
+ this.lintIsNowDone = (src, failures) => {
547
+ this.bigBoard[src].staticErrors = failures;
548
+ this.writeBigBoard();
549
+ this.checkForShutdown();
550
+ };
551
+ this.bddTestIsRunning = (src) => {
552
+ this.bigBoard[src].runTimeError = "?";
553
+ this.writeBigBoard();
554
+ };
555
+ this.bddTestIsNowDone = (src, failures) => {
556
+ this.bigBoard[src].runTimeError = failures;
557
+ this.writeBigBoard();
558
+ this.checkForShutdown();
270
559
  };
271
560
  this.launchNode = async (src, dest) => {
272
561
  console.log(ansiC.green(ansiC.inverse(`! node, ${src}`)));
273
- this.testIsNowRunning(src);
562
+ this.bddTestIsRunning(src);
563
+ const reportDest = `testeranto/reports/${this.name}/${src.split(".").slice(0, -1).join(".")}/node`;
564
+ if (!fs2.existsSync(reportDest)) {
565
+ fs2.mkdirSync(reportDest, { recursive: true });
566
+ }
274
567
  const destFolder = dest.replace(".mjs", "");
275
568
  let argz = "";
276
569
  const testConfig = this.configs.tests.find((t) => {
@@ -287,7 +580,7 @@ ${addableFiles.map((x) => {
287
580
  scheduled: true,
288
581
  name: src,
289
582
  ports: portsToUse,
290
- fs: destFolder,
583
+ fs: reportDest,
291
584
  browserWSEndpoint: this.browser.wsEndpoint()
292
585
  });
293
586
  } else if (testConfigResource.ports > 0) {
@@ -320,14 +613,14 @@ ${addableFiles.map((x) => {
320
613
  this.server[builtfile] = await import(`${builtfile}?cacheBust=${Date.now()}`).then((module) => {
321
614
  return module.default.then((defaultModule) => {
322
615
  defaultModule.receiveTestResourceConfig(argz).then(async ({ features, failed }) => {
323
- this.receiveFeatures(features, destFolder, src);
616
+ this.receiveFeatures(features, destFolder, src, "node");
324
617
  statusMessagePretty(failed, src);
325
- this.receiveExitCode(src, failed);
618
+ this.bddTestIsNowDone(src, failed);
326
619
  }).catch((e) => {
327
620
  console.log(ansiC.red(ansiC.inverse(`${src} errored with: ${e}`)));
621
+ this.bddTestIsNowDone(src, -1);
328
622
  }).finally(() => {
329
623
  webSideCares.forEach((webSideCar) => webSideCar.close());
330
- this.testIsNowDone(src);
331
624
  });
332
625
  });
333
626
  });
@@ -346,50 +639,50 @@ ${addableFiles.map((x) => {
346
639
  this.browser.newPage().then((page) => {
347
640
  page.exposeFunction(
348
641
  "custom-screenshot",
349
- async (ssOpts, testName) => {
642
+ async (ssOpts, testName2) => {
350
643
  const p = ssOpts.path;
351
- const dir = path2.dirname(p);
352
- fs.mkdirSync(dir, {
644
+ const dir = path3.dirname(p);
645
+ fs2.mkdirSync(dir, {
353
646
  recursive: true
354
647
  });
355
- files[testName].add(ssOpts.path);
648
+ files2[testName2].add(ssOpts.path);
356
649
  const sPromise = page.screenshot({
357
650
  ...ssOpts,
358
651
  path: p
359
652
  });
360
- if (!screenshots[testName]) {
361
- screenshots[testName] = [];
653
+ if (!screenshots2[testName2]) {
654
+ screenshots2[testName2] = [];
362
655
  }
363
- screenshots[testName].push(sPromise);
656
+ screenshots2[testName2].push(sPromise);
364
657
  await sPromise;
365
658
  return sPromise;
366
659
  }
367
660
  );
368
661
  page.exposeFunction(
369
662
  "writeFileSync",
370
- (fp, contents, testName) => {
371
- const dir = path2.dirname(fp);
372
- fs.mkdirSync(dir, {
663
+ (fp, contents, testName2) => {
664
+ const dir = path3.dirname(fp);
665
+ fs2.mkdirSync(dir, {
373
666
  recursive: true
374
667
  });
375
668
  const p = new Promise(async (res2, rej2) => {
376
- fs.writeFileSync(fp, contents);
669
+ fs2.writeFileSync(fp, contents);
377
670
  res2(fp);
378
671
  });
379
672
  doneFileStream2.push(p);
380
- if (!files[testName]) {
381
- files[testName] = /* @__PURE__ */ new Set();
673
+ if (!files2[testName2]) {
674
+ files2[testName2] = /* @__PURE__ */ new Set();
382
675
  }
383
- files[testName].add(fp);
676
+ files2[testName2].add(fp);
384
677
  return p;
385
678
  }
386
679
  );
387
680
  page.exposeFunction("existsSync", (fp, contents) => {
388
- return fs.existsSync(fp);
681
+ return fs2.existsSync(fp);
389
682
  });
390
683
  page.exposeFunction("mkdirSync", (fp) => {
391
- if (!fs.existsSync(fp)) {
392
- return fs.mkdirSync(fp, {
684
+ if (!fs2.existsSync(fp)) {
685
+ return fs2.mkdirSync(fp, {
393
686
  recursive: true
394
687
  });
395
688
  }
@@ -397,9 +690,9 @@ ${addableFiles.map((x) => {
397
690
  });
398
691
  page.exposeFunction(
399
692
  "createWriteStream",
400
- (fp, testName) => {
401
- const f = fs.createWriteStream(fp);
402
- files[testName].add(fp);
693
+ (fp, testName2) => {
694
+ const f = fs2.createWriteStream(fp);
695
+ files2[testName2].add(fp);
403
696
  const p = new Promise((res2, rej2) => {
404
697
  res2(fp);
405
698
  });
@@ -483,14 +776,18 @@ ${addableFiles.map((x) => {
483
776
  }
484
777
  }
485
778
  };
486
- this.launchWeb = (t, dest) => {
487
- console.log(ansiC.green(ansiC.inverse(`! web ${t}`)));
488
- this.testIsNowRunning(t);
779
+ this.launchWeb = (src, dest) => {
780
+ console.log(ansiC.green(ansiC.inverse(`! web ${src}`)));
781
+ this.bddTestIsRunning(src);
782
+ const reportDest = `testeranto/reports/${this.name}/${src.split(".").slice(0, -1).join(".")}/web`;
783
+ if (!fs2.existsSync(reportDest)) {
784
+ fs2.mkdirSync(reportDest, { recursive: true });
785
+ }
489
786
  const destFolder = dest.replace(".mjs", "");
490
787
  const webArgz = JSON.stringify({
491
788
  name: dest,
492
789
  ports: [].toString(),
493
- fs: destFolder,
790
+ fs: reportDest,
494
791
  browserWSEndpoint: this.browser.wsEndpoint()
495
792
  });
496
793
  const d = `${dest}?cacheBust=${Date.now()}`;
@@ -506,69 +803,72 @@ ${addableFiles.map((x) => {
506
803
  })`;
507
804
  const fileStreams2 = [];
508
805
  const doneFileStream2 = [];
509
- const stdoutStream = fs.createWriteStream(`${destFolder}/stdout.log`);
510
- const stderrStream = fs.createWriteStream(`${destFolder}/stderr.log`);
806
+ const stdoutStream = fs2.createWriteStream(`${destFolder}/stdout.log`);
807
+ const stderrStream = fs2.createWriteStream(`${destFolder}/stderr.log`);
511
808
  this.browser.newPage().then((page) => {
809
+ page.on("console", (msg) => {
810
+ console.log("web > ", msg.args(), msg.text());
811
+ });
512
812
  page.exposeFunction(
513
813
  "screencast",
514
- async (ssOpts, testName) => {
814
+ async (ssOpts, testName2) => {
515
815
  const p = ssOpts.path;
516
- const dir = path2.dirname(p);
517
- fs.mkdirSync(dir, {
816
+ const dir = path3.dirname(p);
817
+ fs2.mkdirSync(dir, {
518
818
  recursive: true
519
819
  });
520
- if (!files[testName]) {
521
- files[testName] = /* @__PURE__ */ new Set();
820
+ if (!files2[testName2]) {
821
+ files2[testName2] = /* @__PURE__ */ new Set();
522
822
  }
523
- files[testName].add(ssOpts.path);
823
+ files2[testName2].add(ssOpts.path);
524
824
  const sPromise = page.screenshot({
525
825
  ...ssOpts,
526
826
  path: p
527
827
  });
528
- if (!screenshots[testName]) {
529
- screenshots[testName] = [];
828
+ if (!screenshots2[testName2]) {
829
+ screenshots2[testName2] = [];
530
830
  }
531
- screenshots[testName].push(sPromise);
831
+ screenshots2[testName2].push(sPromise);
532
832
  await sPromise;
533
833
  return sPromise;
534
834
  }
535
835
  );
536
836
  page.exposeFunction(
537
837
  "customScreenShot",
538
- async (ssOpts, testName) => {
838
+ async (ssOpts, testName2) => {
539
839
  const p = ssOpts.path;
540
- const dir = path2.dirname(p);
541
- fs.mkdirSync(dir, {
840
+ const dir = path3.dirname(p);
841
+ fs2.mkdirSync(dir, {
542
842
  recursive: true
543
843
  });
544
- if (!files[testName]) {
545
- files[testName] = /* @__PURE__ */ new Set();
844
+ if (!files2[testName2]) {
845
+ files2[testName2] = /* @__PURE__ */ new Set();
546
846
  }
547
- files[testName].add(ssOpts.path);
847
+ files2[testName2].add(ssOpts.path);
548
848
  const sPromise = page.screenshot({
549
849
  ...ssOpts,
550
850
  path: p
551
851
  });
552
- if (!screenshots[testName]) {
553
- screenshots[testName] = [];
852
+ if (!screenshots2[testName2]) {
853
+ screenshots2[testName2] = [];
554
854
  }
555
- screenshots[testName].push(sPromise);
855
+ screenshots2[testName2].push(sPromise);
556
856
  await sPromise;
557
857
  return sPromise;
558
858
  }
559
859
  );
560
860
  page.exposeFunction(
561
861
  "writeFileSync",
562
- (fp, contents, testName) => {
563
- return globalThis["writeFileSync"](fp, contents, testName);
862
+ (fp, contents, testName2) => {
863
+ return globalThis["writeFileSync"](fp, contents, testName2);
564
864
  }
565
865
  );
566
866
  page.exposeFunction("existsSync", (fp, contents) => {
567
- return fs.existsSync(fp);
867
+ return fs2.existsSync(fp);
568
868
  });
569
869
  page.exposeFunction("mkdirSync", (fp) => {
570
- if (!fs.existsSync(fp)) {
571
- return fs.mkdirSync(fp, {
870
+ if (!fs2.existsSync(fp)) {
871
+ return fs2.mkdirSync(fp, {
572
872
  recursive: true
573
873
  });
574
874
  }
@@ -576,12 +876,12 @@ ${addableFiles.map((x) => {
576
876
  });
577
877
  page.exposeFunction(
578
878
  "createWriteStream",
579
- (fp, testName) => {
580
- const f = fs.createWriteStream(fp);
581
- if (!files[testName]) {
582
- files[testName] = /* @__PURE__ */ new Set();
879
+ (fp, testName2) => {
880
+ const f = fs2.createWriteStream(fp);
881
+ if (!files2[testName2]) {
882
+ files2[testName2] = /* @__PURE__ */ new Set();
583
883
  }
584
- files[testName].add(fp);
884
+ files2[testName2].add(fp);
585
885
  const p = new Promise((res, rej) => {
586
886
  res(fp);
587
887
  });
@@ -645,436 +945,172 @@ ${addableFiles.map((x) => {
645
945
  return page;
646
946
  }).then(async (page) => {
647
947
  const close = () => {
648
- if (!files[t]) {
649
- files[t] = /* @__PURE__ */ new Set();
948
+ if (!files2[src]) {
949
+ files2[src] = /* @__PURE__ */ new Set();
650
950
  }
651
- fs.writeFileSync(
951
+ fs2.writeFileSync(
652
952
  destFolder + "/manifest.json",
653
- JSON.stringify(Array.from(files[t]))
953
+ JSON.stringify(Array.from(files2[src]))
654
954
  );
655
- delete files[t];
656
- Promise.all(screenshots[t] || []).then(() => {
657
- delete screenshots[t];
955
+ delete files2[src];
956
+ Promise.all(screenshots2[src] || []).then(() => {
957
+ delete screenshots2[src];
658
958
  page.close();
659
- this.testIsNowDone(t);
660
959
  stderrStream.close();
661
960
  stdoutStream.close();
662
961
  });
663
962
  };
664
963
  page.on("pageerror", (err) => {
665
- console.debug(`Error from ${t}: [${err.name}] `);
964
+ console.debug(`Error from ${src}: [${err.name}] `);
666
965
  stderrStream.write(err.name);
667
966
  if (err.cause) {
668
- console.debug(`Error from ${t} cause: [${err.cause}] `);
967
+ console.debug(`Error from ${src} cause: [${err.cause}] `);
669
968
  stderrStream.write(err.cause);
670
969
  }
671
970
  if (err.stack) {
672
- console.debug(`Error from stack ${t}: [${err.stack}] `);
971
+ console.debug(`Error from stack ${src}: [${err.stack}] `);
673
972
  stderrStream.write(err.stack);
674
973
  }
675
- console.debug(`Error from message ${t}: [${err.message}] `);
974
+ console.debug(`Error from message ${src}: [${err.message}] `);
676
975
  stderrStream.write(err.message);
976
+ this.bddTestIsNowDone(src, -1);
677
977
  close();
678
978
  });
679
979
  page.on("console", (log) => {
680
980
  stdoutStream.write(log.text());
681
- stdoutStream.write(JSON.stringify(log.location()));
682
- stdoutStream.write(JSON.stringify(log.stackTrace()));
683
- });
684
- await page.goto(`file://${`${destFolder}.html`}`, {});
685
- await page.evaluate(evaluation).then(async ({ failed, features }) => {
686
- this.receiveFeatures(features, destFolder, t);
687
- statusMessagePretty(failed, t);
688
- this.receiveExitCode(t, failed);
689
- }).catch((e) => {
690
- console.log(ansiC.red(ansiC.inverse(`${t} errored with: ${e}`)));
691
- }).finally(() => {
692
- close();
693
- });
694
- return page;
695
- });
696
- };
697
- this.receiveFeatures = (features, destFolder, srcTest) => {
698
- const featureDestination = path2.resolve(
699
- process.cwd(),
700
- "docs",
701
- "features",
702
- "strings",
703
- srcTest.split(".").slice(0, -1).join(".") + ".features.txt"
704
- );
705
- features.reduce(async (mm, featureStringKey) => {
706
- const accum = await mm;
707
- const isUrl = isValidUrl(featureStringKey);
708
- if (isUrl) {
709
- const u = new URL(featureStringKey);
710
- if (u.protocol === "file:") {
711
- const newPath = `${process.cwd()}/docs/features/internal/${path2.relative(
712
- process.cwd(),
713
- u.pathname
714
- )}`;
715
- await fs.promises.mkdir(path2.dirname(newPath), { recursive: true });
716
- try {
717
- await fs.unlinkSync(newPath);
718
- } catch (error) {
719
- if (error.code !== "ENOENT") {
720
- }
721
- }
722
- accum.files.push(newPath);
723
- } else if (u.protocol === "http:" || u.protocol === "https:") {
724
- const newPath = `${process.cwd()}/docs/features/external${u.hostname}${u.pathname}`;
725
- const body = await this.configs.featureIngestor(featureStringKey);
726
- writeFileAndCreateDir(newPath, body);
727
- accum.files.push(newPath);
728
- }
729
- } else {
730
- await fs.promises.mkdir(path2.dirname(featureDestination), {
731
- recursive: true
732
- });
733
- accum.strings.push(featureStringKey);
734
- }
735
- return accum;
736
- }, Promise.resolve({ files: [], strings: [] })).then(({ files: files2, strings }) => {
737
- fs.writeFileSync(
738
- `${destFolder}/featurePrompt.txt`,
739
- files2.map((f) => {
740
- return `/read ${f}`;
741
- }).join("\n")
742
- );
743
- });
744
- };
745
- this.receiveExitCode = (srcTest, failures) => {
746
- this.bigBoard[srcTest].runTimeError = failures;
747
- this.writeBigBoard();
748
- };
749
- this.writeBigBoard = () => {
750
- fs.writeFileSync(
751
- "./docs/summary.json",
752
- JSON.stringify(this.bigBoard, null, 2)
753
- );
754
- };
755
- this.mode = configs.devMode ? "DEV" : "PROD";
756
- this.server = {};
757
- this.configs = configs;
758
- this.ports = {};
759
- this.configs.tests.forEach(([t]) => {
760
- this.bigBoard[t] = {
761
- runTimeError: "?",
762
- typeErrors: "?",
763
- staticErrors: "?",
764
- prompt: "?"
765
- };
766
- });
767
- this.configs.ports.forEach((element) => {
768
- this.ports[element] = "true";
769
- });
770
- globalThis["waitForSelector"] = async (pageKey, sel) => {
771
- const page = (await this.browser.pages()).find(
772
- /* @ts-ignore:next-line */
773
- (p) => p.mainFrame()._id === pageKey
774
- );
775
- await page?.waitForSelector(sel);
776
- };
777
- globalThis["screencastStop"] = async (path3) => {
778
- return recorders[path3].stop();
779
- };
780
- globalThis["closePage"] = async (pageKey) => {
781
- const page = (await this.browser.pages()).find(
782
- /* @ts-ignore:next-line */
783
- (p) => p.mainFrame()._id === pageKey
784
- );
785
- return page.close();
786
- };
787
- globalThis["goto"] = async (pageKey, url) => {
788
- const page = (await this.browser.pages()).find(
789
- /* @ts-ignore:next-line */
790
- (p) => p.mainFrame()._id === pageKey
791
- );
792
- await page?.goto(url);
793
- return;
794
- };
795
- globalThis["newPage"] = () => {
796
- return this.browser.newPage();
797
- };
798
- globalThis["pages"] = () => {
799
- return this.browser.pages();
800
- };
801
- globalThis["mkdirSync"] = (fp) => {
802
- if (!fs.existsSync(fp)) {
803
- return fs.mkdirSync(fp, {
804
- recursive: true
805
- });
806
- }
807
- return false;
808
- };
809
- globalThis["writeFileSync"] = (filepath, contents, testName) => {
810
- fs.mkdirSync(path2.dirname(filepath), {
811
- recursive: true
812
- });
813
- if (!files[testName]) {
814
- files[testName] = /* @__PURE__ */ new Set();
815
- }
816
- files[testName].add(filepath);
817
- return fs.writeFileSync(filepath, contents);
818
- };
819
- globalThis["createWriteStream"] = (filepath, testName) => {
820
- const f = fs.createWriteStream(filepath);
821
- fileStreams3.push(f);
822
- if (!files[testName]) {
823
- files[testName] = /* @__PURE__ */ new Set();
824
- }
825
- files[testName].add(filepath);
826
- return {
827
- ...JSON.parse(JSON.stringify(f)),
828
- uid: fileStreams3.length - 1
829
- };
830
- };
831
- globalThis["write"] = (uid, contents) => {
832
- fileStreams3[uid].write(contents);
833
- };
834
- globalThis["end"] = (uid) => {
835
- fileStreams3[uid].end();
836
- };
837
- globalThis["customScreenShot"] = async (opts, pageKey, testName) => {
838
- const page = (await this.browser.pages()).find(
839
- /* @ts-ignore:next-line */
840
- (p2) => p2.mainFrame()._id === pageKey
841
- );
842
- const p = opts.path;
843
- const dir = path2.dirname(p);
844
- fs.mkdirSync(dir, {
845
- recursive: true
846
- });
847
- if (!files[opts.path]) {
848
- files[opts.path] = /* @__PURE__ */ new Set();
849
- }
850
- files[opts.path].add(opts.path);
851
- const sPromise = page.screenshot({
852
- ...opts,
853
- path: p
854
- });
855
- if (!screenshots[opts.path]) {
856
- screenshots[opts.path] = [];
857
- }
858
- screenshots[opts.path].push(sPromise);
859
- await sPromise;
860
- return sPromise;
861
- };
862
- globalThis["screencast"] = async (opts, pageKey) => {
863
- const page = (await this.browser.pages()).find(
864
- /* @ts-ignore:next-line */
865
- (p2) => p2.mainFrame()._id === pageKey
866
- );
867
- const p = opts.path;
868
- const dir = path2.dirname(p);
869
- fs.mkdirSync(dir, {
870
- recursive: true
871
- });
872
- const recorder = await page?.screencast({
873
- ...opts,
874
- path: p
981
+ stdoutStream.write(JSON.stringify(log.location()));
982
+ stdoutStream.write(JSON.stringify(log.stackTrace()));
983
+ });
984
+ await page.goto(`file://${`${destFolder}.html`}`, {});
985
+ await page.evaluate(evaluation).then(async ({ failed, features }) => {
986
+ this.receiveFeatures(features, destFolder, src, "web");
987
+ statusMessagePretty(failed, src);
988
+ this.bddTestIsNowDone(src, failed);
989
+ }).catch((e) => {
990
+ console.log(ansiC.red(ansiC.inverse(`${src} errored with: ${e}`)));
991
+ }).finally(() => {
992
+ this.bddTestIsNowDone(src, -1);
993
+ close();
994
+ });
995
+ return page;
875
996
  });
876
- recorders[opts.path] = recorder;
877
- return opts.path;
878
997
  };
879
- }
880
- customclose() {
881
- throw new Error("Method not implemented.");
882
- }
883
- waitForSelector(p, s) {
884
- throw new Error("Method not implemented.");
885
- }
886
- closePage(p) {
887
- throw new Error("Method not implemented.");
888
- }
889
- newPage() {
890
- throw new Error("Method not implemented.");
891
- }
892
- goto(p, url) {
893
- throw new Error("Method not implemented.");
894
- }
895
- $(selector) {
896
- throw new Error("Method not implemented.");
897
- }
898
- screencast(opts) {
899
- throw new Error("Method not implemented.");
900
- }
901
- customScreenShot(opts, cdpPage) {
902
- throw new Error("Method not implemented.");
903
- }
904
- end(accessObject) {
905
- throw new Error("Method not implemented.");
906
- }
907
- existsSync(destFolder) {
908
- return fs.existsSync(destFolder);
909
- }
910
- async mkdirSync(fp) {
911
- if (!fs.existsSync(fp)) {
912
- return fs.mkdirSync(fp, {
913
- recursive: true
914
- });
915
- }
916
- return false;
917
- }
918
- writeFileSync(fp, contents) {
919
- fs.writeFileSync(fp, contents);
920
- }
921
- createWriteStream(filepath) {
922
- return fs.createWriteStream(filepath);
923
- }
924
- testArtiFactoryfileWriter(tLog, callback) {
925
- return (fPath, value) => {
926
- callback(
927
- new Promise((res, rej) => {
928
- tLog("testArtiFactory =>", fPath);
929
- const cleanPath = path2.resolve(fPath);
930
- fPaths.push(cleanPath.replace(process.cwd(), ``));
931
- const targetDir = cleanPath.split("/").slice(0, -1).join("/");
932
- fs.mkdir(targetDir, { recursive: true }, async (error) => {
933
- if (error) {
934
- console.error(`\u2757\uFE0FtestArtiFactory failed`, targetDir, error);
935
- }
936
- fs.writeFileSync(
937
- path2.resolve(
938
- targetDir.split("/").slice(0, -1).join("/"),
939
- "manifest"
940
- ),
941
- fPaths.join(`
942
- `),
943
- {
944
- encoding: "utf-8"
998
+ this.receiveFeatures = (features, destFolder, srcTest, platform) => {
999
+ const featureDestination = path3.resolve(
1000
+ process.cwd(),
1001
+ "reports",
1002
+ "features",
1003
+ "strings",
1004
+ srcTest.split(".").slice(0, -1).join(".") + ".features.txt"
1005
+ );
1006
+ features.reduce(async (mm, featureStringKey) => {
1007
+ const accum = await mm;
1008
+ const isUrl = isValidUrl(featureStringKey);
1009
+ if (isUrl) {
1010
+ const u = new URL(featureStringKey);
1011
+ if (u.protocol === "file:") {
1012
+ const newPath = `${process.cwd()}/testeranto/features/internal/${path3.relative(
1013
+ process.cwd(),
1014
+ u.pathname
1015
+ )}`;
1016
+ await fs2.promises.mkdir(path3.dirname(newPath), { recursive: true });
1017
+ try {
1018
+ await fs2.unlinkSync(newPath);
1019
+ } catch (error) {
1020
+ if (error.code !== "ENOENT") {
945
1021
  }
946
- );
947
- if (Buffer.isBuffer(value)) {
948
- fs.writeFileSync(fPath, value, "binary");
949
- res();
950
- } else if (`string` === typeof value) {
951
- fs.writeFileSync(fPath, value.toString(), {
952
- encoding: "utf-8"
953
- });
954
- res();
955
- } else {
956
- const pipeStream = value;
957
- const myFile = fs.createWriteStream(fPath);
958
- pipeStream.pipe(myFile);
959
- pipeStream.on("close", () => {
960
- myFile.close();
961
- res();
962
- });
963
1022
  }
964
- });
965
- })
966
- );
967
- };
968
- }
969
- write(accessObject, contents) {
970
- throw new Error("Method not implemented.");
971
- }
972
- page() {
973
- throw new Error("Method not implemented.");
974
- }
975
- click(selector) {
976
- throw new Error("Method not implemented.");
977
- }
978
- focusOn(selector) {
979
- throw new Error("Method not implemented.");
980
- }
981
- typeInto(value) {
982
- throw new Error("Method not implemented.");
983
- }
984
- getValue(value) {
985
- throw new Error("Method not implemented.");
986
- }
987
- getAttribute(selector, attribute) {
988
- throw new Error("Method not implemented.");
989
- }
990
- isDisabled(selector) {
991
- throw new Error("Method not implemented.");
992
- }
993
- screencastStop(s) {
994
- throw new Error("Method not implemented.");
995
- }
996
- ////////////////////////////////////////////////////////////////////////////////
997
- async metafileOutputs(platform) {
998
- const metafile = JSON.parse(
999
- fs.readFileSync(`docs/${platform}/metafile.json`).toString()
1000
- ).metafile;
1001
- if (!metafile)
1002
- return;
1003
- const outputs = metafile.outputs;
1004
- Object.keys(outputs).forEach(async (k) => {
1005
- const addableFiles = Object.keys(outputs[k].inputs).filter((i) => {
1006
- if (!fs.existsSync(i))
1007
- return false;
1008
- if (i.startsWith("node_modules"))
1009
- return false;
1010
- return true;
1011
- });
1012
- const f = `${k.split(".").slice(0, -1).join(".")}/`;
1013
- if (!fs.existsSync(f)) {
1014
- fs.mkdirSync(f);
1015
- }
1016
- const entrypoint = outputs[k].entryPoint;
1017
- if (entrypoint) {
1018
- const changeDigest = await filesHash(addableFiles);
1019
- if (changeDigest === changes[entrypoint]) {
1023
+ accum.files.push(newPath);
1024
+ } else if (u.protocol === "http:" || u.protocol === "https:") {
1025
+ const newPath = `${process.cwd()}/testeranto/features/external${u.hostname}${u.pathname}`;
1026
+ const body = await this.configs.featureIngestor(featureStringKey);
1027
+ writeFileAndCreateDir(newPath, body);
1028
+ accum.files.push(newPath);
1029
+ }
1020
1030
  } else {
1021
- changes[entrypoint] = changeDigest;
1022
- this.tscCheck({
1023
- platform,
1024
- addableFiles,
1025
- entrypoint: "./" + entrypoint
1031
+ await fs2.promises.mkdir(path3.dirname(featureDestination), {
1032
+ recursive: true
1026
1033
  });
1027
- this.eslintCheck("./" + entrypoint, platform, addableFiles);
1028
- this.makePrompt("./" + entrypoint, addableFiles, platform);
1034
+ accum.strings.push(featureStringKey);
1029
1035
  }
1030
- }
1036
+ return accum;
1037
+ }, Promise.resolve({ files: [], strings: [] })).then(({ files: files3, strings }) => {
1038
+ fs2.writeFileSync(
1039
+ // `${destFolder}/featurePrompt.txt`,
1040
+ `testeranto/reports/${this.name}/${srcTest.split(".").slice(0, -1).join(".")}/${platform}/featurePrompt.txt`,
1041
+ files3.map((f) => {
1042
+ return `/read ${f}`;
1043
+ }).join("\n")
1044
+ );
1045
+ });
1046
+ };
1047
+ this.writeBigBoard = () => {
1048
+ fs2.writeFileSync(
1049
+ `./testeranto/reports/${this.name}/summary.json`,
1050
+ JSON.stringify(this.bigBoard, null, 2)
1051
+ );
1052
+ };
1053
+ this.name = name;
1054
+ this.mode = mode2;
1055
+ this.ports = {};
1056
+ this.configs.tests.forEach(([t]) => {
1057
+ this.bigBoard[t] = {
1058
+ runTimeError: "?",
1059
+ typeErrors: "?",
1060
+ staticErrors: "?",
1061
+ prompt: "?"
1062
+ };
1063
+ });
1064
+ this.configs.ports.forEach((element) => {
1065
+ this.ports[element] = "true";
1031
1066
  });
1032
1067
  }
1033
1068
  async start() {
1069
+ if (!fs2.existsSync(`testeranto/reports/${this.name}`)) {
1070
+ fs2.mkdirSync(`testeranto/reports/${this.name}`);
1071
+ }
1034
1072
  this.browser = await puppeteer.launch({
1035
1073
  slowMo: 1,
1036
- // timeout: 1,
1037
1074
  waitForInitialPage: false,
1038
1075
  executablePath: (
1039
1076
  // process.env.CHROMIUM_PATH || "/opt/homebrew/bin/chromium",
1040
1077
  "/opt/homebrew/bin/chromium"
1041
1078
  ),
1042
1079
  headless: true,
1043
- dumpio: true,
1044
- // timeout: 0,
1045
- devtools: true,
1080
+ dumpio: false,
1081
+ devtools: false,
1046
1082
  args: [
1047
- "--auto-open-devtools-for-tabs",
1048
- `--remote-debugging-port=3234`,
1049
- // "--disable-features=IsolateOrigins,site-per-process",
1050
- "--disable-site-isolation-trials",
1051
- "--allow-insecure-localhost",
1052
1083
  "--allow-file-access-from-files",
1084
+ "--allow-insecure-localhost",
1053
1085
  "--allow-running-insecure-content",
1086
+ "--auto-open-devtools-for-tabs",
1054
1087
  "--disable-dev-shm-usage",
1055
1088
  "--disable-extensions",
1056
1089
  "--disable-gpu",
1057
1090
  "--disable-setuid-sandbox",
1058
1091
  "--disable-site-isolation-trials",
1092
+ "--disable-site-isolation-trials",
1059
1093
  "--disable-web-security",
1060
1094
  "--no-first-run",
1061
1095
  "--no-sandbox",
1062
1096
  "--no-startup-window",
1063
- // "--no-zygote",
1064
1097
  "--reduce-security-for-testing",
1065
1098
  "--remote-allow-origins=*",
1099
+ `--remote-debugging-port=3234`,
1066
1100
  "--unsafely-treat-insecure-origin-as-secure=*"
1101
+ // "--disable-features=IsolateOrigins,site-per-process",
1067
1102
  // "--disable-features=IsolateOrigins",
1103
+ // "--disk-cache-dir=/dev/null",
1104
+ // "--disk-cache-size=1",
1105
+ // "--no-zygote",
1068
1106
  // "--remote-allow-origins=ws://localhost:3234",
1069
1107
  // "--single-process",
1108
+ // "--start-maximized",
1070
1109
  // "--unsafely-treat-insecure-origin-as-secure",
1071
1110
  // "--unsafely-treat-insecure-origin-as-secure=ws://192.168.0.101:3234",
1072
- // "--disk-cache-dir=/dev/null",
1073
- // "--disk-cache-size=1",
1074
- // "--start-maximized",
1075
1111
  ]
1076
1112
  });
1077
- const { nodeEntryPoints, webEntryPoints } = getRunnables(
1113
+ const { nodeEntryPoints, webEntryPoints } = this.getRunnables(
1078
1114
  this.configs.tests
1079
1115
  );
1080
1116
  Object.entries(nodeEntryPoints).forEach(
@@ -1108,22 +1144,59 @@ ${addableFiles.map((x) => {
1108
1144
  }
1109
1145
  );
1110
1146
  this.metafileOutputs("node");
1111
- this.nodeMetafileWatcher = watch(
1112
- "docs/node/metafile.json",
1113
- async (e, filename) => {
1114
- console.log(ansiC.green(ansiC.inverse(`< ${e} ${filename} (node)`)));
1115
- this.metafileOutputs("node");
1116
- }
1117
- );
1147
+ const w = `./testeranto/bundles/node/${this.name}/metafile.json`;
1148
+ console.log("w", w);
1149
+ this.nodeMetafileWatcher = watch(w, async (e, filename) => {
1150
+ console.log(ansiC.green(ansiC.inverse(`< ${e} ${filename} (node)`)));
1151
+ this.metafileOutputs("node");
1152
+ });
1118
1153
  this.metafileOutputs("web");
1119
1154
  this.webMetafileWatcher = watch(
1120
- "docs/web/metafile.json",
1155
+ `./testeranto/bundles/web/${this.name}/metafile.json`,
1121
1156
  async (e, filename) => {
1122
1157
  console.log(ansiC.green(ansiC.inverse(`< ${e} ${filename} (web)`)));
1123
1158
  this.metafileOutputs("web");
1124
1159
  }
1125
1160
  );
1126
1161
  }
1162
+ async metafileOutputs(platform) {
1163
+ const metafile = JSON.parse(
1164
+ fs2.readFileSync(
1165
+ `./testeranto/bundles/${platform}/${this.name}/metafile.json`
1166
+ ).toString()
1167
+ ).metafile;
1168
+ if (!metafile)
1169
+ return;
1170
+ const outputs = metafile.outputs;
1171
+ Object.keys(outputs).forEach(async (k) => {
1172
+ const addableFiles = Object.keys(outputs[k].inputs).filter((i) => {
1173
+ if (!fs2.existsSync(i))
1174
+ return false;
1175
+ if (i.startsWith("node_modules"))
1176
+ return false;
1177
+ return true;
1178
+ });
1179
+ const f = `${k.split(".").slice(0, -1).join(".")}/`;
1180
+ if (!fs2.existsSync(f)) {
1181
+ fs2.mkdirSync(f);
1182
+ }
1183
+ const entrypoint = outputs[k].entryPoint;
1184
+ if (entrypoint) {
1185
+ const changeDigest = await filesHash(addableFiles);
1186
+ if (changeDigest === changes[entrypoint]) {
1187
+ } else {
1188
+ changes[entrypoint] = changeDigest;
1189
+ this.tscCheck({
1190
+ platform,
1191
+ addableFiles,
1192
+ entrypoint: "./" + entrypoint
1193
+ });
1194
+ this.eslintCheck("./" + entrypoint, platform, addableFiles);
1195
+ this.makePrompt("./" + entrypoint, addableFiles, platform);
1196
+ }
1197
+ }
1198
+ });
1199
+ }
1127
1200
  };
1128
1201
 
1129
1202
  // src/run.ts
@@ -1137,13 +1210,21 @@ process.stdin.on("keypress", (str, key) => {
1137
1210
  process.exit(-1);
1138
1211
  }
1139
1212
  });
1140
- import(process.cwd() + "/" + process.argv[2]).then(async (module) => {
1141
- const rawConfig = module.default;
1213
+ var testName = process.argv[2];
1214
+ var mode = process.argv[3];
1215
+ if (mode !== "once" && mode !== "dev") {
1216
+ console.error("the 2nd argument should be 'dev' or 'once' ");
1217
+ process.exit(-1);
1218
+ }
1219
+ console.log("testeranto is running", testName, mode);
1220
+ import(process.cwd() + "/testeranto.config.ts").then(async (module) => {
1221
+ const bigConfig = module.default;
1222
+ const rawConfig = bigConfig.projects[testName];
1142
1223
  const config = {
1143
1224
  ...rawConfig,
1144
- buildDir: process.cwd() + "/" + rawConfig.outdir
1225
+ buildDir: process.cwd() + `/testeranto/${testName}.json`
1145
1226
  };
1146
- const pm = new PM_Main(config);
1227
+ const pm = new PM_Main(config, testName, mode);
1147
1228
  pm.start();
1148
1229
  process.stdin.on("keypress", (str, key) => {
1149
1230
  if (key.name === "q") {