I have a onprepare function in my global protractor config
module.exports = {
.....
onPrepare: function() {
// At this point, global 'protractor' object will be set up, and jasmine
// will be available. For example, you can add a Jasmine reporter with:
// jasmine.getEnv().addReporter(new jasmine.JUnitXmlReporter(
// 'outputdir/', true, true));
var chai = require('chai'),
chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
global.chai = chai;
global.expect = chai.expect;
// setting up module file paths
var rootPath = path.normalize(__dirname + '/../');
global.__paths = global.__paths || {};
global.__paths.e2e = {
parts: rootPath + 'parts',
lib: rootPath + 'lib',
pages: rootPath + 'pages',
widgets: rootPath + 'widgets',
api: rootPath + 'api',
};
// detect if this is running locally, or in some staging env
global.isLocal = browser.baseUrl.indexOf('localhost') !== -1 ? true : false;
}
};
I then have my protractor config extending this like so
var path = require('path');
var globalConf = require('global.protractor.conf.js');
exports.config = globalConf;
However I want to add some more paths to global.__paths.e2e from this protractor.config however I am not sure how to extend the onPrepare function so that I can add couple more paths to it and still keep the original onprepare functionality
Im not sure wheter this will work.can you please try the below method.
globalConf.onPrepare.global [key] = path
Related
I am trying to understand the following code from the browserify-css repo:
var gulp = require('gulp');
var gutil = require('gulp-util');
var path = require('path');
var browserify = require('browserify');
var sourceStream = require('vinyl-source-stream');
var fse = require('fs-extra');
var bundleStream = browserify()
.add('src/index.js')
.transform(require('browserify-css'), {
rootDir: 'src',
processRelativeUrl: function(relativeUrl) {
var stripQueryStringAndHashFromPath = function(url) {
return url.split('?')[0].split('#')[0];
};
var rootDir = path.resolve(process.cwd(), 'src');
var relativePath = stripQueryStringAndHashFromPath(relativeUrl);
var queryStringAndHash = relativeUrl.substring(relativePath.length);
//
// Copying files from '../node_modules/bootstrap/' to 'dist/vendor/bootstrap/'
//
var prefix = '../node_modules/';
if (_.startsWith(relativePath, prefix)) {
var vendorPath = 'vendor/' + relativePath.substring(prefix.length);
var source = path.join(rootDir, relativePath);
var target = path.join(rootDir, vendorPath);
gutil.log('Copying file from ' + JSON.stringify(source) + ' to ' + JSON.stringify(target));
fse.copySync(source, target);
// Returns a new path string with original query string and hash fragments
return vendorPath + queryStringAndHash;
}
return relativeUrl;
}
})
.bundle();
bundleStream
.pipe(sourceStream(bundleFile))
.pipe(gulp.dest(browserifyConfig.dest));
I don't understand the part
_.startsWith(relativePath, prefix)
Where is the underscore coming from? It's supposed to be javascript executed by a task runner. I've found that in the NodeJS REPL the underscore character outputs the result of the last executed expression, but that functionality can't be used inside scripts. It's also not an underscore.js instance because it is not being declared anywhere. startsWith is a String method.
So what am I missing?
That code is using the lodash library. You can see in this section of the readme that they're importing lodash with var _ = require('lodash');
I'm using Browserify to create a bundle which contains an exported function that I want to call within a <script> tag. Everything works fine until I require Bootstrap, at which point the function is no longer accessible and I get the error:
TypeError: mainBundle.greeting is not a function
Here's the code:
JavaScript (main.js):
window.jQuery = require('jquery');
window.$ = global.jQuery;
module.exports = {
greeting
};
function greeting (name) {
return `Hello ${name}!`;
}
HTML
<script src="js/bundle.js"></script>
<script>
// Update greeting
$('#greeting').text(mainBundle.greeting('Foo'));
</script>
Gulpfile:
Taken pretty much from the Gulp Browserify recipe. You can see I've added the standalone option to customOpts to generate a standalone module as well as require to add Bootstrap. The issue occurs when the require line is commented in.
const gulp = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const concat = require('gulp-concat');
const watchify = require('watchify');
const browserify = require('browserify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const log = require('gulplog');
// add custom browserify options here
const customOpts = {
entries: ['./src/js/main.js'],
// require: ['bootstrap', 'jquery'], // UNCOMMENT CAUSES ISSUE
standalone: 'mainBundle',
debug: true
};
const opts = {...watchify.args, ...customOpts};
const b = watchify(browserify(opts));
console.log('Browserify options: ', opts);
// add transformations here
// i.e. b.transform(coffeeify);
exports.js = bundle; // so you can run `gulp js` to build the file
b.on('update', bundle); // on any dep update, runs the bundler
b.on('log', log.info); // output build logs to terminal
function bundle() {
return b.bundle()
// log errors if they happen
.on('error', log.error.bind(log, 'Browserify Error'))
.pipe(source('bundle.js'))
// optional, remove if you don't need to buffer file contents
.pipe(buffer())
// optional, remove if you dont want sourcemaps
.pipe(sourcemaps.init({loadMaps: true})) // loads map from browserify file
// Add transformation tasks to the pipeline here.
.pipe(sourcemaps.write('./')) // writes .map file
.pipe(gulp.dest('./dist/js'));
}
Hmm, putting the require in main.js resolves the issue:
const bootstrap = require('bootstrap');
window.jQuery = require('jquery');
window.$ = global.jQuery;
module.exports = {
greeting
};
function greeting (name) {
return `Hello ${name}!`;
}
If anyone has a better answer that would allow me to use the Browserify require option, I will happily accept your answer. I would prefer to use the config option to avoid importing things that are not explicitly required in my scripts.
I have a number of UI tests written in javascript (using selenium and cucumber). Currently I am running tests as follows:
yarn run loginTest
Is there a command for debugging the test?
Update:
Below is a snapshot of my package.json that includes the loginTest script reference:
"scripts": {
"loginTest": "node ./scripts/loginTest.js"
....
},
The loginTest.js file is shown below:
const chalk = require('chalk');
const path = require('path');
const fs = require('fs-extra');
const cp = require('child_process');
const srcPath = './projects/';
const projects = fs.readdirSync(srcPath)
.filter(file => fs.lstatSync(path.join(srcPath, file)).isDirectory())
.filter(file => file !== 'commons');
process.env.HOST = process.argv.slice(2)[0] || 'localhost';
console.log(chalk.magenta('Carrying out integration tests against: ') + process.env.HOST);
projects.forEach((project) => {
if (fs.existsSync(`./projects/${project}/login-tests/features/`)) {
console.log(chalk.yellow('Starting integration tests for: ') + project);
cp.fork(__dirname + '/runtime/pickle.js',
[
'-f', `./projects/${project}/login-tests/features/`,
'-s', `./projects/${project}/login-tests/step-definitions/`,
'-p', `./projects/${project}/login-tests/page-objects/`,
'-r', `./build/reports/${project}`
]);
}
});
The pickle.js file that was referenced above is shown here:
#!/usr/bin / env node
'use strict';
const fs = require('fs-plus');
const path = require('path');
const program = require('commander');
const cucumber = require('cucumber');
function collectPaths(value, paths) {
paths.push(value);
return paths;
}
function coerceInt(value, defaultValue) {
const int = parseInt(value);
if (typeof int === 'number') return int;
return defaultValue;
}
let config = {
steps: './step-definitions',
pageObjects: './page-objects',
sharedObjects: './shared-objects',
reports: './reports',
browser: 'chrome',
timeout: 15000
};
const configFileName = path.resolve(process.cwd(), 'selenium-cucumber-js.json');
if (fs.isFileSync(configFileName)) {
config = Object.assign(config, require(configFileName));
}
program
.option('-s, --steps <path>', 'path to step definitions. defaults to ' + config.steps, config.steps)
.option('-p, --pageObjects <path>', 'path to page objects. defaults to ' + config.pageObjects, config.pageObjects)
.option('-o, --sharedObjects [paths]', 'path to shared objects (repeatable). defaults to ' + config.sharedObjects, collectPaths, [config.sharedObjects])
.option('-b, --browser <path>', 'name of browser to use. defaults to ' + config.browser, config.browser)
.option('-r, --reports <path>', 'output path to save reports. defaults to ' + config.reports, config.reports)
.option('-d, --disableLaunchReport [optional]', 'Disables the auto opening the browser with test report')
.option('-j, --junit <path>', 'output path to save junit-report.xml defaults to ' + config.reports)
.option('-t, --tags <tagName>', 'name of tag to run', collectPaths, [])
.option('-f, --featureFiles <paths>', 'comma-separated list of feature files to run')
.option('-x, --timeOut <n>', 'steps definition timeout in milliseconds. defaults to ' + config.timeout, coerceInt, config.timeout)
.option('-n, --noScreenshot [optional]', 'disable auto capturing of screenshots when an error is encountered')
.parse(process.argv);
program.on('--help', function () {
console.log(' For more details please visit https://github.com/john-doherty/selenium-cucumber-js#readme\n');
});
// store browserName globally (used within world.js to build driver)
global.browserName = program.browser;
// store Eyes Api globally (used within world.js to set Eyes)
global.eyesKey = config.eye_key;
// used within world.js to import page objects
global.pageObjectPath = path.resolve(program.pageObjects);
// used within world.js to output reports
global.reportsPath = path.resolve(program.reports);
if (!fs.existsSync(program.reports)) {
fs.makeTreeSync(program.reports);
}
// used within world.js to decide if reports should be generated
global.disableLaunchReport = (program.disableLaunchReport);
// used with world.js to determine if a screenshot should be captured on error
global.noScreenshot = (program.noScreenshot);
// used within world.js to output junit reports
global.junitPath = path.resolve(program.junit || program.reports);
// set the default timeout to 10 seconds if not already globally defined or passed via the command line
global.DEFAULT_TIMEOUT = global.DEFAULT_TIMEOUT || program.timeOut || 10 * 1000;
// used within world.js to import shared objects into the shared namespace
global.sharedObjectPaths = program.sharedObjects.map(function (item) {
return path.resolve(item);
});
// rewrite command line switches for cucumber
process.argv.splice(2, 100);
// allow specific feature files to be executed
if (program.featureFiles) {
var splitFeatureFiles = program.featureFiles.split(',');
splitFeatureFiles.forEach(function (feature) {
process.argv.push(feature);
});
}
// add switch to tell cucumber to produce json report files
process.argv.push('-f');
process.argv.push('pretty');
process.argv.push('-f');
process.argv.push('json:' + path.resolve(__dirname, global.reportsPath, 'cucumber-report.json'));
// add cucumber world as first required script (this sets up the globals)
process.argv.push('-r');
process.argv.push(path.resolve(__dirname, 'world.js'));
// add path to import step definitions
process.argv.push('-r');
process.argv.push(path.resolve(program.steps));
// add tag
if (program.tags) {
program.tags.forEach(function (tag) {
process.argv.push('-t');
process.argv.push(tag);
});
}
// add strict option (fail if there are any undefined or pending steps)
process.argv.push('-S');
//
// execute cucumber
//
var cucumberCli = cucumber.Cli(process.argv);
global.cucumber = cucumber;
cucumberCli.run(function (succeeded) {
var code = succeeded ? 0 : 1;
function exitNow() {
process.exit(code);
}
if (process.stdout.write('')) {
exitNow();
} else {
// write() returned false, kernel buffer is not empty yet...
process.stdout.on('drain', exitNow);
}
});
I must be missing something here. I have a mocha test file that is set up like so:
require('globals');
var library1 = require('library1'),
library2 = require('library2');
it('tests stuff', function() {
...
});
Where the globals file just contains a before and afterEach block, so that they apply to all my test files.
What I'm trying to do is determine, within the before and afterEach blocks, which files that I have require'd in the test file that those blocks are currently running in. So in the example test file I gave, I would need afterEach to output a list that contains globals, library1, and library2.
I have attempted to use Node.js's module.children property, but for some reason that is only returning me globals, and excluding library1 and library2.
Edit: What am I missing that module.children wouldn't be returning library1 and library2?
Here is an example of a script that will parse requires in a file.
var fs = require('fs');
function parseRequires(absPath){
var requiredFiles = [];
var contents = fs.readFileSync(absPath, 'utf8').split('\n');
contents.forEach(function(line){
var re = /(?:require\('?"?)(.*?)(?:'?"?\))/;
var matches = re.exec(line);
if(matches){
requiredFiles.push(matches[1]);
}
});
return requiredFiles;
}
module.exports = parseRequires;
I made a test script in the same directory
var fs = require('fs');
var os = require('os');
function A(){}
var http = require("http");
var parseRequires = require("./parseRequires");
console.log( parseRequires( __dirname + '/testRequires.js') );
results in console: [ 'fs', 'os', 'http', './parseRequires' ]
This is one solution, though I'm sure there is an easier way to do it with nodejs built in functionality
Here is another solution I came up with using require.cache. It involves parsing require.cache for the files that have been required and provides the name of the file that ends up being required
var someModule = require('./someModule');
var path = require('path');
for( var p in require.cache){
console.log( trim( p ) );
}
function trim(p){
var re = /(.*?).js/;
var basename = path.basename( p );
var moduleName = re.exec( basename )[1];
return moduleName;
}
Test files:
someModule.js
var fs = require('fs');
var os = require('os');
var _ = require('lodash');
var test = require('./test');
test.js
var a = require('lodash'),
jQuery = require('jquery');
Running getRequires.js results in
getRequires
someModule
index
test
jquery
Notice that it includes itself, so there would have to be something that trims that out as well.
Also notice index, that comes from lodash
Here is a modification that shows the file paths as well
var someModule = require('./someModule');
var path = require('path');
for( var p in require.cache){
console.log( trim( p ) );
}
function trim(p){
var re = /(.*?).js/;
var basename = path.basename( p );
var moduleName = re.exec( basename )[1];
return [ moduleName, p ];
}
That gets us:
[ 'getRequires',
'/<myroot>/require/getRequires.js' ]
[ 'someModule',
'/<myroot>/require/someModule.js' ]
[ 'index',
'/<myroot>/require/node_modules/lodash/index.js' ]
[ 'test', '/<myroot>/require/test.js' ]
[ 'jquery',
'/<myroot>/require/node_modules/jquery/dist/jquery.js' ]
require is the directory I'm doing the code in.
Let me know about your thoughts on this solutions. There is more to be done but I think this can get you started.
For clarification - this is a question about writing a webpack plugin
How do you use the webpack require inside a webpack plugin?
MyPlugin.prototype.apply = function(compiler) {
var self = this;
compiler.plugin('emit', function(compilation, callback) {
var file = 'example.css';
compilation.fileDependencies.push(file);
var loaderResult = require('style!css!' + file); // <-- is there any way to make this possible?
});
};
After some searching I saw that the text-extract plugin uses a child compilation to use a compiler inside the plugin:
https://github.com/SanderSpies/extract-text-webpack-plugin/blob/be6484f00c46799280b9ec28946faf935cb9ae63/loader.js#L65
In the following example I am using the my-loader to load and compile the input.js file:
MyPlugin.prototype.apply = function(compiler) {
compiler.plugin('make', function(compilation, callback) {
var outputOptions = {
filename: 'output.js',
publicPath: compilation.outputOptions.publicPath
};
var childCompiler = compilation.createChildCompiler('MyPluginCompilation', outputOptions);
childCompiler.apply(new NodeTemplatePlugin(outputOptions));
childCompiler.apply(new LibraryTemplatePlugin('result', 'var'));
childCompiler.apply(new NodeTargetPlugin());
childCompiler.apply(new SingleEntryPlugin(this.context, 'my-loader!input.js'));
childCompiler.runAsChild(callback);
});
};