Skip to content

Commit 946b5c2

Browse files
netkardamShelex
authored andcommitted
add the support of reran mid-test due to a cy.visit
1 parent 9ab5e4e commit 946b5c2

File tree

4 files changed

+198
-51
lines changed

4 files changed

+198
-51
lines changed

eslint.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export default defineConfig([
3232
Cypress: true
3333
},
3434

35-
ecmaVersion: 2018,
35+
ecmaVersion: 2022,
3636
sourceType: 'module'
3737
},
3838

reporter/index.js

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
require('./commands');
22
const {
3-
clearAllureHookStepsFromTests,
43
setTestIdToScreenshot,
54
reorderAllureHooks,
6-
ALLURE_AFTER_HOOK,
7-
ALLURE_AFTER_EACH_HOOK
5+
buildPendingResults,
6+
loadPendingResults,
7+
clearAllureHookStepsFromTests,
8+
clearAllureHookStepsFromHook,
9+
ALLURE_HOOK_NAME
810
} = require('./patching.js');
911

1012
const {
@@ -80,21 +82,20 @@ const invokeResultsWriter = (allure, isGlobal) => {
8082
}
8183
try {
8284
clearAllureHookStepsFromTests(
83-
allure &&
84-
allure.reporter &&
85-
allure.reporter.runtime &&
86-
allure.reporter.runtime.config &&
87-
allure.reporter.runtime.config.writer &&
88-
allure.reporter.runtime.config.writer.tests,
85+
allure.reporter.runtime.config.writer.tests,
8986
config.logAllureHooksEnabled()
9087
);
88+
9189
return cy
9290
.task(
9391
'writeAllureResults',
9492
{
95-
results: allure.reporter.runtime.config,
93+
pendingResults: buildPendingResults({
94+
currentSpec:
95+
Cypress.spec.relative || Cypress.spec.absolute,
96+
allure
97+
}),
9698
files: allure.reporter.files || [],
97-
mapping: allure.reporter.mochaIdToAllure,
9899
clearSkipped: config.clearSkipped(),
99100
isGlobal,
100101
defineHistoryId: allure.reporter.defineHistoryId
@@ -110,6 +111,17 @@ const invokeResultsWriter = (allure, isGlobal) => {
110111
}
111112
};
112113

114+
const skipAlreadyRunTest = (test) => {
115+
if (test && test._ALREADY_RAN) {
116+
if (!(test.id in Cypress.Allure.reporter.mochaIdToAllure)) {
117+
test['_ALLURE_RUN'] = true;
118+
return false;
119+
}
120+
return !test._ALLURE_RUN;
121+
}
122+
return false;
123+
};
124+
113125
class CypressAllureReporter {
114126
constructor() {
115127
logger.allure(
@@ -157,13 +169,22 @@ class CypressAllureReporter {
157169
this.reporter.endSuite(isGlobal);
158170
})
159171
.on(EVENT_TEST_BEGIN, (test) => {
172+
if (skipAlreadyRunTest(test)) {
173+
return;
174+
}
160175
onTestBegin(test);
161176
})
162177
.on(EVENT_TEST_FAIL, (test, err) => {
178+
if (skipAlreadyRunTest(test)) {
179+
return;
180+
}
163181
onTestFail(test, err);
164182
})
165183
.on(EVENT_TEST_PASS, (test) => {
166184
logger.mocha(`EVENT_TEST_PASS: %s %O`, test.title, test);
185+
if (skipAlreadyRunTest(test)) {
186+
return;
187+
}
167188
this.reporter.passTestCase(test);
168189
})
169190
.on(EVENT_TEST_RETRY, (test) => {
@@ -173,9 +194,15 @@ class CypressAllureReporter {
173194
})
174195
.on(EVENT_TEST_PENDING, (test) => {
175196
logger.mocha(`EVENT_TEST_PENDING: %s %O`, test.title, test);
197+
if (skipAlreadyRunTest(test)) {
198+
return;
199+
}
176200
this.reporter.pendingTestCase(test);
177201
})
178202
.on(EVENT_TEST_END, (test) => {
203+
if (skipAlreadyRunTest(test)) {
204+
return;
205+
}
179206
onTestEnd(test);
180207
})
181208
.on(EVENT_HOOK_BEGIN, (hook) => {
@@ -184,6 +211,11 @@ class CypressAllureReporter {
184211
})
185212
.on(EVENT_HOOK_END, (hook) => {
186213
logger.mocha(`EVENT_HOOK_END: %s %O`, hook.title, hook);
214+
clearAllureHookStepsFromHook({
215+
hook,
216+
reporter: this.reporter,
217+
allureLogHooks: config.logAllureHooksEnabled()
218+
});
187219
this.reporter.endHook(hook);
188220
});
189221

@@ -298,13 +330,11 @@ if (!Cypress.Allure) {
298330
Cypress.Screenshot.defaults({
299331
onAfterScreenshot(_, details) {
300332
logger.cy(`onAfterScreenshot: %O`, details);
301-
setTestIdToScreenshot(
302-
config.allureEnabled(),
303-
Cypress.Allure &&
304-
Cypress.Allure.reporter &&
305-
Cypress.Allure.reporter.mochaIdToAllure,
333+
setTestIdToScreenshot({
334+
allureEnabled: config.allureEnabled(),
335+
allure: Cypress.Allure,
306336
details
307-
);
337+
});
308338
if (
309339
config.allureEnabled() &&
310340
!shouldUseAfterSpec(Cypress.config()) &&
@@ -384,12 +414,19 @@ const attachVideo = (reporter, test, status) => {
384414
};
385415

386416
if (config.allureEnabled()) {
387-
afterEach(ALLURE_AFTER_EACH_HOOK, function () {
417+
before(ALLURE_HOOK_NAME['before'], () => {
418+
logger.allure('########### before all ################');
419+
cy.task('getPendingAllureResults', undefined, {
420+
log: config.logAllureHooksEnabled()
421+
}).then(loadPendingResults);
422+
});
423+
424+
afterEach(ALLURE_HOOK_NAME['afterEach'], () => {
388425
logger.allure('########### after each ################');
389426
cy.then(() => invokeResultsWriter(Cypress.Allure, false));
390427
});
391428

392-
after(ALLURE_AFTER_HOOK, function () {
429+
after(ALLURE_HOOK_NAME['after'], () => {
393430
logger.allure('########### after all ################');
394431
cy.then(() => {
395432
Cypress.Allure.reporter.prepareAllureReport(

reporter/patching.js

Lines changed: 121 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,41 @@
11
const logger = require('./debug');
22

3-
const ALLURE_AFTER_HOOK = '__allure_after_hook__';
4-
const ALLURE_AFTER_EACH_HOOK = '__allure_after_each_hook__';
5-
6-
const isAllureAfterHook = (nameOrFn) => nameOrFn.includes(ALLURE_AFTER_HOOK);
3+
const ALLURE_HOOK_NAME = {
4+
after: '__allure_after_hook__',
5+
afterEach: '__allure_after_each_hook__',
6+
before: '__allure_before_hook__',
7+
beforeEach: '__allure_before_each_hook__'
8+
};
79

8-
const isAllureAfterEachHook = (nameOrFn) =>
9-
nameOrFn.includes(ALLURE_AFTER_EACH_HOOK);
10+
/**
11+
* isAllureSpecificHook
12+
* @param {string} hookName
13+
* @param {Array<String>} type - can be after/afterEach/before/beforeEach
14+
* @return true/false
15+
*/
16+
const isAllureSpecificHook = (hookName, ...type) => {
17+
if (!hookName) {
18+
return false;
19+
}
20+
let keys = type.flat(Infinity);
21+
if (keys.length === 0) {
22+
keys = Object.keys(ALLURE_HOOK_NAME);
23+
}
24+
keys = keys.filter((key) => key in ALLURE_HOOK_NAME);
25+
return keys.some((key) => hookName.includes(ALLURE_HOOK_NAME[key]));
26+
};
1027

11-
const isAllureHook = (nameOrFn) =>
12-
isAllureAfterHook(nameOrFn) || isAllureAfterEachHook(nameOrFn);
28+
const isAllureHook = (hookName) => isAllureSpecificHook(hookName);
1329

1430
const reorderAllureHooksArray = (hooksArray) => {
1531
let commonHooks = hooksArray.filter((hook) => !isAllureHook(hook.title));
16-
let allureHooks = hooksArray.filter((hook) => isAllureHook(hook.title));
17-
return [...commonHooks, ...allureHooks];
32+
let allureBeforeHooks = hooksArray.filter((hook) =>
33+
isAllureSpecificHook(hook.title, 'before', 'beforeEach')
34+
);
35+
let allureAfterHooks = hooksArray.filter((hook) =>
36+
isAllureSpecificHook(hook.title, 'after', 'afterEach')
37+
);
38+
return [...allureBeforeHooks, ...commonHooks, ...allureAfterHooks];
1839
};
1940

2041
const reorderAllureHooksGeneric = (
@@ -41,11 +62,10 @@ const reorderAllureHooksGeneric = (
4162
}
4263
};
4364

44-
const clearAllureHookSteps = (test, allureLogHooks = false) => {
65+
const clearTestAllureHookSteps = (test, allureLogHooks = false) => {
4566
if (!(test && test.steps && test.steps.length)) {
4667
return test;
4768
}
48-
4969
test.steps = test.steps.reduce((steps, step) => {
5070
if (
5171
isAllureHook(step.name) &&
@@ -68,26 +88,31 @@ const clearAllureHookSteps = (test, allureLogHooks = false) => {
6888
const clearAllureHookStepsFromTests = (tests, allureLogHooks = false) => {
6989
if (tests) {
7090
tests.forEach((test) => {
71-
clearAllureHookSteps(test, allureLogHooks);
91+
clearTestAllureHookSteps(test, allureLogHooks);
7292
});
7393
}
7494
};
7595

76-
const reorderAllureAfterHooks = (suite) => {
96+
const reorderAllureAfterAllHooks = (suite) => {
7797
reorderAllureHooksGeneric(suite, 'afterAll');
7898
};
7999

80100
const reorderAllureAfterEachHooks = (suite) => {
81101
reorderAllureHooksGeneric(suite, 'afterEach');
82102
};
83103

104+
const reorderAllureBeforeAllHooks = (suite) => {
105+
reorderAllureHooksGeneric(suite, 'beforeAll');
106+
};
107+
84108
const reorderAllureGlobalHooks = (suite) => {
85109
reorderAllureHooksGeneric(suite, 'hooks', '');
86110
};
87111

88112
const reorderAllureHooks = (suite) => {
113+
reorderAllureBeforeAllHooks(suite);
89114
reorderAllureAfterEachHooks(suite);
90-
reorderAllureAfterHooks(suite);
115+
reorderAllureAfterAllHooks(suite);
91116
reorderAllureGlobalHooks(suite);
92117
};
93118

@@ -110,11 +135,12 @@ const isLastRootHook = () => {
110135
return lastHook && lastHook.hookId === currentRunnable.hookId;
111136
};
112137

113-
const setTestIdToScreenshot = (allureEnabled, mochaIdToAllure, details) => {
114-
if (allureEnabled) {
138+
const setTestIdToScreenshot = ({ allureEnabled, allure, details }) => {
139+
if (allureEnabled && allure && allure.reporter) {
115140
let currentTest = cy.state('test');
141+
let { mochaIdToAllure } = allure.reporter;
116142
if (details && currentTest && mochaIdToAllure) {
117-
const testIds = mochaIdToAllure[currentTest && currentTest.id];
143+
const testIds = mochaIdToAllure[currentTest.id];
118144
if (testIds) {
119145
details['testId'] = currentTest.id;
120146
let testId = testIds.at(-1);
@@ -127,16 +153,84 @@ const setTestIdToScreenshot = (allureEnabled, mochaIdToAllure, details) => {
127153
}
128154
};
129155

156+
const buildPendingResults = ({ currentSpec, allure }) => {
157+
return {
158+
currentSpec: currentSpec,
159+
allureMapping: allure.reporter.mochaIdToAllure,
160+
allureResults: allure.reporter.runtime.config,
161+
allureResultContainer: allure.reporter.suites.map(
162+
(suite) => suite.testResultContainer
163+
)
164+
};
165+
};
166+
167+
const clearAllureHookStepsFromHook = ({
168+
hook,
169+
reporter,
170+
allureLogHooks = false
171+
}) => {
172+
if (!hook || !reporter) {
173+
return;
174+
}
175+
let { currentHook } = reporter;
176+
if (currentHook && !allureLogHooks && isAllureHook(hook.title)) {
177+
// remove allure hook steps so hook will not be kept in the report
178+
currentHook.info && (currentHook.info['steps'] = []);
179+
currentHook.stepResult && (currentHook.stepResult['steps'] = []);
180+
}
181+
};
182+
183+
const loadPendingResults = ({
184+
currentSpec,
185+
allureResults,
186+
allureMapping,
187+
allureResultContainer
188+
}) => {
189+
if (!currentSpec) {
190+
return;
191+
}
192+
let currentRunningSpec = Cypress.spec.relative || Cypress.spec.absolute;
193+
if (currentRunningSpec === currentSpec) {
194+
if (
195+
allureMapping &&
196+
Object.keys(Cypress.Allure.reporter.mochaIdToAllure || {})
197+
.length === 0
198+
) {
199+
Cypress.Allure.reporter.mochaIdToAllure = allureMapping;
200+
}
201+
if (allureResults && allureResults.writer) {
202+
Object.keys(allureResults.writer).forEach((key) => {
203+
Cypress.Allure.reporter.runtime.config.writer[key] =
204+
allureResults.writer[key];
205+
});
206+
}
207+
if (allureResultContainer) {
208+
Cypress.Allure.reporter.runtime.config.writer['groups'].push(
209+
...allureResultContainer
210+
);
211+
}
212+
} else {
213+
cy.task(
214+
'savePendingAllureResults',
215+
{},
216+
{
217+
log: config.logAllureHooksEnabled()
218+
}
219+
).then((pendingResults) => {
220+
logger.allure(
221+
'########### Reinit pendingResults ################ %O',
222+
pendingResults
223+
);
224+
});
225+
}
226+
};
130227
// Export everything
131228
module.exports = {
132-
ALLURE_AFTER_HOOK,
133-
ALLURE_AFTER_EACH_HOOK,
134-
isAllureHook,
135-
clearAllureHookStepsFromTests,
136-
reorderAllureAfterHooks,
137-
reorderAllureAfterEachHooks,
138-
reorderAllureGlobalHooks,
229+
ALLURE_HOOK_NAME,
139230
reorderAllureHooks,
140-
isLastRootHook,
141-
setTestIdToScreenshot
231+
setTestIdToScreenshot,
232+
buildPendingResults,
233+
loadPendingResults,
234+
clearAllureHookStepsFromTests,
235+
clearAllureHookStepsFromHook
142236
};

0 commit comments

Comments
 (0)