Override JSHint Options by using the Grunt Command-Line - command-line

By calling
grunt jshint:path_to_file
I want to override the default JSHint configuration
grunt.initConfig({
jshint: {
options: {
curly: true,
eqeqeq: true,
eqnull: true,
browser: true,
globals: {
jQuery: true
}
},
all: ['Gruntfile.js', 'Scripts/src/**/*.js']
}
});
and only include that specific file.
"grunt jshint path_to_file" would also be okay yet I do not want to use the
grunt jshint --file=filePath
grunt.option function unless it can do what I need.
Is this achievable somehow?

The spirit of grunt is more to code which files to use in the gruntfile itself than specifying it on the command line.
So we would need more details on why you want to do that. I imagined 2 possibilities:
you only want to work on a subcomponent: in that case, you would declare different targets for each and call the targets from the command line: grunt jshint component1 with in your Gruntfile:
jshint: {
component1: [filePath1],
component2: [filePath2]
}
it's a performance issue: you only want to jshint some files because only them changed. In that case, combine grunt-contrib-watch (to run jshint on file change) and grunt-newer (to only run on the modified files)

Related

Requiring config.js file in VSCode extension with absolute path (e.g. "C:\...") does not work

I am developing the Argdown VSCode extension. The Argdown parser can be configured using either argdown.config.json files or argdown.config.js files exporting a config object. Using Javascript files is the easiest way to allow users to add custom plugins to the Argdown parser.
If the user tells the parser to use a Javascript file, the file is loaded using import-fresh, (which uses node's require, but deletes the cached version.
Using the Argdown commandline tool (#argdown/cli) this works fine, but in the VSCode extension the module of the config file can not be found. The extension is using absolute file paths to require the config module (e.g. "C:\Users\my-username\projects\my-argdown-project\argdown.config.js"). These paths work with import-fresh outside of the VScode extension.
Is there a security restriction for VSCode extensions that does not allow to require modules with absolute file paths? Or is there some other reason why this does not work?
This was not related to VSCode. The problem was caused by bundling up import-fresh with webpack. I thought that webpack would ignore dynamic imports, but it did not.
I was lucky: Since last month, webpack supports "magic comments" for require (not only for import). So I can use:
require(/* webpackIgnore: true */ file);
You have to activate magic comments support in your webpack config:
module.exports = {
parser: {
javascript: {
commonjsMagicComments: true,
},
},
}
Now the next question is how to add the magic comments to the import-fresh package. For that I used the string-replace-loader:
module.exports = {
module: {
rules: {
{
enforce: "pre",
test: /import-fresh[\/\\]index\.js/,
loader: "string-replace-loader",
options: {
search:
"return parent === undefined ? require(filePath) : parent.require(filePath);",
replace:
"return parent === undefined ? require(/* webpackIgnore: true */ filePath) : parent.require(/* webpackIgnore: true */ filePath);",
},
},
}
}
}
After that, I could load the argdown.config.js files again, even after bundling everything with webpack.

How do I disable babel minification when not in production?

I am using babelify and babili for JS minification, via gulp:
// Now run the watchifys function for this bundle
watchifysForBundle[jsBundle]
// Note: we don't use any babel presets - instead we just write code in what evergreen browsers support
.transform(babelify, {
presets: ['babel-preset-babili'],
ignore: ['buffer']
})
However I can't seem to find how to pass the options to check NODE_ENV and disable babeli when not in production. The babelify docs don't seem to help, even with this common use case.
How can I disable babelify minification when not in production?
Babili is deprecated and has been renamed to babel-minify, so you should be using that instead.
npm install babel-preset-minify --save-dev
To disable the minification in development you simply don't use the babel-preset-minify (or babel-preset-babili for that matter). As you're using Gulp you can use everything Node.js has to offer to decide which presets you want to include, which means that you can check process.env.NODE_ENV and decide whether you want to include the minify preset.
watchifysForBundle[jsBundle]
.transform(babelify, {
presets: process.env.NODE_ENV === 'production' ? ['minify'] : [],
ignore: ['buffer']
})
An alternative would be to use Babel's env option (not to confuse with babel-preset-env), which uses the configuration that matches the value of BABEL_ENV or NODE_ENV if no BABEL_ENV was defined. This approach is shown in babel-preset-minify - Usage.
{
"env": {
"production": {
"presets": ["minify"]
}
}
}
The env option is not really recommended and mainly exists because .babelrc is JSON and there is no good way to define conditional configurations. This will change in Babel 7 which allows a .babelrc.js config where you have the full power of Node.js and that means you could do the same thing as with Gulp.
To avoid minification, don't use uglify
gulp.task('build:js', function(){
return browserify(
'test.js'
)
.transform('babelify',{
presets: ['#babel/preset-env']
})
.bundle()
.pipe(source('test.js'))
.pipe(buffer())
.pipe(uglify())
.pipe(gulp.dest('destpath'));
});
Instead try--- adding option- compact:false, global:true in babelify
gulp.task('build:js', function(){
return browserify(
'test.js'
)
.transform('babelify',{
presets: ['#babel/preset-env'],
compact: false,
global: true
})
.bundle()
.pipe(source('test.js'))
.pipe(buffer())
.pipe(gulp.dest('destpath'));
});

Gulp + Browserify: CoffeeScript not loading when loading files from node_modules

After setting up the folder structure for my Gulp project, I was wondering how to do paths in browserify, and found this page: https://github.com/substack/browserify-handbook#organizing-modules. It recommends putting common application parts in a subfolder of node_modules. This appears to be working, it's getting the files, but it's not applying my coffeeify transform, so it's throwing errors because it's trying to interpret them as JS. Any ideas how to fix this? This is my browserify config:
browserify: {
// Enable source maps
debug: true,
// Additional file extentions to make optional
extensions: ['.coffee', '.hbs'],
// A separate bundle will be generated for each
// bundle config in the list below
bundleConfigs: [{
entries: src + '/javascript/app.coffee',
dest: dest,
outputName: 'app.js'
}, {
entries: src + '/javascript/head.coffee',
dest: dest,
outputName: 'head.js'
}]
}
and these are the relevant bits form my package.json.
"browserify": {
"transform": [
"coffeeify",
"hbsfy"
]
}
Transfroms aren't applied to files in node_modules unless they are marked as being global: https://github.com/substack/node-browserify#btransformtr-opts. If you choose to make it global, be warned, the documentation suggests against it:
Use global transforms cautiously and sparingly, since most of the time
an ordinary transform will suffice.
You won't be able to specify the tranform in package.json:
You can also not configure global transforms in a package.json like
you can with ordinary transforms.
The two options are programmatically, by passing {global: true} as options or at the command line with the -g option:
browserify -g coffeeify main.coffee > bundle.js

How do I run only certain tests in karma?

I have karma config set up correctly, config file, running in the background, just great. As soon as I change and save a file, it reruns the tests.... all 750 of the unit tests. I want to be able to run just a few. Short of manually hacking the config file or commenting out hundreds of tests across many files, is there any easy way to do it?
E.g. when running command line server tests using say mocha, I just use regexp: mocha -g 'only tests that I want'. Makes it much easier to debug and quickly check.
So now I feel foolish. mocha supports a very narrow version of regexp matching.
This runs all tests
describe('all tests',function(){
describe('first tests',function(){
});
describe('second tests',function(){
});
});
This runs just 'first tests'
describe('all tests',function(){
describe.only('first tests',function(){
});
describe('second tests',function(){
});
});
You can also do it.only()
I should have noticed that. Sigh.
You can do that at karma startup time unfortunately, not at runtime.
If you want to change it dynamically you have to put some more effort.
Say you want to focus on a specific set/suite of tests from the beginning, on the karma-mocha plugin page there's this snippet of code to do what you want:
module.exports = function(config) {
config.set({
// karma configuration here
...
// this is a mocha configuration object
client: {
// The pattern string will be passed to mocha
args: ['--grep', '<pattern>'],
...
}
});
};
In order to make the <pattern> parametric you have to wrap the configuration file in a Configurator that will listen CLI and customize the karma configuration for you.
Have a look to this SO answer to know how to setup a very simple Configurator.
I have same question and this is my workround by a little change on karma.conf.js.
In fact, take an argument from command line and modify the pattern in "files".
I use minimist to parse the argument list.
In config file:
/* Begin */
var minimist = require('minimist');
var argv = minimist(process.argv);
var testBase="test/unit";
var testExt=".spec.js";
var unitTestPattern = testBase+'/**/*'+testExt;
if ("test" in argv){
unitTestPattern = testBase+"/"+argv["test"]+testExt;
}
/* End */
module.exports = function(config){
config.set({
//....
files : [
//....
unitTestPattern, //place here
// 'test/unit/**/*.spec.js', //replace this
//....
],
//....
});
};
run in command prompt:
karma start test/karma.conf.js --single-run --test #TEST_CASE_FILE#
a nice extension that can help here is karma-jasmine-html-reporter-livereload
https://www.npmjs.com/package/karma-jasmine-html-reporter-livereload
or karma-jasmine-html-reporter https://www.npmjs.com/package/karma-jasmine-html-reporter?__hstc=72727564.86845f057bb4d741f59d578059e30644.1443860954685.1453095135802.1453138187458.37&__hssc=72727564.1.1453138187458&__hsfp=2285154675
It creates a debug page in which you can run each test individually. very useful for large projects!
1) In your karma.conf.js get the params from the terminal:
var files = (process.env.npm_config_single_file) ? process.env.npm_config_single_file : 'test/test_index.js';
2) In order to run a single test you will need to set an option object with all your configuration (Without files and preprocessors):
var option = {
webpack: {
// webpack configuration
},
// more configuration......
};
3) Set your files path and preprocessors:
option.files = [
{pattern: files, watch: false}
];
option.preprocessors = {};
option.preprocessors[files] = [ 'webpack', 'sourcemap' ];
// call config.set function
config.set(option);
4) Run in the terminal:
npm test --single_file=**/my-specific-file-spec.js
For more information check this PR:
https://github.com/webpack/karma-webpack/pull/178
There are different ways to do it.
Use --grep option. The disadvantage of this is that all the tests are preprocessed before running the specific test suite.
Use .only method. Disadvantage same as no. 1. Using both 1 and 2 method my node process used to crash often saying out of memory.
Limit the files options for processing. This is super fast.
Limit preprocessing to certain folder like Unit or Integration folder.
For this I have used custom cli option --only and in the karma config
const modules = config.only;
and in the the files pattern
files: typeof modules === 'string ? '[`tests/**/${module}/**/*.(test|spec).js`]: 'tests/**/*.(test|spec).js'
Advantage: Developers can run only certain tests when they make a small change way faster by limiting in the preprocessing phase.
You can also use combination of no.3 and no.1 or 2.

How can I configure Karma to open a browser with command line arguments?

I'm using the Karma Test Runner and I've configured it to use Chrome and PhantomJS like this:
browsers = ['Chrome', 'PhantomJS'];
How can I configure Karma to open these browsers with certain command line arguments, like --diable-web-security in the case of Chrome, and --web-security=no in the case of PhantomJS?
I suppose one option would be to write a custom browser script, but that seems like overkill if there is some feature in Karma I don't know about that handles this case.
Something like this should work:
// karma.conf.js
module.exports = function(config) {
config.set({
browsers: ['Chrome_without_security','PhantomJS_without_security'],
// you can define custom flags
customLaunchers: {
Chrome_without_security: {
base: 'Chrome',
flags: ['--disable-web-security']
},
PhantomJS_without_security: {
base: 'PhantomJS',
flags: ['--web-security=no']
}
}
});
};
More information here: https://github.com/karma-runner/karma-chrome-launcher#configuration
One solution I found, which may not be the most elegant, is to actually modify Karma's launcher scripts for each browser. This has solved the problem.