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

Add component stack to invariant #11652

Closed

Conversation

Ethan-Arrowood
Copy link
Contributor

Ref: #11619

Initial PR shows changes in ReactFiber.js. Notice I needed to update some unit tests to expect the component stacks. Currently I had to hard-code the component stack into the expected response. Is there a way to implement this using globs or some other method? If anyone ever makes other changes to these test files those hard-coded lines will break.

@gaearon
Copy link
Collaborator

gaearon commented Nov 24, 2017

Regarding CI failure, might be a bug in the new bundle testing system: #11653. Can you cherry pick my change there to verify if it helps?

@Ethan-Arrowood
Copy link
Contributor Author

Ethan-Arrowood commented Nov 25, 2017

Okay cherry picked and pushed. Let's see what happens to the build ( 😢 😄 )

@gaearon
Copy link
Collaborator

gaearon commented Nov 25, 2017

Oh, I see what's going on. Our build script clears the changes to the error code file.

@gaearon
Copy link
Collaborator

gaearon commented Nov 25, 2017

#11655

@Ethan-Arrowood
Copy link
Contributor Author

Nice work!

@Ethan-Arrowood
Copy link
Contributor Author

@gaearon can you review what I've done so far and give me some feedback?

@gaearon
Copy link
Collaborator

gaearon commented Dec 7, 2017

Could you please bring this up to date?

@Ethan-Arrowood
Copy link
Contributor Author

Will do

@Ethan-Arrowood
Copy link
Contributor Author

Ethan-Arrowood commented Dec 8, 2017

Uh oh I don't think I did that correctly.

@gaearon is there something I can do to fix this? Should I just open a new PR on an update branch. I'm sorry I messed this up 🤦‍♀️

@@ -3,6 +3,7 @@
set -e

yarn build --extract-errors

Copy link
Collaborator

Choose a reason for hiding this comment

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

?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Merge conflict mistake. Will change

