Jest globalSetup option not working - unit-testing

I'm trying to make a function called loadFixtures available to all Jest tests.
I have the following line within the jest config object inside package.json:
"globalSetup": "<rootDir>/src/test/js/config/setup-globals.js"
setup-globals.js contains:
module.exports = function() {
function loadFixtures(filename) {
console.info('loadFixtures is working');
}
}
Within my tests I have, for example:
beforeEach(() => {
loadFixtures('tooltip-fixture.html');
});
However when I run Jest I get the following for each test:
ReferenceError: loadFixtures is not defined
I verified that the setup-globals.js file is definitely being found and loaded in by Jest before the tests execute.
Can anyone assist in identifying where I've gone wrong here? I've spent pretty much an entire day trying to debug without luck.

You should be using setupFiles and not globalSetup.
// jest config
"setupFiles": [
"<rootDir>/src/test/js/config/setup-globals.js"
]
then src/test/js/config/setup-globals.js:
global.loadFixtures(filename) {
console.info('loadFixtures is working');
}
references: https://medium.com/#justintulk/how-to-mock-an-external-library-in-jest-140ac7b210c2

If you bootstrapped your application using npx create-react-app (CRA), you do not need to add the setupFiles key under your jest key in the package.json file (CRA prevents overriding that key).
what you simply need to do is to add the file setupTests.js in the root of your SRC folder, and populate it with the snippet below:
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({
adapter: new Adapter(),
});
remember you must have earlier installed the right versions of enzyme and enzyme-adapter-react
CRA has been wired to automatically load the setupTests.js file in the src folder if it exists. Hence after adding these, you can then go over to your test and do import {shallow} from enzyme without triggering an error.
if you are not using Create-react-app, all you need to do, in addition to adding the file above to your src folder is to add the key setupFiles into the jest key in your package.json. it should look like this:
"jest": {
"setupFiles": ['<rootDir>/src/setupTests.js'],
}
and you are good to go.
Cheers!

You're defining a function in a different scope. How about you create a separate module and import it directly in your test files. Or if you really want to define it in the global scope, try using the following code in your setup-globals.js file.
module.exports = function() {
global.loadFixtures = function(filename) {
console.info('loadFixtures is working');
}
}

Related

How to run a single test suite in Jest?

