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

Unit testing <Composer> with nested <Fetch> components? #58

Open
istan opened this issue Oct 19, 2018 · 4 comments
Open

Unit testing <Composer> with nested <Fetch> components? #58

istan opened this issue Oct 19, 2018 · 4 comments
Labels

Comments

@istan
Copy link

istan commented Oct 19, 2018

Hi! Thanks for the great libraries! I'm running into some issues trying to write enzyme unit tests for a component that follows a pattern like this, where Fetch comes from react-request:

<Composer components=[FetchComponentA, FetchComponentB] />
  {([fetchA, fetchB]) => {
     if (fetchA.failed || fetchB.failed) {
         return <ErrorPage ... />;
     }
     if (fetchA.fetching || fetchB.fetching) {
         return <LoadingPage ... />;
     }
     return <HappyPage ... />;
  }}
</Composer>

Do you have any examples you can share of how to test this pattern? I seem to be having trouble getting at the underlying promise chain, so my tests complete before fetchA, fetchB, fetchC all resolve.

Thanks!

@jamesplease
Copy link
Owner

jamesplease commented Oct 19, 2018

👋 hi @istan ! Thanks for opening this issue. I'm happy to help out, though note that what I'm about to share with you should work, but can probably be improved.

Looking at the React Request test suite itself could possibly be useful here, if you haven't already taken a look there. They're not the best tests ever, but they lay out the general strategy I would use.

Some general tips I have are:

  1. stub out the requests, so that you know how long they will take to resolve, and whether they succeed or not
  2. try to write your tests in a way that doesn't depend on the number of times that render is called

If your test suite supports it, it could be worthwhile stubbing out the clock, so that you can control how much time is passing, too.

By controlling as much as you can (the actual network requests, and possibly the clock), and being conscious of the things that you cannot control (the number of times render is called), you should be able to put together something that works.

I'm never 100% happy with unit tests for this sort of things, because, when I write them, they always feel a little bit too brittle for my tastes. I haven't yet had a chance to do this, but I believe that an integration testing approach (something using, say, Puppeteer) would feel less brittle.


Oh, also, be sure to switch on async mode in your test suite, so that you control when the test is complete. If you're using Jest, you can do that by including done as an argument the callback expect callback, and then calling it once you have completed your last assertion.

You won't be able to unit test anything involving network requests using the default, synchronous runs of most test suites afaik.

@istan
Copy link
Author

istan commented Oct 19, 2018

Thanks! I'm using nock to mock out the requests. I'm able to get my tests passing by passing the done function into the tests as you suggested and wrapping my asserts in a setTimeout to push them to the end of the event queue. So that's good...But I think it would be better to not have to artificially "wait" like this to make sure the asserts run after all the async code completes, and instead be able to chain off the promises that underly the <Fetch> components. Since the Fetch components encapsulate fetch, I'm not sure how to get access to the promise that fetch (or, in this case, a mocked fetch call) would return so that I can set up an assertion call at the end of my test like return mockedFetchReturnPromise.then(() => { expect(wrapper.find('HappyPage').length).toBe(1); ... etc });... This is made more complicated (I think) when using Composer with multiple Fetch components because these components (and their fetch calls and thus promises?) get nested within one another (if I am understanding the library correctly)... Any ideas? Thanks!

@jamesplease
Copy link
Owner

jamesplease commented Oct 21, 2018

I understand your desire to use the underlying Promise. Right now, that isn’t exposed to consumers by design.

I’d consider an API that adds it, though. It would likely need to be behind a flag, like dangerouslyExposeFetchPromise or something to that effect. What do you think?

Also, note that I’m planning on a “sequel” library to React Request that solves many of the problems associated with using it, including testability. I’m waiting for some new feature announcements from the React team before i invest the time though ✌️

@istan
Copy link
Author

istan commented Oct 22, 2018

@jamesplease I think that could be pretty helpful, particularly if you provided an example for how to use it. Thanks!

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

No branches or pull requests

2 participants