React-testing-library: Server side rendered component testing

Created on 16 Jun 2019  路  10Comments  路  Source: testing-library/react-testing-library

Describe the feature you'd like:

Currently there is no documentation, recommendations or API's that I could find regarding testing components that are rendered in a server side context.

Related twitter discussion: https://twitter.com/dylan_piercey/status/1139990868213952512

Suggested implementation:

I think that for many frameworks, especially those that have compilers in front, it will make the most sense to have a completely different implementation for the server side but likely with a similar API. This can be done easily via a browser field shim.

I think a simple way forward would be to reuse the existing query api on the server, however we'd want to omit the event and async helpers since they don't make sense in this context.

Perhaps we could get away with the exact same query API but instead support passing html strings on the server side? Something like:

import { getByLabelText } from '@testing-library/dom'

const html = `<div><label> <span>Username</span> <input /> </label></div>`
const inputNode = getByLabelText(html, 'Username')

Under the hood the server side implementation could use JSDOM to parse the html and leverage the browser implementation for all of the query apis.

For framework wrappers there would be very little difference in API since that part would be abstracted away.

Teachability, Documentation, Adoption, Migration Strategy:

My sample solution above would likely be a breaking change since it would rely on resolving assets in a browser like context (bundler, jest with browser: true, etc). If someone was using a testing-library module in node and assigned jsdom to globals for example this would break.

As far as teaching this and documentation goes it should be fairly straight forward since it could be all of the same API's besides accepting HTML instead of container nodes.

All 10 comments

I'm in favor of this. I hadn't considered the fact that people testing SSR probably wouldn't have JSDOM set up globally, but that's a good consideration that we should probably account for. Luckily, dom-testing-library does work without a global DOM, so I think we should be good to go with the suggested implementation.

Anyone want to try to get this working?

Took a quick stab at this: https://github.com/testing-library/dom-testing-library/compare/master...DylanPiercey:ssr-html-testing?expand=1

I don't have time just yet to see it through, and some feed back would be great.

My approach in the PR was to remap a few places for the browser and add a normalizer (prepare-container) which uses the JSDOM.fragment api to parse html for server side tests.

I've hit a couple roadblocks that I'd appreciate some thoughts on:

  1. I was hoping the tests would be able to run in both environments with a few shims, but it turns out this isn't the case since several tests directly use DOM api's. Maybe there needs to be SSR specific test folders?
  2. The current package.json setup I have doesn't work with the stock jest browser resolver since it has many issues. Hopefully we can find a way to do this that does work with the current browser-resolve module -_-.

Going to pause on this for now. Given that the scope is a bit larger than I had imagined, maybe it would make sense for this to be implemented per library instead of in a generic way through this module?

Since the main thing exported from the wrapper modules is the results of getQueriesForElement it's quite easy to write an alternative getQueriesForHTML that could be shimmed in for SSR.

Ah, dang, I had been working on making some tests work on node and I thought I'd finished that but I haven't and it's still hanging out on my computer. I'll try to get that finished soon. That should make your PR a lot easier.

Ah, actually I was thinking of the wrong place. My changes were in dom-testing-library.

But they're committed now: https://github.com/testing-library/dom-testing-library/commit/c4b4efffb19233e1cca9799544e7ab016b3bd916

Maybe that'll help give you an idea of how to make the same concept work in react-testing-library :)

That does help actually (I am/was planning to make these changes to dom-testing-library). I think the direction of have separate tests for server side as you had will simplify things a fair amount.

Will take another stab at this in the near future off of that commit. 馃槃

I'm starting to think this might be best done by the wrapping modules of @testing-library/dom (such as this module).

I've got a WIP setup going for the Marko side of things by using the JSDOM.fragment API server side (https://github.com/marko-js/testing-library/blob/master/src/index.ts#L13) and a fairly generic rendering into a div solution client side (https://github.com/marko-js/testing-library/blob/master/src/index-browser.ts#L8).

I personally like this approach as for server side only tests it allows for using all of the existing helpers exported by this module, except in my implementation it does not allow for rerendering, destroying or firing events when testing the SSR api. In my opinion if you want to test the client side behavior you should have a client side test instead for that.

I'm not sure I understand. Are you suggesting that we make another package rather than include this feature in @testing-library/react?

@kentcdodds my original proposal was basically to add string => jsdom element parsing with the helpers in @testing-library/dom, not here (@testing-library/react).

Instead I think it's simpler to just have the wrapping modules (such as @testing-library/react) convert html strings to dom with their render api's.

For the Marko implementation, on the server side that happens here and in the browser side I am just directly rendering into a container

I _think_ I understand. But I'll understand better when I see a PR :)

Closing this as there's been no traction. Folks can feel free to open a new issue if they'd like to discuss it/make a PR :)

Was this page helpful?
0 / 5 - 0 ratings