testit-adapter-playwright 4.1.0 → 4.1.1-TMS-5.7
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/labels.d.ts +3 -0
- package/dist/labels.js +38 -1
- package/dist/metadata-store.d.ts +24 -0
- package/dist/metadata-store.js +107 -0
- package/dist/reporter.d.ts +6 -0
- package/dist/reporter.js +79 -58
- package/package.json +2 -2
package/dist/labels.d.ts
CHANGED
|
@@ -46,6 +46,9 @@ export declare enum Extensions {
|
|
|
46
46
|
}
|
|
47
47
|
type Parameters = Record<string, string>;
|
|
48
48
|
export declare class testit {
|
|
49
|
+
private static isMetadataAttachment;
|
|
50
|
+
private static readAttachmentBuffer;
|
|
51
|
+
private static mergeMetadataAttachments;
|
|
49
52
|
private static addMetadataAttachment;
|
|
50
53
|
static addAttachment(name: string, content: Buffer | string, options: ContentType | string | Pick<AttachmentOptions, "contentType">): Promise<void>;
|
|
51
54
|
private static mapParams;
|
package/dist/labels.js
CHANGED
|
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.testit = exports.Extensions = exports.ContentType = void 0;
|
|
7
7
|
const crypto_1 = require("crypto");
|
|
8
8
|
const test_1 = __importDefault(require("@playwright/test"));
|
|
9
|
+
const testit_js_commons_1 = require("testit-js-commons");
|
|
10
|
+
const metadata_store_1 = require("./metadata-store");
|
|
9
11
|
const utils_1 = require("./utils");
|
|
10
12
|
var ContentType;
|
|
11
13
|
(function (ContentType) {
|
|
@@ -34,10 +36,45 @@ var Extensions;
|
|
|
34
36
|
Extensions["MD"] = ".md";
|
|
35
37
|
})(Extensions || (exports.Extensions = Extensions = {}));
|
|
36
38
|
class testit {
|
|
39
|
+
static isMetadataAttachment(attachment) {
|
|
40
|
+
return (attachment.contentType === "application/vnd.tms.metadata+json" ||
|
|
41
|
+
attachment.name === "tms-metadata.json");
|
|
42
|
+
}
|
|
43
|
+
static readAttachmentBuffer(attachment) {
|
|
44
|
+
if (attachment.body) {
|
|
45
|
+
return attachment.body;
|
|
46
|
+
}
|
|
47
|
+
if (!attachment.path) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
return testit_js_commons_1.Utils.readBufferSync(attachment.path);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
static mergeMetadataAttachments() {
|
|
58
|
+
let merged = {};
|
|
59
|
+
for (const attachment of test_1.default.info().attachments) {
|
|
60
|
+
if (!this.isMetadataAttachment(attachment)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const body = this.readAttachmentBuffer(attachment);
|
|
64
|
+
if (!body) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
merged = { ...merged, ...JSON.parse(body.toString()) };
|
|
68
|
+
}
|
|
69
|
+
return merged;
|
|
70
|
+
}
|
|
37
71
|
static async addMetadataAttachment(metadata) {
|
|
72
|
+
const info = test_1.default.info();
|
|
73
|
+
(0, metadata_store_1.patchTestMetadataForRun)({ testId: info.testId, file: info.file, titlePath: info.titlePath, title: info.title }, metadata);
|
|
74
|
+
const merged = { ...this.mergeMetadataAttachments(), ...metadata };
|
|
38
75
|
await test_1.default.info().attach("tms-metadata.json", {
|
|
39
76
|
contentType: "application/vnd.tms.metadata+json",
|
|
40
|
-
body: Buffer.from(JSON.stringify(
|
|
77
|
+
body: Buffer.from(JSON.stringify(merged), "utf8"),
|
|
41
78
|
});
|
|
42
79
|
}
|
|
43
80
|
static async addAttachment(name, content, options) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { MetadataMessage } from "./labels";
|
|
2
|
+
export declare function metadataKey(file: string, titlePath: string[]): string;
|
|
3
|
+
export type MetadataRunContext = {
|
|
4
|
+
testId: string;
|
|
5
|
+
file: string;
|
|
6
|
+
titlePath: string[];
|
|
7
|
+
title: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function metadataKeys(ctx: MetadataRunContext): string[];
|
|
10
|
+
/** In-process metadata from testit.*(); attachments alone are unreliable in the reporter. */
|
|
11
|
+
export declare function patchTestMetadataForRun(ctx: MetadataRunContext, patch: MetadataMessage): void;
|
|
12
|
+
export declare function resolveTestMetadata(ctx: {
|
|
13
|
+
testId: string;
|
|
14
|
+
file: string;
|
|
15
|
+
titlePath: string[];
|
|
16
|
+
title: string;
|
|
17
|
+
}): MetadataMessage | undefined;
|
|
18
|
+
export declare function releaseTestMetadata(ctx: {
|
|
19
|
+
testId: string;
|
|
20
|
+
file: string;
|
|
21
|
+
titlePath: string[];
|
|
22
|
+
title: string;
|
|
23
|
+
}): void;
|
|
24
|
+
export declare function applyMetadataTo(target: MetadataMessage, source: MetadataMessage): void;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.metadataKey = metadataKey;
|
|
7
|
+
exports.metadataKeys = metadataKeys;
|
|
8
|
+
exports.patchTestMetadataForRun = patchTestMetadataForRun;
|
|
9
|
+
exports.resolveTestMetadata = resolveTestMetadata;
|
|
10
|
+
exports.releaseTestMetadata = releaseTestMetadata;
|
|
11
|
+
exports.applyMetadataTo = applyMetadataTo;
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const testit_js_commons_1 = require("testit-js-commons");
|
|
14
|
+
const STORE_KEY = Symbol.for("testit.playwright.metadata");
|
|
15
|
+
function metadataMap() {
|
|
16
|
+
const g = globalThis;
|
|
17
|
+
if (!g[STORE_KEY]) {
|
|
18
|
+
g[STORE_KEY] = new Map();
|
|
19
|
+
}
|
|
20
|
+
return g[STORE_KEY];
|
|
21
|
+
}
|
|
22
|
+
function metadataKey(file, titlePath) {
|
|
23
|
+
return `${path_1.default.resolve(file)}\0${titlePath.join("\0")}`;
|
|
24
|
+
}
|
|
25
|
+
function metadataKeys(ctx) {
|
|
26
|
+
const fullTitle = ctx.titlePath.join(" › ");
|
|
27
|
+
return [
|
|
28
|
+
ctx.testId,
|
|
29
|
+
metadataKey(ctx.file, ctx.titlePath),
|
|
30
|
+
metadataKey(ctx.file, [ctx.title]),
|
|
31
|
+
`hash:${testit_js_commons_1.Utils.getHash(ctx.title)}`,
|
|
32
|
+
`hash:${testit_js_commons_1.Utils.getHash(fullTitle)}`,
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
/** In-process metadata from testit.*(); attachments alone are unreliable in the reporter. */
|
|
36
|
+
function patchTestMetadataForRun(ctx, patch) {
|
|
37
|
+
for (const key of metadataKeys(ctx)) {
|
|
38
|
+
const map = metadataMap();
|
|
39
|
+
map.set(key, { ...(map.get(key) ?? {}), ...patch });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function peekTestMetadata(key) {
|
|
43
|
+
return metadataMap().get(key);
|
|
44
|
+
}
|
|
45
|
+
function resolveTestMetadata(ctx) {
|
|
46
|
+
let merged = {};
|
|
47
|
+
let found = false;
|
|
48
|
+
for (const key of metadataKeys(ctx)) {
|
|
49
|
+
const chunk = peekTestMetadata(key);
|
|
50
|
+
if (!chunk) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
merged = { ...merged, ...chunk };
|
|
54
|
+
found = true;
|
|
55
|
+
}
|
|
56
|
+
return found ? merged : undefined;
|
|
57
|
+
}
|
|
58
|
+
function releaseTestMetadata(ctx) {
|
|
59
|
+
const map = metadataMap();
|
|
60
|
+
for (const key of metadataKeys(ctx)) {
|
|
61
|
+
map.delete(key);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function applyMetadataTo(target, source) {
|
|
65
|
+
if (source.externalId) {
|
|
66
|
+
target.externalId = source.externalId;
|
|
67
|
+
}
|
|
68
|
+
if (source.displayName) {
|
|
69
|
+
target.displayName = source.displayName;
|
|
70
|
+
}
|
|
71
|
+
if (source.title) {
|
|
72
|
+
target.title = source.title;
|
|
73
|
+
}
|
|
74
|
+
if (source.description) {
|
|
75
|
+
target.description = source.description;
|
|
76
|
+
}
|
|
77
|
+
if (source.labels) {
|
|
78
|
+
target.labels = source.labels;
|
|
79
|
+
}
|
|
80
|
+
if (source.tags) {
|
|
81
|
+
target.tags = source.tags;
|
|
82
|
+
}
|
|
83
|
+
if (source.links) {
|
|
84
|
+
target.links = source.links;
|
|
85
|
+
}
|
|
86
|
+
if (source.namespace) {
|
|
87
|
+
target.namespace = source.namespace;
|
|
88
|
+
}
|
|
89
|
+
if (source.classname) {
|
|
90
|
+
target.classname = source.classname;
|
|
91
|
+
}
|
|
92
|
+
if (source.addLinks) {
|
|
93
|
+
target.addLinks = source.addLinks;
|
|
94
|
+
}
|
|
95
|
+
if (source.addMessage) {
|
|
96
|
+
target.addMessage = source.addMessage;
|
|
97
|
+
}
|
|
98
|
+
if (source.params) {
|
|
99
|
+
target.params = source.params;
|
|
100
|
+
}
|
|
101
|
+
if (source.workItemIds) {
|
|
102
|
+
target.workItemIds = source.workItemIds;
|
|
103
|
+
}
|
|
104
|
+
if (source.externalKey) {
|
|
105
|
+
target.externalKey = source.externalKey;
|
|
106
|
+
}
|
|
107
|
+
}
|
package/dist/reporter.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ declare class TmsReporter implements Reporter {
|
|
|
27
27
|
onTestBegin(test: TestCase): void;
|
|
28
28
|
onTestEnd(test: TestCase, result: TestResult): void;
|
|
29
29
|
private _processAttachmentsWithExtensions;
|
|
30
|
+
private metadataContext;
|
|
30
31
|
onStepBegin(test: TestCase, _result: TestResult, step: TestStep): void;
|
|
31
32
|
onEnd(): Promise<void>;
|
|
32
33
|
addSkippedResults(): Promise<void>;
|
|
@@ -34,6 +35,11 @@ declare class TmsReporter implements Reporter {
|
|
|
34
35
|
printsToStdio(): boolean;
|
|
35
36
|
private getDictionariesByTest;
|
|
36
37
|
private getAutotestData;
|
|
38
|
+
private isMetadataAttachment;
|
|
39
|
+
/** Playwright copies inline attach to disk — reporter often gets path only, not body. */
|
|
40
|
+
private readAttachmentBuffer;
|
|
41
|
+
/** Each testit.*() call may add a separate tms-metadata.json; merge all of them. */
|
|
42
|
+
private applyMetadataAttachments;
|
|
37
43
|
private loadTest;
|
|
38
44
|
}
|
|
39
45
|
export default TmsReporter;
|
package/dist/reporter.js
CHANGED
|
@@ -19,6 +19,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
20
|
const testit_js_commons_1 = require("testit-js-commons");
|
|
21
21
|
const converter_1 = require("./converter");
|
|
22
|
+
const metadata_store_1 = require("./metadata-store");
|
|
22
23
|
const utils_1 = require("./utils");
|
|
23
24
|
const path_1 = __importDefault(require("path"));
|
|
24
25
|
const testit_js_commons_2 = require("testit-js-commons");
|
|
@@ -66,6 +67,17 @@ class TmsReporter {
|
|
|
66
67
|
_processAttachmentsWithExtensions(result) {
|
|
67
68
|
return result.attachments.map(utils_1.processAttachmentExtensions);
|
|
68
69
|
}
|
|
70
|
+
metadataContext(test) {
|
|
71
|
+
const titlePath = typeof test.titlePath === "function"
|
|
72
|
+
? test.titlePath()
|
|
73
|
+
: [test.title];
|
|
74
|
+
return {
|
|
75
|
+
testId: test.id,
|
|
76
|
+
file: test.location.file,
|
|
77
|
+
titlePath,
|
|
78
|
+
title: test.title,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
69
81
|
onStepBegin(test, _result, step) {
|
|
70
82
|
if (!this.testCache.includes(test)) {
|
|
71
83
|
return;
|
|
@@ -148,6 +160,9 @@ class TmsReporter {
|
|
|
148
160
|
externalKey: test.title,
|
|
149
161
|
};
|
|
150
162
|
for (const attachment of result.attachments) {
|
|
163
|
+
if (this.isMetadataAttachment(attachment)) {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
151
166
|
if (!attachment.body) {
|
|
152
167
|
if (attachment.path && attachment.name !== "screenshot") {
|
|
153
168
|
let content;
|
|
@@ -170,49 +185,6 @@ class TmsReporter {
|
|
|
170
185
|
}
|
|
171
186
|
continue;
|
|
172
187
|
}
|
|
173
|
-
if (attachment.contentType === "application/vnd.tms.metadata+json") {
|
|
174
|
-
const metadata = JSON.parse(attachment.body.toString());
|
|
175
|
-
if (metadata.externalId) {
|
|
176
|
-
autotestData.externalId = metadata.externalId;
|
|
177
|
-
}
|
|
178
|
-
if (metadata.displayName) {
|
|
179
|
-
autotestData.displayName = metadata.displayName;
|
|
180
|
-
}
|
|
181
|
-
if (metadata.title) {
|
|
182
|
-
autotestData.title = metadata.title;
|
|
183
|
-
}
|
|
184
|
-
if (metadata.description) {
|
|
185
|
-
autotestData.description = metadata.description;
|
|
186
|
-
}
|
|
187
|
-
if (metadata.labels) {
|
|
188
|
-
autotestData.labels = metadata.labels;
|
|
189
|
-
}
|
|
190
|
-
if (metadata.tags) {
|
|
191
|
-
autotestData.tags = metadata.tags;
|
|
192
|
-
}
|
|
193
|
-
if (metadata.links) {
|
|
194
|
-
autotestData.links = metadata.links;
|
|
195
|
-
}
|
|
196
|
-
if (metadata.namespace) {
|
|
197
|
-
autotestData.namespace = metadata.namespace;
|
|
198
|
-
}
|
|
199
|
-
if (metadata.classname) {
|
|
200
|
-
autotestData.classname = metadata.classname;
|
|
201
|
-
}
|
|
202
|
-
if (metadata.addLinks) {
|
|
203
|
-
autotestData.addLinks = metadata.addLinks;
|
|
204
|
-
}
|
|
205
|
-
if (metadata.addMessage) {
|
|
206
|
-
autotestData.addMessage = metadata.addMessage;
|
|
207
|
-
}
|
|
208
|
-
if (metadata.params) {
|
|
209
|
-
autotestData.params = metadata.params;
|
|
210
|
-
}
|
|
211
|
-
if (metadata.workItemIds) {
|
|
212
|
-
autotestData.workItemIds = metadata.workItemIds;
|
|
213
|
-
}
|
|
214
|
-
continue;
|
|
215
|
-
}
|
|
216
188
|
if (attachment.name.match(utils_1.stepAttachRegexp)) {
|
|
217
189
|
const step = this.attachmentStepsCache.find((step) => step.title === attachment.name);
|
|
218
190
|
try {
|
|
@@ -228,35 +200,84 @@ class TmsReporter {
|
|
|
228
200
|
}
|
|
229
201
|
}
|
|
230
202
|
}
|
|
203
|
+
this.applyMetadataAttachments(autotestData, result.attachments);
|
|
204
|
+
const stored = (0, metadata_store_1.resolveTestMetadata)(this.metadataContext(test));
|
|
205
|
+
if (stored) {
|
|
206
|
+
(0, metadata_store_1.applyMetadataTo)(autotestData, stored);
|
|
207
|
+
testit_js_commons_2.logger.debug("[playwright] metadata from store", {
|
|
208
|
+
title: test.title,
|
|
209
|
+
namespace: autotestData.namespace,
|
|
210
|
+
classname: autotestData.classname,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
231
213
|
return autotestData;
|
|
232
214
|
}
|
|
215
|
+
isMetadataAttachment(attachment) {
|
|
216
|
+
return (attachment.contentType === "application/vnd.tms.metadata+json" ||
|
|
217
|
+
attachment.name === "tms-metadata.json");
|
|
218
|
+
}
|
|
219
|
+
/** Playwright copies inline attach to disk — reporter often gets path only, not body. */
|
|
220
|
+
readAttachmentBuffer(attachment) {
|
|
221
|
+
if (attachment.body) {
|
|
222
|
+
return attachment.body;
|
|
223
|
+
}
|
|
224
|
+
if (!attachment.path) {
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
try {
|
|
228
|
+
return testit_js_commons_1.Utils.readBufferSync(attachment.path);
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
if (err?.code === "ENOENT") {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
throw err;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/** Each testit.*() call may add a separate tms-metadata.json; merge all of them. */
|
|
238
|
+
applyMetadataAttachments(autotestData, attachments) {
|
|
239
|
+
let merged = {};
|
|
240
|
+
for (const attachment of attachments) {
|
|
241
|
+
if (!this.isMetadataAttachment(attachment)) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
const body = this.readAttachmentBuffer(attachment);
|
|
245
|
+
if (!body) {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
merged = { ...merged, ...JSON.parse(body.toString()) };
|
|
249
|
+
}
|
|
250
|
+
(0, metadata_store_1.applyMetadataTo)(autotestData, merged);
|
|
251
|
+
}
|
|
233
252
|
async loadTest(test, result) {
|
|
234
253
|
testit_js_commons_2.logger.debug("[playwright] loadTest", { title: test.title, status: result.status });
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if (!origin) {
|
|
254
|
+
try {
|
|
255
|
+
const autotestData = await this.getAutotestData(test, result);
|
|
238
256
|
const dictionaries = this.getDictionariesByTest(test);
|
|
239
257
|
const pathNamespace = dictionaries.slice(0, -1).join(path_1.default.sep);
|
|
240
258
|
const pathClassname = dictionaries[dictionaries.length - 1];
|
|
241
|
-
// Prefer testit.namespace / testit.classname from
|
|
259
|
+
// Prefer testit.namespace / testit.classname from metadata; file path only when missing.
|
|
242
260
|
if (pathNamespace.length > 0 && autotestData.namespace == null) {
|
|
243
261
|
autotestData.namespace = pathNamespace;
|
|
244
262
|
}
|
|
245
263
|
if (pathClassname?.length && autotestData.classname == null) {
|
|
246
264
|
autotestData.classname = pathClassname;
|
|
247
265
|
}
|
|
266
|
+
const autotest = converter_1.Converter.convertTestCaseToAutotestPost(autotestData);
|
|
267
|
+
const rawSteps = result.steps?.length
|
|
268
|
+
? result.steps
|
|
269
|
+
: [...this.stepsMap.keys()].filter((step) => this.stepsMap.get(step) === test);
|
|
270
|
+
const stepResults = converter_1.Converter.convertTestStepsToSteps(rawSteps, this.attachmentsMap);
|
|
271
|
+
result.status = (0, utils_1.getTestStatus)(test);
|
|
272
|
+
autotest.steps = converter_1.Converter.convertTestStepsToShortSteps(rawSteps);
|
|
273
|
+
await this.strategy.loadAutotest(autotest, converter_1.Converter.convertStatus(result.status, test.expectedStatus));
|
|
274
|
+
const autotestResult = converter_1.Converter.convertAutotestPostToAutotestResult(autotestData, test, result);
|
|
275
|
+
autotestResult.stepResults = stepResults;
|
|
276
|
+
await this.strategy.loadTestRun([autotestResult]);
|
|
277
|
+
}
|
|
278
|
+
finally {
|
|
279
|
+
(0, metadata_store_1.releaseTestMetadata)(this.metadataContext(test));
|
|
248
280
|
}
|
|
249
|
-
const autotest = converter_1.Converter.convertTestCaseToAutotestPost(autotestData);
|
|
250
|
-
const rawSteps = result.steps?.length
|
|
251
|
-
? result.steps
|
|
252
|
-
: [...this.stepsMap.keys()].filter((step) => this.stepsMap.get(step) === test);
|
|
253
|
-
const stepResults = converter_1.Converter.convertTestStepsToSteps(rawSteps, this.attachmentsMap);
|
|
254
|
-
result.status = (0, utils_1.getTestStatus)(test);
|
|
255
|
-
autotest.steps = converter_1.Converter.convertTestStepsToShortSteps(rawSteps);
|
|
256
|
-
await this.strategy.loadAutotest(autotest, converter_1.Converter.convertStatus(result.status, test.expectedStatus));
|
|
257
|
-
const autotestResult = converter_1.Converter.convertAutotestPostToAutotestResult(autotestData, test, result);
|
|
258
|
-
autotestResult.stepResults = stepResults;
|
|
259
|
-
await this.strategy.loadTestRun([autotestResult]);
|
|
260
281
|
}
|
|
261
282
|
}
|
|
262
283
|
exports.default = TmsReporter;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testit-adapter-playwright",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.1-TMS-5.7",
|
|
4
4
|
"description": "Playwright adapter for Test IT",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"prettier": "^3.0.1"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"testit-js-commons": "4.1.
|
|
43
|
+
"testit-js-commons": "4.1.1-TMS-5.7"
|
|
44
44
|
},
|
|
45
45
|
"files": [
|
|
46
46
|
"dist"
|