TestCafe: import tests from another file into the current fixture - node.js

I have a file tests.js that contains some test(...) definitions. I want to reuse these tests across multiple fixtures, preferably without making any modifications to the original code.
So I wrote a main.js that defines a fixture and imports tests.js, thereby "assembling" a test suite. (In case that works, I could write different driver files with different fixtures, importing the same tests.js from within each.)
However, I'm getting a test is not defined error when trying to execute main.js:
C:\Windows\Temp\dummy>testcafe chrome main.js --debug-on-fail
ERROR Cannot prepare tests due to an error.
ReferenceError: test is not defined
at Object.<anonymous> (C:\Windows\Temp\dummy\tests.js:1:1)
at Object.<anonymous> (C:\Windows\Temp\dummy\main.js:7:1)
Type "testcafe -h" for help.
Minimal sample:
// tests.js
test('wait', async t => {
await t.wait(1);
});
// main.js
fixture `here goes the name`
.page("http://localhost:3000")
.beforeEach(async t => {
// do stuff
});
import "./tests";
/*
trick testcafe to scan the file;
based on https://github.com/DevExpress/testcafe/issues/2889#issuecomment-423859785
test();
*/
I already tried:
removing the block comment hack (test();) - which gives ERROR No tests to run. Either the test files contain no tests or the filter function is too restrictive.
moving the tests.js import to the top - still gives test is not defined
importing testcafe from within main.js and tests.js - same error
Is there a way to make the test function "visible" to other files imported by the testcafe entrypoint file? Or will I actually need to modify my tests.js file in order to get this working? Maybe by adding the test definitions into a method, and invoking it from within main.js - as in the original code sample of this issue?

TestCafe doesn't allow calling fixture and test functions outside the test scope. You can wrap your tests from the tests.js file in a function and call this function in the main.js file:
// tests.js
export default function () {
test('Test 1', () => {});
test('Test 2', () => {});
test('Test 3', () => {});
}
// main.js
import defineTests from './tests';
defineTests();
See also: Organize Tests

Try to add the option --disable-test-syntax-validation on the TestCafe command-line
(works only in latest TestCafe version).

Related

Reuse Jest module mocks across tests

I want to mock a module for a test. Everything works, but I have to copy/paste the same code into every test file. How can I make this more maintainable?
(This is using Babel and TypeScript in a Next.js project.)
The production code looks like this:
import { useRouter } from 'next/router';
// Then call the hook in a React component:
const router = useRouter();
The test code:
// I need to access these mocks in the tests
const mockRouterPush = jest.fn();
const mockRouterBack = jest.fn();
jest.mock('next/router', () => ({
useRouter: () => ({
push: mockRouterPush,
query: { segment: 'seg1' },
back: mockRouterBack,
}),
}));
This works fine. The module and its hook are mocked for the test file, and I can refer to the mocks in the tests. The issue is that it's difficult to maintain across multiple test files.
Calls to jest.mock() are hoisted to the top of the file, and can only refer to variables that start with the word 'mock'.
With other mocks I've used require within the module factory instead of import; this works and reduces boilerplate, but (a) makes it more difficult for the tests to refer to the mocks and (b) my IDE (VSCode) won't auto-update require paths like it does with imports when I move files. For example:
jest.mock('react-i18next', () => {
// Sometimes the path is '../../../testhelpers' etc.
const { mockUseTranslation } = require('./testhelpers');
return {
useTranslation: mockUseTranslation,
};
});
I've tried doMock and createMockFromModule without success.
How do other folks deal with this issue?
Maybe using the __mocks__ directory can help you.
from the docs:
Manual mocks are defined by writing a module in a mocks/ subdirectory immediately adjacent to the module. For example, to mock a module called user in the models directory, create a file called user.js and put it in the models/mocks directory.
You can also mock modules from the node_modules directory.
Manual Mocks

Can I get Jest test instance id or context

Suppose my test setup has the following pattern:
Build a model for this test
Initialize some application based on this model
Test the functioniality in the application
As part of #3, there are some async functions which can be run.
I have thousands of tests and want to create a safeguard against leaks of async functions into other tests- in other words, developers who forget to await for the result
My idea is as follows - Implement an afterEach in a global context which would check if an applcation instance was created for this test. If it was, I can catch all open async functions from here, and throw an error
To do this, I would need to have a testId instance or test context to which I can register the app instance when creating it for tests.
If we were using jasmine and old ES5 syntax, jasmine has a userContext feature which would make this easy:
it('some test', async function(){
this.appInstance = createAppInstance(model)
...
})
afterEach(function(){
if(this.appInstance){
...
}
})
Is there a way to do something like this in jest?

