cypress-qase-reporter 3.1.0 → 3.1.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/changelog.md CHANGED
@@ -1,3 +1,9 @@
1
+ # cypress-qase-reporter@3.1.1
2
+
3
+ ## What's new
4
+
5
+ - Fixed an issue where the reporter was not reporting skipped tests due to failing beforeEach hooks.
6
+
1
7
  # cypress-qase-reporter@3.1.0
2
8
 
3
9
  ## What's new
@@ -35,6 +35,12 @@ export declare class CypressQaseReporter extends reporters.Base {
35
35
  */
36
36
  private reporter;
37
37
  private testBeginTime;
38
+ /**
39
+ * Set to track processed tests to identify skipped tests when beforeEach fails
40
+ * @type {Set<string>}
41
+ * @private
42
+ */
43
+ private processedTests;
38
44
  /**
39
45
  * @param {Runner} runner
40
46
  * @param {CypressQaseOptionsType} options
@@ -46,6 +52,38 @@ export declare class CypressQaseReporter extends reporters.Base {
46
52
  * @private
47
53
  */
48
54
  private addRunnerListeners;
55
+ /**
56
+ * Generate a unique identifier for a test
57
+ * @param {Test} test
58
+ * @returns {string}
59
+ * @private
60
+ */
61
+ private getTestIdentifier;
62
+ /**
63
+ * Mark a test as processed
64
+ * @param {Test} test
65
+ * @private
66
+ */
67
+ private markTestAsProcessed;
68
+ /**
69
+ * Check if a test was processed
70
+ * @param {Test} test
71
+ * @returns {boolean}
72
+ * @private
73
+ */
74
+ private isTestProcessed;
75
+ /**
76
+ * Handle skipped tests in a suite when beforeEach hook fails
77
+ * @param {Suite} suite
78
+ * @private
79
+ */
80
+ private handleSkippedTestsInSuite;
81
+ /**
82
+ * Add a test result for a skipped test (due to beforeEach failure)
83
+ * @param {Test} test
84
+ * @private
85
+ */
86
+ private addSkippedTestResult;
49
87
  /**
50
88
  * @param {Test} test
51
89
  * @private
package/dist/reporter.js CHANGED
@@ -14,7 +14,7 @@ const manager_1 = require("./metadata/manager");
14
14
  const fileSearcher_1 = require("./fileSearcher");
15
15
  const tagParser_1 = require("./utils/tagParser");
16
16
  const resultsManager_1 = require("./metadata/resultsManager");
17
- const { EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING, EVENT_RUN_END, EVENT_TEST_BEGIN, } = mocha_1.Runner.constants;
17
+ const { EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING, EVENT_RUN_END, EVENT_TEST_BEGIN, EVENT_SUITE_END } = mocha_1.Runner.constants;
18
18
  /**
19
19
  * @class CypressQaseReporter
20
20
  * @extends reporters.Base
@@ -57,6 +57,12 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
57
57
  */
58
58
  reporter;
59
59
  testBeginTime = Date.now();
60
+ /**
61
+ * Set to track processed tests to identify skipped tests when beforeEach fails
62
+ * @type {Set<string>}
63
+ * @private
64
+ */
65
+ processedTests = new Set();
60
66
  // private options: Omit<(FrameworkOptionsType<'cypress', ReporterOptionsType> & ConfigType & ReporterOptionsType & NonNullable<unknown>) | (null & ReporterOptionsType & NonNullable<unknown>), 'framework'>;
61
67
  /**
62
68
  * @param {Runner} runner
@@ -84,26 +90,161 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
84
90
  * @private
85
91
  */
86
92
  addRunnerListeners(runner) {
87
- runner.on(EVENT_TEST_PASS, (test) => this.addTestResult(test));
88
- runner.on(EVENT_TEST_PENDING, (test) => this.addTestResult(test));
89
- runner.on(EVENT_TEST_FAIL, (test) => this.addTestResult(test));
93
+ runner.on(EVENT_TEST_PASS, (test) => {
94
+ this.markTestAsProcessed(test);
95
+ this.addTestResult(test);
96
+ });
97
+ runner.on(EVENT_TEST_PENDING, (test) => {
98
+ this.markTestAsProcessed(test);
99
+ this.addTestResult(test);
100
+ });
101
+ runner.on(EVENT_TEST_FAIL, (test) => {
102
+ this.markTestAsProcessed(test);
103
+ this.addTestResult(test);
104
+ });
90
105
  runner.on(EVENT_TEST_BEGIN, () => {
91
106
  this.testBeginTime = Date.now();
92
107
  manager_1.MetadataManager.clear();
93
108
  });
109
+ runner.on(EVENT_SUITE_END, (suite) => {
110
+ this.handleSkippedTestsInSuite(suite);
111
+ });
94
112
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
95
113
  runner.once(EVENT_RUN_END, () => {
96
114
  const results = this.reporter.getResults();
97
115
  resultsManager_1.ResultsManager.setResults(results);
98
- // spawnSync('node', [`${__dirname}/child.js`], {
99
- // stdio: 'inherit',
100
- // env: Object.assign(process.env, {
101
- // reporterConfig: JSON.stringify(this.options),
102
- // results: JSON.stringify(results),
103
- // }),
104
- // });
116
+ this.processedTests.clear();
105
117
  });
106
118
  }
119
+ /**
120
+ * Generate a unique identifier for a test
121
+ * @param {Test} test
122
+ * @returns {string}
123
+ * @private
124
+ */
125
+ getTestIdentifier(test) {
126
+ const file = test.parent ? this.getFile(test.parent) ?? '' : '';
127
+ const suitePath = test.parent ? test.parent.titlePath().join(' > ') : '';
128
+ let testTitle = test.fullTitle();
129
+ // Remove "before each" hook prefix and quotes if present (can be anywhere in the string)
130
+ testTitle = testTitle.replace(/"before each" hook for "/g, '');
131
+ // Remove trailing quote if present
132
+ if (testTitle.endsWith('"')) {
133
+ testTitle = testTitle.slice(0, -1);
134
+ }
135
+ return `${file}::${suitePath}::${testTitle}`;
136
+ }
137
+ /**
138
+ * Mark a test as processed
139
+ * @param {Test} test
140
+ * @private
141
+ */
142
+ markTestAsProcessed(test) {
143
+ const identifier = this.getTestIdentifier(test);
144
+ this.processedTests.add(identifier);
145
+ }
146
+ /**
147
+ * Check if a test was processed
148
+ * @param {Test} test
149
+ * @returns {boolean}
150
+ * @private
151
+ */
152
+ isTestProcessed(test) {
153
+ const identifier = this.getTestIdentifier(test);
154
+ return this.processedTests.has(identifier);
155
+ }
156
+ /**
157
+ * Handle skipped tests in a suite when beforeEach hook fails
158
+ * @param {Suite} suite
159
+ * @private
160
+ */
161
+ handleSkippedTestsInSuite(suite) {
162
+ // Get tests only from the current suite (not nested suites, they will be processed separately)
163
+ const tests = suite.tests ?? [];
164
+ // Find tests that were not processed (skipped due to beforeEach failure)
165
+ for (const test of tests) {
166
+ // Skip if test was already processed (e.g., first test that got EVENT_TEST_FAIL)
167
+ if (!this.isTestProcessed(test)) {
168
+ // Test was skipped due to beforeEach failure, report it as skipped
169
+ this.addSkippedTestResult(test);
170
+ }
171
+ }
172
+ }
173
+ /**
174
+ * Add a test result for a skipped test (due to beforeEach failure)
175
+ * @param {Test} test
176
+ * @private
177
+ */
178
+ addSkippedTestResult(test) {
179
+ const end_time = Date.now();
180
+ const duration = 0; // Skipped tests have no duration
181
+ const start_time = this.testBeginTime || Date.now();
182
+ const ids = CypressQaseReporter.getCaseId(test.title);
183
+ const testFileName = this.getTestFileName(test);
184
+ const files = this.screenshotsFolder ?
185
+ fileSearcher_1.FileSearcher.findFilesBeforeTime(this.screenshotsFolder, testFileName, new Date(start_time))
186
+ : [];
187
+ const attachments = files.map((file) => ({
188
+ content: '',
189
+ id: (0, uuid_1.v4)(),
190
+ mime_type: 'image/png',
191
+ size: 0,
192
+ file_name: path_1.default.basename(file),
193
+ file_path: file,
194
+ }));
195
+ let relations = {};
196
+ if (test.parent !== undefined) {
197
+ const data = [];
198
+ for (const suite of test.parent.titlePath()) {
199
+ data.push({
200
+ title: suite,
201
+ public_id: null,
202
+ });
203
+ }
204
+ relations = {
205
+ suite: {
206
+ data: data,
207
+ },
208
+ };
209
+ }
210
+ // For skipped tests, we don't have metadata since the test never ran
211
+ // But we can still check for cucumber tags if the test has a parent with a file
212
+ if (test.parent) {
213
+ const file = this.getFile(test.parent);
214
+ if (file) {
215
+ const tags = (0, tagParser_1.extractTags)(file, test.title);
216
+ ids.push(...this.extractQaseIds(tags));
217
+ }
218
+ }
219
+ const result = {
220
+ attachments: attachments,
221
+ author: null,
222
+ fields: {},
223
+ message: null,
224
+ muted: false,
225
+ params: {},
226
+ group_params: {},
227
+ relations: relations,
228
+ run_id: null,
229
+ signature: this.getSignature(test, ids, {}),
230
+ steps: [],
231
+ id: (0, uuid_1.v4)(),
232
+ execution: {
233
+ status: qase_javascript_commons_1.TestStatusEnum.skipped,
234
+ start_time: this.testBeginTime / 1000,
235
+ end_time: end_time / 1000,
236
+ duration: duration,
237
+ stacktrace: null,
238
+ thread: null,
239
+ },
240
+ testops_id: ids.length > 0 ? ids : null,
241
+ title: this.removeQaseIdsFromTitle(test.title),
242
+ preparedAttachments: [],
243
+ };
244
+ void this.reporter.addTestResult(result);
245
+ // Mark as processed to avoid duplicate reporting
246
+ this.markTestAsProcessed(test);
247
+ }
107
248
  /**
108
249
  * @param {Test} test
109
250
  * @private
@@ -113,6 +254,8 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
113
254
  const duration = end_time - this.testBeginTime;
114
255
  const metadata = manager_1.MetadataManager.getMetadata();
115
256
  if (metadata?.ignore) {
257
+ // Mark as processed even if ignored to avoid duplicate reporting
258
+ this.markTestAsProcessed(test);
116
259
  manager_1.MetadataManager.clear();
117
260
  return;
118
261
  }
@@ -198,7 +341,7 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
198
341
  steps: steps,
199
342
  id: (0, uuid_1.v4)(),
200
343
  execution: {
201
- status: (0, qase_javascript_commons_1.determineTestStatus)(test.err || null, test.state || 'failed'),
344
+ status: (0, qase_javascript_commons_1.determineTestStatus)(test.err ?? null, test.state ?? 'failed'),
202
345
  start_time: this.testBeginTime / 1000,
203
346
  end_time: end_time / 1000,
204
347
  duration: duration,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cypress-qase-reporter",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "Qase Cypress Reporter",
5
5
  "homepage": "https://github.com/qase-tms/qase-javascript",
6
6
  "sideEffects": false,
@@ -51,19 +51,19 @@
51
51
  "author": "Qase Team <support@qase.io>",
52
52
  "license": "Apache-2.0",
53
53
  "dependencies": {
54
- "qase-javascript-commons": "~2.4.5",
54
+ "qase-javascript-commons": "~2.4.13",
55
55
  "uuid": "^9.0.1"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "cypress": ">=8.0.0"
59
59
  },
60
60
  "devDependencies": {
61
- "@jest/globals": "^29.5.0",
62
- "@types/jest": "^29.5.2",
63
- "@types/mocha": "^10.0.1",
64
- "ajv": "^8.12.0",
65
- "jest": "^29.5.0",
66
- "mocha": "^10.2.0",
67
- "ts-jest": "^29.1.0"
61
+ "@jest/globals": "^29.7.0",
62
+ "@types/jest": "^29.5.14",
63
+ "@types/mocha": "^10.0.10",
64
+ "ajv": "^8.17.1",
65
+ "jest": "^29.7.0",
66
+ "mocha": "^10.8.2",
67
+ "ts-jest": "^29.4.5"
68
68
  }
69
69
  }
@@ -2,7 +2,9 @@
2
2
  "extends": "./tsconfig.json",
3
3
 
4
4
  "compilerOptions": {
5
- "noEmit": false
5
+ "noEmit": false,
6
+ "skipLibCheck": true,
7
+ "types": []
6
8
  },
7
9
 
8
10
  "include": ["./src/**/*.ts", "./src/*.js"],