Run mocha excluding paths - npm

I have this (in gulpfile.js):
var gulp = require("gulp");
var mocha = require("gulp-mocha");
gulp.task("test", function() {
gulp
.src(["./**/*_test.js", "!./node_modules/**/*.js"]);
});
and it works.
I want to replicate the same behavior, excluding "node_modules" folder, from mocha command, running npm test (in package.json):
"scripts": {
"test": "mocha **\\*_test.js !./node_modules/**/*.js*",
}
and it doesn't work.
I'm using Windows.
Any suggestion?

I was able to solve this using globbing patterns in the argument to mocha. Like you I didn't want to put all my tests under a single tests folder. I wanted them in the same directory as the class they were testing. My file structure looked like this:
project
|- lib
|- class1.js
|- class1.test.js
|- node_modules
|- lots of stuff...
Running this from the project folder worked for me:
mocha './{,!(node_modules)/**}/*.test.js'
Which match any *.test.js file in the tree, so long is its path isn't rooted at ./node_modules/.
This is an online tool for testing glob patterns that I found useful.

You can exclude files in mocha by passing opts
mocha -h|grep -i exclude
--exclude <file> a file or glob pattern to ignore (default: )
mocha --exclude **/*-.jest.js
Additionally, you can also create a test/mocha.opts file and add it there
# test/mocha.opts
--exclude **/*-test.jest.js
--require ./test/setup.js
If you want to exclude a particular file type you could do something like this
// test/setup.js
require.extensions['.graphql'] = function() {
return null
}
This is useful when processing extensions with a module loader such as webpack that mocha does not understand.

For Windows users
This script will run perfectly
"test": "mocha \"./{,!(node_modules)/**/}*.test.js\"",
I hope this will help.
cheers!

I'm not a guru on mocha or ant-style pattern but maybe it isn't possible escluding specific path in the mocha command line.
You can put all your test files under a test folder, and set your package.json like this:
"scripts": {
"test": "mocha ./test/**/*_test.js"
}
You can also provide more than one starting folder:
"scripts": {
"test": "mocha ./test/**/*_test.js ./another_test_folder/**/*_test.js"
}

As of 2019 the modern way of configuring Mocha under Node is via config file in your project root (e.g. via .mocharc.js).
Here is the example of the .mocharc.js that
rederfines the default test directory (spec key) and
excludes the example (or can be any experimental tests) from the overall suite (exclude key).
module.exports = {
'spec': 'src/front/js/tests/**/*.spec.js',
'exclude': 'src/front/js/tests/examples/*.spec.js',
'reporter': 'dot'
};
As you may see there can be more options used in the config. In part they are just replicas of Mocha CLI options. Just look up ones what you like and try to use within .mocharc.js (use camelCase for dash-comprising CLI options). Or see the config examples.

As suggested in a comment by #thebearingedge, in the end I put ALL the source files (with the relative test files) in a new "src" dir.
In this way I can define the root for tests with a path that exclude by default the "node_modules" folder.
.
├── src
├── fileA.js
├── fileA_test.js
├── fileB.js
├── fileB_test.js
├── node_modules
├── ...
I had to update the path in the package.json, gulpfile.js and in some batch files that I use as utilities.
Changes in gulpfile.js:
.src(["./src/**/*_test.js"]);
and in package.json:
"test": "mocha src\\**\\*_test.js",
Simple change and it works.
I'm free to choose whatever naming conventions I like.
Each test files remain close to the relative JS file.

I had a spec directory containing all my specs. Within that directory, I had several sub-directories, one of which was the e2e specs directory. In that scenario, I used the mocha specs $(find specs -name '*.js' -not -path "specs/e2e/*") command to run all my tests ignoring those within the e2e directory.

Related

Does package.json support compound variables?

