{"record":{"id":"d8b8c1c040925d90","repo":"facebook/relay","slug":"this-version-of-act-requires-jest-s-timer-mocks","errorCode":null,"errorMessage":"This version of `act` requires Jest's timer mocks (i.e. jest.useFakeTimers).","messagePattern":"This version of `act` requires Jest's timer mocks \\(i\\.e\\. jest\\.useFakeTimers\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-relay/jest-react/internalAct.js","lineNumber":46,"sourceCode":"// This doesn't require a return value neither from the handler nor the\n// then function.\ninterface Thenable<out R> {\n  then<U>(\n    onFulfill: (value: R) => void | Thenable<U> | U,\n    onReject: (error: unknown) => void | Thenable<U> | U,\n  ): void | Thenable<U>;\n}\n\nlet actingUpdatesScopeDepth = 0;\n\nfunction act<T>(scope: () => Thenable<T> | T): Thenable<T> {\n  if (Scheduler.unstable_flushAllWithoutAsserting === undefined) {\n    throw Error(\n      'This version of `act` requires a special mock build of Scheduler.',\n    );\n  }\n  if (setTimeout._isMockFunction !== true) {\n    throw Error(\n      \"This version of `act` requires Jest's timer mocks \" +\n        '(i.e. jest.useFakeTimers).',\n    );\n  }\n\n  const previousIsActEnvironment = global.IS_REACT_ACT_ENVIRONMENT;\n  const previousActingUpdatesScopeDepth = actingUpdatesScopeDepth;\n  actingUpdatesScopeDepth++;\n  if (__DEV__ && actingUpdatesScopeDepth === 1) {\n    // Because this is not the \"real\" `act`, we set this to `false` so React\n    // knows not to fire `act` warnings.\n    global.IS_REACT_ACT_ENVIRONMENT = false;\n  }\n\n  const unwind = () => {\n    if (__DEV__ && actingUpdatesScopeDepth === 1) {\n      global.IS_REACT_ACT_ENVIRONMENT = previousIsActEnvironment;\n    }","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/packages/react-relay/jest-react/internalAct.js#L28-L64","documentation":"After confirming the mock Scheduler, internal act() also asserts that Jest's timer mocks are installed: setTimeout._isMockFunction must be true. act() flushes work using timer-mocked setTimeout, so with real timers (jest.useFakeTimers not called) it cannot guarantee synchronous flushing and throws.","triggerScenarios":"Invoking RelayTestingEnvironment APIs (testRender, resolve, etc.) inside a test that runs with real timers — no jest.useFakeTimers() call, or fake timers enabled only after act() was first invoked, or using a test runner whose fake timers don't set setTimeout._isMockFunction (e.g. some sinon/lolex configurations).","commonSituations":"Migrating tests to modern fake-timers APIs where the underscore mock flag differs, suites mixing vi.useFakeTimers (vitest) or sinon fake timers with jest-react, or forgetting fake timers in setupFilesAfterEach for a specific test file.","solutions":["Call jest.useFakeTimers() at the top of the test (or in setupFilesAfterAll) before using Relay test APIs","If using modern fake timers, verify jest-react's expected version compatibility or configure legacy fake timers (jest.useFakeTimers('legacy'))","Ensure all suites using RelayTestingEnvironment share a setup file that installs fake timers","Check that no other mocking library replaces global setTimeout without setting _isMockFunction"],"exampleFix":"// before\nit('renders', () => {\n  const env = createMockEnvironment();\n  TestRenderer.create(<Component />);\n});\n// after\nit('renders', () => {\n  jest.useFakeTimers();\n  const env = createMockEnvironment();\n  TestRenderer.create(<Component />);\n});","handlingStrategy":"try-catch","validationCode":"// at top of test file\nif ((global.setTimeout as any)._isMockFunction !== true) {\n  jest.useFakeTimers();\n}","typeGuard":null,"tryCatchPattern":"try {\n  env.execute({...}).toPromise();\n  jest.runAllTimers();\n} catch (e) {\n  if (String(e.message).includes('timer mocks')) {\n    jest.useFakeTimers();\n  }\n  throw e;\n}","preventionTips":["Install jest.useFakeTimers() in a shared setup file for all Relay test suites","Confirm fake-timer implementation sets setTimeout._isMockFunction","Avoid mixing sinon/vitest fake timers with jest-react"],"tags":["relay","testing","jest","fake-timers","act"],"backgroundTag":"act-mock-scheduler-missing","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}