Global beforeAll in Jest?

I need to simulate different window sizes in my tests using React Testing Library and Jest.
Currently I'm having to have this beforeAll in every test file:
import matchMediaPolyfill from 'mq-polyfill';
beforeAll(() => {
matchMediaPolyfill(window)
window.resizeTo = function resizeTo(width, height) {
Object.assign(this, {
innerWidth: width,
innerHeight: height,
outerWidth: width,
outerHeight: height,
}).dispatchEvent(new this.Event('resize'))
}
})
Which I use like so:
it('does something at small screen sizes', async () => {
window.resizeTo(320, 800);
// actual test here
Can I have a global beforeAll that will apply to every test file in my project?
The docs mention globalsetup:
https://jestjs.io/docs/en/configuration#globalsetup-string
However it errors as it doenst recognise the beforeAll function. I seemed to me that that option is meant for setting up an environment but not adding something to the test files?
globalSetup runs in another process and cannot access beforeAll or other variables from test scope. It's meant for initializations made before any test is started, e.g. setting up a server, like the documentation shows.
It's setupFiles that runs in test process. beforeAll should be executed after Jest environment is initialized, so it should be moved to setupFilesAfterEnv.

Jest Mock Globally From a Node Module

I am writing a series of Node modules that require a bunch of common Jest mocks to be setup before I can write unit tests.
I am trying to refactor the unit test setup into a separate module so I can avoid rewriting the setup each time.
The problem is that when I import the following code as a module it no longer mocks the other libraries, while it works just fine when the mocks are set up in a utility file.
Working Code:
jest.mock('#actions/core')
jest.mock('#actions/github')
const { GitHub, context} = require('#actions/github')
const core = require('#actions/core')
GitHub.mockImplementation(() => {
return {
{
repos: {
getContents: jest.fn()
}
}
}
}
module.exports = { core, GitHub, context }
I keep this in a utils.js file next to my test files and import it like const { core, GitHub, context } = require('./utils.js') and everything mocks as I expect. I can run expect().toHaveBeenCalledTimes() and get the numbers I expect.
The problem appears when I move utils.js to another module and require it.
I know that at bottom of the jest documentation it says "...Another file that imports the module will get the original implementation even if it runs after the test file that mocks the module." But I am seeing this work inconsistently with the external file.
Anyone know how to get mocking setup in external modules?

Changing mocha tests to jest tests

I'm having trouble changing my mocha tests to jest tests.
I have three test files with three classes: FirstTestGroup, SecondTestGroup and ThirdTestGroup, each with a static execute method, that contains some tests, like this:
class FirstTestGroup {
execute(params) {
describe('some tests', function tests() {
it('one test', () => {
// uses params
});
...
});
...
}
}
Each of those execute methods use the same parameters. These parameters are created in an async before call, like shown bellow.
describe('My Tests', function testSuite() {
let params;
before('param creation', async function asyncFunc() {
// creates params asynchronously
});
it('should pass all', () => {
FirstTestGroup.execute(params);
SecondTestGroup.execute(params);
ThirdTestGroup.execute(params);
});
});
The it('should pass all', ...) is needed because everything inside a describe is run instantly, so params would be passed as null without it. This works in mocha because "it"s can be nested, but apparently this is not the case for jest.
I could make the beforeAll (equivalent of before in jest) be called each time before a test group is run, but I didn't want to do that as this seems inefficient.
I could also place the code inside the before call before the describe('My Tests', ...) is defined. This seems wrong as this should be part of the describe only.
I couldn't find anything in the jest documentation that could help me with that.
Am I doing something wrong? Is there a way to achieve this using jest, even if I have to restructure the tests? But I'd like to keep the tests in different files.
This is my first question here, so please tell me if more info is needed as I'm not used writting here.
Have you tried Jest-Codemods yet?
Jest-Codemods allows you to convert your Mocha, AVA, Jasmine tests into equivalent Jest tests. It would also help you migrate assertion libraries such as Chai and Expect.
The way you do it:
Install jest-codemods with npm install -g jest-codemods
Go to your project and execute jest-codemods
It will ask you Which test library would you like to migrate from?
Select Mocha by using arrow keys (As you want to migrate from Mocha)
Next, It will ask you Will you be using Jest on Node.js as your test runner?
Select Yes, use the globals provided by Jest (recommended)
Last, You need to provide file name on which you are working to migrate from Mocha to Jest.
And you are done!
It will automatically migrate your code from Mocha to Jest. No need to touch code. That's one of the most powerful feature of Jest which would save your time and you don't need to worry about changing mocha tests to jest tests.

Resources