A project that respects the semver directory structure for build artefacts is beginning soon, and package.json or .nmprc would seem to be the right place to define this metadata. This is some preliminary code that demonstrates how the goal is intended to be achieved:
{
"name": "com.vendor.product"
, "version": "0.0.0"
, "directories": {
"build": "./out"
}
, "main": "./${npm_directories_build}/${npm_package_name}/${npm_package_version}/${npm_package_name}.js"
, "exports": "${npm_package_main}"
, "scripts": {
"echo": "echo\"${npm_package_exports}\""
}
}
I expected
npm run echo
to print the compound variable result to standard output,
./out/com.vendor.product/0.0.0/com.vendor.product.js
but instead, it prints the literal text
${npm_package_export}
I attempted to use array variables in .npmrc
outpath[]=./out
outpath[]=/${npm_package_name}
outpath[]=/${npm_package_version}
But
...
{
"echo": "echo \"${npm_config_outpath}\""
}
Simply prints an empty newline
It was expected that package.json supports compound variables, but this assumption is now in question. I have checked documentation, but either I am missing something or such is not defined. Long hand repetition of the same data is to be avoided (e.g. multiple references to package variables in order to make a single path). It is intended for package name and version to always dictate the location of the build files in a reliable and predictable manner.
If compound variables are not supported, could you clarify how .npmrc array variables actually work? Failing that, could you recommend an alternative method to achieve the same ends? Many thanks!
Searched documentation:
https://docs.npmjs.com/misc/config
https://docs.npmjs.com/files/npmrc
https://docs.npmjs.com/configuring-npm/npmrc.html
https://docs.npmjs.com/files/package.json#config
http://doc.codingdict.com/npm-ref/misc/config.html#config-settings
https://github.com/npm/ini
Short Answer:
"Does package.json support compound variables?"
Unfortunately no, not for the way you are wanting to use them. It only has package json vars which can be used in npm scripts only. For example on *Nix defining the echo script as:
"echo": "echo $npm_package_version"
or on Windows defining it as:
"echo": "echo %npm_package_version%"
will print the version e.g. 0.0.0.
Note: cross-env provides a solution for a single syntax that works cross-platform.
You certainly cannot include parameter substitution ${...} elsewhere in package.json fields except for the scripts section.
Additional info:
Regarding your subsequent comment:
How array values defined in .npmrc can be used in package.json
AFAIK I don't think you can. For example let's say we;
Save this contrived .npmrc in the root of the project directory.
.npmrc
quux[]="one"
quux[]="two"
quux[]="three"
foo=foobar
Then cd to the project directory and run the following command to print all environment variables:
npm run env
As you can see, the npm_config_foo=foobar environment variable has been added by npm. However for the quux array there is no npm_config_quux=[ ... ] environment variable added.
So, in npm scripts using package.json vars the following does work:
"echo": "echo $npm_config_foo"
However the following, (for referencing the array), does not - simply because it does not exist;
"echo": "echo $npm_config_quux"
The ini node.js package:
Maybe consider investigating the ini node.js package that npm utilizes for parsing .npmrc files. For example:
If you run the following command to install the package in your project:
npm i -D ini
Then define the npm echo script as per this:
"scripts": {
"echo": "node -e \"var fs = require('fs'), ini = require('ini'); var config = ini.parse(fs.readFileSync('./.npmrc', 'utf-8')); console.log(config.quux)\""
}
Note it uses the nodejs command line option -e to evaluate the JavaScript code. It essentially executes the following:
var fs = require('fs'),
ini = require('ini');
var config = ini.parse(fs.readFileSync('./.npmrc', 'utf-8'));
console.log(config.quux);
Then given the contrived .npmrc file that I mentioned previously when running:
npm run echo
it will print:
[ 'one', 'two', 'three' ]

Assign a random number (UUID) value to a environment variable in npm script

I'd like to add a UUID argument when calling my npm script. Each time the script is called, I'd like to generate a new number. It should look like:
"build": "cross-env UUID=unique_number ng build"
The only thing I need is generating the unique_number here. I tried to use the uuid package but I don't know how to fire it in the script and pass the number as the argument.
tl;dr As you're question shows the use of cross-var I've assumed a cross-platform solution is required. In which case refer to the Solution A. However refer to either Solution B or C if my assumption is incorrect.
Solution A: Cross Platform (Windows/Linux/macOS...)
Fo a cross platform solution, (i.e. one that runs successfully on Windows, Linux, and macOS...), you'll need to utilize nodejs to achieve your requirement. There are a couple of different ways to approach this as described in the following two sub-sections titled:
Using an external nodejs (.js) file
Inlining your JavaScript in package.json.
Note both approaches are effectively the same
Using an external nodejs (.js) file
Create a nodejs utility script. Let's name the file run-ng-build.js and save it in the root of your project directory, i.e. in the same directory where package.json currently resides:
run-ng-build.js
const uuid = require('uuid/v1');
const execSync = require('child_process').execSync;
process.env.UUID = uuid();
execSync('ng build', { stdio: [0, 1, 2]} );
In the scripts section of your package.json replace your current build script with the following:
package.json
"scripts": {
"build": "node run-ng-build"
}
Explanation:
In run-ng-build.js we require the uuid package and the nodejs built-in execSync().
To create the environment variable named UUID we utilize the nodejs builtin process.env, and assign a uuid value to it by invoking uuid().
We then invoke the ng build command using execSync.
The options.stdio option configures the pipes between the parent and child process - [0, 1, 2] effectively inherit's stdin, stdout, and stderr.
Inlining your JavaScript in package.json.
Alternatively, you can inline your nodejs/JavaScript code in the scripts section of your package.json.
In the scripts section of your package.json replace your current build script with the following instead:
package.json
"scripts": {
"build": "node -e \"process.env.UUID = require('uuid/v1')(); require('child_process').execSync('ng build', { stdio: [0, 1, 2]} );\""
}
Explanation:
This is effectively the same as the aforementioned solution that utilized a separate .js file, however the use of a separate nodejs script/file is now redundant.
The nodejs command line option -e is utilized to evaluate the inline JavaScript.
Important The cross-env package is redundant utilizing either of the two aforementioned solutions. To uninstall it run: npm un -D cross-env via your CLI.
Solution B: *Nix platforms only (Linux/MacOS...)
For *nix platforms only it becomes very terse, you can just define your build script in package.json as follows:
package.json
"scripts": {
"build": "cross-env UUID=$(uuid) ng build"
}
This utilizes a Bash feature known as command substitution, i.e. $(uuid). However, if *nix is the only platform you need to support, then cross-env is really not necessary. Use the built-in export feature instead. For instance:
package.json
"scripts": {
"build": "export UUID=$(uuid) && ng build"
}
Solution C: Windows only (cmd.exe)
On Windows (only) running via Command Prompt or PowerShell you can do the following:
package.json
"scripts": {
"build": "FOR /F %U IN ('uuid') DO cross-env UUID=%~U node -e \"process.env.UUID = require('uuid/v1')(); require('child_process').execSync('ng buuld', { stdio: [0, 1, 2] });\""
}
This is similar to the first example shown in Solution B however command substitution is achieved (very) differently in cmd.exe. See this answer for further explanation.

