How to use shallowRenderer method in storybook-root

Best JavaScript code snippet using storybook-root

ReactShallowRenderer-test.js

Source:ReactShallowRenderer-test.js Github

copy

Full Screen

1/**2 * Copyright (c) Facebook, Inc. and its affiliates.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 *7 * @emails react-core8 * @jest-environment node9 */10'use strict';11let createRenderer;12let PropTypes;13let React;14describe('ReactShallowRenderer', () => {15 beforeEach(() => {16 jest.resetModules();17 createRenderer = require('react-test-renderer/shallow').createRenderer;18 PropTypes = require('prop-types');19 React = require('react');20 });21 it('should call all of the legacy lifecycle hooks', () => {22 const logs = [];23 const logger = message => () => logs.push(message) || true;24 class SomeComponent extends React.Component {25 UNSAFE_componentWillMount = logger('componentWillMount');26 componentDidMount = logger('componentDidMount');27 UNSAFE_componentWillReceiveProps = logger('componentWillReceiveProps');28 shouldComponentUpdate = logger('shouldComponentUpdate');29 UNSAFE_componentWillUpdate = logger('componentWillUpdate');30 componentDidUpdate = logger('componentDidUpdate');31 componentWillUnmount = logger('componentWillUnmount');32 render() {33 return <div />;34 }35 }36 const shallowRenderer = createRenderer();37 shallowRenderer.render(<SomeComponent foo={1} />);38 // Calling cDU might lead to problems with host component references.39 // Since our components aren't really mounted, refs won't be available.40 expect(logs).toEqual(['componentWillMount']);41 logs.splice(0);42 const instance = shallowRenderer.getMountedInstance();43 instance.setState({});44 expect(logs).toEqual(['shouldComponentUpdate', 'componentWillUpdate']);45 logs.splice(0);46 shallowRenderer.render(<SomeComponent foo={2} />);47 // The previous shallow renderer did not trigger cDU for props changes.48 expect(logs).toEqual([49 'componentWillReceiveProps',50 'shouldComponentUpdate',51 'componentWillUpdate',52 ]);53 });54 it('should call all of the new lifecycle hooks', () => {55 const logs = [];56 const logger = message => () => logs.push(message) || true;57 class SomeComponent extends React.Component {58 state = {};59 static getDerivedStateFromProps = logger('getDerivedStateFromProps');60 componentDidMount = logger('componentDidMount');61 shouldComponentUpdate = logger('shouldComponentUpdate');62 componentDidUpdate = logger('componentDidUpdate');63 componentWillUnmount = logger('componentWillUnmount');64 render() {65 return <div />;66 }67 }68 const shallowRenderer = createRenderer();69 shallowRenderer.render(<SomeComponent foo={1} />);70 // Calling cDU might lead to problems with host component references.71 // Since our components aren't really mounted, refs won't be available.72 expect(logs).toEqual(['getDerivedStateFromProps']);73 logs.splice(0);74 const instance = shallowRenderer.getMountedInstance();75 instance.setState({});76 expect(logs).toEqual(['getDerivedStateFromProps', 'shouldComponentUpdate']);77 logs.splice(0);78 shallowRenderer.render(<SomeComponent foo={2} />);79 // The previous shallow renderer did not trigger cDU for props changes.80 expect(logs).toEqual(['getDerivedStateFromProps', 'shouldComponentUpdate']);81 });82 it('should not invoke deprecated lifecycles (cWM/cWRP/cWU) if new static gDSFP is present', () => {83 class Component extends React.Component {84 state = {};85 static getDerivedStateFromProps() {86 return null;87 }88 componentWillMount() {89 throw Error('unexpected');90 }91 componentWillReceiveProps() {92 throw Error('unexpected');93 }94 componentWillUpdate() {95 throw Error('unexpected');96 }97 render() {98 return null;99 }100 }101 const shallowRenderer = createRenderer();102 shallowRenderer.render(<Component />);103 });104 it('should not invoke deprecated lifecycles (cWM/cWRP/cWU) if new getSnapshotBeforeUpdate is present', () => {105 class Component extends React.Component {106 getSnapshotBeforeUpdate() {107 return null;108 }109 componentWillMount() {110 throw Error('unexpected');111 }112 componentWillReceiveProps() {113 throw Error('unexpected');114 }115 componentWillUpdate() {116 throw Error('unexpected');117 }118 render() {119 return null;120 }121 }122 const shallowRenderer = createRenderer();123 shallowRenderer.render(<Component value={1} />);124 shallowRenderer.render(<Component value={2} />);125 });126 it('should not call getSnapshotBeforeUpdate or componentDidUpdate when updating since refs wont exist', () => {127 class Component extends React.Component {128 getSnapshotBeforeUpdate() {129 throw Error('unexpected');130 }131 componentDidUpdate() {132 throw Error('unexpected');133 }134 render() {135 return null;136 }137 }138 const shallowRenderer = createRenderer();139 shallowRenderer.render(<Component value={1} />);140 shallowRenderer.render(<Component value={2} />);141 });142 it('should only render 1 level deep', () => {143 function Parent() {144 return (145 <div>146 <Child />147 </div>148 );149 }150 function Child() {151 throw Error('This component should not render');152 }153 const shallowRenderer = createRenderer();154 shallowRenderer.render(React.createElement(Parent));155 });156 it('should have shallow rendering', () => {157 class SomeComponent extends React.Component {158 render() {159 return (160 <div>161 <span className="child1" />162 <span className="child2" />163 </div>164 );165 }166 }167 const shallowRenderer = createRenderer();168 const result = shallowRenderer.render(<SomeComponent />);169 expect(result.type).toBe('div');170 expect(result.props.children).toEqual([171 <span className="child1" />,172 <span className="child2" />,173 ]);174 });175 it('should handle ForwardRef', () => {176 const testRef = React.createRef();177 const SomeComponent = React.forwardRef((props, ref) => {178 expect(ref).toEqual(testRef);179 return (180 <div>181 <span className="child1" />182 <span className="child2" />183 </div>184 );185 });186 const shallowRenderer = createRenderer();187 const result = shallowRenderer.render(<SomeComponent ref={testRef} />);188 expect(result.type).toBe('div');189 expect(result.props.children).toEqual([190 <span className="child1" />,191 <span className="child2" />,192 ]);193 });194 it('should handle Profiler', () => {195 class SomeComponent extends React.Component {196 render() {197 return (198 <React.Profiler id="test" onRender={jest.fn()}>199 <div>200 <span className="child1" />201 <span className="child2" />202 </div>203 </React.Profiler>204 );205 }206 }207 const shallowRenderer = createRenderer();208 const result = shallowRenderer.render(<SomeComponent />);209 expect(result.type).toBe(React.Profiler);210 expect(result.props.children).toEqual(211 <div>212 <span className="child1" />213 <span className="child2" />214 </div>,215 );216 });217 it('should enable shouldComponentUpdate to prevent a re-render', () => {218 let renderCounter = 0;219 class SimpleComponent extends React.Component {220 state = {update: false};221 shouldComponentUpdate(nextProps, nextState) {222 return this.state.update !== nextState.update;223 }224 render() {225 renderCounter++;226 return <div>{`${renderCounter}`}</div>;227 }228 }229 const shallowRenderer = createRenderer();230 shallowRenderer.render(<SimpleComponent />);231 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);232 const instance = shallowRenderer.getMountedInstance();233 instance.setState({update: false});234 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);235 instance.setState({update: true});236 expect(shallowRenderer.getRenderOutput()).toEqual(<div>2</div>);237 });238 it('should enable PureComponent to prevent a re-render', () => {239 let renderCounter = 0;240 class SimpleComponent extends React.PureComponent {241 state = {update: false};242 render() {243 renderCounter++;244 return <div>{`${renderCounter}`}</div>;245 }246 }247 const shallowRenderer = createRenderer();248 shallowRenderer.render(<SimpleComponent />);249 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);250 const instance = shallowRenderer.getMountedInstance();251 instance.setState({update: false});252 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);253 instance.setState({update: true});254 expect(shallowRenderer.getRenderOutput()).toEqual(<div>2</div>);255 });256 it('should not run shouldComponentUpdate during forced update', () => {257 let scuCounter = 0;258 class SimpleComponent extends React.Component {259 state = {count: 1};260 shouldComponentUpdate() {261 scuCounter++;262 return false;263 }264 render() {265 return <div>{`${this.state.count}`}</div>;266 }267 }268 const shallowRenderer = createRenderer();269 shallowRenderer.render(<SimpleComponent />);270 expect(scuCounter).toEqual(0);271 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);272 // Force update the initial state. sCU should not fire.273 const instance = shallowRenderer.getMountedInstance();274 instance.forceUpdate();275 expect(scuCounter).toEqual(0);276 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);277 // Setting state updates the instance, but doesn't re-render278 // because sCU returned false.279 instance.setState(state => ({count: state.count + 1}));280 expect(scuCounter).toEqual(1);281 expect(instance.state.count).toEqual(2);282 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);283 // A force update updates the render output, but doesn't call sCU.284 instance.forceUpdate();285 expect(scuCounter).toEqual(1);286 expect(instance.state.count).toEqual(2);287 expect(shallowRenderer.getRenderOutput()).toEqual(<div>2</div>);288 });289 it('should rerender when calling forceUpdate', () => {290 let renderCounter = 0;291 class SimpleComponent extends React.Component {292 render() {293 renderCounter += 1;294 return <div />;295 }296 }297 const shallowRenderer = createRenderer();298 shallowRenderer.render(<SimpleComponent />);299 expect(renderCounter).toEqual(1);300 const instance = shallowRenderer.getMountedInstance();301 instance.forceUpdate();302 expect(renderCounter).toEqual(2);303 });304 it('should shallow render a function component', () => {305 function SomeComponent(props, context) {306 return (307 <div>308 <div>{props.foo}</div>309 <div>{context.bar}</div>310 <span className="child1" />311 <span className="child2" />312 </div>313 );314 }315 SomeComponent.contextTypes = {316 bar: PropTypes.string,317 };318 const shallowRenderer = createRenderer();319 const result = shallowRenderer.render(<SomeComponent foo={'FOO'} />, {320 bar: 'BAR',321 });322 expect(result.type).toBe('div');323 expect(result.props.children).toEqual([324 <div>FOO</div>,325 <div>BAR</div>,326 <span className="child1" />,327 <span className="child2" />,328 ]);329 });330 it('should shallow render a component returning strings directly from render', () => {331 const Text = ({value}) => value;332 const shallowRenderer = createRenderer();333 const result = shallowRenderer.render(<Text value="foo" />);334 expect(result).toEqual('foo');335 });336 it('should shallow render a component returning numbers directly from render', () => {337 const Text = ({value}) => value;338 const shallowRenderer = createRenderer();339 const result = shallowRenderer.render(<Text value={10} />);340 expect(result).toEqual(10);341 });342 it('should shallow render a fragment', () => {343 class SomeComponent extends React.Component {344 render() {345 return <div />;346 }347 }348 class Fragment extends React.Component {349 render() {350 return [<div key="a" />, <span key="b" />, <SomeComponent />];351 }352 }353 const shallowRenderer = createRenderer();354 const result = shallowRenderer.render(<Fragment />);355 expect(result).toEqual([356 <div key="a" />,357 <span key="b" />,358 <SomeComponent />,359 ]);360 });361 it('should shallow render a React.fragment', () => {362 class SomeComponent extends React.Component {363 render() {364 return <div />;365 }366 }367 class Fragment extends React.Component {368 render() {369 return (370 <React.Fragment>371 <div />372 <span />373 <SomeComponent />374 </React.Fragment>375 );376 }377 }378 const shallowRenderer = createRenderer();379 const result = shallowRenderer.render(<Fragment />);380 expect(result).toEqual(381 <React.Fragment>382 <div />383 <span />384 <SomeComponent />385 </React.Fragment>,386 );387 });388 it('should throw for invalid elements', () => {389 class SomeComponent extends React.Component {390 render() {391 return <div />;392 }393 }394 const shallowRenderer = createRenderer();395 expect(() => shallowRenderer.render(SomeComponent)).toThrowError(396 'ReactShallowRenderer render(): Invalid component element. Instead of ' +397 'passing a component class, make sure to instantiate it by passing it ' +398 'to React.createElement.',399 );400 expect(() => shallowRenderer.render(<div />)).toThrowError(401 'ReactShallowRenderer render(): Shallow rendering works only with ' +402 'custom components, not primitives (div). Instead of calling ' +403 '`.render(el)` and inspecting the rendered output, look at `el.props` ' +404 'directly instead.',405 );406 });407 it('should have shallow unmounting', () => {408 const componentWillUnmount = jest.fn();409 class SomeComponent extends React.Component {410 componentWillUnmount = componentWillUnmount;411 render() {412 return <div />;413 }414 }415 const shallowRenderer = createRenderer();416 shallowRenderer.render(<SomeComponent />);417 shallowRenderer.unmount();418 expect(componentWillUnmount).toBeCalled();419 });420 it('can shallow render to null', () => {421 class SomeComponent extends React.Component {422 render() {423 return null;424 }425 }426 const shallowRenderer = createRenderer();427 const result = shallowRenderer.render(<SomeComponent />);428 expect(result).toBe(null);429 });430 it('can shallow render with a ref', () => {431 class SomeComponent extends React.Component {432 render() {433 return <div ref="hello" />;434 }435 }436 const shallowRenderer = createRenderer();437 // Shouldn't crash.438 shallowRenderer.render(<SomeComponent />);439 });440 it('lets you update shallowly rendered components', () => {441 class SomeComponent extends React.Component {442 state = {clicked: false};443 onClick = () => {444 this.setState({clicked: true});445 };446 render() {447 const className = this.state.clicked ? 'was-clicked' : '';448 if (this.props.aNew === 'prop') {449 return (450 <a href="#" onClick={this.onClick} className={className}>451 Test link452 </a>453 );454 } else {455 return (456 <div>457 <span className="child1" />458 <span className="child2" />459 </div>460 );461 }462 }463 }464 const shallowRenderer = createRenderer();465 const result = shallowRenderer.render(<SomeComponent />);466 expect(result.type).toBe('div');467 expect(result.props.children).toEqual([468 <span className="child1" />,469 <span className="child2" />,470 ]);471 const updatedResult = shallowRenderer.render(<SomeComponent aNew="prop" />);472 expect(updatedResult.type).toBe('a');473 const mockEvent = {};474 updatedResult.props.onClick(mockEvent);475 const updatedResultCausedByClick = shallowRenderer.getRenderOutput();476 expect(updatedResultCausedByClick.type).toBe('a');477 expect(updatedResultCausedByClick.props.className).toBe('was-clicked');478 });479 it('can access the mounted component instance', () => {480 class SimpleComponent extends React.Component {481 someMethod = () => {482 return this.props.n;483 };484 render() {485 return <div>{this.props.n}</div>;486 }487 }488 const shallowRenderer = createRenderer();489 shallowRenderer.render(<SimpleComponent n={5} />);490 expect(shallowRenderer.getMountedInstance().someMethod()).toEqual(5);491 });492 it('can shallowly render components with contextTypes', () => {493 class SimpleComponent extends React.Component {494 static contextTypes = {495 name: PropTypes.string,496 };497 render() {498 return <div />;499 }500 }501 const shallowRenderer = createRenderer();502 const result = shallowRenderer.render(<SimpleComponent />);503 expect(result).toEqual(<div />);504 });505 it('passes expected params to legacy component lifecycle methods', () => {506 const componentDidUpdateParams = [];507 const componentWillReceivePropsParams = [];508 const componentWillUpdateParams = [];509 const setStateParams = [];510 const shouldComponentUpdateParams = [];511 const initialProp = {prop: 'init prop'};512 const initialState = {state: 'init state'};513 const initialContext = {context: 'init context'};514 const updatedState = {state: 'updated state'};515 const updatedProp = {prop: 'updated prop'};516 const updatedContext = {context: 'updated context'};517 class SimpleComponent extends React.Component {518 constructor(props, context) {519 super(props, context);520 this.state = initialState;521 }522 static contextTypes = {523 context: PropTypes.string,524 };525 componentDidUpdate(...args) {526 componentDidUpdateParams.push(...args);527 }528 UNSAFE_componentWillReceiveProps(...args) {529 componentWillReceivePropsParams.push(...args);530 this.setState((...innerArgs) => {531 setStateParams.push(...innerArgs);532 return updatedState;533 });534 }535 UNSAFE_componentWillUpdate(...args) {536 componentWillUpdateParams.push(...args);537 }538 shouldComponentUpdate(...args) {539 shouldComponentUpdateParams.push(...args);540 return true;541 }542 render() {543 return null;544 }545 }546 const shallowRenderer = createRenderer();547 shallowRenderer.render(548 React.createElement(SimpleComponent, initialProp),549 initialContext,550 );551 expect(componentDidUpdateParams).toEqual([]);552 expect(componentWillReceivePropsParams).toEqual([]);553 expect(componentWillUpdateParams).toEqual([]);554 expect(setStateParams).toEqual([]);555 expect(shouldComponentUpdateParams).toEqual([]);556 // Lifecycle hooks should be invoked with the correct prev/next params on update.557 shallowRenderer.render(558 React.createElement(SimpleComponent, updatedProp),559 updatedContext,560 );561 expect(componentWillReceivePropsParams).toEqual([562 updatedProp,563 updatedContext,564 ]);565 expect(setStateParams).toEqual([initialState, initialProp]);566 expect(shouldComponentUpdateParams).toEqual([567 updatedProp,568 updatedState,569 updatedContext,570 ]);571 expect(componentWillUpdateParams).toEqual([572 updatedProp,573 updatedState,574 updatedContext,575 ]);576 expect(componentDidUpdateParams).toEqual([]);577 });578 it('passes expected params to new component lifecycle methods', () => {579 const componentDidUpdateParams = [];580 const getDerivedStateFromPropsParams = [];581 const shouldComponentUpdateParams = [];582 const initialProp = {prop: 'init prop'};583 const initialState = {state: 'init state'};584 const initialContext = {context: 'init context'};585 const updatedProp = {prop: 'updated prop'};586 const updatedContext = {context: 'updated context'};587 class SimpleComponent extends React.Component {588 constructor(props, context) {589 super(props, context);590 this.state = initialState;591 }592 static contextTypes = {593 context: PropTypes.string,594 };595 componentDidUpdate(...args) {596 componentDidUpdateParams.push(...args);597 }598 static getDerivedStateFromProps(...args) {599 getDerivedStateFromPropsParams.push(args);600 return null;601 }602 shouldComponentUpdate(...args) {603 shouldComponentUpdateParams.push(...args);604 return true;605 }606 render() {607 return null;608 }609 }610 const shallowRenderer = createRenderer();611 // The only lifecycle hook that should be invoked on initial render612 // Is the static getDerivedStateFromProps() methods613 shallowRenderer.render(614 React.createElement(SimpleComponent, initialProp),615 initialContext,616 );617 expect(getDerivedStateFromPropsParams).toEqual([618 [initialProp, initialState],619 ]);620 expect(componentDidUpdateParams).toEqual([]);621 expect(shouldComponentUpdateParams).toEqual([]);622 // Lifecycle hooks should be invoked with the correct prev/next params on update.623 shallowRenderer.render(624 React.createElement(SimpleComponent, updatedProp),625 updatedContext,626 );627 expect(getDerivedStateFromPropsParams).toEqual([628 [initialProp, initialState],629 [updatedProp, initialState],630 ]);631 expect(shouldComponentUpdateParams).toEqual([632 updatedProp,633 initialState,634 updatedContext,635 ]);636 expect(componentDidUpdateParams).toEqual([]);637 });638 it('can shallowly render components with ref as function', () => {639 class SimpleComponent extends React.Component {640 state = {clicked: false};641 handleUserClick = () => {642 this.setState({clicked: true});643 };644 render() {645 return (646 <div647 ref={() => {}}648 onClick={this.handleUserClick}649 className={this.state.clicked ? 'clicked' : ''}650 />651 );652 }653 }654 const shallowRenderer = createRenderer();655 shallowRenderer.render(<SimpleComponent />);656 let result = shallowRenderer.getRenderOutput();657 expect(result.type).toEqual('div');658 expect(result.props.className).toEqual('');659 result.props.onClick();660 result = shallowRenderer.getRenderOutput();661 expect(result.type).toEqual('div');662 expect(result.props.className).toEqual('clicked');663 });664 it('can initialize state via static getDerivedStateFromProps', () => {665 class SimpleComponent extends React.Component {666 state = {667 count: 1,668 };669 static getDerivedStateFromProps(props, prevState) {670 return {671 count: prevState.count + props.incrementBy,672 other: 'foobar',673 };674 }675 render() {676 return (677 <div>{`count:${this.state.count}, other:${this.state.other}`}</div>678 );679 }680 }681 const shallowRenderer = createRenderer();682 const result = shallowRenderer.render(<SimpleComponent incrementBy={2} />);683 expect(result).toEqual(<div>count:3, other:foobar</div>);684 });685 it('can setState in componentWillMount when shallow rendering', () => {686 class SimpleComponent extends React.Component {687 UNSAFE_componentWillMount() {688 this.setState({groovy: 'doovy'});689 }690 render() {691 return <div>{this.state.groovy}</div>;692 }693 }694 const shallowRenderer = createRenderer();695 const result = shallowRenderer.render(<SimpleComponent />);696 expect(result).toEqual(<div>doovy</div>);697 });698 it('can setState in componentWillMount repeatedly when shallow rendering', () => {699 class SimpleComponent extends React.Component {700 state = {701 separator: '-',702 };703 UNSAFE_componentWillMount() {704 this.setState({groovy: 'doovy'});705 this.setState({doovy: 'groovy'});706 }707 render() {708 const {groovy, doovy, separator} = this.state;709 return <div>{`${groovy}${separator}${doovy}`}</div>;710 }711 }712 const shallowRenderer = createRenderer();713 const result = shallowRenderer.render(<SimpleComponent />);714 expect(result).toEqual(<div>doovy-groovy</div>);715 });716 it('can setState in componentWillMount with an updater function repeatedly when shallow rendering', () => {717 class SimpleComponent extends React.Component {718 state = {719 separator: '-',720 };721 UNSAFE_componentWillMount() {722 this.setState(state => ({groovy: 'doovy'}));723 this.setState(state => ({doovy: state.groovy}));724 }725 render() {726 const {groovy, doovy, separator} = this.state;727 return <div>{`${groovy}${separator}${doovy}`}</div>;728 }729 }730 const shallowRenderer = createRenderer();731 const result = shallowRenderer.render(<SimpleComponent />);732 expect(result).toEqual(<div>doovy-doovy</div>);733 });734 it('can setState in componentWillReceiveProps when shallow rendering', () => {735 class SimpleComponent extends React.Component {736 state = {count: 0};737 UNSAFE_componentWillReceiveProps(nextProps) {738 if (nextProps.updateState) {739 this.setState({count: 1});740 }741 }742 render() {743 return <div>{this.state.count}</div>;744 }745 }746 const shallowRenderer = createRenderer();747 let result = shallowRenderer.render(748 <SimpleComponent updateState={false} />,749 );750 expect(result.props.children).toEqual(0);751 result = shallowRenderer.render(<SimpleComponent updateState={true} />);752 expect(result.props.children).toEqual(1);753 });754 it('can update state with static getDerivedStateFromProps when shallow rendering', () => {755 class SimpleComponent extends React.Component {756 state = {count: 1};757 static getDerivedStateFromProps(nextProps, prevState) {758 if (nextProps.updateState) {759 return {count: nextProps.incrementBy + prevState.count};760 }761 return null;762 }763 render() {764 return <div>{this.state.count}</div>;765 }766 }767 const shallowRenderer = createRenderer();768 let result = shallowRenderer.render(769 <SimpleComponent updateState={false} incrementBy={0} />,770 );771 expect(result.props.children).toEqual(1);772 result = shallowRenderer.render(773 <SimpleComponent updateState={true} incrementBy={2} />,774 );775 expect(result.props.children).toEqual(3);776 result = shallowRenderer.render(777 <SimpleComponent updateState={false} incrementBy={2} />,778 );779 expect(result.props.children).toEqual(3);780 });781 it('should not override state with stale values if prevState is spread within getDerivedStateFromProps', () => {782 class SimpleComponent extends React.Component {783 state = {value: 0};784 static getDerivedStateFromProps(nextProps, prevState) {785 return {...prevState};786 }787 updateState = () => {788 this.setState(state => ({value: state.value + 1}));789 };790 render() {791 return <div>{`value:${this.state.value}`}</div>;792 }793 }794 const shallowRenderer = createRenderer();795 let result = shallowRenderer.render(<SimpleComponent />);796 expect(result).toEqual(<div>value:0</div>);797 let instance = shallowRenderer.getMountedInstance();798 instance.updateState();799 result = shallowRenderer.getRenderOutput();800 expect(result).toEqual(<div>value:1</div>);801 });802 it('should pass previous state to shouldComponentUpdate even with getDerivedStateFromProps', () => {803 class SimpleComponent extends React.Component {804 constructor(props) {805 super(props);806 this.state = {807 value: props.value,808 };809 }810 static getDerivedStateFromProps(nextProps, prevState) {811 if (nextProps.value === prevState.value) {812 return null;813 }814 return {value: nextProps.value};815 }816 shouldComponentUpdate(nextProps, nextState) {817 return nextState.value !== this.state.value;818 }819 render() {820 return <div>{`value:${this.state.value}`}</div>;821 }822 }823 const shallowRenderer = createRenderer();824 const initialResult = shallowRenderer.render(825 <SimpleComponent value="initial" />,826 );827 expect(initialResult).toEqual(<div>value:initial</div>);828 const updatedResult = shallowRenderer.render(829 <SimpleComponent value="updated" />,830 );831 expect(updatedResult).toEqual(<div>value:updated</div>);832 });833 it('can setState with an updater function', () => {834 let instance;835 class SimpleComponent extends React.Component {836 state = {837 counter: 0,838 };839 render() {840 instance = this;841 return (842 <button ref="button" onClick={this.onClick}>843 {this.state.counter}844 </button>845 );846 }847 }848 const shallowRenderer = createRenderer();849 let result = shallowRenderer.render(<SimpleComponent defaultCount={1} />);850 expect(result.props.children).toEqual(0);851 instance.setState((state, props) => {852 return {counter: props.defaultCount + 1};853 });854 result = shallowRenderer.getRenderOutput();855 expect(result.props.children).toEqual(2);856 });857 it('can access component instance from setState updater function', done => {858 let instance;859 class SimpleComponent extends React.Component {860 state = {};861 render() {862 instance = this;863 return null;864 }865 }866 const shallowRenderer = createRenderer();867 shallowRenderer.render(<SimpleComponent />);868 instance.setState(function updater(state, props) {869 expect(this).toBe(instance);870 done();871 });872 });873 it('can setState with a callback', () => {874 let instance;875 class SimpleComponent extends React.Component {876 state = {877 counter: 0,878 };879 render() {880 instance = this;881 return <p>{this.state.counter}</p>;882 }883 }884 const shallowRenderer = createRenderer();885 const result = shallowRenderer.render(<SimpleComponent />);886 expect(result.props.children).toBe(0);887 const callback = jest.fn(function() {888 expect(this).toBe(instance);889 });890 instance.setState({counter: 1}, callback);891 const updated = shallowRenderer.getRenderOutput();892 expect(updated.props.children).toBe(1);893 expect(callback).toHaveBeenCalled();894 });895 it('can replaceState with a callback', () => {896 let instance;897 class SimpleComponent extends React.Component {898 state = {899 counter: 0,900 };901 render() {902 instance = this;903 return <p>{this.state.counter}</p>;904 }905 }906 const shallowRenderer = createRenderer();907 const result = shallowRenderer.render(<SimpleComponent />);908 expect(result.props.children).toBe(0);909 const callback = jest.fn(function() {910 expect(this).toBe(instance);911 });912 // No longer a public API, but we can test that it works internally by913 // reaching into the updater.914 shallowRenderer._updater.enqueueReplaceState(915 instance,916 {counter: 1},917 callback,918 );919 const updated = shallowRenderer.getRenderOutput();920 expect(updated.props.children).toBe(1);921 expect(callback).toHaveBeenCalled();922 });923 it('can forceUpdate with a callback', () => {924 let instance;925 class SimpleComponent extends React.Component {926 state = {927 counter: 0,928 };929 render() {930 instance = this;931 return <p>{this.state.counter}</p>;932 }933 }934 const shallowRenderer = createRenderer();935 const result = shallowRenderer.render(<SimpleComponent />);936 expect(result.props.children).toBe(0);937 const callback = jest.fn(function() {938 expect(this).toBe(instance);939 });940 instance.forceUpdate(callback);941 const updated = shallowRenderer.getRenderOutput();942 expect(updated.props.children).toBe(0);943 expect(callback).toHaveBeenCalled();944 });945 it('can pass context when shallowly rendering', () => {946 class SimpleComponent extends React.Component {947 static contextTypes = {948 name: PropTypes.string,949 };950 render() {951 return <div>{this.context.name}</div>;952 }953 }954 const shallowRenderer = createRenderer();955 const result = shallowRenderer.render(<SimpleComponent />, {956 name: 'foo',957 });958 expect(result).toEqual(<div>foo</div>);959 });960 it('should track context across updates', () => {961 class SimpleComponent extends React.Component {962 static contextTypes = {963 foo: PropTypes.string,964 };965 state = {966 bar: 'bar',967 };968 render() {969 return <div>{`${this.context.foo}:${this.state.bar}`}</div>;970 }971 }972 const shallowRenderer = createRenderer();973 let result = shallowRenderer.render(<SimpleComponent />, {974 foo: 'foo',975 });976 expect(result).toEqual(<div>foo:bar</div>);977 const instance = shallowRenderer.getMountedInstance();978 instance.setState({bar: 'baz'});979 result = shallowRenderer.getRenderOutput();980 expect(result).toEqual(<div>foo:baz</div>);981 });982 it('should filter context by contextTypes', () => {983 class SimpleComponent extends React.Component {984 static contextTypes = {985 foo: PropTypes.string,986 };987 render() {988 return <div>{`${this.context.foo}:${this.context.bar}`}</div>;989 }990 }991 const shallowRenderer = createRenderer();992 let result = shallowRenderer.render(<SimpleComponent />, {993 foo: 'foo',994 bar: 'bar',995 });996 expect(result).toEqual(<div>foo:undefined</div>);997 });998 it('can fail context when shallowly rendering', () => {999 class SimpleComponent extends React.Component {1000 static contextTypes = {1001 name: PropTypes.string.isRequired,1002 };1003 render() {1004 return <div>{this.context.name}</div>;1005 }1006 }1007 const shallowRenderer = createRenderer();1008 expect(() => shallowRenderer.render(<SimpleComponent />)).toWarnDev(1009 'Warning: Failed context type: The context `name` is marked as ' +1010 'required in `SimpleComponent`, but its value is `undefined`.\n' +1011 ' in SimpleComponent (at **)',1012 );1013 });1014 it('should warn about propTypes (but only once)', () => {1015 class SimpleComponent extends React.Component {1016 render() {1017 return React.createElement('div', null, this.props.name);1018 }1019 }1020 SimpleComponent.propTypes = {1021 name: PropTypes.string.isRequired,1022 };1023 const shallowRenderer = createRenderer();1024 expect(() =>1025 shallowRenderer.render(React.createElement(SimpleComponent, {name: 123})),1026 ).toWarnDev(1027 'Warning: Failed prop type: Invalid prop `name` of type `number` ' +1028 'supplied to `SimpleComponent`, expected `string`.\n' +1029 ' in SimpleComponent',1030 );1031 });1032 it('should enable rendering of cloned element', () => {1033 class SimpleComponent extends React.Component {1034 constructor(props) {1035 super(props);1036 this.state = {1037 bar: 'bar',1038 };1039 }1040 render() {1041 return <div>{`${this.props.foo}:${this.state.bar}`}</div>;1042 }1043 }1044 const shallowRenderer = createRenderer();1045 const el = <SimpleComponent foo="foo" />;1046 let result = shallowRenderer.render(el);1047 expect(result).toEqual(<div>foo:bar</div>);1048 const cloned = React.cloneElement(el, {foo: 'baz'});1049 result = shallowRenderer.render(cloned);1050 expect(result).toEqual(<div>baz:bar</div>);1051 });1052 it('this.state should be updated on setState callback inside componentWillMount', () => {1053 let stateSuccessfullyUpdated = false;1054 class Component extends React.Component {1055 constructor(props, context) {1056 super(props, context);1057 this.state = {1058 hasUpdatedState: false,1059 };1060 }1061 UNSAFE_componentWillMount() {1062 this.setState(1063 {hasUpdatedState: true},1064 () => (stateSuccessfullyUpdated = this.state.hasUpdatedState),1065 );1066 }1067 render() {1068 return <div>{this.props.children}</div>;1069 }1070 }1071 const shallowRenderer = createRenderer();1072 shallowRenderer.render(<Component />);1073 expect(stateSuccessfullyUpdated).toBe(true);1074 });1075 it('should handle multiple callbacks', () => {1076 const mockFn = jest.fn();1077 const shallowRenderer = createRenderer();1078 class Component extends React.Component {1079 constructor(props, context) {1080 super(props, context);1081 this.state = {1082 foo: 'foo',1083 };1084 }1085 UNSAFE_componentWillMount() {1086 this.setState({foo: 'bar'}, () => mockFn());1087 this.setState({foo: 'foobar'}, () => mockFn());1088 }1089 render() {1090 return <div>{this.state.foo}</div>;1091 }1092 }1093 shallowRenderer.render(<Component />);1094 expect(mockFn).toHaveBeenCalledTimes(2);1095 // Ensure the callback queue is cleared after the callbacks are invoked1096 const mountedInstance = shallowRenderer.getMountedInstance();1097 mountedInstance.setState({foo: 'bar'}, () => mockFn());1098 expect(mockFn).toHaveBeenCalledTimes(3);1099 });1100 it('should call the setState callback even if shouldComponentUpdate = false', done => {1101 const mockFn = jest.fn().mockReturnValue(false);1102 class Component extends React.Component {1103 constructor(props, context) {1104 super(props, context);1105 this.state = {1106 hasUpdatedState: false,1107 };1108 }1109 shouldComponentUpdate() {1110 return mockFn();1111 }1112 render() {1113 return <div>{this.state.hasUpdatedState}</div>;1114 }1115 }1116 const shallowRenderer = createRenderer();1117 shallowRenderer.render(<Component />);1118 const mountedInstance = shallowRenderer.getMountedInstance();1119 mountedInstance.setState({hasUpdatedState: true}, () => {1120 expect(mockFn).toBeCalled();1121 expect(mountedInstance.state.hasUpdatedState).toBe(true);1122 done();1123 });1124 });1125 it('throws usefully when rendering badly-typed elements', () => {1126 const shallowRenderer = createRenderer();1127 const renderAndVerifyWarningAndError = (Component, typeString) => {1128 expect(() => {1129 expect(() => shallowRenderer.render(<Component />)).toWarnDev(1130 'React.createElement: type is invalid -- expected a string ' +1131 '(for built-in components) or a class/function (for composite components) ' +1132 `but got: ${typeString}.`,1133 );1134 }).toThrowError(1135 'ReactShallowRenderer render(): Shallow rendering works only with custom ' +1136 `components, but the provided element type was \`${typeString}\`.`,1137 );1138 };1139 renderAndVerifyWarningAndError(undefined, 'undefined');1140 renderAndVerifyWarningAndError(null, 'null');1141 renderAndVerifyWarningAndError([], 'array');1142 renderAndVerifyWarningAndError({}, 'object');1143 });1144 it('should have initial state of null if not defined', () => {1145 class SomeComponent extends React.Component {1146 render() {1147 return <span />;1148 }1149 }1150 const shallowRenderer = createRenderer();1151 shallowRenderer.render(<SomeComponent />);1152 expect(shallowRenderer.getMountedInstance().state).toBeNull();1153 });1154 it('should invoke both deprecated and new lifecycles if both are present', () => {1155 const log = [];1156 class Component extends React.Component {1157 componentWillMount() {1158 log.push('componentWillMount');1159 }1160 componentWillReceiveProps() {1161 log.push('componentWillReceiveProps');1162 }1163 componentWillUpdate() {1164 log.push('componentWillUpdate');1165 }1166 UNSAFE_componentWillMount() {1167 log.push('UNSAFE_componentWillMount');1168 }1169 UNSAFE_componentWillReceiveProps() {1170 log.push('UNSAFE_componentWillReceiveProps');1171 }1172 UNSAFE_componentWillUpdate() {1173 log.push('UNSAFE_componentWillUpdate');1174 }1175 render() {1176 return null;1177 }1178 }1179 const shallowRenderer = createRenderer();1180 shallowRenderer.render(<Component foo="bar" />);1181 expect(log).toEqual(['componentWillMount', 'UNSAFE_componentWillMount']);1182 log.length = 0;1183 shallowRenderer.render(<Component foo="baz" />);1184 expect(log).toEqual([1185 'componentWillReceiveProps',1186 'UNSAFE_componentWillReceiveProps',1187 'componentWillUpdate',1188 'UNSAFE_componentWillUpdate',1189 ]);1190 });1191 it('should stop the update when setState returns null or undefined', () => {1192 const log = [];1193 let instance;1194 class Component extends React.Component {1195 constructor(props) {1196 super(props);1197 this.state = {1198 count: 0,1199 };1200 }1201 render() {1202 log.push('render');1203 instance = this;1204 return null;1205 }1206 }1207 const shallowRenderer = createRenderer();1208 shallowRenderer.render(<Component />);1209 log.length = 0;1210 instance.setState(() => null);1211 instance.setState(() => undefined);1212 instance.setState(null);1213 instance.setState(undefined);1214 expect(log).toEqual([]);1215 instance.setState(state => ({count: state.count + 1}));1216 expect(log).toEqual(['render']);1217 });1218 it('should not get this in a function component', () => {1219 const logs = [];1220 function Foo() {1221 logs.push(this);1222 return <div>foo</div>;1223 }1224 const shallowRenderer = createRenderer();1225 shallowRenderer.render(<Foo foo="bar" />);1226 expect(logs).toEqual([undefined]);1227 });1228 it('should handle memo', () => {1229 function Foo() {1230 return <div>foo</div>;1231 }1232 const MemoFoo = React.memo(Foo);1233 const shallowRenderer = createRenderer();1234 shallowRenderer.render(<MemoFoo />);1235 });1236 it('should enable React.memo to prevent a re-render', () => {1237 const logs = [];1238 const Foo = React.memo(({count}) => {1239 logs.push(`Foo: ${count}`);1240 return <div>{count}</div>;1241 });1242 const Bar = React.memo(({count}) => {1243 logs.push(`Bar: ${count}`);1244 return <div>{count}</div>;1245 });1246 const shallowRenderer = createRenderer();1247 shallowRenderer.render(<Foo count={1} />);1248 expect(logs).toEqual(['Foo: 1']);1249 logs.length = 0;1250 // Rendering the same element with the same props should be prevented1251 shallowRenderer.render(<Foo count={1} />);1252 expect(logs).toEqual([]);1253 // A different element with the same props should cause a re-render1254 shallowRenderer.render(<Bar count={1} />);1255 expect(logs).toEqual(['Bar: 1']);1256 });1257 it('should respect a custom comparison function with React.memo', () => {1258 let renderCount = 0;1259 function areEqual(props, nextProps) {1260 return props.foo === nextProps.foo;1261 }1262 const Foo = React.memo(({foo, bar}) => {1263 renderCount++;1264 return (1265 <div>1266 {foo} {bar}1267 </div>1268 );1269 }, areEqual);1270 const shallowRenderer = createRenderer();1271 shallowRenderer.render(<Foo foo={1} bar={1} />);1272 expect(renderCount).toBe(1);1273 // Change a prop that the comparison funciton ignores1274 shallowRenderer.render(<Foo foo={1} bar={2} />);1275 expect(renderCount).toBe(1);1276 shallowRenderer.render(<Foo foo={2} bar={2} />);1277 expect(renderCount).toBe(2);1278 });1279 it('should not call the comparison function with React.memo on the initial render', () => {1280 const areEqual = jest.fn(() => false);1281 const SomeComponent = React.memo(({foo}) => {1282 return <div>{foo}</div>;1283 }, areEqual);1284 const shallowRenderer = createRenderer();1285 shallowRenderer.render(<SomeComponent foo={1} />);1286 expect(areEqual).not.toHaveBeenCalled();1287 expect(shallowRenderer.getRenderOutput()).toEqual(<div>{1}</div>);1288 });1289 it('should handle memo(forwardRef())', () => {1290 const testRef = React.createRef();1291 const SomeComponent = React.forwardRef((props, ref) => {1292 expect(ref).toEqual(testRef);1293 return (1294 <div>1295 <span className="child1" />1296 <span className="child2" />1297 </div>1298 );1299 });1300 const SomeMemoComponent = React.memo(SomeComponent);1301 const shallowRenderer = createRenderer();1302 const result = shallowRenderer.render(<SomeMemoComponent ref={testRef} />);1303 expect(result.type).toBe('div');1304 expect(result.props.children).toEqual([1305 <span className="child1" />,1306 <span className="child2" />,1307 ]);1308 });1309 it('should warn for forwardRef(memo())', () => {1310 const testRef = React.createRef();1311 const SomeMemoComponent = React.memo(({foo}) => {1312 return <div>{foo}</div>;1313 });1314 const shallowRenderer = createRenderer();1315 expect(() => {1316 expect(() => {1317 const SomeComponent = React.forwardRef(SomeMemoComponent);1318 shallowRenderer.render(<SomeComponent ref={testRef} />);1319 }).toWarnDev(1320 'Warning: forwardRef requires a render function but received ' +1321 'a `memo` component. Instead of forwardRef(memo(...)), use ' +1322 'memo(forwardRef(...))',1323 {withoutStack: true},1324 );1325 }).toThrowError(1326 'forwardRef requires a render function but was given object.',1327 );1328 });1329 it('should let you change type', () => {1330 function Foo({prop}) {1331 return <div>Foo {prop}</div>;1332 }1333 function Bar({prop}) {1334 return <div>Bar {prop}</div>;1335 }1336 const shallowRenderer = createRenderer();1337 shallowRenderer.render(<Foo prop="foo1" />);1338 expect(shallowRenderer.getRenderOutput()).toEqual(<div>Foo {'foo1'}</div>);1339 shallowRenderer.render(<Foo prop="foo2" />);1340 expect(shallowRenderer.getRenderOutput()).toEqual(<div>Foo {'foo2'}</div>);1341 shallowRenderer.render(<Bar prop="bar1" />);1342 expect(shallowRenderer.getRenderOutput()).toEqual(<div>Bar {'bar1'}</div>);1343 shallowRenderer.render(<Bar prop="bar2" />);1344 expect(shallowRenderer.getRenderOutput()).toEqual(<div>Bar {'bar2'}</div>);1345 });1346 it('should let you change class type', () => {1347 class Foo extends React.Component {1348 render() {1349 return <div>Foo {this.props.prop}</div>;1350 }1351 }1352 class Bar extends React.Component {1353 render() {1354 return <div>Bar {this.props.prop}</div>;1355 }1356 }1357 const shallowRenderer = createRenderer();1358 shallowRenderer.render(<Foo prop="foo1" />);1359 expect(shallowRenderer.getRenderOutput()).toEqual(<div>Foo {'foo1'}</div>);1360 shallowRenderer.render(<Foo prop="foo2" />);1361 expect(shallowRenderer.getRenderOutput()).toEqual(<div>Foo {'foo2'}</div>);1362 shallowRenderer.render(<Bar prop="bar1" />);1363 expect(shallowRenderer.getRenderOutput()).toEqual(<div>Bar {'bar1'}</div>);1364 shallowRenderer.render(<Bar prop="bar2" />);1365 expect(shallowRenderer.getRenderOutput()).toEqual(<div>Bar {'bar2'}</div>);1366 });...

Full Screen

Full Screen

ReactShallowRendererMemo-test.js

Source:ReactShallowRendererMemo-test.js Github

copy

Full Screen

1/**2 * Copyright (c) Facebook, Inc. and its affiliates.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 *7 * @emails react-core8 * @jest-environment node9 */10'use strict';11let createRenderer;12let PropTypes;13let React;14describe('ReactShallowRendererMemo', () => {15 beforeEach(() => {16 jest.resetModules();17 createRenderer = require('react-test-renderer/shallow').createRenderer;18 PropTypes = require('prop-types');19 React = require('react');20 });21 it('should call all of the legacy lifecycle hooks', () => {22 const logs = [];23 const logger = message => () => logs.push(message) || true;24 const SomeComponent = React.memo(25 class SomeComponent extends React.Component {26 UNSAFE_componentWillMount = logger('componentWillMount');27 componentDidMount = logger('componentDidMount');28 UNSAFE_componentWillReceiveProps = logger('componentWillReceiveProps');29 shouldComponentUpdate = logger('shouldComponentUpdate');30 UNSAFE_componentWillUpdate = logger('componentWillUpdate');31 componentDidUpdate = logger('componentDidUpdate');32 componentWillUnmount = logger('componentWillUnmount');33 render() {34 return <div />;35 }36 },37 );38 const shallowRenderer = createRenderer();39 shallowRenderer.render(<SomeComponent foo={1} />);40 // Calling cDU might lead to problems with host component references.41 // Since our components aren't really mounted, refs won't be available.42 expect(logs).toEqual(['componentWillMount']);43 logs.splice(0);44 const instance = shallowRenderer.getMountedInstance();45 instance.setState({});46 expect(logs).toEqual(['shouldComponentUpdate', 'componentWillUpdate']);47 logs.splice(0);48 shallowRenderer.render(<SomeComponent foo={2} />);49 // The previous shallow renderer did not trigger cDU for props changes.50 expect(logs).toEqual([51 'componentWillReceiveProps',52 'shouldComponentUpdate',53 'componentWillUpdate',54 ]);55 });56 it('should call all of the new lifecycle hooks', () => {57 const logs = [];58 const logger = message => () => logs.push(message) || true;59 const SomeComponent = React.memo(60 class SomeComponent extends React.Component {61 state = {};62 static getDerivedStateFromProps = logger('getDerivedStateFromProps');63 componentDidMount = logger('componentDidMount');64 shouldComponentUpdate = logger('shouldComponentUpdate');65 componentDidUpdate = logger('componentDidUpdate');66 componentWillUnmount = logger('componentWillUnmount');67 render() {68 return <div />;69 }70 },71 );72 const shallowRenderer = createRenderer();73 shallowRenderer.render(<SomeComponent foo={1} />);74 // Calling cDU might lead to problems with host component references.75 // Since our components aren't really mounted, refs won't be available.76 expect(logs).toEqual(['getDerivedStateFromProps']);77 logs.splice(0);78 const instance = shallowRenderer.getMountedInstance();79 instance.setState({});80 expect(logs).toEqual(['getDerivedStateFromProps', 'shouldComponentUpdate']);81 logs.splice(0);82 shallowRenderer.render(<SomeComponent foo={2} />);83 // The previous shallow renderer did not trigger cDU for props changes.84 expect(logs).toEqual(['getDerivedStateFromProps', 'shouldComponentUpdate']);85 });86 it('should not invoke deprecated lifecycles (cWM/cWRP/cWU) if new static gDSFP is present', () => {87 const Component = React.memo(88 class Component extends React.Component {89 state = {};90 static getDerivedStateFromProps() {91 return null;92 }93 componentWillMount() {94 throw Error('unexpected');95 }96 componentWillReceiveProps() {97 throw Error('unexpected');98 }99 componentWillUpdate() {100 throw Error('unexpected');101 }102 render() {103 return null;104 }105 },106 );107 const shallowRenderer = createRenderer();108 shallowRenderer.render(<Component />);109 });110 it('should not invoke deprecated lifecycles (cWM/cWRP/cWU) if new getSnapshotBeforeUpdate is present', () => {111 const Component = React.memo(112 class Component extends React.Component {113 getSnapshotBeforeUpdate() {114 return null;115 }116 componentWillMount() {117 throw Error('unexpected');118 }119 componentWillReceiveProps() {120 throw Error('unexpected');121 }122 componentWillUpdate() {123 throw Error('unexpected');124 }125 render() {126 return null;127 }128 },129 );130 const shallowRenderer = createRenderer();131 shallowRenderer.render(<Component value={1} />);132 shallowRenderer.render(<Component value={2} />);133 });134 it('should not call getSnapshotBeforeUpdate or componentDidUpdate when updating since refs wont exist', () => {135 const Component = React.memo(136 class Component extends React.Component {137 getSnapshotBeforeUpdate() {138 throw Error('unexpected');139 }140 componentDidUpdate() {141 throw Error('unexpected');142 }143 render() {144 return null;145 }146 },147 );148 const shallowRenderer = createRenderer();149 shallowRenderer.render(<Component value={1} />);150 shallowRenderer.render(<Component value={2} />);151 });152 it('should only render 1 level deep', () => {153 const Parent = React.memo(function Parent() {154 return (155 <div>156 <Child />157 </div>158 );159 });160 function Child() {161 throw Error('This component should not render');162 }163 const shallowRenderer = createRenderer();164 shallowRenderer.render(React.createElement(Parent));165 });166 it('should have shallow rendering', () => {167 const SomeComponent = React.memo(168 class SomeComponent extends React.Component {169 render() {170 return (171 <div>172 <span className="child1" />173 <span className="child2" />174 </div>175 );176 }177 },178 );179 const shallowRenderer = createRenderer();180 const result = shallowRenderer.render(<SomeComponent />);181 expect(result.type).toBe('div');182 expect(result.props.children).toEqual([183 <span className="child1" />,184 <span className="child2" />,185 ]);186 });187 it('should handle Profiler', () => {188 const SomeComponent = React.memo(189 class SomeComponent extends React.Component {190 render() {191 return (192 <React.Profiler id="test" onRender={jest.fn()}>193 <div>194 <span className="child1" />195 <span className="child2" />196 </div>197 </React.Profiler>198 );199 }200 },201 );202 const shallowRenderer = createRenderer();203 const result = shallowRenderer.render(<SomeComponent />);204 expect(result.type).toBe(React.Profiler);205 expect(result.props.children).toEqual(206 <div>207 <span className="child1" />208 <span className="child2" />209 </div>,210 );211 });212 it('should enable shouldComponentUpdate to prevent a re-render', () => {213 let renderCounter = 0;214 const SimpleComponent = React.memo(215 class SimpleComponent extends React.Component {216 state = {update: false};217 shouldComponentUpdate(nextProps, nextState) {218 return this.state.update !== nextState.update;219 }220 render() {221 renderCounter++;222 return <div>{`${renderCounter}`}</div>;223 }224 },225 );226 const shallowRenderer = createRenderer();227 shallowRenderer.render(<SimpleComponent />);228 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);229 const instance = shallowRenderer.getMountedInstance();230 instance.setState({update: false});231 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);232 instance.setState({update: true});233 expect(shallowRenderer.getRenderOutput()).toEqual(<div>2</div>);234 });235 it('should enable PureComponent to prevent a re-render', () => {236 let renderCounter = 0;237 const SimpleComponent = React.memo(238 class SimpleComponent extends React.PureComponent {239 state = {update: false};240 render() {241 renderCounter++;242 return <div>{`${renderCounter}`}</div>;243 }244 },245 );246 const shallowRenderer = createRenderer();247 shallowRenderer.render(<SimpleComponent />);248 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);249 const instance = shallowRenderer.getMountedInstance();250 instance.setState({update: false});251 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);252 instance.setState({update: true});253 expect(shallowRenderer.getRenderOutput()).toEqual(<div>2</div>);254 });255 it('should not run shouldComponentUpdate during forced update', () => {256 let scuCounter = 0;257 const SimpleComponent = React.memo(258 class SimpleComponent extends React.Component {259 state = {count: 1};260 shouldComponentUpdate() {261 scuCounter++;262 return false;263 }264 render() {265 return <div>{`${this.state.count}`}</div>;266 }267 },268 );269 const shallowRenderer = createRenderer();270 shallowRenderer.render(<SimpleComponent />);271 expect(scuCounter).toEqual(0);272 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);273 // Force update the initial state. sCU should not fire.274 const instance = shallowRenderer.getMountedInstance();275 instance.forceUpdate();276 expect(scuCounter).toEqual(0);277 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);278 // Setting state updates the instance, but doesn't re-render279 // because sCU returned false.280 instance.setState(state => ({count: state.count + 1}));281 expect(scuCounter).toEqual(1);282 expect(instance.state.count).toEqual(2);283 expect(shallowRenderer.getRenderOutput()).toEqual(<div>1</div>);284 // A force update updates the render output, but doesn't call sCU.285 instance.forceUpdate();286 expect(scuCounter).toEqual(1);287 expect(instance.state.count).toEqual(2);288 expect(shallowRenderer.getRenderOutput()).toEqual(<div>2</div>);289 });290 it('should rerender when calling forceUpdate', () => {291 let renderCounter = 0;292 const SimpleComponent = React.memo(293 class SimpleComponent extends React.Component {294 render() {295 renderCounter += 1;296 return <div />;297 }298 },299 );300 const shallowRenderer = createRenderer();301 shallowRenderer.render(<SimpleComponent />);302 expect(renderCounter).toEqual(1);303 const instance = shallowRenderer.getMountedInstance();304 instance.forceUpdate();305 expect(renderCounter).toEqual(2);306 });307 it('should shallow render a function component', () => {308 function SomeComponent(props, context) {309 return (310 <div>311 <div>{props.foo}</div>312 <div>{context.bar}</div>313 <span className="child1" />314 <span className="child2" />315 </div>316 );317 }318 const SomeMemoComponent = React.memo(SomeComponent);319 SomeComponent.contextTypes = {320 bar: PropTypes.string,321 };322 const shallowRenderer = createRenderer();323 const result = shallowRenderer.render(<SomeMemoComponent foo={'FOO'} />, {324 bar: 'BAR',325 });326 expect(result.type).toBe('div');327 expect(result.props.children).toEqual([328 <div>FOO</div>,329 <div>BAR</div>,330 <span className="child1" />,331 <span className="child2" />,332 ]);333 });334 it('should shallow render a component returning strings directly from render', () => {335 const Text = React.memo(({value}) => value);336 const shallowRenderer = createRenderer();337 const result = shallowRenderer.render(<Text value="foo" />);338 expect(result).toEqual('foo');339 });340 it('should shallow render a component returning numbers directly from render', () => {341 const Text = React.memo(({value}) => value);342 const shallowRenderer = createRenderer();343 const result = shallowRenderer.render(<Text value={10} />);344 expect(result).toEqual(10);345 });346 it('should shallow render a fragment', () => {347 class SomeComponent extends React.Component {348 render() {349 return <div />;350 }351 }352 class Fragment extends React.Component {353 render() {354 return [<div key="a" />, <span key="b" />, <SomeComponent />];355 }356 }357 const shallowRenderer = createRenderer();358 const result = shallowRenderer.render(<Fragment />);359 expect(result).toEqual([360 <div key="a" />,361 <span key="b" />,362 <SomeComponent />,363 ]);364 });365 it('should shallow render a React.fragment', () => {366 class SomeComponent extends React.Component {367 render() {368 return <div />;369 }370 }371 class Fragment extends React.Component {372 render() {373 return (374 <React.Fragment>375 <div />376 <span />377 <SomeComponent />378 </React.Fragment>379 );380 }381 }382 const shallowRenderer = createRenderer();383 const result = shallowRenderer.render(<Fragment />);384 expect(result).toEqual(385 <React.Fragment>386 <div />387 <span />388 <SomeComponent />389 </React.Fragment>,390 );391 });392 it('should throw for invalid elements', () => {393 class SomeComponent extends React.Component {394 render() {395 return <div />;396 }397 }398 const shallowRenderer = createRenderer();399 expect(() => shallowRenderer.render(SomeComponent)).toThrowError(400 'ReactShallowRenderer render(): Invalid component element. Instead of ' +401 'passing a component class, make sure to instantiate it by passing it ' +402 'to React.createElement.',403 );404 expect(() => shallowRenderer.render(<div />)).toThrowError(405 'ReactShallowRenderer render(): Shallow rendering works only with ' +406 'custom components, not primitives (div). Instead of calling ' +407 '`.render(el)` and inspecting the rendered output, look at `el.props` ' +408 'directly instead.',409 );410 });411 it('should have shallow unmounting', () => {412 const componentWillUnmount = jest.fn();413 class SomeComponent extends React.Component {414 componentWillUnmount = componentWillUnmount;415 render() {416 return <div />;417 }418 }419 const shallowRenderer = createRenderer();420 shallowRenderer.render(<SomeComponent />);421 shallowRenderer.unmount();422 expect(componentWillUnmount).toBeCalled();423 });424 it('can shallow render to null', () => {425 class SomeComponent extends React.Component {426 render() {427 return null;428 }429 }430 const shallowRenderer = createRenderer();431 const result = shallowRenderer.render(<SomeComponent />);432 expect(result).toBe(null);433 });434 it('can shallow render with a ref', () => {435 class SomeComponent extends React.Component {436 render() {437 return <div ref="hello" />;438 }439 }440 const shallowRenderer = createRenderer();441 // Shouldn't crash.442 shallowRenderer.render(<SomeComponent />);443 });444 it('lets you update shallowly rendered components', () => {445 class SomeComponent extends React.Component {446 state = {clicked: false};447 onClick = () => {448 this.setState({clicked: true});449 };450 render() {451 const className = this.state.clicked ? 'was-clicked' : '';452 if (this.props.aNew === 'prop') {453 return (454 <a href="#" onClick={this.onClick} className={className}>455 Test link456 </a>457 );458 } else {459 return (460 <div>461 <span className="child1" />462 <span className="child2" />463 </div>464 );465 }466 }467 }468 const shallowRenderer = createRenderer();469 const result = shallowRenderer.render(<SomeComponent />);470 expect(result.type).toBe('div');471 expect(result.props.children).toEqual([472 <span className="child1" />,473 <span className="child2" />,474 ]);475 const updatedResult = shallowRenderer.render(<SomeComponent aNew="prop" />);476 expect(updatedResult.type).toBe('a');477 const mockEvent = {};478 updatedResult.props.onClick(mockEvent);479 const updatedResultCausedByClick = shallowRenderer.getRenderOutput();480 expect(updatedResultCausedByClick.type).toBe('a');481 expect(updatedResultCausedByClick.props.className).toBe('was-clicked');482 });483 it('can access the mounted component instance', () => {484 const SimpleComponent = React.memo(485 class SimpleComponent extends React.Component {486 someMethod = () => {487 return this.props.n;488 };489 render() {490 return <div>{this.props.n}</div>;491 }492 },493 );494 const shallowRenderer = createRenderer();495 shallowRenderer.render(<SimpleComponent n={5} />);496 expect(shallowRenderer.getMountedInstance().someMethod()).toEqual(5);497 });498 it('can shallowly render components with contextTypes', () => {499 const SimpleComponent = React.memo(500 class SimpleComponent extends React.Component {501 static contextTypes = {502 name: PropTypes.string,503 };504 render() {505 return <div />;506 }507 },508 );509 const shallowRenderer = createRenderer();510 const result = shallowRenderer.render(<SimpleComponent />);511 expect(result).toEqual(<div />);512 });513 it('passes expected params to legacy component lifecycle methods', () => {514 const componentDidUpdateParams = [];515 const componentWillReceivePropsParams = [];516 const componentWillUpdateParams = [];517 const setStateParams = [];518 const shouldComponentUpdateParams = [];519 const initialProp = {prop: 'init prop'};520 const initialState = {state: 'init state'};521 const initialContext = {context: 'init context'};522 const updatedState = {state: 'updated state'};523 const updatedProp = {prop: 'updated prop'};524 const updatedContext = {context: 'updated context'};525 const SimpleComponent = React.memo(526 class SimpleComponent extends React.Component {527 constructor(props, context) {528 super(props, context);529 this.state = initialState;530 }531 static contextTypes = {532 context: PropTypes.string,533 };534 componentDidUpdate(...args) {535 componentDidUpdateParams.push(...args);536 }537 UNSAFE_componentWillReceiveProps(...args) {538 componentWillReceivePropsParams.push(...args);539 this.setState((...innerArgs) => {540 setStateParams.push(...innerArgs);541 return updatedState;542 });543 }544 UNSAFE_componentWillUpdate(...args) {545 componentWillUpdateParams.push(...args);546 }547 shouldComponentUpdate(...args) {548 shouldComponentUpdateParams.push(...args);549 return true;550 }551 render() {552 return null;553 }554 },555 );556 const shallowRenderer = createRenderer();557 shallowRenderer.render(558 React.createElement(SimpleComponent, initialProp),559 initialContext,560 );561 expect(componentDidUpdateParams).toEqual([]);562 expect(componentWillReceivePropsParams).toEqual([]);563 expect(componentWillUpdateParams).toEqual([]);564 expect(setStateParams).toEqual([]);565 expect(shouldComponentUpdateParams).toEqual([]);566 // Lifecycle hooks should be invoked with the correct prev/next params on update.567 shallowRenderer.render(568 React.createElement(SimpleComponent, updatedProp),569 updatedContext,570 );571 expect(componentWillReceivePropsParams).toEqual([572 updatedProp,573 updatedContext,574 ]);575 expect(setStateParams).toEqual([initialState, initialProp]);576 expect(shouldComponentUpdateParams).toEqual([577 updatedProp,578 updatedState,579 updatedContext,580 ]);581 expect(componentWillUpdateParams).toEqual([582 updatedProp,583 updatedState,584 updatedContext,585 ]);586 expect(componentDidUpdateParams).toEqual([]);587 });588 it('passes expected params to new component lifecycle methods', () => {589 const componentDidUpdateParams = [];590 const getDerivedStateFromPropsParams = [];591 const shouldComponentUpdateParams = [];592 const initialProp = {prop: 'init prop'};593 const initialState = {state: 'init state'};594 const initialContext = {context: 'init context'};595 const updatedProp = {prop: 'updated prop'};596 const updatedContext = {context: 'updated context'};597 const SimpleComponent = React.memo(598 class SimpleComponent extends React.Component {599 constructor(props, context) {600 super(props, context);601 this.state = initialState;602 }603 static contextTypes = {604 context: PropTypes.string,605 };606 componentDidUpdate(...args) {607 componentDidUpdateParams.push(...args);608 }609 static getDerivedStateFromProps(...args) {610 getDerivedStateFromPropsParams.push(args);611 return null;612 }613 shouldComponentUpdate(...args) {614 shouldComponentUpdateParams.push(...args);615 return true;616 }617 render() {618 return null;619 }620 },621 );622 const shallowRenderer = createRenderer();623 // The only lifecycle hook that should be invoked on initial render624 // Is the static getDerivedStateFromProps() methods625 shallowRenderer.render(626 React.createElement(SimpleComponent, initialProp),627 initialContext,628 );629 expect(getDerivedStateFromPropsParams).toEqual([630 [initialProp, initialState],631 ]);632 expect(componentDidUpdateParams).toEqual([]);633 expect(shouldComponentUpdateParams).toEqual([]);634 // Lifecycle hooks should be invoked with the correct prev/next params on update.635 shallowRenderer.render(636 React.createElement(SimpleComponent, updatedProp),637 updatedContext,638 );639 expect(getDerivedStateFromPropsParams).toEqual([640 [initialProp, initialState],641 [updatedProp, initialState],642 ]);643 expect(shouldComponentUpdateParams).toEqual([644 updatedProp,645 initialState,646 updatedContext,647 ]);648 expect(componentDidUpdateParams).toEqual([]);649 });650 it('can shallowly render components with ref as function', () => {651 const SimpleComponent = React.memo(652 class SimpleComponent extends React.Component {653 state = {clicked: false};654 handleUserClick = () => {655 this.setState({clicked: true});656 };657 render() {658 return (659 <div660 ref={() => {}}661 onClick={this.handleUserClick}662 className={this.state.clicked ? 'clicked' : ''}663 />664 );665 }666 },667 );668 const shallowRenderer = createRenderer();669 shallowRenderer.render(<SimpleComponent />);670 let result = shallowRenderer.getRenderOutput();671 expect(result.type).toEqual('div');672 expect(result.props.className).toEqual('');673 result.props.onClick();674 result = shallowRenderer.getRenderOutput();675 expect(result.type).toEqual('div');676 expect(result.props.className).toEqual('clicked');677 });678 it('can initialize state via static getDerivedStateFromProps', () => {679 const SimpleComponent = React.memo(680 class SimpleComponent extends React.Component {681 state = {682 count: 1,683 };684 static getDerivedStateFromProps(props, prevState) {685 return {686 count: prevState.count + props.incrementBy,687 other: 'foobar',688 };689 }690 render() {691 return (692 <div>{`count:${this.state.count}, other:${this.state.other}`}</div>693 );694 }695 },696 );697 const shallowRenderer = createRenderer();698 const result = shallowRenderer.render(<SimpleComponent incrementBy={2} />);699 expect(result).toEqual(<div>count:3, other:foobar</div>);700 });701 it('can setState in componentWillMount when shallow rendering', () => {702 const SimpleComponent = React.memo(703 class SimpleComponent extends React.Component {704 UNSAFE_componentWillMount() {705 this.setState({groovy: 'doovy'});706 }707 render() {708 return <div>{this.state.groovy}</div>;709 }710 },711 );712 const shallowRenderer = createRenderer();713 const result = shallowRenderer.render(<SimpleComponent />);714 expect(result).toEqual(<div>doovy</div>);715 });716 it('can setState in componentWillMount repeatedly when shallow rendering', () => {717 const SimpleComponent = React.memo(718 class SimpleComponent extends React.Component {719 state = {720 separator: '-',721 };722 UNSAFE_componentWillMount() {723 this.setState({groovy: 'doovy'});724 this.setState({doovy: 'groovy'});725 }726 render() {727 const {groovy, doovy, separator} = this.state;728 return <div>{`${groovy}${separator}${doovy}`}</div>;729 }730 },731 );732 const shallowRenderer = createRenderer();733 const result = shallowRenderer.render(<SimpleComponent />);734 expect(result).toEqual(<div>doovy-groovy</div>);735 });736 it('can setState in componentWillMount with an updater function repeatedly when shallow rendering', () => {737 const SimpleComponent = React.memo(738 class SimpleComponent extends React.Component {739 state = {740 separator: '-',741 };742 UNSAFE_componentWillMount() {743 this.setState(state => ({groovy: 'doovy'}));744 this.setState(state => ({doovy: state.groovy}));745 }746 render() {747 const {groovy, doovy, separator} = this.state;748 return <div>{`${groovy}${separator}${doovy}`}</div>;749 }750 },751 );752 const shallowRenderer = createRenderer();753 const result = shallowRenderer.render(<SimpleComponent />);754 expect(result).toEqual(<div>doovy-doovy</div>);755 });756 it('can setState in componentWillReceiveProps when shallow rendering', () => {757 const SimpleComponent = React.memo(758 class SimpleComponent extends React.Component {759 state = {count: 0};760 UNSAFE_componentWillReceiveProps(nextProps) {761 if (nextProps.updateState) {762 this.setState({count: 1});763 }764 }765 render() {766 return <div>{this.state.count}</div>;767 }768 },769 );770 const shallowRenderer = createRenderer();771 let result = shallowRenderer.render(772 <SimpleComponent updateState={false} />,773 );774 expect(result.props.children).toEqual(0);775 result = shallowRenderer.render(<SimpleComponent updateState={true} />);776 expect(result.props.children).toEqual(1);777 });778 it('can update state with static getDerivedStateFromProps when shallow rendering', () => {779 const SimpleComponent = React.memo(780 class SimpleComponent extends React.Component {781 state = {count: 1};782 static getDerivedStateFromProps(nextProps, prevState) {783 if (nextProps.updateState) {784 return {count: nextProps.incrementBy + prevState.count};785 }786 return null;787 }788 render() {789 return <div>{this.state.count}</div>;790 }791 },792 );793 const shallowRenderer = createRenderer();794 let result = shallowRenderer.render(795 <SimpleComponent updateState={false} incrementBy={0} />,796 );797 expect(result.props.children).toEqual(1);798 result = shallowRenderer.render(799 <SimpleComponent updateState={true} incrementBy={2} />,800 );801 expect(result.props.children).toEqual(3);802 result = shallowRenderer.render(803 <SimpleComponent updateState={false} incrementBy={2} />,804 );805 expect(result.props.children).toEqual(3);806 });807 it('should not override state with stale values if prevState is spread within getDerivedStateFromProps', () => {808 const SimpleComponent = React.memo(809 class SimpleComponent extends React.Component {810 state = {value: 0};811 static getDerivedStateFromProps(nextProps, prevState) {812 return {...prevState};813 }814 updateState = () => {815 this.setState(state => ({value: state.value + 1}));816 };817 render() {818 return <div>{`value:${this.state.value}`}</div>;819 }820 },821 );822 const shallowRenderer = createRenderer();823 let result = shallowRenderer.render(<SimpleComponent />);824 expect(result).toEqual(<div>value:0</div>);825 let instance = shallowRenderer.getMountedInstance();826 instance.updateState();827 result = shallowRenderer.getRenderOutput();828 expect(result).toEqual(<div>value:1</div>);829 });830 it('should pass previous state to shouldComponentUpdate even with getDerivedStateFromProps', () => {831 const SimpleComponent = React.memo(832 class SimpleComponent extends React.Component {833 constructor(props) {834 super(props);835 this.state = {836 value: props.value,837 };838 }839 static getDerivedStateFromProps(nextProps, prevState) {840 if (nextProps.value === prevState.value) {841 return null;842 }843 return {value: nextProps.value};844 }845 shouldComponentUpdate(nextProps, nextState) {846 return nextState.value !== this.state.value;847 }848 render() {849 return <div>{`value:${this.state.value}`}</div>;850 }851 },852 );853 const shallowRenderer = createRenderer();854 const initialResult = shallowRenderer.render(855 <SimpleComponent value="initial" />,856 );857 expect(initialResult).toEqual(<div>value:initial</div>);858 const updatedResult = shallowRenderer.render(859 <SimpleComponent value="updated" />,860 );861 expect(updatedResult).toEqual(<div>value:updated</div>);862 });863 it('can setState with an updater function', () => {864 let instance;865 const SimpleComponent = React.memo(866 class SimpleComponent extends React.Component {867 state = {868 counter: 0,869 };870 render() {871 instance = this;872 return (873 <button ref="button" onClick={this.onClick}>874 {this.state.counter}875 </button>876 );877 }878 },879 );880 const shallowRenderer = createRenderer();881 let result = shallowRenderer.render(<SimpleComponent defaultCount={1} />);882 expect(result.props.children).toEqual(0);883 instance.setState((state, props) => {884 return {counter: props.defaultCount + 1};885 });886 result = shallowRenderer.getRenderOutput();887 expect(result.props.children).toEqual(2);888 });889 it('can access component instance from setState updater function', done => {890 let instance;891 const SimpleComponent = React.memo(892 class SimpleComponent extends React.Component {893 state = {};894 render() {895 instance = this;896 return null;897 }898 },899 );900 const shallowRenderer = createRenderer();901 shallowRenderer.render(<SimpleComponent />);902 instance.setState(function updater(state, props) {903 expect(this).toBe(instance);904 done();905 });906 });907 it('can setState with a callback', () => {908 let instance;909 const SimpleComponent = React.memo(910 class SimpleComponent extends React.Component {911 state = {912 counter: 0,913 };914 render() {915 instance = this;916 return <p>{this.state.counter}</p>;917 }918 },919 );920 const shallowRenderer = createRenderer();921 const result = shallowRenderer.render(<SimpleComponent />);922 expect(result.props.children).toBe(0);923 const callback = jest.fn(function() {924 expect(this).toBe(instance);925 });926 instance.setState({counter: 1}, callback);927 const updated = shallowRenderer.getRenderOutput();928 expect(updated.props.children).toBe(1);929 expect(callback).toHaveBeenCalled();930 });931 it('can replaceState with a callback', () => {932 let instance;933 const SimpleComponent = React.memo(934 class SimpleComponent extends React.Component {935 state = {936 counter: 0,937 };938 render() {939 instance = this;940 return <p>{this.state.counter}</p>;941 }942 },943 );944 const shallowRenderer = createRenderer();945 const result = shallowRenderer.render(<SimpleComponent />);946 expect(result.props.children).toBe(0);947 const callback = jest.fn(function() {948 expect(this).toBe(instance);949 });950 // No longer a public API, but we can test that it works internally by951 // reaching into the updater.952 shallowRenderer._updater.enqueueReplaceState(953 instance,954 {counter: 1},955 callback,956 );957 const updated = shallowRenderer.getRenderOutput();958 expect(updated.props.children).toBe(1);959 expect(callback).toHaveBeenCalled();960 });961 it('can forceUpdate with a callback', () => {962 let instance;963 const SimpleComponent = React.memo(964 class SimpleComponent extends React.Component {965 state = {966 counter: 0,967 };968 render() {969 instance = this;970 return <p>{this.state.counter}</p>;971 }972 },973 );974 const shallowRenderer = createRenderer();975 const result = shallowRenderer.render(<SimpleComponent />);976 expect(result.props.children).toBe(0);977 const callback = jest.fn(function() {978 expect(this).toBe(instance);979 });980 instance.forceUpdate(callback);981 const updated = shallowRenderer.getRenderOutput();982 expect(updated.props.children).toBe(0);983 expect(callback).toHaveBeenCalled();984 });985 it('can pass context when shallowly rendering', () => {986 const SimpleComponent = React.memo(987 class SimpleComponent extends React.Component {988 static contextTypes = {989 name: PropTypes.string,990 };991 render() {992 return <div>{this.context.name}</div>;993 }994 },995 );996 const shallowRenderer = createRenderer();997 const result = shallowRenderer.render(<SimpleComponent />, {998 name: 'foo',999 });1000 expect(result).toEqual(<div>foo</div>);1001 });1002 it('should track context across updates', () => {1003 const SimpleComponent = React.memo(1004 class SimpleComponent extends React.Component {1005 static contextTypes = {1006 foo: PropTypes.string,1007 };1008 state = {1009 bar: 'bar',1010 };1011 render() {1012 return <div>{`${this.context.foo}:${this.state.bar}`}</div>;1013 }1014 },1015 );1016 const shallowRenderer = createRenderer();1017 let result = shallowRenderer.render(<SimpleComponent />, {1018 foo: 'foo',1019 });1020 expect(result).toEqual(<div>foo:bar</div>);1021 const instance = shallowRenderer.getMountedInstance();1022 instance.setState({bar: 'baz'});1023 result = shallowRenderer.getRenderOutput();1024 expect(result).toEqual(<div>foo:baz</div>);1025 });1026 it('should filter context by contextTypes', () => {1027 const SimpleComponent = React.memo(1028 class SimpleComponent extends React.Component {1029 static contextTypes = {1030 foo: PropTypes.string,1031 };1032 render() {1033 return <div>{`${this.context.foo}:${this.context.bar}`}</div>;1034 }1035 },1036 );1037 const shallowRenderer = createRenderer();1038 let result = shallowRenderer.render(<SimpleComponent />, {1039 foo: 'foo',1040 bar: 'bar',1041 });1042 expect(result).toEqual(<div>foo:undefined</div>);1043 });1044 it('can fail context when shallowly rendering', () => {1045 const SimpleComponent = React.memo(1046 class SimpleComponent extends React.Component {1047 static contextTypes = {1048 name: PropTypes.string.isRequired,1049 };1050 render() {1051 return <div>{this.context.name}</div>;1052 }1053 },1054 );1055 const shallowRenderer = createRenderer();1056 expect(() => shallowRenderer.render(<SimpleComponent />)).toWarnDev(1057 'Warning: Failed context type: The context `name` is marked as ' +1058 'required in `SimpleComponent`, but its value is `undefined`.\n' +1059 ' in SimpleComponent (at **)',1060 );1061 });1062 it('should warn about propTypes (but only once)', () => {1063 const SimpleComponent = React.memo(1064 class SimpleComponent extends React.Component {1065 static propTypes = {1066 name: PropTypes.string.isRequired,1067 };1068 render() {1069 return React.createElement('div', null, this.props.name);1070 }1071 },1072 );1073 const shallowRenderer = createRenderer();1074 expect(() =>1075 shallowRenderer.render(React.createElement(SimpleComponent, {name: 123})),1076 ).toWarnDev(1077 'Warning: Failed prop type: Invalid prop `name` of type `number` ' +1078 'supplied to `SimpleComponent`, expected `string`.\n' +1079 ' in SimpleComponent',1080 );1081 });1082 it('should enable rendering of cloned element', () => {1083 const SimpleComponent = React.memo(1084 class SimpleComponent extends React.Component {1085 constructor(props) {1086 super(props);1087 this.state = {1088 bar: 'bar',1089 };1090 }1091 render() {1092 return <div>{`${this.props.foo}:${this.state.bar}`}</div>;1093 }1094 },1095 );1096 const shallowRenderer = createRenderer();1097 const el = <SimpleComponent foo="foo" />;1098 let result = shallowRenderer.render(el);1099 expect(result).toEqual(<div>foo:bar</div>);1100 const cloned = React.cloneElement(el, {foo: 'baz'});1101 result = shallowRenderer.render(cloned);1102 expect(result).toEqual(<div>baz:bar</div>);1103 });1104 it('this.state should be updated on setState callback inside componentWillMount', () => {1105 let stateSuccessfullyUpdated = false;1106 const Component = React.memo(1107 class Component extends React.Component {1108 constructor(props, context) {1109 super(props, context);1110 this.state = {1111 hasUpdatedState: false,1112 };1113 }1114 UNSAFE_componentWillMount() {1115 this.setState(1116 {hasUpdatedState: true},1117 () => (stateSuccessfullyUpdated = this.state.hasUpdatedState),1118 );1119 }1120 render() {1121 return <div>{this.props.children}</div>;1122 }1123 },1124 );1125 const shallowRenderer = createRenderer();1126 shallowRenderer.render(<Component />);1127 expect(stateSuccessfullyUpdated).toBe(true);1128 });1129 it('should handle multiple callbacks', () => {1130 const mockFn = jest.fn();1131 const shallowRenderer = createRenderer();1132 const Component = React.memo(1133 class Component extends React.Component {1134 constructor(props, context) {1135 super(props, context);1136 this.state = {1137 foo: 'foo',1138 };1139 }1140 UNSAFE_componentWillMount() {1141 this.setState({foo: 'bar'}, () => mockFn());1142 this.setState({foo: 'foobar'}, () => mockFn());1143 }1144 render() {1145 return <div>{this.state.foo}</div>;1146 }1147 },1148 );1149 shallowRenderer.render(<Component />);1150 expect(mockFn).toHaveBeenCalledTimes(2);1151 // Ensure the callback queue is cleared after the callbacks are invoked1152 const mountedInstance = shallowRenderer.getMountedInstance();1153 mountedInstance.setState({foo: 'bar'}, () => mockFn());1154 expect(mockFn).toHaveBeenCalledTimes(3);1155 });1156 it('should call the setState callback even if shouldComponentUpdate = false', done => {1157 const mockFn = jest.fn().mockReturnValue(false);1158 const Component = React.memo(1159 class Component extends React.Component {1160 constructor(props, context) {1161 super(props, context);1162 this.state = {1163 hasUpdatedState: false,1164 };1165 }1166 shouldComponentUpdate() {1167 return mockFn();1168 }1169 render() {1170 return <div>{this.state.hasUpdatedState}</div>;1171 }1172 },1173 );1174 const shallowRenderer = createRenderer();1175 shallowRenderer.render(<Component />);1176 const mountedInstance = shallowRenderer.getMountedInstance();1177 mountedInstance.setState({hasUpdatedState: true}, () => {1178 expect(mockFn).toBeCalled();1179 expect(mountedInstance.state.hasUpdatedState).toBe(true);1180 done();1181 });1182 });1183 it('throws usefully when rendering badly-typed elements', () => {1184 const shallowRenderer = createRenderer();1185 const renderAndVerifyWarningAndError = (Component, typeString) => {1186 expect(() => {1187 expect(() => shallowRenderer.render(<Component />)).toWarnDev(1188 'React.createElement: type is invalid -- expected a string ' +1189 '(for built-in components) or a class/function (for composite components) ' +1190 `but got: ${typeString}.`,1191 );1192 }).toThrowError(1193 'ReactShallowRenderer render(): Shallow rendering works only with custom ' +1194 `components, but the provided element type was \`${typeString}\`.`,1195 );1196 };1197 renderAndVerifyWarningAndError(undefined, 'undefined');1198 renderAndVerifyWarningAndError(null, 'null');1199 renderAndVerifyWarningAndError([], 'array');1200 renderAndVerifyWarningAndError({}, 'object');1201 });1202 it('should have initial state of null if not defined', () => {1203 const SomeComponent = React.memo(1204 class SomeComponent extends React.Component {1205 render() {1206 return <span />;1207 }1208 },1209 );1210 const shallowRenderer = createRenderer();1211 shallowRenderer.render(<SomeComponent />);1212 expect(shallowRenderer.getMountedInstance().state).toBeNull();1213 });1214 it('should invoke both deprecated and new lifecycles if both are present', () => {1215 const log = [];1216 const Component = React.memo(1217 class Component extends React.Component {1218 componentWillMount() {1219 log.push('componentWillMount');1220 }1221 componentWillReceiveProps() {1222 log.push('componentWillReceiveProps');1223 }1224 componentWillUpdate() {1225 log.push('componentWillUpdate');1226 }1227 UNSAFE_componentWillMount() {1228 log.push('UNSAFE_componentWillMount');1229 }1230 UNSAFE_componentWillReceiveProps() {1231 log.push('UNSAFE_componentWillReceiveProps');1232 }1233 UNSAFE_componentWillUpdate() {1234 log.push('UNSAFE_componentWillUpdate');1235 }1236 render() {1237 return null;1238 }1239 },1240 );1241 const shallowRenderer = createRenderer();1242 shallowRenderer.render(<Component foo="bar" />);1243 expect(log).toEqual(['componentWillMount', 'UNSAFE_componentWillMount']);1244 log.length = 0;1245 shallowRenderer.render(<Component foo="baz" />);1246 expect(log).toEqual([1247 'componentWillReceiveProps',1248 'UNSAFE_componentWillReceiveProps',1249 'componentWillUpdate',1250 'UNSAFE_componentWillUpdate',1251 ]);1252 });1253 it('should stop the update when setState returns null or undefined', () => {1254 const log = [];1255 let instance;1256 const Component = React.memo(1257 class Component extends React.Component {1258 constructor(props) {1259 super(props);1260 this.state = {1261 count: 0,1262 };1263 }1264 render() {1265 log.push('render');1266 instance = this;1267 return null;1268 }1269 },1270 );1271 const shallowRenderer = createRenderer();1272 shallowRenderer.render(<Component />);1273 log.length = 0;1274 instance.setState(() => null);1275 instance.setState(() => undefined);1276 instance.setState(null);1277 instance.setState(undefined);1278 expect(log).toEqual([]);1279 instance.setState(state => ({count: state.count + 1}));1280 expect(log).toEqual(['render']);1281 });1282 it('should not get this in a function component', () => {1283 const logs = [];1284 const Foo = React.memo(function Foo() {1285 logs.push(this);1286 return <div>foo</div>;1287 });1288 const shallowRenderer = createRenderer();1289 shallowRenderer.render(<Foo foo="bar" />);1290 expect(logs).toEqual([undefined]);1291 });...

Full Screen

Full Screen

ReactShallowRendererHooks-test.js

Source:ReactShallowRendererHooks-test.js Github

copy

Full Screen

1/**2 * Copyright (c) Facebook, Inc. and its affiliates.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 *7 * @emails react-core8 * @jest-environment node9 */10'use strict';11let createRenderer;12let React;13describe('ReactShallowRenderer with hooks', () => {14 beforeEach(() => {15 jest.resetModules();16 createRenderer = require('react-test-renderer/shallow').createRenderer;17 React = require('react');18 });19 it('should work with useState', () => {20 function SomeComponent({defaultName}) {21 const [name] = React.useState(defaultName);22 return (23 <div>24 <p>25 Your name is: <span>{name}</span>26 </p>27 </div>28 );29 }30 const shallowRenderer = createRenderer();31 let result = shallowRenderer.render(32 <SomeComponent defaultName={'Dominic'} />,33 );34 expect(result).toEqual(35 <div>36 <p>37 Your name is: <span>Dominic</span>38 </p>39 </div>,40 );41 result = shallowRenderer.render(42 <SomeComponent defaultName={'Should not use this name'} />,43 );44 expect(result).toEqual(45 <div>46 <p>47 Your name is: <span>Dominic</span>48 </p>49 </div>,50 );51 });52 it('should work with updating a value from useState', () => {53 function SomeComponent({defaultName}) {54 const [name, updateName] = React.useState(defaultName);55 if (name !== 'Dan') {56 updateName('Dan');57 }58 return (59 <div>60 <p>61 Your name is: <span>{name}</span>62 </p>63 </div>64 );65 }66 const shallowRenderer = createRenderer();67 const result = shallowRenderer.render(68 <SomeComponent defaultName={'Dominic'} />,69 );70 expect(result).toEqual(71 <div>72 <p>73 Your name is: <span>Dan</span>74 </p>75 </div>,76 );77 });78 it('should work with updating a derived value from useState', () => {79 let _updateName;80 function SomeComponent({defaultName}) {81 const [name, updateName] = React.useState(defaultName);82 const [prevName, updatePrevName] = React.useState(defaultName);83 const [letter, updateLetter] = React.useState(name[0]);84 _updateName = updateName;85 if (name !== prevName) {86 updatePrevName(name);87 updateLetter(name[0]);88 }89 return (90 <div>91 <p>92 Your name is: <span>{name + ' (' + letter + ')'}</span>93 </p>94 </div>95 );96 }97 const shallowRenderer = createRenderer();98 let result = shallowRenderer.render(99 <SomeComponent defaultName={'Sophie'} />,100 );101 expect(result).toEqual(102 <div>103 <p>104 Your name is: <span>Sophie (S)</span>105 </p>106 </div>,107 );108 result = shallowRenderer.render(<SomeComponent defaultName={'Dan'} />);109 expect(result).toEqual(110 <div>111 <p>112 Your name is: <span>Sophie (S)</span>113 </p>114 </div>,115 );116 _updateName('Dan');117 expect(shallowRenderer.getRenderOutput()).toEqual(118 <div>119 <p>120 Your name is: <span>Dan (D)</span>121 </p>122 </div>,123 );124 });125 it('should work with useReducer', () => {126 function reducer(state, action) {127 switch (action.type) {128 case 'increment':129 return {count: state.count + 1};130 case 'decrement':131 return {count: state.count - 1};132 }133 }134 function SomeComponent(props) {135 const [state] = React.useReducer(reducer, props, p => ({136 count: p.initialCount,137 }));138 return (139 <div>140 <p>141 The counter is at: <span>{state.count.toString()}</span>142 </p>143 </div>144 );145 }146 const shallowRenderer = createRenderer();147 let result = shallowRenderer.render(<SomeComponent initialCount={0} />);148 expect(result).toEqual(149 <div>150 <p>151 The counter is at: <span>0</span>152 </p>153 </div>,154 );155 result = shallowRenderer.render(<SomeComponent initialCount={10} />);156 expect(result).toEqual(157 <div>158 <p>159 The counter is at: <span>0</span>160 </p>161 </div>,162 );163 });164 it('should work with a dispatched state change for a useReducer', () => {165 function reducer(state, action) {166 switch (action.type) {167 case 'increment':168 return {count: state.count + 1};169 case 'decrement':170 return {count: state.count - 1};171 }172 }173 function SomeComponent(props) {174 const [state, dispatch] = React.useReducer(reducer, props, p => ({175 count: p.initialCount,176 }));177 if (state.count === 0) {178 dispatch({type: 'increment'});179 }180 return (181 <div>182 <p>183 The counter is at: <span>{state.count.toString()}</span>184 </p>185 </div>186 );187 }188 const shallowRenderer = createRenderer();189 let result = shallowRenderer.render(<SomeComponent initialCount={0} />);190 expect(result).toEqual(191 <div>192 <p>193 The counter is at: <span>1</span>194 </p>195 </div>,196 );197 });198 it('should not trigger effects', () => {199 let effectsCalled = [];200 function SomeComponent({defaultName}) {201 React.useEffect(() => {202 effectsCalled.push('useEffect');203 });204 React.useLayoutEffect(() => {205 effectsCalled.push('useEffect');206 });207 return <div>Hello world</div>;208 }209 const shallowRenderer = createRenderer();210 shallowRenderer.render(<SomeComponent />);211 expect(effectsCalled).toEqual([]);212 });213 it('should work with useRef', () => {214 function SomeComponent() {215 const randomNumberRef = React.useRef({number: Math.random()});216 return (217 <div>218 <p>The random number is: {randomNumberRef.current.number}</p>219 </div>220 );221 }222 const shallowRenderer = createRenderer();223 let firstResult = shallowRenderer.render(<SomeComponent />);224 let secondResult = shallowRenderer.render(<SomeComponent />);225 expect(firstResult).toEqual(secondResult);226 });227 it('should work with useMemo', () => {228 function SomeComponent() {229 const randomNumber = React.useMemo(() => {230 return {number: Math.random()};231 }, []);232 return (233 <div>234 <p>The random number is: {randomNumber.number}</p>235 </div>236 );237 }238 const shallowRenderer = createRenderer();239 let firstResult = shallowRenderer.render(<SomeComponent />);240 let secondResult = shallowRenderer.render(<SomeComponent />);241 expect(firstResult).toEqual(secondResult);242 });243 it('should work with useContext', () => {244 const SomeContext = React.createContext('default');245 function SomeComponent() {246 const value = React.useContext(SomeContext);247 return (248 <div>249 <p>{value}</p>250 </div>251 );252 }253 const shallowRenderer = createRenderer();254 let result = shallowRenderer.render(<SomeComponent />);255 expect(result).toEqual(256 <div>257 <p>default</p>258 </div>,259 );260 });261 it('should not leak state when component type changes', () => {262 function SomeComponent({defaultName}) {263 const [name] = React.useState(defaultName);264 return (265 <div>266 <p>267 Your name is: <span>{name}</span>268 </p>269 </div>270 );271 }272 function SomeOtherComponent({defaultName}) {273 const [name] = React.useState(defaultName);274 return (275 <div>276 <p>277 Your name is: <span>{name}</span>278 </p>279 </div>280 );281 }282 const shallowRenderer = createRenderer();283 let result = shallowRenderer.render(284 <SomeComponent defaultName={'Dominic'} />,285 );286 expect(result).toEqual(287 <div>288 <p>289 Your name is: <span>Dominic</span>290 </p>291 </div>,292 );293 result = shallowRenderer.render(<SomeOtherComponent defaultName={'Dan'} />);294 expect(result).toEqual(295 <div>296 <p>297 Your name is: <span>Dan</span>298 </p>299 </div>,300 );301 });302 it('should work with with forwardRef + any hook', () => {303 const SomeComponent = React.forwardRef((props, ref) => {304 const randomNumberRef = React.useRef({number: Math.random()});305 return (306 <div ref={ref}>307 <p>The random number is: {randomNumberRef.current.number}</p>308 </div>309 );310 });311 const shallowRenderer = createRenderer();312 let firstResult = shallowRenderer.render(<SomeComponent />);313 let secondResult = shallowRenderer.render(<SomeComponent />);314 expect(firstResult).toEqual(secondResult);315 });316 it('should update a value from useState outside the render', () => {317 let _dispatch;318 function SomeComponent({defaultName}) {319 const [count, dispatch] = React.useReducer(320 (s, a) => (a === 'inc' ? s + 1 : s),321 0,322 );323 const [name, updateName] = React.useState(defaultName);324 _dispatch = () => dispatch('inc');325 return (326 <div onClick={() => updateName('Dan')}>327 <p>328 Your name is: <span>{name}</span> ({count})329 </p>330 </div>331 );332 }333 const shallowRenderer = createRenderer();334 const element = <SomeComponent defaultName={'Dominic'} />;335 const result = shallowRenderer.render(element);336 expect(result.props.children).toEqual(337 <p>338 Your name is: <span>Dominic</span> ({0})339 </p>,340 );341 result.props.onClick();342 let updated = shallowRenderer.render(element);343 expect(updated.props.children).toEqual(344 <p>345 Your name is: <span>Dan</span> ({0})346 </p>,347 );348 _dispatch('foo');349 updated = shallowRenderer.render(element);350 expect(updated.props.children).toEqual(351 <p>352 Your name is: <span>Dan</span> ({1})353 </p>,354 );355 _dispatch('inc');356 updated = shallowRenderer.render(element);357 expect(updated.props.children).toEqual(358 <p>359 Your name is: <span>Dan</span> ({2})360 </p>,361 );362 });363 it('should ignore a foreign update outside the render', () => {364 let _updateCountForFirstRender;365 function SomeComponent() {366 const [count, updateCount] = React.useState(0);367 if (!_updateCountForFirstRender) {368 _updateCountForFirstRender = updateCount;369 }370 return count;371 }372 const shallowRenderer = createRenderer();373 const element = <SomeComponent />;374 let result = shallowRenderer.render(element);375 expect(result).toEqual(0);376 _updateCountForFirstRender(1);377 result = shallowRenderer.render(element);378 expect(result).toEqual(1);379 shallowRenderer.unmount();380 result = shallowRenderer.render(element);381 expect(result).toEqual(0);382 _updateCountForFirstRender(1); // Should be ignored.383 result = shallowRenderer.render(element);384 expect(result).toEqual(0);385 });386 it('should not forget render phase updates', () => {387 let _updateCount;388 function SomeComponent() {389 const [count, updateCount] = React.useState(0);390 _updateCount = updateCount;391 if (count < 5) {392 updateCount(x => x + 1);393 }394 return count;395 }396 const shallowRenderer = createRenderer();397 const element = <SomeComponent />;398 let result = shallowRenderer.render(element);399 expect(result).toEqual(5);400 _updateCount(10);401 result = shallowRenderer.render(element);402 expect(result).toEqual(10);403 _updateCount(x => x + 1);404 result = shallowRenderer.render(element);405 expect(result).toEqual(11);406 _updateCount(x => x - 10);407 result = shallowRenderer.render(element);408 expect(result).toEqual(5);409 });...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1import React from 'react';2import { shallow } from 'enzyme';3import { storiesOf } from '@storybook/react';4import { action } from '@storybook/addon-actions';5import { linkTo } from '@storybook/addon-links';6import { Welcome } from '@storybook/react/demo';7import { StorybookRoot } from 'storybook-root';8import { Button } from '@storybook/react/demo';9import { withKnobs, text, boolean, number } from '@storybook/addon-knobs';10storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);11storiesOf('Button', module)12 .addDecorator(withKnobs)13 .add('with text', () => (14 <Button onClick={action('clicked')}>{text('Label', 'Hello Button')}</Button>15 .add('with some emoji', () => (16 <Button onClick={action('clicked')}>17 .add('with some emoji and action', () => (18 <Button onClick={action('clicked')}>19 ));20storiesOf('StorybookRoot', module).add('with text', () => <StorybookRoot />);21import React from 'react';22import { shallow } from 'enzyme';23import { storiesOf } from '@storybook/react';24import { action } from '@storybook/addon-actions';25import { linkTo } from '@storybook/addon-links';26import { Welcome } from '@storybook/react/demo';27import { StorybookRoot } from 'storybook-root';28import { Button } from '@storybook/react/demo';29import { withKnobs, text, boolean, number } from '@storybook/addon-knobs';30storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);31storiesOf('Button', module)32 .addDecorator(withKnobs)33 .add('with text', () => (34 <Button onClick={action('clicked')}>{text('

Full Screen

Using AI Code Generation

copy

Full Screen

1import React from 'react';2import { shallow } from 'enzyme';3import { shallowRender } from 'storybook-root';4import MyComponent from './MyComponent';5describe('MyComponent', () => {6 it('should render', () => {7 const component = shallowRender(<MyComponent />);8 expect(component).toMatchSnapshot();9 });10});11{12 "scripts": {13 },14 "dependencies": {15 },16 "devDependencies": {17 }18}

Full Screen

Using AI Code Generation

copy

Full Screen

1import React from 'react';2import { shallow } from 'enzyme';3import { shallowRenderer } from 'storybook-root';4import { MyComponent } from './MyComponent';5describe('MyComponent', () => {6 it('should render', () => {7 const component = shallowRenderer(<MyComponent />);8 expect(component).toMatchSnapshot();9 });10});11import React from 'react';12import { shallowRenderer } from 'storybook-root';13export const MyComponent = () => {14 return <div>MyComponent</div>;15};16export default shallowRenderer(MyComponent);17import React from 'react';18import { shallow } from 'enzyme';19export const shallowRenderer = (component) => {20 const wrapper = shallow(component);21 return wrapper;22};23import { configure } from '@storybook/react';24import { setOptions } from '@storybook/addon-options';25import { setDefaults } from '@storybook/addon-info';26import { configureViewport } from '@storybook/addon-viewport';27setOptions({28});29setDefaults({30});31configureViewport({32 viewports: {33 iphone6: {34 styles: {35 },36 },37 },38});39const req = require.context('../src', true, /.stories.js$/);40function loadStories() {41 req.keys().forEach(filename => req(filename));42}43configure(loadStories, module);44import '@storybook/addon-actions/register';45import '@storybook/addon-links/register';46import '@storybook/addon-notes/register';47import '@storybook/addon-knobs/register';48import '@storybook/addon

Full Screen

Using AI Code Generation

copy

Full Screen

1const renderer = new ShallowRenderer();2renderer.render(<App />);3const result = renderer.getRenderOutput();4const wrapper = mount(<App />);5console.log(wrapper.find('div').length);6const wrapper = shallow(<App />);7console.log(wrapper.find('div').length);8const wrapper = render(<App />);9console.log(wrapper.find('div').length);10const wrapper = mount(<App />);11console.log(wrapper.find('div').length);12const wrapper = shallow(<App />);13console.log(wrapper.find('div').length);14const wrapper = render(<App />);15console.log(wrapper.find('div').length);16const wrapper = renderer.create(<App />).toJSON();17console.log(wrapper.find('div').length);18const wrapper = renderer.create(<App />).toJSON();19console.log(wrapper.find('div').length);20const wrapper = renderer.create(<App />).toJSON();21console.log(wrapper.find('div').length);22const wrapper = renderer.create(<App />).toJSON();23console.log(wrapper.find('div').length);24const wrapper = renderer.create(<App />).toJSON();25console.log(wrapper.find('div').length);26const wrapper = renderer.create(<App />).toJSON();27console.log(wrapper.find('div').length);28const wrapper = renderer.create(<App />).toJSON();29console.log(wrapper.find('div').length);30const wrapper = renderer.create(<App />).toJSON();31console.log(wrapper.find('div').length);32const wrapper = renderer.create(<App />).toJSON();33console.log(wrapper.find('div').length);34const wrapper = renderer.create(<App />).toJSON();

Full Screen

Using AI Code Generation

copy

Full Screen

1import React from 'react';2import { shallowRender } from 'storybook-root';3import { expect } from 'chai';4import { spy } from 'sinon';5import MyComponent from './MyComponent';6describe('MyComponent', () => {7 it('should render the component', () => {8 const props = {9 onClick: spy(),10 };11 const component = shallowRender(<MyComponent {...props} />);12 expect(component.find('button').length).to.equal(1);13 });14});

Full Screen

Using AI Code Generation

copy

Full Screen

1import React from 'react';2import { shallowRenderer } from 'storybook-root';3import { expect } from 'chai';4import { mount } from 'enzyme';5import { Link } from 'react-router';6import { Button } from 'react-bootstrap';7import { LinkContainer } from 'react-router-bootstrap';8describe('Link', () => {9 it('should render Link', () => {10 const wrapper = shallowRenderer(<Link />);11 expect(wrapper).to.exist;12 });13 it('should render LinkContainer', () => {14 const wrapper = shallowRenderer(<LinkContainer />);15 expect(wrapper).to.exist;16 });17});18"scripts": {19}20import React from 'react';21import { shallowRenderer } from 'storybook-root';22import { expect } from 'chai';23import { mount } from 'enzyme';24import { Link } from 'react-router';25import { Button } from 'react-bootstrap';26import { LinkContainer } from 'react-router-bootstrap';27describe('Link', () => {28 it('should render Link', () => {29 const wrapper = shallowRenderer(<Link />);30 expect(wrapper).to.exist;31 });32 it('should render LinkContainer', () => {33 const wrapper = shallowRenderer(<LinkContainer />);34 expect(wrapper).to.exist;35 });36});37"scripts": {38}39import React from 'react';40import { shallowRenderer } from 'storybook-root';41import { expect } from 'chai';42import { mount } from 'enzyme';43import { Link } from 'react-router';44import { Button } from 'react-bootstrap';45import { LinkContainer } from 'react-router-bootstrap';46describe('Link', () => {47 it('should render Link', () => {48 const wrapper = shallowRenderer(<Link />);49 expect(wrapper).to.exist;50 });51 it('should render LinkContainer', () => {52 const wrapper = shallowRenderer(<LinkContainer />);53 expect(wrapper).to.exist;54 });55});

Full Screen

Using AI Code Generation

copy

Full Screen

1const renderer = require('./storybook-root').renderer;2const story = require('./storybook-root').story;3describe('Button', () => {4 it('should render correctly', () => {5 renderer.render(story);6 const result = renderer.getRenderOutput();7 expect(result.type).toBe('button');8 expect(result.props.children).toBe('Hello');9 });10});11import React from 'react';12import { shallow } from 'enzyme';13import { storiesOf } from '@storybook/react';14import { action } from '@storybook/addon-actions';15import Button from './Button';16storiesOf('Button', module)17 .add('with text', () => (18 <Button onClick={action('clicked')}>Hello Button</Button>19 .add('with some emoji', () => (20 <Button onClick={action('clicked')}>😀 😎 👍 💯</Button>21 ));22export const renderer = shallow;23export const story = <Button onClick={action('clicked')}>Hello Button</Button>;24import React from 'react';25import PropTypes from 'prop-types';26const Button = ({ onClick, children }) => (27 <button onClick={onClick}>28 {children}29);30Button.propTypes = {31};32export default Button;

Full Screen

Using AI Code Generation

copy

Full Screen

1import { shallowRenderer } from 'storybook-root';2import { Component } from 'react';3import { shallow } from 'enzyme';4const component = shallowRenderer(Component);5const wrapper = shallow(component);6import { shallowRenderer } from 'storybook-root';7import { Component } from 'react';8import { shallow } from 'enzyme';9const component = shallowRenderer(Component);10const wrapper = shallow(component);11import { shallowRenderer } from 'storybook-root';12import { Component } from 'react';13import { shallow } from 'enzyme';14const component = shallowRenderer(Component);15const wrapper = shallow(component);16import { shallowRenderer } from 'storybook-root';17import { Component } from 'react';18import { shallow } from 'enzyme';19const component = shallowRenderer(Component);20const wrapper = shallow(component);21import { shallowRenderer } from 'storybook-root';22import { Component } from 'react';23import { shallow } from 'enzyme';24const component = shallowRenderer(Component);25const wrapper = shallow(component);26import { shallowRenderer } from 'storybook-root';27import { Component } from 'react';28import { shallow } from 'enzyme';29const component = shallowRenderer(Component);30const wrapper = shallow(component);31import { shallowRenderer } from 'storybook-root';32import { Component } from 'react';33import { shallow } from 'enzyme';34const component = shallowRenderer(Component);35const wrapper = shallow(component);36import { shallowRenderer } from 'storybook-root';37import { Component } from 'react';38import { shallow } from 'enzyme';39const component = shallowRenderer(Component);40const wrapper = shallow(component);

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run storybook-root automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful