/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format * @emails oncall+react_native */ const LogBoxData = require('../Data/LogBoxData'); const TestRenderer = require('react-test-renderer'); import * as React from 'react'; import { DoesNotUseKey, FragmentWithProp, } from './__fixtures__/ReactWarningFixtures'; const installLogBox = () => { const LogBox = require('../LogBox'); LogBox.install(); }; const uninstallLogBox = () => { const LogBox = require('../LogBox'); LogBox.uninstall(); }; const BEFORE_SLASH_RE = /(?:\/[a-zA-Z]+\/)(.+?)(?:\/.+)\//; const cleanPath = message => { return message.replace(BEFORE_SLASH_RE, '/path/to/'); }; const cleanLog = logs => { return logs.map(log => { return { ...log, componentStack: log.componentStack.map(stack => ({ ...stack, fileName: cleanPath(stack.fileName), })), }; }); }; // TODO(T71117418): Re-enable skipped LogBox integration tests once React component // stack frames are the same internally and in open source. // eslint-disable-next-line jest/no-disabled-tests describe.skip('LogBox', () => { const {error, warn} = console; const mockError = jest.fn(); const mockWarn = jest.fn(); beforeEach(() => { jest.resetModules(); jest.restoreAllMocks(); mockError.mockClear(); mockWarn.mockClear(); (console: any).error = mockError; (console: any).warn = mockWarn; }); afterEach(() => { uninstallLogBox(); (console: any).error = error; (console: any).warn = warn; }); it('integrates with React and handles a key error in LogBox', () => { const spy = jest.spyOn(LogBoxData, 'addLog'); installLogBox(); // Spy console.error after LogBox is installed // so we can assert on what React logs. jest.spyOn(console, 'error'); const output = TestRenderer.create(); // The key error should always be the highest severity. // In LogBox, we expect these errors to: // - Be added to LogBox, because all errors and warnings are. // - Not call through to console.warn, because they are errors. // - Pass to console.error, with a "Warning" prefix so it does not pop a RedBox. expect(output).toBeDefined(); expect(mockWarn).not.toBeCalled(); expect(console.error.mock.calls[0].map(cleanPath)).toMatchSnapshot( 'Log sent from React', ); expect(cleanLog(spy.mock.calls[0])).toMatchSnapshot('Log added to LogBox'); expect(mockError.mock.calls[0].map(cleanPath)).toMatchSnapshot( 'Log passed to console error', ); expect(mockError.mock.calls[0][0].startsWith('Warning: ')).toBe(true); }); it('integrates with React and handles a fragment warning in LogBox', () => { const spy = jest.spyOn(LogBoxData, 'addLog'); installLogBox(); // Spy console.error after LogBox is installed // so we can assert on what React logs. jest.spyOn(console, 'error'); const output = TestRenderer.create(); // The fragment warning is not as severe. For this warning we don't want to // pop open a dialog, so we show a collapsed error UI. // That means we expect these warnings to: // - Be added to LogBox and displayed collapsed as an error. // - Not call console.warn, because they are errors in the console. // - Pass to console.error, with a "Warning" prefix so it does not pop a RedBox. expect(output).toBeDefined(); expect(mockWarn).not.toBeCalled(); expect(console.error.mock.calls[0].map(cleanPath)).toMatchSnapshot( 'Log sent from React', ); expect(cleanLog(spy.mock.calls[0])).toMatchSnapshot('Log added to LogBox'); expect(mockError.mock.calls[0].map(cleanPath)).toMatchSnapshot( 'Log passed to console error', ); expect(mockError.mock.calls[0][0].startsWith('Warning: ')).toBe(true); }); });