-
Notifications
You must be signed in to change notification settings - Fork 24.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add React integration tests for LogBox
Summary: This diff adds some integration tests that throw read React errors and asserts on the LogBox data. Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D22752147 fbshipit-source-id: eb2e1542524d67558f2450130015164acd4d6093
- Loading branch information
1 parent
4720ee9
commit 7af3f6e
Showing
3 changed files
with
256 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
/** | ||
* 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 | ||
*/ | ||
|
||
'use strict'; | ||
|
||
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), | ||
})), | ||
}; | ||
}); | ||
}; | ||
|
||
describe('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(<DoesNotUseKey />); | ||
|
||
// 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(<FragmentWithProp />); | ||
|
||
// 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); | ||
}); | ||
}); |
34 changes: 34 additions & 0 deletions
34
Libraries/LogBox/__tests__/__fixtures__/ReactWarningFixtures.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/** | ||
* 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 | ||
*/ | ||
|
||
'use strict'; | ||
|
||
import {Text} from 'react-native'; | ||
import * as React from 'react'; | ||
|
||
export const DoesNotUseKey = () => { | ||
return ( | ||
<> | ||
{['foo', 'bar'].map(item => ( | ||
<Text>{item}</Text> | ||
))} | ||
</> | ||
); | ||
}; | ||
|
||
export const FragmentWithProp = () => { | ||
return ( | ||
<React.Fragment invalid="prop"> | ||
{['foo', 'bar'].map(item => ( | ||
<Text key={item}>{item}</Text> | ||
))} | ||
</React.Fragment> | ||
); | ||
}; |
94 changes: 94 additions & 0 deletions
94
Libraries/LogBox/__tests__/__snapshots__/LogBox-integration-test.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`LogBox integrates with React and handles a fragment warning in LogBox: Log added to LogBox 1`] = ` | ||
Array [ | ||
Object { | ||
"category": "Warning: Invalid prop \`%s\` supplied to \`React.Fragment\`. React.Fragment can only have \`key\` and \`children\` props.", | ||
"componentStack": Array [ | ||
Object { | ||
"content": "Fragment", | ||
"fileName": "ReactWarningFixtures.js", | ||
"location": Object { | ||
"column": -1, | ||
"row": 28, | ||
}, | ||
}, | ||
], | ||
"level": "warn", | ||
"message": Object { | ||
"content": "Warning: Invalid prop \`invalid\` supplied to \`React.Fragment\`. React.Fragment can only have \`key\` and \`children\` props.", | ||
"substitutions": Array [ | ||
Object { | ||
"length": 7, | ||
"offset": 23, | ||
}, | ||
], | ||
}, | ||
}, | ||
] | ||
`; | ||
|
||
exports[`LogBox integrates with React and handles a fragment warning in LogBox: Log passed to console error 1`] = ` | ||
Array [ | ||
"Warning: Invalid prop \`invalid\` supplied to \`React.Fragment\`. React.Fragment can only have \`key\` and \`children\` props. | ||
in Fragment (at ReactWarningFixtures.js:28)", | ||
] | ||
`; | ||
|
||
exports[`LogBox integrates with React and handles a fragment warning in LogBox: Log sent from React 1`] = ` | ||
Array [ | ||
"Warning: Invalid prop \`%s\` supplied to \`React.Fragment\`. React.Fragment can only have \`key\` and \`children\` props.%s", | ||
"invalid", | ||
" | ||
in Fragment (at ReactWarningFixtures.js:28)", | ||
] | ||
`; | ||
|
||
exports[`LogBox integrates with React and handles a key error in LogBox: Log added to LogBox 1`] = ` | ||
Array [ | ||
Object { | ||
"category": "Warning: Each child in a list should have a unique \\"key\\" prop.%s%s See https://fb.me/react-warning-keys for more information.", | ||
"componentStack": Array [ | ||
Object { | ||
"content": "Text", | ||
"fileName": "ReactWarningFixtures.js", | ||
"location": Object { | ||
"column": -1, | ||
"row": 20, | ||
}, | ||
}, | ||
], | ||
"level": "warn", | ||
"message": Object { | ||
"content": "Warning: Each child in a list should have a unique \\"key\\" prop. See https://fb.me/react-warning-keys for more information.", | ||
"substitutions": Array [ | ||
Object { | ||
"length": 0, | ||
"offset": 62, | ||
}, | ||
Object { | ||
"length": 0, | ||
"offset": 62, | ||
}, | ||
], | ||
}, | ||
}, | ||
] | ||
`; | ||
|
||
exports[`LogBox integrates with React and handles a key error in LogBox: Log passed to console error 1`] = ` | ||
Array [ | ||
"Warning: Each child in a list should have a unique \\"key\\" prop. See https://fb.me/react-warning-keys for more information. | ||
in Text (at ReactWarningFixtures.js:20)", | ||
] | ||
`; | ||
|
||
exports[`LogBox integrates with React and handles a key error in LogBox: Log sent from React 1`] = ` | ||
Array [ | ||
"Warning: Each child in a list should have a unique \\"key\\" prop.%s%s See https://fb.me/react-warning-keys for more information.%s", | ||
"", | ||
"", | ||
" | ||
in Text (at ReactWarningFixtures.js:20)", | ||
] | ||
`; |