@midscene/core 1.17.4 → 1.17.5

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 (86) hide show
  1. package/dist/es/agent/agent-report-manager.mjs +28 -5
  2. package/dist/es/agent/agent-report-manager.mjs.map +1 -1
  3. package/dist/es/agent/agent.mjs +2 -2
  4. package/dist/es/agent/agent.mjs.map +1 -1
  5. package/dist/es/agent/utils.mjs +1 -1
  6. package/dist/es/dump/html-utils.mjs +51 -68
  7. package/dist/es/dump/html-utils.mjs.map +1 -1
  8. package/dist/es/dump/report-artifact-publication.mjs +52 -0
  9. package/dist/es/dump/report-artifact-publication.mjs.map +1 -0
  10. package/dist/es/dump/report-artifact-store.mjs +2 -2
  11. package/dist/es/dump/report-artifact-store.mjs.map +1 -1
  12. package/dist/es/dump/report-artifact-writer.mjs +129 -0
  13. package/dist/es/dump/report-artifact-writer.mjs.map +1 -0
  14. package/dist/es/dump/report-session.mjs +229 -0
  15. package/dist/es/dump/report-session.mjs.map +1 -0
  16. package/dist/es/dump/test-report-images.mjs +68 -42
  17. package/dist/es/dump/test-report-images.mjs.map +1 -1
  18. package/dist/es/index.mjs +2 -2
  19. package/dist/es/index.mjs.map +1 -1
  20. package/dist/es/report-cli.mjs +38 -11
  21. package/dist/es/report-cli.mjs.map +1 -1
  22. package/dist/es/report-generator.mjs +2 -1
  23. package/dist/es/report-generator.mjs.map +1 -1
  24. package/dist/es/report-html-template.mjs +1 -1
  25. package/dist/es/report.mjs +152 -159
  26. package/dist/es/report.mjs.map +1 -1
  27. package/dist/es/test-run-report.mjs.map +1 -1
  28. package/dist/es/utils.mjs +1 -1
  29. package/dist/es/yaml/player.mjs +1 -1
  30. package/dist/es/yaml/player.mjs.map +1 -1
  31. package/dist/lib/agent/agent-report-manager.js +27 -4
  32. package/dist/lib/agent/agent-report-manager.js.map +1 -1
  33. package/dist/lib/agent/agent.js +2 -2
  34. package/dist/lib/agent/agent.js.map +1 -1
  35. package/dist/lib/agent/utils.js +1 -1
  36. package/dist/lib/dump/html-utils.js +59 -70
  37. package/dist/lib/dump/html-utils.js.map +1 -1
  38. package/dist/lib/dump/report-artifact-publication.js +89 -0
  39. package/dist/lib/dump/report-artifact-publication.js.map +1 -0
  40. package/dist/lib/dump/report-artifact-store.js +2 -2
  41. package/dist/lib/dump/report-artifact-store.js.map +1 -1
  42. package/dist/lib/dump/report-artifact-writer.js +163 -0
  43. package/dist/lib/dump/report-artifact-writer.js.map +1 -0
  44. package/dist/lib/dump/report-session.js +266 -0
  45. package/dist/lib/dump/report-session.js.map +1 -0
  46. package/dist/lib/dump/test-report-images.js +67 -41
  47. package/dist/lib/dump/test-report-images.js.map +1 -1
  48. package/dist/lib/index.js +3 -0
  49. package/dist/lib/index.js.map +1 -1
  50. package/dist/lib/report-cli.js +37 -10
  51. package/dist/lib/report-cli.js.map +1 -1
  52. package/dist/lib/report-generator.js +2 -1
  53. package/dist/lib/report-generator.js.map +1 -1
  54. package/dist/lib/report-html-template.js +1 -1
  55. package/dist/lib/report.js +152 -153
  56. package/dist/lib/report.js.map +1 -1
  57. package/dist/lib/test-run-report.js.map +1 -1
  58. package/dist/lib/utils.js +1 -1
  59. package/dist/lib/yaml/player.js +1 -1
  60. package/dist/lib/yaml/player.js.map +1 -1
  61. package/dist/types/agent/agent-report-manager.d.ts +4 -1
  62. package/dist/types/agent/agent-report-manager.d.ts.map +1 -1
  63. package/dist/types/agent/agent.d.ts +1 -1
  64. package/dist/types/agent/agent.d.ts.map +1 -1
  65. package/dist/types/dump/html-utils.d.ts +7 -1
  66. package/dist/types/dump/html-utils.d.ts.map +1 -1
  67. package/dist/types/dump/report-artifact-publication.d.ts +5 -0
  68. package/dist/types/dump/report-artifact-publication.d.ts.map +1 -0
  69. package/dist/types/dump/report-artifact-store.d.ts +1 -1
  70. package/dist/types/dump/report-artifact-store.d.ts.map +1 -1
  71. package/dist/types/dump/report-artifact-writer.d.ts +21 -0
  72. package/dist/types/dump/report-artifact-writer.d.ts.map +1 -0
  73. package/dist/types/dump/report-session.d.ts +48 -0
  74. package/dist/types/dump/report-session.d.ts.map +1 -0
  75. package/dist/types/dump/test-report-images.d.ts +5 -2
  76. package/dist/types/dump/test-report-images.d.ts.map +1 -1
  77. package/dist/types/index.d.ts +1 -1
  78. package/dist/types/index.d.ts.map +1 -1
  79. package/dist/types/report-cli.d.ts +2 -1
  80. package/dist/types/report-cli.d.ts.map +1 -1
  81. package/dist/types/report-generator.d.ts.map +1 -1
  82. package/dist/types/report.d.ts +11 -0
  83. package/dist/types/report.d.ts.map +1 -1
  84. package/dist/types/test-run-report.d.ts +2 -2
  85. package/dist/types/test-run-report.d.ts.map +1 -1
  86. package/package.json +2 -2
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ ReportArtifactWriter: ()=>ReportArtifactWriter
28
+ });
29
+ const external_node_fs_namespaceObject = require("node:fs");
30
+ const promises_namespaceObject = require("node:fs/promises");
31
+ const external_node_path_namespaceObject = require("node:path");
32
+ const report_artifact_namespaceObject = require("@midscene/shared/report-artifact");
33
+ const utils_namespaceObject = require("@midscene/shared/utils");
34
+ const external_utils_js_namespaceObject = require("../utils.js");
35
+ const external_html_utils_js_namespaceObject = require("./html-utils.js");
36
+ const external_report_artifact_store_js_namespaceObject = require("./report-artifact-store.js");
37
+ const external_test_report_images_js_namespaceObject = require("./test-report-images.js");
38
+ function _define_property(obj, key, value) {
39
+ if (key in obj) Object.defineProperty(obj, key, {
40
+ value: value,
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true
44
+ });
45
+ else obj[key] = value;
46
+ return obj;
47
+ }
48
+ class ReportArtifactWriter {
49
+ get template() {
50
+ const template = (0, external_utils_js_namespaceObject.getReportTpl)();
51
+ const end = template.lastIndexOf('</html>');
52
+ return (end < 0 ? template : template.slice(0, end)) + (this.external ? (0, external_html_utils_js_namespaceObject.getBaseUrlFixScript)() : '');
53
+ }
54
+ async initialize() {
55
+ await (0, promises_namespaceObject.mkdir)((0, external_node_path_namespaceObject.dirname)(this.entry), {
56
+ recursive: true
57
+ });
58
+ await (0, promises_namespaceObject.writeFile)(this.entry, this.template);
59
+ }
60
+ initializeSync() {
61
+ (0, external_node_fs_namespaceObject.mkdirSync)((0, external_node_path_namespaceObject.dirname)(this.entry), {
62
+ recursive: true
63
+ });
64
+ (0, external_node_fs_namespaceObject.writeFileSync)(this.entry, this.template);
65
+ }
66
+ group(id, attributes) {
67
+ if (this.manifest.groups.some((group)=>group.id === id)) throw new Error(`Duplicate report group: ${id}`);
68
+ const path = `data/group-${this.manifest.groups.length + 1}/1.json`;
69
+ this.manifest.groups.push({
70
+ id,
71
+ status: 'complete',
72
+ attributes: {
73
+ ...attributes,
74
+ 'data-screenshot-mode': 'directory'
75
+ },
76
+ dumps: [
77
+ path
78
+ ]
79
+ });
80
+ return (0, external_node_path_namespaceObject.join)((0, external_node_path_namespaceObject.dirname)(this.entry), path);
81
+ }
82
+ inlineGroup(id, attributes, serialized) {
83
+ return (0, external_utils_js_namespaceObject.reportHTMLContent)({
84
+ dumpString: serialized,
85
+ attributes: {
86
+ ...attributes,
87
+ 'data-group-id': id,
88
+ 'data-screenshot-mode': 'inline',
89
+ 'data-report-kind': this.manifest.kind
90
+ }
91
+ }, void 0, void 0, false);
92
+ }
93
+ async addGroup(id, serialized, sourcePath, attributes, origins) {
94
+ const rewritten = await this.images.rewriteAsync(serialized, sourcePath, origins);
95
+ if (this.external) await (0, external_report_artifact_store_js_namespaceObject.writeReportArtifactFile)(this.group(id, attributes), rewritten);
96
+ else await (0, promises_namespaceObject.appendFile)(this.entry, this.inlineGroup(id, attributes, rewritten));
97
+ }
98
+ addGroupSync(id, serialized, sourcePath, attributes, origins) {
99
+ const rewritten = this.images.rewriteSync(serialized, sourcePath, origins);
100
+ if (this.external) {
101
+ const file = this.group(id, attributes);
102
+ (0, external_node_fs_namespaceObject.mkdirSync)((0, external_node_path_namespaceObject.dirname)(file), {
103
+ recursive: true
104
+ });
105
+ (0, external_node_fs_namespaceObject.writeFileSync)(file, rewritten);
106
+ } else (0, external_node_fs_namespaceObject.appendFileSync)(this.entry, this.inlineGroup(id, attributes, rewritten));
107
+ }
108
+ footer(runner, comment) {
109
+ const data = this.external ? (0, external_html_utils_js_namespaceObject.generateReportArtifactScriptTag)('report.json') : runner ? (0, external_html_utils_js_namespaceObject.generateTestRunReportScriptTag)(runner) : '';
110
+ return `${data}${comment}\n</html>\n`;
111
+ }
112
+ async finish(runner, comment = '') {
113
+ if (this.external) {
114
+ if (runner) {
115
+ this.manifest.runner = 'data/runner.json';
116
+ await (0, external_report_artifact_store_js_namespaceObject.writeReportArtifactFile)((0, external_node_path_namespaceObject.join)((0, external_node_path_namespaceObject.dirname)(this.entry), this.manifest.runner), JSON.stringify(runner));
117
+ }
118
+ (0, report_artifact_namespaceObject.parseReportArtifactManifest)(this.manifest);
119
+ await (0, external_report_artifact_store_js_namespaceObject.writeReportArtifactFile)((0, external_node_path_namespaceObject.join)((0, external_node_path_namespaceObject.dirname)(this.entry), 'report.json'), JSON.stringify(this.manifest));
120
+ }
121
+ await (0, promises_namespaceObject.appendFile)(this.entry, this.footer(runner, comment));
122
+ }
123
+ finishSync(runner, comment = '') {
124
+ if (this.external) {
125
+ if (runner) {
126
+ this.manifest.runner = 'data/runner.json';
127
+ (0, external_node_fs_namespaceObject.mkdirSync)((0, external_node_path_namespaceObject.join)((0, external_node_path_namespaceObject.dirname)(this.entry), 'data'), {
128
+ recursive: true
129
+ });
130
+ (0, external_node_fs_namespaceObject.writeFileSync)((0, external_node_path_namespaceObject.join)((0, external_node_path_namespaceObject.dirname)(this.entry), this.manifest.runner), JSON.stringify(runner));
131
+ }
132
+ (0, report_artifact_namespaceObject.parseReportArtifactManifest)(this.manifest);
133
+ (0, external_node_fs_namespaceObject.writeFileSync)((0, external_node_path_namespaceObject.join)((0, external_node_path_namespaceObject.dirname)(this.entry), 'report.json'), JSON.stringify(this.manifest));
134
+ }
135
+ (0, external_node_fs_namespaceObject.appendFileSync)(this.entry, this.footer(runner, comment));
136
+ }
137
+ constructor(entry, external, kind, reportId = (0, utils_namespaceObject.uuid)()){
138
+ _define_property(this, "entry", void 0);
139
+ _define_property(this, "external", void 0);
140
+ _define_property(this, "manifest", void 0);
141
+ _define_property(this, "images", void 0);
142
+ this.entry = entry;
143
+ this.external = external;
144
+ this.manifest = {
145
+ schemaVersion: 1,
146
+ kind,
147
+ reportId,
148
+ entry: (0, external_node_path_namespaceObject.basename)(entry),
149
+ status: 'complete',
150
+ groups: []
151
+ };
152
+ this.images = new external_test_report_images_js_namespaceObject.TestReportImages(entry, external);
153
+ }
154
+ }
155
+ exports.ReportArtifactWriter = __webpack_exports__.ReportArtifactWriter;
156
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
157
+ "ReportArtifactWriter"
158
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
159
+ Object.defineProperty(exports, '__esModule', {
160
+ value: true
161
+ });
162
+
163
+ //# sourceMappingURL=report-artifact-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dump/report-artifact-writer.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/dump/report-artifact-writer.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { appendFileSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { appendFile, mkdir, writeFile } from 'node:fs/promises';\nimport { basename, dirname, join } from 'node:path';\nimport {\n type ReportArtifactManifest,\n parseReportArtifactManifest,\n} from '@midscene/shared/report-artifact';\nimport { uuid } from '@midscene/shared/utils';\nimport type { TestRunReportDump } from '../test-run-report';\nimport { getReportTpl, reportHTMLContent } from '../utils';\nimport {\n generateReportArtifactScriptTag,\n generateTestRunReportScriptTag,\n getBaseUrlFixScript,\n} from './html-utils';\nimport { writeReportArtifactFile } from './report-artifact-store';\nimport { TestReportImages } from './test-report-images';\n\nexport type ReportGroupAttributes = Record<string, string | number | boolean>;\n\n/** Final publisher shared by Test, report merging, and format conversion. */\nexport class ReportArtifactWriter {\n private readonly manifest: ReportArtifactManifest;\n private readonly images: TestReportImages;\n\n constructor(\n private readonly entry: string,\n private readonly external: boolean,\n kind: 'agent' | 'test',\n reportId = uuid(),\n ) {\n this.manifest = {\n schemaVersion: 1,\n kind,\n reportId,\n entry: basename(entry),\n status: 'complete',\n groups: [],\n };\n this.images = new TestReportImages(entry, external);\n }\n\n private get template(): string {\n const template = getReportTpl();\n const end = template.lastIndexOf('</html>');\n return (\n (end < 0 ? template : template.slice(0, end)) +\n (this.external ? getBaseUrlFixScript() : '')\n );\n }\n\n async initialize(): Promise<void> {\n await mkdir(dirname(this.entry), { recursive: true });\n await writeFile(this.entry, this.template);\n }\n initializeSync(): void {\n mkdirSync(dirname(this.entry), { recursive: true });\n writeFileSync(this.entry, this.template);\n }\n\n private group(id: string, attributes: ReportGroupAttributes) {\n if (this.manifest.groups.some((group) => group.id === id))\n throw new Error(`Duplicate report group: ${id}`);\n const path = `data/group-${this.manifest.groups.length + 1}/1.json`;\n this.manifest.groups.push({\n id,\n status: 'complete',\n attributes: { ...attributes, 'data-screenshot-mode': 'directory' },\n dumps: [path],\n });\n return join(dirname(this.entry), path);\n }\n\n private inlineGroup(\n id: string,\n attributes: ReportGroupAttributes,\n serialized: string,\n ): string {\n return reportHTMLContent(\n {\n dumpString: serialized,\n attributes: {\n ...attributes,\n 'data-group-id': id,\n 'data-screenshot-mode': 'inline',\n 'data-report-kind': this.manifest.kind,\n },\n },\n undefined,\n undefined,\n false,\n );\n }\n\n async addGroup(\n id: string,\n serialized: string,\n sourcePath: string,\n attributes: ReportGroupAttributes,\n origins?: ReadonlyMap<string, string>,\n ): Promise<void> {\n const rewritten = await this.images.rewriteAsync(\n serialized,\n sourcePath,\n origins,\n );\n if (this.external)\n await writeReportArtifactFile(this.group(id, attributes), rewritten);\n else\n await appendFile(this.entry, this.inlineGroup(id, attributes, rewritten));\n }\n addGroupSync(\n id: string,\n serialized: string,\n sourcePath: string,\n attributes: ReportGroupAttributes,\n origins?: ReadonlyMap<string, string>,\n ): void {\n const rewritten = this.images.rewriteSync(serialized, sourcePath, origins);\n if (this.external) {\n const file = this.group(id, attributes);\n mkdirSync(dirname(file), { recursive: true });\n writeFileSync(file, rewritten);\n } else\n appendFileSync(this.entry, this.inlineGroup(id, attributes, rewritten));\n }\n\n private footer(\n runner: TestRunReportDump | undefined,\n comment: string,\n ): string {\n const data = this.external\n ? generateReportArtifactScriptTag('report.json')\n : runner\n ? generateTestRunReportScriptTag(runner)\n : '';\n return `${data}${comment}\\n</html>\\n`;\n }\n\n async finish(runner?: TestRunReportDump, comment = ''): Promise<void> {\n if (this.external) {\n if (runner) {\n this.manifest.runner = 'data/runner.json';\n await writeReportArtifactFile(\n join(dirname(this.entry), this.manifest.runner),\n JSON.stringify(runner),\n );\n }\n parseReportArtifactManifest(this.manifest);\n await writeReportArtifactFile(\n join(dirname(this.entry), 'report.json'),\n JSON.stringify(this.manifest),\n );\n }\n await appendFile(this.entry, this.footer(runner, comment));\n }\n finishSync(runner?: TestRunReportDump, comment = ''): void {\n if (this.external) {\n if (runner) {\n this.manifest.runner = 'data/runner.json';\n mkdirSync(join(dirname(this.entry), 'data'), { recursive: true });\n writeFileSync(\n join(dirname(this.entry), this.manifest.runner),\n JSON.stringify(runner),\n );\n }\n parseReportArtifactManifest(this.manifest);\n writeFileSync(\n join(dirname(this.entry), 'report.json'),\n JSON.stringify(this.manifest),\n );\n }\n appendFileSync(this.entry, this.footer(runner, comment));\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","ReportArtifactWriter","template","getReportTpl","end","getBaseUrlFixScript","mkdir","dirname","writeFile","mkdirSync","writeFileSync","id","attributes","group","Error","path","join","serialized","reportHTMLContent","undefined","sourcePath","origins","rewritten","writeReportArtifactFile","appendFile","file","appendFileSync","runner","comment","data","generateReportArtifactScriptTag","generateTestRunReportScriptTag","JSON","parseReportArtifactManifest","entry","external","kind","reportId","uuid","basename","TestReportImages"],"mappings":"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"}
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ currentReportSession: ()=>currentReportSession,
28
+ ReportSession: ()=>ReportSession
29
+ });
30
+ const promises_namespaceObject = require("node:fs/promises");
31
+ const external_node_path_namespaceObject = require("node:path");
32
+ const utils_namespaceObject = require("@midscene/shared/utils");
33
+ const external_yaml_execution_context_namespaceObject = require("#yaml-execution-context");
34
+ const external_execution_recorder_js_namespaceObject = require("./execution-recorder.js");
35
+ const external_image_reference_js_namespaceObject = require("./image-reference.js");
36
+ const external_report_artifact_store_js_namespaceObject = require("./report-artifact-store.js");
37
+ const external_screenshot_store_js_namespaceObject = require("./screenshot-store.js");
38
+ function _define_property(obj, key, value) {
39
+ if (key in obj) Object.defineProperty(obj, key, {
40
+ value: value,
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true
44
+ });
45
+ else obj[key] = value;
46
+ return obj;
47
+ }
48
+ const contextKey = Symbol.for('@midscene/core/report-session/v1');
49
+ const host = globalThis;
50
+ host[contextKey] ??= (0, external_yaml_execution_context_namespaceObject.createExecutionContext)();
51
+ const context = host[contextKey];
52
+ class ReportSession {
53
+ async run(callback) {
54
+ if (this.ended) throw new Error('The report session has ended.');
55
+ this.ownership ??= (async ()=>{
56
+ await (0, promises_namespaceObject.mkdir)((0, external_node_path_namespaceObject.dirname)(this.directory), {
57
+ recursive: true
58
+ });
59
+ await (0, promises_namespaceObject.mkdir)(this.directory);
60
+ })();
61
+ await this.ownership;
62
+ return context.run(this, callback);
63
+ }
64
+ createRecorder(isBusy) {
65
+ if (!this.ownership) throw new Error('Start the report session before creating a writer.');
66
+ if (this.ended) throw new Error('Cannot add a writer to an ended report session.');
67
+ const writer = new ReportSourceRecorder(this.directory, isBusy);
68
+ this.writers.add(writer);
69
+ return writer;
70
+ }
71
+ async finish() {
72
+ this.ended = true;
73
+ this.completion ??= (async ()=>{
74
+ const sources = [];
75
+ for (const writer of this.writers){
76
+ const source = await writer.captureUncollected();
77
+ if (source) sources.push(source);
78
+ if (writer.isBusy()) await writer.flush();
79
+ else await writer.finalize();
80
+ }
81
+ return sources;
82
+ })();
83
+ return this.completion;
84
+ }
85
+ async prune() {
86
+ if (!this.completion) throw new Error('Finish the report session before pruning it.');
87
+ await this.completion;
88
+ if (!this.writers.size) return void await (0, promises_namespaceObject.rm)(this.directory, {
89
+ recursive: true,
90
+ force: true
91
+ });
92
+ if ([
93
+ ...this.writers
94
+ ].some((writer)=>writer.isBusy())) return;
95
+ await (0, promises_namespaceObject.rm)((0, external_node_path_namespaceObject.join)(this.directory, 'data'), {
96
+ recursive: true,
97
+ force: true
98
+ });
99
+ await (0, promises_namespaceObject.rm)((0, external_node_path_namespaceObject.join)(this.directory, 'report.json'), {
100
+ force: true
101
+ });
102
+ const retained = new Set([
103
+ ...this.writers
104
+ ].flatMap((writer)=>[
105
+ ...writer.snapshotImages
106
+ ]));
107
+ const images = (0, external_node_path_namespaceObject.join)(this.directory, 'screenshots');
108
+ const files = await (0, promises_namespaceObject.readdir)(images).catch((error)=>{
109
+ if ('ENOENT' === error.code) return [];
110
+ throw error;
111
+ });
112
+ for (const file of files)if (!retained.has(`./screenshots/${file}`)) await (0, promises_namespaceObject.rm)((0, external_node_path_namespaceObject.join)(images, file));
113
+ }
114
+ constructor(directory){
115
+ _define_property(this, "directory", void 0);
116
+ _define_property(this, "writers", void 0);
117
+ _define_property(this, "ended", void 0);
118
+ _define_property(this, "completion", void 0);
119
+ _define_property(this, "ownership", void 0);
120
+ this.directory = directory;
121
+ this.writers = new Set();
122
+ this.ended = false;
123
+ if (!(0, external_node_path_namespaceObject.isAbsolute)(directory)) throw new Error('Report session directory must be absolute.');
124
+ }
125
+ }
126
+ const currentReportSession = ()=>context.getStore();
127
+ class ReportSourceRecorder {
128
+ getReportPath() {}
129
+ enableSourceSnapshots() {}
130
+ isBusy() {
131
+ return this.busy?.() ?? false;
132
+ }
133
+ onExecutionUpdate(execution, meta, attributes = {}) {
134
+ if (this.finalization) throw new Error('The report record stream has been finalized.');
135
+ const key = this.recorder.record(execution, meta);
136
+ const update = new external_execution_recorder_js_namespaceObject.ExecutionRecorder();
137
+ update.record(execution, meta);
138
+ const captured = update.capture();
139
+ this.queue = this.queue.then(async ()=>{
140
+ const serialized = await this.serialize(captured);
141
+ await this.store.writeExecution(key, serialized, Object.fromEntries(Object.entries(attributes).map(([key, value])=>[
142
+ key,
143
+ String(value)
144
+ ])));
145
+ });
146
+ }
147
+ async serialize(captured) {
148
+ for (const screenshot of captured.screenshots)await this.images.persist(screenshot);
149
+ const references = new Map();
150
+ for (const url of captured.referenceImageUrls)references.set(url, await this.images.persistReferenceImage(url));
151
+ return JSON.stringify(JSON.parse(captured.dump.serializeWithReferenceImages(references)), (_key, value)=>{
152
+ const ref = (0, external_image_reference_js_namespaceObject.normalizeStoredImageRef)(value);
153
+ if (!ref) return value;
154
+ return {
155
+ ...ref,
156
+ storage: 'file',
157
+ path: this.images.getFilePath(ref.id)
158
+ };
159
+ });
160
+ }
161
+ async createSourceSnapshot(scopeId, executionIds) {
162
+ if (this.finalization) throw new Error('The report record stream has been finalized.');
163
+ return this.snapshot(scopeId, executionIds);
164
+ }
165
+ async snapshot(scopeId, executionIds) {
166
+ if ('string' != typeof scopeId || !scopeId.trim()) throw new Error('Invalid report scope ID');
167
+ const busyAtCutoff = this.isBusy();
168
+ const captured = this.recorder.capture(executionIds, this.recorder.reportMeta ?? {
169
+ sdkVersion: '',
170
+ groupName: 'Test execution',
171
+ modelBriefs: []
172
+ });
173
+ const path = (0, external_node_path_namespaceObject.join)(this.directory, `${this.id}.${(0, utils_namespaceObject.uuid)()}.json`);
174
+ const publication = this.queue.then(async ()=>{
175
+ const serialized = await this.serialize(captured);
176
+ await (0, external_report_artifact_store_js_namespaceObject.writeReportArtifactFile)(path, serialized);
177
+ JSON.parse(serialized, (_key, value)=>{
178
+ const ref = (0, external_image_reference_js_namespaceObject.normalizeStoredImageRef)(value);
179
+ if (ref?.path) this.snapshotImages.add(ref.path);
180
+ return value;
181
+ });
182
+ this.sourcePath ??= path;
183
+ for (const execution of captured.dump.executions)if (execution.id) this.collected.add(execution.id);
184
+ });
185
+ this.queue = publication;
186
+ await publication;
187
+ return {
188
+ sourcePath: this.sourcePath,
189
+ dumpPath: path,
190
+ collection: {
191
+ status: busyAtCutoff ? 'partial' : 'complete',
192
+ capturedAt: captured.capturedAt,
193
+ ...busyAtCutoff ? {
194
+ reason: 'An Agent operation was still running at the snapshot cutoff.'
195
+ } : {}
196
+ }
197
+ };
198
+ }
199
+ async captureUncollected() {
200
+ if (this.finalization) {
201
+ await this.finalization;
202
+ const source = this.uncollectedSource;
203
+ this.uncollectedSource = void 0;
204
+ return source;
205
+ }
206
+ return this.capturePending();
207
+ }
208
+ async capturePending() {
209
+ const ids = this.recorder.executions.flatMap((execution)=>execution.id && !this.collected.has(execution.id) ? [
210
+ execution.id
211
+ ] : []);
212
+ return ids.length ? this.snapshot(this.id, ids) : void 0;
213
+ }
214
+ async flush() {
215
+ await this.queue;
216
+ }
217
+ async finalize() {
218
+ if (!this.finalization) this.finalization = (async ()=>{
219
+ await this.flush();
220
+ this.uncollectedSource = await this.capturePending();
221
+ await this.store.finalize();
222
+ this.recorder.clear();
223
+ this.collected.clear();
224
+ this.busy = void 0;
225
+ })();
226
+ return this.finalization;
227
+ }
228
+ constructor(directory, busy){
229
+ _define_property(this, "directory", void 0);
230
+ _define_property(this, "busy", void 0);
231
+ _define_property(this, "snapshotImages", void 0);
232
+ _define_property(this, "recorder", void 0);
233
+ _define_property(this, "id", void 0);
234
+ _define_property(this, "images", void 0);
235
+ _define_property(this, "store", void 0);
236
+ _define_property(this, "collected", void 0);
237
+ _define_property(this, "sourcePath", void 0);
238
+ _define_property(this, "queue", void 0);
239
+ _define_property(this, "finalization", void 0);
240
+ _define_property(this, "uncollectedSource", void 0);
241
+ this.directory = directory;
242
+ this.busy = busy;
243
+ this.snapshotImages = new Set();
244
+ this.recorder = new external_execution_recorder_js_namespaceObject.ExecutionRecorder();
245
+ this.id = (0, utils_namespaceObject.uuid)();
246
+ this.collected = new Set();
247
+ this.queue = Promise.resolve();
248
+ this.images = new external_screenshot_store_js_namespaceObject.ReportImageStore({
249
+ mode: 'directory',
250
+ reportPath: (0, external_node_path_namespaceObject.join)(directory, `${this.id}.json`),
251
+ screenshotsDir: (0, external_node_path_namespaceObject.join)(directory, 'screenshots')
252
+ });
253
+ this.store = new external_report_artifact_store_js_namespaceObject.ReportArtifactStore(directory, this.id, 'test', true);
254
+ }
255
+ }
256
+ exports.ReportSession = __webpack_exports__.ReportSession;
257
+ exports.currentReportSession = __webpack_exports__.currentReportSession;
258
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
259
+ "ReportSession",
260
+ "currentReportSession"
261
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
262
+ Object.defineProperty(exports, '__esModule', {
263
+ value: true
264
+ });
265
+
266
+ //# sourceMappingURL=report-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dump/report-session.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/dump/report-session.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { mkdir, readdir, rm } from 'node:fs/promises';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport { uuid } from '@midscene/shared/utils';\nimport { createExecutionContext } from '#yaml-execution-context';\nimport type { IReportGenerator } from '../report-generator';\nimport type { WorkflowReportSource } from '../test-runner/engine/types';\nimport type { ExecutionDump, ReportAttributes, ReportMeta } from '../types';\nimport {\n type ExecutionRecordSnapshot,\n ExecutionRecorder,\n} from './execution-recorder';\nimport { normalizeStoredImageRef } from './image-reference';\nimport {\n ReportArtifactStore,\n writeReportArtifactFile,\n} from './report-artifact-store';\nimport { type ImageUrlRef, ReportImageStore } from './screenshot-store';\n\nconst contextKey = Symbol.for('@midscene/core/report-session/v1');\nconst host = globalThis as typeof globalThis & {\n [contextKey]?: ReturnType<typeof createExecutionContext<ReportSession>>;\n};\nhost[contextKey] ??= createExecutionContext<ReportSession>();\nconst context = host[contextKey];\n\n/** The execution host owns the records; Agents do not publish independent pages. */\nexport class ReportSession {\n private readonly writers = new Set<ReportSourceRecorder>();\n private ended = false;\n private completion?: Promise<WorkflowReportSource[]>;\n private ownership?: Promise<void>;\n\n constructor(readonly directory: string) {\n if (!isAbsolute(directory))\n throw new Error('Report session directory must be absolute.');\n }\n\n async run<T>(callback: () => Promise<T>): Promise<T> {\n if (this.ended) throw new Error('The report session has ended.');\n this.ownership ??= (async () => {\n await mkdir(dirname(this.directory), { recursive: true });\n await mkdir(this.directory);\n })();\n await this.ownership;\n return context.run(this, callback);\n }\n\n createRecorder(isBusy: () => boolean): ReportSourceRecorder {\n if (!this.ownership)\n throw new Error('Start the report session before creating a writer.');\n if (this.ended)\n throw new Error('Cannot add a writer to an ended report session.');\n const writer = new ReportSourceRecorder(this.directory, isBusy);\n this.writers.add(writer);\n return writer;\n }\n\n /** Persist untraced setup/teardown evidence too, without waiting on device calls. */\n async finish(): Promise<WorkflowReportSource[]> {\n this.ended = true;\n this.completion ??= (async () => {\n const sources: WorkflowReportSource[] = [];\n for (const writer of this.writers) {\n const source = await writer.captureUncollected();\n if (source) sources.push(source);\n if (!writer.isBusy()) await writer.finalize();\n else await writer.flush();\n }\n return sources;\n })();\n return this.completion;\n }\n\n /** Cutoff records remain authoritative facts; discard replaceable progress only after delivery. */\n async prune(): Promise<void> {\n if (!this.completion)\n throw new Error('Finish the report session before pruning it.');\n await this.completion;\n if (!this.writers.size) {\n await rm(this.directory, { recursive: true, force: true });\n return;\n }\n if ([...this.writers].some((writer) => writer.isBusy())) return;\n await rm(join(this.directory, 'data'), { recursive: true, force: true });\n await rm(join(this.directory, 'report.json'), { force: true });\n const retained = new Set(\n [...this.writers].flatMap((writer) => [...writer.snapshotImages]),\n );\n const images = join(this.directory, 'screenshots');\n const files = await readdir(images).catch((error) => {\n if (error.code === 'ENOENT') return [];\n throw error;\n });\n for (const file of files)\n if (!retained.has(`./screenshots/${file}`)) await rm(join(images, file));\n }\n}\n\nexport const currentReportSession = (): ReportSession | undefined =>\n context.getStore();\n\n/** Structured Agent records and immutable Step cutoffs, with shared image assets. */\nclass ReportSourceRecorder implements IReportGenerator {\n readonly snapshotImages = new Set<string>();\n private readonly recorder = new ExecutionRecorder();\n private readonly id = uuid();\n private readonly images: ReportImageStore;\n private readonly store: ReportArtifactStore;\n private readonly collected = new Set<string>();\n private sourcePath?: string;\n private queue: Promise<void> = Promise.resolve();\n private finalization?: Promise<undefined>;\n private uncollectedSource?: WorkflowReportSource;\n\n constructor(\n private readonly directory: string,\n private busy: (() => boolean) | undefined,\n ) {\n this.images = new ReportImageStore({\n mode: 'directory',\n reportPath: join(directory, `${this.id}.json`),\n screenshotsDir: join(directory, 'screenshots'),\n });\n this.store = new ReportArtifactStore(directory, this.id, 'test', true);\n }\n\n getReportPath(): undefined {\n return undefined;\n }\n enableSourceSnapshots(): void {}\n isBusy(): boolean {\n return this.busy?.() ?? false;\n }\n\n onExecutionUpdate(\n execution: ExecutionDump,\n meta: ReportMeta,\n attributes: ReportAttributes = {},\n ): void {\n if (this.finalization)\n throw new Error('The report record stream has been finalized.');\n const key = this.recorder.record(execution, meta);\n const update = new ExecutionRecorder();\n update.record(execution, meta);\n const captured = update.capture();\n this.queue = this.queue.then(async () => {\n const serialized = await this.serialize(captured);\n await this.store.writeExecution(\n key,\n serialized,\n Object.fromEntries(\n Object.entries(attributes).map(([key, value]) => [\n key,\n String(value),\n ]),\n ),\n );\n });\n }\n\n private async serialize(captured: ExecutionRecordSnapshot): Promise<string> {\n for (const screenshot of captured.screenshots)\n await this.images.persist(screenshot);\n const references = new Map<string, ImageUrlRef>();\n for (const url of captured.referenceImageUrls)\n references.set(url, await this.images.persistReferenceImage(url));\n return JSON.stringify(\n JSON.parse(captured.dump.serializeWithReferenceImages(references)),\n (_key, value) => {\n const ref = normalizeStoredImageRef(value);\n if (!ref) return value;\n return {\n ...ref,\n storage: 'file',\n path: this.images.getFilePath(ref.id),\n };\n },\n );\n }\n\n async createSourceSnapshot(\n scopeId: string,\n executionIds?: readonly string[],\n ): Promise<WorkflowReportSource> {\n if (this.finalization)\n throw new Error('The report record stream has been finalized.');\n return this.snapshot(scopeId, executionIds);\n }\n\n private async snapshot(\n scopeId: string,\n executionIds?: readonly string[],\n ): Promise<WorkflowReportSource> {\n if (typeof scopeId !== 'string' || !scopeId.trim())\n throw new Error('Invalid report scope ID');\n // Freeze before any I/O: late progress cannot mutate this Step's evidence.\n const busyAtCutoff = this.isBusy();\n const captured = this.recorder.capture(\n executionIds,\n this.recorder.reportMeta ?? {\n sdkVersion: '',\n groupName: 'Test execution',\n modelBriefs: [],\n },\n );\n const path = join(this.directory, `${this.id}.${uuid()}.json`);\n const publication = this.queue.then(async () => {\n const serialized = await this.serialize(captured);\n await writeReportArtifactFile(path, serialized);\n JSON.parse(serialized, (_key, value) => {\n const ref = normalizeStoredImageRef(value);\n if (ref?.path) this.snapshotImages.add(ref.path);\n return value;\n });\n this.sourcePath ??= path;\n for (const execution of captured.dump.executions)\n if (execution.id) this.collected.add(execution.id);\n });\n this.queue = publication;\n await publication;\n return {\n sourcePath: this.sourcePath!,\n dumpPath: path,\n collection: {\n status: busyAtCutoff ? 'partial' : 'complete',\n capturedAt: captured.capturedAt,\n ...(busyAtCutoff\n ? {\n reason:\n 'An Agent operation was still running at the snapshot cutoff.',\n }\n : {}),\n },\n };\n }\n\n async captureUncollected(): Promise<WorkflowReportSource | undefined> {\n if (this.finalization) {\n await this.finalization;\n const source = this.uncollectedSource;\n this.uncollectedSource = undefined;\n return source;\n }\n return this.capturePending();\n }\n\n private async capturePending(): Promise<WorkflowReportSource | undefined> {\n const ids = this.recorder.executions.flatMap((execution) =>\n execution.id && !this.collected.has(execution.id) ? [execution.id] : [],\n );\n return ids.length ? this.snapshot(this.id, ids) : undefined;\n }\n\n async flush(): Promise<void> {\n await this.queue;\n }\n\n async finalize(): Promise<undefined> {\n if (!this.finalization)\n this.finalization = (async () => {\n await this.flush();\n // Preserve setup/teardown evidence before releasing executions. The\n // Session can collect this lightweight source after Agent.destroy().\n this.uncollectedSource = await this.capturePending();\n await this.store.finalize();\n this.recorder.clear();\n this.collected.clear();\n this.busy = undefined;\n return undefined;\n })();\n return this.finalization;\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","contextKey","host","globalThis","createExecutionContext","context","ReportSession","callback","Error","mkdir","dirname","isBusy","writer","ReportSourceRecorder","sources","source","rm","join","retained","Set","images","files","readdir","error","file","directory","isAbsolute","currentReportSession","execution","meta","attributes","update","ExecutionRecorder","captured","serialized","value","String","screenshot","references","Map","url","JSON","_key","ref","normalizeStoredImageRef","scopeId","executionIds","busyAtCutoff","path","uuid","publication","writeReportArtifactFile","undefined","ids","busy","Promise","ReportImageStore","ReportArtifactStore"],"mappings":"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"}
@@ -29,6 +29,7 @@ __webpack_require__.d(__webpack_exports__, {
29
29
  const external_node_fs_namespaceObject = require("node:fs");
30
30
  const promises_namespaceObject = require("node:fs/promises");
31
31
  const external_node_path_namespaceObject = require("node:path");
32
+ const report_artifact_namespaceObject = require("@midscene/shared/report-artifact");
32
33
  const external_html_utils_js_namespaceObject = require("./html-utils.js");
33
34
  const external_image_reference_js_namespaceObject = require("./image-reference.js");
34
35
  const external_screenshot_store_js_namespaceObject = require("./screenshot-store.js");
@@ -75,6 +76,7 @@ class TestReportImages {
75
76
  const refs = new Map();
76
77
  JSON.parse(serialized, (_key, value)=>{
77
78
  const ref = (0, external_image_reference_js_namespaceObject.normalizeStoredImageRef)(value);
79
+ if (ref?.storage === 'file') (0, report_artifact_namespaceObject.assertReportArtifactPath)(ref.path);
78
80
  if (ref && !this.locations.has(ref.id)) refs.set(ref.id, ref);
79
81
  return value;
80
82
  });
@@ -82,53 +84,77 @@ class TestReportImages {
82
84
  ...refs.values()
83
85
  ];
84
86
  }
85
- rewriteSync(serialized, sourcePath) {
86
- let inlineImages;
87
- for (const ref of this.collect(serialized)){
88
- let data;
89
- if ('file' === ref.storage) data = `data:${ref.mimeType};base64,${(0, external_node_fs_namespaceObject.readFileSync)((0, external_node_path_namespaceObject.resolve)((0, external_node_path_namespaceObject.dirname)(sourcePath), ref.path)).toString('base64')}`;
90
- else {
91
- inlineImages ??= (0, external_html_utils_js_namespaceObject.parseImageScripts)((0, external_node_fs_namespaceObject.readFileSync)(sourcePath, 'utf8'));
92
- data = inlineImages[ref.id];
93
- if (!data) throw new Error(`Missing report image ${ref.id} in ${sourcePath}`);
87
+ inlineSources(refs, sourcePath, origins) {
88
+ const sources = new Map();
89
+ for (const ref of refs)if ('inline' === ref.storage) {
90
+ const source = origins?.get(ref.id) ?? sourcePath;
91
+ const images = sources.get(source) ?? new Map();
92
+ images.set(ref.id, ref);
93
+ sources.set(source, images);
94
+ }
95
+ return sources;
96
+ }
97
+ writeSync(ref, data) {
98
+ const target = this.reference(ref, data);
99
+ if ('file' === target.storage) {
100
+ if (!this.files.has(target.path)) {
101
+ const file = (0, external_node_path_namespaceObject.join)((0, external_node_path_namespaceObject.dirname)(this.reportPath), target.path);
102
+ (0, external_node_fs_namespaceObject.mkdirSync)((0, external_node_path_namespaceObject.dirname)(file), {
103
+ recursive: true
104
+ });
105
+ (0, external_node_fs_namespaceObject.writeFileSync)(file, Buffer.from((0, external_screenshot_store_js_namespaceObject.parseBase64ImageDataUrl)(data).rawBase64, 'base64'));
106
+ this.files.add(target.path);
94
107
  }
95
- const target = this.reference(ref, data);
96
- if ('file' === target.storage) {
97
- if (!this.files.has(target.path)) {
98
- const file = (0, external_node_path_namespaceObject.join)((0, external_node_path_namespaceObject.dirname)(this.reportPath), target.path);
99
- (0, external_node_fs_namespaceObject.mkdirSync)((0, external_node_path_namespaceObject.dirname)(file), {
100
- recursive: true
101
- });
102
- (0, external_node_fs_namespaceObject.writeFileSync)(file, Buffer.from((0, external_screenshot_store_js_namespaceObject.parseBase64ImageDataUrl)(data).rawBase64, 'base64'));
103
- this.files.add(target.path);
108
+ } else (0, external_node_fs_namespaceObject.appendFileSync)(this.reportPath, `${(0, external_html_utils_js_namespaceObject.generateImageScriptTag)(ref.id, data)}\n`);
109
+ }
110
+ async write(ref, data) {
111
+ const target = this.reference(ref, data);
112
+ if ('file' === target.storage) {
113
+ if (!this.files.has(target.path)) {
114
+ const file = (0, external_node_path_namespaceObject.join)((0, external_node_path_namespaceObject.dirname)(this.reportPath), target.path);
115
+ await promises_namespaceObject.mkdir((0, external_node_path_namespaceObject.dirname)(file), {
116
+ recursive: true
117
+ });
118
+ await promises_namespaceObject.writeFile(file, Buffer.from((0, external_screenshot_store_js_namespaceObject.parseBase64ImageDataUrl)(data).rawBase64, 'base64'));
119
+ this.files.add(target.path);
120
+ }
121
+ } else await promises_namespaceObject.appendFile(this.reportPath, `${(0, external_html_utils_js_namespaceObject.generateImageScriptTag)(ref.id, data)}\n`);
122
+ }
123
+ rewriteSync(serialized, sourcePath, origins) {
124
+ const refs = this.collect(serialized);
125
+ for (const ref of refs)if ('file' === ref.storage) {
126
+ const bytes = (0, external_node_fs_namespaceObject.readFileSync)((0, external_node_path_namespaceObject.resolve)((0, external_node_path_namespaceObject.dirname)(origins?.get(ref.id) ?? sourcePath), ref.path));
127
+ this.writeSync(ref, `data:${ref.mimeType};base64,${bytes.toString('base64')}`);
128
+ }
129
+ for (const [source, images] of this.inlineSources(refs, sourcePath, origins)){
130
+ (0, external_html_utils_js_namespaceObject.streamInlineReportImages)(source, (id, data)=>{
131
+ const ref = images.get(id);
132
+ if (ref) {
133
+ this.writeSync(ref, data);
134
+ images.delete(id);
104
135
  }
105
- } else (0, external_node_fs_namespaceObject.appendFileSync)(this.reportPath, `${(0, external_html_utils_js_namespaceObject.generateImageScriptTag)(ref.id, data)}\n`);
136
+ return 0 === images.size;
137
+ });
138
+ if (images.size) throw new Error(`Missing report image ${images.keys().next().value} in ${source}`);
106
139
  }
107
140
  return this.rewrite(serialized);
108
141
  }
109
- async rewriteAsync(serialized, sourcePath) {
110
- let inlineImages;
111
- for (const ref of this.collect(serialized)){
112
- let data;
113
- if ('file' === ref.storage) {
114
- const bytes = await promises_namespaceObject.readFile((0, external_node_path_namespaceObject.resolve)((0, external_node_path_namespaceObject.dirname)(sourcePath), ref.path));
115
- data = `data:${ref.mimeType};base64,${bytes.toString('base64')}`;
116
- } else {
117
- inlineImages ??= (0, external_html_utils_js_namespaceObject.parseImageScripts)(await promises_namespaceObject.readFile(sourcePath, 'utf8'));
118
- data = inlineImages[ref.id];
119
- if (!data) throw new Error(`Missing report image ${ref.id} in ${sourcePath}`);
120
- }
121
- const target = this.reference(ref, data);
122
- if ('file' === target.storage) {
123
- if (!this.files.has(target.path)) {
124
- const file = (0, external_node_path_namespaceObject.join)((0, external_node_path_namespaceObject.dirname)(this.reportPath), target.path);
125
- await promises_namespaceObject.mkdir((0, external_node_path_namespaceObject.dirname)(file), {
126
- recursive: true
127
- });
128
- await promises_namespaceObject.writeFile(file, Buffer.from((0, external_screenshot_store_js_namespaceObject.parseBase64ImageDataUrl)(data).rawBase64, 'base64'));
129
- this.files.add(target.path);
142
+ async rewriteAsync(serialized, sourcePath, origins) {
143
+ const refs = this.collect(serialized);
144
+ for (const ref of refs)if ('file' === ref.storage) {
145
+ const bytes = await promises_namespaceObject.readFile((0, external_node_path_namespaceObject.resolve)((0, external_node_path_namespaceObject.dirname)(origins?.get(ref.id) ?? sourcePath), ref.path));
146
+ await this.write(ref, `data:${ref.mimeType};base64,${bytes.toString('base64')}`);
147
+ }
148
+ for (const [source, images] of this.inlineSources(refs, sourcePath, origins)){
149
+ for await (const { id, data } of (0, external_html_utils_js_namespaceObject.streamInlineReportImagesAsync)(source)){
150
+ const ref = images.get(id);
151
+ if (ref) {
152
+ await this.write(ref, data);
153
+ images.delete(id);
130
154
  }
131
- } else await promises_namespaceObject.appendFile(this.reportPath, `${(0, external_html_utils_js_namespaceObject.generateImageScriptTag)(ref.id, data)}\n`);
155
+ if (!images.size) break;
156
+ }
157
+ if (images.size) throw new Error(`Missing report image ${images.keys().next().value} in ${source}`);
132
158
  }
133
159
  return this.rewrite(serialized);
134
160
  }