Skip to content

Commit

Permalink
fix: write results after each test and sanitize when finished, address
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleksandr Shevtsov authored and Oleksandr Shevtsov committed Apr 4, 2023
1 parent d0678ab commit b50035e
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 30 deletions.
63 changes: 36 additions & 27 deletions reporter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,37 @@ const config = {
}
};

const invokeResultsWriter = (allure, isGlobal) => {
if (!config || !config.allureEnabled()) {
return;
}
try {
cy.now(
'task',
'writeAllureResults',
{
results: allure.reporter.runtime.config,
files: allure.reporter.files,
mapping: allure.reporter.mochaIdToAllure,
clearSkipped: config.clearSkipped(),
isGlobal
},
{ log: false }
)
// eslint-disable-next-line no-console
.catch((e) =>
logger.allure(
`failed to execute task to write allure results: %O`,
e
)
);
logger.allure(`writing allure results`);
} catch (e) {
// happens when cy.task could not be executed due to fired outside of it
logger.allure(`failed to write allure results: %O`, e);
}
};

class CypressAllureReporter {
constructor() {
logger.allure(
Expand Down Expand Up @@ -112,33 +143,7 @@ class CypressAllureReporter {
*/
const isGlobal = suite.title === '';
this.reporter.endSuite(isGlobal);

if (config && config.allureEnabled() && isGlobal) {
try {
cy.now(
'task',
'writeAllureResults',
{
results: this.reporter.runtime.config,
files: this.reporter.files,
mapping: this.reporter.mochaIdToAllure,
clearSkipped: config.clearSkipped()
},
{ log: false }
)
// eslint-disable-next-line no-console
.catch((e) =>
logger.allure(
`failed to execute task to write allure results: %O`,
e
)
);
logger.allure(`writing allure results`);
} catch (e) {
// happens when cy.task could not be executed due to fired outside of it
logger.allure(`failed to write allure results: %O`, e);
}
}
isGlobal && invokeResultsWriter(this, isGlobal);
})
.on(EVENT_TEST_BEGIN, (test) => {
onTestBegin(test);
Expand Down Expand Up @@ -240,6 +245,10 @@ class CypressAllureReporter {
}
}

Cypress.on('test:after:run', () => {
invokeResultsWriter(Cypress.Allure, false);
});

// when different hosts used in same test
// Cypress opens new host URL and loads index.js
// so if we already have Allure data we should not replace it with new instance
Expand Down
11 changes: 9 additions & 2 deletions writer.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@ function allureWriter(on, config) {
}

on('task', {
writeAllureResults: ({ results, files, mapping, clearSkipped }) => {
writeAllureResults: ({
results,
files,
mapping,
clearSkipped,
isGlobal
}) => {
const { resultsDir: relativeResultsDir, writer } = results;

const resultsDir = config.projectRoot
Expand All @@ -69,7 +75,8 @@ function allureWriter(on, config) {
files,
clearSkipped,
writer,
allureMapping
allureMapping,
isGlobal
});

return null;
Expand Down
113 changes: 113 additions & 0 deletions writer/handleMultiDomain.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
const fs = require('fs');
const path = require('path');
const logger = require('../reporter/debug');

const readAllureResults = (folder) => {
try {
logger.writer('parsing existing allure results');
if (!fs.existsSync(folder)) {
return;
}

const files = fs.readdirSync(folder);

const fileMap = files.map((filePath) => {
const getType = (file) => {
const types = {
suite: (f) =>
f.includes('-container') && f.endsWith('.json'),
test: (f) => f.includes('-result') && f.endsWith('.json')
};
return Object.keys(types).find((type) => types[type](file));
};

const resultType = getType(filePath);

const fileContent =
resultType === 'suite' || resultType === 'test'
? JSON.parse(
fs.readFileSync(path.join(folder, filePath), {
encoding: 'utf-8'
})
)
: filePath;

return fileContent;
});

return fileMap;
} catch (e) {
return e;
}
};

const sanitizeSuites = (folder, files, isGlobal) => {
const suites = files.filter((file) => file.children);

for (const suite of suites) {
logger.writer('checking suite %s children', suite.uuid);
for (const childID of suite.children) {
const child = files.find((file) => file.uuid === childID);

if (child.steps.length) {
logger.writer('child %s %s has steps', child.uuid, child.name);
continue;
}

const duplicates = files.filter(
(file) =>
file.historyId === child.historyId &&
file.uuid !== child.uuid &&
file.steps.length
);

const earliestDuplicate = duplicates
.sort((a, b) => a.start - b.start)
.shift();

if (!earliestDuplicate) {
logger.writer('no duplicate executions found: %s', child.uuid);
continue;
}

const newChild = `${earliestDuplicate.uuid}-result.json`;
const originalChild = `${childID}-result.json`;

fs.existsSync(path.join(folder, originalChild)) &&
fs.unlinkSync(path.join(folder, originalChild));

fs.renameSync(
path.join(folder, newChild),
path.join(folder, originalChild)
);
}

const suitePath = `${suite.uuid}-container.json`;
fs.writeFileSync(path.join(folder, suitePath), JSON.stringify(suite));
}

if (!isGlobal) {
return;
}

logger.writer('suite run finished, checking tests');

const tests = files.filter((file) => !file.children && file.historyId);

for (const test of tests) {
const isAttached = suites.find((suite) =>
suite.children.includes(test.uuid)
);
if (!isAttached) {
const fileName = `${test.uuid}-result.json`;
const filePath = path.join(folder, fileName);
logger.writer('found orphan test, removing %s', fileName);
fs.existsSync(filePath) && fs.unlinkSync(filePath);
}
}
};

module.exports = {
readAllureResults,
sanitizeSuites
};
10 changes: 9 additions & 1 deletion writer/results.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const logger = require('../reporter/debug');
const { overwriteTestNameMaybe } = require('./customTestName');
const { clearEmptyHookSteps } = require('./clearEmptyHookSteps');
const { writeInfoFile, writeEnvProperties } = require('./infoFiles');
const { readAllureResults, sanitizeSuites } = require('./handleMultiDomain');

const writeAttachmentFiles = ({ files, resultsDir, tests }) => {
if (!files || !files.length) {
Expand Down Expand Up @@ -142,6 +143,11 @@ const writeAttachments = ({ attachments, resultsDir }) => {
}
};

const handleAfterTestWrites = ({ resultsDir, isGlobal }) => {
const parsed = readAllureResults(resultsDir);
return sanitizeSuites(resultsDir, parsed, isGlobal);
};

const catchError = (fn, ...args) => {
try {
fn(...args);
Expand All @@ -156,7 +162,8 @@ const writeResultFiles = ({
files,
clearSkipped,
writer,
allureMapping
allureMapping,
isGlobal
}) => {
!fs.existsSync(resultsDir) && fs.mkdirSync(resultsDir, { recursive: true });

Expand All @@ -169,6 +176,7 @@ const writeResultFiles = ({
catchError(writeSuites, { groups, resultsDir, tests, clearSkipped });
catchError(writeTests, { tests, resultsDir, clearSkipped, allureMapping });
catchError(writeAttachments, { attachments, resultsDir });
catchError(handleAfterTestWrites, { resultsDir, isGlobal });

const allureResultsPath = (file) => path.join(resultsDir, file);

Expand Down

0 comments on commit b50035e

Please sign in to comment.