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

Adding some server rendering unit tests. #9055

Merged
merged 7 commits into from
Mar 1, 2017

Conversation

aickin
Copy link
Contributor

@aickin aickin commented Feb 23, 2017

This PR adds a handful of server rendering unit tests.

With the move to Fiber, it's likely that the server rendering path and client rendering path are going to diverge significantly, and I think it'd be useful to have a more robust unit test suite for server rendering as the work on Fiber SSR begins.

This PR starts to port over tests that I wrote in (since abandoned) PR #6836. This PR only ports over some of the helper functions and 4 of the simplest tests. If this PR is accepted, I plan to submit the rest of the tests in a series of further PRs; I only added four tests here because I wanted to keep this PR as digestible as possible.

Thanks for all your great work!

Note: I ran tests, linting, and flow, but I could not get ./scripts/fiber/record-tests to work. It first complained about not being able to find jest-cli; when I npm installed jest-cli, it complained about an unresolved Promise with the error TypeError: Path must be a string. Received undefined. I expect the CI build will fail on this, and I'd appreciate any pointers to getting it to work.

@aickin
Copy link
Contributor Author

aickin commented Feb 26, 2017

Weirdly, the CI build seems to have succeeded, even though I haven't updated the list of failing fiber tests. I would greatly appreciate any help from the core team in figuring out what's going on there, and in figuring out how to run the update script on my machine.

Simultaneously, I've ported the rest of my SSR tests in a separate local branch; there are about 550 extra tests in total, and they are all passing on Stack. Unsurprisingly, many fail on Fiber, but that's arguably a good thing! If and when this PR is merged, I'll file a series of PRs to add more tests.

@sophiebits
Copy link
Collaborator

@acdlite fixed the test runner a couple days ago in #9060 – a Jest upgrade broke it, nothing you did. We're not sure why CI didn't catch that. If you rebase over that then it should work locally.

I wouldn't actually expect these tests to generally fail on Fiber. Do you have an example of a failing one handy?

I expect to have time to look at this tomorrow.

@aickin
Copy link
Contributor Author

aickin commented Feb 28, 2017

@spicyj: Thanks for the tip on the test runner; I merged from master and was able to run the test list update scripts. Committed in 9257660.

I wouldn't actually expect these tests to generally fail on Fiber.

All the itRenders tests are run four times in different rendering situations:

  • Server render to string
  • Client render on top of an empty DOM
  • Client render on top of good server markup
  • Client render on top of a bad server markup

The last of those (client render on bad markup) is expected to raise a markup mismatch warning, which Fiber can't do yet, so all those tests currently fail.

@aickin
Copy link
Contributor Author

aickin commented Feb 28, 2017

I expect to have time to look at this tomorrow.

Oh, and thanks for that! 👍

@zackargyle
Copy link

I just want to throw out how excited I am about this. Thank you @aickin for doing this! Really stoked that Fiber SR is getting some attention. ✌🏻

Copy link
Collaborator

@sophiebits sophiebits left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great, just a couple questions inline.

Can we also just put these in a new test file for simplicity? I'm thinking something like ReactDOMServerAndClientAttribute-test although that's a little wordy and probably still not accurate. (I don't care strongly what the name is.)

If you like, we can turn on async/await in the tests; I have no objection. Sounds like this should be pretty easy in babelrc: http://stackoverflow.com/questions/33861267/how-to-set-a-rc-file-conditionally (we set NODE_ENV=test on tests).

//
// Since all of the renders in this function are on the client, you can test interactivity,
// unlike with itRenders.
function itClientRenders(desc, testFn) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason these three are split from the other one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of the tests in this PR use it, but some of the ones coming later do.

The idea is that itRenders is for tests that only need to inspect the DOM, whereas itClientRenders is for tests that need to test interactivity (things like events, refs, etc.). The latter tests are only possible when ReactDOM.render has been called, which doesn't happen in the server render-only tests.

I tried to explain that in the comment above the function, but obviously it wasn't clear enough. Any suggestions on how to make it clearer?

ReactReconcileTransaction = require('ReactReconcileTransaction');

ExecutionEnvironment = require('ExecutionEnvironment');
ExecutionEnvironment.canUseDOM = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be conditional on whether we are going to do client or server rendering, correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right; this was an incantation I copied from the old code without thinking. I've changed it in a91c836 to change canUseDom to true before the call to ReactDOM.render in renderToDom (and change it back after). Seems to work right AFAICT.

@@ -549,4 +661,27 @@ describe('ReactDOMServer', () => {
);
}).toThrowError(/Cannot assign to read only property.*/);
});

describe('basic rendering', function() {
itRenders('should render a blank div', render =>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we rename this function or the tests so that "it renders should render a blank div" is an actual sentence/phrase?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem. Changed in a91c836.

);

itRenders('should render a self-closing tag', render =>
render(<br />).then(e => expect(e.tagName.toLowerCase()).toBe('br')));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I think tagName is guaranteed to be uppercase so this could just be expect(e.tagName).toBe('BR')?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. Modified all three tests in a91c836. Thanks!

…eworked wording of test names, corrected use of canUseDom, and simplified tests against tagName. Thanks for the help, @spicyj!
@aickin
Copy link
Contributor Author

aickin commented Mar 1, 2017

Thanks, @spicyj! I think I've addressed all the comments in your review in a91c836. I named the file ReactDOMServerIntegration-test.js because it's more of an integration-y test, but I'm not in love with the name at all; open to any suggestions.

I'm very interested in enabling async/await, but I'll put it in a separate PR so as to not slow this PR down.

Thank you for your time and thoughtful review!

Copy link
Collaborator

@sophiebits sophiebits left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks. I think it would be nice to assert on the warning/error message text but we can solve that in a future PR. Maybe it can just take expectedErrors as an array?

@sophiebits sophiebits merged commit 3788654 into facebook:master Mar 1, 2017
@sophiebits
Copy link
Collaborator

Actually, for async/await – let's do the configuration in this file

var babelOptions = {
and only do it if the file path matches __tests__ so we don't accidentally introduce async/await into our actual bundle code. (Probably unlikely but I'd rather be safe.)

@aickin
Copy link
Contributor Author

aickin commented Mar 1, 2017

I think it would be nice to assert on the warning/error message text... Maybe it can just take expectedErrors as an array?

I was also thinking that's probably a good idea, or maybe assert on a substring/regex of the text. I'd be happy to do that a bit later.

@aickin
Copy link
Contributor Author

aickin commented Mar 1, 2017

Actually, for async/await – let's do the configuration in this file ...

Darn it; I almost had the async PR filed before you asked for this... ;)

Seriously though: good suggestion and thanks for it.

@sophiebits
Copy link
Collaborator

Sorry. :)

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

Successfully merging this pull request may close these issues.

5 participants