testit-adapter-cypress 3.7.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.
- package/README.md +240 -0
- package/dist/browser/commandLog.d.ts +10 -0
- package/dist/browser/commandLog.js +213 -0
- package/dist/browser/events/cypress.d.ts +2 -0
- package/dist/browser/events/cypress.js +38 -0
- package/dist/browser/events/index.d.ts +2 -0
- package/dist/browser/events/index.js +15 -0
- package/dist/browser/events/mocha.d.ts +3 -0
- package/dist/browser/events/mocha.js +80 -0
- package/dist/browser/index.d.ts +1 -0
- package/dist/browser/index.js +14 -0
- package/dist/browser/lifecycle.d.ts +21 -0
- package/dist/browser/lifecycle.js +227 -0
- package/dist/browser/patching.d.ts +5 -0
- package/dist/browser/patching.js +117 -0
- package/dist/browser/runtime.d.ts +31 -0
- package/dist/browser/runtime.js +284 -0
- package/dist/browser/serialize.d.ts +3 -0
- package/dist/browser/serialize.js +57 -0
- package/dist/browser/state.d.ts +28 -0
- package/dist/browser/state.js +80 -0
- package/dist/browser/steps.d.ts +14 -0
- package/dist/browser/steps.js +114 -0
- package/dist/browser/testplan.d.ts +2 -0
- package/dist/browser/testplan.js +55 -0
- package/dist/browser/types.d.ts +35 -0
- package/dist/browser/types.js +30 -0
- package/dist/browser/utils.d.ts +65 -0
- package/dist/browser/utils.js +187 -0
- package/dist/converter.d.ts +43 -0
- package/dist/converter.js +84 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -0
- package/dist/models/index.d.ts +0 -0
- package/dist/models/index.js +1 -0
- package/dist/models/status.d.ts +5 -0
- package/dist/models/status.js +9 -0
- package/dist/models/types.d.ts +280 -0
- package/dist/models/types.js +2 -0
- package/dist/node-utils.d.ts +15 -0
- package/dist/node-utils.js +93 -0
- package/dist/reporter.d.ts +24 -0
- package/dist/reporter.js +382 -0
- package/dist/utils.d.ts +17 -0
- package/dist/utils.js +34 -0
- package/package.json +50 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Helpers that use Node.js built-in modules. Import only in Node context (e.g. reporter, plugins).
|
|
4
|
+
* Do not import in browser bundle (Cypress support/specs).
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
40
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.getProjectRoot = getProjectRoot;
|
|
44
|
+
exports.getRelativePath = getRelativePath;
|
|
45
|
+
exports.getPosixPath = getPosixPath;
|
|
46
|
+
exports.parseTestPlan = parseTestPlan;
|
|
47
|
+
const fs = __importStar(require("node:fs"));
|
|
48
|
+
const path = __importStar(require("node:path"));
|
|
49
|
+
const node_process_1 = __importDefault(require("node:process"));
|
|
50
|
+
let cachedProjectRoot = null;
|
|
51
|
+
function findProjectRoot() {
|
|
52
|
+
let dir = node_process_1.default.cwd();
|
|
53
|
+
while (dir !== path.dirname(dir)) {
|
|
54
|
+
try {
|
|
55
|
+
fs.accessSync(path.join(dir, "package.json"), fs.constants.F_OK);
|
|
56
|
+
return dir;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
dir = path.dirname(dir);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return node_process_1.default.cwd();
|
|
63
|
+
}
|
|
64
|
+
function getProjectRoot() {
|
|
65
|
+
if (!cachedProjectRoot)
|
|
66
|
+
cachedProjectRoot = findProjectRoot();
|
|
67
|
+
return cachedProjectRoot;
|
|
68
|
+
}
|
|
69
|
+
function getRelativePath(absolutePath) {
|
|
70
|
+
const root = getProjectRoot();
|
|
71
|
+
if (path.isAbsolute(absolutePath)) {
|
|
72
|
+
return path.relative(root, absolutePath);
|
|
73
|
+
}
|
|
74
|
+
return absolutePath;
|
|
75
|
+
}
|
|
76
|
+
function getPosixPath(filepath) {
|
|
77
|
+
return node_process_1.default.platform === "win32" ? filepath.replaceAll("\\", "/") : filepath;
|
|
78
|
+
}
|
|
79
|
+
function parseTestPlan() {
|
|
80
|
+
const envPath = node_process_1.default.env.TMS_TESTPLAN_PATH;
|
|
81
|
+
if (!envPath)
|
|
82
|
+
return undefined;
|
|
83
|
+
try {
|
|
84
|
+
const content = fs.readFileSync(envPath, "utf-8");
|
|
85
|
+
const plan = JSON.parse(content);
|
|
86
|
+
if (!plan.tests?.length)
|
|
87
|
+
return undefined;
|
|
88
|
+
return plan;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { TestData, StepData } from "./converter.js";
|
|
2
|
+
import type { TmsCypressConfig } from "./models/types.js";
|
|
3
|
+
interface TestItSpecContext {
|
|
4
|
+
specPath: string;
|
|
5
|
+
suiteNames: string[];
|
|
6
|
+
currentTestData: TestData | null;
|
|
7
|
+
completedTests: TestData[];
|
|
8
|
+
stepsByFrontEndId: Map<string, StepData>;
|
|
9
|
+
stepStack: StepData[];
|
|
10
|
+
failed: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare class TmsCypress {
|
|
13
|
+
#private;
|
|
14
|
+
private strategy;
|
|
15
|
+
private additions;
|
|
16
|
+
specContextByAbsolutePath: Map<string, TestItSpecContext>;
|
|
17
|
+
videoOnFailOnly: boolean;
|
|
18
|
+
constructor(config?: TmsCypressConfig);
|
|
19
|
+
attachToCypress: (on: Cypress.PluginEvents) => void;
|
|
20
|
+
onAfterSpec: (spec: Cypress.Spec, results: CypressCommandLine.RunResult | undefined) => void;
|
|
21
|
+
endSpec: (specAbsolutePath: string, cypressVideoPath?: string) => Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export declare const tmsCypress: (on: Cypress.PluginEvents, cypressConfig?: Cypress.PluginConfigOptions, tmsConfig?: TmsCypressConfig) => TmsCypress;
|
|
24
|
+
export {};
|
package/dist/reporter.js
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
7
|
+
var _TmsCypress_endAllSpecs, _TmsCypress_applySpecMessages, _TmsCypress_startRun, _TmsCypress_startSuite, _TmsCypress_stopSuite, _TmsCypress_startHook, _TmsCypress_stopHook, _TmsCypress_startTest, _TmsCypress_passTest, _TmsCypress_failTest, _TmsCypress_skipTest, _TmsCypress_addSkippedTest, _TmsCypress_stopTest, _TmsCypress_startStep, _TmsCypress_stopStep, _TmsCypress_finalizeStep, _TmsCypress_handleAttachmentPath, _TmsCypress_handleAttachmentContent, _TmsCypress_applyRuntimeMessage;
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.tmsCypress = exports.TmsCypress = void 0;
|
|
10
|
+
const testit_js_commons_1 = require("testit-js-commons");
|
|
11
|
+
const converter_js_1 = require("./converter.js");
|
|
12
|
+
const utils_js_1 = require("./utils.js");
|
|
13
|
+
const node_utils_js_1 = require("./node-utils.js");
|
|
14
|
+
const status_js_1 = require("./models/status.js");
|
|
15
|
+
class TmsCypress {
|
|
16
|
+
constructor(config = {}) {
|
|
17
|
+
this.specContextByAbsolutePath = new Map();
|
|
18
|
+
this.videoOnFailOnly = false;
|
|
19
|
+
this.attachToCypress = (on) => {
|
|
20
|
+
on("before:run", async () => {
|
|
21
|
+
await this.strategy.setup();
|
|
22
|
+
});
|
|
23
|
+
on("task", {
|
|
24
|
+
reportTmsCypressSpecMessages: async (args) => {
|
|
25
|
+
await __classPrivateFieldGet(this, _TmsCypress_applySpecMessages, "f").call(this, args);
|
|
26
|
+
return null;
|
|
27
|
+
},
|
|
28
|
+
reportFinalTmsCypressSpecMessages: async (args) => {
|
|
29
|
+
await __classPrivateFieldGet(this, _TmsCypress_applySpecMessages, "f").call(this, args);
|
|
30
|
+
if (args.isInteractive) {
|
|
31
|
+
await this.endSpec(args.absolutePath);
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
on("after:spec", this.onAfterSpec);
|
|
37
|
+
on("after:run", async () => {
|
|
38
|
+
await __classPrivateFieldGet(this, _TmsCypress_endAllSpecs, "f").call(this);
|
|
39
|
+
await this.strategy.teardown();
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
this.onAfterSpec = (spec, results) => {
|
|
43
|
+
this.endSpec(spec.absolute, results?.video ?? undefined);
|
|
44
|
+
};
|
|
45
|
+
this.endSpec = async (specAbsolutePath, cypressVideoPath) => {
|
|
46
|
+
const context = this.specContextByAbsolutePath.get(specAbsolutePath);
|
|
47
|
+
if (!context)
|
|
48
|
+
return;
|
|
49
|
+
let videoAttachmentIds = [];
|
|
50
|
+
if ((!this.videoOnFailOnly || context.failed) && cypressVideoPath) {
|
|
51
|
+
try {
|
|
52
|
+
const attachments = await this.additions.addAttachments([cypressVideoPath]);
|
|
53
|
+
videoAttachmentIds = attachments.map((a) => a.id);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// ignore
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const posixSpecPath = (0, node_utils_js_1.getRelativePath)(specAbsolutePath).replace(/\\/g, "/");
|
|
60
|
+
const uniqueByFullName = new Map();
|
|
61
|
+
for (const t of context.completedTests) {
|
|
62
|
+
uniqueByFullName.set(t.fullNameSuffix, t);
|
|
63
|
+
}
|
|
64
|
+
for (const t of uniqueByFullName.values()) {
|
|
65
|
+
const autotest = (0, converter_js_1.toAutotestPost)(posixSpecPath, t);
|
|
66
|
+
await this.strategy.loadAutotest(autotest, t.outcome);
|
|
67
|
+
const result = (0, converter_js_1.toAutotestResult)(autotest.externalId, t, t.outcome, videoAttachmentIds);
|
|
68
|
+
await this.strategy.loadTestRun([result]);
|
|
69
|
+
}
|
|
70
|
+
this.specContextByAbsolutePath.delete(specAbsolutePath);
|
|
71
|
+
};
|
|
72
|
+
_TmsCypress_endAllSpecs.set(this, async () => {
|
|
73
|
+
for (const path of Array.from(this.specContextByAbsolutePath.keys())) {
|
|
74
|
+
await this.endSpec(path);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
_TmsCypress_applySpecMessages.set(this, async ({ messages, absolutePath }) => {
|
|
78
|
+
if (messages.some((m) => m.type === "cypress_run_start")) {
|
|
79
|
+
__classPrivateFieldGet(this, _TmsCypress_startRun, "f").call(this, absolutePath);
|
|
80
|
+
}
|
|
81
|
+
const context = this.specContextByAbsolutePath.get(absolutePath);
|
|
82
|
+
if (!context)
|
|
83
|
+
return;
|
|
84
|
+
for (const message of messages) {
|
|
85
|
+
if (message.type === "cypress_run_start")
|
|
86
|
+
continue;
|
|
87
|
+
switch (message.type) {
|
|
88
|
+
case "cypress_suite_start":
|
|
89
|
+
__classPrivateFieldGet(this, _TmsCypress_startSuite, "f").call(this, context, message.data);
|
|
90
|
+
break;
|
|
91
|
+
case "cypress_suite_end":
|
|
92
|
+
__classPrivateFieldGet(this, _TmsCypress_stopSuite, "f").call(this, context, message.data);
|
|
93
|
+
break;
|
|
94
|
+
case "cypress_hook_start":
|
|
95
|
+
__classPrivateFieldGet(this, _TmsCypress_startHook, "f").call(this, context, message.data);
|
|
96
|
+
break;
|
|
97
|
+
case "cypress_hook_end":
|
|
98
|
+
__classPrivateFieldGet(this, _TmsCypress_stopHook, "f").call(this);
|
|
99
|
+
break;
|
|
100
|
+
case "cypress_test_start":
|
|
101
|
+
__classPrivateFieldGet(this, _TmsCypress_startTest, "f").call(this, context, message.data);
|
|
102
|
+
break;
|
|
103
|
+
case "cypress_test_pass":
|
|
104
|
+
__classPrivateFieldGet(this, _TmsCypress_passTest, "f").call(this, context);
|
|
105
|
+
break;
|
|
106
|
+
case "cypress_fail":
|
|
107
|
+
__classPrivateFieldGet(this, _TmsCypress_failTest, "f").call(this, context, message.data);
|
|
108
|
+
break;
|
|
109
|
+
case "cypress_test_skip":
|
|
110
|
+
__classPrivateFieldGet(this, _TmsCypress_skipTest, "f").call(this, context, message.data);
|
|
111
|
+
break;
|
|
112
|
+
case "cypress_skipped_test":
|
|
113
|
+
__classPrivateFieldGet(this, _TmsCypress_addSkippedTest, "f").call(this, context, message.data);
|
|
114
|
+
break;
|
|
115
|
+
case "cypress_test_end":
|
|
116
|
+
__classPrivateFieldGet(this, _TmsCypress_stopTest, "f").call(this, context, message.data);
|
|
117
|
+
break;
|
|
118
|
+
case "cypress_step_start":
|
|
119
|
+
__classPrivateFieldGet(this, _TmsCypress_startStep, "f").call(this, context, message.data);
|
|
120
|
+
break;
|
|
121
|
+
case "cypress_step_stop":
|
|
122
|
+
__classPrivateFieldGet(this, _TmsCypress_stopStep, "f").call(this, context, message.data);
|
|
123
|
+
break;
|
|
124
|
+
case "cypress_step_finalize":
|
|
125
|
+
__classPrivateFieldGet(this, _TmsCypress_finalizeStep, "f").call(this, context, message.data);
|
|
126
|
+
break;
|
|
127
|
+
case "attachment_path":
|
|
128
|
+
await __classPrivateFieldGet(this, _TmsCypress_handleAttachmentPath, "f").call(this, context, message.data);
|
|
129
|
+
break;
|
|
130
|
+
case "attachment_content":
|
|
131
|
+
await __classPrivateFieldGet(this, _TmsCypress_handleAttachmentContent, "f").call(this, context, message.data);
|
|
132
|
+
break;
|
|
133
|
+
default:
|
|
134
|
+
__classPrivateFieldGet(this, _TmsCypress_applyRuntimeMessage, "f").call(this, context, message);
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
_TmsCypress_startRun.set(this, (absolutePath) => {
|
|
140
|
+
const specPath = (0, node_utils_js_1.getRelativePath)(absolutePath);
|
|
141
|
+
const context = {
|
|
142
|
+
specPath,
|
|
143
|
+
suiteNames: [],
|
|
144
|
+
currentTestData: null,
|
|
145
|
+
completedTests: [],
|
|
146
|
+
stepsByFrontEndId: new Map(),
|
|
147
|
+
stepStack: [],
|
|
148
|
+
failed: false,
|
|
149
|
+
};
|
|
150
|
+
this.specContextByAbsolutePath.set(absolutePath, context);
|
|
151
|
+
});
|
|
152
|
+
_TmsCypress_startSuite.set(this, (context, data) => {
|
|
153
|
+
if (!data.root) {
|
|
154
|
+
context.suiteNames.push(data.name);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
_TmsCypress_stopSuite.set(this, (context, data) => {
|
|
158
|
+
if (!data.root && context.suiteNames.length) {
|
|
159
|
+
context.suiteNames.pop();
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
_TmsCypress_startHook.set(this, (context, _data) => {
|
|
163
|
+
if (context.currentTestData)
|
|
164
|
+
return;
|
|
165
|
+
context.stepStack = [];
|
|
166
|
+
});
|
|
167
|
+
_TmsCypress_stopHook.set(this, () => { });
|
|
168
|
+
_TmsCypress_startTest.set(this, (context, data) => {
|
|
169
|
+
context.stepStack = [];
|
|
170
|
+
context.stepsByFrontEndId.clear();
|
|
171
|
+
context.currentTestData = {
|
|
172
|
+
displayName: data.name,
|
|
173
|
+
fullNameSuffix: data.fullNameSuffix,
|
|
174
|
+
outcome: status_js_1.Status.PASSED,
|
|
175
|
+
labels: data.labels ?? [],
|
|
176
|
+
tags: data.tags ?? [],
|
|
177
|
+
links: data.links ?? [],
|
|
178
|
+
workItemIds: data.workItemIds ?? [],
|
|
179
|
+
start: data.start,
|
|
180
|
+
steps: [],
|
|
181
|
+
attachmentIds: [],
|
|
182
|
+
externalKey: data.fullNameSuffix,
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
_TmsCypress_passTest.set(this, (context) => {
|
|
186
|
+
if (context.currentTestData)
|
|
187
|
+
context.currentTestData.outcome = status_js_1.Status.PASSED;
|
|
188
|
+
});
|
|
189
|
+
_TmsCypress_failTest.set(this, (context, data) => {
|
|
190
|
+
context.failed = true;
|
|
191
|
+
if (context.currentTestData) {
|
|
192
|
+
context.currentTestData.outcome = data.status === status_js_1.Status.SKIPPED ? status_js_1.Status.SKIPPED : status_js_1.Status.FAILED;
|
|
193
|
+
context.currentTestData.statusDetails = data.statusDetails;
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
_TmsCypress_skipTest.set(this, (context, data) => {
|
|
197
|
+
if (context.currentTestData) {
|
|
198
|
+
context.currentTestData.outcome = status_js_1.Status.SKIPPED;
|
|
199
|
+
if (data.statusDetails)
|
|
200
|
+
context.currentTestData.statusDetails = data.statusDetails;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
_TmsCypress_addSkippedTest.set(this, (context, data) => {
|
|
204
|
+
const alreadyAdded = context.completedTests.some((c) => c.fullNameSuffix === data.fullNameSuffix) ||
|
|
205
|
+
(context.currentTestData?.fullNameSuffix === data.fullNameSuffix);
|
|
206
|
+
if (alreadyAdded)
|
|
207
|
+
return;
|
|
208
|
+
const t = {
|
|
209
|
+
displayName: data.name,
|
|
210
|
+
fullNameSuffix: data.fullNameSuffix,
|
|
211
|
+
labels: data.labels ?? [],
|
|
212
|
+
tags: data.tags ?? [],
|
|
213
|
+
links: data.links ?? [],
|
|
214
|
+
workItemIds: data.workItemIds ?? [],
|
|
215
|
+
outcome: status_js_1.Status.SKIPPED,
|
|
216
|
+
duration: data.duration,
|
|
217
|
+
statusDetails: data.statusDetails,
|
|
218
|
+
steps: [],
|
|
219
|
+
attachmentIds: [],
|
|
220
|
+
externalKey: data.fullNameSuffix,
|
|
221
|
+
};
|
|
222
|
+
context.completedTests.push(t);
|
|
223
|
+
});
|
|
224
|
+
_TmsCypress_stopTest.set(this, (context, data) => {
|
|
225
|
+
var _a;
|
|
226
|
+
if (context.currentTestData) {
|
|
227
|
+
context.currentTestData.duration = data.duration;
|
|
228
|
+
if (context.currentTestData.start != null) {
|
|
229
|
+
context.currentTestData.stop = context.currentTestData.start + data.duration;
|
|
230
|
+
}
|
|
231
|
+
(_a = context.currentTestData).outcome ?? (_a.outcome = status_js_1.Status.PASSED);
|
|
232
|
+
context.completedTests.push(context.currentTestData);
|
|
233
|
+
context.currentTestData = null;
|
|
234
|
+
}
|
|
235
|
+
context.stepStack = [];
|
|
236
|
+
context.stepsByFrontEndId.clear();
|
|
237
|
+
});
|
|
238
|
+
_TmsCypress_startStep.set(this, (context, data) => {
|
|
239
|
+
const step = {
|
|
240
|
+
id: data.id,
|
|
241
|
+
name: data.name,
|
|
242
|
+
start: data.start,
|
|
243
|
+
attachmentIds: [],
|
|
244
|
+
children: [],
|
|
245
|
+
};
|
|
246
|
+
context.stepsByFrontEndId.set(data.id, step);
|
|
247
|
+
if (!context.currentTestData)
|
|
248
|
+
return;
|
|
249
|
+
const parent = (0, utils_js_1.last)(context.stepStack);
|
|
250
|
+
if (parent) {
|
|
251
|
+
parent.children.push(step);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
context.currentTestData.steps.push(step);
|
|
255
|
+
}
|
|
256
|
+
context.stepStack.push(step);
|
|
257
|
+
});
|
|
258
|
+
_TmsCypress_stopStep.set(this, (context, data) => {
|
|
259
|
+
const step = context.stepsByFrontEndId.get(data.id);
|
|
260
|
+
if (step) {
|
|
261
|
+
step.stop = data.stop;
|
|
262
|
+
step.status = data.status;
|
|
263
|
+
step.statusDetails = data.statusDetails;
|
|
264
|
+
}
|
|
265
|
+
if (context.stepStack.length)
|
|
266
|
+
context.stepStack.pop();
|
|
267
|
+
});
|
|
268
|
+
_TmsCypress_finalizeStep.set(this, (context, data) => {
|
|
269
|
+
const step = context.stepsByFrontEndId.get(data.id);
|
|
270
|
+
if (step) {
|
|
271
|
+
if (data.name)
|
|
272
|
+
step.name = data.name;
|
|
273
|
+
if (data.statusDetails)
|
|
274
|
+
step.statusDetails = data.statusDetails;
|
|
275
|
+
}
|
|
276
|
+
context.stepsByFrontEndId.delete(data.id);
|
|
277
|
+
});
|
|
278
|
+
_TmsCypress_handleAttachmentPath.set(this, async (context, data) => {
|
|
279
|
+
try {
|
|
280
|
+
const attachments = await this.additions.addAttachments([data.path]);
|
|
281
|
+
const ids = attachments.map((a) => a.id);
|
|
282
|
+
const target = (0, utils_js_1.last)(context.stepStack) ?? context.currentTestData;
|
|
283
|
+
if (target)
|
|
284
|
+
target.attachmentIds.push(...ids);
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
// ignore
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
_TmsCypress_handleAttachmentContent.set(this, async (context, data) => {
|
|
291
|
+
try {
|
|
292
|
+
const buffer = Buffer.from(data.content, data.encoding);
|
|
293
|
+
const attachments = await this.additions.addAttachments(buffer, data.name);
|
|
294
|
+
const ids = attachments.map((a) => a.id);
|
|
295
|
+
const target = (0, utils_js_1.last)(context.stepStack) ?? context.currentTestData;
|
|
296
|
+
if (target)
|
|
297
|
+
target.attachmentIds.push(...ids);
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
// ignore
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
_TmsCypress_applyRuntimeMessage.set(this, (context, message) => {
|
|
304
|
+
if (message.type !== "metadata" || !context.currentTestData)
|
|
305
|
+
return;
|
|
306
|
+
const data = message.data;
|
|
307
|
+
const current = context.currentTestData;
|
|
308
|
+
if (data.labels?.length) {
|
|
309
|
+
current.labels.push(...data.labels);
|
|
310
|
+
}
|
|
311
|
+
if (data.tags?.length) {
|
|
312
|
+
current.tags.push(...data.tags);
|
|
313
|
+
}
|
|
314
|
+
if (data.links?.length) {
|
|
315
|
+
current.links.push(...data.links.map((l) => ({
|
|
316
|
+
url: l.url,
|
|
317
|
+
title: l.title ?? l.url,
|
|
318
|
+
description: l.description,
|
|
319
|
+
})));
|
|
320
|
+
}
|
|
321
|
+
if (data.parameters?.length) {
|
|
322
|
+
current.parameters ?? (current.parameters = {});
|
|
323
|
+
for (const p of data.parameters) {
|
|
324
|
+
current.parameters[p.name] = p.value;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (data.description) {
|
|
328
|
+
current.description = data.description;
|
|
329
|
+
}
|
|
330
|
+
else if (data.descriptionHtml && !current.description) {
|
|
331
|
+
current.description = data.descriptionHtml;
|
|
332
|
+
}
|
|
333
|
+
if (data.displayName) {
|
|
334
|
+
current.displayName = data.displayName;
|
|
335
|
+
}
|
|
336
|
+
if (data.title) {
|
|
337
|
+
current.title = data.title;
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
const { videoOnFailOnly = false, ...rest } = config;
|
|
341
|
+
this.videoOnFailOnly = videoOnFailOnly;
|
|
342
|
+
const adapterConfig = rest.tmsOptions ?? rest;
|
|
343
|
+
const composed = new testit_js_commons_1.ConfigComposer().compose(adapterConfig);
|
|
344
|
+
this.strategy = testit_js_commons_1.StrategyFactory.create(composed);
|
|
345
|
+
this.additions = new testit_js_commons_1.Additions(composed);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
exports.TmsCypress = TmsCypress;
|
|
349
|
+
_TmsCypress_endAllSpecs = new WeakMap(), _TmsCypress_applySpecMessages = new WeakMap(), _TmsCypress_startRun = new WeakMap(), _TmsCypress_startSuite = new WeakMap(), _TmsCypress_stopSuite = new WeakMap(), _TmsCypress_startHook = new WeakMap(), _TmsCypress_stopHook = new WeakMap(), _TmsCypress_startTest = new WeakMap(), _TmsCypress_passTest = new WeakMap(), _TmsCypress_failTest = new WeakMap(), _TmsCypress_skipTest = new WeakMap(), _TmsCypress_addSkippedTest = new WeakMap(), _TmsCypress_stopTest = new WeakMap(), _TmsCypress_startStep = new WeakMap(), _TmsCypress_stopStep = new WeakMap(), _TmsCypress_finalizeStep = new WeakMap(), _TmsCypress_handleAttachmentPath = new WeakMap(), _TmsCypress_handleAttachmentContent = new WeakMap(), _TmsCypress_applyRuntimeMessage = new WeakMap();
|
|
350
|
+
const getRuntimeConfigDefaults = (config = {}) => ({
|
|
351
|
+
stepsFromCommands: {
|
|
352
|
+
maxArgumentLength: config.stepsFromCommands?.maxArgumentLength ?? utils_js_1.DEFAULT_RUNTIME_CONFIG.stepsFromCommands.maxArgumentLength,
|
|
353
|
+
maxArgumentDepth: config.stepsFromCommands?.maxArgumentDepth ?? utils_js_1.DEFAULT_RUNTIME_CONFIG.stepsFromCommands.maxArgumentDepth,
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
const createRuntimeState = (config) => ({
|
|
357
|
+
config: getRuntimeConfigDefaults(config),
|
|
358
|
+
initialized: false,
|
|
359
|
+
messages: [],
|
|
360
|
+
testPlan: (0, node_utils_js_1.parseTestPlan)(),
|
|
361
|
+
projectDir: (0, node_utils_js_1.getProjectRoot)(),
|
|
362
|
+
stepStack: [],
|
|
363
|
+
stepsToFinalize: [],
|
|
364
|
+
nextApiStepId: 0,
|
|
365
|
+
});
|
|
366
|
+
const initializeRuntimeState = (cypressConfig, config) => {
|
|
367
|
+
cypressConfig.env.tms = createRuntimeState(config);
|
|
368
|
+
return cypressConfig;
|
|
369
|
+
};
|
|
370
|
+
const tmsCypress = (on, cypressConfig, tmsConfig) => {
|
|
371
|
+
if (!tmsConfig && cypressConfig && !("env" in cypressConfig)) {
|
|
372
|
+
tmsConfig = cypressConfig;
|
|
373
|
+
}
|
|
374
|
+
const hasCypressConfig = cypressConfig && "env" in cypressConfig;
|
|
375
|
+
const reporter = new TmsCypress(tmsConfig);
|
|
376
|
+
reporter.attachToCypress(on);
|
|
377
|
+
if (hasCypressConfig) {
|
|
378
|
+
initializeRuntimeState(cypressConfig, tmsConfig);
|
|
379
|
+
}
|
|
380
|
+
return reporter;
|
|
381
|
+
};
|
|
382
|
+
exports.tmsCypress = tmsCypress;
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const DEFAULT_RUNTIME_CONFIG: {
|
|
2
|
+
stepsFromCommands: {
|
|
3
|
+
maxArgumentLength: number;
|
|
4
|
+
maxArgumentDepth: number;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Pops items from an array into a new one. The item that matches the predicate is the last item to pop.
|
|
9
|
+
* If there is no such item in the array, the array is left unmodified.
|
|
10
|
+
* @param items An array to pop the items from.
|
|
11
|
+
* @param pred A predicate that defines the last item to pop.
|
|
12
|
+
* @returns An array of popped items. The first popped item becomes the first element of this array.
|
|
13
|
+
*/
|
|
14
|
+
export declare const popUntilFindIncluded: <T>(items: T[], pred: (value: T) => boolean) => T[];
|
|
15
|
+
export declare const toReversed: <T = unknown>(arr: T[]) => T[];
|
|
16
|
+
export declare const last: <T = unknown>(arr: T[]) => T | undefined;
|
|
17
|
+
export declare const isDefined: <T>(value: T | undefined) => value is T;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isDefined = exports.last = exports.toReversed = exports.popUntilFindIncluded = exports.DEFAULT_RUNTIME_CONFIG = void 0;
|
|
4
|
+
exports.DEFAULT_RUNTIME_CONFIG = {
|
|
5
|
+
stepsFromCommands: {
|
|
6
|
+
maxArgumentLength: 128,
|
|
7
|
+
maxArgumentDepth: 3,
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Pops items from an array into a new one. The item that matches the predicate is the last item to pop.
|
|
12
|
+
* If there is no such item in the array, the array is left unmodified.
|
|
13
|
+
* @param items An array to pop the items from.
|
|
14
|
+
* @param pred A predicate that defines the last item to pop.
|
|
15
|
+
* @returns An array of popped items. The first popped item becomes the first element of this array.
|
|
16
|
+
*/
|
|
17
|
+
const popUntilFindIncluded = (items, pred) => {
|
|
18
|
+
const index = items.findIndex(pred);
|
|
19
|
+
return index !== -1 ? (0, exports.toReversed)(items.splice(index)) : [];
|
|
20
|
+
};
|
|
21
|
+
exports.popUntilFindIncluded = popUntilFindIncluded;
|
|
22
|
+
const toReversed = (arr) => {
|
|
23
|
+
const len = arr.length;
|
|
24
|
+
const result = new Array(len);
|
|
25
|
+
for (let i = 0; i < len; i++) {
|
|
26
|
+
result[len - i - 1] = arr[i];
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
};
|
|
30
|
+
exports.toReversed = toReversed;
|
|
31
|
+
const last = (arr) => arr[arr.length - 1];
|
|
32
|
+
exports.last = last;
|
|
33
|
+
const isDefined = (value) => typeof value !== "undefined";
|
|
34
|
+
exports.isDefined = isDefined;
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "testit-adapter-cypress",
|
|
3
|
+
"version": "3.7.5",
|
|
4
|
+
"description": "Cypress adapter for Test IT",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Integration team",
|
|
8
|
+
"email": "integrations@testit.software"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/testit-tms/adapters-js.git"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [],
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./reporter": {
|
|
23
|
+
"types": "./dist/reporter.d.ts",
|
|
24
|
+
"default": "./dist/reporter.js"
|
|
25
|
+
},
|
|
26
|
+
"./runtime": {
|
|
27
|
+
"types": "./dist/browser/runtime.d.ts",
|
|
28
|
+
"default": "./dist/browser/runtime.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"clean": "rimraf ./dist ./out",
|
|
33
|
+
"prebuild": "npm --prefix ../testit-js-commons run build && npm link ../testit-js-commons",
|
|
34
|
+
"build": "tsc -p tsconfig.json"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"cypress": "14.2.0",
|
|
38
|
+
"typescript": "^5.2.2",
|
|
39
|
+
"esbuild": "^0.27.0",
|
|
40
|
+
"eslint": "^8.57.0",
|
|
41
|
+
"@types/eslint": "^8.56.11",
|
|
42
|
+
"@types/node": "^20.14.2"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"testit-js-commons": "3.7.5"
|
|
46
|
+
},
|
|
47
|
+
"files": [
|
|
48
|
+
"dist"
|
|
49
|
+
]
|
|
50
|
+
}
|