@@ -751,7 +751,9 @@ describe('ReactIncrementalErrorHandling', () => {
(__DEV__
? " You likely forgot to export your component from the file it's " +
'defined in, or you might have mixed up default and named imports.' +
'\n\nCheck the render method of `BrokenRender`.'
'\n\nCheck the render method of `BrokenRender`.' +
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we remove this line now? Seems unnecessary with the stack.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. I need to make the following two lines globs instead of hardcoded values too.

@gaearon
Copy link
Collaborator

gaearon commented Dec 8, 2017

I usually just write down the hashes of commits I want to keep and then do

git fetch origin # assuming origin points to our react repo, might be 'upstream' for you
git reset --hard origin/master
git cherry-pick <my first commit hash>
git cherry-pick <my second commit hash>
...
git push -f

@Ethan-Arrowood
Copy link
Contributor Author

@gaearon thank you for this! I'm honestly going to print it and pin it to my workspace so I can use it in the future.

@gaearon
Copy link
Collaborator

gaearon commented Dec 8, 2017

Just make sure you have all the commits you need written down before you reset.

@gaearon
Copy link
Collaborator

gaearon commented Dec 12, 2017

Ping :-)

@Ethan-Arrowood
Copy link
Contributor Author

@gaearon apologies on the delay I just finished finals yesterday and I have to move out of the dorms today. I'll get to work on this tomorrow and hopefully have something substantial by friday

@gaearon
Copy link
Collaborator

gaearon commented Dec 12, 2017

Ah sorry, I didn’t know. Take your time please!

@Ethan-Arrowood Ethan-Arrowood force-pushed the add-callstack-to-invariant branch 2 times, most recently from fe77ee9 to 7ae3037 Compare December 15, 2017 04:12
@Ethan-Arrowood
Copy link
Contributor Author

Okay I've done a bunch of clean up. And now I'm going to try and implement the callstack on invariants!

@Ethan-Arrowood
Copy link
Contributor Author

Ethan-Arrowood commented Dec 15, 2017

@gaearon do you have any ideas on how I can get the unit tests to expect the stack trace? If there is a way to use string wildcards that might suffice; otherwise, I'm a little lost. Will continue to try stuff this evening.

screen shot 2017-12-14 at 11 40 24 pm

I was able to import the getCurrentStackAddendum into the test file but it is returning null when I use it within the test 😔 Still returns 'is not a function'

@gaearon
Copy link
Collaborator

gaearon commented Jan 5, 2018

Can you rebase? You can see how our new custom toWarnDev() matcher implements the stack aliasing and do something similar, e.g. by overriding the built-in toError() matcher.

@gaearon
Copy link
Collaborator

gaearon commented Jan 5, 2018

Or maybe you could add toErrorWithStack() or something like this.

@Ethan-Arrowood
Copy link
Contributor Author

I'll give it a shot thank you!

@Ethan-Arrowood Ethan-Arrowood force-pushed the add-callstack-to-invariant branch from 5bdd984 to 48833f6 Compare January 6, 2018 03:24
@Ethan-Arrowood
Copy link
Contributor Author

I don't know why this closed itself. . . I was just rebaseing. I'll try to make some changes and reopen.

@Ethan-Arrowood Ethan-Arrowood reopened this Jan 6, 2018
@Ethan-Arrowood
Copy link
Contributor Author

After a lot of head scratching tonight I'm not exactly sure where to go with this. The tests that are failing after I add the stack to the invariant are .toEqual( ). These toEqual methods contain the span array returned from ReactNoop.getChildren(). I cannot get the getCurrentFiberStackAddendum() to run in the test file (for whatever reason it says it is 'not a function' but I'm importing it just like any other module).

@Ethan-Arrowood
Copy link
Contributor Author

Ethan-Arrowood commented Jan 6, 2018

But I think I understand your recommendation on making a custom matcher.

Getting the component stack in the test file doesn't matter if I can essentially parse the .getChildren() result and replace all the at (File/Location/Path/thing.js:234) with at **.

Working on a custom matcher now. Never wrote one before so lets see how this goes!

@Ethan-Arrowood
Copy link
Contributor Author

Commit 8825ba2 adds a custom matcher toErrorWithStack; however, I am having some trouble integrating it with jest. -- working on it now.

@Ethan-Arrowood
Copy link
Contributor Author

🎉 I got the custom matcher to work. (I was using an arrow function before which didn't pass the jest this through).

Now I gotta go add the component stack to all invariants and then update failing tests!

@@ -792,14 +794,16 @@ describe('ReactIncrementalErrorHandling', () => {
expect(ReactNoop.flush).toWarnDev(
'Warning: React.createElement: type is invalid -- expected a string',
);
expect(ReactNoop.getChildren()).toEqual([
expect(ReactNoop.getChildren()).toErrorWithStack([
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not an error. It’s comparing the actual children (because the error was “rendered” into the DOM by an error boundary).

Just change this to toContain and completely drop the part with the stack. It doesn’t matter because we have other tests verifying the stack works.

@@ -745,14 +745,16 @@ describe('ReactIncrementalErrorHandling', () => {
expect(ReactNoop.flush).toWarnDev(
'Warning: React.createElement: type is invalid -- expected a string',
);
expect(ReactNoop.getChildren()).toEqual([
expect(ReactNoop.getChildren()).toErrorWithStack([
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as below. It was not throwing an error so it shouldn’t throw one now either.

@Ethan-Arrowood
Copy link
Contributor Author

Okay so I made the changes. I'll be adding the component stack to all invariants soon

@@ -745,7 +745,7 @@ describe('ReactIncrementalErrorHandling', () => {
expect(ReactNoop.flush).toWarnDev(
'Warning: React.createElement: type is invalid -- expected a string',
);
expect(ReactNoop.getChildren()).toEqual([
expect(ReactNoop.getChildren()).toContent([
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we should add a custom matcher just for this one use case.

I'm sorry I wasn't clear before—when I said about custom matchers I meant about changing the code that currently uses toThrow(), not this use case.

Here, you can just use toContain and remove the part with the stack trace (it's not essential to this test)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

toContain is checking if something is within an array with ===. The span() method returns an object which would fail the strict equals. Could I keep it as .toEqual() and strip out the stack trace? I'll get to work on a code sample for this right now.

Copy link
Collaborator

Choose a reason for hiding this comment

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

You can do expect(ReactNoop.getChildren()[0].children[0]).toContain(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In these instances it seems as though children is an empty array. I'm getting: Expected array but received undefined when I use that line in the expect() statement.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Well, you can inspect the structure and figure out which one to compare 😉

}

function stripStackTrace(obj) {
obj[0].prop = removeStack(obj[0].prop);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we return a copy here please instead of mutating?

obj[0].prop = removeStack(obj[0].prop);
return obj;
let stripped = [...obj];
stripped[0].prop = removeStack(stripped[0].prop);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This still mutates the object.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay I guess I don't fully understand mutation. Let me know how the most recent changes look. I'm also going to start trying to fix the build errors.

return [{
...compSpan[0],
prop: removeStack(compSpan[0].prop),
}];
Copy link
Collaborator

Choose a reason for hiding this comment

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

If there is (incorrectly) more than one child, this will ignore it. Let's make sure we don't "lose" any input children?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Gotcha. Let me see what I can come up with.

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.

3 participants