UNPKG

hm-react-cli

Version:

Create a Huimei React project by module

1,331 lines (1,150 loc) 44.9 kB
"use strict"; describe("ReactChildren", () => { let React; let ReactTestUtils; beforeEach(() => { jest.resetModules(); React = require("react"); ReactTestUtils = require("test-utils"); }); it("should support identity for simple", () => { var context = {}; var callback = jasmine.createSpy().and.callFake(function (kid, index) { expect(this).toBe(context); expect(index).toBe(0); return kid; }); var simpleKid = <span key="simple" />; // First pass children into a component to fully simulate what happens when // using structures that arrive from transforms. var instance = <div>{simpleKid}</div>; React.Children.forEach(instance.props.children, callback, context); expect(callback).toHaveBeenCalledWith(simpleKid, 0); callback.calls.reset(); var mappedChildren = React.Children.map(instance.props.children, callback, context); expect(callback).toHaveBeenCalledWith(simpleKid, 0); expect(mappedChildren[0]).toEqual(<span key=".$simple" />); }); it("should treat single arrayless child as being in array", () => { var context = {}; var callback = jasmine.createSpy().and.callFake(function (kid, index) { expect(this).toBe(context); expect(index).toBe(0); return kid; }); var simpleKid = <span />; var instance = <div>{simpleKid}</div>; React.Children.forEach(instance.props.children, callback, context); expect(callback).toHaveBeenCalledWith(simpleKid, 0); callback.calls.reset(); var mappedChildren = React.Children.map(instance.props.children, callback, context); expect(callback).toHaveBeenCalledWith(simpleKid, 0); expect(mappedChildren[0]).toEqual(<span key=".0" />); }); it("should treat single child in array as expected", () => { var context = {}; var callback = jasmine.createSpy().and.callFake(function (kid, index) { expect(this).toBe(context); return kid; }); var simpleKid = <span key="simple" />; var instance = <div>{[simpleKid]}</div>; React.Children.forEach(instance.props.children, callback, context); expect(callback).toHaveBeenCalledWith(simpleKid, 0); callback.calls.reset(); var mappedChildren = React.Children.map(instance.props.children, callback, context); expect(callback).toHaveBeenCalledWith(simpleKid, 0); expect(mappedChildren[0]).toEqual(<span key=".$simple" />); }); it("should be called for each child", () => { var zero = <div key="keyZero" />; var one = null; var two = <div key="keyTwo" />; var three = null; var four = <div key="keyFour" />; var context = {}; var callback = jasmine.createSpy().and.callFake(function (kid, index) { expect(this).toBe(context); return kid; }); var instance = ( <div> {zero} {one} {two} {three} {four} </div> ); function assertCalls() { expect(callback).toHaveBeenCalledWith(zero, 0); expect(callback).toHaveBeenCalledWith(one, 1); expect(callback).toHaveBeenCalledWith(two, 2); expect(callback).toHaveBeenCalledWith(three, 3); expect(callback).toHaveBeenCalledWith(four, 4); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); var mappedChildren = React.Children.map(instance.props.children, callback, context); assertCalls(); expect(mappedChildren).toEqual([<div key=".$keyZero" />, <div key=".$keyTwo" />, <div key=".$keyFour" />]); }); it("React.Children.forEach不处理null void 0", () => { var i = 0; React.Children.forEach(null, function () { i++; }); React.Children.forEach(void 0, function () { i++; }); expect(i).toBe(0); }); it("should traverse children of different kinds", () => { var div = <div key="divNode" />; var span = <span key="spanNode" />; var a = <a key="aNode" />; var context = {}; var callback = jasmine.createSpy().and.callFake(function (kid, index) { expect(this).toBe(context); return kid; }); var instance = ( <div> {div} {[[span]]} {[a]} {"string"} {1234} {true} {false} {null} {undefined} </div> ); function assertCalls() { expect(callback.calls.count()).toBe(9); expect(callback).toHaveBeenCalledWith(div, 0); expect(callback).toHaveBeenCalledWith(span, 1); expect(callback).toHaveBeenCalledWith(a, 2); expect(callback).toHaveBeenCalledWith("string", 3); expect(callback).toHaveBeenCalledWith(1234, 4); expect(callback).toHaveBeenCalledWith(null, 5); expect(callback).toHaveBeenCalledWith(null, 6); expect(callback).toHaveBeenCalledWith(null, 7); expect(callback).toHaveBeenCalledWith(null, 8); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); var mappedChildren = React.Children.map(instance.props.children, callback, context); assertCalls(); expect(mappedChildren).toEqual([<div key=".$divNode" />, <span key=".1:0:$spanNode" />, <a key=".2:$aNode" />, "string", 1234]); }); it("should be called for each child in nested structure", () => { var zero = <div key="keyZero" />; var one = null; var two = <div key="keyTwo" />; var three = null; var four = <div key="keyFour" />; var five = <div key="keyFive" />; var context = {}; var callback = jasmine.createSpy().and.callFake(function (kid, index) { expect(this).toBe(context); return kid; }); var instance = <div>{[[zero, one, two], [three, four], five]}</div>; function assertCalls() { expect(callback.calls.count()).toBe(6); expect(callback).toHaveBeenCalledWith(zero, 0); expect(callback).toHaveBeenCalledWith(one, 1); expect(callback).toHaveBeenCalledWith(two, 2); expect(callback).toHaveBeenCalledWith(three, 3); expect(callback).toHaveBeenCalledWith(four, 4); expect(callback).toHaveBeenCalledWith(five, 5); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); var mappedChildren = React.Children.map(instance.props.children, callback, context); assertCalls(); expect(mappedChildren).toEqual([<div key=".0:$keyZero" />, <div key=".0:$keyTwo" />, <div key=".1:$keyFour" />, <div key=".$keyFive" />]); }); it("should retain key across two mappings", () => { var zeroForceKey = <div key="keyZero" />; var oneForceKey = <div key="keyOne" />; var context = {}; var callback = jasmine.createSpy().and.callFake(function (kid, index) { expect(this).toBe(context); return kid; }); var forcedKeys = ( <div> {zeroForceKey} {oneForceKey} </div> ); function assertCalls() { expect(callback).toHaveBeenCalledWith(zeroForceKey, 0); expect(callback).toHaveBeenCalledWith(oneForceKey, 1); callback.calls.reset(); } React.Children.forEach(forcedKeys.props.children, callback, context); assertCalls(); var mappedChildren = React.Children.map(forcedKeys.props.children, callback, context); assertCalls(); expect(mappedChildren).toEqual([<div key=".$keyZero" />, <div key=".$keyOne" />]); }); it("should be called for each child in an iterable without keys", () => { //spyOn(console, "error"); var threeDivIterable = { "@@iterator": function () { var i = 0; return { next: function () { if (i++ < 3) { return { value: <div />, done: false }; } else { return { value: undefined, done: true }; } } }; } }; var context = {}; var callback = jasmine.createSpy().and.callFake(function (kid, index) { expect(this).toBe(context); return kid; }); var instance = <div>{threeDivIterable}</div>; function assertCalls() { expect(callback.calls.count()).toBe(3); expect(callback).toHaveBeenCalledWith(<div />, 0); expect(callback).toHaveBeenCalledWith(<div />, 1); expect(callback).toHaveBeenCalledWith(<div />, 2); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); var mappedChildren = React.Children.map(instance.props.children, callback, context); assertCalls(); var compareChildren = [<div key=".0" />, <div key=".1" />, <div key=".2" />]; expect(mappedChildren).toEqual(compareChildren); }); it("should be called for each child in an iterable with keys", () => { var threeDivIterable = { "@@iterator": function () { var i = 0; return { next: function () { if (i++ < 3) { return { value: <div key={"#" + i} />, done: false }; } else { return { value: undefined, done: true }; } } }; } }; var context = {}; var callback = jasmine.createSpy().and.callFake(function (kid, index) { expect(this).toBe(context); return kid; }); var instance = <div>{threeDivIterable}</div>; function assertCalls() { expect(callback.calls.count()).toBe(3); expect(callback).toHaveBeenCalledWith(<div key="#1" />, 0); expect(callback).toHaveBeenCalledWith(<div key="#2" />, 1); expect(callback).toHaveBeenCalledWith(<div key="#3" />, 2); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); var mappedChildren = React.Children.map(instance.props.children, callback, context); assertCalls(); expect(mappedChildren).toEqual([<div key=".$#1" />, <div key=".$#2" />, <div key=".$#3" />]); }); it("should not enumerate enumerable numbers (#4776)", () => { /*eslint-disable no-extend-native */ Number.prototype["@@iterator"] = function () { throw new Error("number iterator called"); }; /*eslint-enable no-extend-native */ try { var instance = ( <div> {5} {12} {13} </div> ); var context = {}; var callback = jasmine.createSpy().and.callFake(function (kid, index) { expect(this).toBe(context); return kid; }); var assertCalls = function () { expect(callback.calls.count()).toBe(3); expect(callback).toHaveBeenCalledWith(5, 0); expect(callback).toHaveBeenCalledWith(12, 1); expect(callback).toHaveBeenCalledWith(13, 2); callback.calls.reset(); }; React.Children.forEach(instance.props.children, callback, context); assertCalls(); var mappedChildren = React.Children.map(instance.props.children, callback, context); assertCalls(); expect(mappedChildren).toEqual([5, 12, 13]); } finally { delete Number.prototype["@@iterator"]; } }); it("should allow extension of native prototypes", () => { /*eslint-disable no-extend-native */ String.prototype.key = "react"; Number.prototype.key = "rocks"; /*eslint-enable no-extend-native */ var instance = ( <div> {"a"} {13} </div> ); var context = {}; var callback = jasmine.createSpy().and.callFake(function (kid, index) { expect(this).toBe(context); return kid; }); function assertCalls() { expect(callback.calls.count()).toBe(2, 0); expect(callback).toHaveBeenCalledWith("a", 0); expect(callback).toHaveBeenCalledWith(13, 1); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); var mappedChildren = React.Children.map(instance.props.children, callback, context); assertCalls(); expect(mappedChildren).toEqual(["a", 13]); delete String.prototype.key; delete Number.prototype.key; }); it("should pass key to returned component", () => { var mapFn = function (kid, index) { return <div>{kid}</div>; }; var simpleKid = <span key="simple" />; var instance = <div>{simpleKid}</div>; var mappedChildren = React.Children.map(instance.props.children, mapFn); expect(React.Children.count(mappedChildren)).toBe(1); expect(mappedChildren[0]).not.toBe(simpleKid); expect(mappedChildren[0].props.children).toBe(simpleKid); expect(mappedChildren[0].key).toBe(".$simple"); }); it("should invoke callback with the right context", () => { var lastContext; var callback = function (kid, index) { lastContext = this; return this; }; // TODO: Use an object to test, after non-object fragments has fully landed. var scopeTester = "scope tester"; var simpleKid = <span key="simple" />; var instance = <div>{simpleKid}</div>; React.Children.forEach(instance.props.children, callback, scopeTester); expect(lastContext).toBe(scopeTester); var mappedChildren = React.Children.map(instance.props.children, callback, scopeTester); expect(React.Children.count(mappedChildren)).toBe(1); expect(mappedChildren[0]).toBe(scopeTester); }); it("should be called for each child", () => { const zero = <div key="keyZero" />; const one = null; const two = <div key="keyTwo" />; const three = null; const four = <div key="keyFour" />; const context = {}; const callback = jasmine.createSpy().and.callFake(function (kid) { expect(this).toBe(context); return kid; }); const instance = ( <div> {zero} {one} {two} {three} {four} </div> ); function assertCalls() { expect(callback).toHaveBeenCalledWith(zero, 0); expect(callback).toHaveBeenCalledWith(one, 1); expect(callback).toHaveBeenCalledWith(two, 2); expect(callback).toHaveBeenCalledWith(three, 3); expect(callback).toHaveBeenCalledWith(four, 4); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); const mappedChildren = React.Children.map( instance.props.children, callback, context, ); assertCalls(); expect(mappedChildren).toEqual([ <div key=".$keyZero" />, <div key=".$keyTwo" />, <div key=".$keyFour" />, ]); }); it('should traverse children of different kinds', () => { const div = <div key="divNode" />; const span = <span key="spanNode" />; const a = <a key="aNode" />; const context = {}; const callback = jasmine.createSpy().and.callFake(function (kid) { expect(this).toBe(context); return kid; }); const instance = ( <div> {div} {[[span]]} {[a]} {'string'} {1234} {true} {false} {null} {undefined} </div> ); function assertCalls() { expect(callback.calls.count()).toBe(9); expect(callback).toHaveBeenCalledWith(div, 0); expect(callback).toHaveBeenCalledWith(span, 1); expect(callback).toHaveBeenCalledWith(a, 2); expect(callback).toHaveBeenCalledWith('string', 3); expect(callback).toHaveBeenCalledWith(1234, 4); expect(callback).toHaveBeenCalledWith(null, 5); expect(callback).toHaveBeenCalledWith(null, 6); expect(callback).toHaveBeenCalledWith(null, 7); expect(callback).toHaveBeenCalledWith(null, 8); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); const mappedChildren = React.Children.map( instance.props.children, callback, context, ); assertCalls(); expect(mappedChildren).toEqual([ <div key=".$divNode" />, <span key=".1:0:$spanNode" />, <a key=".2:$aNode" />, 'string', 1234, ]); }); it('should be called for each child in nested structure', () => { const zero = <div key="keyZero" />; const one = null; const two = <div key="keyTwo" />; const three = null; const four = <div key="keyFour" />; const five = <div key="keyFive" />; const context = {}; const callback = jasmine.createSpy().and.callFake(function (kid) { return kid; }); const instance = <div>{[[zero, one, two], [three, four], five]}</div>; function assertCalls() { expect(callback.calls.count()).toBe(6); expect(callback).toHaveBeenCalledWith(zero, 0); expect(callback).toHaveBeenCalledWith(one, 1); expect(callback).toHaveBeenCalledWith(two, 2); expect(callback).toHaveBeenCalledWith(three, 3); expect(callback).toHaveBeenCalledWith(four, 4); expect(callback).toHaveBeenCalledWith(five, 5); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); const mappedChildren = React.Children.map( instance.props.children, callback, context, ); assertCalls(); expect(mappedChildren).toEqual([ <div key=".0:$keyZero" />, <div key=".0:$keyTwo" />, <div key=".1:$keyFour" />, <div key=".$keyFive" />, ]); }); it('should retain key across two mappings', () => { const zeroForceKey = <div key="keyZero" />; const oneForceKey = <div key="keyOne" />; const context = {}; const callback = jasmine.createSpy().and.callFake(function (kid) { expect(this).toBe(context); return kid; }); const forcedKeys = ( <div> {zeroForceKey} {oneForceKey} </div> ); function assertCalls() { expect(callback).toHaveBeenCalledWith(zeroForceKey, 0); expect(callback).toHaveBeenCalledWith(oneForceKey, 1); callback.calls.reset(); } React.Children.forEach(forcedKeys.props.children, callback, context); assertCalls(); const mappedChildren = React.Children.map( forcedKeys.props.children, callback, context, ); assertCalls(); expect(mappedChildren).toEqual([ <div key=".$keyZero" />, <div key=".$keyOne" />, ]); }); it('should be called for each child in an iterable without keys', () => { const threeDivIterable = { '@@iterator': function () { let i = 0; return { next: function () { if (i++ < 3) { return { value: <div />, done: false }; } else { return { value: undefined, done: true }; } }, }; }, }; const context = {}; const callback = jasmine.createSpy().and.callFake(function (kid) { expect(this).toBe(context); return kid; }); let instance; expect(() => (instance = <div>{threeDivIterable}</div>)).toWarnDev( 'Warning: Each child in an array or iterator should have a unique "key" prop.', ); function assertCalls() { expect(callback.calls.count()).toBe(3); expect(callback).toHaveBeenCalledWith(<div />, 0); expect(callback).toHaveBeenCalledWith(<div />, 1); expect(callback).toHaveBeenCalledWith(<div />, 2); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); const mappedChildren = React.Children.map( instance.props.children, callback, context, ); assertCalls(); expect(mappedChildren).toEqual([ <div key=".0" />, <div key=".1" />, <div key=".2" />, ]); }); it('should be called for each child in an iterable without keys', () => { const threeDivIterable = { '@@iterator': function () { let i = 0; return { next: function () { if (i++ < 3) { return { value: <div />, done: false }; } else { return { value: undefined, done: true }; } }, }; }, }; const context = {}; const callback = jasmine.createSpy().and.callFake(function (kid) { expect(this).toBe(context); return kid; }); let instance; expect(() => (instance = <div>{threeDivIterable}</div>)).toWarnDev( 'Warning: Each child in an array or iterator should have a unique "key" prop.', ); function assertCalls() { expect(callback.calls.count()).toBe(3); expect(callback).toHaveBeenCalledWith(<div />, 0); expect(callback).toHaveBeenCalledWith(<div />, 1); expect(callback).toHaveBeenCalledWith(<div />, 2); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); const mappedChildren = React.Children.map( instance.props.children, callback, context, ); assertCalls(); expect(mappedChildren).toEqual([ <div key=".0" />, <div key=".1" />, <div key=".2" />, ]); }); it('should be called for each child in an iterable with keys', () => { const threeDivIterable = { '@@iterator': function () { let i = 0; return { next: function () { if (i++ < 3) { return { value: <div key={'#' + i} />, done: false }; } else { return { value: undefined, done: true }; } }, }; }, }; const context = {}; const callback = jasmine.createSpy().and.callFake(function (kid) { expect(this).toBe(context); return kid; }); const instance = <div>{threeDivIterable}</div>; function assertCalls() { expect(callback.calls.count()).toBe(3); expect(callback).toHaveBeenCalledWith(<div key="#1" />, 0); expect(callback).toHaveBeenCalledWith(<div key="#2" />, 1); expect(callback).toHaveBeenCalledWith(<div key="#3" />, 2); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); const mappedChildren = React.Children.map( instance.props.children, callback, context, ); assertCalls(); expect(mappedChildren).toEqual([ <div key=".$#1" />, <div key=".$#2" />, <div key=".$#3" />, ]); }); it('should not enumerate enumerable numbers (#4776)', () => { /*eslint-disable no-extend-native */ Number.prototype['@@iterator'] = function () { throw new Error('number iterator called'); }; /*eslint-enable no-extend-native */ try { const instance = ( <div> {5} {12} {13} </div> ); const context = {}; const callback = jasmine.createSpy().and.callFake(function (kid) { expect(this).toBe(context); return kid; }); const assertCalls = function () { expect(callback.calls.count()).toBe(3); expect(callback).toHaveBeenCalledWith(5, 0); expect(callback).toHaveBeenCalledWith(12, 1); expect(callback).toHaveBeenCalledWith(13, 2); callback.calls.reset(); }; React.Children.forEach(instance.props.children, callback, context); assertCalls(); const mappedChildren = React.Children.map( instance.props.children, callback, context, ); assertCalls(); expect(mappedChildren).toEqual([5, 12, 13]); } finally { delete Number.prototype['@@iterator']; } }); it('should allow extension of native prototypes', () => { /*eslint-disable no-extend-native */ String.prototype.key = 'react'; Number.prototype.key = 'rocks'; /*eslint-enable no-extend-native */ const instance = ( <div> {'a'} {13} </div> ); const context = {}; const callback = jasmine.createSpy().and.callFake(function (kid) { expect(this).toBe(context); return kid; }); function assertCalls() { expect(callback.calls.count()).toBe(2, 0); expect(callback).toHaveBeenCalledWith('a', 0); expect(callback).toHaveBeenCalledWith(13, 1); callback.calls.reset(); } React.Children.forEach(instance.props.children, callback, context); assertCalls(); const mappedChildren = React.Children.map( instance.props.children, callback, context, ); assertCalls(); expect(mappedChildren).toEqual(['a', 13]); delete String.prototype.key; delete Number.prototype.key; }); it('should pass key to returned component', () => { const mapFn = function (kid, index) { return <div>{kid}</div>; }; const simpleKid = <span key="simple" />; const instance = <div>{simpleKid}</div>; const mappedChildren = React.Children.map(instance.props.children, mapFn); expect(React.Children.count(mappedChildren)).toBe(1); expect(mappedChildren[0]).not.toBe(simpleKid); expect(mappedChildren[0].props.children).toBe(simpleKid); expect(mappedChildren[0].key).toBe('.$simple'); }); it('should invoke callback with the right context', () => { let lastContext; const callback = function (kid, index) { lastContext = this; return this; }; // TODO: Use an object to test, after non-object fragments has fully landed. const scopeTester = 'scope tester'; const simpleKid = <span key="simple" />; const instance = <div>{simpleKid}</div>; React.Children.forEach(instance.props.children, callback, scopeTester); expect(lastContext).toBe(scopeTester); const mappedChildren = React.Children.map( instance.props.children, callback, scopeTester, ); expect(React.Children.count(mappedChildren)).toBe(1); expect(mappedChildren[0]).toBe(scopeTester); }); it('should be called for each child', () => { const zero = <div key="keyZero" />; const one = null; const two = <div key="keyTwo" />; const three = null; const four = <div key="keyFour" />; const mapped = [ <div key="giraffe" />, // Key should be joined to obj key null, // Key should be added even if we don't supply it! <div />, // Key should be added even if not supplied! <span />, // Map from null to something. <div key="keyFour" />, ]; const callback = jasmine.createSpy().and.callFake(function (kid, index) { return mapped[index]; }); const instance = ( <div> {zero} {one} {two} {three} {four} </div> ); React.Children.forEach(instance.props.children, callback); expect(callback).toHaveBeenCalledWith(zero, 0); expect(callback).toHaveBeenCalledWith(one, 1); expect(callback).toHaveBeenCalledWith(two, 2); expect(callback).toHaveBeenCalledWith(three, 3); expect(callback).toHaveBeenCalledWith(four, 4); callback.calls.reset(); const mappedChildren = React.Children.map( instance.props.children, callback, ); expect(callback.calls.count()).toBe(5); expect(React.Children.count(mappedChildren)).toBe(4); // Keys default to indices. expect([ mappedChildren[0].key, mappedChildren[1].key, mappedChildren[2].key, mappedChildren[3].key, ]).toEqual(['giraffe/.$keyZero', '.$keyTwo', '.3', '.$keyFour']); expect(callback).toHaveBeenCalledWith(zero, 0); expect(callback).toHaveBeenCalledWith(one, 1); expect(callback).toHaveBeenCalledWith(two, 2); expect(callback).toHaveBeenCalledWith(three, 3); expect(callback).toHaveBeenCalledWith(four, 4); expect(mappedChildren[0]).toEqual(<div key="giraffe/.$keyZero" />); expect(mappedChildren[1]).toEqual(<div key=".$keyTwo" />); expect(mappedChildren[2]).toEqual(<span key=".3" />); expect(mappedChildren[3]).toEqual(<div key=".$keyFour" />); }); it('should be called for each child in nested structure', () => { const zero = <div key="keyZero" />; const one = null; const two = <div key="keyTwo" />; const three = null; const four = <div key="keyFour" />; const five = <div key="keyFive" />; const zeroMapped = <div key="giraffe" />; // Key should be overridden const twoMapped = <div />; // Key should be added even if not supplied! const fourMapped = <div key="keyFour" />; const fiveMapped = <div />; const callback = jasmine.createSpy().and.callFake(function (kid) { switch (kid) { case zero: return zeroMapped; case two: return twoMapped; case four: return fourMapped; case five: return fiveMapped; default: return kid; } }); const frag = [[zero, one, two], [three, four], five]; const instance = <div>{[frag]}</div>; React.Children.forEach(instance.props.children, callback); expect(callback.calls.count()).toBe(6); expect(callback).toHaveBeenCalledWith(zero, 0); expect(callback).toHaveBeenCalledWith(one, 1); expect(callback).toHaveBeenCalledWith(two, 2); expect(callback).toHaveBeenCalledWith(three, 3); expect(callback).toHaveBeenCalledWith(four, 4); expect(callback).toHaveBeenCalledWith(five, 5); callback.calls.reset(); const mappedChildren = React.Children.map( instance.props.children, callback, ); expect(callback.calls.count()).toBe(6); expect(callback).toHaveBeenCalledWith(zero, 0); expect(callback).toHaveBeenCalledWith(one, 1); expect(callback).toHaveBeenCalledWith(two, 2); expect(callback).toHaveBeenCalledWith(three, 3); expect(callback).toHaveBeenCalledWith(four, 4); expect(callback).toHaveBeenCalledWith(five, 5); expect(React.Children.count(mappedChildren)).toBe(4); // Keys default to indices. expect([ mappedChildren[0].key, mappedChildren[1].key, mappedChildren[2].key, mappedChildren[3].key, ]).toEqual([ 'giraffe/.0:0:$keyZero', '.0:0:$keyTwo', '.0:1:$keyFour', '.0:$keyFive', ]); expect(mappedChildren[0]).toEqual(<div key="giraffe/.0:0:$keyZero" />); expect(mappedChildren[1]).toEqual(<div key=".0:0:$keyTwo" />); expect(mappedChildren[2]).toEqual(<div key=".0:1:$keyFour" />); expect(mappedChildren[3]).toEqual(<div key=".0:$keyFive" />); }); it('should retain key across two mappings', () => { const zeroForceKey = <div key="keyZero" />; const oneForceKey = <div key="keyOne" />; // Key should be joined to object key const zeroForceKeyMapped = <div key="giraffe" />; // Key should be added even if we don't supply it! const oneForceKeyMapped = <div />; const mapFn = function (kid, index) { return index === 0 ? zeroForceKeyMapped : oneForceKeyMapped; }; const forcedKeys = ( <div> {zeroForceKey} {oneForceKey} </div> ); const expectedForcedKeys = ['giraffe/.$keyZero', '.$keyOne']; const mappedChildrenForcedKeys = React.Children.map( forcedKeys.props.children, mapFn, ); const mappedForcedKeys = mappedChildrenForcedKeys.map(c => c.key); expect(mappedForcedKeys).toEqual(expectedForcedKeys); const expectedRemappedForcedKeys = [ 'giraffe/.$giraffe/.$keyZero', '.$.$keyOne', ]; const remappedChildrenForcedKeys = React.Children.map( mappedChildrenForcedKeys, mapFn, ); expect(remappedChildrenForcedKeys.map(c => c.key)).toEqual( expectedRemappedForcedKeys, ); }); it('should not throw if key provided is a dupe with array key', () => { const zero = <div />; const one = <div key="0" />; const mapFn = function () { return null; }; const instance = ( <div> {zero} {one} </div> ); expect(function () { React.Children.map(instance.props.children, mapFn); }).not.toThrow(); }); it('should use the same key for a cloned element', () => { const instance = ( <div> <div /> </div> ); const mapped = React.Children.map( instance.props.children, element => element, ); const mappedWithClone = React.Children.map( instance.props.children, element => React.cloneElement(element), ); expect(mapped[0].key).toBe(mappedWithClone[0].key); }); it('should use the same key for a cloned element with key', () => { const instance = ( <div> <div key="unique" /> </div> ); const mapped = React.Children.map( instance.props.children, element => element, ); const mappedWithClone = React.Children.map( instance.props.children, element => React.cloneElement(element, { key: 'unique' }), ); expect(mapped[0].key).toBe(mappedWithClone[0].key); }); it('should return 0 for null children', () => { const numberOfChildren = React.Children.count(null); expect(numberOfChildren).toBe(0); }); it('should return 0 for undefined children', () => { const numberOfChildren = React.Children.count(undefined); expect(numberOfChildren).toBe(0); }); it('should return 1 for single child', () => { const simpleKid = <span key="simple" />; const instance = <div>{simpleKid}</div>; const numberOfChildren = React.Children.count(instance.props.children); expect(numberOfChildren).toBe(1); }); it('should count the number of children in flat structure', () => { const zero = <div key="keyZero" />; const one = null; const two = <div key="keyTwo" />; const three = null; const four = <div key="keyFour" />; const instance = ( <div> {zero} {one} {two} {three} {four} </div> ); const numberOfChildren = React.Children.count(instance.props.children); expect(numberOfChildren).toBe(5); }); it('should count the number of children in nested structure', () => { const zero = <div key="keyZero" />; const one = null; const two = <div key="keyTwo" />; const three = null; const four = <div key="keyFour" />; const five = <div key="keyFive" />; const instance = ( <div>{[[[zero, one, two], [three, four], five], null]}</div> ); const numberOfChildren = React.Children.count(instance.props.children); expect(numberOfChildren).toBe(7); }); it('should flatten children to an array', () => { expect(React.Children.toArray(undefined)).toEqual([]); expect(React.Children.toArray(null)).toEqual([]); expect(React.Children.toArray(<div />).length).toBe(1); expect(React.Children.toArray([<div />]).length).toBe(1); expect(React.Children.toArray(<div />)[0].key).toBe( React.Children.toArray([<div />])[0].key, ); const flattened = React.Children.toArray([ [<div key="apple" />, <div key="banana" />, <div key="camel" />], [<div key="banana" />, <div key="camel" />, <div key="deli" />], ]); expect(flattened.length).toBe(6); expect(flattened[1].key).toContain('banana'); expect(flattened[3].key).toContain('banana'); expect(flattened[1].key).not.toBe(flattened[3].key); const reversed = React.Children.toArray([ [<div key="camel" />, <div key="banana" />, <div key="apple" />], [<div key="deli" />, <div key="camel" />, <div key="banana" />], ]); expect(flattened[0].key).toBe(reversed[2].key); expect(flattened[1].key).toBe(reversed[1].key); expect(flattened[2].key).toBe(reversed[0].key); expect(flattened[3].key).toBe(reversed[5].key); expect(flattened[4].key).toBe(reversed[4].key); expect(flattened[5].key).toBe(reversed[3].key); // null/undefined/bool are all omitted expect(React.Children.toArray([1, 'two', null, undefined, true])).toEqual([ 1, 'two', ]); }); it('should escape keys', () => { const zero = <div key="1" />; const one = <div key="1=::=2" />; const instance = ( <div> {zero} {one} </div> ); const mappedChildren = React.Children.map( instance.props.children, kid => kid, ); expect(mappedChildren).toEqual([ <div key=".$1" />, <div key=".$1=0=2=2=02" />, ]); }); it("should throw on object", () => { // 'Objects are not valid as a React child (found: object with keys ' + // '{a, b}). If you meant to render a collection of children, use an ' + // 'array instead.', expect(function () { React.Children.forEach({ a: 1, b: 2 }, function () { }, null); }).toThrow("children: type is invalid."); }); it("should throw on regex", () => { // Really, we care about dates (#4840) but those have nondeterministic // serialization (timezones) so let's test a regex instead: expect(function () { React.Children.forEach(/abc/, function () { }, null); }).toThrow("children: type is invalid."); }); it("复杂的孩子转换", function () { function getString(nodes) { var str = []; for (var i = 0, node; (node = nodes[i++]);) { if (node.nodeType === 8 && node.nodeValue.indexOf("react-text") !== 0) { continue; } str.push(node.nodeName.toLowerCase()); } return str.join(" "); } var index = 0; var map = [ <div> 1111<p>ddd</p> <span>333</span> <Link /> </div>, <div> <em>新的</em> <span>111</span>222<span>333</span> <b>444</b> <Link /> </div>, <div> <span>33</span> </div> ]; function Link() { return index == 1 ? <strong>ddd</strong> : <i>ddd</i>; } class App extends React.Component { constructor(props) { super(props); this.state = { aaa: "aaa" }; } change(a) { this.setState({ aaa: a }); } componentDidMount() { } componentWillUpdate() { } render() { return map[index++]; } } var div = document.createElement("div") var s = ReactDOM.render(<App />, div); expect(getString(div.firstChild.childNodes)).toBe("#text p span strong"); s.change(100); expect(getString(div.firstChild.childNodes)).toBe("em span #text span b i"); s.change(100); expect(getString(div.firstChild.childNodes)).toBe("span"); }); it("对一个容器节点反复渲染组件或元素 ", () => { class Comp extends React.Component { render() { return <span>span in a component</span>; } } var div = document.createElement("div") function test(content) { React.render(content, div); } test(<Comp />); test(<div>just a div</div>); test(<Comp />); expect(div.firstChild.innerHTML).toEqual("span in a component"); }); });