How do I configure jest to give coverage on Selenium tests? - javascript

I just started using jest for testing my JavaScript project. I was using mocha and chai, but I couldn't get coverage information on my component tests, which use babel and Selenium, so I thought I'd try jest. I've converted my tests over to use jest and they are working but again, the Selenium tests do not give coverage information. I have a few unit tests that don't use Selenium, and I'm getting coverage data from them. If I disable the unit tests, the coverage numbers are basically zeroes across the board (though not exactly zero, there are a handful of lines that do get covered).
I've found a few blogs and SO questions addressing this problem, but their solutions are out-of-date (i.e. bug in jest, fixed in version 0.9.0. I'm using version 29.3.1). My jest.config.js contains this:
{
collectCoverage: true,
coverageDirectory: 'coverage',
coverageProvider: 'babel',
coverageReporters: [ 'html' ]
}
I'm using node.js v16.13.0 on Windows. My dependencies are:
"dependencies": {
"#babel/cli": "^7.19.3",
"#babel/core": "^7.20.2",
"#babel/preset-env": "^7.20.2",
"#babel/register": "^7.18.9",
"babel-jest": "^29.3.1",
"babel-plugin-rewire": "^1.2.0",
"chai": "^4.3.6",
"eslint": "^8.9.0",
"eslint-plugin-html": "^6.2.0",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-mocha": "^10.1.0",
"express": "^4.18.2",
"jest": "^29.3.1",
"mocha": "^10.1.0",
"rewire": "^6.0.0",
"selenium-webdriver": "^4.6.0",
"sinon": "^14.0.1"
}
How can I get coverage information from the Selenium tests?

I have been trying for about a week to get code coverage with Jest and Selenium-webdriver. It just does not work. I tried a different approach using nyc reporter. After the Selenium tests run, I use JavascriptExecutor to return the value of window.__coverage__, stringify it, save it as output.json in nyc_output directory and then run nyc report --reporter=lcov.
Magic. I get the code coverage report.
const data = await driver.executeScript("return window.__coverage__");
fs.promises.writeFile(".nyc_output/output.json", JSON.stringify(data));
It's a little hacky and not a long term solution, but meets my requirements until I can understand why Jest is not working.
Hopefully we get a better answer from someone else. But I have searched the internet high and low and have not seen any working examples of how to get code coverage for Selenium with Jest or even Mocha and nyc.

Related

Why is my Jest code coverage report invalid?

When I generate a Jest code coverage report for my Vue 2.7.X app, the lines shown as covered/uncovered in the report don't make any sense:
The red sections in this report should indicate code that's not covered (executed) by the test suite, but obviously it makes no sense to show comments (lines 290, 291) as uncovered, or to show (part of) line 298 as uncovered when the lines before and after are covered.
I guess what's happening is that the lines which Jest detects as uncovered are not being correctly mapped back to the source code, so there may be a problem with the Babel transpilation.
I generate the code coverage report with yarn jest --coverage and the application source code is written in JavaScript (rather than TypeScript).
some of the dependencies from package.json which may be relevant to the problem are shown below:
"devDependencies": {
"#babel/core": "^7.20.5",
"#babel/preset-env": "^7.20.2",
"#vue/test-utils": "1.3.3",
"#vue/vue2-jest": "29.2.2",
"#vitejs/plugin-vue2": "^2.2.0",
"babel-jest": "^29.3.1",
"http-proxy": "^1.18.1",
"jest": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
"sass": "1.32.13",
"sass-lint": "^1.13.1",
"start-server-and-test": "^1.14.0",
"unplugin-vue-components": "^0.22.12",
"vite": "^4.0.1",
"vite-plugin-rewrite-all": "^1.0.1",
"vue-template-compiler": "^2.7.14"
}
Minimum Reproducible Example
I've created a minimal Git repo that demonstrates the problem.
Clone the repo
Run yarn install && yarn test:unit:coverage to generate the coverage report (or use npm instead)
Open the file coverage/lcov-report/index.html to see the report
If you open the page for components/toaster-message.vue, it says 1/2 branches and 2/3 functions are covered, but none of the lines are marked in red (hideAppMessage should be red because it's not tested).
If you open the page for views/login.vue the lines that are marked in red (uncovered) don't make any sense. There are no tests for this component.
What worked for me was adding coverageProvider: 'v8' to the jest.config.js. I'm not entirely sure why changing coverageProvider works, but seems like vue-jest is having general problems with collecting coverage correctly due to babel dependency changes.
Try adding this to your Jest configuration:
coverageProvider: 'v8'
Then npm run test:unit:coverage.
This worked on Node v16.16.0 and v18.12.1.
jest uses its own version of Babel to transpile your code, but the source map that generates it could be unnacurate or have a differrent version than the one you are using.
You can make sure that jest is using the same version of Babel that you're using in your app by adding the following configuration to your package.json file:
"jest": {
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/babel-jest"
}
}
Also, could it be that even though your package.json has that version you have something else in the package-lock.json?
Looks like solution with coverageProvider: 'v8' added by #morganney works.
For the problem of generating a coverage report.
Failed to write coverage reports:
ERROR: Error: ENOENT: no such file or directory, open 'path\to\file\<<jsx-config-pragma.js>>.html'
Just remove the .ts("\\.(tsx|ts|jsx|js)$") files from configuration (package.json)
...
"transform": {
"\\.(tsx|jsx|js)$": [
"#swc-node/jest",
{
"dynamicImport": true
}
]
},
...

'Cannot find module' when trying to unit test an import from a federated module (webpack 5) with Jest

Do you want to request a feature or report a bug?
Report a bug
What is the current behavior?
https://gitter.im/webpack/webpack?at=5fad8fcdb86f64070448ee1c
The current behavior is that when running tests now 'imports' of components from federated modules being found because they're just a reference for webpack from the federated module entryPoint.js
If the current behavior is a bug, please provide the steps to reproduce.
Let's say we have an A repo with hosts other apps and modules and has an App.js file with the application page.
That App.js imports a component from a federated module.
Then we create an App.test.js to unit test the file and we try to mock the component from the federated module.
What is the expected behavior?
Unit tests should be able to pass with the mocked component.
Please mention other relevant information such as the browser version, Node.js version, webpack version, and Operating System.
Node v12.16.3
"webpack": "^5.4.0",
"webpack-cli": "^4.2.0",
"webpack-dev-server": "^3.11.0"
"#babel/core": "^7.12.3",
"#babel/plugin-proposal-class-properties": "^7.12.1",
"#babel/preset-env": "^7.12.1",
"#babel/preset-react": "^7.12.5",
"babel-loader": "^8.2.1",
jest#25.5.4
Example!
https://github.com/testacode/basic-host-remote

How to ditch Babel from Vue build chain?

I'm developing a Vue app solely for Chrome, which leads me to believe (please correct me if wrong) that I can write native ES6 and don't need to transpile.
The Vue CLI generates a package.json like this:
"devDependencies": {
"babel-core": "^6.0.0",
"babel-preset-es2015": "^6.0.0",
"babelify": "^7.2.0",
"browserify": "^13.0.1",
"browserify-hmr": "^0.3.1",
"cross-env": "^1.0.6",
"envify": "^3.4.1",
"http-server": "^0.9.0",
"npm-run-all": "^2.1.2",
"uglify-js": "^2.5.0",
"vueify": "^9.1.0",
"watchify": "^3.4.0"
},
"browserify": {
"transform": [
"vueify",
"babelify"
]
}
But if I remove the 4 references to Babel, I get compile errors on my very first file. So really I just have two questions:
1) Am I correct in thinking that I can ditch Babel?
2) How do I do it?
I don't think browserify can handle ES6 imports without Babel. Usually, you could just get away with using something like gulp to uglify and minify without transpiling, because browserify is intended to allow require to be used in the browser, but if the browser supports import then you don't really need it. Unfortunately, this means that you won't be able to use vueify, so you lose the ability to use single file components, so I guess it's down to whether you think that trade-off is acceptable.
You may be interested in this discussion on GitHub: https://github.com/substack/node-browserify/issues/1186

setup.js is deleted in react-boilerplate when running npm run setup

I have a very strange problem. I have cloned the react-boilerplate repository from here:
https://github.com/mxstbr/react-boilerplate
I add the following dependencies:
"body-parser": "^1.15.0",
"cors": "^2.7.1",
"feathers-client": "^1.6.1",
"feathers-rest": "^1.5.0",
"material-ui": "^0.16.0-rc2",
"node-uuid": "^1.4.7",
"react-json-viewer": "^1.1.0",
"request-promise": "^4.1.1",
"rest-client": "^0.1.5",
"socket.io-client": "^1.4.8"
When I run 'npm run setup' the file internals/scripts/setup.js is deleted which means that I get an error the next time I run 'npm run setup'.
Any suggestion as to how this can happen will be appreciated.
It turns out that
npm run setup
is only intended to run once. Afterwards I assume I should
run npm install
I found out after reading this article:
https://github.com/mxstbr/react-boilerplate/issues/339
In the boiler plate you are working there will be a file setup.js that will be missing in your boilerplate and the path where it should be will be provided in the error, Copy that setup.js file from original boiler plate and paste there where it is missing. This solution worked for me perfectly

Vue.js browserify Cannot find module

With almost every npm package that I'm trying to use with vue.js 1.0 I receive this error:
{ Error: Cannot find module '!!./../../../node_modules/css-loader/index.js!./../../../node_modules/vue-loader/lib/style-rewriter.js!./../../../node_modules/vue-loader/lib/selector.js?type=style&index=0!./dashboard.vue' from '/Users/jamie/Code/forum/node_modules/vue-html5-editor/dist'
at /Users/jamie/Code/forum/node_modules/resolve/lib/async.js:46:17
at process (/Users/jamie/Code/forum/node_modules/resolve/lib/async.js:173:43)
at ondir (/Users/jamie/Code/forum/node_modules/resolve/lib/async.js:188:17)
at load (/Users/jamie/Code/forum/node_modules/resolve/lib/async.js:69:43)
at onex (/Users/jamie/Code/forum/node_modules/resolve/lib/async.js:92:31)
at /Users/jamie/Code/forum/node_modules/resolve/lib/async.js:22:47
at FSReqWrap.oncomplete (fs.js:117:15)
It drives me nuts! I'm using vue.js with browserify. Looked everywhere on the web:
https://github.com/webpack/css-loader/issues/240
https://github.com/webpack/css-loader/issues/180
https://github.com/webpack/css-loader/issues/295
https://github.com/webpack/css-loader/issues/163
Nothing seems to work! What am I doing wrong!?
2 packages where I've this problem:
https://github.com/lian-yue/vue-upload-component/
https://github.com/PeakTai/vue-html5-editor
My gulpfile:
const elixir = require('laravel-elixir');
require('laravel-elixir-vueify');
require('laravel-elixir-stylus');
elixir(mix => {
mix.browserify('main.js');
mix.styles([
'./node_modules/normalize-css/normalize.css',
'./node_modules/nprogress/nprogress.css',
'./node_modules/sweetalert/dist/sweetalert.css',
]);
mix.stylus('app.styl');
});
A solution would really help me out.
--EDIT--
{
"private": true,
"scripts": {
"prod": "gulp --production",
"dev": "gulp watch"
},
"devDependencies": {
"gulp": "^3.9.1",
"laravel-elixir": "^6.0.0-9",
"laravel-elixir-browserify-official": "^0.1.3",
"laravel-elixir-stylus": "^2.0.3",
"vue-html5-editor": "^0.5.1"
},
"dependencies": {
"browserify": "^13.1.0",
"laravel-elixir-vueify": "^2.0.0",
"normalize-css": "^2.3.1",
"nprogress": "^0.2.0",
"stylus": "^0.54.5",
"sweetalert": "^1.1.3",
"vue": "^1.0.26",
"vue-resource": "^0.9.3",
"vue-router": "^0.7.13",
"vue-spinner": "^1.0.2",
"vue-upload-component": "^2.0.0-beta"
}
}
Those are webpack packages and you are using browserify. If you need to use webpack packages you should be using webpack as your bundler.
I did have a go at installing the vue-upload-component package to see how easy it would be with browserify and elixir but it's awkward to say the least. I didn't get it working because it uses babel transforms to compile the vue files, so first you need to pull them in manually and then you would likely need to write an elixir extension to use those transforms to get it to work. Obviously each webpack package will be different so you would need to do that each time you install one, which is hardly convenient.
I had some luck changing the configuration output of the Vue component I wanted to use to use webpack -p instead of just webpack.
I could then take that output without the hot module code and put it through browserify:
browserify file.js --standalone SomeLibrary > file.browser.js
Where file.js is the webpack -p output, SomeLibrary is the name you want on the global window scope from the browserify packaging, and file.browser.js is your resultant file to include in your project.

Categories

Resources