Skip to content
This repository has been archived by the owner on May 22, 2024. It is now read-only.

Commit

Permalink
[terra-functional-testing] Added FileOutputReporter reporter (#665)
Browse files Browse the repository at this point in the history
* file output reporter added

* added change log

* addressed comments

* changed the folder name for jest test for reporter

* updated the log-context

* added change log for docs

* updated the package name functionality

* lint fix

* ypdated the modulename functionality

* lint fix

* Refactored buildFileName. Added updateResultObject. Made getPackageName static.

Co-authored-by: Sireesha Nekkanti <[email protected]>
Co-authored-by: Ben Cai <[email protected]>
Co-authored-by: Ben Cai <[email protected]>
  • Loading branch information
4 people authored Jun 7, 2021
1 parent efdbd9f commit 88bd8fb
Show file tree
Hide file tree
Showing 8 changed files with 546 additions and 4 deletions.
9 changes: 6 additions & 3 deletions packages/terra-functional-testing/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# Changelog

* Fixed
* Updated waitForSeleniumHubReady to accommodate Windows users.

## Unreleased

* Added
* Added FileOutputReporter reporter that logs wdio test output to separate files based on locale, theme, and form-factor

## 1.7.0 - (June 1, 2021)

* Added
* `cloudRegion` namespace to screenshot directories - this is useful for full stack testing contexts that define a cloudRegion per test run.

* Fixed
* Updated waitForSeleniumHubReady to accommodate Windows users.

## 1.6.0 - (May 25, 2021)

* Added
Expand Down
1 change: 1 addition & 0 deletions packages/terra-functional-testing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"lodash.isstring": "^4.0.1",
"lodash.isundefined": "^3.0.1",
"lodash.pickby": "^4.6.0",
"strip-ansi": "^6.0.0",
"uuid": "^3.0.0",
"webdriverio": "^6.5.0",
"webpack-dev-server": "^3.11.0",
Expand Down
3 changes: 2 additions & 1 deletion packages/terra-functional-testing/src/config/wdio.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const VisualRegressionLauncher = require('../services/wdio-visual-regression-ser

const { AccessibilityReporter } = require('../reporters/accessibility-reporter');
const { SpecReporter, cleanResults, mergeResults } = require('../reporters/spec-reporter');
const FileOutputReporter = require('../reporters/file-output-reporter');

exports.config = {
//
Expand Down Expand Up @@ -126,7 +127,7 @@ exports.config = {
// Test reporter for stdout.
// The only one supported by default is 'dot'
// see also: https://webdriver.io/docs/dot-reporter.html
reporters: ['spec', AccessibilityReporter, SpecReporter],
reporters: ['spec', AccessibilityReporter, SpecReporter, FileOutputReporter],
//
// Options to be passed to Mocha.
// See the full list at http://mochajs.org/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
const fs = require('fs-extra');
const path = require('path');
const stripAnsi = require('strip-ansi');
const SpecReporter = require('@wdio/spec-reporter').default;
const endOfLine = require('os').EOL;
const { Logger } = require('@cerner/terra-cli');

const LOG_CONTEXT = '[terra-functional-testing:file-output-reporter]';

class FileOutputReporter extends SpecReporter {
constructor() {
super();
this.runners = [];
this.resultJsonObject = {
startDate: '',
type: 'wdio',
locale: '',
formFactor: '',
theme: '',
output: {},
endDate: '',
};
this.fileName = '';
this.setResultsDir = this.setResultsDir.bind(this);
this.hasResultsDir = this.hasResultsDir.bind(this);
this.printReport = this.printReport.bind(this);
this.getMessage = this.getMessage.bind(this);

this.setResultsDir();
this.hasResultsDir();
}

/**
* Sets results directory for the test run. Uses the wdio reporterOptions.outputDir if set, otherwise
* it outputs to tests/wdio/reports.
* @return null;
*/
setResultsDir() {
this.resultsDir = path.join(process.cwd(), 'tests', 'wdio', 'reports');
}

/**
* Check and create reports dir if doesn't exist
* @return null
*/
hasResultsDir() {
if (!fs.existsSync(this.resultsDir)) {
fs.mkdirSync(this.resultsDir, { recursive: true }, (err) => {
if (err) {
Logger.error(err.message, { context: LOG_CONTEXT });
}
});
}
}

/**
* Formatting the filename based on locale, theme, and formFactor
* @return null
*/
buildFileName(options) {
const {
browserName,
cid,
formFactor,
locale,
theme,
} = options;

const fileNameConf = ['fileOutput'];
if (locale) {
fileNameConf.push(locale);
}

if (theme) {
fileNameConf.push(theme);
}

if (formFactor) {
fileNameConf.push(formFactor);
}

if (browserName) {
fileNameConf.push(browserName);
}

if (cid) {
fileNameConf.push(cid);
}

this.fileName = fileNameConf.join('-');
}

/**
* Updates resultJsonObject based on locale, theme, and formFactor
* @return null
*/
updateResultObject(options) {
const {
formFactor,
locale,
theme,
} = options;

if (locale) {
this.resultJsonObject.locale = locale;
}

if (theme) {
this.resultJsonObject.theme = theme;
}

if (formFactor) {
this.resultJsonObject.formFactor = formFactor;
}
}

/**
* Returns the package name of the spec file.
* @param {string} spec - The spec filepath.
* @returns {string} - The package name of the spec file.
*/
static getPackageName(spec) {
// Check if the spec file is nested within a monorepo package.
if (spec.indexOf(`${path.sep}packages${path.sep}`) > -1) {
return spec.split(`${path.sep}packages${path.sep}`).pop().split(path.sep)[0];
}
const packageJsonPath = path.join(process.cwd(), 'package.json');
if (fs.existsSync(packageJsonPath)) {
const packagejson = fs.readJsonSync(packageJsonPath);
return packagejson.name;
}
return process.cwd().split(path.sep).pop();
}

onRunnerEnd(runner) {
this.runners.push(runner);
this.printReport(runner);
}

getMessage(runner) {
const results = this.getResultDisplay();

if (results.length === 0) {
return null;
}

let testLinks;

if (runner.isMultiremote) {
testLinks = Object.entries(runner.capabilities).map(
([instanceName, capabilities]) => this.getTestLink({
config: { ...runner.config, ...{ capabilities } },
sessionId: capabilities.sessionId,
isMultiremote: runner.isMultiremote,
instanceName,
}),
);
} else {
testLinks = this.getTestLink(runner);
}

const output = [
...this.getHeaderDisplay(runner),
'',
...results,
...this.getFailureDisplay(),
...(testLinks.length ? ['', ...testLinks] : []),
];

const preface = `[${this.getEnviromentCombo(
runner.capabilities,
false,
runner.isMultiremote,
).trim()} #${runner.cid}]`;

const divider = '------------------------------------------------------------------';
const prefacedOutput = output.map((value) => (value ? `${preface} ${value}` : preface));

return `${divider}\n${prefacedOutput}`;
}

printReport() {
const { runners } = this;
if (runners && runners.length) {
runners.forEach((runner, index) => {
// determine correct file name given configuration for run
if (index === 0) {
const { cid, capabilities, config } = runner;
const { browserName } = capabilities;
const { formFactor, locale, theme } = config.launcherOptions;
const options = {
browserName,
cid,
formFactor,
locale,
theme,
};

this.buildFileName(options);
this.updateResultObject(options);
}

const packageName = FileOutputReporter.getPackageName(runner.specs[0]);

if (!this.resultJsonObject.output[packageName]) {
this.resultJsonObject.output[packageName] = [];
}
const readableMessage = this.getMessage(runner);
const readableArrayMessage = readableMessage.toString().split(',');
const messages = readableArrayMessage.map((message) => stripAnsi(`${message}${endOfLine}`));
this.resultJsonObject.output[packageName].push(messages.join(''));
this.resultJsonObject.startDate = new Date(
runner.start,
).toLocaleString();
this.resultJsonObject.endDate = new Date(runner.end).toLocaleString();
});
}
const {
endDate, startDate, locale, formFactor, theme, output,
} = this.resultJsonObject;

const moduleKeys = Object.keys(output) || [];
if (output && moduleKeys.length) {
moduleKeys.forEach((key) => {
const fileData = {
startDate,
locale,
theme,
formFactor,
output: output[key],
endDate,
};

const filePathLocation = path.join(
this.resultsDir,
`${this.fileName}-${key}.json`,
);
fs.writeFileSync(
filePathLocation,
`${JSON.stringify(fileData, null, 2)}`,
{ flag: 'w+' },
(err) => {
if (err) {
Logger.error(err.message, { context: LOG_CONTEXT });
}
},
);
});
}
}
}

module.exports = FileOutputReporter;
Loading

0 comments on commit 88bd8fb

Please sign in to comment.