-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Discuss edge cases of indentation in pretty-format plugins #3518
Comments
Seems like a nice enhancement, although we need to keep in mind this is a breaking change. |
Yeah, for sure. Am interested to know if arrays of test objects might become more common if render method can return arrays of elements in React 16? So far, has been from enzyme query. There is some irony in the digital archaeology or cultural anthropology:
|
Sample of proposed changes to pretty-format/src/index.js so it and plugins indent consistently. Have adapted The limiting factor to move forward is whether to adjust the plugin API:
My first attempt a few weeks ago to leave args the same and add properties to Proposed version runs faster in many cases and is within measurement precision in the rest :) internal function arguments
assignment statements
initialization function, which is not called for basic values
type Indenter = (level: number) => string;
function createIndenter(indent: number): Indenter {
if (indent === 0) {
return function () {
return '';
}
}
let indentation = ['', new Array(indent + 1).join(' ')];
// Given number of indent levels, return indentation string.
return function (n) {
for (let i = indentation.length; i <= n; i += 1) {
indentation[i] = indentation[i - 1] + indentation[1];
}
return indentation[n];
}
} bound print function for plugins
bound indent function for plugins
|
Forgot to say that a way forward is support another key in plugin object for proposed arguments:
|
It has turned out as Fred Brooks advised: plan to throw one away; you will, anyhow.
Measurements of 22 tests adapted from
Measurements of 22 tests for hypothesis in #3745 that proposed version will make up the time lost from the plugin shortcut, because it replaces regexp with concatenation.
Bound print function for plugins
Bound indent function for plugins
Plugin API:
Both alternatives add an arg so plugin has the indentation. That was the root of the problem. Y’all have given such super direction about API for my pull requests. So WHAT do you suggest as an object key for serializers which support the proposed API? function printPlugin(val, indent, prevIndent, /* and so on */) {}
// Find plugin whose test matches val.
if (typeof plugin.WHAT !== 'function') {
// Old API
function boundPrint(val) {
return print(val, indent, prevIndent, /* and so on */);
}
function boundIndent(str) {
const indentation = prevIndent + indent;
return indentation + str.replace(NEWLINE_REGEXP, '\n' + indentation);
}
return plugin.print(val, boundPrint, boundIndent, opts, colors);
}
// New API
function boundPrint(val, argIndent) {
return print(val, indent, argIndent, /* and so on */);
}
return plugin.WHAT(val, boundPrint, indent, prevIndent, opts, colors);
} |
What do you think about serialize as property name for the new API? Because we have already merged breaking changes for edge cases of Here is some pseudo Flow. export type PrintOld = any => string;
export type PrintNew = (val: any, indentation: string) => string;
export type Plugin = {
print: (
val: any,
print: PrintOld,
indent: Indent,
opts: PluginOptions,
colors: Colors,
) => string,
serialize: (
val: any,
print: PrintNew,
indentation: string, // current indentation
indent: string, // string of spaces whose length is specified by indent number option
opts: PluginOptions,
colors: Colors,
) => string,
test: any => boolean,
}; P.S. Thinking about adding an Indeed, even with no plugins at all, look at the “massive” world.geo.json perf test case!
|
Maybe this issue becomes “slow good” like a Heinz ketchup advert. Here’s a way to make API of (and code snippets in) plugins very similar to
Plugin property:
Plugin callback arg to print descendants:
Plugin object args:
Example of a major core function:
Example of minor core function:
As suggested in preceding comments, we can:
Performance tests suggest that:
|
Do you want to request a feature or report a bug?
Report bugs with indentation in
ReactElement
andReactTestComponent
pluginsWhat is the current behavior?
The first problem I found and put aside while writing test cases for #3429 notice that the second and third lines of multiline string are indented for
points
prop. If we change the hypothetical component to render ag
element in the tree betweensvg
andpolyline
then the additional level of indentation within a multiline string will defeat ignoring indentation for thepoints
prop and it will appear in the diff as removed and added :(Compare to
pretty-format
for a similar object which respects the lack of indentation:The second problem I found while studying the code in
pretty-format
and its plugins. It might become a more than theoretical problem when React components can render fragments.indent
function as if it represents one indent level. That assumption isn’t true for an array of elements (or for elements which are props of elements).For a minimal example of array of elements, see:
https://github.com/adriantoine/enzyme-to-json/blob/master/tests/core/__snapshots__/mount.test.js.snap#L222-L231
In the following example, notice how the indent level changes from 2 to 4 starting from the
prop
because the total indentation at that point is used incorrectly as one level increment.
EDIT on 2017-07-11 while studying #1772 found excess indentation in prop of React 15 component instance:
What is the expected behavior?
Plugins (especially for React elements and test objects) return indentation that is consistent with
pretty-format
for similar data structures (for example, objects).EDIT on 2017-07-11 disregard the following and skip to comments at the end of the issue :)
I am happy to receive your critique about an idea how to solve the problem. Provide as options to plugins two functions (please, please, please suggest better names than the following :-)
returnIndentationString(nLevels)
returns the current indentation plusnLevels
additional indent levels:<type
or close>
or end tag</type>
prop="value"
orprop={
returnPrintFunction(nLevels)
returns a print function that is bound to the current indentation plusnLevels
additional indent levels:Jest 19.0.2 and Node 7.10.0
Depending on your feedback, I can create a sample project for Jest 20 and take a baseline perf profile for a few examples of the unexpected indentation. It seems like calling a
print
function that is bound with the correct indentation should outperform callingindent
to replace the (sometimes incorrect) indentation afterward.The text was updated successfully, but these errors were encountered: