Installed jest:
yarn add jest
Add a file in ./src/index.js with the content:
test('First test', () => {
expect(true).toBe(true);
});
Try to run it with:
node node_modules/jest/bin/jest.js src/index.js
or
node node_modules/jest/bin/jest.js ./src/index.js
But all I get is:
No tests found
In /home/me/dev/lib
7 files checked.
testMatch: **/__tests__/**/*.js?(x),**/?(*.)(spec|test).js?(x) - 0 matches
testPathIgnorePatterns: /node_modules/ - 7 matches
Pattern: ./src/index.js - 0 matches
Just would like to run the one file without having to go through the pain of setting up a directory convention or config file. Is this possible?
From Jest's website
Place your tests in a __tests__ folder, or name your test files with a .spec.js or .test.js extension. Whatever you prefer, Jest will find and run your tests.
You can see in the test match
testMatch: **/__tests__/**/*.js?(x),**/?(*.)(spec|test).js?(x) - 0 matches
It is looking for files that are .spec or .test and end in .js or .jsx
import LoggerService from '../LoggerService ';
describe('Method called****', () => {
it('00000000', () => {
const logEvent = jest.spyOn(LoggerService , 'logEvent');
expect(logEvent).toBeDefined();
});
});
npm test -- tests/LoggerService .test.ts -t '00000000'
Related
I have a file called "test-file-1", within it i have a few describes (test suites) with unique names and inside them i have tests which may have similar names across test suites.
To run a single test suite or test i type the command below.
npm test -- -t "Test Suite or Test"
I'm trying to figure out how to run a single test of a specific test suite.
Give the path of the file you want to test :
npm test path/of/your/testfile.js -t "test name"
will run only the test (or group) named "test name" of this specific file.
After trying a lot of different things i found out that it was simpler than i thought.
You simply have to put the test after the test suite in the same string:
npm test -- -t "<Test Suite> <Test>"
import LoggerService from '../LoggerService ';
describe('Method called****', () => {
it('00000000', () => {
const logEvent = jest.spyOn(LoggerService , 'logEvent');
expect(logEvent).toBeDefined();
});
});
run below command
npm test -- tests/LoggerService.test.ts -t '00000000'
Point to the test suite in jest config file via "testMatch":["**/path/testSuite/*.js"]
and now execute by giving unique testname by jest testName
Here you have to update the testMatch every time which is your testSuite
If you are using a jest config file, you can use the testNamePattern key to configure this. So your config file could look something like
jest-e2e.json
{
"moduleFileExtensions": ["js", "json", "ts"],
"rootDir": ".",
"testEnvironment": "node",
"testRegex": ".spec.ts$",
"testNamePattern": "login",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"bail": true,
"verbose": true,
"testTimeout": 30000
}
This will only run test that has "login" in one of the test pattern
Reference:
https://jestjs.io/docs/cli#--testnamepatternregex
For me, it only works with:
npm run test -- tests/01_login.js --testcase "Should login into Dashboard"
npm run <script> -- <test suite path> --testcase "<test case>"
my script in package.json:
"test": "env-cmd -f ./.env nightwatch --retries 2 --env selenium.chrome",
at nightwatch version 1.3.4
Jest allows you to specify a coverage reporter in the package.json like so
{
...
"jest": {
"coverageDirectory": "./coverage",
"coverageReporters": ["json", "text", ...]
}
...
}
However, this only outputs the .json summary to the coverage directory. It only prints the text version to the console. Is there a way to output the text version to a .txt file in the coverage folder as well?
I've been referring to the docs here, which says that it is compatible with any of the Istanbul reporters. The text Istanbul reporter appears to have support for writing to a file. Is there any way to utilize it this?
In your jest config, you can specify the file option, and optionally the dir options which defaults to the current working directory:
"jest": {
"coverageReporters": ["text", { file: 'coverage.txt' }]
}
See docs for available options here.
Add json to coverageReports in your jest config:
"coverageReporters": ["json"]
Then install istanbul:
npm i -D istanbul
Add this script to package.json:
"scripts": {
"test": "jest --coverage && istanbul report --include coverage/coverage-final.json text > coverage.txt",
...
}
The script will generate the code coverage report file coverage-final.json then istanbul will generate the expected output redirected to coverage.txt
#KerSplosh We ended up writing a custom script with shelljs. Basically it runs the tests, and writes the table to a file with fs.
const shell = require("shelljs");
const path = require("path");
const fs = require("fs");
const result = shell.exec("yarn test --coverage");
fs.writeFileSync(
path.resolve(".", "coverage.txt"),
result.substring(result.indexOf("|\nFile") + 2)
);
if (result.code !== 0) {
shell.exit(1);
}
This isn't ideal though. Preferably this would be done through the Jest configuration. But at the time I implemented this, I don't think it wasn't possible.
If you happen to use react scripts on top of jest:
Add these snippets to their sections in package.json:
"scripts": {
"cover:report": "react-scripts test --coverage .> coverage/coverage-report.txt",
}
...
"jest": {
"collectCoverageFrom": [
"src/**/*.ts*"
],
"coverageReporters": ["text"]
}
This generates coverage report in file coverage/coverage-report.txt.
The dot in ".>" part tells the script to take all files (except for ignored ones) that match the "." pattern - which would typically be all of them.
Modify the "collectCoverageFrom" array of strings to include files/folders as needed.
This command doesn't exit itself unfortunately so you have to Ctrl+C to end it when it just hangs in there after being done.
To run it in terminal: "yarn cover:report"
The result contains plaintext table of coverage results.
I am trying to run my jest with a grunt task but on doing so I get No tests found message in console. Here is the setup for the same:
gruntfile.js snippet :
exec: {
jest: 'node node_modules/jest/bin/jest -u --config="test/unit/jest/jest.conf.json"'
}
jest.conf.json :
{
"testEnvironment": "jsdom",
"setupTestFrameworkScriptFile": "./enzyme.setup.js",
"testResultsProcessor": "jest-teamcity-reporter"
}
enzyme.setup.js :
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-15.4';
configure({ adapter: new Adapter() });
Console on running the grunt exec task shows below:
No tests found
In C:\Vishal\UI\Jest-Grunt\proj\test\unit\jest
3 files checked.
testMatch: .js?(x),**/?(*.)(spec|test).js?(x) - 0 matches
testPathIgnorePatterns: \\node_modules\\ - 3 matches
Pattern: - 0 matches
Done, without errors.
However the surprising thing is if I don't pass the jest config file path in cli inside grunt exec task and instead specify the jest configuration in package.json file then it works.
Not sure why this is behaving like this.
Aah, after banging my head around. I noticed that the error is pity straight forward:
In C:\My-User\UI\Jest-Grunt\proj\test\unit\jest
This clearly explains that JEST tries to execute test cases inside folder specified above. But ideally JEST looks into __tests__. Hence I had to specify the roots folder myself. With package json this doesn't occur. Strange though!
Here is my updates jest configuration:
{
"testEnvironment": "jsdom",
"setupTestFrameworkScriptFile": "./enzyme.setup.js",
"testResultsProcessor": "jest-teamcity-reporter",
"coverageReporters": [
"teamcity", "lcov"
],
"roots": [
"../../../__tests__"
]
}
Repo is available here: https://github.com/systemnate/vuetesting
I created a rails app by running the command rails _5.1.2_ new vuetesting --webpack=vue
And then added mocha and chai yarn add mocha chai --save-dev
And then created a test directory by running mkdir test/javascript
Then I created a spec file to run... touch app/javascript/App.spec.js
And pasted in the following code:
const chai = require('chai')
const expect = chai.expect
describe('first test', () => {
it('is true', () => {
expect(true).to.equal(true)
})
})
And added the following to package.json
"scripts": {
"test": "mocha test/**/*.spec.js --recursive"
}
Now previous yarn test passes. Let's try to implement a Vue specific test.
I run the command yarn add avoriaz mocha-webpack --save-dev
And then modified package.json to use mocha-webpack:
"scripts": {
"test": "mocha-webpack test/**/*.spec.js --recursive"
}
yarn test still passes.
Now I want to test the single file component. To start with, I added to the top of my test so it looks like this:
import Vue from 'vue';
import App from '../../app/javascript/packs/App.vue';
const chai = require('chai')
const expect = chai.expect
describe('first test', () => {
it('is true', () => {
expect(true).to.equal(true)
})
})
And then run yarn test and get the following output
yarn test v0.27.5
$ mocha-webpack test/**/*.spec.js --recursive
ERROR in ./app/javascript/packs/App.vue
Module parse failed: /Users/natedalo/Ruby/vuetesting/app/javascript/packs/App.vue Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
| <template>
| <div id="app">
| <p>{{ message }}</p>
# ./test/javascript/App.spec.js 2:0-53
error Command failed with exit code 1.
Any thoughts on what could be going wrong?
Using Unit Test Vue Components for Beginners as a guide, and copying the webpack.config.js and .setup files from the link above and then changing the test run to read like this inside the package.json:
"test": "mocha-webpack --webpack-config test/javascript/webpack.test.config.js test/**/*.spec.js --recursive --require test/javascript/.setup"
I am trying to get a unit test written in Typescript using Jasmine to compile. With the following in my unit-test file, Resharper prompts me with a link to import types from jasmine.d.ts.
/// <reference path="sut.ts" />
/// <reference path="../../../scripts/typings/jasmine/jasmine.d.ts" />
describe("Person FullName", function () {
var person;
BeforeEach(function () {
person = new Person();
person.setFirstName("Joe");
person.setLastName("Smith");
});
It("should concatenate first and last names", function () {
Expect(person.getFullName()).toBe("Joe, Smith");
});
});
So I click on the link and end up with the following (actually resharper only prefixed the describe function with "Jasmine.", so I manually prefixed the other Jasmine calls):
/// <reference path="sut.ts" />
/// <reference path="../../../scripts/typings/jasmine/jasmine.d.ts" />
import Jasmine = require("../../../Scripts/typings/jasmine/jasmine");
Jasmine.describe("Person FullName", function () {
var person;
Jasmine.BeforeEach(function () {
person = new Person();
person.setFirstName("Joe");
person.setLastName("Smith");
});
Jasmine.It("should concatenate first and last names", function () {
Jasmine.Expect(person.getFullName()).toBe("Joe, Smith");
});
});
However the import statement has a red squiggly line with error message "Unable to resolve external module ../../../scripts/typings/jasmine/jasmine. Module cannot be aliased to a non-module type"
Any idea what is causing this error? I've checked that the "Module System" option is set to AMD in my project build settings. I've also checked that the jasmine module is defined in jasmine.d.ts. I downloaded this file from DefinitelyTyped site.
declare module jasmine {
...
}
Here's (in my opinion) the best way to test a ts-node app as of 2018:
npm install --save-dev typescript jasmine #types/jasmine ts-node
In package.json:
{
"scripts": {
"test": "ts-node node_modules/jasmine/bin/jasmine"
}
}
In jasmine.json change file pattern to *.ts
"spec_files": ["**/*[sS]pec.ts"],
In your spec files:
import "jasmine";
import something from "../src/something";
describe("something", () => {
it("should work", () => {
expect(something.works()).toBe(true);
});
});
To run the tests:
npm test
This will use the locally installed versions of ts-node and jasmine. This is better than using globally installed versions, because with local versions, you can be sure that everyone is using the same version.
Note: if you have a web app instead of a node app, you should probably run your tests using Karma instead of the Jasmine CLI.
Put this at the top of your typescript spec file:
/// <reference path="../../node_modules/#types/jasmine/index.d.ts" />
let Jasmine = require('jasmine');
You must install the following Jasmine modules for that to work:
$ npm install jasmine-core jasmine #types/jasmine #ert78gb/jasmine-ts --save-dev
Once you do that, the IDE (such as WebStorm) will recognize Jasmine and its functions such as describe(), it(), and expect().. So you don't need to prefix them with "Jasmine." Also, you can run your spec files from the command line using the jasmine-ts module. Install these command line tools globally:
$ npm install -g jasmine #ert78gb/jasmine-ts
Then configure the "jasmine" command line module so that Jasmine can find its configuration file. Then you should be able to run jasmine-ts and your spec file should run fine from the command line:
./node_modules/.bin/jasmine-ts src/something.spec.ts
.. and, you can configure your IDE to run it like that as well, and debug runs that way should also work (works for me).
Writing your tests this way, you can run a Jasmine test spec on the server side without Karma, or run it in a web browser using Karma. Same typescript code.
If you have issues with imports, use tsconfig-paths
npm i ts-node tsconfig-paths types/jasmine jasmine --save-dev
Run typescript-enabled jasmine:
ts-node -r tsconfig-paths/register node_modules/jasmine/bin/jasmine.js
Ensure that your jasmine will search .ts files:
"spec_files": [
"**/*[sS]pec.ts"
],
"helpers": [
"helpers/**/*.ts"
],
To test your scripts you may also need polyfills if you use them in your project. Create a helper file with required imports, like helpers/global/polifill.ts
import 'core-js';
For me I did the following:
Install Typings
npm install typings --global
Then add the typings in for jasmine
typings install dt~jasmine --save --global
You could try a side-effect only import which brings in the #types/jasmine declaration and places the jasmine functions into the global scope so you don't need to prefix each call with jasmine. allowing a quick port from existing unit tests and still plays nice with webpack.
// tslint:disable-next-line:no-import-side-effect
import "jasmine";
describe("My Unit Test", () => { /* ... */ } );
Of course you still need to install jasmine and the typings:
$ npm i jasmine #types/jasmine --save-dev
But no need for specialized jasmine loaders for ts or node. Just run jasmine against the compiled js files:
$ node ./node_modules/jasmine/bin/jasmine.js --config=test/support/jasmine.json
Assuming your typescript files are within a "test" subdirectory compiling to bin/test and you have a test/support/jasmine.json with something like this:
{
"spec_dir": "bin/test",
"spec_files": [
"**/*[sS]pec.js"
],
"stopSpecOnExpectationFailure": false,
"random": false
}
P.S. all of the above works on Windows too
Include this to your jasmine html file,...
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.0/jasmine.js"></script>
...or install the npm jasmine package:
npm install --save-dev jasmine
when you are using the second way (jasmine as module) you have to import it:
var jasmine = require('jasmine');
or
import jasmine from 'jasmine';
then change the other code:
jasmine.describe("Person FullName", function () {
var person;
jasmine.beforeEach(function () {
person = new Person();
person.setFirstName("Joe");
person.setLastName("Smith");
});
jasmine.it("should concatenate first and last names", function () {
jasmine.expect(person.getFullName()).toBe("Joe, Smith");
});
});
Personally i would prefer the first way without using the jasmine npm module. (I didn't test the module yet)
You didn't ask for this, but for bonus points: once you get AJ's answer up and running (using ts-node to invoke the Jasmine startup script), you can add a new task:
"scripts": {
"watch": "ts-node-dev --respawn -- ./node_modules/jasmine/bin/jasmine src/**.spec.ts"
}
Of course, you can pass your specs or any other arguments using Jasmine's config file instead, if you like. Now, Jasmine will run all your specs once, then ts-node-dev will sit in the background waiting for your tests or anything they might have require'd to change, at which point jasmine will be run again. I haven't worked out a way to only run the tests that have changed (or tests whose imports have changed) yet -- as far as I can tell, that's not supported anyway;
My folder structure
Spec folder is on the root of project
spec
\- dist // compiled tests
\- helpers // files modified testing env
\- ts-console.ts // pretty prints of results
\- support
\- jasmine.json
\- YourTestHere.spec.ts
\- tsconfig.json // tsconfig for your tests
Files content
ts-console.ts
const TSConsoleReporter = require("jasmine-console-reporter");
jasmine.getEnv().clearReporters();
jasmine.getEnv().addReporter(new TSConsoleReporter());
jasmine.json
{
"spec_dir": "spec/dist",
"spec_files": [
"**/*[sS]pec.js"
],
"helpers": [
"spec/helpers/**/*.js"
],
"stopSpecOnExpectationFailure": false,
"random": true
}
With extra script in package.json
"scripts": {
"test": "rm -rf ./spec/dist && tsc -p ./spec && jasmine"
}
and add line "/spec/dist" to .gitignore
Run your tests!
Run your tests with npm test.
How does it work?
Directory for tests is cleaned.
Tests are compiled to spec/dist folder to JS.
Tests are runned from this location.
I hope it will help you. Good coding.