@allurereport/reader 3.0.0-beta.9 → 3.0.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.
- package/dist/allure2/index.js +3 -0
- package/dist/allure2/model.d.ts +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/xcresult/bundle.d.ts +7 -0
- package/dist/xcresult/bundle.js +68 -0
- package/dist/xcresult/index.d.ts +2 -0
- package/dist/xcresult/index.js +91 -0
- package/dist/xcresult/model.d.ts +61 -0
- package/dist/xcresult/model.js +1 -0
- package/dist/xcresult/utils.d.ts +42 -0
- package/dist/xcresult/utils.js +378 -0
- package/dist/xcresult/xcresulttool/cli.d.ts +10 -0
- package/dist/xcresult/xcresulttool/cli.js +42 -0
- package/dist/xcresult/xcresulttool/index.d.ts +7 -0
- package/dist/xcresult/xcresulttool/index.js +311 -0
- package/dist/xcresult/xcresulttool/legacy/index.d.ts +10 -0
- package/dist/xcresult/xcresulttool/legacy/index.js +455 -0
- package/dist/xcresult/xcresulttool/legacy/model.d.ts +74 -0
- package/dist/xcresult/xcresulttool/legacy/model.js +1 -0
- package/dist/xcresult/xcresulttool/legacy/parsing.d.ts +15 -0
- package/dist/xcresult/xcresulttool/legacy/parsing.js +41 -0
- package/dist/xcresult/xcresulttool/legacy/utils.d.ts +7 -0
- package/dist/xcresult/xcresulttool/legacy/utils.js +33 -0
- package/dist/xcresult/xcresulttool/legacy/xcModel.d.ts +357 -0
- package/dist/xcresult/xcresulttool/legacy/xcModel.js +5 -0
- package/dist/xcresult/xcresulttool/model.d.ts +17 -0
- package/dist/xcresult/xcresulttool/model.js +6 -0
- package/dist/xcresult/xcresulttool/utils.d.ts +3 -0
- package/dist/xcresult/xcresulttool/utils.js +74 -0
- package/dist/xcresult/xcresulttool/xcModel.d.ts +96 -0
- package/dist/xcresult/xcresulttool/xcModel.js +18 -0
- package/package.json +10 -8
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { isDefined, isNumber } from "@allurereport/reader-api";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
export const MS_IN_S = 1000;
|
|
4
|
+
export const ALLURE_API_ACTIVITY_PREFIX = "allure.";
|
|
5
|
+
export const statusPriorities = new Map([
|
|
6
|
+
["failed", 0],
|
|
7
|
+
["broken", 1],
|
|
8
|
+
["unknown", 2],
|
|
9
|
+
["skipped", 3],
|
|
10
|
+
["passed", 4],
|
|
11
|
+
]);
|
|
12
|
+
export const utiToMediaType = {
|
|
13
|
+
"public.plain-text": "text/plain",
|
|
14
|
+
"public.utf8-plain-text": "text/plain",
|
|
15
|
+
"public.utf16-external-plain-text": "text/plain",
|
|
16
|
+
"public.utf16-plain-text": "text/plain",
|
|
17
|
+
"public.rtf": "text/rtf",
|
|
18
|
+
"public.html": "text/html",
|
|
19
|
+
"public.xml": "text/xml",
|
|
20
|
+
"public.source-code": "text/plain",
|
|
21
|
+
"public.c-source": "text/plain",
|
|
22
|
+
"public.objective-c-source": "text/plain",
|
|
23
|
+
"public.c-plus-plus-source": "text/plain",
|
|
24
|
+
"public.objective-c-plus-plus-source": "text/plain",
|
|
25
|
+
"public.c-header": "text/plain",
|
|
26
|
+
"public.c-plus-plus-header": "text/plain",
|
|
27
|
+
"com.sun.java-source": "text/plain",
|
|
28
|
+
"public.script": "text/plain",
|
|
29
|
+
"public.assembly-source": "text/plain",
|
|
30
|
+
"com.apple.rez-source": "text/plain",
|
|
31
|
+
"public.mig-source": "text/plain",
|
|
32
|
+
"com.apple.symbol-export": "text/plain",
|
|
33
|
+
"com.netscape.javascript-source": "text/plain",
|
|
34
|
+
"public.shell-script": "text/plain",
|
|
35
|
+
"public.csh-script": "text/plain",
|
|
36
|
+
"public.perl-script": "text/plain",
|
|
37
|
+
"public.python-script": "text/plain",
|
|
38
|
+
"public.ruby-script": "text/plain",
|
|
39
|
+
"public.php-script": "text/plain",
|
|
40
|
+
"com.sun.java-web-start": "text/plain",
|
|
41
|
+
"com.apple.applescript.text": "text/plain",
|
|
42
|
+
"com.microsoft.windows-executable": "application/x-msdownload",
|
|
43
|
+
"com.microsoft.windows-dynamic-link-library": "application/x-msdownload",
|
|
44
|
+
"com.sun.java-archive": "application/java-archive",
|
|
45
|
+
"com.apple.quartz-composer-composition": "application/x-quartzcomposer",
|
|
46
|
+
"org.gnu.gnu-tar-archive": "application/x-gtar",
|
|
47
|
+
"public.tar-archive": "application/x-tar",
|
|
48
|
+
"org.gnu.gnu-zip-archive": "application/gzip",
|
|
49
|
+
"org.gnu.gnu-zip-tar-archive": "application/gzip",
|
|
50
|
+
"com.apple.binhex-archive": "application/mac-binhex40",
|
|
51
|
+
"com.apple.macbinary-archive": "application/x-macbinary",
|
|
52
|
+
"public.heic": "image/heic",
|
|
53
|
+
"public.heif": "image/heif",
|
|
54
|
+
"public.jpeg": "image/jpeg",
|
|
55
|
+
"public.jpeg-2000": "image/jp2",
|
|
56
|
+
"public.tiff": "image/tiff",
|
|
57
|
+
"com.apple.pict": "image/x-pict",
|
|
58
|
+
"public.png": "image/png",
|
|
59
|
+
"public.xbitmap-image": "image/x-quicktime",
|
|
60
|
+
"com.apple.quicktime-image": "image/x-quicktime",
|
|
61
|
+
"com.apple.quicktime-movie": "video/quicktime",
|
|
62
|
+
"public.avi": "video/x-msvideo",
|
|
63
|
+
"public.mpeg": "video/mpeg",
|
|
64
|
+
"public.mpeg-4": "video/mp4",
|
|
65
|
+
"public.3gpp": "video/3gpp",
|
|
66
|
+
"public.3gpp2": "video/3gpp2",
|
|
67
|
+
"public.mp3": "audio/mpeg",
|
|
68
|
+
"public.mpeg-4-audio": "audio/mp4",
|
|
69
|
+
"public.ulaw-audio": "audio/basic",
|
|
70
|
+
"public.aifc-audio": "audio/x-aiff",
|
|
71
|
+
"public.aiff-audio": "audio/x-aiff",
|
|
72
|
+
"com.pkware.zip-archive": "application/zip",
|
|
73
|
+
"com.adobe.pdf": "application/pdf",
|
|
74
|
+
"com.adobe.photoshop-image": "image/vnd.adobe.photoshop",
|
|
75
|
+
"com.compuserve.gif": "image/gif",
|
|
76
|
+
"com.microsoft.bmp": "image/bmp",
|
|
77
|
+
"com.microsoft.ico": "image/vnd.microsoft.icon",
|
|
78
|
+
"com.microsoft.word.doc": "application/msword",
|
|
79
|
+
"com.microsoft.excel.xls": "application/vnd.ms-excel",
|
|
80
|
+
"com.microsoft.powerpoint.ppt": "application/vnd.ms-powerpoint",
|
|
81
|
+
"com.microsoft.waveform-audio": "audio/x-wav",
|
|
82
|
+
"com.microsoft.advanced-systems-format": "video/x-ms-asf",
|
|
83
|
+
"com.microsoft.windows-media-wm": "video/x-ms-wm",
|
|
84
|
+
"com.microsoft.windows-media-wmv": "video/x-ms-wmv",
|
|
85
|
+
"com.microsoft.windows-media-wmp": "video/x-ms-wmp",
|
|
86
|
+
"com.microsoft.windows-media-wma": "video/x-ms-wma",
|
|
87
|
+
"com.microsoft.advanced-stream-redirector": "video/x-ms-asx",
|
|
88
|
+
"com.microsoft.windows-media-wmx": "video/x-ms-wmx",
|
|
89
|
+
"com.microsoft.windows-media-wvx": "video/x-ms-wvx",
|
|
90
|
+
"com.microsoft.windows-media-wax": "video/x-ms-wax",
|
|
91
|
+
"com.truevision.tga-image": "image/x-tga",
|
|
92
|
+
"com.sgi.sgi-image": "image/x-sgi",
|
|
93
|
+
"com.kodak.flashpix.image": "image/vnd.fpx",
|
|
94
|
+
"com.real.realmedia": "application/vnd.rn-realmedia",
|
|
95
|
+
"com.real.realaudio": "audio/vnd.rn-realaudio",
|
|
96
|
+
"com.real.smil": "application/smil",
|
|
97
|
+
"com.allume.stuffit-archive": "application/x-stuffit",
|
|
98
|
+
};
|
|
99
|
+
export const getMediaTypeByUti = (uti) => (uti ? utiToMediaType[uti] : undefined);
|
|
100
|
+
export const prependTitle = (title, text, spaces) => [title, ...text.split("\n").map((l) => `${" ".repeat(spaces)}${l}`)].join("\n");
|
|
101
|
+
export const getWorstStatusWithDetails = (failureSteps) => {
|
|
102
|
+
const sortedFailureSteps = [...failureSteps];
|
|
103
|
+
sortedFailureSteps.sort(({ status: statusA }, { status: statusB }) => statusPriorities.get(statusA ?? "unknown") - statusPriorities.get(statusB ?? "unknown"));
|
|
104
|
+
if (!sortedFailureSteps.length) {
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
const { status, trace, message: worstStepMessage } = sortedFailureSteps[0];
|
|
108
|
+
const totalFailuresCount = failureSteps.length;
|
|
109
|
+
const expectedFailuresCount = countExpectedFailures(failureSteps);
|
|
110
|
+
const message = resolveFailureMessage(worstStepMessage, totalFailuresCount, expectedFailuresCount);
|
|
111
|
+
return { status, message, trace };
|
|
112
|
+
};
|
|
113
|
+
export const countExpectedFailures = (failureSteps) => failureSteps.reduce((a, { status }) => (status === "passed" ? a + 1 : a), 0);
|
|
114
|
+
export const resolveFailureMessage = (firstFailureMessage, failuresCount, expectedFailuresCount) => {
|
|
115
|
+
switch (failuresCount) {
|
|
116
|
+
case 0:
|
|
117
|
+
return undefined;
|
|
118
|
+
case 1:
|
|
119
|
+
return firstFailureMessage;
|
|
120
|
+
default:
|
|
121
|
+
return getAggregatedFailureMessage(firstFailureMessage, failuresCount, expectedFailuresCount);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
export const getAggregatedFailureMessage = (message, failures, expected) => {
|
|
125
|
+
const [summary, prefix] = failures === expected
|
|
126
|
+
? [`${failures} expected failures have occured`, "The first one is"]
|
|
127
|
+
: expected === 0
|
|
128
|
+
? [`${failures} failures have occured`, "The first one is"]
|
|
129
|
+
: [`${failures} failures have occured (${expected} expected)`, "The first unexpected one is"];
|
|
130
|
+
return message ? prependTitle(`${summary}. ${prefix}:`, message, 2) : summary;
|
|
131
|
+
};
|
|
132
|
+
export const DEFAULT_BUNDLE_NAME = "The test bundle name is not defined";
|
|
133
|
+
export const DEFAULT_SUITE_ID = "__unknown__";
|
|
134
|
+
export const DEFAULT_SUITE_NAME = "The test suite name is not defined";
|
|
135
|
+
export const DEFAULT_TEST_NAME = "The test name is not defined";
|
|
136
|
+
export const DEFAULT_STEP_NAME = "The test name is not defined";
|
|
137
|
+
export const DEFAULT_ATTACHMENT_NAME = "Attachment";
|
|
138
|
+
export const DEFAULT_EXPECTED_FAILURE_REASON = "Expected failure";
|
|
139
|
+
export const SURROGATE_DEVICE_ID = randomUUID();
|
|
140
|
+
export const SURROGATE_TEST_PLAN_ID = randomUUID();
|
|
141
|
+
export const SURROGATE_ARGS_ID = randomUUID();
|
|
142
|
+
export const getArgsKeyByValues = (values) => values.map(String).join(",");
|
|
143
|
+
export const getArgsKey = (args) => getArgsKeyByValues(args.map((arg) => arg?.value));
|
|
144
|
+
export const createTestRunLookup = (entries) => mappedGroupBy(entries, ([{ device }]) => device ?? SURROGATE_DEVICE_ID, (deviceRuns) => mappedGroupBy(deviceRuns, ([{ testPlan }]) => testPlan ?? SURROGATE_TEST_PLAN_ID, (configRuns) => mappedGroupBy(configRuns, ([{ args }]) => (args && args.length ? getArgsKey(args) : SURROGATE_ARGS_ID), (argRuns) => {
|
|
145
|
+
argRuns.sort(([{ attempt: attemptA }], [{ attempt: attemptB }]) => (attemptA ?? 0) - (attemptB ?? 0));
|
|
146
|
+
return argRuns.map(([, data]) => data);
|
|
147
|
+
})));
|
|
148
|
+
export const lookupTestAttempts = (lookup, { args, device, testPlan }) => lookup
|
|
149
|
+
.get(device ?? SURROGATE_DEVICE_ID)
|
|
150
|
+
?.get(testPlan ?? SURROGATE_TEST_PLAN_ID)
|
|
151
|
+
?.get(args ? getArgsKeyByValues(args) : SURROGATE_ARGS_ID);
|
|
152
|
+
export const lookupTestAttempt = (lookup, selector) => {
|
|
153
|
+
const attempts = lookupTestAttempts(lookup, selector);
|
|
154
|
+
const { attempt = 0 } = selector;
|
|
155
|
+
return attempts?.[attempt];
|
|
156
|
+
};
|
|
157
|
+
export const lookupNextTestAttempt = (lookup, selector, pred) => {
|
|
158
|
+
const attempts = lookupTestAttempts(lookup, selector);
|
|
159
|
+
return attempts?.find(pred);
|
|
160
|
+
};
|
|
161
|
+
export const groupBy = (values, keyFn) => values.reduce((m, v) => {
|
|
162
|
+
const key = keyFn(v);
|
|
163
|
+
if (!m.get(key)?.push(v)) {
|
|
164
|
+
m.set(key, [v]);
|
|
165
|
+
}
|
|
166
|
+
return m;
|
|
167
|
+
}, new Map());
|
|
168
|
+
export const mappedGroupBy = (values, keyFn, groupMapFn) => {
|
|
169
|
+
const result = new Map();
|
|
170
|
+
for (const [k, g] of groupBy(values, keyFn)) {
|
|
171
|
+
result.set(k, groupMapFn(g));
|
|
172
|
+
}
|
|
173
|
+
return result;
|
|
174
|
+
};
|
|
175
|
+
export const getTargetDetails = ({ architecture, model, platform, osVersion } = {}) => {
|
|
176
|
+
const osPart = platform ? (osVersion ? `${platform} ${osVersion}` : platform) : undefined;
|
|
177
|
+
return [model, architecture, osPart].filter(isDefined).join(", ") || undefined;
|
|
178
|
+
};
|
|
179
|
+
export const compareChronologically = ({ start: startA, stop: stopA }, { start: startB, stop: stopB }) => (startA ?? 0) - (startB ?? 0) || (stopA ?? 0) - (stopB ?? 0);
|
|
180
|
+
export const toSortedSteps = (...stepArrays) => {
|
|
181
|
+
const allSteps = stepArrays.reduce((result, steps) => {
|
|
182
|
+
result.push(...steps);
|
|
183
|
+
return result;
|
|
184
|
+
}, []);
|
|
185
|
+
allSteps.sort(compareChronologically);
|
|
186
|
+
return allSteps;
|
|
187
|
+
};
|
|
188
|
+
export const secondsToMilliseconds = (seconds) => isNumber(seconds) ? Math.round(MS_IN_S * seconds) : undefined;
|
|
189
|
+
export const parseAsAllureApiActivity = (title) => {
|
|
190
|
+
if (isPotentialAllureApiActivity(title)) {
|
|
191
|
+
const maybeApiCall = title.slice(ALLURE_API_ACTIVITY_PREFIX.length);
|
|
192
|
+
const { apiCall, value } = splitApiCallAndValue(maybeApiCall);
|
|
193
|
+
switch (apiCall) {
|
|
194
|
+
case "id":
|
|
195
|
+
return { type: "label", value: { name: "ALLURE_ID", value } };
|
|
196
|
+
case "name":
|
|
197
|
+
return { type: "name", value };
|
|
198
|
+
case "description":
|
|
199
|
+
return { type: "description", value };
|
|
200
|
+
case "precondition":
|
|
201
|
+
return { type: "precondition", value };
|
|
202
|
+
case "expectedResult":
|
|
203
|
+
return { type: "expectedResult", value };
|
|
204
|
+
case "flaky":
|
|
205
|
+
return { type: "flaky", value: parseBooleanApiArg(value) };
|
|
206
|
+
case "muted":
|
|
207
|
+
return { type: "muted", value: parseBooleanApiArg(value) };
|
|
208
|
+
case "known":
|
|
209
|
+
return { type: "known", value: parseBooleanApiArg(value) };
|
|
210
|
+
default:
|
|
211
|
+
return parseComplexAllureApiCall(apiCall, value);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
export const splitApiCallAndValue = (text) => {
|
|
216
|
+
const apiValueSeparatorIndex = indexOfAny(text, ":", "=");
|
|
217
|
+
return apiValueSeparatorIndex === -1
|
|
218
|
+
? { apiCall: text, value: "" }
|
|
219
|
+
: { apiCall: text.slice(0, apiValueSeparatorIndex).trim(), value: text.slice(apiValueSeparatorIndex + 1) };
|
|
220
|
+
};
|
|
221
|
+
export const applyApiCalls = (testResult, apiCalls) => {
|
|
222
|
+
const groupedApiCalls = mappedGroupBy(apiCalls, (v) => v.type, (g) => g.map(({ value }) => value));
|
|
223
|
+
for (const [type, values] of groupedApiCalls) {
|
|
224
|
+
applyApiCallGroup(testResult, type, values);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
const applyApiCallGroup = (testResult, type, values) => {
|
|
228
|
+
switch (type) {
|
|
229
|
+
case "name":
|
|
230
|
+
testResult.name = values.at(-1);
|
|
231
|
+
break;
|
|
232
|
+
case "flaky":
|
|
233
|
+
testResult.flaky = values.at(-1);
|
|
234
|
+
break;
|
|
235
|
+
case "muted":
|
|
236
|
+
testResult.muted = values.at(-1);
|
|
237
|
+
break;
|
|
238
|
+
case "known":
|
|
239
|
+
testResult.known = values.at(-1);
|
|
240
|
+
break;
|
|
241
|
+
case "description":
|
|
242
|
+
testResult.description = mergeMarkdownBlocks(testResult.description, ...values);
|
|
243
|
+
break;
|
|
244
|
+
case "precondition":
|
|
245
|
+
testResult.precondition = mergeMarkdownBlocks(testResult.precondition, ...values);
|
|
246
|
+
break;
|
|
247
|
+
case "expectedResult":
|
|
248
|
+
testResult.expectedResult = mergeMarkdownBlocks(testResult.expectedResult, ...values);
|
|
249
|
+
break;
|
|
250
|
+
case "label":
|
|
251
|
+
testResult.labels = [...(testResult.labels ?? []), ...values];
|
|
252
|
+
break;
|
|
253
|
+
case "link":
|
|
254
|
+
testResult.links = [...(testResult.links ?? []), ...values];
|
|
255
|
+
break;
|
|
256
|
+
case "parameter":
|
|
257
|
+
testResult.parameters = [...(testResult.parameters ?? []), ...values];
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
export const createTestLabels = ({ hostName, projectName, bundle, suites, className, functionName, tags, }) => {
|
|
262
|
+
const labels = [];
|
|
263
|
+
if (hostName) {
|
|
264
|
+
labels.push({ name: "host", value: hostName });
|
|
265
|
+
}
|
|
266
|
+
const packageName = [projectName, bundle].filter(isDefined).join(".");
|
|
267
|
+
if (packageName) {
|
|
268
|
+
labels.push({ name: "package", value: packageName });
|
|
269
|
+
}
|
|
270
|
+
if (className) {
|
|
271
|
+
labels.push({ name: "testClass", value: className });
|
|
272
|
+
}
|
|
273
|
+
if (functionName) {
|
|
274
|
+
labels.push({ name: "testMethod", value: functionName });
|
|
275
|
+
}
|
|
276
|
+
if (bundle) {
|
|
277
|
+
labels.push({ name: "parentSuite", value: bundle });
|
|
278
|
+
}
|
|
279
|
+
const [suite, ...subSuites] = suites;
|
|
280
|
+
if (suite) {
|
|
281
|
+
labels.push({ name: "suite", value: suite });
|
|
282
|
+
}
|
|
283
|
+
const subSuite = subSuites.join(" > ");
|
|
284
|
+
if (subSuite) {
|
|
285
|
+
labels.push({ name: "subSuite", value: subSuite });
|
|
286
|
+
}
|
|
287
|
+
labels.push(...tags.map((value) => ({ name: "tag", value })));
|
|
288
|
+
return labels;
|
|
289
|
+
};
|
|
290
|
+
export const getDefaultAttachmentName = (index, length) => {
|
|
291
|
+
return length > 1 ? `${DEFAULT_ATTACHMENT_NAME} ${index + 1}` : DEFAULT_ATTACHMENT_NAME;
|
|
292
|
+
};
|
|
293
|
+
const mergeMarkdownBlocks = (...blocks) => blocks.filter(isDefined).reduce((a, b) => `${a}\n\n${b}`);
|
|
294
|
+
const isPotentialAllureApiActivity = (title) => isDefined(title) && title.startsWith(ALLURE_API_ACTIVITY_PREFIX);
|
|
295
|
+
const parseComplexAllureApiCall = (apiCall, value) => {
|
|
296
|
+
const { apiFn, primaryOption, secondaryOptions } = splitApiFnAndOptions(apiCall);
|
|
297
|
+
switch (apiFn) {
|
|
298
|
+
case "label":
|
|
299
|
+
return primaryOption ? parseAllureLabelApiCall(primaryOption, value) : undefined;
|
|
300
|
+
case "link":
|
|
301
|
+
return parseAllureLinkApiCall(primaryOption, secondaryOptions, value);
|
|
302
|
+
case "issue":
|
|
303
|
+
return parseAllureLinkApiCall(primaryOption, ["issue"], value);
|
|
304
|
+
case "tms":
|
|
305
|
+
return parseAllureLinkApiCall(primaryOption, ["tms"], value);
|
|
306
|
+
case "parameter":
|
|
307
|
+
return primaryOption ? parseAllureParameterApiCall(primaryOption, secondaryOptions, value) : undefined;
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
const splitApiFnAndOptions = (apiCall) => {
|
|
311
|
+
const apiFnEnd = apiCall.indexOf(".");
|
|
312
|
+
if (apiFnEnd === -1) {
|
|
313
|
+
const { primaryOption: apiFn, secondaryOptions } = parseAllureApiCallOptions(apiCall);
|
|
314
|
+
return { apiFn, primaryOption: undefined, secondaryOptions };
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
apiFn: apiCall.slice(0, apiFnEnd),
|
|
318
|
+
...parseAllureApiCallOptions(apiCall.slice(apiFnEnd + 1)),
|
|
319
|
+
};
|
|
320
|
+
};
|
|
321
|
+
const parseAllureLabelApiCall = (name, value) => name ? { type: "label", value: { name, value } } : undefined;
|
|
322
|
+
const parseAllureLinkApiCall = (name, [type], url) => {
|
|
323
|
+
return { type: "link", value: { name, type, url } };
|
|
324
|
+
};
|
|
325
|
+
const parseAllureParameterApiCall = (name, options, value) => {
|
|
326
|
+
const parameter = { name, value };
|
|
327
|
+
options.forEach((option) => {
|
|
328
|
+
switch (option.toLowerCase()) {
|
|
329
|
+
case "hidden":
|
|
330
|
+
parameter.hidden = true;
|
|
331
|
+
break;
|
|
332
|
+
case "excluded":
|
|
333
|
+
parameter.excluded = true;
|
|
334
|
+
break;
|
|
335
|
+
case "masked":
|
|
336
|
+
parameter.masked = true;
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
return { type: "parameter", value: parameter };
|
|
341
|
+
};
|
|
342
|
+
const parseAllureApiCallOptions = (options) => {
|
|
343
|
+
const primaryEnd = options.indexOf("[");
|
|
344
|
+
if (primaryEnd !== -1) {
|
|
345
|
+
const primaryOption = decodeURIComponentSafe(options.slice(0, primaryEnd));
|
|
346
|
+
if (options.indexOf("]") === options.length - 1) {
|
|
347
|
+
return {
|
|
348
|
+
primaryOption,
|
|
349
|
+
secondaryOptions: options
|
|
350
|
+
.slice(primaryEnd + 1, -1)
|
|
351
|
+
.split(",")
|
|
352
|
+
.map((v) => decodeURIComponentSafe(v.trim())),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
return { primaryOption, secondaryOptions: [] };
|
|
356
|
+
}
|
|
357
|
+
return { primaryOption: decodeURIComponentSafe(options), secondaryOptions: [] };
|
|
358
|
+
};
|
|
359
|
+
const indexOfAny = (input, ...searchStrings) => {
|
|
360
|
+
const indices = searchStrings.map((search) => input.indexOf(search)).filter((i) => i !== -1);
|
|
361
|
+
switch (indices.length) {
|
|
362
|
+
case 0:
|
|
363
|
+
return -1;
|
|
364
|
+
case 1:
|
|
365
|
+
return indices[0];
|
|
366
|
+
default:
|
|
367
|
+
return Math.min(...indices);
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
const parseBooleanApiArg = (value) => !value || value.toLowerCase() === "true";
|
|
371
|
+
const decodeURIComponentSafe = (value) => {
|
|
372
|
+
try {
|
|
373
|
+
return decodeURIComponent(value);
|
|
374
|
+
}
|
|
375
|
+
catch {
|
|
376
|
+
return value;
|
|
377
|
+
}
|
|
378
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { XcActivities, XcTestDetails, XcTests } from "./xcModel.js";
|
|
2
|
+
export declare const xcrunJson: <T>(utilityName: string, ...args: readonly string[]) => Promise<import("@allurereport/reader-api").Unknown<T>>;
|
|
3
|
+
export declare const xcrunBinary: (utilityName: string, ...args: readonly string[]) => Promise<Buffer | undefined>;
|
|
4
|
+
export declare const xcresulttool: <T>(...args: readonly string[]) => Promise<import("@allurereport/reader-api").Unknown<T>>;
|
|
5
|
+
export declare const xcresulttoolBinary: (...args: readonly string[]) => Promise<Buffer | undefined>;
|
|
6
|
+
export declare const version: () => Promise<string>;
|
|
7
|
+
export declare const getTests: (xcResultPath: string) => Promise<import("@allurereport/reader-api").Unknown<XcTests>>;
|
|
8
|
+
export declare const getTestDetails: (xcResultPath: string, testId: string) => Promise<import("@allurereport/reader-api").Unknown<XcTestDetails>>;
|
|
9
|
+
export declare const getTestActivities: (xcResultPath: string, testId: string) => Promise<import("@allurereport/reader-api").Unknown<XcActivities>>;
|
|
10
|
+
export declare const exportAttachments: (xcResultPath: string, outputPath: string) => Promise<void>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { collectCliToolStdoutText, invokeCliTool, invokeJsonCliTool, invokeStdoutCliTool, } from "@allurereport/reader-api";
|
|
2
|
+
import console from "node:console";
|
|
3
|
+
export const xcrunJson = async (utilityName, ...args) => {
|
|
4
|
+
try {
|
|
5
|
+
return await invokeJsonCliTool("xcrun", [utilityName, ...args], { timeout: 10000 });
|
|
6
|
+
}
|
|
7
|
+
catch (e) {
|
|
8
|
+
console.error(e);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
export const xcrunBinary = async (utilityName, ...args) => {
|
|
12
|
+
try {
|
|
13
|
+
const chunks = [];
|
|
14
|
+
for await (const chunk of invokeStdoutCliTool("xcrun", [utilityName, ...args], { timeout: 60000 })) {
|
|
15
|
+
chunks.push(chunk);
|
|
16
|
+
}
|
|
17
|
+
return Buffer.concat(chunks);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
console.error(e);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export const xcresulttool = async (...args) => await xcrunJson("xcresulttool", ...args);
|
|
24
|
+
export const xcresulttoolBinary = async (...args) => await xcrunBinary("xcresulttool", ...args);
|
|
25
|
+
export const version = async () => {
|
|
26
|
+
const stdout = await collectCliToolStdoutText("xcrun", ["xcresulttool", "version"], { timeout: 10000 });
|
|
27
|
+
return stdout.trim();
|
|
28
|
+
};
|
|
29
|
+
export const getTests = async (xcResultPath) => await xcresulttool("get", "test-results", "tests", "--path", xcResultPath);
|
|
30
|
+
export const getTestDetails = async (xcResultPath, testId) => await xcresulttool("get", "test-results", "test-details", "--test-id", testId, "--path", xcResultPath);
|
|
31
|
+
export const getTestActivities = async (xcResultPath, testId) => await xcresulttool("get", "test-results", "activities", "--test-id", testId, "--path", xcResultPath);
|
|
32
|
+
export const exportAttachments = async (xcResultPath, outputPath) => {
|
|
33
|
+
await invokeCliTool("xcrun", [
|
|
34
|
+
"xcresulttool",
|
|
35
|
+
"export",
|
|
36
|
+
"attachments",
|
|
37
|
+
"--path",
|
|
38
|
+
xcResultPath,
|
|
39
|
+
"--output-path",
|
|
40
|
+
outputPath,
|
|
41
|
+
]);
|
|
42
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ResultFile } from "@allurereport/plugin-api";
|
|
2
|
+
import type { RawTestResult } from "@allurereport/reader-api";
|
|
3
|
+
import { XcresultParser } from "./model.js";
|
|
4
|
+
export default class NewApiParser extends XcresultParser {
|
|
5
|
+
#private;
|
|
6
|
+
parse(): AsyncGenerator<ResultFile | RawTestResult, void, unknown>;
|
|
7
|
+
}
|