I have many test suites. I wanna to run a singe one and skip all the others, and I would like to do this on the code level.
I know I can do this using .only() and .skip() in a test file, but that supports only the tests / describes defined in that file.
Is there a way to do this globally? Like is there something like .only() which - when called on the top level describe - runs only that test suite and all others are skipped?
Or: when called on a single test ( it().only() ), then only that test runs and nothing else?
I see nothing like this in the API, but maybe Jest can be configured to work this way?
Is this possible with Jest or is this something I can only do via CLI?
If I understand correctly: You want to run just one test suite/file.
You can do this from the command line with jest path/to/filename.test.js.
Within a file, you can use test.only(name, fn, timeout) to only run that test. This won't stop Jest from moving on to the next testing file though.
Full Jest CLI docs
As far as I am aware, you cannot do this from within the test file itself.
The closest I can think of would be to set the `testmatch' in Jest's config to a pattern that only matches the file(s) you want run.
package.json
{
"name": "my-project",
"jest": {
"testmatch": "**/my.test.js"
}
}
I think if you adapt this answer: https://stackoverflow.com/a/59487370/14553660 it should give you what you need.
For example:
testsuite.test.js
import { signuptests } from './signup.test.js'
import { logintests } from './login.test.js'
import { logouttests } from './logout.test.js'
describe('Signup', signuptests)
describe.only('Login', logintests)
describe('Logout', logouttests)
signup.test.js
export const signuptests = () => {
it('Should have login elements', () => {});
it('Should Signup', () => {}});
}
login.test.js
export const logintests = () => {
it.only('Should Login', () => {}});
it('etc',()=>{});
}
logout.test.js
export const logouttests = () => {
it('Should Logout', () => {}});
it('etc',()=>{});
}
You will be able to use .only at the top level - in the testsuite file - to determine which test files are run, and you can also use .only within each individual test file (e.g. within login.test.js) to only run one particular test from that file.
I don't know that there is a limit to nesting describe blocks, so I imagine you could even make a 'master-testsuite' that imports different testsuites (which in turn import different test files...etc)

Is there a way to use global jest mocks with Quasar?

I want to mock my i18n object globally.
I'm following a guideline. I'm creating jest.init.ts file inside my jest folder. It contains following rules:
import { config } from "#vue/test-utils"
config.mocks["$t"] = () => ""
But my tests fail with the error:
TypeError: _vm.$t is not a function
I've also tried to import quasar implementation of vue-test utils ('#quasar/quasar-app-extension-testing-unit-jest'), but the result is the same
I found this https://testing.quasar.dev/packages/unit-jest/. Here is a section for mocking i18n.

How to mock global Vue.js variable in JEST test

I have a global property/variable with my app urls:
Vue.prototype.$apiUrls = {
root: 'http://localhost:8080/',
api: 'api/v1/'
// etc.
}
I use it inside my components as axios request:
axios.get(`${this.$apiUrls.root}${this.$apiUrls.api}/users/`)
Now I want to test my component's code, I've mocked axios already, but still I receive an error:
TypeError: Cannot read property '$apiUrls' of undefined
I've tried to define/mock this property inside each test and/or in JEST's setup file, like e.g.
global.$apiUrls = {...}
// or
Vue.prototype.$apiUrls = {...}
// or
Object.defineProperties(Vue.prototype, {$apiUrls: {...}})
I've also tried mocking it to window or this (yeah, thats silly), but with no success - I still receive that error - please help.
There is two ways to achieve this. One is using the Config option, as mentioned by #Aldarund. You can read about it here.
If you are using Jest, I recommend doing this in the jest.init.js file:
import { config } from '#vue/test-utils'
config.mocks['$apiUrls'] = {
'some/endpoint'
}
Then add this to the jest section of your package.json:
"setupFiles": [
"<rootDir>/jest.init.js"
]
Now it is globally mocked. If you want to do this on a per test basis, you can use the mocks mounting option:
const wrapper = shallowMount(Foo, {
mocks: {
$apiUrls: 'some/endpoint'
}
})
Hopefully this helps!
If you are interested I am compiling a collection of simple guides on how to test Vue components here. It's under development, but feel free to ask make an issue if you need help with other related things to testing Vue components.
I don't think the answers above work anymore (in 2020).
Here's what worked for me:
For vue-test-utils 1.x.x (Vue 2)
Create a new file, name it eg. jest.init.js
Give it the following content:
import { config } from "#vue/test-utils";
config.mocks["yourGlobalProperty"] = label => label; //you can replace it with your own mock
Add this to your jest.config.js (actually write "rootDir", don't replace anything with a real path)
module.exports = {
setupFiles: ["<rootDir>/jest.init.js"]
}
These files will be only ran before jest runs unit tests.
Note that I'm importing {config}, not the default export. I don't know why the default didn't work for me. Even the documentation for vue test utils doesn't import the default export anymore
Also make sure you're not trying to import from the old vue-test-utils package. (The new one is #vue/test-utils)
For #vue/test-utils 2.x.x (vue-test-utils-next) (Vue 3)
Follow steps like for 1.x.x above, but in step two, do this instead:
import { config } from "#vue/test-utils"; //2.0.0-beta.5
config.global.mocks = {
yourGlobalProperty: label => label
};
You can do it with vue-test-utils beta 15 and later.
Here docs
And some example would be:
import VueTestUtils from '#vue/test-utils'
VueTestUtils.config.mocks['$apiUrls'] = {
...
}

Babel ignore equivalent in ember engines?

In a traditional Ember app, I have something along the lines of this in my ember-cli-build.js:
//ember-cli-build.js
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
babel: {
includePolyfill: true,
ignore: ['my-ember-ui/models/myFile.js'] // <-- question is here
},
Is there an equivalent to this when using an Ember Engine (or addon)? I couldn't find anything within ember-cli-babel or ember-engines.
I understand that ember-cli-build.js is just for the dummy app when using an engine, so I wouldn't make the change there. I attempted similar to above in the index.js file, but did not have any luck. The file was not ignored by babel. I need a way to ignore a particular file. Thanks!
Well, adding new rules to Cli.build.js is ok depends on what you want to do. However, I may have another solution that you can give it a try.
Babel will look for a .babelrc in the current directory of the file being transpiled. If one does not exist, it will travel up the directory tree until it finds either a .babelrc, or a package.json with a "babel": {} hash within.(.babelrc files are serializable JSON).
{
"plugins": ["transform-react-jsx"],
"ignore": [
"foo.js",
"bar/**/*.js"
]
}
or
{
"name": "my-package",
"version": "1.0.0",
"babel": {
// my babel config here
}
}
There should be another way which seems ok to use. the following does work:
babel src --out-dir build --ignore "**/*.test.js" // or simply add your file
For more information, you can read Babel document

Testing service in Angular returns module is not defined

I am trying to run the default service unit test in my project (Taken from the Angular Seed project on GitHub), but I keep getting the error "module is not defined".
I have read that it could be something to do with the order of the referenced JavaScript files, but I can't seem to get it to work, so hopefully one of you might be able to help.
My configuration for the test looks like this:
basePath = '../';
files = [
'public/javascripts/lib/jquery-1.8.2.js',
'public/javascripts/lib/angular.js',
'public/javascripts/lib/angular-.js',
'public/app.js',
'public/controllers/.js',
'public/directives.js',
'public/filters.js',
'public/services.js',
JASMINE,
JASMINE_ADAPTER,
'public/javascripts/lib/angular-mocks.js',
'test/unit/*.js' ];
autoWatch = true;
browsers = ['Chrome'];
junitReporter = { outputFile: 'test_out/unit.xml', suite: 'unit'
};
The service looks like the following:
angular.module('myApp.services', []).
value('version', '0.1');
The test looks like this:
'use strict';
describe('service', function() {
beforeEach(module('myApp.services'));
describe('version', function() {
it('should return current version', inject(function(version) {
expect(version).toEqual('0.1');
}));
});
});
And the error when running the test through testacular is this:
ReferenceError: module is not defined
You are missing the angular-mocks.js file.
I had the same problem, and I understood why it wasn't working:
The jasmine.js javascript must be referenced BEFORE the angular-mocks.js file.
Indeed, the angular-mocks.js checks if Jasmine is loaded, and only if it is it will add the module function to the window.
Here is an extract of Angular Mocks code:
(Edit after the few comments about 'hacking' I had below: this is just an extract of the code, this is not something you need to write yourself, it's already there!)
window.jasmine && (function(window) {
[...]
window.module = angular.mock.module = function() {
var moduleFns = Array.prototype.slice.call(arguments, 0);
return isSpecRunning() ? workFn() : workFn;
/////////////////////
[...]
};
In a nutshell:
Just reference your jasmine.js before angular-mocks.js and off you go.
The window.module function comes in angular-mocks.js and is a shorthand for angular.mock.module. As mentioned in the docs, the module function only works with Jasmine.
Using Testacular, the following example configuration file will load angular-mocks.js.
/** example testacular.conf.js */
basePath = '../';
files = [
JASMINE,
JASMINE_ADAPTER,
'path/to/angular.js',
'path/to/angular-mocks.js', // for angular.mock.module and inject.
'src/js/**/*.js', // application sources
'test/unit/**/*.spec.js' // specs
];
autoWatch = true;
browsers = ['Chrome'];
And, as suggested elsewhere, you can run Testacular with debug logging to see what scripts are loaded (you can also see the same in the inspector):
testacular --log-level debug start config/testacular.conf.js
The angular.mock.inject docs include a pretty complete example.
We use 'module' without 'angular' in our unit tests and it works fine.
CoffeeScript:
describe 'DiscussionServicesSpec', ->
beforeEach module 'DiscussionServices'
beforeEach inject ... etc.
which compiles to
JavaScript:
describe('DiscussionServices', function() {
beforeEach(module('DiscussionServices'));
beforeEach(inject(function ... etc.
The only time I see something like the error you described is if in the testacular.conf.js file the angular-mocks.js file is not listed in the files section before the specs trying to use 'module'. If I put it after my tests in the 'files' list I get
ReferenceError: Can't find variable: module
(Our tests are being run through PhantomJS)
I had included angular-mocks.js in my karma config, but was still getting the error. It turns out the order is important in the files array. (duh) Just like in the head of an html doc, if a script calls angular before it's defined, and error occurs. So I just had to include my app.js after angular.js and angular-mocks.js.
If you're using Yeoman and its angular-generator, you probably get this error. Especially when you do the Tutorial ( ._.)
I fixed it, by copying the angular-mocks.js file, from the bower_components/angular-mocks dir to the test/mock dir. Of course you have to be sure, that your karma.conf.js file is configured correctly.
Greetings!
I had this same issue when I was doing something like var module = angular.module('my',[]). I needed to make sure it was surrounded by IIFE