I have a Grunt task called "test". The responsibility of this task is the execute end-to-end tests. Currently, I can run my tests if I start the grunt-protractor-runner in a seperate command-line window. I start that by executing the following command:
node_modules\grunt-protractor-runner\node_modules\protractor\bin\webdriver-manager start
My question is, is there a way I can start this as part of my grunt task if the webdriver-manager hasn't already been started? If so, how? I've seen tasks like grunt-contrib-connect, yet I don't see how those allow me to get my test server running as part of a task.
protractor will take care of starting the selenium server for you if you don't define seleniumAddress in the protractor config file.
It seems like you're pretty much there. Your 'test' task should first start up a server using grunt-contrib-connect to serve the app you want to test. That task should then use grunt-protractor-runner to start protractor and protractor will start the selenium server (assuming seleniumAddress=null).
Something like the following:
connect: {
test: {
options: {
port: 9001,
base: [
'app'
]
}
}
}
protractor: {
options: {
keepAlive: true,
configFile: 'protractor.conf.js'
},
run: {}
}
grunt.registerTask('test', [
'connect:test',
'protractor:run'
]);
To start webdriver automatically put following in your grunt file:
grunt.initConfig: ({
..
protractor: {
test: {
options: {
configFile: 'protractor.conf.js'
}
}
},
..
}
..
grunt.registerTask('test': ['protractor:test']);
and following in your ./protractor.conf.js
var chromeDriver =
'./node_modules/protractor/selenium/chromeDriver';
var platform = require('os').platform();
var fs = require('fs');
var platformChrome = chromeDriver + '-' + platform;
if (fs.existsSync(platformChrome)){
log.console('Using ' + platform + ' specific driver ');
chromeDriver = platformChrome;
}
exports.config = {
directConnect: true,
chromeDriver: chromeDriver,
// Capabilities to be passed to the webdriver instance
capabilities: {
'browserName': 'chrome',
'chromeOptions': {
args: ['--no-sandbox']
}
},
..
}
Start your grunt server:
grunt serve;
and in another terminal start your tests:
grunt test
Related
If you bundle react-pdf for the browser using esbuild today you will run into errors that prompt you to build for platform=node because zlib and stream are not available in the browser environment.
I did find a conversation around how to swap this when using vite but I'm curious if others have created a shim for esbuild that offers something equivalent
process: "process/browser",
stream: "vite-compatible-readable-stream",
zlib: "browserify-zlib"
the version I'm using today: #react-pdf/renderer": "^2.0.21"
edit
It just so happens a node modules polyfill exists for esbuild and you should be able to configure this as a plugin
https://github.com/remorses/esbuild-plugins#readme
npm i -D #esbuild-plugins/node-globals-polyfill
and then w/ esbuild you can pass it in like so
https://esbuild.github.io/plugins/#using-plugins
More after I confirm this is working end to end
I was able to achieve this using esbuild v0.14.10 and 2 plugins
npm i -D #esbuild-plugins/node-modules-polyfill
npm i -D #esbuild-plugins/node-globals-polyfill
With a build configuration like this
const esbuild = require('esbuild')
const globalsPlugin = require('#esbuild-plugins/node-globals-polyfill')
const modulesPlugin = require('#esbuild-plugins/node-modules-polyfill')
const args = process.argv.slice(2)
const deploy = args.includes('--deploy')
const loader = {
// Add loaders for images/fonts/etc, e.g. { '.svg': 'file' }
}
const plugins = [
globalsPlugin.NodeGlobalsPolyfillPlugin({
process: true,
buffer: true,
define: { 'process.env.NODE_ENV': deploy ? '"production"' : '"development"' },
}),
modulesPlugin.NodeModulesPolyfillPlugin(),
]
let opts = {
entryPoints: ['js/app.js'],
bundle: true,
target: 'es2017',
outdir: '../priv/static/assets',
logLevel: 'info',
inject: ['./react-shim.js'],
loader,
plugins
}
if (deploy) {
opts = {
...opts,
minify: true
}
}
const promise = esbuild.build(opts)
I am using YO lessapp project, "grunt-contrib-connect" helps me to start a node js server on 9000 port. Whenever I run grunt serve (start the server) the service is aborted due to the below warning.
Running "connect:livereload" (connect) task
Warning: connect.static is not a function Use --force to continue.
The exact error took place in the below function in Gruntfile.js
livereload: {
options: {
middleware: function(connect) {
return [
connect.static('.tmp'),
connect().use('/bower_components', connect.static('./bower_components')),
connect.static(config.app)
];
}
}
},
I have installed
npm install grunt-contrib-connect --save-dev,
npm install serve-static --save-dev
I came across few post, some suggest to turn off the firewall but no luck.
I know there is something to do with my machine or npm/node/connect version conflicts, because I tried to run the same app from other machine and it works fine.
System configuration :
Windows 7 Professional
Node -v4.1.2
npm -v2.14.4
connect#3.4.0
I have installed connect and serve-static based upon the post nodejs connect cannot find static, but still the same
Any help? Thanks in Advance
You have to install connect and serve-static:
npm install --save-dev grunt-contrib-connect serve-static
And then you have to import serve-static in Gruntfile.js:
module.exports = function (grunt) {
...
var serveStatic = require('serve-static');
grunt.initConfig({
...
connect: {
...
livereload: {
options: {
middleware: function(connect) {
return [
serveStatic('.tmp'),
connect().use('/bower_components', serveStatic('./bower_components')),
serveStatic(config.app)
];
}
}
}
From version 0.11.x, the new grunt-contrib-connect does not support connect.static and connect.directory.
You should install serve-static(for serve static files) and serve-index (for Serves pages that contain directory listings for a given path).
like this:
var serveStatic = require('serve-static');
var serveIndex = require('serve-index');
Use serveStatic instead connect.static
and
serveIndex instead connect.directory
grunt.initConfig({
connect: {
options: {
test: {
directory: 'somePath',
middleware: function(connect, options){
var _staticPath = path.resolve(options.directory);
return [serveStatic(_staticPath), serveIndex(_staticPath)]
}
}
}
}
})
I am trying to launch protractor multiple times from a grunt task like this
grunt.registerTask('makeapps', 'Create Apps', function(count) {
console.log('value of count is' + count);
var done=this.async();
for(var i=1 ;i <= count; i++)
{
grunt.initConfig({
protractor: {
options: {
configFile: "./createAppConf.js", // Default config file which includes protractor tests and other dependencies such as HTML protractor screenshot reporter
keepAlive: true, // If false, the grunt process stops when the test fails.
noColor: false, // If true, protractor will not use colors in its output.
args: {
// Arguments passed to the command
}
},
your_target: { // Grunt requires at least one target to run so you can simply put 'all: {}' here too.
options: {
configFile: "createAppConf.js", // // Default config file which includes protractor tests and other dependencies such as HTML protractor screenshot reporter
args: {} // Target-specific arguments
}
},
},
})
grunt.loadNpmTasks('grunt-protractor-runner');
}
done();
});
I run the task like this
grunt makeapps:3 protractor
I am able to launch protractor and the test once only. I am not able to launch it multiple times. Can anyone please tell me what I am doing wrong?
Your solution would run the function you have and the protractor task defined alongside it. Grunt is more declarative, it first collects task definitions and then you can trigger them.
What about using https://github.com/sindresorhus/grunt-concurrent or https://github.com/iammerrick/grunt-parallel?
I want to write a grunt task, which will run some tests. It has 3 steps:
Start a server asynchronously
Run a task to check if the server is ready, by visiting the homepage of that server. It will check the homepage every second, until get status code 200, or fail if can't get that in 10 seconds.
If task 2 is successful, run some test files
I can do the first step by grunt-shell-spawn, but I don't know how to the second task effectively
using grunt-contrib-connect isnt an option, or what server do you want to start?
if not just use grunt-wait-server
so your gruntfile would look something like this
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
shell: {
command: 'whatever your startup-server-script is',
options: {
async: true
}
},
waitServer: {
server: {
options: {
url: 'http://yourserverurl:yourserverport'
}
}
},
whateverTestTask: {}
});
grunt.loadNpmTasks('grunt-shell-spawn');
grunt.loadNpmTasks('grunt-wait-server');
grunt.loadNpmTasks('grunt-whatever-test-task');
// default task
grunt.registerTask('default', ['shell', 'waitServer', 'whateverTestTask']);
};
I am either blanking out or it is more complex that it should have been.
I am trying to run grunt-init from a Grunt task, something like this:
grunt.registerTask('init', 'Scaffold various artifacts', function(param) {
// analyze `param` and pass execution to `grunt-init`
// run `grunt-init path/to/some/template/based/on/param/value`
});
The part of analysis of the param is, of course, not the issue. It's running the grunt-init that is.
Running grunt-init directly in the same folder as the below attempts works fine.
I've tried the following methods (path to template is inlined for shortness of the code), all to no avail:
grunt-shell
shell: {
init: {
options: {
stdout: true,
callback: function(err, stdout, stderr, cb) {
...
}
},
command: 'grunt-init path/to/some/template/based/on/param/value'
}
}
and then:
grunt.registerTask('init', 'Scaffold various artifacts', function(param) {
grunt.task.run(['shell:init']);
});
and in command line:
grunt init
or from command line directly:
grunt shell:init
grunt-exec
exec: {
init: {
cmd: 'grunt-init path/to/some/template/based/on/param/value',
callback: function() {
...
}
}
}
and then:
grunt.registerTask('init', 'Scaffold various artifacts', function(param) {
grunt.task.run(['exec:init']);
});
and in command line:
grunt init
or from command line directly:
grunt exec:init
Node's exec
grunt.registerTask('init', 'Scaffold various artifacts', function(param) {
var exec = require('child_process').exec;
exec('grunt-init path/to/some/template/based/on/param/value', function(err, stdout, stderr) {
...
});
});
and in command line:
grunt init
Nothing.
There were various attempts, best of which would print the first line of grunt-init prompt:
Running "init" task
And that's it.
What am I missing? Should I have connected the stdout somehow?
Create a child process with grunt.util.spawn. You can make it asynchronous and set stdio to 'inherit' so that any template prompts can be answered. Also, you should set a cwd or else it will try to overwrite your existing Gruntfile.js!
grunt.registerTask('init', 'Scaffold various artifacts', function(grunt_init_template) {
var done = this.async();
grunt.util.spawn({
cmd: 'grunt-init',
args: [grunt_init_template],
opts: {
stdio: 'inherit',
cwd: 'new_project_dir',
}
}, function (err, result, code) {
done();
});
});
I think I found a way, but it feels hack-ish to me. I am going to answer this, but, please give yours too.
It can be done using grunt-parallel
grunt-parallel
where task is defined using:
parallel: {
init: {
options: {
stream: true
},
tasks: [
{cmd: 'grunt-init'}
]
}
}
and init task is:
grunt.registerTask('init', 'Scaffold various artifacts', function(param) {
// calculate path based on `param`
...
grunt.config.set('parallel.init.tasks.0.args', ['path/to/some/template/based/on/param/value']);
grunt.task.run(['parallel:init']);
});
then, running the following in command line:
grunt init:<some param indicating template type or similar>
properly runs grunt-init.