According to the docs one can increase the default async timeout from 5000ms using the jest-object
More specifically, by using the jestsettimeouttimeout
The issue I am facing is I am running a series of tests against an API that is very slow, 5-15 second response times, configuring this jest object at the top of each test is painfully annoying.
Is it possible to declare these settings once before all test files are run?
Jest offers a testTimeout configuration option you can add to your package.json:
"jest": {
"testTimeout": 15000,
}
OK, putting bits together:
Option "setupTestFrameworkScriptFile" was replaced by configuration "setupFilesAfterEnv", which supports multiple paths
https://jestjs.io/docs/en/jest-object#jestsettimeouttimeout
https://jestjs.io/docs/en/jest-object#jestdisableautomock
The Jest search box doesn't actually return anything when you search for: setupFilesAfterEnv
And docs talk about: setupTestFrameworkScriptFile (which also doesn't return anything on the search:/ )
Anyway, the docs leave you scratching your head but this works:
jest.config.js:
module.exports = {
setupFilesAfterEnv: ['./setup.js'],
setup.js:
jest.setTimeout(10000); // in milliseconds
The jest folks should make it easier to find this information.
Use testTimeout. In yourjest.config.js (or similar), add the following:
export SECONDS = 1000;
module.exports = {
testTimeout: 60 * SECONDS
}
If you are working with react and initializing you app using create-react-app, then under your src/ directory you should have a file named setupTests.js. Here you can setup a global timeout for all of your tests just by insert this line after the import statement for #testing-libary
jest.setTimeout(15000); // in milliseconds
Related
I have a Cypress project where I use the Cypress session API to maintain a session throughout features.
Now I try switching from the deprecated Klaveness Cypress Cucumber Preprocessor to the replacement, Badeball's Cypress Cucumber Preprocessor. But I am running into an issue; the beforeEach() step where my authentication takes place gets repeated several times before the tests start. Eventually, Cypress "snaps out of it" and starts running the actual tests - but obviously this is very resource and time intensive, something is going wrong.
My setup:
Dependencies:
"cypress": "^9.6.1",
"#badeball/cypress-cucumber-preprocessor": "^9.1.3",
index.ts:
beforeEach(() => {
let isAuthInitialized = false;
function spyOnAuthInitialized(window: Window) {
window.addEventListener('react:authIsInitialized', () => {
isAuthInitialized = true;
});
}
login();
cy.visit('/', { onBeforeLoad: spyOnAuthInitialized });
cy.waitUntil(() => isAuthInitialized, { timeout: 30000 });
});
login() function:
export function login() {
cy.session('auth', () => {
cy.authenticate();
});
}
As far as I can see, I follow the docs for cy.session almost literally.
My authenticate command has only application specific steps, it does include a cy.visit('/') - after which my application is redirected to a login service (different domain) and then continues.
The problem
cy.session works OK, it creates a session on the first try - then each subsequent time it logs a succesful restore of a valid session. But this happens a number of times, it seems to get stuck in a loop.
Screenshot:
It looks to me like cy.visit() is somehow triggering the beforeEach() again. Perhaps clearing some session data (localstorage?) that causes my authentication redirect to happen again - or somehow makes Cypress think the test starts fresh. But of course beforeEach() should only happen once per feature.
I am looking at a diff of my code changes, and the only difference except the preprocessor change is:
my .cypress-cucumber-preprocessorrc.json (which I set up according to the docs
typing changes, this preprocessor is stricter about typings
plugins/index.ts file, also set up according to the docs
Am I looking at a bug in the preprocessor? Did I make a mistake? Or something else?
There are two aspects of Cypress + Cucumber with preprocessor that make this potentially confusing
Cypress >10 "Run all specs" behaviour
As demonstrated in Gleb Bahmutov PhD's great blog post, if you don't configure Cypress to do otherwise, running all specs runs each hook before each test. His proposed solution is to not use the "run all specs" button, which I find excessive - because there are ways around this; see below for a working solution with the Cucumber preprocessor.
Note: as of Cypress 10, "run all specs" is no longer supported (for reasons related to this unclarity).
Cucumber preprocessor config
The Cypress Cucumber preprocessor recommends to not use the config option nonGlobalStepDefinitions, but instead configure specific paths like (source):
"stepDefinitions": [
"cypress/integration/[filepath]/**/*.{js,ts}",
"cypress/integration/[filepath].{js,ts}",
"cypress/support/step_definitions/**/*.{js,ts}",
]
}
What it doesn't explicitly state though, is that the file which includes your hooks (in my case index.ts) should be excluded from these paths if you don't want them to run for each test! I could see how one might think this is obvious, but it's easy to accidentally include your hooks' file in this filepath config.
TLDR: If I exclude my index.ts file which includes my hooks from my stepDefinitions config, I can use "run all specs" as intended - with beforeEach() running only once before each test.
I have read and tried the options described in every stackoverflow thread related to this issue but I'm tempted to believe they're all out of date and no longer reflect jest behaviour.
I have a configuration service which returns a default value or a value from the environment.
During tests, I need to overwrite process.env values such as:
process.env.config_CORS_ENABLED = overwrittenAllConfig;
// expecting them to be overwritten
const corsEnabled = allConfigs.get('CORS_ENABLED');
expect(corsEnabled).toStrictEqual(overwrittenAllConfig);
Everything works fine on windows but on WSL and linux workers during pipelines, the value from the environment is never set.
I have beforeEach and afterEach hooks:
afterEach(async () => {
process.env = env;
});
beforeEach(async () => {
jest.resetModules();
process.env = { ...env };
and at the beginning of the describe block:
const env = process.env;
I have also tried the Object.assign() strategy for the whole process.env object but that didn't work either, and upon logging the process.env object after assigning it has a ton of values unrelated to what I've assigned to it.
I've also tried the --runInBand and the --maxWorkers 1 option to make sure that there aren't conflicts, but that didn't do anything.
I can't be setting up env variables using .dotEnv() as I need to assign multiple different values between expectations in some cases.
This is a very reasonable real-world usage and I'm just shocked at the mountain of issues I've had trying to get this working so far.
Happy to try any suggestions. An unreasoanble amount of time has already been spent reading threads and blogs and documentation attempting to get this working.
Dynamic imports might be the answer, as described in Dynamically import module in TypeScript.
When you import the module to be tested (allConfigs) at the top of the file, it will import process before you've intercepted it. Therefore remove that import at the top, and do something like this:
const allConfigs = await import('<correctPath>/allConfigs');
const corsEnabled = allConfigs.get('CORS_ENABLED');
Please note that dynamic imports require an await, so you'll need to mark your test with async.
I have some NodeJS logging done via console.log() internally (its actually loglevel) and as I see it, Jest tags console.log output with console.log ../path/to/string/with/console.log/call:line# for whatever reason:
I haven't found any related options in the docs. How can I disable it?
IMPORTANT:
I had the curiosity to take a look to the answer mentioned in the first answer, wich it says:
Looking at the source code for Jest, it doesn't seem like there is a
neat way to turn those messages off.
And I noticed an update marked on the answer and resolves the problem.
Solution:
Just add this code to your test:
beforeEach(() => {
global.console = require('console');
});
Create a global configuration test file e.g. src/test/config.js, add this line to that file:
jest.spyOn(console, "log").mockImplementation();
add this to jest config:
setupFilesAfterEnv: ['./src/test/config.js']
you can also use that file for global cleanup, before/after each etc
Thanks #Anders Carstensen, I've looked at the answer you mentioned and it says:
Looking at the source code for Jest, it doesn't seem like there is a neat way to turn those messages off.
Not an option for me to write my own console, so I'll just stick with Mocha/Sinon for now.
tslalamam answer code not worked for me, but this one works
1: Create a file with this code (e.g. config.js)
import console from "console"
global.console = console
2: Add this line to your jest.config.js
setupFilesAfterEnv: ["./config.js"]
Before:
After:
Enjoi!
when running a test locally it succeeds, but when configuring a remote grid, it fails with
1) Scenario: Login - features/api.feature:10
Step: When he enters his credentials - features/api.feature:13
Step Definition: node_modules/serenity-js/src/serenity-cucumber/webdriver_synchroniser.ts:46
Message:
function timed out after 5000 milliseconds
How can I increase the timeout value?
Thanks & Ciao
Stefan
Hi Stefan and thanks for giving Serenity/JS a try!
You have a couple of options here, depending on what is timing out.
As it's Protractor that's in charge of the timeouts, you'll need to look into your protractor.conf.js file.
Let's assume that your protractor.conf.js file looks more or less like the snippet below. I omit the Serenity/JS and Cucumber.js config for brevity as they're described at serenity-js.org:
exports.config = {
baseUrl: 'http://your.webapp.com',
// Serenity/JS config
framework: ...
specs: [ 'features/**/*.feature' ],
cucumberOpts: {
// ...
},
};
0. Increasing the overall timeout
To start with, you might want to increase the overall timeout of all the tests (for Protractor 5.0.0 the default value is set to 11s).
To do this, add the allScriptsTimeout entry to your config:
exports.config = {
allScriptsTimeout: <appropriate_timeout_in_millis>
// ... rest of the config file
}
1. Loading the page
If the webapp under test is slow to load, you can tweak the getPageTimeout property (default set to 10s):
exports.config = {
getPageTimeout: <appropriate_timeout_in_millis>
// ... rest of the config file
}
2. A specific Cucumber step
If a specific Cucumber step is timing out (which is most likely the case here, as Cucumber.js sets the default value of the cucumber step timeout to 5s), you can increase the timeout by changing the step definition (value in millis):
this.Given(/^When he enters his credentials$/, { timeout: 10 * 1000 }, () => {
return stage.theActorInTheSpotlight().attemptsTo(
Login.withTheirCredentials()
);
});
Please note that in the above answer I'm assuming that you're using Serenity/JS with Cucumber to test an Angular app. If you're using a different web framework (like React), the test might also time out when Protractor is waiting for Angular to load.
If this describes your scenario, you might want to ignoreSynchronization:
exports.config = {
onPrepare: function() {
browser.ignoreSynchronization = false;
}
// ... rest of the config file
}
To find out more, check out the Protractor documentation and the already mentioned Cucumber docs. I'll also add an article on serenity-js.org shortly to describe the different options so everything is in one place :-)
Hope this helps!
Jan
Hello i have some problem with the bootstrap of sails, i need run a function that take approximately a minute in finished, before sails initialize, so tried do, in the bootstrap hook, but i got this error:
warn: Bootstrap is taking unusually long to execute its callback (2000 milliseconds).
Perhaps you forgot to call it? The callback is the first argument of the function, `cb`.
and searching in internet a the solution of the people was that, i have to create:
config/hookTimeout.js
and put inside :
module.exports.hookTimeout = {
hookTimeout:120000
}
to override the time of load, but still i get the same error, but i figurethat the other hooks had the hookTimeout = 120000, just the bootstrap hook dont.
The field name is bootstrapTimeout instead of hookTimeout (see here for more details).
And your config file (with a name as you like) should be as follows (nothing after module.exports):
module.exports = {
bootstrapTimeout: 60000, // in millis
};
Check if you call callback in the bootstrap file.
The simples version of config/bootstrap.js should be like next:
module.exports.bootstrap = function(cb) {
cb();
};