Here is my conf.js file.
var HtmlScreenshotReporter = require('protractor-jasmine2-screenshot-reporter');
var reporter = new HtmlScreenshotReporter({
dest : '/opt/src/protractor/results/',
filename : 'index.html',
showSummary : true,
showQuickLinks : true,
showConfiguration : true,
cleanDestination : true,
ignoreSkippedSpecs : false,
reportOnlyFailedSpecs : false,
captureOnlyFailedSpecs : true,
});
exports.config = {
...
// Setup the report before any tests start
beforeLaunch: function() {
return new Promise(function(resolve){
reporter.beforeLaunch(resolve);
});
},
onPrepare: function () {
reporter.dest = '/opt/src/protractor/results/' + browser.params.directory + '/';
jasmine.getEnv().addReporter(reporter);
I would like to dynamicly change the destination directory by passing arguments :
Eg :
protractor conf.js --suite=MySuiteName --browser.params.directory=MyDirectory
All reports are generated in /opt/src/protractor/results/ instead of /opt/src/protractor/results/MyDirectory
Why I can't change Destination directory?
Thanks in advance. :)
Inside protractor-jasmine2-screenshot-reporter implement, it only read the destination folder by options.dest of the passed-in options when call new HtmlScreenshotReporter(options).
Thus changing reporter.dest won't change the destination folder when generate report files
Please try below code: (delay to init reporter instance in onPrepare, in which you can get the value of CLI argument: --browser.params.directory
var HtmlScreenshotReporter = require('protractor-jasmine2-screenshot-reporter');
var reportOpts = {
dest : '/opt/src/protractor/results/',
filename : 'index.html',
showSummary : true,
showQuickLinks : true,
showConfiguration : true,
cleanDestination : true,
ignoreSkippedSpecs : false,
reportOnlyFailedSpecs : false,
captureOnlyFailedSpecs : true,
};
var reporter;
exports.config = {
onPrepare: function () {
// change reporter destination
reportOpts.dest = '/opt/src/protractor/results/' + browser.params.directory + '/';
// delay init reporter instance in onPrepare(), but beforelaunch()
reporter = new HtmlScreenshotReporter(reportOpts);
reporter.beforeLaunch(function(){
jasmine.getEnv().addReporter(reporter);
});
},
// Close the report after all tests finish
afterLaunch: function(exitCode) {
return new Promise(function(resolve){
reporter.afterLaunch(resolve.bind(this, exitCode));
});
}
};
Related
The following code does not work. I am trying to connect the 'html-minifier' plugin to 'gulp' via the 'vinyl-source-stream' plugin.
Why am I doing this? I read on this page that you can connect the plugin 'browserify'. I wrote this code but it gives an error. How can I resolve it?
'use strict';
const { src, dest, series } = require('gulp')
const htmlMinify = require('html-minifier').minify;
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const options = {
includeAutoGeneratedTags: true,
removeAttributeQuotes: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
sortClassName: true,
useShortDoctype: true
};
const result = htmlMinify('frontend/*.html', options)
function test() {
return result.bundle()
.pipe(source('frontend/**/*.html'))
.pipe(buffer())
.pipe(dest('public'))
}
exports.build = series(test)
I wrote the following code and now the 'html-minifier' plugin can work directly in 'gulp'.
The const options variable is the 'html-minifier' plugin settings.
Then we create a function gHtmlMinify that can be run with the gulp gHtmlMinify command.
return src(...) is your html files path.
.on('data', function(file) {...} Each thread has a "data" event..
We hang the processing of the "data" event..
When the "data" event is called, the "file" object comes to us, which contains information: file name, file path, working directory and file contents.
The content of the file is represented as a read buffer file.isBuffer().
Buffer.from The raw data is stored in instances of the Buffer class.
(file.contents.toString() This file content is BUFFER.
The toString() method returns a function that represents an object. Converts to a string.
console.log ({ // Outputting the structure of what the file consists of.
contents: file.contents, // Content of the file BUFFER. The buffer is not a string!
path: file.path, // Path to the file.
cwd: file.cwd, // Current directory. "The directory where the gulp command was run".
base: file.base, // Value before asterisks i.e. app/
relative: file.relative, // Value after the asterisks i.e. filename.html
dirname: file.dirname, // File directory.
basename: file.basename, // File name.
stem: file.stem, // File name without extension.
extname: file.extname // File extension.
})
const { src, dest, series } = require('gulp');
const htmlMinify = require('html-minifier');
const options = {
includeAutoGeneratedTags: true,
removeAttributeQuotes: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
sortClassName: true,
useShortDoctype: true,
collapseWhitespace: true
};
function gHtmlMinify() {
return src('app/**/*.html')
.on('data', function(file) {
const buferFile = Buffer.from(htmlMinify.minify(file.contents.toString(), options))
file.contents = buferFile;
console.log(file);
return;
})
.pipe(dest('build'))
}
exports.gHtmlMinify = series(gHtmlMinify)
I want to create cucumber html reports and I am new to Node JS and I tried searching for it and I used the following
this.registerHandler('AfterFeatures', function(callback) {
try {
var options = {
theme: "bootstrap",
jsonFile: "/report/cucumber.json",
output: "/report/cucumber_report.html",
reportSuiteAsScenarios: true,
launchReport: true,
metadata: {
"App Version": "0.0.1"
}
};
reporter.generate(options);
} catch (e) {
console.log(e);
}
callback();
});
But when I run my code, The cucumber feature scenarios gets executed and it finally gives me an error stating,
Unable to parse cucumberjs output into json: '/report/cucumber.json' { Error: /report/cucumber.json: ENOENT: no such file or directory, open '/report/cucumber.json'
at Object.fs.openSync (fs.js:652:18)
at Object.fs.readFileSync (fs.js:553:33)
at Object.readFileSync (/Users/sarav/Documents/GitHub/automationtests/node_modules/jsonfile/index.js:67:22)
at isValidJsonFile (/Users/sarav/Documents/GitHub/automationtests/node_modules/cucumber-html-reporter/lib/reporter.js:404:48)
at Object.generate (/Users/sarav/Documents/GitHub/automationtests/node_modules/cucumber-html-reporter/lib/reporter.js:426:9)
at Object.generateReport [as generate] (/Users/sarav/Documents/GitHub/automationtests/node_modules/cucumber-html-reporter/index.js:30:21)
at /Users/sarav/Documents/GitHub/automationtests/features/support/hooks.js:49:22
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/report/cucumber.json' }
Do the above code automatically generates .json and .html file or we need to manually create a .json file and converts that into a html report.
I have worked on Java and it automatically creates the json and html reports at the end the execution.
As this is very new I am not able to figure out whats the missing part
Thanks
Your code to generate HTML report will expect the json file: /report/cucumber.json had been exist.
So you need other code to help to generate the json file during test running, I will give code used in my project for your reference.
Note: below code can only work on Cucumber 1, can't work on Cucumver 2, below is the version I used:
"dependencies": {
"cucumber": "1.2.1",
"cucumber-html-reporter": "0.2.6",
1) cucumber-json-report.js to generate Cucumber JSON report during running.
var fs = require('fs-extra');
var path = require('path');
var moment = require('moment');
var Cucumber = require('cucumber');
module.exports = function() {
var JsonFormatter = Cucumber.Listener.JsonFormatter();
JsonFormatter.log = function(string) {
var outputDir = './reports';
var targetJson = outputDir + '/cucumber_report.json';
if (fs.existsSync(outputDir)) {
fs.moveSync(outputDir, outputDir + '_' + moment().format('YYYYMMDD_HHmmss') + "_" + Math.floor(Math.random() * 10000), {
overwrite: true
});
}
fs.mkdirSync(outputDir);
fs.writeFileSync(targetJson, string);
};
this.registerListener(JsonFormatter);
};
2) screenshot.js to take screenshot when failure
module.exports = function() {
this.After(function(scenario, callback) {
if (scenario.isFailed()) {
browser.takeScreenshot().then(function(buffer) {
var decodedImage = new Buffer(buffer, 'base64');
scenario.attach(decodedImage, 'image/png');
callback();
}, function(err) {
callback(err);
});
} else {
callback();
}
});
};
3) cucumber-html-report.js to generate Cucumber HTML report after all features running end.
var reporter = require('cucumber-html-reporter');
module.exports = function() {
this.AfterFeatures(function(features, callback) {
var options = {
theme: 'bootstrap',
jsonFile: 'reports/cucumber_report.json',
output: 'reports/cucumber_report.html',
reportSuiteAsScenarios: true
};
reporter.generate(options);
callback();
});
};
4) Protractor conf.js to include above three files in cucumberOpts.require
cucumberOpts: {
monochrome: true,
strict: true,
plugin: ["pretty"],
require:[
'./step_definitions/*step.js',
'./support/screenshot.js',
'./support/cucumber-json-report.js',
'./support/cucumber-html-report.js'
],
tags: '',
},
I am using the following plugin to paralelized the uglify step in webpack
https://github.com/tradingview/webpack-uglify-parallel
unfortunately, I get the following error:
Fatal error: Cannot set property '__UglifyJsPlugin' of undefined
Here's my webpack config:
/*jslint node: true */
var webpack = require("webpack"),
_ = require("lodash"),
path = require("path"),
fs = require("fs"),
os = require('os'),
UglifyJsParallelPlugin = require('webpack-uglify-parallel'),
webpackConfig,
commonsPlugin = new webpack.optimize.CommonsChunkPlugin('m-common-[chunkhash:8].js'),
dedupePlugin = new webpack.optimize.DedupePlugin(),
uglifyPlugin = new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
parallelUglify = new UglifyJsParallelPlugin({
workers: os.cpus().length
}),
sourceMapPlugin = new webpack.SourceMapDevToolPlugin('[file].map', null,
'[absolute-resource-path]',
'[absolute-resource-path]'),
fnCaseSensitivityPlugin = function () {
this.plugin('normal-module-factory', function(nmf) {
nmf.plugin('after-resolve', function(data, done) {
var parentDir = path.dirname(data.resource);
var resourceName = path.basename(data.resource);
fs.readdir(parentDir, function(err, files) {
if (err) {
done(err);
}
if (files.indexOf(resourceName) === -1) {
var realName = _.find(files, function(filename) {
return filename.toLowerCase() === resourceName.toLowerCase();
});
done(new Error('CaseSensitivityPlugin: `' + resourceName + '` does not match the corresponding file on disk `' + realName + '`'));
return;
}
done(null, data);
});
});
});
},
fnDonePlugin = function () {
this.plugin("done", function(stats) {
var statsByChunk = JSON.parse(JSON.stringify(stats.toJson())).assetsByChunkName;
webpackConfig.statsByChunk = statsByChunk;
for (var chunkName in statsByChunk) {
if (statsByChunk.hasOwnProperty(chunkName)) {
var nameIn = statsByChunk[chunkName][0],
gzName = nameIn.substring(0, nameIn.length - 2) + "gz.js";
webpackConfig.filesToCompress['./marvel-web/dist/' + gzName] = './marvel-web/dist/' + nameIn;
// The mrvlBuildOut object contains a set of name/value
// pairs to be used during HTML template processing.
// There are certain filenames we need to add to the
// mrvlBuildOut object as properties so that they can be
// injected into HTML templates that make use of them.
// The code below takes the nameIn string which will have
// one of 2 forms:
//
// Debug Builds:
// m-core-fixed.js
//
// Produciton Builds:
// m-core-<chunkid>.js
//
// It strips off everything after the last dash including the
// .js extension so we are left with the base filename. We then
// use that filename base to look up the name of the property
// we should set to that filename on the mrvlBuildOut object.
var map = webpackConfig.mrvlBuildOutFilePropMap,
propName = map[nameIn.replace(/-[^-]+\.js$/ , '')];
if (propName) {
webpackConfig.mrvlBuildOut[propName] = nameIn;
}
}
}
webpackConfig.webpackDoneListeners.forEach(function (fnCall) {
fnCall(statsByChunk);
});
});
};
webpackConfig = {
mrvlBuildOut: {
//gets filled in with m-common-[chunkhash] and m-web-[chunkhash]
},
mrvlBuildOutFilePropMap: {
"m-common": "marvelcommon",
"m-web": "marvelweb",
"m-blog": "marvelblog",
"m-gallery": "marvelgallery",
"m-landing": "marvellanding",
"m-unsupported": "marvelunsupported",
"m-login": "marvellogin",
"m-voice-chrome": "voicechrome",
"m-apps-chrome": "appschrome",
"m-viewpage-chrome": "viewpagechrome"
},
webpackDoneListeners: [],
filesToCompress: {
},
marvel: {
addVendor: function (name, path, noparse) {
this.resolve.alias[name] = path;
if (noparse) {
this.module.noParse.push(new RegExp(path));
}
this.entry.vendors.push(name);
},
addBuildOutFilePropMapEntry: function( filenameBase, propName ) {
if ( filenameBase && propName ) {
webpackConfig.mrvlBuildOutFilePropMap[filenameBase] = propName;
}
},
stats: {
colors: true,
modules: true,
reasons: false
},
entry: {
'm-web': './marvel-web/js/app.js',
'm-blog': './marvel-web/js/app-blog.js',
'm-gallery': './marvel-web/js/app-gallery.js',
'm-landing': './marvel-web/js/app-landing.js',
'm-unsupported': './marvel-web/js/app-unsupported.js',
'm-login': './marvel-web/js/app-login.js',
'm-voice-chrome': './marvel-web/js/app-voice-chrome.js',
'm-apps-chrome': './marvel-web/js/app-apps-chrome.js',
'm-viewpage-chrome': './marvel-web/js/app-viewpage-chrome.js',
vendors: []
},
resolve: {
modulesDirectories: [
'node_modules',
'marvel-web',
'marvel-web/js'
],
alias: {
// If you find yourself wanting to add an alias here, think
// about if it would be better for your component to live in
// marvel-core instead of in marvel-web. See the README.md in
// marvel-core for more info.
'marvel-apps': __dirname + '/marvel-web/js/apps.js',
'uuid': 'node-uuid'
}
},
output: {
path: 'marvel-web/dist',
filename: '[name]-[chunkhash:8].js',
chunkFilename: '[name]-[chunkhash:8].js'
},
module: {
noParse: [
/[\/\\].html$/
]
},
plugins: [
commonsPlugin,
dedupePlugin,
parallelUglify,
fnCaseSensitivityPlugin,
sourceMapPlugin,
fnDonePlugin
]
}
};
var libs_dir = __dirname + '/marvel-core/src/js/lib/';
webpackConfig.marvel.addVendor("jquery", libs_dir + "jQuery/jquery.min.js", true);
webpackConfig.marvel.addVendor("lodash", libs_dir + "lodash/lodash.min.js", true);
webpackConfig.marvel.addVendor("underscore", libs_dir + "lodash/lodash.min.js", true);
webpackConfig.marvel.addVendor("q", libs_dir + "q/q.js", true);
webpackConfig.marvel.addVendor("backbone", libs_dir + "backbone/backbone-min.js", false);//if we don't parse backbone then require is not found??
webpackConfig.marvel.addVendor("cookie", libs_dir + "cookie/cookie.js", true);
webpackConfig.marvel.addVendor("canvas-to-blob", libs_dir + "canvas-to-blob/canvas-to-blob.js", true);
webpackConfig.marvelDebug = {
watch: true,
keepAlive: true,
stats: webpackConfig.marvel.stats,
entry: webpackConfig.marvel.entry,
resolve: webpackConfig.marvel.resolve,
output: {
path: 'marvel-web/dist',
filename: '[name]-fixed.js',
chunkFilename: '[name]-fixed.js'
},
module: webpackConfig.marvel.module,
//devtool: "eval-source-map",
devtool: "source-map",
//devtool: "eval",
addBuildOutFilePropMapEntry: webpackConfig.marvel.addBuildOutFilePropMapEntry,
plugins: [
commonsPlugin,
dedupePlugin,
fnCaseSensitivityPlugin,
sourceMapPlugin,
fnDonePlugin
]
};
webpackConfig.marvelDebug.output.pathinfo = true;
module.exports = webpackConfig;
The plugin works in my project when I don't include a separate entry for the original UglifyJsPlugin. Try removing that and add its config to the UglifyJsParallelPlugin.
I have just simplified the source file to below, which works fine when I use System.import in a script tag.
import angular from "angular";
angular.element(document).ready(function () {
alert('Hello word');;
});
Below is my config.js
System.config({
baseURL: "/",
defaultJSExtensions: true,
transpiler: "typescript",
paths: {
"npm:": "jspm_packages/npm/"
},
map: {
"angular": "npm:angular#1.5.2",
"typescript": "npm:typescript#1.8.9"
}
});
I have a gulp task to build it:
gulp.task('bundle:js', ['clean:js'], function () {
var builder = new Builder();
builder.loadConfig('./config.js').then(function () {
var destination = paths.coreJsDest;
builder.buildStatic(paths.srcRoot + 'js/ng/homepage', destination, {
minify: false,
sourceMaps: false,
runtime: false
});
});
});
But the output file contains the file name rather than JavaScript from the file and its imports:
(["1"], ["1"], function($__System) {
})
(function(factory) {
if (typeof define == 'function' && define.amd)
define(["D:/Projects/etc-etc/assets/js/ng/homepage.js"], factory);
else if (typeof module == 'object' && module.exports && typeof require == 'function')
module.exports = factory(require("D:/Projects/etc-etc/js/ng/homepage.js"));
else
throw new Error("Module must be loaded as AMD or CommonJS");
});
Doh, I just needed to change the baseUrl from "/" to "./".
I really don't know what is the reason for this exception and what are the side effects of it.
But It appears every time even all test cases are passed.
Please help to figure out how to solve this -
[launcher] Error: TypeError: Cannot read property 'headerPrinter' of undefined
at printHeader (C:\automation\tests\node_modules\protractor-console\dist\protractor-console.js:81:8)
at C:\automation\tests\node_modules\protractor-console\dist\protractor-console.js:56:19
at [object Object].promise.ControlFlow.runInFrame_ (C:\automation\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\webdriver\promise.js:1877:20)
at [object Object].promise.Callback_.goog.defineClass.notify (C:\automation\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\webdriver\promise.js:2464:25)
at [object Object].promise.Promise.notify_ (C:\automation\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\webdriver\promise.js:563:12)
at Array.forEach (native)
at Object.goog.array.forEach (C:\automation\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\goog\array\array.js:203:43)
at [object Object].promise.Promise.notifyAll_ (C:\automation\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\webdriver\promise.js:552:16)
at goog.async.run.processWorkQueue (C:\automation\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\goog\async\run.js:125:21)
at runMicrotasksCallback (node.js:337:7)
[launcher] Process exited with error code 100
Protractor conf:
//-=-=-=- Packages -=-=-=-
var path = require('path');
var fs = require('fs');
var HtmlReporter = require('protractor-html-screenshot-reporter');
var util = require('util');
var Imap = require('imap'),
inspect = require('util').inspect;
var MailParser = require("mailparser").MailParser;
var MailListener = require("mail-listener2");
var log_file = fs.createWriteStream('c:\\automation\\tests\\' + '/emailResponses.log', {flags : 'w'});
// var log_exceptions = fs.createWriteStream('c:\\automation\\tests\\' + '/exceptions.log', {flags : 'w'});
var log_stdout = process.stdout;
//-=-=-=- Helpers -=-=-=-
captureScreen = function(name){
browser.driver.takeScreenshot().then(function(data){
var base64Data = data.replace(/^data:image\/png;base64,/,"");
return browser.getCapabilities().then(function (cap) {
var fname = name + "-" + cap.caps_.browserName + ".png";
fs.writeFile(fname, base64Data, 'base64', function(err) {
if(err) console.log(err);
});
});
});
}
waitPageToLoad = function(){
browser.driver.manage().timeouts().pageLoadTimeout(60000);
}
getLastEmail = function() {
var deferred = protractor.promise.defer();
console.log("Waiting for an email...");
mailListener.on("mail", function(mail){
deferred.fulfill(mail);
});
return deferred.promise;
};
// -=-=- Testing configuration -=-=-
exports.config = {
chromeDriver: 'npm/node_modules/protractor/selenium/chromedriver',
chromeOnly: false,
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['c:\\automation\\tests\\frontageSanity.js'],
plugins: [{
package: 'C:\\automation\\tests\\node_modules\\protractor-console',
logLevels: ['severe', 'warning']
}],
// directConnect: true,
multiCapabilities: [{
// 'browserName': 'firefox',
// 'cli': {
// 'args': ['webdriver.firefox.useExisting=default', '-jsconsole', '-jsdebugger']
// }},
// }
// {
'browserName': 'chrome',
'chromeOptions': {
args: ['--no-sandbox','--test-type','--memory-metrics','--console','--crash-on-failure'],
// '--load-extension=' + 'C:\\Users\\idan\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Extensions\\idgpnmonknjnojddfkpgkljpfnnfcklj\\1.2.4_0'
prefs: {
download: {
'prompt_for_download': false,
'directory_upgrade': true,
'default_directory': 'C:\\automation\\tests\\downloaded\\'
}
}
}
// },
// {
// 'browserName': 'internet explorer',
// 'platform': 'ANY',
// 'version': '12'
}],
framework: "jasmine",
allScriptsTimeout: 90000,
getPageTimeout: 90000,
// -=-=- Pre-Conditions & Tools configurations -=-=-
onPrepare: function() {
//-=-=-=- HTML Reporter -=-=-=-
jasmine.getEnv().addReporter(new HtmlReporter({
baseDirectory: 'C:\\automation\\tests\\HtmlReporter\\',
// takeScreenShotsOnlyForFailedSpecs: true,
docTitle: 'vCita - Sanity testing report',
docName: 'Test_Report.html',
cssOverrideFile: 'htmlReporter_css.css'
}));
browser.driver.manage().window().maximize();
browser.getCapabilities().then(function (cap) {
browser.browserName = cap.caps_.browserName;
});
// -=-=-=- Email Listener - here goes your email connection configuration -=-=-=-
var mailListener = new MailListener({
username: "username",
password: "password",
host: "imap.gmail.com",
port: 993, // imap port
tls: true,
tlsOptions: { rejectUnauthorized: false },
mailbox: "INBOX", // mailbox to monitor
// searchFilter: ["UNSEEN", "FLAGGED"], // the search filter being used after an IDLE notification has been retrieved
markSeen: true, // all fetched email willbe marked as seen and not fetched next time
fetchUnreadOnStart: true, // use it only if you want to get all unread email on lib start. Default is `false`,
// mailParserOptions: {streamAttachments: true}, // options to be passed to mailParser lib.
// attachments: true, // download attachments as they are encountered to the project directory
// attachmentOptions: { directory: "attachments/" } // specify a download directory for attachments
});
mailListener.start();
mailListener.on("server:connected", function(){
console.log("imapConnected");
});
mailListener.on("server:disconnected", function(){
console.log("imapDisconnected");
});
mailListener.on("mail", function(){
// console.log("GO IT!");
});
mailListener.on("mail", function(mail, seqno, attributes){
// do something with mail object including attachments
console.log("emailParsed", mail)
// mail processing code goes here
log_file.write(util.format(mail));
log_stdout.write(util.format(mail));
});
global.mailListener = mailListener;
},
// onCleanUp: function () {
// mailListener.stop();
// },
// -=-=- Node JS Settings -=-=-
jasmineNodeOpts: {
onComplete: function () {
mailListener.stop();
},
// If true, display spec names.
isVerbose: true,
// If true, print colors to the terminal.
showColors: true,
// If true, include stack traces in failures.
includeStackTrace: true,
// Default time to wait in ms before a test fails.
defaultTimeoutInterval: 9999999
}
}
The package you needed to install and use is called protractor-console-plugin, not protractor-console.