How can I get express static to work when starting from another folder

I have the following structure
-project
-packages
-express-project
-static
-dist
-index.js
When I run from express-project everything works fine. However, when I run from project like this node packages\express-project\dist\index.js it doesn't map the static folder properly so I get 404s for the resources. My static is set like this this.express.use(express.static(path.join(__dirname, "static")));
How can I start it from another folder?
Update
import path from "path";
const __dirname = path.resolve();
So this worked...
In my package.json I made my start "start": "cd .\\packages\\express-project && node dist\\index.js". Then I can run npm start and it works just as I would expect and after it is done it is still in project.

How to avoid subdirectory output in node-sass?

I have following setup under my project:
/assets/scss has many SCSS files organized under different subdirectories; including a root global.scss file. As you can imagine, global.scss will only have #imports.
/assets/css is set as output directory. I am trying to output only one file under this folder - global.css.
package.json has this command
"scripts": {
"scss": "node-sass --watch assets/scss/styleguide.scss -o assets/css --recursive"
}
When I run npm run scss it outputs subdirectory CSS files as well. Does anyone know how to avoid output of subdirectory sass files?
Thanks in advance!
You are passing the --recursive argument to node-sass. That will mean that node-sass will search recursively on every directory under assets/scss and will compile all the scss files found. To avoid that behavior just remove the --recursive option:
"scripts": {
"scss": "node-sass --watch assets/scss/styleguide.scss -o assets/css"
}
More about node-sass usages and options can be found here.

How to setup environments for Cypress.io

I am taking a swing at setting up a test suite for my company's web app. We use four environments at the time (Production, Regression, Staging, Development). I have environment variables setup in my cypress.json file but I would like to be able to switch my environment for example from regression to development and force cypress to change the baseURL to my new environment as well as point to a different cypress.json file that has development variables. The documentation around environments on cypress.io is a little confusing to me and I'm not sure where to start.
I have cypress running in different environments using package.json's scripts. You can pass in env vars before the cypress command. It would look something like:
"scripts": {
"cypress:open:dev": "CYPRESS_BASE_URL=http://localhost:3000 cypress open",
"cypress:open:prod": "CYPRESS_BASE_URL=http://mycompanydomain.com cypress open",
"cypress:run:dev": "CYPRESS_BASE_URL=http://localhost:3000 cypress run",
"cypress:run:prod": "CYPRESS_BASE_URL=http://mycompanydomain.com cypress run",
}
If you want to make 4 separate cypress.json files instead, you could have them all named according to environment and when you run an npm script that corresponds with that environment just copy it to be the main cypress.json when you run the tests.
Files:
./cypress.dev.json
./cypress.prod.json
./cypress.staging.json
./cypress.regression.json
npm scripts:
"scripts": {
"cypress:run:dev": "cp ./cypress.dev.json ./cypress.json; cypress run;"
}
Update:
I wrote this while cypress was still in beta. Using the config flag seems like a cleaner option:
https://docs.cypress.io/guides/guides/command-line.html#cypress-run
npm scripts:
"scripts": {
"cypress:run:dev": "cypress run -c cypress.dev.json;"
}
You can pass the config file to be used with --config-file param as:
Syntax:-
cypress open --config-file <config-file-name>
If you have different environment files then it should be as:
"scripts": {
"cypress:open:prod": "cypress open --config-file production-config.json",
"cypress:open:stag": "cypress open --config-file staging-config.json",
},
If you see above commands we are telling the cypress to use production-config.json file for prod environment and similarly staging-config.json for stag environment.