cucumber-protractor
Version:
POM CukeTractor - Bootstrap your cucumber tests with cucumber, protractor and a structured way of creating page objects and component objects
185 lines (156 loc) • 5.55 kB
JavaScript
const fs = require('fs');
const path = require('path');
const { argv } = require('yargs');
const Table = require('cli-table');
require('colors');
const os = require('os');
// eslint-disable-next-line
const confFile = argv.confFile || process.env.confFile || 'conf.js';
const { pomConfig } = require(path.resolve(confFile));
const { spawn } = require('child_process');
const cucumberHtmlReporter = require('cucumber-html-reporter');
const log = (...args) => {
console.log(...args);
};
log('Brm brm... off we go!');
const rmDir = function rmDir(dir, rmSelf) {
let files;
const isSelf = (rmSelf === undefined) ? true : rmSelf;
const directory = dir;
try {
files = fs.readdirSync(directory);
} catch (e) {
log('Directory not exist.');
return;
}
if (files.length > 0) {
files.forEach((x) => {
const newPath = path.join(directory, x);
if (fs.statSync(newPath).isDirectory()) {
rmDir(newPath);
} else {
fs.unlinkSync(newPath);
}
});
}
if (isSelf) {
// check if user want to delete the directory ir just the files in this directory
fs.rmdirSync(directory);
}
};
const outputPath = path.join(process.cwd(), pomConfig.outputPath);
if (fs.existsSync(outputPath)) {
rmDir(outputPath);
}
if (!fs.existsSync(outputPath)) {
fs.mkdirSync(outputPath);
}
const logPath = path.join(outputPath, 'test-result.log');
const logStream = fs.createWriteStream(logPath);
const cmd = path.join('node_modules', '.bin', `protractor${os.type().toLowerCase().includes('windows') ? '.cmd' : ''}`);
const args = [confFile];
const firstArg = process.argv && process.argv[2];
const tags = firstArg && firstArg.indexOf('--') !== 0 ? firstArg : null;
const spawnedProcess = spawn(cmd, args, {
env: Object.assign({}, process.env, {
cukeTags: (tags || argv.tags || '').replace(',', ' or '),
confFile,
showStepDefinitionUsage: process.env.showStepDefinitionUsage || argv.showStepDefinitionUsage || '',
}),
});
const cucumberHtmlReporterConfig = Object.assign({
theme: 'bootstrap',
jsonDir: outputPath,
output: path.join(outputPath, 'cucumberReport.html'),
reportSuiteAsScenarios: true,
launchReport: false,
}, pomConfig.cucumberHtmlReporterConfig);
const printCukeErrors = (el, step) => {
const red = '\x1b[31m%s\x1b[0m';
const yellow = '\x1b[33m%s\x1b[0m';
if (step.result.error_message) {
log(red, `\n------------------ Scenario Error --------------- ${el.name}`);
log(yellow, `Tags: ${el.tags.map((tag) => tag.name).join(', ')}`);
log(yellow, `Step: ${step.keyword}${step.name}`);
log(yellow, `Location: ${step.match.location}`);
log(yellow, `Error message: ${step.result.error_message}`);
} else if (step.result.status === 'undefined') {
log(red, `\n------------------ Scenario Undefined Step Definition --------------- ${el.name}`);
log(yellow, `Tags: ${el.tags.map((tag) => tag.name).join(', ')}`);
log(yellow, `Step: ${step.keyword}${step.name}`);
}
if (step.result.error_message || step.result.status === 'undefined') {
const screenshotStep = el.steps.find((stp) =>
stp.keyword === 'After' &&
stp.match &&
stp.match.location &&
stp.match.location.includes('attachScreenshotAfter'));
const screenshotFilePath = screenshotStep &&
screenshotStep.embeddings &&
screenshotStep.embeddings
.find((embed) =>
embed.data && embed.data.includes('ScreenshotFilePath'));
log('-----SCREENSHOT - hold cmd (on mac) and click .png below if using iterm ----');
log(screenshotFilePath ? screenshotFilePath.data : '');
log('---------');
}
};
const loopThroughReport = () => new Promise((resolve, reject) => {
try {
// eslint-disable-next-line
const features = JSON.parse(fs.readFileSync(`${cucumberHtmlReporterConfig.output}.json`, 'utf8'));
const elements = features.reduce((arr, scenario) => arr.concat(scenario.elements), []);
let successCount = 0;
let failureCount = 0;
let totalCount = 0;
elements.forEach((el) => {
let scenarioStatus = 'passed';
el.steps.forEach((step) => {
const { status } = step.result;
const { keyword } = step;
if (!keyword.includes('After') && !keyword.includes('Before')) {
if (status === 'failed' || scenarioStatus !== 'failed') {
scenarioStatus = status;
}
}
printCukeErrors(el, step);
return step.result.status;
});
if (scenarioStatus === 'passed') {
successCount += 1;
} else {
failureCount += 1;
}
totalCount += 1;
});
resolve({ successCount, failureCount, totalCount });
} catch (e) {
reject(e);
}
});
const output = (data) => {
log(data.toString());
// eslint-disable-next-line
logStream.write(data.toString().replace(/\x1b\[\d\dm/g, ''));
};
spawnedProcess.stdout.on('data', output);
spawnedProcess.stderr.on('data', output);
spawnedProcess.on('exit', () => {
logStream.end();
cucumberHtmlReporter.generate(cucumberHtmlReporterConfig);
loopThroughReport()
.then(({ successCount, failureCount, totalCount }) => {
const table = new Table({
head: [
'Total Scenarios'.white,
'Successful'.green,
'Failures'.red,
],
});
table.push([totalCount, `${successCount}`.green, `${failureCount}`.red]);
log('');
log(table.toString());
process.exitCode = totalCount === successCount ? 0 : 1;
});
});