-
Notifications
You must be signed in to change notification settings - Fork 47.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Fiber] Fix reactComponentExpect (#8258)
* Add more reactComponentExpect tests * Implement reactComponentExpect in Fiber
- Loading branch information
Showing
5 changed files
with
245 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,9 +13,23 @@ | |
|
||
var ReactInstanceMap = require('ReactInstanceMap'); | ||
var ReactTestUtils = require('ReactTestUtils'); | ||
var ReactTypeOfWork = require('ReactTypeOfWork'); | ||
|
||
var { | ||
HostText, | ||
} = ReactTypeOfWork; | ||
|
||
var invariant = require('invariant'); | ||
|
||
// Fiber doesn't actually have an instance for empty components | ||
// but we'll pretend it does while we keep compatibility with Stack. | ||
var fiberNullInstance = { | ||
type: null, | ||
child: null, | ||
sibling: null, | ||
tag: 99, | ||
}; | ||
|
||
function reactComponentExpect(instance) { | ||
if (instance instanceof reactComponentExpectInternal) { | ||
return instance; | ||
|
@@ -52,7 +66,13 @@ Object.assign(reactComponentExpectInternal.prototype, { | |
* @instance: Retrieves the backing instance. | ||
*/ | ||
instance: function() { | ||
return this._instance.getPublicInstance(); | ||
if (typeof this._instance.tag === 'number') { | ||
// Fiber reconciler | ||
return this._instance.stateNode; | ||
} else { | ||
// Stack reconciler | ||
return this._instance.getPublicInstance(); | ||
} | ||
}, | ||
|
||
/** | ||
|
@@ -71,7 +91,14 @@ Object.assign(reactComponentExpectInternal.prototype, { | |
*/ | ||
expectRenderedChild: function() { | ||
this.toBeCompositeComponent(); | ||
var child = this._instance._renderedComponent; | ||
var child = null; | ||
if (typeof this._instance.tag === 'number') { | ||
// Fiber reconciler | ||
child = this._instance.child || fiberNullInstance; | ||
} else { | ||
// Stack reconciler | ||
child = this._instance._renderedComponent; | ||
} | ||
// TODO: Hide ReactEmptyComponent instances here? | ||
return new reactComponentExpectInternal(child); | ||
}, | ||
|
@@ -83,15 +110,30 @@ Object.assign(reactComponentExpectInternal.prototype, { | |
// Currently only dom components have arrays of children, but that will | ||
// change soon. | ||
this.toBeDOMComponent(); | ||
var renderedChildren = | ||
this._instance._renderedChildren || {}; | ||
for (var name in renderedChildren) { | ||
if (!renderedChildren.hasOwnProperty(name)) { | ||
continue; | ||
|
||
if (typeof this._instance.tag === 'number') { | ||
// Fiber reconciler | ||
var child = this._instance.child; | ||
var i = 0; | ||
while (child) { | ||
if (i === childIndex) { | ||
return new reactComponentExpectInternal(child); | ||
} | ||
child = child.sibling; | ||
i++; | ||
} | ||
if (renderedChildren[name]) { | ||
if (renderedChildren[name]._mountIndex === childIndex) { | ||
return new reactComponentExpectInternal(renderedChildren[name]); | ||
} else { | ||
// Stack reconciler | ||
var renderedChildren = | ||
this._instance._renderedChildren || {}; | ||
for (var name in renderedChildren) { | ||
if (!renderedChildren.hasOwnProperty(name)) { | ||
continue; | ||
} | ||
if (renderedChildren[name]) { | ||
if (renderedChildren[name]._mountIndex === childIndex) { | ||
return new reactComponentExpectInternal(renderedChildren[name]); | ||
} | ||
} | ||
} | ||
} | ||
|
@@ -100,24 +142,47 @@ Object.assign(reactComponentExpectInternal.prototype, { | |
|
||
toBeDOMComponentWithChildCount: function(count) { | ||
this.toBeDOMComponent(); | ||
var renderedChildren = this._instance._renderedChildren; | ||
expect(renderedChildren).toBeTruthy(); | ||
expect(Object.keys(renderedChildren).length).toBe(count); | ||
if (typeof this._instance.tag === 'number') { | ||
// Fiber reconciler | ||
var child = this._instance.child; | ||
var i = 0; | ||
while (child) { | ||
child = child.sibling; | ||
i++; | ||
} | ||
expect(i).toBe(count); | ||
} else { | ||
// Stack reconciler | ||
var renderedChildren = this._instance._renderedChildren; | ||
if (count > 0) { | ||
expect(renderedChildren).toBeTruthy(); | ||
expect(Object.keys(renderedChildren).length).toBe(count); | ||
} else { | ||
expect(renderedChildren).toBeFalsy(); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
gaearon
Author
Collaborator
|
||
} | ||
} | ||
return this; | ||
}, | ||
|
||
toBeDOMComponentWithNoChildren: function() { | ||
this.toBeDOMComponent(); | ||
expect(this._instance._renderedChildren).toBeFalsy(); | ||
this.toBeDOMComponentWithChildCount(0); | ||
return this; | ||
}, | ||
|
||
// Matchers ------------------------------------------------------------------ | ||
|
||
toBeComponentOfType: function(constructor) { | ||
expect( | ||
this._instance._currentElement.type === constructor | ||
).toBe(true); | ||
if (typeof this._instance.tag === 'number') { | ||
// Fiber reconciler | ||
expect( | ||
this._instance.type === constructor | ||
).toBe(true); | ||
} else { | ||
// Stack reconciler | ||
expect( | ||
this._instance._currentElement.type === constructor | ||
).toBe(true); | ||
} | ||
return this; | ||
}, | ||
|
||
|
@@ -126,6 +191,8 @@ Object.assign(reactComponentExpectInternal.prototype, { | |
* here. | ||
*/ | ||
toBeCompositeComponent: function() { | ||
// TODO: this code predates functional components | ||
// and doesn't work with them. | ||
expect( | ||
typeof this.instance() === 'object' && | ||
typeof this.instance().render === 'function' | ||
|
@@ -135,22 +202,35 @@ Object.assign(reactComponentExpectInternal.prototype, { | |
|
||
toBeCompositeComponentWithType: function(constructor) { | ||
this.toBeCompositeComponent(); | ||
expect( | ||
this._instance._currentElement.type === constructor | ||
).toBe(true); | ||
this.toBeComponentOfType(constructor); | ||
return this; | ||
}, | ||
|
||
toBeTextComponentWithValue: function(val) { | ||
var elementType = typeof this._instance._currentElement; | ||
expect(elementType === 'string' || elementType === 'number').toBe(true); | ||
expect(this._instance._stringText).toBe(val); | ||
if (typeof this._instance.tag === 'number') { | ||
// Fiber reconciler | ||
expect(this._instance.tag === HostText).toBe(true); | ||
var actualVal = this._instance.memoizedProps; | ||
expect(typeof actualVal === 'string' || typeof actualVal === 'number').toBe(true); | ||
expect(String(actualVal)).toBe(val); | ||
} else { | ||
// Fiber reconciler | ||
var elementType = typeof this._instance._currentElement; | ||
expect(elementType === 'string' || elementType === 'number').toBe(true); | ||
expect(this._instance._stringText).toBe(val); | ||
} | ||
return this; | ||
}, | ||
|
||
toBeEmptyComponent: function() { | ||
var element = this._instance._currentElement; | ||
return element === null || element === false; | ||
if (typeof this._instance.tag === 'number') { | ||
// Fiber reconciler | ||
expect(this._instance).toBe(fiberNullInstance); | ||
} else { | ||
// Stack reconciler | ||
var element = this._instance._currentElement; | ||
expect(element === null || element === false).toBe(true); | ||
} | ||
}, | ||
|
||
toBePresent: function() { | ||
|
Why is this expected to be falsy? This is a logic change for Stack. It's breaking tests in www.