diff --git a/TestUtils.ts b/TestUtils.ts index ba80887bda29..1275e4ecb8eb 100644 --- a/TestUtils.ts +++ b/TestUtils.ts @@ -55,6 +55,7 @@ const DEFAULT_GLOBAL_CONFIG: Config.GlobalConfig = { testNamePattern: '', testPathPattern: '', testResultsProcessor: null, + timeout: 5000, updateSnapshot: 'none', useStderr: false, verbose: false, diff --git a/docs/CLI.md b/docs/CLI.md index 2530a940879b..d6a7a7b664cd 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -301,6 +301,10 @@ Lets you specify a custom test runner. Lets you specify a custom test sequencer. Please refer to the documentation of the corresponding configuration property for details. +### `--timeout=` + +Default timeout of the test case. If the value is 0 then the timeout is 1 193 days. + ### `--updateSnapshot` Alias: `-u`. Use this flag to re-record every snapshot that fails during this test run. Can be used together with a test suite pattern or with `--testNamePattern` to re-record snapshots. diff --git a/e2e/__tests__/__snapshots__/timeouts.test.ts.snap b/e2e/__tests__/__snapshots__/timeouts.test.ts.snap index 19ed2b0400be..2375a758ccc6 100644 --- a/e2e/__tests__/__snapshots__/timeouts.test.ts.snap +++ b/e2e/__tests__/__snapshots__/timeouts.test.ts.snap @@ -20,3 +20,37 @@ Snapshots: 0 total Time: <> Ran all test suites. `; + +exports[`exceeds the command line timeout 1`] = ` +Test Suites: 1 failed, 1 total +Tests: 1 failed, 1 total +Snapshots: 0 total +Time: <> +Ran all test suites. +`; + +exports[`does not exceed the command line timeout 1`] = ` +PASS __tests__/a-banana.js + ✓ banana +`; + +exports[`does not exceed the command line timeout 2`] = ` +Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Snapshots: 0 total +Time: <> +Ran all test suites. +`; + +exports[`if command line timeout=0 its mean no timeout 1`] = ` +PASS __tests__/a-banana.js + ✓ banana +`; + +exports[`if command line timeout=0 its mean no timeout 2`] = ` +Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Snapshots: 0 total +Time: <> +Ran all test suites. +`; diff --git a/e2e/__tests__/timeouts.test.ts b/e2e/__tests__/timeouts.test.ts index 09d38e6e9d1b..b5177166c475 100644 --- a/e2e/__tests__/timeouts.test.ts +++ b/e2e/__tests__/timeouts.test.ts @@ -60,3 +60,73 @@ test('does not exceed the timeout', () => { expect(wrap(summary)).toMatchSnapshot(); expect(status).toBe(0); }); + +test('exceeds the command line timeout', () => { + writeFiles(DIR, { + '__tests__/a-banana.js': ` + + test('banana', () => { + return new Promise(resolve => { + setTimeout(resolve, 1000); + }); + }); + `, + 'package.json': '{}', + }); + + const {stderr, status} = runJest(DIR, [ + '-w=1', + '--ci=false', + '--timeout=200', + ]); + const {rest, summary} = extractSummary(stderr); + expect(rest).toMatch( + /(jest\.setTimeout|jasmine\.DEFAULT_TIMEOUT_INTERVAL|Exceeded timeout)/, + ); + expect(wrap(summary)).toMatchSnapshot(); + expect(status).toBe(1); +}); + +test('does not exceed the command line timeout', () => { + writeFiles(DIR, { + '__tests__/a-banana.js': ` + + test('banana', () => { + return new Promise(resolve => { + setTimeout(resolve, 200); + }); + }); + `, + 'package.json': '{}', + }); + + const {stderr, status} = runJest(DIR, [ + '-w=1', + '--ci=false', + '--timeout=1000', + ]); + const {rest, summary} = extractSummary(stderr); + expect(wrap(rest)).toMatchSnapshot(); + expect(wrap(summary)).toMatchSnapshot(); + expect(status).toBe(0); +}); + +test('if command line timeout=0 its mean no timeout', () => { + writeFiles(DIR, { + '__tests__/a-banana.js': ` + + test('banana', () => { + return new Promise(resolve => { + setTimeout(resolve, 6000); + }); + }); + `, + 'package.json': '{}', + }); + + const {stderr, status} = runJest(DIR, ['-w=1', '--ci=false', '--timeout=0']); + const {rest, summary} = extractSummary(stderr); + expect(wrap(rest)).toMatchSnapshot(); + expect(wrap(summary)).toMatchSnapshot(); + expect(status).toBe(0); +}); diff --git a/packages/jest-cli/src/cli/args.ts b/packages/jest-cli/src/cli/args.ts index 2f7c38aa0279..ec48ec359f13 100644 --- a/packages/jest-cli/src/cli/args.ts +++ b/packages/jest-cli/src/cli/args.ts @@ -626,6 +626,12 @@ export const options = { description: 'This option sets the URL for the jsdom environment.', type: 'string' as 'string', }, + timeout: { + description: + 'This option sets the default timeouts of test cases.' + + "If you don't want timeout set it to 0", + type: 'number' as 'number', + }, timers: { description: 'Setting this value to fake allows the use of fake timers ' + diff --git a/packages/jest-config/src/ValidConfig.ts b/packages/jest-config/src/ValidConfig.ts index 97e22dc030da..b1e743606d30 100644 --- a/packages/jest-config/src/ValidConfig.ts +++ b/packages/jest-config/src/ValidConfig.ts @@ -114,6 +114,7 @@ const initialOptions: Config.InitialOptions = { testRunner: 'jasmine2', testSequencer: '@jest/test-sequencer', testURL: 'http://localhost', + timeout: 5000, timers: 'real', transform: { '^.+\\.js$': '/preprocessor.js', diff --git a/packages/jest-config/src/__tests__/normalize.test.js b/packages/jest-config/src/__tests__/normalize.test.js index 88e557f1939e..6d721808e479 100644 --- a/packages/jest-config/src/__tests__/normalize.test.js +++ b/packages/jest-config/src/__tests__/normalize.test.js @@ -1562,3 +1562,19 @@ describe('displayName', () => { }, ); }); + +describe('timeout', () => { + it('should return timeout value if defined', () => { + console.warn.mockImplementation(() => {}); + const {options} = normalize({rootDir: '/root/', timeout: 1000}, {}); + + expect(options.timeout).toBe(1000); + expect(console.warn).not.toHaveBeenCalled(); + }); + + it('should return with 2^32 -1 if timeout=0', () => { + const {options} = normalize({rootDir: '/root/', timeout: 0}, {}); + + expect(options.timeout).toBe(Math.pow(2, 31) - 1); + }); +}); diff --git a/packages/jest-config/src/index.ts b/packages/jest-config/src/index.ts index 337e7ab47c81..9cf7161ef9ab 100644 --- a/packages/jest-config/src/index.ts +++ b/packages/jest-config/src/index.ts @@ -149,6 +149,7 @@ const groupOptions = ( testPathPattern: options.testPathPattern, testResultsProcessor: options.testResultsProcessor, testSequencer: options.testSequencer, + timeout: options.timeout, updateSnapshot: options.updateSnapshot, useStderr: options.useStderr, verbose: options.verbose, diff --git a/packages/jest-config/src/normalize.ts b/packages/jest-config/src/normalize.ts index 813706ab60f2..f84424c49a9d 100644 --- a/packages/jest-config/src/normalize.ts +++ b/packages/jest-config/src/normalize.ts @@ -40,6 +40,7 @@ import VALID_CONFIG from './ValidConfig'; const ERROR = `${BULLET}Validation Error`; const PRESET_EXTENSIONS = ['.json', '.js']; const PRESET_NAME = 'jest-preset'; +const MAX_32_BIT_SIGNED_INTEGER = Math.pow(2, 31) - 1; type AllOptions = Config.ProjectConfig & Config.GlobalConfig; @@ -789,6 +790,11 @@ export default function normalize( value = oldOptions[key]; break; } + case 'timeout': { + value = + oldOptions[key] === 0 ? MAX_32_BIT_SIGNED_INTEGER : oldOptions[key]; + break; + } case 'automock': case 'browser': case 'cache': diff --git a/packages/jest-core/src/lib/__tests__/__snapshots__/log_debug_messages.test.ts.snap b/packages/jest-core/src/lib/__tests__/__snapshots__/log_debug_messages.test.ts.snap index fc4ae3ee76e0..b3aff5324245 100644 --- a/packages/jest-core/src/lib/__tests__/__snapshots__/log_debug_messages.test.ts.snap +++ b/packages/jest-core/src/lib/__tests__/__snapshots__/log_debug_messages.test.ts.snap @@ -112,6 +112,7 @@ exports[`prints the config object 1`] = ` "testNamePattern": "", "testPathPattern": "", "testResultsProcessor": null, + "timeout": 5000, "updateSnapshot": "none", "useStderr": false, "verbose": false, diff --git a/packages/jest-jasmine2/src/index.ts b/packages/jest-jasmine2/src/index.ts index 1860ad51bf96..25c8db594d34 100644 --- a/packages/jest-jasmine2/src/index.ts +++ b/packages/jest-jasmine2/src/index.ts @@ -32,6 +32,7 @@ async function jasmine2( const reporter = new JasmineReporter(globalConfig, config, testPath); const jasmineFactory = runtime.requireInternalModule(JASMINE); const jasmine = jasmineFactory.create({ + globalConfig, process, testPath, }); diff --git a/packages/jest-jasmine2/src/jasmine/jasmineLight.ts b/packages/jest-jasmine2/src/jasmine/jasmineLight.ts index bde9103904fb..3b2ae0f88458 100644 --- a/packages/jest-jasmine2/src/jasmine/jasmineLight.ts +++ b/packages/jest-jasmine2/src/jasmine/jasmineLight.ts @@ -43,7 +43,7 @@ import Timer from './Timer'; const create = function(createOptions: Record): Jasmine { const j$ = {...createOptions} as Jasmine; - j$._DEFAULT_TIMEOUT_INTERVAL = 5000; + j$._DEFAULT_TIMEOUT_INTERVAL = createOptions.globalConfig.timeout || 5000; j$.getEnv = function(options?: object) { const env = (j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options)); diff --git a/packages/jest-types/src/Config.ts b/packages/jest-types/src/Config.ts index b5a479c884d5..2ac8785baa01 100644 --- a/packages/jest-types/src/Config.ts +++ b/packages/jest-types/src/Config.ts @@ -207,6 +207,7 @@ export type InitialOptions = { testRunner?: string; testSequencer?: string; testURL?: string; + timeout?: number; timers?: 'real' | 'fake'; transform?: { [key: string]: string; @@ -344,6 +345,7 @@ export type GlobalConfig = { testPathPattern: string; testResultsProcessor: string | null | undefined; testSequencer: string; + timeout: number; updateSnapshot: SnapshotUpdateState; useStderr: boolean; verbose: boolean | null | undefined; @@ -489,6 +491,7 @@ export type Argv = Arguments< testRunner: string; testSequencer: string; testURL: string; + timeout: number | null | undefined; timers: string; transform: string; transformIgnorePatterns: Array;