Summary:
This diff adds handling to fatal errors such as thrown exceptions by popping them full screen and not allowing the user to dismiss them. They say that they're "Fatal Errors" and explain that "Fatal errors require a reload".

Changelog: [Internal]

Reviewed By: motiz88

Differential Revision: D18257185

fbshipit-source-id: ca051027b19c3cd2410ae59764d7b98a78f08dca
This commit is contained in:
Rick Hanlon 2019-11-01 16:05:02 -07:00 коммит произвёл Facebook Github Bot
Родитель 34989c88e0
Коммит f6b1fa3197
16 изменённых файлов: 588 добавлений и 116 удалений

Просмотреть файл

@ -127,17 +127,21 @@ export function addException(error: ExceptionData): void {
if (lastLog && lastLog.category === category) { if (lastLog && lastLog.category === category) {
lastLog.incrementCount(); lastLog.incrementCount();
} else { } else {
logs.add( const newLog = new LogBoxLog(
new LogBoxLog( error.isFatal ? 'fatal' : 'error',
'error', message,
message, error.stack,
error.stack, category,
category, error.componentStack != null
error.componentStack != null ? parseComponentStack(error.componentStack)
? parseComponentStack(error.componentStack) : [],
: [],
),
); );
// Start symbolicating now so it's warm when it renders.
if (error.isFatal) {
symbolicateLogLazy(newLog);
}
logs.add(newLog);
} }
handleUpdate(); handleUpdate();

Просмотреть файл

@ -15,7 +15,7 @@ import * as LogBoxSymbolication from './LogBoxSymbolication';
import type {Category, Message, ComponentStack} from './parseLogBoxLog'; import type {Category, Message, ComponentStack} from './parseLogBoxLog';
import type {Stack} from './LogBoxSymbolication'; import type {Stack} from './LogBoxSymbolication';
export type LogLevel = 'warn' | 'error'; export type LogLevel = 'warn' | 'error' | 'fatal';
export type SymbolicationRequest = $ReadOnly<{| export type SymbolicationRequest = $ReadOnly<{|
abort: () => void, abort: () => void,

Просмотреть файл

@ -51,12 +51,38 @@ function LogBoxContainer(props: Props): React.Node {
function openLog(log: LogBoxLog) { function openLog(log: LogBoxLog) {
let index = logs.length - 1; let index = logs.length - 1;
// Stop at zero because if we don't find any log, we'll open the first log.
while (index > 0 && logs[index] !== log) { while (index > 0 && logs[index] !== log) {
index -= 1; index -= 1;
} }
setSelectedLog(index); setSelectedLog(index);
} }
let fatalIndex = logs.length - 1;
while (fatalIndex >= 0) {
if (logs[fatalIndex].level === 'fatal') {
break;
}
fatalIndex -= 1;
}
if (selectedLogIndex == null && fatalIndex >= 0) {
return (
<View style={StyleSheet.absoluteFill}>
<LogBoxInspector
onDismiss={handleInspectorDismiss}
onMinimize={handleInspectorMinimize}
onChangeSelectedIndex={setSelectedLog}
logs={logs}
hasFatal={true}
selectedIndex={fatalIndex}
/>
</View>
);
}
if (selectedLogIndex != null) { if (selectedLogIndex != null) {
return ( return (
<View style={StyleSheet.absoluteFill}> <View style={StyleSheet.absoluteFill}>
@ -65,6 +91,7 @@ function LogBoxContainer(props: Props): React.Node {
onMinimize={handleInspectorMinimize} onMinimize={handleInspectorMinimize}
onChangeSelectedIndex={setSelectedLog} onChangeSelectedIndex={setSelectedLog}
logs={logs} logs={logs}
hasFatal={fatalIndex != null}
selectedIndex={selectedLogIndex} selectedIndex={selectedLogIndex}
/> />
</View> </View>

Просмотреть файл

@ -32,6 +32,7 @@ type Props = $ReadOnly<{|
onMinimize: () => void, onMinimize: () => void,
logs: $ReadOnlyArray<LogBoxLog>, logs: $ReadOnlyArray<LogBoxLog>,
selectedIndex: number, selectedIndex: number,
hasFatal: boolean,
|}>; |}>;
function LogBoxInspector(props: Props): React.Node { function LogBoxInspector(props: Props): React.Node {
@ -77,6 +78,7 @@ function LogBoxInspector(props: Props): React.Node {
<LogBoxInspectorFooter <LogBoxInspectorFooter
onDismiss={props.onDismiss} onDismiss={props.onDismiss}
onMinimize={props.onMinimize} onMinimize={props.onMinimize}
hasFatal={props.hasFatal}
/> />
</View> </View>
); );

Просмотреть файл

@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
* *
* @flow strict-local * @flow
* @format * @format
*/ */
@ -21,9 +21,18 @@ import * as LogBoxStyle from './LogBoxStyle';
type Props = $ReadOnly<{| type Props = $ReadOnly<{|
onDismiss: () => void, onDismiss: () => void,
onMinimize: () => void, onMinimize: () => void,
hasFatal: boolean,
|}>; |}>;
function LogBoxInspectorFooter(props: Props): React.Node { function LogBoxInspectorFooter(props: Props): React.Node {
if (props.hasFatal) {
return (
<View style={styles.root}>
<FatalButton />
</View>
);
}
return ( return (
<View style={styles.root}> <View style={styles.root}>
<FooterButton text="Minimize" onPress={props.onMinimize} /> <FooterButton text="Minimize" onPress={props.onMinimize} />
@ -54,6 +63,55 @@ function FooterButton(props: ButtonProps): React.Node {
); );
} }
function FatalButton(): React.Node {
return (
<LogBoxButton
backgroundColor={{
default: LogBoxStyle.getFatalColor(),
pressed: LogBoxStyle.getFatalDarkColor(),
}}
onPress={() =>
require('../../Utilities/DevSettings').reload('LogBox fatal')
}
style={fatalStyles.button}>
<View style={[fatalStyles.content]}>
<Text style={fatalStyles.label}>Reload</Text>
<Text style={fatalStyles.subtextLabel}>
Fatal errors require a full reload
</Text>
</View>
<SafeAreaView />
</LogBoxButton>
);
}
const fatalStyles = StyleSheet.create({
button: {
flex: 1,
},
content: {
alignItems: 'center',
height: 60,
justifyContent: 'center',
},
subtext: {
height: 60,
},
label: {
color: LogBoxStyle.getTextColor(1),
fontSize: 14,
fontWeight: '600',
includeFontPadding: false,
lineHeight: 20,
},
subtextLabel: {
color: LogBoxStyle.getTextColor(0.8),
fontSize: 11,
includeFontPadding: false,
lineHeight: 12,
},
});
const buttonStyles = StyleSheet.create({ const buttonStyles = StyleSheet.create({
button: { button: {
flex: 1, flex: 1,
@ -67,7 +125,7 @@ const buttonStyles = StyleSheet.create({
color: LogBoxStyle.getTextColor(1), color: LogBoxStyle.getTextColor(1),
fontSize: 14, fontSize: 14,
includeFontPadding: false, includeFontPadding: false,
lineHeight: 18, lineHeight: 20,
}, },
}); });

Просмотреть файл

@ -59,6 +59,22 @@ function LogBoxInspectorHeader(props: Props): React.Node {
); );
} }
const backgroundForLevel = (level: LogLevel) =>
({
warn: {
default: LogBoxStyle.getWarningColor(),
pressed: LogBoxStyle.getWarningDarkColor(),
},
error: {
default: LogBoxStyle.getErrorColor(),
pressed: LogBoxStyle.getErrorDarkColor(),
},
fatal: {
default: LogBoxStyle.getFatalColor(),
pressed: LogBoxStyle.getFatalDarkColor(),
},
}[level]);
function LogBoxInspectorHeaderButton( function LogBoxInspectorHeaderButton(
props: $ReadOnly<{| props: $ReadOnly<{|
disabled: boolean, disabled: boolean,
@ -69,16 +85,7 @@ function LogBoxInspectorHeaderButton(
): React.Node { ): React.Node {
return ( return (
<LogBoxButton <LogBoxButton
backgroundColor={{ backgroundColor={backgroundForLevel(props.level)}
default:
props.level === 'warn'
? LogBoxStyle.getWarningColor()
: LogBoxStyle.getErrorColor(),
pressed:
props.level === 'warn'
? LogBoxStyle.getWarningDarkColor()
: LogBoxStyle.getErrorDarkColor(),
}}
onPress={props.disabled ? null : props.onPress} onPress={props.disabled ? null : props.onPress}
style={headerStyles.button}> style={headerStyles.button}>
{props.disabled ? null : ( {props.disabled ? null : (
@ -96,7 +103,7 @@ const headerStyles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
aspectRatio: 1, aspectRatio: 1,
justifyContent: 'center', justifyContent: 'center',
marginTop: 3, marginTop: 5,
marginRight: 6, marginRight: 6,
marginLeft: 6, marginLeft: 6,
marginBottom: -8, marginBottom: -8,
@ -108,6 +115,9 @@ const headerStyles = StyleSheet.create({
}); });
const styles = StyleSheet.create({ const styles = StyleSheet.create({
fatal: {
backgroundColor: LogBoxStyle.getFatalColor(),
},
warn: { warn: {
backgroundColor: LogBoxStyle.getWarningColor(), backgroundColor: LogBoxStyle.getWarningColor(),
}, },

Просмотреть файл

@ -51,7 +51,7 @@ function LogBoxInspectorMessageHeader(props: Props): React.Node {
<View style={messageStyles.body}> <View style={messageStyles.body}>
<View style={messageStyles.heading}> <View style={messageStyles.heading}>
<Text style={[messageStyles.headingText, messageStyles[props.level]]}> <Text style={[messageStyles.headingText, messageStyles[props.level]]}>
{props.level === 'warn' ? 'Warning' : 'Error'} {{warn: 'Warning', error: 'Error', fatal: 'Fatal Error'}[props.level]}
</Text> </Text>
{renderShowMore()} {renderShowMore()}
</View> </View>
@ -106,6 +106,9 @@ const messageStyles = StyleSheet.create({
error: { error: {
color: LogBoxStyle.getErrorColor(1), color: LogBoxStyle.getErrorColor(1),
}, },
fatal: {
color: LogBoxStyle.getFatalColor(1),
},
messageText: { messageText: {
color: LogBoxStyle.getTextColor(0.6), color: LogBoxStyle.getTextColor(0.6),
}, },

Просмотреть файл

@ -30,6 +30,14 @@ export function getWarningDarkColor(opacity?: number): string {
return `rgba(224, 167, 8, ${opacity == null ? 1 : opacity})`; return `rgba(224, 167, 8, ${opacity == null ? 1 : opacity})`;
} }
export function getFatalColor(opacity?: number): string {
return `rgba(243, 83, 105, ${opacity == null ? 1 : opacity})`;
}
export function getFatalDarkColor(opacity?: number): string {
return `rgba(208, 75, 95, ${opacity == null ? 1 : opacity})`;
}
export function getErrorColor(opacity?: number): string { export function getErrorColor(opacity?: number): string {
return `rgba(243, 83, 105, ${opacity == null ? 1 : opacity})`; return `rgba(243, 83, 105, ${opacity == null ? 1 : opacity})`;
} }

Просмотреть файл

@ -137,4 +137,86 @@ describe('LogBoxContainer', () => {
expect(output).toMatchSnapshot(); expect(output).toMatchSnapshot();
}); });
it('should render fatal before warn and error', () => {
const output = render.shallowRender(
<LogBoxContainer
onDismiss={() => {}}
onDismissWarns={() => {}}
onDismissErrors={() => {}}
logs={
new Set([
new LogBoxLog(
'fatal',
{
content: 'Some kind of fatal message',
substitutions: [],
},
[],
'Some kind of fatal message',
[],
),
new LogBoxLog(
'warn',
{
content: 'Some kind of message',
substitutions: [],
},
[],
'Some kind of message',
[],
),
new LogBoxLog(
'error',
{
content: 'Some kind of message (latest)',
substitutions: [],
},
[],
'Some kind of message (latest)',
[],
),
])
}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render most recent fatal', () => {
const output = render.shallowRender(
<LogBoxContainer
onDismiss={() => {}}
onDismissWarns={() => {}}
onDismissErrors={() => {}}
logs={
new Set([
new LogBoxLog(
'fatal',
{
content: 'Should not be selected',
substitutions: [],
},
[],
'Some kind of fatal message',
[],
),
new LogBoxLog(
'fatal',
{
content: 'Should be selected',
substitutions: [],
},
[],
'Some kind of message',
[],
),
])
}
/>,
);
expect(output).toMatchSnapshot();
});
}); });

Просмотреть файл

@ -37,6 +37,16 @@ const logs = [
'Some kind of message (second)', 'Some kind of message (second)',
[], [],
), ),
new LogBoxLog(
'fatal',
{
content: 'Some kind of message (third)',
substitutions: [],
},
[],
'Some kind of message (third)',
[],
),
]; ];
describe('LogBoxContainer', () => { describe('LogBoxContainer', () => {
@ -48,6 +58,7 @@ describe('LogBoxContainer', () => {
onChangeSelectedIndex={() => {}} onChangeSelectedIndex={() => {}}
logs={[]} logs={[]}
selectedIndex={0} selectedIndex={0}
hasFatal={false}
/>, />,
); );
@ -62,20 +73,22 @@ describe('LogBoxContainer', () => {
onChangeSelectedIndex={() => {}} onChangeSelectedIndex={() => {}}
logs={logs} logs={logs}
selectedIndex={0} selectedIndex={0}
hasFatal={false}
/>, />,
); );
expect(output).toMatchSnapshot(); expect(output).toMatchSnapshot();
}); });
it('should render error with selectedIndex 1', () => { it('should render fatal with selectedIndex 2', () => {
const output = render.shallowRender( const output = render.shallowRender(
<LogBoxInspector <LogBoxInspector
onDismiss={() => {}} onDismiss={() => {}}
onMinimize={() => {}} onMinimize={() => {}}
onChangeSelectedIndex={() => {}} onChangeSelectedIndex={() => {}}
logs={logs} logs={logs}
selectedIndex={1} selectedIndex={2}
hasFatal={true}
/>, />,
); );

Просмотреть файл

@ -18,7 +18,23 @@ const render = require('../../../../jest/renderer');
describe('LogBoxInspectorFooter', () => { describe('LogBoxInspectorFooter', () => {
it('should render two buttons', () => { it('should render two buttons', () => {
const output = render.shallowRender( const output = render.shallowRender(
<LogBoxInspectorFooter onMinimize={() => {}} onDismiss={() => {}} />, <LogBoxInspectorFooter
onMinimize={() => {}}
onDismiss={() => {}}
hasFatal={false}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render fatal button', () => {
const output = render.shallowRender(
<LogBoxInspectorFooter
onMinimize={() => {}}
onDismiss={() => {}}
hasFatal
/>,
); );
expect(output).toMatchSnapshot(); expect(output).toMatchSnapshot();

Просмотреть файл

@ -17,13 +17,29 @@ const LogBoxInspectorMessageHeader = require('../LogBoxInspectorMessageHeader')
const render = require('../../../../jest/renderer'); const render = require('../../../../jest/renderer');
describe('LogBoxInspectorMessageHeader', () => { describe('LogBoxInspectorMessageHeader', () => {
it('should not render error', () => { it('should render error', () => {
const output = render.shallowRender( const output = render.shallowRender(
<LogBoxInspectorMessageHeader <LogBoxInspectorMessageHeader
level="error" level="error"
collapsed={false} collapsed={false}
message={{ message={{
content: 'Short', content: 'Some error message',
substitutions: [],
}}
onPress={() => {}}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render fatal', () => {
const output = render.shallowRender(
<LogBoxInspectorMessageHeader
level="fatal"
collapsed={false}
message={{
content: 'Some fatal message',
substitutions: [], substitutions: [],
}} }}
onPress={() => {}} onPress={() => {}}

Просмотреть файл

@ -91,6 +91,138 @@ exports[`LogBoxContainer should render both an error and warning 1`] = `
</View> </View>
`; `;
exports[`LogBoxContainer should render fatal before warn and error 1`] = `
<View
style={
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<LogBoxInspector
hasFatal={true}
logs={
Array [
LogBoxLog {
"category": "Some kind of fatal message",
"componentStack": Array [],
"count": 1,
"level": "fatal",
"message": Object {
"content": "Some kind of fatal message",
"substitutions": Array [],
},
"stack": Array [],
"symbolicated": Object {
"error": null,
"stack": null,
"status": "NONE",
},
},
LogBoxLog {
"category": "Some kind of message",
"componentStack": Array [],
"count": 1,
"level": "warn",
"message": Object {
"content": "Some kind of message",
"substitutions": Array [],
},
"stack": Array [],
"symbolicated": Object {
"error": null,
"stack": null,
"status": "NONE",
},
},
LogBoxLog {
"category": "Some kind of message (latest)",
"componentStack": Array [],
"count": 1,
"level": "error",
"message": Object {
"content": "Some kind of message (latest)",
"substitutions": Array [],
},
"stack": Array [],
"symbolicated": Object {
"error": null,
"stack": null,
"status": "NONE",
},
},
]
}
onChangeSelectedIndex={[Function]}
onDismiss={[Function]}
onMinimize={[Function]}
selectedIndex={0}
/>
</View>
`;
exports[`LogBoxContainer should render most recent fatal 1`] = `
<View
style={
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<LogBoxInspector
hasFatal={true}
logs={
Array [
LogBoxLog {
"category": "Some kind of fatal message",
"componentStack": Array [],
"count": 1,
"level": "fatal",
"message": Object {
"content": "Should not be selected",
"substitutions": Array [],
},
"stack": Array [],
"symbolicated": Object {
"error": null,
"stack": null,
"status": "NONE",
},
},
LogBoxLog {
"category": "Some kind of message",
"componentStack": Array [],
"count": 1,
"level": "fatal",
"message": Object {
"content": "Should be selected",
"substitutions": Array [],
},
"stack": Array [],
"symbolicated": Object {
"error": null,
"stack": null,
"status": "NONE",
},
},
]
}
onChangeSelectedIndex={[Function]}
onDismiss={[Function]}
onMinimize={[Function]}
selectedIndex={1}
/>
</View>
`;
exports[`LogBoxContainer should render null with no logs 1`] = `null`; exports[`LogBoxContainer should render null with no logs 1`] = `null`;
exports[`LogBoxContainer should render the latest error 1`] = ` exports[`LogBoxContainer should render the latest error 1`] = `

Просмотреть файл

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LogBoxContainer should render error with selectedIndex 1 1`] = ` exports[`LogBoxContainer should render fatal with selectedIndex 2 1`] = `
<View <View
style={ style={
Object { Object {
@ -11,20 +11,20 @@ exports[`LogBoxContainer should render error with selectedIndex 1 1`] = `
} }
> >
<LogBoxInspectorHeader <LogBoxInspectorHeader
level="error" level="fatal"
onSelectIndex={[Function]} onSelectIndex={[Function]}
selectedIndex={1} selectedIndex={2}
total={2} total={3}
/> />
<LogBoxInspectorBody <LogBoxInspectorBody
log={ log={
LogBoxLog { LogBoxLog {
"category": "Some kind of message (second)", "category": "Some kind of message (third)",
"componentStack": Array [], "componentStack": Array [],
"count": 1, "count": 1,
"level": "error", "level": "fatal",
"message": Object { "message": Object {
"content": "Some kind of message (second)", "content": "Some kind of message (third)",
"substitutions": Array [], "substitutions": Array [],
}, },
"stack": Array [], "stack": Array [],
@ -38,6 +38,7 @@ exports[`LogBoxContainer should render error with selectedIndex 1 1`] = `
onRetry={[Function]} onRetry={[Function]}
/> />
<LogBoxInspectorFooter <LogBoxInspectorFooter
hasFatal={true}
onDismiss={[Function]} onDismiss={[Function]}
onMinimize={[Function]} onMinimize={[Function]}
/> />
@ -60,7 +61,7 @@ exports[`LogBoxContainer should render warning with selectedIndex 0 1`] = `
level="warn" level="warn"
onSelectIndex={[Function]} onSelectIndex={[Function]}
selectedIndex={0} selectedIndex={0}
total={2} total={3}
/> />
<LogBoxInspectorBody <LogBoxInspectorBody
log={ log={
@ -84,6 +85,7 @@ exports[`LogBoxContainer should render warning with selectedIndex 0 1`] = `
onRetry={[Function]} onRetry={[Function]}
/> />
<LogBoxInspectorFooter <LogBoxInspectorFooter
hasFatal={false}
onDismiss={[Function]} onDismiss={[Function]}
onMinimize={[Function]} onMinimize={[Function]}
/> />

Просмотреть файл

@ -1,5 +1,26 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LogBoxInspectorFooter should render fatal button 1`] = `
<View
style={
Object {
"backgroundColor": "rgba(51, 51, 51, 1)",
"elevation": 1,
"flexDirection": "row",
"shadowColor": "#000",
"shadowOffset": Object {
"height": -2,
"width": 0,
},
"shadowOpacity": 0.5,
"shadowRadius": 2,
}
}
>
<FatalButton />
</View>
`;
exports[`LogBoxInspectorFooter should render two buttons 1`] = ` exports[`LogBoxInspectorFooter should render two buttons 1`] = `
<View <View
style={ style={

Просмотреть файл

@ -78,84 +78,6 @@ exports[`LogBoxInspectorMessageHeader should not render collapse button for shor
</View> </View>
`; `;
exports[`LogBoxInspectorMessageHeader should not render error 1`] = `
<View
style={
Object {
"backgroundColor": "rgba(51, 51, 51, 1)",
"elevation": 2,
"flex": 0,
"shadowColor": "#000",
"shadowOffset": Object {
"height": 2,
"width": 0,
},
"shadowOpacity": 0.5,
"shadowRadius": 2,
}
}
>
<View
style={
Object {
"alignItems": "center",
"flexDirection": "row",
"marginBottom": 5,
"marginTop": 10,
"paddingHorizontal": 12,
}
}
>
<Text
style={
Array [
Object {
"flex": 1,
"fontSize": 20,
"fontWeight": "600",
"includeFontPadding": false,
"lineHeight": 28,
},
Object {
"color": "rgba(243, 83, 105, 1)",
},
]
}
>
Error
</Text>
</View>
<Text
numberOfLines={null}
style={
Object {
"color": "rgba(255, 255, 255, 1)",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 20,
"paddingBottom": 10,
"paddingHorizontal": 12,
}
}
>
<LogBoxMessage
message={
Object {
"content": "Short",
"substitutions": Array [],
}
}
style={
Object {
"color": "rgba(255, 255, 255, 0.6)",
}
}
/>
</Text>
</View>
`;
exports[`LogBoxInspectorMessageHeader should render "collapse" if expanded 1`] = ` exports[`LogBoxInspectorMessageHeader should render "collapse" if expanded 1`] = `
<View <View
style={ style={
@ -369,3 +291,159 @@ exports[`LogBoxInspectorMessageHeader should render "see more" if collapsed 1`]
</Text> </Text>
</View> </View>
`; `;
exports[`LogBoxInspectorMessageHeader should render error 1`] = `
<View
style={
Object {
"backgroundColor": "rgba(51, 51, 51, 1)",
"elevation": 2,
"flex": 0,
"shadowColor": "#000",
"shadowOffset": Object {
"height": 2,
"width": 0,
},
"shadowOpacity": 0.5,
"shadowRadius": 2,
}
}
>
<View
style={
Object {
"alignItems": "center",
"flexDirection": "row",
"marginBottom": 5,
"marginTop": 10,
"paddingHorizontal": 12,
}
}
>
<Text
style={
Array [
Object {
"flex": 1,
"fontSize": 20,
"fontWeight": "600",
"includeFontPadding": false,
"lineHeight": 28,
},
Object {
"color": "rgba(243, 83, 105, 1)",
},
]
}
>
Error
</Text>
</View>
<Text
numberOfLines={null}
style={
Object {
"color": "rgba(255, 255, 255, 1)",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 20,
"paddingBottom": 10,
"paddingHorizontal": 12,
}
}
>
<LogBoxMessage
message={
Object {
"content": "Some error message",
"substitutions": Array [],
}
}
style={
Object {
"color": "rgba(255, 255, 255, 0.6)",
}
}
/>
</Text>
</View>
`;
exports[`LogBoxInspectorMessageHeader should render fatal 1`] = `
<View
style={
Object {
"backgroundColor": "rgba(51, 51, 51, 1)",
"elevation": 2,
"flex": 0,
"shadowColor": "#000",
"shadowOffset": Object {
"height": 2,
"width": 0,
},
"shadowOpacity": 0.5,
"shadowRadius": 2,
}
}
>
<View
style={
Object {
"alignItems": "center",
"flexDirection": "row",
"marginBottom": 5,
"marginTop": 10,
"paddingHorizontal": 12,
}
}
>
<Text
style={
Array [
Object {
"flex": 1,
"fontSize": 20,
"fontWeight": "600",
"includeFontPadding": false,
"lineHeight": 28,
},
Object {
"color": "rgba(243, 83, 105, 1)",
},
]
}
>
Fatal Error
</Text>
</View>
<Text
numberOfLines={null}
style={
Object {
"color": "rgba(255, 255, 255, 1)",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 20,
"paddingBottom": 10,
"paddingHorizontal": 12,
}
}
>
<LogBoxMessage
message={
Object {
"content": "Some fatal message",
"substitutions": Array [],
}
}
style={
Object {
"color": "rgba(255, 255, 255, 0.6)",
}
}
/>
</Text>
</View>
`;