I am trying to instrument my code to get some coverage up and running, but something is slipping through my fingers.
I launch istanbul with:
node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha -- -u exports -R spec
And my mocha.opts looks like this:
app/assets/javascripts/components/**/*-mocha.jsx
--compilers jsx:mocha/compiler.js
Everything seems to run fine (the tests run, at least), but the only coverage that I get is on the files used to compile the JSX to JavaScript (used in compiler.js
compiler.js 100%
jsx-stub-transform.js 65%
Terribly useful...
Any ideas?
I use gulp-jsx-coverage.
Here is my config as an example:
var jsxCoverage = require('gulp-jsx-coverage');
gulp.task('test', ['lint', 'env:test'], jsxCoverage.createTask({
src: ['src/**/*_test.js', 'src/**/*_test.jsx'], // will pass to gulp.src as mocha tests
istanbul: { // will pass to istanbul
coverageVariable: '__MY_TEST_COVERAGE__',
exclude: /node_modules|tests|._test/ // do not instrument these files
},
transpile: { // this is default whitelist/blacklist for transpilers
babel: {
include: /\.jsx?$/,
exclude: /node_modules/
}
},
coverage: {
reporters: ['text', 'lcov', 'cobertura'], // list of istanbul reporters
directory: 'coverage' // will pass to istanbul reporters
},
mocha: { // will pass to mocha
reporter: 'spec'
},
babel: { // will pass to babel
sourceMap: 'inline', // get hints in HTML coverage reports
plugins: []
}
}));
* UPDATE *
Over time I decided to stop using gulp-jsx-coverage. My tests use the babel-rewire-plugin, and gulp-jsx-coverage was not instrumenting my files correctly, resulting in a coverage report that included a bunch of untested generated code. No bueno.
See my 2nd answer for my current set up.
I am using mocha and isparta directly with Babel 6 as follows:
npm test command
BABEL_ENV=test babel-node node_modules/isparta/bin/isparta cover _mocha
.babelrc
{
"plugins": [
"add-module-exports",
"transform-decorators-legacy",
"transform-runtime"
],
"presets": [
"es2015",
"react",
"stage-0"
],
"env": {
"test": {
"plugins": [
"rewire"
]
}
}
}
test/mocha.opts
--compilers js:babel-core/register
--require test/init.js
src/**/*_test.js*
test.init.js
'use strict';
require('mock-require')('clappr');
require('testdom')('<html><body></body></html>', {
React: 'react',
localStorage: 'localStorage'
});
.istanbul.yml
instrumentation:
root: src
excludes: ['*_test.js']
select dependencies from package.json
"babel-cli": "^6.7.5",
"babel-core": "^6.7.2",
"babel-eslint": "^5.0.0",
"babel-loader": "^6.2.4",
"babel-plugin-add-module-exports": "^0.1.2",
"babel-plugin-rewire": "^1.0.0-rc-2",
"babel-plugin-runtime": "^1.0.7",
"babel-plugin-syntax-jsx": "^6.5.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-runtime": "^6.6.0",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-0": "^6.5.0",
"babel-register": "^6.7.2",
"babel-runtime": "^5.8.34",
"babel-template": "^6.7.0",
"babel-types": "^6.7.2",
"isparta": "^4.0.0",
"mocha": "^2.4.5",
A note on .JSX files
I renamed all of my .JSX files to .JS, and here's why:
I use codecov for hosted coverage reporting. This exposed the fact that while coverage/lcov-report/index.html showed the correct coverages, something in the JSON coverage files is missing for .JSX files. I was never able to figure it out. As far as I can tell, it's a bug in isparta or istanbul. I also tried istanbul#1.0.0-alpha.2 and found it had the same issue.
React used to recommend naming files .JSX for the benefit of transform utilites and editors. This is no longer a recommendation. As far as I can tell, it just doesn't matter anymore.
Since switching to .JS, I haven't seen any issues with tools including Atom and IntelliJ.
If you don't want to rename your files, you can add the following to my examples from above:
In the script, after isparta cover, add --include \"src/**/*_test.jsx\".
To .istanbul.yml, add
extensions:
- .js
- .jsx
Related
I would like to create a simple npm package and import that into svelte components, however, I cannot seem to use index files to import deeply nested files, e.g.
// routes/test.svelte
<script lang="ts">
import { Test } from '#my-co/my-lib/dist/folder1/folder2/test';
const test = new Test('foo', 'bar');
</script>
works, but
// routes/test.svelte
<script lang="ts">
import { Test } from '#my-co/my-lib';
const test = new Test('foo', 'bar');
</script>
does not. I have the following in the index.ts file in my npm module:
export { Test } from './folder1/folder2/test';
This strangely also does seem to work in ssr (dev server output in console seems to pick the import {Test} from '#my-co/my-lib' correctly), but not in the browser, where I get the error that Test is not a constructor...
Npm library package.json:
{
"name": "#myco/my-lib",
"version": "0.0.2",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"prepare": "npm run build"
},
"author": "redacted",
"license": "ISC",
"dependencies": {
"#types/rosie": "0.0.40",
"#types/slug": "^5.0.3",
"rosie": "^2.1.0",
"slug": "^5.1.1"
}
}
Npm library tsconfig
{
"compilerOptions": {
"declaration": true,
"strictNullChecks": true,
"outDir": "dist",
"moduleResolution": "node",
"module": "es2015",
"target": "es5",
"sourceMap": true,
"lib": ["es2015", "dom"],
"rootDir": "src"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
Lib structure
my-lib/
| dist/
| node_modules/
| src/
| | folder1/
| | | folder2/
| | | | test.ts
test.ts
export class Test {
foo: string;
bar: string;
constructor(foo: string, bar: string) {
this.foo = foo;
this.bar = bar;
}
testMe() {
console.log("foobar", this.foo, this.bar);
}
}
The svelte-kit package command should automatically do everything for you (docs).
This Youtube video should explain everything.
The steps it provides to publish are:
npm init svelte#next project-name
cd project-name
Create component
npx svelte-kit package
cd package
Login to npm / create an account
npm publish --access public
While Caleb's answer did not really help in my case, I think it was a bit of a pointer as to what was going wrong. I did not intend to write a svelte-focused Component library, but rather a general model/factory library to be reused between the front- and backend.
I did a couple of things since this issue occurred and here is a list of things I think went wrong:
Local linking of the npm package into my project caused issues (npm link). I have very little experience with all the build tools in sveltekit but figured out where those stale/non-functional libs are referenced from. I deleted the node-modules/.vite folder which sometimes resolved my issues (I greped for seemingly cached values which led me to this directory. In my dev experience quite uncommon to have found build artifacts in node-modules, so that was a bit tedious to find in that place).
I converted my npm package to a hybrid ESM/CJS module (previously CommonJS only). I'm unsure whether that resolved the initial issues, but might be worth a try.
I think the main issue was the local linking and some sort of build caching going on in vite.
That being said, I haven't encountered any issues with the library ever since.
When running ng test --code-coverage only coverage for source files that are undergoing tests are reported in the coverage report. How to configure instrumentation to include all source files (e.g. all .ts files in src/app folder)?
I have tried different things:
Following https://github.com/angular/angular-cli/issues/1735 I tried replacing the suggested context definition. This does not work at all in my case. Loads of errors are outputted and no tests are executed
Remove istanbul as dependency and rely solely on karma-coverage, where it is possible to configure includeAllSources: true - however Angular CLI cannot run without karma-coverage-istanbul-reporter
A combination of the above with karma-coverage-istanbul-reporter as a dependency - no difference from the original setup
There has to be some way to instrument Angular CLI to include all source files. Adding empty specs seems tedious and error-prone, since coverage will not show up at all if the class/source file is not undergoing test and you therefore manually have to check whether it's included in the coverage report or not.
Any suggestions appreciated!
Various information:
ng --version
#angular/cli: 1.4.8
node: 6.11.3
os: linux x64
#angular/animations: 4.4.6
#angular/common: 4.4.6
#angular/compiler: 4.4.6
#angular/core: 4.4.6
#angular/forms: 4.4.6
#angular/http: 4.4.6
#angular/platform-browser: 4.4.6
#angular/platform-browser-dynamic: 4.4.6
#angular/router: 4.4.6
#angular/cli: 1.4.8
#angular/compiler-cli: 4.4.6
#angular/language-service: 4.4.6
typescript: 2.3.4
package.json:
"devDependencies": {
"#angular/cli": "1.4.8",
"#angular/compiler-cli": "^4.2.4",
"#angular/language-service": "^4.2.4",
"#types/jasmine": "~2.5.53",
"#types/jasminewd2": "~2.0.2",
"#types/node": "~6.0.60",
"codelyzer": "~3.2.0",
"jasmine-core": "~2.6.2",
"jasmine-jquery": "2.1.1",
"jasmine-spec-reporter": "~4.1.0",
"karma": "^1.7.1",
"karma-chrome-launcher": "~2.1.1",
"karma-cli": "~1.0.1",
"karma-coverage": "^1.1.1",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-htmlfile-reporter": "0.3.5",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"karma-json-reporter": "1.2.1",
"karma-spec-reporter": "0.0.31",
"ts-node": "~3.2.0",
"tslint": "~5.7.0",
"typescript": "~2.3.3"
}
karma.conf.js:
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '#angular/cli'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('karma-spec-reporter'),
require('karma-htmlfile-reporter'),
require('karma-json-reporter'),
//require('karma-coverage-istanbul-reporter'),
require('#angular/cli/plugins/karma')
],
files: [
],
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
// coverageIstanbulReporter: {
// reports: [ 'html', 'text', 'text-summary', 'json' ],
// fixWebpackSourcePaths: true
// },
angularCli: {
environment: 'dev'
},
reporters: ['spec', 'kjhtml', 'html', 'json', 'coverage'],
preprocessors: {
'src/app/*.ts': ['coverage']
},
htmlReporter: {
outputFile: 'testresults/index.html',
pageTitle: 'CRS Frontend Unit-tests - test results'
},
jsonReporter: {
stdout: false,
outputFile: 'testresults/results.json' // defaults to none
},
coverageReporter: {
dir: 'coverage',
includeAllSources: true,
reporters: [
{ type: 'html', subdir: 'html' },
{ type: 'json', subdir: 'json' }
]
},
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: true,
failOnEmptyTestSuite: false
});
};
Please do the following changes if you using angular CLI 1.7.X
~/src/test.ts
const context = require.context('./', true, /\/app\/.*\.ts$/);
~/src/tsconfig.spec.json
"include": [
"**/*.ts",
"**/*.d.ts"
]
I've had good luck using the karma-sabarivka-reporter to pick up missed source files into coverage.
I've been working in aurelia app and I'm getting an error while testing.
I'm trying to use aurelia-dependency-injection which is already a dependency of other packages which I'm including via jspm like aurelia-framework, aurelia-router, aurelia-templating-resources, aurelia-templating-router and when I try to inject it just works fine on my browser. However, when I try to test using Karma, it says
27 05 2016 09:45:18.202:WARN [web-server]: 404: /base/aurelia-dependency-injection.js
Chrome 50.0.2661 (Linux 0.0.0) ERROR
Error: XHR error (404 Not Found) loading /home/cyberkiller/test_project/aurelia-dependency-injection.js
Error loading /home/cyberkiller/test_project/aurelia-dependency-injection.js as "aurelia-dependency-injection" from /home/cyberkiller/test_project/src/users/list.ts
My package.json has the following jspm dependencies:
"jspm": {
"dependencies": {
"aurelia-animator-css": "npm:aurelia-animator-css#^1.0.0-beta.1.1.2",
"aurelia-bootstrapper": "npm:aurelia-bootstrapper#^1.0.0-beta.1.1.4",
"aurelia-fetch-client": "npm:aurelia-fetch-client#^1.0.0-beta.1.1.1",
"aurelia-framework": "npm:aurelia-framework#^1.0.0-beta.1.1.4",
"aurelia-history-browser": "npm:aurelia-history-browser#^1.0.0-beta.1.1.4",
"aurelia-loader-default": "npm:aurelia-loader-default#^1.0.0-beta.1.1.3",
"aurelia-logging-console": "npm:aurelia-logging-console#^1.0.0-beta.1.1.4",
"aurelia-pal-browser": "npm:aurelia-pal-browser#^1.0.0-beta.1.1.4",
"aurelia-polyfills": "npm:aurelia-polyfills#^1.0.0-beta.1.0.3",
"aurelia-router": "npm:aurelia-router#^1.0.0-beta.1.1.3",
"aurelia-templating-binding": "npm:aurelia-templating-binding#^1.0.0-beta.1.1.2",
"aurelia-templating-resources": "npm:aurelia-templating-resources#^1.0.0-beta.1.1.3",
"aurelia-templating-router": "npm:aurelia-templating-router#^1.0.0-beta.1.1.2",
"bootstrap": "github:twbs/bootstrap#^3.3.5",
"fetch": "github:github/fetch#^0.11.0",
"font-awesome": "npm:font-awesome#^4.6.1",
"simple-line-icons": "npm:simple-line-icons#^2.2.4",
"text": "github:systemjs/plugin-text#^0.0.3"
},
"devDependencies": {
"babel": "npm:babel-core#^5.8.24",
"babel-runtime": "npm:babel-runtime#^5.8.24",
"core-js": "npm:core-js#^1.1.4"
}
}
I did find a workaround, which is to add aurelia-dependency-injection explicitly as a dependency in my package.json like
"aurelia-dependency-injection": "npm:aurelia-dependency-injection#1.0.0-beta.1.2.3"
Which makes my package.json look like:
"jspm": {
"dependencies": {
"aurelia-animator-css": "npm:aurelia-animator-css#^1.0.0-beta.1.1.2",
"aurelia-bootstrapper": "npm:aurelia-bootstrapper#^1.0.0-beta.1.1.4",
"aurelia-dependency-injection": "npm:aurelia-dependency-injection#1.0.0-beta.1.2.3",
"aurelia-fetch-client": "npm:aurelia-fetch-client#^1.0.0-beta.1.1.1",
"aurelia-framework": "npm:aurelia-framework#^1.0.0-beta.1.1.4",
"aurelia-history-browser": "npm:aurelia-history-browser#^1.0.0-beta.1.1.4",
"aurelia-loader-default": "npm:aurelia-loader-default#^1.0.0-beta.1.1.3",
"aurelia-logging-console": "npm:aurelia-logging-console#^1.0.0-beta.1.1.4",
"aurelia-pal-browser": "npm:aurelia-pal-browser#^1.0.0-beta.1.1.4",
"aurelia-polyfills": "npm:aurelia-polyfills#^1.0.0-beta.1.0.3",
"aurelia-router": "npm:aurelia-router#^1.0.0-beta.1.1.3",
"aurelia-templating-binding": "npm:aurelia-templating-binding#^1.0.0-beta.1.1.2",
"aurelia-templating-resources": "npm:aurelia-templating-resources#^1.0.0-beta.1.1.3",
"aurelia-templating-router": "npm:aurelia-templating-router#^1.0.0-beta.1.1.2",
"bootstrap": "github:twbs/bootstrap#^3.3.5",
"fetch": "github:github/fetch#^0.11.0",
"font-awesome": "npm:font-awesome#^4.6.1",
"simple-line-icons": "npm:simple-line-icons#^2.2.4",
"text": "github:systemjs/plugin-text#^0.0.3"
},
"devDependencies": {
"babel": "npm:babel-core#^5.8.24",
"babel-runtime": "npm:babel-runtime#^5.8.24",
"core-js": "npm:core-js#^1.1.4"
}
}
When I update everything and build and run test, it no longer complains and it executes successfully. However I'm not sure if this is just a workaround, or the way to do it. Is there any better way to handle this?
Thanks in advanced!
I am using yeoman webapp generator to generate a template to kick start of my work. At this moment, my bower.json looks like this
{
"name": "sample-project",
"private": true,
"dependencies": {
"bootstrap-sass": "~3.3.5",
"modernizr": "~2.8.3",
"fontawesome": "~4.3.0",
"jquery.smooth-scroll": "~1.5.5",
"animate.css": "~3.3.0",
"jquery.appear": "*"
},
"overrides": {
"bootstrap-sass": {
"main": [
"assets/stylesheets/_bootstrap.scss",
"assets/fonts/bootstrap/*",
"assets/javascripts/bootstrap.js"
]
}
},
"devDependencies": {
"chai": "~3.0.0",
"mocha": "~2.2.5"
}
}
Now, in cmd prompt I type this while grunt watch is running
bower install bootstrap-datepicker -S
Then I found "bootstrap-datepicker": "~1.4.0" is inserted into the dependencies section, then
<script src="bower_components/bootstrap-datepicker/js/bootstrap-datepicker.js"></script>
will be automatically wiredep into my index.html, it becomes this
<!-- build:js(.) scripts/vendor.js -->
<!-- bower:js -->
.
.
<script src="bower_components/bootstrap-datepicker/js/bootstrap-datepicker.js"></script>
<!-- endbower -->
<!-- endbuild -->
Then I try to install another bower component to my webapp
bower install country-region-selector -S
The next thing happens is I found "country-region-selector": "~0.1.8" is under dependencies section of bower.json like bootstrap-datepicker, however the corresponding
<script src="bower_components/country-region-selector/dist/crs.min.js"></script>
doesn't get wiredep into my index.html.
So my question is why grunt wiredep doesn't work on some bower components? The same thing happens to form.validation Could anybody shed some light on this problem?
grunt-wiredep works in a very specific way. The dependencies should be listed in an array inside the main property in bower.josn like the example you mentioned from bootstrap.
The problem you are facing is probably those packages doesn't have a main property or it is using multiple files in a string not an array.
To fix that, you can always define an override for the packages main property likes the following ...
In your grunt file:
wiredep: {
...
overrides: {
'package-name': {
'main': [
'link-to-css-file.css',
'link-to-js-file.js'
]
},
},
},
I am downloading angular, angular-bootstrap and bootstrap with bower. Bootstrap has a dependency on jquery which is installed in the process. But i don't need it in my project as i am only using bootstrap's css.
So i tried to permanently remove the dependency on jquery with
bower uninstall jquery --save
It's uninstalling jquery, but the next time i make bower update, it's downloaded again.
Is there a way to tell bower to permanently skip a dependency ?
edit: I wish there was something like this:
"resolutions": {
"jquery": "no, thanks"
}
Pull request #1394 added official support for this feature and is present in bower version 1.6.3 and later. Check your version with bower -v, and run npm install -g bower to upgrade.
For reference, please see the .bowerrc official specification document. If this doesn't work for you, please file an issue with bower because it is a bug.
We use it like this in our .bowerrc such as the following:
{
"ignoredDependencies": [
"bootstrap",
"bootstrap-sass",
"bootstrap-sass-official"
]
}
We had a similar situation where we had Backbone depend on Underscore in its bower.json, but we're using Lo-Dash in its stead, so Bower was unnecessarily pulling down Underscore for each install. We have automated checks for 3rd party license compliance, so we didn't want anything we don't actually use.
I realize this isn't exactly what they're meant for, but Bower's install-hooks can be used to clean unneeded deps post-install (at least until Bower gets the sort of "no thanks" resolution you hinted at). In your .bowerrc:
{
"directory": "app/bower_components",
"scripts": {
"postinstall": "rm -rf app/bower_components/underscore"
}
}
It's a bit of a hack, but works.
Something you can do also in your bower.json file:
{
"dependencies": {
...
"bootstrap": "^3.2.0"
}
"overrides": {
"bootstrap": {
"dependencies": []
}
}
}
This means: remove all boostrap's dependencies, which is what you want since jquery is the only one (you can check with bower info bootstrap)
Add it to your .gitignore if you commit your dependencies. Otherwise leave it as it makes no difference. You should just use what you need and ignore the rest.
The above answers are correct but an additional solution is to use wiredep as explained in this answer:
grunt-bower-install: exclude certain components
After installing grunt-wiredep, you can add something similar to this to your Grunt.js to exclude jquery from being injected:
// Automatically inject Bower components into the app
wiredep: {
options: {},
app: {
src: ['<%= my.app %>/index.html'],
exclude: ['bower_components/jquery']
}
},
Bower will still download jquery unfortunately but at least you can tell it not to be included in the HTML src.
DISCLAIMER: This doesn't fix your particular problem, but it helped with mine, so maybe it'll help other people.
I'm using grunt-bower-task to pull the files into a lib directory. I wanted to exclude "angular" and just include "angular.js". One of my dependencies was pulling in "angular". In my bower.json I now have:
{
"name": "myapp",
"version": "0.0.1",
"dependencies": {
"angular.js": "1.3.15",
"angular-bootstrap": "0.13.0",
"angular-cookies": "1.3.15",
"angular-storage": "0.5.0",
"angular-ui-router": "0.2.15",
"mjolnic-bootstrap-colorpicker": "2.1"
},
"exportsOverride": {
"angular": {
"dump": "*.xxx"
},
"angular.js": {
"js": [ "*.js", "*.js.map" ],
"css": "*.css"
}
},
"resolutions": {
"angular": "1.3.15"
}
}
In my gruntfile.js I have:
bower: {
install: {
options: {
targetDir: './lib',
layout: 'byType',
install: true,
cleanTargetDir: true,
cleanBowerDir: false
}
}
},
This stops the "angular" files from being copied to the destination.