Skip to content
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

Shallow rendering and parameter object serialization #256

Open
remko79 opened this issue Oct 19, 2022 · 1 comment
Open

Shallow rendering and parameter object serialization #256

remko79 opened this issue Oct 19, 2022 · 1 comment

Comments

@remko79
Copy link
Contributor

remko79 commented Oct 19, 2022

We're currently working on creating unit tests and as a starter, we're trying to snapshot the components using renderToString with shallow set to true.
The problem is that a object passed as parameter to a child component will be rendered as string "[object Object]", simplified example:

export default function MyComponent { return (<WrapperComponent param1={{ test: '1234' }} />); }
generates ==>
<WrapperComponent param1="[object Object]" />

As far as I can trace it, it's because the default JS serializing is used for a simple JS object (done in src/util.js -> encodeEntities). We're using typescript and got the parameter typed, but that doesn't help us because I don't think you can override the toString method for that one. Changing everything to classes / functions and override the toString is really a no-go because it adds tons of extra code. Any way provide a callback or something that objects are serialized with (for example) JSON.stringify so we get something like:

<WrapperComponent param1="{&quot;test&quot;:&quot;1234&quot;}" />

Note: I really want to test using the renderToString function and not enzyme or any other jest snapshot serializer, because that just doesn't render the components in exactly the same way this module does.

@remko79
Copy link
Contributor Author

remko79 commented May 13, 2023

After finally diving further into this, the "problem" occurs when we typecast the value to a string:
s = s + ` ${name}="${encodeEntities(v + '')}"`;
See: https://github.com/preactjs/preact-render-to-string/blob/master/src/pretty.js#L304

It would be nice if we have a bit more control over that, so maybe we could pass in a function to the options which will be used instead of the default toString function for the object.

We could change those lines into something like:

if (opts.shallow
  && typeof v === 'object'
  && typeof opts.shallowObjectsToString === 'function'
) {
  s = s + ` ${name}="${encodeEntities(opts.shallowObjectsToString(name, v) +'')}"`;
} else {
  s = s + ` ${name}="${encodeEntities(v + '')}"`;
}

And we can pass in an option 'shallowObjectsToString' to do whatever we want with it, for example:

shallowObjectsToString: (name, v) => JSON.stringify(v),

Note that I've added the 'name' to the function so you could do different things depending on the object's name

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant