-
Notifications
You must be signed in to change notification settings - Fork 272
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: format element & debug (#1730)
- Loading branch information
1 parent
d21dbb4
commit 692c55b
Showing
26 changed files
with
233 additions
and
309 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 |
---|---|---|
@@ -1,3 +1,11 @@ | ||
{ | ||
"cSpell.words": ["labelledby", "Pressable", "RNTL", "Uncapitalize", "valuenow", "valuetext"] | ||
"cSpell.words": [ | ||
"labelledby", | ||
"Pressable", | ||
"redent", | ||
"RNTL", | ||
"Uncapitalize", | ||
"valuenow", | ||
"valuetext" | ||
] | ||
} |
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
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
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,25 @@ | ||
import * as React from 'react'; | ||
import { Text, View } from 'react-native'; | ||
import { render, screen } from '../..'; | ||
import { formatElement } from '../format-element'; | ||
|
||
test('formatElement', () => { | ||
render( | ||
<View testID="root"> | ||
<View testID="view" /> | ||
<Text>Hello</Text> | ||
</View>, | ||
); | ||
|
||
expect(formatElement(screen.getByTestId('view'), { mapProps: null })).toMatchInlineSnapshot(` | ||
"<View | ||
testID="view" | ||
/>" | ||
`); | ||
expect(formatElement(screen.getByText('Hello'))).toMatchInlineSnapshot(` | ||
"<Text> | ||
Hello | ||
</Text>" | ||
`); | ||
expect(formatElement(null)).toMatchInlineSnapshot(`"(null)"`); | ||
}); |
2 changes: 1 addition & 1 deletion
2
...helpers/__tests__/format-default.test.tsx → src/helpers/__tests__/map-props.test.tsx
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
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 |
---|---|---|
@@ -1,26 +1,22 @@ | ||
import type { ReactTestRendererJSON } from 'react-test-renderer'; | ||
import type { FormatOptions } from './format'; | ||
import format from './format'; | ||
import type { FormatElementOptions } from './format-element'; | ||
import { formatJson } from './format-element'; | ||
import { logger } from './logger'; | ||
|
||
export type DebugOptions = { | ||
message?: string; | ||
} & FormatOptions; | ||
} & FormatElementOptions; | ||
|
||
/** | ||
* Log pretty-printed deep test component instance | ||
*/ | ||
export function debug( | ||
instance: ReactTestRendererJSON | ReactTestRendererJSON[], | ||
options?: DebugOptions | string, | ||
{ message, ...formatOptions }: DebugOptions = {}, | ||
) { | ||
const message = typeof options === 'string' ? options : options?.message; | ||
|
||
const formatOptions = typeof options === 'object' ? { mapProps: options?.mapProps } : undefined; | ||
|
||
if (message) { | ||
logger.info(`${message}\n\n`, format(instance, formatOptions)); | ||
logger.info(`${message}\n\n`, formatJson(instance, formatOptions)); | ||
} else { | ||
logger.info(format(instance, formatOptions)); | ||
logger.info(formatJson(instance, formatOptions)); | ||
} | ||
} |
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,92 @@ | ||
import type { ReactTestInstance, ReactTestRendererJSON } from 'react-test-renderer'; | ||
import type { NewPlugin } from 'pretty-format'; | ||
import prettyFormat, { plugins } from 'pretty-format'; | ||
import type { MapPropsFunction } from './map-props'; | ||
import { defaultMapProps } from './map-props'; | ||
|
||
export type FormatElementOptions = { | ||
/** Minimize used space. */ | ||
compact?: boolean; | ||
|
||
/** Highlight the output. */ | ||
highlight?: boolean; | ||
|
||
/** Filter or map props to display. */ | ||
mapProps?: MapPropsFunction | null; | ||
}; | ||
|
||
/*** | ||
* Format given element as a pretty-printed string. | ||
* | ||
* @param element Element to format. | ||
*/ | ||
export function formatElement( | ||
element: ReactTestInstance | null, | ||
{ compact, highlight = true, mapProps = defaultMapProps }: FormatElementOptions = {}, | ||
) { | ||
if (element == null) { | ||
return '(null)'; | ||
} | ||
|
||
const { children, ...props } = element.props; | ||
const childrenToDisplay = typeof children === 'string' ? [children] : undefined; | ||
|
||
return prettyFormat( | ||
{ | ||
// This prop is needed persuade the prettyFormat that the element is | ||
// a ReactTestRendererJSON instance, so it is formatted as JSX. | ||
$$typeof: Symbol.for('react.test.json'), | ||
type: `${element.type}`, | ||
props: mapProps ? mapProps(props) : props, | ||
children: childrenToDisplay, | ||
}, | ||
// See: https://www.npmjs.com/package/pretty-format#usage-with-options | ||
{ | ||
plugins: [plugins.ReactTestComponent, plugins.ReactElement], | ||
printFunctionName: false, | ||
printBasicPrototype: false, | ||
highlight: highlight, | ||
min: compact, | ||
}, | ||
); | ||
} | ||
|
||
export function formatElementList(elements: ReactTestInstance[], options?: FormatElementOptions) { | ||
if (elements.length === 0) { | ||
return '(no elements)'; | ||
} | ||
|
||
return elements.map((element) => formatElement(element, options)).join('\n'); | ||
} | ||
|
||
export function formatJson( | ||
json: ReactTestRendererJSON | ReactTestRendererJSON[], | ||
{ compact, highlight = true, mapProps = defaultMapProps }: FormatElementOptions = {}, | ||
) { | ||
return prettyFormat(json, { | ||
plugins: [getElementJsonPlugin(mapProps), plugins.ReactElement], | ||
highlight: highlight, | ||
printBasicPrototype: false, | ||
min: compact, | ||
}); | ||
} | ||
|
||
function getElementJsonPlugin(mapProps?: MapPropsFunction | null): NewPlugin { | ||
return { | ||
test: (val) => plugins.ReactTestComponent.test(val), | ||
serialize: (val, config, indentation, depth, refs, printer) => { | ||
let newVal = val; | ||
if (mapProps && val.props) { | ||
newVal = { ...val, props: mapProps(val.props) }; | ||
} | ||
return plugins.ReactTestComponent.serialize( | ||
newVal, | ||
config, | ||
indentation, | ||
depth, | ||
refs, | ||
printer, | ||
); | ||
}, | ||
}; | ||
} |
Oops, something went wrong.