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