How to add function call to jest.config.js file? - javascript

I am trying to add jest-json-schema to my Jest tests. In the Readme file they state that:
*In any test file:
import { matchers } from 'jest-json-schema';
expect.extend(matchers);
Or if you want it available for all test files then set it up the same way in a test framework script file*
But I don't understand how to do it. Following docs in the jest documentation I created a file jest.config.js with
module.exports = async () => {
return {
verbose: true,
};
};
But cannot figure out how to actually combine the import and expect.extend(matchers) with the jest.config.js file. I'm getting errors like Unresolved function or method extend() when trying to return it within the block.

Related

How to use functions from different part of my code in jest testing?

I'm trying to write a test in jest.
I have 2 functions in a different js file that i need to use in order to pass
data to the function im testing.
i tried to use:
import {func} from './funcfile' gives:
SyntaxError: Cannot use import statement outside a module
const {func} = require('./funcfile') gives:
SyntaxError: Unexpected token 'export'
looking at other topics and google, tried every dependency installation and added configurations to package.json, jest.config.js, .babelrc, babel.config.js.
the only thing that happened is getting an error around type ErrorHandler = ...
where it says a syntax error again excepted ";"
i reverted everything therefore i don't have the files with the changes, willing to try any solution you may seem fit.
it crashes on export const phone_number and never event get to the getSubCategory export line....
Edit:
Been asked to add some more code so others could understand better,
Thing is there is not much more code.
I have a file with lots of export const = ;
(as described in photo)
and eventually the function export const (as described in photo)
on my jest file i just have the import/ require line I added and the test fails there.
the error i get when using the suggested answer :
You can import your utils class and use constants as properties of this exported module, e.g.
import * as UTILS from './utils';
...
UTILS.getSubCategoryId('return input')
where utils is
export const getSubCategoryId = (category) => category;
Please check example
https://stackblitz.com/edit/typescript-rujqvm?file=index.ts
Combined with VadimB solution had to add these lines to .babelrc on root directory
{
"env": {
"test": {
"plugins": ["#babel/plugin-transform-modules-commonjs"]
}
}
}
Now its all up and working

Cypress not recognizing my imported module from outside /cypress directory

I am trying to import a module from a file outside my /cypress directory into the /cypress/integration directory's test.spec.js file like so:
import { LAB_MODEL } from '../../models/search/lab-model';
But inside this imported module "LAB_MODEL" there are other files being imported using the "##" at the start of the file imports like
import ExperimentDetails from "##/components/experiment/ExperimentDetails";
and I think this is why Cypress isn't working and giving me this error:
Error: Webpack Compilation Error
./models/search/lab-model.js
Module not found: Error: Can't resolve '##/components/experiment/ExperimentDetails' in '/Users/hidden/models/search'
resolve '##/components/experiment/ExperimentDetails' in '/Users/hidden/models/search'
Parsed request is a module
using description file: /Users/hidden/package.json (relative path: ./models/search)
Field 'browser' doesn't contain a valid alias configuration
resolve as module
So I think this is the reason why my test won't run, but I have no idea how to make Cypress recognize "##" imports and can't find any documentation/stackoverflow answers, any help is appreciated, thanks!
##/ looks like something that gets translated into a full path during the Nuxt build.
(ref The alias Property).
Cypress has a separate build that doesn't know about this Nuxt feature. You could try to replicate it with some webpack config via a preprocessor, but another way is to have your Nuxt app put a reference to lab_model on the window object
// somewhere in the Nuxt app
if (window.Cypress) {
window.lab_model = LAB_MODEL;
}
then at the top of the test
const lab_model = cy.state('window').lab_model;
This has the benefit of giving you the exact same instance of lab_model, in case you wanted to stub something.
In a starter Nuxt app, I added the code window.lab_model = LAB_MODEL in /pages/index.vue, but you can add it in any component that imports it, right after the import statement.
In the spec add a .should() to test the property exists, to allow the app time to settle.
it('gets labModel from the Nuxt app', () => {
cy.visit('http://localhost:3000/')
cy.window()
.should('have.property', 'lab_model') // retries until property appears
.then(labModel => {
console.log(labModel)
// test with labModel here
})
})

