@mmisty/cypress-allure-adapter
Version:
cypress allure adapter to generate allure results during tests execution (Allure TestOps compatible)
256 lines (255 loc) • 12.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleCyLogEvents = void 0;
const helper_1 = require("./helper");
const common_1 = require("../common");
const command_names_1 = require("../common/command-names");
const request_events_1 = require("./request-events");
const custom_commands_handling_1 = require("../setup/custom-commands-handling");
const group_handling_1 = require("./group-handling");
const requests_handler_1 = require("./requests-handler");
const dbg = 'cypress-allure:cy-events';
const UNCAUGHT_EXCEPTION_NAME = 'uncaught exception';
const UNCAUGHT_EXCEPTION_STATUS = 'broken';
const failedStatus = 'failed';
const passedStatus = 'passed';
const brokenStatus = 'broken';
const swapDoSyncCommand = () => {
Cypress.on('command:enqueued', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const queue = () => cy.queue;
// swap if next chainer is 'should'
// should be done for all child commands ?
const swapCmd = () => {
const custId = queue().queueables.findIndex((t, i) => { var _a; return i >= queue().index && ((_a = t.attributes) === null || _a === void 0 ? void 0 : _a.name) === 'doSyncCommand'; });
const next = custId + 1;
if (queue().queueables.length > next && ['assertion'].includes(queue().queueables[next].attributes.type)) {
(0, common_1.swapItems)(queue().queueables, custId, next);
swapCmd();
}
};
swapCmd();
});
};
const handleCyLogEvents = (runner, events, config) => {
const debug = (0, helper_1.logClient)(dbg);
const { ignoreCommands, wrapCustomCommands, allureLogCyCommands, spyOnRequests } = config;
const customCommands = [];
const groups = new group_handling_1.Groups(events);
const customCommandsHandler = new custom_commands_handling_1.CustomCommandsHandler(events, ignoreCommands, wrapCustomCommands);
const requests = [];
groups.handleGroupsEvents();
swapDoSyncCommand();
(0, request_events_1.logRequestEvents)(requests, events);
const allureAttachRequests = Cypress.env('allureAttachRequests')
? `${Cypress.env('allureAttachRequests')}` === 'true'
: false;
const allureCompactAttachmentsRequests = Cypress.env('allureCompactAttachments')
? `${Cypress.env('allureCompactAttachments')}` === 'true'
: true;
const isLogCommand = (isLog, name) => {
return isLog && !(0, command_names_1.ignoreAllCommands)(ignoreCommands).includes(name) && !Object.keys(Cypress.Allure).includes(name);
};
if (allureLogCyCommands()) {
customCommandsHandler.wrap();
// customCommandsHandler.wrapGroupedCommands();
}
// should be beforeEach (not before) to get env variable value from test config
beforeEach(`${common_1.packageLog}`, () => {
// this way can save bodies for intercepted requests
var _a;
const requestsToSpy = (_a = spyOnRequests === null || spyOnRequests === void 0 ? void 0 : spyOnRequests()) !== null && _a !== void 0 ? _a : [];
cy.allure().parameter('To access request bodies', "add environment variable: `allureAddBodiesToRequests`\n(value is requests split by comma that you wish to save, to save all set '*')");
cy.allure().parameter('To skip this message', "add environment variable `allureSkipSteps: '*\\[cypress-allure-adapter\\]*' `");
if (requestsToSpy.length > 0) {
requestsToSpy.forEach(r => {
cy.intercept(r).as('allure');
});
}
else {
// for not using step command
cy.allure().startStep('will not intercept requests to save bodies');
cy.allure().endStep();
}
requests.splice(0, requests.length);
groups.resetGroups();
});
Cypress.on('log:added', (log) => {
if (!allureLogCyCommands()) {
return;
}
(0, command_names_1.withTry)('report log:added', () => {
const logName = (0, command_names_1.logNameFn)(log);
const logMessage = log.message;
const chainerId = log.chainerId;
const end = log.end || log.ended;
const logState = log.state;
const groupStart = log.groupStart;
const cmdMessage = (0, command_names_1.stepMessage)(logName, logMessage === 'null' ? '' : logMessage);
groups.endGroupMayBe('');
if (chainerId || !end || logName === command_names_1.COMMAND_REQUEST) {
return;
}
// only synchronous logs without parent commands
if (groupStart) {
if (groups.startGroupMaybe(cmdMessage)) {
// only start when no chainer
return;
}
}
Cypress.Allure.startStep(cmdMessage);
let status = passedStatus;
if (logName === 'WARNING') {
status = brokenStatus;
}
if (logState === 'failed') {
status = failedStatus;
}
Cypress.Allure.endStep(status);
});
});
const addCommandLogs = (command) => {
if (!allureLogCyCommands()) {
return;
}
const filtered = (0, command_names_1.filterCommandLog)(command, ignoreCommands).sort((aLog, bLog) => {
var _a, _b;
const attrA = (_a = aLog === null || aLog === void 0 ? void 0 : aLog.attributes) === null || _a === void 0 ? void 0 : _a.commandLogId;
const attrB = (_b = bLog === null || bLog === void 0 ? void 0 : bLog.attributes) === null || _b === void 0 ? void 0 : _b.commandLogId;
if (!attrA || !attrB) {
return 0;
}
return attrA < attrB ? -1 : 1;
});
filtered.forEach(log => {
var _a, _b;
const attr = log.attributes;
const logName = (0, command_names_1.logNameFn)(attr);
const logErr = attr === null || attr === void 0 ? void 0 : attr.error;
const message = attr === null || attr === void 0 ? void 0 : attr.message;
const groupStart = attr === null || attr === void 0 ? void 0 : attr.groupStart;
const logMessage = (0, command_names_1.stepMessage)(logName, message === 'null' ? '' : message);
const getProps = () => {
if (attr && attr.consoleProps && typeof attr.consoleProps === 'function') {
return attr.consoleProps();
}
if (attr && attr.consoleProps && typeof attr.consoleProps !== 'function') {
return attr.consoleProps;
}
return undefined;
};
const consoleProps = getProps();
// console.log('logName', logName);
// console.log('logMessage', logMessage);
// console.log('attr');
// console.log(attr);
// console.log('consoleProps');
// console.log(consoleProps);
// console.log(groups);
groups.endGroupMayBe(logMessage);
if (groupStart) {
if (groups.startGroupMaybe(logMessage)) {
return;
}
}
Cypress.Allure.startStep(logMessage);
if (logName !== 'assert' && message && message.length > command_names_1.ARGS_TRIM_AT) {
Cypress.Allure.step('Commnad has long args...');
}
let state = ((_a = consoleProps === null || consoleProps === void 0 ? void 0 : consoleProps.error) !== null && _a !== void 0 ? _a : logErr) ? failedStatus : passedStatus;
let details = undefined;
const isIgnoreException = () => {
var _a, _b;
const ignored = Cypress.env('allureIgnoreUncaughtExceptions');
if (!ignored) {
return false;
}
const exceptions = (_a = ignored.split(',').map((x) => new RegExp(`^${x.replace(/\./g, '.').replace(/\*/g, '.*')}$`))) !== null && _a !== void 0 ? _a : [];
const err = (_b = consoleProps === null || consoleProps === void 0 ? void 0 : consoleProps.props) === null || _b === void 0 ? void 0 : _b.Error;
return (err === null || err === void 0 ? void 0 : err.message) && exceptions.some((e) => e.test(err.message));
};
if (logName.indexOf(UNCAUGHT_EXCEPTION_NAME) !== -1 && !isIgnoreException()) {
const err = (_b = consoleProps === null || consoleProps === void 0 ? void 0 : consoleProps.props) === null || _b === void 0 ? void 0 : _b.Error;
const isCommandFailed = command.state === 'failed';
// when command failed we mark uncaught exception log as error,
// in other cases it will be marked as broken
state = isCommandFailed ? failedStatus : UNCAUGHT_EXCEPTION_STATUS;
details = { message: err === null || err === void 0 ? void 0 : err.message, trace: err === null || err === void 0 ? void 0 : err.stack };
}
if (logName === 'WARNING') {
state = brokenStatus;
}
Cypress.Allure.endStep(state, details);
});
};
Cypress.on('command:start', (command) => {
events.emit('cmd:started:tech', command);
});
Cypress.on('command:failed', (command) => {
events.emit('cmd:ended:tech', command);
});
Cypress.on('command:end', (command) => {
events.emit('cmd:ended:tech', command);
});
events.on('cmd:started:tech', (command, isCustom) => {
const { message: cmdMessage } = (0, command_names_1.commandParams)(command);
groups.endGroupMayBe();
debug(`started tech: ${cmdMessage}`);
if (isCustom) {
customCommands.push(cmdMessage);
// not start when custom because cypress already
// fired event command:start
return;
}
events.emit('cmd:started', command);
});
Cypress.Allure.on('cmd:started', (command) => {
const { name, isLog, message: cmdMessage, args } = (0, command_names_1.commandParams)(command);
if (!isLogCommand(isLog, name) || !allureLogCyCommands()) {
return;
}
debug(`started: ${cmdMessage}`);
Cypress.Allure.startStep(cmdMessage);
(0, command_names_1.withTry)('report command:attachment', () => {
const requestAndLogRequests = allureAttachRequests && name === command_names_1.COMMAND_REQUEST;
if (!requestAndLogRequests && args.join(',').length > command_names_1.ARGS_TRIM_AT) {
Cypress.Allure.step('command has long args...');
}
});
});
events.on('cmd:ended:tech', (command, isCustom) => {
const { message: cmdMessage } = (0, command_names_1.commandParams)(command);
const last = customCommands[customCommands.length - 1];
groups.endGroupMayBe();
if (!isCustom) {
// will be added here for all custom or non-custom
// since cypress ends custom commands right away
addCommandLogs(command);
}
if (last && last === cmdMessage) {
customCommands.pop();
// cypress ends custom commands right away
// not end when custom started
return;
}
events.emit('cmd:ended', command, isCustom);
});
Cypress.Allure.on('cmd:ended', (command, isCustom) => {
const { name, isLog, state, message: cmdMessage } = (0, command_names_1.commandParams)(command);
const status = state;
if (!isLogCommand(isLog, name)) {
return;
}
if (name === command_names_1.COMMAND_REQUEST) {
(0, command_names_1.withTry)('report attach:requests', () => {
(0, requests_handler_1.attachRequests)(dbg, allureAttachRequests, command, { compactAttachments: allureCompactAttachmentsRequests });
});
}
if (!allureLogCyCommands()) {
return;
}
debug(`ended ${isCustom ? 'CUSTOM' : ''}: ${cmdMessage}`);
Cypress.Allure.endStep(status);
});
};
exports.handleCyLogEvents = handleCyLogEvents;