From 4c4f967bfc501f199103796d3722bfff0dbb2563 Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Sun, 11 Sep 2022 14:33:08 -0700 Subject: [PATCH 1/3] Fix LogBoxSymbolication-test Differential Revision: D39418412 fbshipit-source-id: e2b76fa91df28ce1418a487f45dbeb590a66d184 --- .../LogBox/Data/__tests__/LogBoxSymbolication-test.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Libraries/LogBox/Data/__tests__/LogBoxSymbolication-test.js b/Libraries/LogBox/Data/__tests__/LogBoxSymbolication-test.js index 1d35a1e9867ffd..072be3035cfdf2 100644 --- a/Libraries/LogBox/Data/__tests__/LogBoxSymbolication-test.js +++ b/Libraries/LogBox/Data/__tests__/LogBoxSymbolication-test.js @@ -12,6 +12,7 @@ 'use strict'; import type {StackFrame} from '../../../Core/NativeExceptionsManager'; +import type {SymbolicatedStackTrace} from '../../../Core/Devtools/symbolicateStackTrace'; jest.mock('../../../Core/Devtools/symbolicateStackTrace'); @@ -19,7 +20,7 @@ const LogBoxSymbolication = require('../LogBoxSymbolication'); const symbolicateStackTrace: JestMockFn< $ReadOnlyArray>, - Promise>, + Promise, > = (require('../../../Core/Devtools/symbolicateStackTrace'): any); const createStack = (methodNames: Array) => @@ -33,7 +34,10 @@ const createStack = (methodNames: Array) => describe('LogBoxSymbolication', () => { beforeEach(() => { jest.resetModules(); - symbolicateStackTrace.mockImplementation(async stack => stack); + symbolicateStackTrace.mockImplementation(async stack => ({ + stack, + codeFrame: null, + })); }); it('symbolicates different stacks', () => { From ffe0cd91fc288f5688b4e53805d63ce5565e6294 Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Sun, 11 Sep 2022 14:33:08 -0700 Subject: [PATCH 2/3] Allow LogBoxLog-test to work with native promises Differential Revision: D39418413 fbshipit-source-id: 7b4c96c62ada4ef7cd5231b305c926068026df38 --- .../LogBox/Data/__tests__/LogBoxLog-test.js | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/Libraries/LogBox/Data/__tests__/LogBoxLog-test.js b/Libraries/LogBox/Data/__tests__/LogBoxLog-test.js index bd26449ba0a96d..98b758d9b62dca 100644 --- a/Libraries/LogBox/Data/__tests__/LogBoxLog-test.js +++ b/Libraries/LogBox/Data/__tests__/LogBoxLog-test.js @@ -57,6 +57,10 @@ const createStack = (methodNames: Array) => methodName, })); +// Adds a new task to the end of the microtask queue, so that awaiting this +// function will run all queued immediates +const runMicrotasks = async () => {}; + describe('LogBoxLog', () => { beforeEach(() => { jest.resetModules(); @@ -132,7 +136,7 @@ describe('LogBoxLog', () => { expect(getLogBoxSymbolication().symbolicate).not.toBeCalled(); }); - it('updates when symbolication finishes', () => { + it('updates when symbolication finishes', async () => { const log = getLogBoxLog(); const callback = jest.fn(); @@ -141,7 +145,7 @@ describe('LogBoxLog', () => { expect(callback).toBeCalledWith('PENDING'); expect(getLogBoxSymbolication().symbolicate).toBeCalled(); - jest.runAllTicks(); + await runMicrotasks(); expect(callback).toBeCalledTimes(2); expect(callback).toBeCalledWith('COMPLETE'); @@ -156,13 +160,14 @@ describe('LogBoxLog', () => { getLogBoxSymbolication().symbolicate.mockClear(); log.symbolicate(callback); - jest.runAllTicks(); + + await runMicrotasks(); expect(callback).toBeCalledTimes(0); expect(getLogBoxSymbolication().symbolicate).not.toBeCalled(); }); - it('updates when symbolication fails', () => { + it('updates when symbolication fails', async () => { const error = new Error('...'); getLogBoxSymbolication().symbolicate.mockImplementation(async stack => { throw error; @@ -176,7 +181,7 @@ describe('LogBoxLog', () => { expect(callback).toBeCalledWith('PENDING'); expect(getLogBoxSymbolication().symbolicate).toBeCalled(); - jest.runAllTicks(); + await runMicrotasks(); expect(callback).toBeCalledTimes(2); expect(callback).toBeCalledWith('FAILED'); @@ -191,7 +196,8 @@ describe('LogBoxLog', () => { getLogBoxSymbolication().symbolicate.mockClear(); log.symbolicate(callback); - jest.runAllTicks(); + + await runMicrotasks(); expect(callback).toBeCalledTimes(0); expect(getLogBoxSymbolication().symbolicate).not.toBeCalled(); @@ -221,7 +227,7 @@ describe('LogBoxLog', () => { expect(getLogBoxSymbolication().symbolicate).not.toBeCalled(); }); - it('retry updates when symbolication finishes', () => { + it('retry updates when symbolication finishes', async () => { const log = getLogBoxLog(); const callback = jest.fn(); @@ -230,7 +236,7 @@ describe('LogBoxLog', () => { expect(callback).toBeCalledWith('PENDING'); expect(getLogBoxSymbolication().symbolicate).toBeCalled(); - jest.runAllTicks(); + await runMicrotasks(); expect(callback).toBeCalledTimes(2); expect(callback).toBeCalledWith('COMPLETE'); @@ -251,7 +257,7 @@ describe('LogBoxLog', () => { expect(getLogBoxSymbolication().symbolicate).not.toBeCalled(); }); - it('retry updates when symbolication fails', () => { + it('retry updates when symbolication fails', async () => { const error = new Error('...'); getLogBoxSymbolication().symbolicate.mockImplementation(async stack => { throw error; @@ -265,7 +271,7 @@ describe('LogBoxLog', () => { expect(callback).toBeCalledWith('PENDING'); expect(getLogBoxSymbolication().symbolicate).toBeCalled(); - jest.runAllTicks(); + await runMicrotasks(); expect(callback).toBeCalledTimes(2); expect(callback).toBeCalledWith('FAILED'); @@ -289,7 +295,7 @@ describe('LogBoxLog', () => { expect(callback).toBeCalledWith('PENDING'); expect(getLogBoxSymbolication().symbolicate).toBeCalled(); - jest.runAllTicks(); + await runMicrotasks(); expect(callback).toBeCalledTimes(2); expect(callback).toBeCalledWith('COMPLETE'); From 64656776ef739ba5e8e96a1acc5d94dc300fcac6 Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Sun, 11 Sep 2022 14:33:27 -0700 Subject: [PATCH 3/3] Stop polyfilling Promise in Jest tests Summary: We've used this Promise polyfill in Jest setup since at least 2015 ([`3ff3987`](https://github.com/facebook/react-native/commit/3ff39870ce776c653823e1733363be0401896294)), when native Promise implementations were either non-existent or new and unstable. We no longer need it. It causes issues with "modern" timers in Jest, as documented in: - https://github.com/facebook/react-native/issues/29303 - https://github.com/facebook/jest/issues/10221 It can also obscure real issues due to its default silent handling of uncaught rejections, eg: D39418412. Changelog: [General][Changed] - Don't polyfill Promise in Jest setup Differential Revision: D39417597 fbshipit-source-id: 1773032343f914a37789c7bc43760838f2d86d31 --- jest/setup.js | 1 - 1 file changed, 1 deletion(-) diff --git a/jest/setup.js b/jest/setup.js index e422cb64460d95..36b922f3529dcf 100644 --- a/jest/setup.js +++ b/jest/setup.js @@ -21,7 +21,6 @@ global.performance = { now: jest.fn(Date.now), }; -global.Promise = jest.requireActual('promise'); global.regeneratorRuntime = jest.requireActual('regenerator-runtime/runtime'); global.window = global;