How can I run a global setup script before any mocha test in watch mode

I want to run mocha tests in a TDD manner (--watch mode), which works fine.
But I have a "global setup.js" file, which mocks part of the application, that is used by most tests.
If I run the tests normally or in watch mode for the first time everything is fine because the setup script loads.
If a test or source file is changed, however, only the relevant tests run (sounds awesome in theory) but since my global mocking script is not run the tests fail.
How can I execute a setup script each time (once per overall test run) even in watch mode with mocha?
This is the command I use:
vue-cli-service test:unit --watch
# pure mocha would be (I assume)
mocha 'tests/**/*.spec.js' --watch
I have tried using the --require and --file option, but they are also not rerun on file changes.
I am using a vue app created with the VUE CLI and this is how my code looks
// setup.spec.js
import { config } from "#vue/test-utils";
before(() => {
config.mocks["$t"] = () => {};
});
// some_test.spec.js
import { expect } from "chai";
import { shallowMount } from "#vue/test-utils";
import MyComp from "#/components/MyComp.vue";
describe("MyComp", () => {
it("renders sth", () => {
const wrapper = shallowMount(MyComp);
expect(wrapper.find(".sth").exists()).to.be.true;
});
});
This isn't a very satisfying answer because it feels like there should be a better way but you can import your setup script into the individual test files.
For example:
// some_test.spec.js
import 'setup.spec.js' //<-- this guy right here
import { expect } from "chai";
import { shallowMount } from "#vue/test-utils";
import MyComp from "#/components/MyComp.vue";
describe("MyComp", () => {
it("renders sth", () => {
const wrapper = shallowMount(MyComp);
expect(wrapper.find(".sth").exists()).to.be.true;
});
});
Feels sub optimal, but it is better than replicating logic everywhere.
Have you tried utilizing .mocharc.js file to setup your mocha configurations before you run a test?
'use strict';
module.exports = {
package: './package.json',
watch: true,
timeout: 100000
};

Shared utils functions for testing with Jest

I have some utils functions that I'm using among various Jest tests, for example a function like this, for mocking a fetch response:
export const mockFetchJsonResponse = (data) => {
ok: () => true,
json: () => data
};
I would like to share those functions in a way that I can import them and reuse among my tests. For example:
// Some .spec.jsx file
// ...
import {mockFetchJsonResponse} from 'some/path/to/shared/tests/utils.jsx'
// Then I can use mockFetchJsonResponse inside this test
// ...
Where should I place such common utils functions?
My project folder looks like this:
components/
CompOne/
__tests__
index.jsx
CompTwo/
__tests__
...
utils/
__tests__
http.js
user.js
...
Should I place them inside the utils folder together with other utils functions that I use for my project? Then should I write unit tests also for these functions?
There is an ability to expose helpers as global functions without any need to import modules explicitly.
Jest allows to configure some files will be run before every test file executed through setupFiles configuration option
Also Jest provides global object that you can modify and everything you put there will be available in your tests.
Example
package.json:
"jest": {
"setupFiles": ["helpers.js"]
}
helpers.js:
global.mockFetchJsonResponse = (data) => {
ok: () => true,
json: () => data
};
somecomponent.test.js:
mockFetchJsonResponse(); // look mom, I can call this like say expect()!
With TypeScript
TypeScript will complain with cannot find name 'mockFetchJsonResponse'. You can fix that by adding a declaration file:
helpers.d.ts:
declare function mockFetchJsonResponse(data: any): any;
Create a new tsconfig.test.json file and add that file to the files section and extend your main tsconfig:
{
"extends": "./tsconfig.json",
"files": ["./.jest/helpers.d.ts"]
}
In your jest.config.js file, add a new global setup for ts-jest to have jest use your new tsconfig file:
// ...
globals: {
"ts-jest": {
tsconfig: "tsconfig.test.json"
}
}
// ...
Sure it does not answer you direct question "where to put the files" but it's anyway up to you. You just need specify those files in setupFiles section. Since there is no import needed in tests it does not really matter.
As for testing test helpers I'm not sure. See it's part of testing infrastructure like spec file itself. And we don't write tests for tests or it would never stop. Sure, it's up to you - say if logic behind is really-really complex and hard to follow. But if helper provides too complex/complicated logic it would lead to tests themselves be impossible to understand, do you agree?
kudos to that article on testing compoentns with intl. Have never dealt with globals in jest before.
TL;DR; create a /__utils__/ and update testPathIgnorePatterns
Full answer:
Here's just a suggestion:
testPathIgnorePatterns: ['/__fixtures__/', '/__utils__/'],
I use /__tests__/ for the tests and within it sometimes I need to add a folder with data that will be used by those tests, so I use /__fixtures__/ folder.
Likewise, when I have a shared logic across tests, I place them at /__utils__/ folder (also within /__tests__/)
For more details, please read more about testPathIgnorePatterns
Another approach is by having a test directory and moving helpers on it.
src/
components/
utils/
...
test/
testHelpers.js
Then on the test:
// src/components/MyComponent.spec.js
import { helperFn } from '../../test/testHelpers';
Benefits:
Be explicit of where the function is coming from
Separate helpers that need to be tested from those that do not ¹
Drawbacks:
The test directory might look silly by containing just a helper file
AFAIK this approach is no where specified on official documentation
Looks like GitLab is implementing this approach on their RoR project.
¹ no matter which approach you take, please don't test the test helpers. If the helper fails then your test must fail too. Otherwise your helper is not helping at all.

