Closed edgarechm closed 7 years ago
Do you need to save the JSON formatter output yourself? cucumber-js supports multiple formatters and the ability to send a formatter output to a file: https://github.com/cucumber/cucumber-js/blob/master/docs/cli.md#formats
Nope that won't work. Like I said, I need to have the output from cucumber in "pretty" gherkin format and the JSON file. In addition, I don't run my cucumberjs directly, I use protractor to execute them. There is a Jenkins job, that runs the script using a package.json, containing the call to protractor and the config file.
This is my protractor config file:
var featsLocation = 'features/';
var stepsLocation = 'steps/';
exports.config = {
directConnect: true,
chromeDriver: '/srv/build/applications/chromedriver/chromedriver.exe',
seleniumServerJar: '/srv/build/applications/selenium/selenium-server-standalone-3.4.0.jar',
rootElement: 'html',
params:{
authURL: '',
login:{
email:'',
passw:''
}
},
resultJsonOutputFile:'',
getPageTimeout: 30000,
allScriptsTimeout: 30000,
framework: 'custom',
frameworkPath: require.resolve('protractor-cucumber-framework'),
capabilities: {
'browserName': 'chrome',
chromeOptions:{
args:[]//"--headless"]
}
//'browserName': 'phantomjs',
//'phantomjs.binary.path': '/srv/build/applications/phantomjs/bin/phantomjs' //<--Comment to run from local
},
onPrepare: function(){
global.EC = protractor.ExpectedConditions;
},
specs: [ /**/
featsLocation+'authenticateCSM.feature'
, featsLocation+'ediRejects.feature'
, featsLocation+'ediRejects_sprint.feature'
],
baseUrl: '',
cucumberOpts: {
tags: '',
require: [
'./support/*.js'
, stepsLocation+'ediRejects/ediRejects.spec.js'
],
monochrome: true,
strict: true,
plugin: "json"
},
};
Now, all I need to know, is what changes I need to make to my hooks.js in order to have it working as it was before the update of cucumberjs 2.0? Before, it was working fine. What changed in the JsonFormatter implementation, that makes my code fail?
Nope that won't work. Like I said, I need to have the output from cucumber in "pretty" gherkin format and the JSON file.
I don't understand why that means you can't use the fact that cucumber-js support multiple formatters. You could use cucumber-js --format pretty --format json:cucumber_report.json
to have cucumber-js print the pretty format to stdout and the json output to cucumber-report.json. I don't know if protractor supports specifying multiple formats and if not that issue should be brought up there. Creating the html report could be done afterward in another script.
Now, all I need to know, is what changes I need to make to my hooks.js in order to have it working as it was before the update of cucumberjs 2.0? Before, it was working fine. What changed in the JsonFormatter implementation, that makes my code fail?
You are using undocumented internals of cucumber-js which is why I am suggesting solving this in a different way. In 2.0, cucumber now exports JsonFormatter
at the top level instead of a sub property under Listener
:
var JsonFormatter = require('cucumber').JsonFormatter
I was battling with this issue and thought I was going crazy. Glad I am not alone. In order to solve my problem I took a different path. I created a cucumber.js in the root of my project (Where package.json is defined) and put this code in and ran my test:
const common = '--format json:features/output/cucumber.json';
module.exports = {
build: common,
'default': common,
'es5': '--tags ~@es6'
};
Now, this file I am putting in is not there so I have to create it manually for now but I am pretty sure I will be able to automate it as well. Hope this code helps someone else too.
Why using two scripts now when, before cucumberjs2.0 I could do it in only one?
I tried...
protractor ./FM_IntTest_UI_conf.js --format pretty --format json:cucumber.json
And also tried...
protractor ./FM_IntTest_UI_conf.js --format json:cucumber.json
No JSON output on either.
Changed my hooks to this:
var JsonFormatter = require('cucumber').JsonFormatter;
var fs = require('fs');
var reporter = require('cucumber-html-reporter');
var CucumberHtmlReport = require('cucumber-html-report');
var seleniumWebdriver = require('selenium-webdriver');
var {defineSupportCode} = require('cucumber');
'use strict';
defineSupportCode(function({After,registerHandler,registerListener}) {
var outputDir = './'
After(function (scenario,callback) {
if (scenario.isFailed()) {
browser.takeScreenshot().then(function (base64png) {
scenario.attach(new Buffer(base64png, 'base64'), 'image/png');
callback();
}, function (err) {
return callback(err);
});
} else{
callback();
}
});
var createHtmlReport = function (sourceJson) {
var report = new CucumberHtmlReport({
source: sourceJson
, dest: outputDir
});
report.createReport();
};
//I don't know what method to call since now it's a class!
//var JsonFormatter = Cucumber.Listener.JsonFormatter();
JsonFormatter.log = function (string) {
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir);
}
var targetJson = outputDir + 'cucumber.json';
fs.writeFile(targetJson, string, function (err) {
if (err) {
console.log('Failed to save cucumber test results to json file.');
console.log(err);
} else {
createHtmlReport(targetJson);
}
});
};
registerListener(JsonFormatter);
});
Since the following is commented, I have no Json output... but how call the formatter, since there is no listener?
var JsonFormatter = Cucumber.Listener.JsonFormatter(); ///?????
Should open an issue at protractor?
require('cucumber').JsonFormatter
is a class. You can create an instance with:
jsonFormatter = new JsonFormatter()
Thus I believe you need the following:
jsonFormatter = new JsonFormatter()
jsonFormatter.log = //...
registerListener(jsonFormatter)
I would still advise you to read the documentation on protractor-cucumber-framework and open an issue there if you can't figure out how to configure it to output json to a file. I think thats a much more reliable way as you are using the documented CLI interface versus the undocumented internals which could break at any time if the internals change. An example would be if the JsonFormatter gets updated to be passed in something important which would be missing since you are creating your own instead of having cucumber-js create it.
Yes, what you provided helped me solving the issue, which then created another problem, but I was able to solve. JSON file is generated correctly, so I will put it here in case anyone else still uses cucumber-html-reporter needs it:
var JsonFormatter = require('cucumber').JsonFormatter;
var fs = require('fs');
var reporter = require('cucumber-html-reporter');
var CucumberHtmlReport = require('cucumber-html-report');
var seleniumWebdriver = require('selenium-webdriver');
var {defineSupportCode} = require('cucumber');
var outputDir = './'
'use strict';
defineSupportCode(function({After,registerListener}) {
After(function (scenario,callback) {
let self = this;
if (scenario.isFailed()) {
browser.takeScreenshot().then(function (base64png) {
self.attach(new Buffer(base64png, 'base64'), 'image/png');
callback();
}, function (err) {
return callback(err);
});
} else{
callback();
}
});
var createHtmlReport = function (sourceJson) {
var report = new CucumberHtmlReport({
source: sourceJson
, dest: outputDir
});
report.createReport();
};
jsonFormatter = new JsonFormatter;
jsonFormatter.log = function (string) {
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir);
}
var targetJson = outputDir + 'cucumber.json';
fs.writeFile(targetJson, string, function (err) {
if (err) {
console.log('Failed to save cucumber test results to json file.');
console.log(err);
} else {
createHtmlReport(targetJson);
}
});
};
registerListener(jsonFormatter);
});
I'll close the issue, since I have the solution.
Thanks to all!
Hi @charlierudolph
I upgraded to v3.0.3 but it would seem this snippet of code
const JsonFormatter = require('cucumber').JsonFormatter;
const { defineSupportCode } = require('cucumber');
const outputDir = './';
'use strict';
defineSupportCode(({ After, registerListener }) => {
const jsonFormatter = new JsonFormatter();
jsonFormatter.log = function (string) {
console.log(string);
};
registerListener(jsonFormatter);
});
similar to what is mentioned here breaks. Namely line
const jsonFormatter = new JsonFormatter();
throws an exception...details of exception are below
Unhandled rejection TypeError: Cannot read property 'eventBroadcaster' of undefined
at new JsonFormatter (C:\src\qa\node_modules\cucumber\src\formatter\json_formatter.js:21:5)
at defineSupportCode (C:\src\qa\Support\CucumberJs_Json_Listener.js:10:25)
at defineSupportCode (C:\src\qa\node_modules\cucumber\src\support_code_library_builder\index.js:20:9)
at Object.<anonymous> (C:\src\qa\Support\CucumberJs_Json_Listener.js:8:1)
at Module._compile (module.js:624:30)
at Object.Module._extensions..js (module.js:635:10)
at Module.load (module.js:545:32)
at tryModuleLoad (module.js:508:12)
at Function.Module._load (module.js:500:3)
at Module.require (module.js:568:17)
at require (internal/module.js:11:18)
at C:\src\qa\node_modules\cucumber\src\cli\index.js:61:42
at Array.forEach (<anonymous>)
at Cli.getSupportCodeLibrary (C:\src\qa\node_modules\cucumber\src\cli\index.js:61:22)
at Cli.<anonymous> (C:\src\qa\node_modules\cucumber\src\cli\index.js:76:37)
at Generator.next (<anonymous>)
My use case is similar to what was discussed above so have you any suggestions on how I can resolve this? Many thanks in advance.
@bhreinb just refer to the class instead of creating an instance of it, e.g.
const JsonFormatter = require('cucumber').JsonFormatter;
const { defineSupportCode } = require('cucumber');
const outputDir = './';
'use strict';
defineSupportCode(({ After, registerListener }) => {
const jsonFormatter = JsonFormatter;
jsonFormatter.log = function (string) {
console.log(string);
};
registerListener(jsonFormatter);
});
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
With the upcoming of Cucumberjs2.0, I had to make some changes to my hooks.js file, in order to have cucumber-html-reporter working back again.
My hooks.js explicitly creates a json file with the execution report, that I will later use to generate an HTML report (because I need both JSON and gherkin outputs).
HOWEVER.... I get this error message:
The error is in this line of code:
var JsonFormatter = Cucumber.Listener.JsonFormatter();
I noticed that since Cucumberjs2.0, implementation of JsonFormatter changed a lot. Could someone drive me to the changes I need to make in my hooks to have it working as it did before May12 (date when cucumberjs2.0 came into the picture)?
The "cucumber-html-reporter" team told me to ask my question to the cucumberjs team, please don't bounce me back.