@decaf-ts/utils 0.9.5 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -26,7 +26,7 @@ export * from "./writers";
26
26
  * @const VERSION
27
27
  * @memberOf module:utils
28
28
  */
29
- export declare const VERSION = "0.9.4";
29
+ export declare const VERSION = "0.9.6";
30
30
  /**
31
31
  * @description Represents the current version of the module.
32
32
  * @summary Stores the version for the @decaf-ts/utils package. The build replaces
package/lib/esm/index.js CHANGED
@@ -26,7 +26,7 @@ export * from "./writers/index.js";
26
26
  * @const VERSION
27
27
  * @memberOf module:utils
28
28
  */
29
- export const VERSION = "0.9.4";
29
+ export const VERSION = "0.9.6";
30
30
  /**
31
31
  * @description Represents the current version of the module.
32
32
  * @summary Stores the version for the @decaf-ts/utils package. The build replaces
@@ -0,0 +1,39 @@
1
+ import { LoggedClass } from "@decaf-ts/logging";
2
+ import { TestReporter } from "./TestReporter";
3
+ type LogStore = Record<number, string[]>;
4
+ export interface ParsedLog {
5
+ timestamp: number;
6
+ child: string;
7
+ action: string;
8
+ }
9
+ export interface ComparerResult {
10
+ consumer: ParsedLog[];
11
+ producer: ParsedLog[];
12
+ }
13
+ type Comparer = (consumerData: LogStore, producerData: LogStore) => Promise<ComparerResult>;
14
+ type ConsumerHandler = (identifier: number, ...args: unknown[]) => unknown | Promise<unknown>;
15
+ export declare const defaultComparer: Comparer;
16
+ export interface ReportingComparerOptions {
17
+ reporter?: TestReporter;
18
+ testCase?: string;
19
+ referencePrefix?: string;
20
+ }
21
+ export declare const reportingComparer: (consumerData: LogStore, producerData: LogStore, options?: ReportingComparerOptions) => Promise<ComparerResult>;
22
+ export declare class ConsumerRunner extends LoggedClass {
23
+ private readonly action;
24
+ private readonly handler;
25
+ private readonly comparerHandle;
26
+ private forkedCache;
27
+ private consumerResults;
28
+ private producerResults;
29
+ private completionTriggered;
30
+ constructor(action: string, consumerHandler: ConsumerHandler, compareHandler?: Comparer);
31
+ private reset;
32
+ private store;
33
+ private recordConsumer;
34
+ private isProducerComplete;
35
+ private isConsumerComplete;
36
+ private terminateChildren;
37
+ run(count: number, timeout: number | undefined, times: number, random: boolean | undefined): Promise<ComparerResult>;
38
+ }
39
+ export {};
@@ -0,0 +1,250 @@
1
+ import { fork } from "node:child_process";
2
+ import { join } from "node:path";
3
+ import { LoggedClass } from "@decaf-ts/logging";
4
+ import { TestReporter } from "./TestReporter.js";
5
+ const parseData = (data) => {
6
+ const [timestamp, , child, action] = data.split(" - ");
7
+ return {
8
+ timestamp: parseInt(timestamp, 10),
9
+ child,
10
+ action,
11
+ };
12
+ };
13
+ export const defaultComparer = async (consumerData, producerData) => {
14
+ const sortedConsumerData = Object.keys(consumerData)
15
+ .reduce((accum, key) => {
16
+ const identifier = Number(key);
17
+ const entries = consumerData[identifier] ?? [];
18
+ accum.push(...entries.map((entry) => parseData(entry)));
19
+ return accum;
20
+ }, [])
21
+ .sort((a, b) => a.timestamp - b.timestamp);
22
+ const sortedProducerData = Object.keys(producerData)
23
+ .reduce((accum, key) => {
24
+ const identifier = Number(key);
25
+ const entries = producerData[identifier] ?? [];
26
+ accum.push(...entries.map((entry) => parseData(entry)));
27
+ return accum;
28
+ }, [])
29
+ .sort((a, b) => a.timestamp - b.timestamp);
30
+ if (sortedProducerData.length !== sortedConsumerData.length) {
31
+ throw new Error("Producer data and consumer data does not match in length");
32
+ }
33
+ let counter = -1;
34
+ const isMatching = sortedProducerData.every((producer, index) => {
35
+ counter = index;
36
+ const consumer = sortedConsumerData[index];
37
+ return (producer.child === consumer.child && producer.action === consumer.action);
38
+ });
39
+ if (!isMatching) {
40
+ const errorLines = [
41
+ `Producer data and consumer data do not sort the same way as of record ${counter}:`,
42
+ " | CONSUMER | PRODUCER |",
43
+ " | id | action | timestamp | id | action | timestamp |",
44
+ ];
45
+ sortedProducerData.forEach((producer, index) => {
46
+ if (index < counter || index > counter + 15) {
47
+ return;
48
+ }
49
+ const consumer = sortedConsumerData[index];
50
+ errorLines.push(` ${index < 10 ? `0${index}` : index}| ${consumer.child} | ${consumer.action} | ${consumer.timestamp} | ${producer.child} | ${producer.action} | ${producer.timestamp} |`);
51
+ });
52
+ throw new Error(errorLines.join("\n"));
53
+ }
54
+ return {
55
+ consumer: sortedConsumerData,
56
+ producer: sortedProducerData,
57
+ };
58
+ };
59
+ const formatTimestamp = (value) => new Date(value).toISOString();
60
+ export const reportingComparer = async (consumerData, producerData, options) => {
61
+ const reporter = options?.reporter ??
62
+ new TestReporter(options?.testCase ?? "consumer-producer");
63
+ const referencePrefix = options?.referencePrefix ?? "consumer-producer";
64
+ try {
65
+ const comparison = await defaultComparer(consumerData, producerData);
66
+ const rows = comparison.consumer.map((consumerEntry, index) => {
67
+ const producerEntry = comparison.producer[index];
68
+ return {
69
+ Index: `${index}`,
70
+ "Consumer Child": consumerEntry.child,
71
+ "Consumer Action": consumerEntry.action,
72
+ "Consumer Timestamp": formatTimestamp(consumerEntry.timestamp),
73
+ "Producer Child": producerEntry?.child ?? "N/A",
74
+ "Producer Action": producerEntry?.action ?? "N/A",
75
+ "Producer Timestamp": producerEntry
76
+ ? formatTimestamp(producerEntry.timestamp)
77
+ : "N/A",
78
+ };
79
+ });
80
+ await Promise.allSettled([
81
+ reporter.reportMessage(`${referencePrefix}-comparison`, `Consumer and producer logs matched (${comparison.consumer.length} entries).`),
82
+ reporter.reportTable(`${referencePrefix}-logs`, {
83
+ headers: [
84
+ "Index",
85
+ "Consumer Child",
86
+ "Consumer Action",
87
+ "Consumer Timestamp",
88
+ "Producer Child",
89
+ "Producer Action",
90
+ "Producer Timestamp",
91
+ ],
92
+ rows,
93
+ }),
94
+ ]);
95
+ return comparison;
96
+ }
97
+ catch (error) {
98
+ const message = error instanceof Error ? error.message : String(error ?? "Unknown error");
99
+ await Promise.allSettled([
100
+ reporter.reportMessage(`${referencePrefix}-mismatch`, message),
101
+ reporter.reportObject(`${referencePrefix}-consumer`, consumerData),
102
+ reporter.reportObject(`${referencePrefix}-producer`, producerData),
103
+ ]);
104
+ throw error;
105
+ }
106
+ };
107
+ export class ConsumerRunner extends LoggedClass {
108
+ constructor(action, consumerHandler, compareHandler) {
109
+ super();
110
+ this.forkedCache = [];
111
+ this.consumerResults = {};
112
+ this.producerResults = {};
113
+ this.completionTriggered = false;
114
+ this.action = action;
115
+ this.handler = consumerHandler;
116
+ this.comparerHandle = compareHandler ?? defaultComparer;
117
+ this.reset();
118
+ }
119
+ reset() {
120
+ this.forkedCache = [];
121
+ this.consumerResults = {};
122
+ this.producerResults = {};
123
+ this.completionTriggered = false;
124
+ }
125
+ store(identifier, action, timeout, times, count, random) {
126
+ const logParts = [
127
+ Date.now(),
128
+ "PRODUCER",
129
+ identifier,
130
+ action,
131
+ ];
132
+ if (timeout) {
133
+ logParts.push(timeout);
134
+ }
135
+ if (times && count) {
136
+ logParts.push(`${count}/${times}`, random ?? false);
137
+ }
138
+ const log = logParts.join(" - ");
139
+ if (!this.producerResults[identifier]) {
140
+ this.producerResults[identifier] = [];
141
+ }
142
+ this.producerResults[identifier].push(log);
143
+ }
144
+ recordConsumer(identifier) {
145
+ const logParts = [
146
+ Date.now(),
147
+ "CONSUMER",
148
+ identifier,
149
+ this.action,
150
+ ];
151
+ const log = logParts.join(" - ");
152
+ if (!this.consumerResults[identifier]) {
153
+ this.consumerResults[identifier] = [];
154
+ }
155
+ this.consumerResults[identifier].push(log);
156
+ }
157
+ isProducerComplete(count, times) {
158
+ const producerKeys = Object.keys(this.producerResults);
159
+ if (producerKeys.length !== count) {
160
+ return false;
161
+ }
162
+ return producerKeys.every((key) => this.producerResults[Number(key)]?.length === times);
163
+ }
164
+ isConsumerComplete(count, times) {
165
+ const consumerKeys = Object.keys(this.consumerResults);
166
+ if (consumerKeys.length !== count) {
167
+ return false;
168
+ }
169
+ return consumerKeys.every((key) => this.consumerResults[Number(key)]?.length === times);
170
+ }
171
+ terminateChildren() {
172
+ if (!this.forkedCache) {
173
+ return;
174
+ }
175
+ this.forkedCache.forEach((forked, index) => {
176
+ forked.send({
177
+ identifier: index,
178
+ terminate: true,
179
+ });
180
+ });
181
+ this.forkedCache = undefined;
182
+ }
183
+ async run(count, timeout, times, random) {
184
+ this.reset();
185
+ const childPath = join(__dirname, "ProducerChildProcess.cjs");
186
+ return new Promise((resolve, reject) => {
187
+ const handleError = (error) => {
188
+ if (this.completionTriggered) {
189
+ return;
190
+ }
191
+ this.completionTriggered = true;
192
+ this.terminateChildren();
193
+ reject(error);
194
+ };
195
+ const finalizeIfComplete = () => {
196
+ if (this.completionTriggered) {
197
+ return;
198
+ }
199
+ if (!this.isProducerComplete(count, times) ||
200
+ !this.isConsumerComplete(count, times)) {
201
+ return;
202
+ }
203
+ this.terminateChildren();
204
+ this.completionTriggered = true;
205
+ try {
206
+ Promise.resolve(this.comparerHandle(this.consumerResults, this.producerResults))
207
+ .then(resolve)
208
+ .catch(reject);
209
+ }
210
+ catch (error) {
211
+ reject(error);
212
+ }
213
+ };
214
+ const checkProducerCompletion = () => {
215
+ if (this.isProducerComplete(count, times)) {
216
+ this.terminateChildren();
217
+ }
218
+ };
219
+ for (let identifier = 1; identifier < count + 1; identifier += 1) {
220
+ const forked = fork(childPath);
221
+ this.forkedCache?.push(forked);
222
+ forked.on("error", handleError);
223
+ forked.on("message", async (message) => {
224
+ const { identifier: childId, args, action, timeout: childTimeout, times: childTimes, random: childRandom, } = message;
225
+ try {
226
+ this.store(childId, action, childTimeout, childTimes, count, childRandom);
227
+ checkProducerCompletion();
228
+ const handlerArgs = Array.isArray(args) ? args : [];
229
+ await Promise.resolve(this.handler(childId, ...handlerArgs));
230
+ this.recordConsumer(childId);
231
+ finalizeIfComplete();
232
+ }
233
+ catch (error) {
234
+ handleError(error);
235
+ }
236
+ });
237
+ }
238
+ this.forkedCache?.forEach((forked, index) => {
239
+ forked.send({
240
+ identifier: index,
241
+ action: this.action,
242
+ timeout,
243
+ times,
244
+ random,
245
+ });
246
+ });
247
+ });
248
+ }
249
+ }
250
+ //# sourceMappingURL=Consumer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Consumer.js","sourceRoot":"","sources":["../../../src/tests/Consumer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ type ParentMessage = {
2
+ identifier: number;
3
+ action: string;
4
+ timeout?: number;
5
+ times: number;
6
+ random?: boolean;
7
+ terminate?: boolean;
8
+ };
9
+ type ProducerResponse = {
10
+ identifier: number;
11
+ action: string;
12
+ timeout?: number;
13
+ times: number;
14
+ random?: boolean;
15
+ result?: string[];
16
+ };
17
+ declare const result: string[];
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ const result = [];
3
+ process.on('message', (args) => {
4
+ const { identifier, action, timeout, times, random, terminate } = args;
5
+ const tick = (count) => {
6
+ const logParts = [Date.now(), 'PRODUCER', identifier, action];
7
+ if (timeout) {
8
+ logParts.push(timeout);
9
+ }
10
+ if (times && count) {
11
+ logParts.push(`${count}/${times}`, random ?? false);
12
+ }
13
+ const log = logParts.join(' - ');
14
+ result.push(log);
15
+ const response = { identifier, action, timeout, times, random };
16
+ if (result.length === times) {
17
+ response.result = [...result];
18
+ }
19
+ process.send?.(response);
20
+ };
21
+ if (terminate) {
22
+ const log = [Date.now(), 'PRODUCER', identifier, action, 'Quitting!'].join(' - ');
23
+ console.log(log);
24
+ process.exit(0);
25
+ }
26
+ if (!timeout) {
27
+ tick(times);
28
+ return;
29
+ }
30
+ const getTimeout = () => {
31
+ if (!random) {
32
+ return timeout;
33
+ }
34
+ return Math.floor(Math.random() * timeout);
35
+ };
36
+ let actionCount = 0;
37
+ const iterator = () => {
38
+ const currentTimeout = getTimeout();
39
+ setTimeout(() => {
40
+ actionCount += 1;
41
+ tick(actionCount);
42
+ if (actionCount < times) {
43
+ iterator();
44
+ }
45
+ }, currentTimeout);
46
+ };
47
+ iterator();
48
+ });
49
+ //# sourceMappingURL=ProducerChildProcess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProducerChildProcess.js","sourceRoot":"","sources":["../../../src/tests/ProducerChildProcess.ts"],"names":[],"mappings":";AAkBA,MAAM,MAAM,GAAa,EAAE,CAAC;AAE5B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAmB,EAAE,EAAE;IAC5C,MAAM,EAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAC,GAAG,IAAI,CAAC;IAErE,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE;QAC7B,MAAM,QAAQ,GAAqC,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QAChG,IAAI,OAAO,EAAE,CAAC;YACZ,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;QACD,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,KAAK,EAAE,EAAE,MAAM,IAAI,KAAK,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEjB,MAAM,QAAQ,GAAqB,EAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAC,CAAC;QAChF,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC5B,QAAQ,CAAC,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QAChC,CAAC;QAED,OAAO,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC,CAAC;IAEF,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClF,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,CAAC,CAAC;QACZ,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC;IAC7C,CAAC,CAAC;IAEF,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,MAAM,QAAQ,GAAG,GAAG,EAAE;QACpB,MAAM,cAAc,GAAG,UAAU,EAAE,CAAC;QACpC,UAAU,CAAC,GAAG,EAAE;YACd,WAAW,IAAI,CAAC,CAAC;YACjB,IAAI,CAAC,WAAW,CAAC,CAAC;YAClB,IAAI,WAAW,GAAG,KAAK,EAAE,CAAC;gBACxB,QAAQ,EAAE,CAAC;YACb,CAAC;QACH,CAAC,EAAE,cAAc,CAAC,CAAC;IACrB,CAAC,CAAC;IAEF,QAAQ,EAAE,CAAC;AACb,CAAC,CAAC,CAAC"}
@@ -0,0 +1,193 @@
1
+ import { MdTableDefinition } from "../utils/md";
2
+ /**
3
+ * @interface AddAttachParams
4
+ * @description Parameters for adding an attachment to a report
5
+ * @summary Interface for attachment parameters
6
+ * @memberOf module:utils
7
+ */
8
+ export interface AddAttachParams {
9
+ attach: string | Buffer;
10
+ description: string | object;
11
+ context?: any;
12
+ bufferFormat?: string;
13
+ }
14
+ /**
15
+ * @interface AddMsgParams
16
+ * @description Parameters for adding a message to a report
17
+ * @summary Interface for message parameters
18
+ * @memberOf module:utils
19
+ */
20
+ export interface AddMsgParams {
21
+ message: string | object;
22
+ context?: any;
23
+ }
24
+ /**
25
+ * @typedef {("json"|"image"|"text"|"md")} PayloadType
26
+ * @description Types of payloads that can be handled
27
+ * @summary Union type for payload types
28
+ * @memberOf module:utils
29
+ */
30
+ export type PayloadType = "json" | "image" | "text" | "md";
31
+ /**
32
+ * @description Environment variable key for Jest HTML reporters temporary directory path
33
+ * @summary Constant defining the environment variable key for Jest HTML reporters
34
+ * @const JestReportersTempPathEnvKey
35
+ * @memberOf module:utils
36
+ */
37
+ export declare const JestReportersTempPathEnvKey = "JEST_HTML_REPORTERS_TEMP_DIR_PATH";
38
+ /**
39
+ * @description Test reporting utility class for managing test results and evidence
40
+ * @summary A comprehensive test reporter that handles various types of test artifacts including messages,
41
+ * attachments, data, images, tables, and graphs. It provides methods to report and store test evidence
42
+ * in different formats and manages dependencies for reporting functionality.
43
+ *
44
+ * @template T - Type of data being reported
45
+ * @param {string} [testCase="tests"] - Name of the test case
46
+ * @param {string} [basePath] - Base path for storing test reports
47
+ * @class
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const reporter = new TestReporter('login-test');
52
+ *
53
+ * // Report test messages
54
+ * await reporter.reportMessage('Test Started', 'Login flow initiated');
55
+ *
56
+ * // Report test data
57
+ * await reporter.reportData('user-credentials', { username: 'test' }, 'json');
58
+ *
59
+ * // Report test results table
60
+ * await reporter.reportTable('test-results', {
61
+ * headers: ['Step', 'Status'],
62
+ * rows: [
63
+ * { Step: 'Login', Status: 'Pass' },
64
+ * { Step: 'Validation', Status: 'Pass' }
65
+ * ]
66
+ * });
67
+ *
68
+ * // Report test evidence
69
+ * await reporter.reportAttachment('Screenshot', screenshotBuffer);
70
+ * ```
71
+ *
72
+ * @mermaid
73
+ * sequenceDiagram
74
+ * participant Client
75
+ * participant TestReporter
76
+ * participant FileSystem
77
+ * participant Dependencies
78
+ *
79
+ * Client->>TestReporter: new TestReporter(testCase, basePath)
80
+ * TestReporter->>FileSystem: Create report directory
81
+ *
82
+ * alt Report Message
83
+ * Client->>TestReporter: reportMessage(title, message)
84
+ * TestReporter->>Dependencies: Import helpers
85
+ * TestReporter->>FileSystem: Store message
86
+ * else Report Data
87
+ * Client->>TestReporter: reportData(reference, data, type)
88
+ * TestReporter->>Dependencies: Process data
89
+ * TestReporter->>FileSystem: Store formatted data
90
+ * else Report Table
91
+ * Client->>TestReporter: reportTable(reference, tableDef)
92
+ * TestReporter->>Dependencies: Convert to MD format
93
+ * TestReporter->>FileSystem: Store table
94
+ * end
95
+ */
96
+ export declare class TestReporter {
97
+ protected testCase: string;
98
+ protected basePath: string;
99
+ /**
100
+ * @description Function for adding messages to the test report
101
+ * @summary Static handler for processing and storing test messages
102
+ * @type {function(AddMsgParams): Promise<void>}
103
+ */
104
+ protected static addMsgFunction: (params: AddMsgParams) => Promise<void>;
105
+ /**
106
+ * @description Function for adding attachments to the test report
107
+ * @summary Static handler for processing and storing test attachments
108
+ * @type {function(AddAttachParams): Promise<void>}
109
+ */
110
+ protected static addAttachFunction: (params: AddAttachParams) => Promise<void>;
111
+ /**
112
+ * @description Map of dependencies required by the reporter
113
+ * @summary Stores the current state of dependencies
114
+ * @type {SimpleDependencyMap}
115
+ */
116
+ private deps?;
117
+ constructor(testCase?: string, basePath?: string);
118
+ /**
119
+ * @description Imports required helper functions
120
+ * @summary Ensures all necessary dependencies are available and imports helper functions
121
+ * @return {Promise<void>} Promise that resolves when helpers are imported
122
+ */
123
+ private importHelpers;
124
+ /**
125
+ * @description Reports a message to the test report
126
+ * @summary Adds a formatted message to the test report with an optional title
127
+ * @param {string} title - Title of the message
128
+ * @param {string | object} message - Content of the message
129
+ * @return {Promise<void>} Promise that resolves when the message is reported
130
+ */
131
+ reportMessage(title: string, message: string | object): Promise<void>;
132
+ /**
133
+ * @description Reports an attachment to the test report
134
+ * @summary Adds a formatted message to the test report with an optional title
135
+ * @param {string} title - Title of the message
136
+ * @param {string | Buffer} attachment - Content of the message
137
+ * @return {Promise<void>} Promise that resolves when the message is reported
138
+ */
139
+ reportAttachment(title: string, attachment: string | Buffer): Promise<void>;
140
+ /**
141
+ * @description Reports data with specified type
142
+ * @summary Processes and stores data in the test report with formatting
143
+ * @param {string} reference - Reference identifier for the data
144
+ * @param {string | number | object} data - Data to be reported
145
+ * @param {PayloadType} type - Type of the payload
146
+ * @param {boolean} [trim=false] - Whether to trim the data
147
+ * @return {Promise<void>} Promise that resolves when data is reported
148
+ */
149
+ protected report(reference: string, data: string | number | object | Buffer, type: PayloadType, trim?: boolean): Promise<void>;
150
+ /**
151
+ * @description Reports data with a specified type
152
+ * @summary Wrapper method for reporting various types of data
153
+ * @param {string} reference - Reference identifier for the data
154
+ * @param {string | number | object} data - Data to be reported
155
+ * @param {PayloadType} [type="json"] - Type of the payload
156
+ * @param {boolean} [trim=false] - Whether to trim the data
157
+ * @return {Promise<void>} Promise that resolves when data is reported
158
+ */
159
+ reportData(reference: string, data: string | number | object, type?: PayloadType, trim?: boolean): Promise<void>;
160
+ /**
161
+ * @description Reports a JSON object
162
+ * @summary Convenience method for reporting JSON objects
163
+ * @param {string} reference - Reference identifier for the object
164
+ * @param {object} json - JSON object to be reported
165
+ * @param {boolean} [trim=false] - Whether to trim the object
166
+ * @return {Promise<void>} Promise that resolves when object is reported
167
+ */
168
+ reportObject(reference: string, json: object, trim?: boolean): Promise<void>;
169
+ /**
170
+ * @description Reports a table in markdown format
171
+ * @summary Converts and stores a table definition in markdown format
172
+ * @param {string} reference - Reference identifier for the table
173
+ * @param {MdTableDefinition} tableDef - Table definition object
174
+ * @return {Promise<void>} Promise that resolves when table is reported
175
+ */
176
+ reportTable(reference: string, tableDef: MdTableDefinition): Promise<void>;
177
+ /**
178
+ * @description Reports a graph using Chart.js
179
+ * @summary Generates and stores a graph visualization
180
+ * @param {string} reference - Reference identifier for the graph
181
+ * @param {any} config - Chart.js configuration object
182
+ * @return {Promise<void>} Promise that resolves when graph is reported
183
+ */
184
+ reportGraph(reference: string, config: any): Promise<void>;
185
+ /**
186
+ * @description Reports an image to the test report
187
+ * @summary Stores an image buffer in the test report
188
+ * @param {string} reference - Reference identifier for the image
189
+ * @param {Buffer} buffer - Image data buffer
190
+ * @return {Promise<void>} Promise that resolves when image is reported
191
+ */
192
+ reportImage(reference: string, buffer: Buffer): Promise<void>;
193
+ }