TypeError when using Systemjs loaded class

I am once again puzzled by Javascript. I am using Systemjs as a module loader and have a class as follows:
export default class Tool{
constructor(state, displayText) {
this._state = state;
this._displayText = displayText;
}
get displayText() {
return this._displayText;
}
get state() {
return this._state;
}
}
I am using this class in a unit test (Karma/Mocha/Chai) as follows:
'use strict';
import Tool from '../core/model/framework/Tool';
import chai from '../../../jspm_packages/npm/chai#3.5.0';
chai.should();
describe('MenuProvider', () => {
describe('registration', () => {
it('should register a new Workbench Module', ()=> {
let tools = [];
debugger;
tools.push(new Tool('Pink Fuzzy Bunnies', 'bunnyState'));
tools.push(new Tool('Look no hands', 'nohandsstate'));
let toolboxes = [];
toolboxes.push(new Toolbox('My Shiny New Toolbox', tools));
let newModule = new WorkbenchModule('My Module', toolboxes);
let providerUnderTest = new MenuProvider();
providerUnderTest.loadModule(newModule);
provider.modules.count.should.equal(1);
provider.getModule('My Module').should.not.be.null;
});
});
});
When I hit the debugger statement Tool is undefined. I am pretty sure I have jspm configured properly for my Karma test. I can see that every file is loading correctly when I debug the Karma test.
Is there something I am missing? I would just like to be pointed in the right direction. Let me know if I need to add more of my code or config.
You aren't exporting your class. Add this to the bottom of your Tool file:
export default Tool;
I was in fact exporting my class on the first line. The problem turned out to be related to the fact that Javascript does not hoist classes. Basically the tests were trying to use the classes before they were loaded by Karma and JSPM. I was able to resolve the issue by explicitly loading the files by adding the following to my config file:
jspm: {
config: 'jspm.conf.js',
loadFiles: ['src/app/angular-bootstrap.js', 'src/app/core/model/**/*.js', 'src/app/**/*.spec.js'], //'src/app/**/!(*.e2e|*.po).js'
serveFiles: ['src/app/**/*.+(js|html|css|json|*jade*)'] // *.{a,b,c} to *.+(a|b|c) https://github.com/karma-runner/karma/issues/1532
}
This is what did the trick: 'src/app/core/model//*.js'
Just as a tangential note. I also had fits over why Karam was not loading my Jade files so I could import them using JSPM. All I had to do was add the .jade extension to the list of file types being served up by Karma.
Such as a strange and wonderful world this Javascript stuff is!

Categories