Best JavaScript code snippet using wpt
ReactErrorBoundaries-test.internal.js
Source:ReactErrorBoundaries-test.internal.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 */9'use strict';10let PropTypes;11let React;12let ReactDOM;13let act;14let ReactFeatureFlags;15let Scheduler;16describe('ReactErrorBoundaries', () => {17 let BrokenConstructor;18 let BrokenComponentWillMount;19 let BrokenComponentDidMount;20 let BrokenComponentWillReceiveProps;21 let BrokenComponentWillUpdate;22 let BrokenComponentDidUpdate;23 let BrokenComponentWillUnmount;24 let BrokenRenderErrorBoundary;25 let BrokenComponentWillMountErrorBoundary;26 let BrokenComponentDidMountErrorBoundary;27 let BrokenRender;28 let BrokenUseEffect;29 let BrokenUseLayoutEffect;30 let ErrorBoundary;31 let ErrorMessage;32 let NoopErrorBoundary;33 let RetryErrorBoundary;34 let Normal;35 beforeEach(() => {36 jest.useFakeTimers();37 jest.resetModules();38 PropTypes = require('prop-types');39 ReactFeatureFlags = require('shared/ReactFeatureFlags');40 ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;41 ReactDOM = require('react-dom');42 React = require('react');43 act = require('react-dom/test-utils').unstable_concurrentAct;44 Scheduler = require('scheduler');45 BrokenConstructor = class extends React.Component {46 constructor(props) {47 super(props);48 Scheduler.unstable_yieldValue('BrokenConstructor constructor [!]');49 throw new Error('Hello');50 }51 render() {52 Scheduler.unstable_yieldValue('BrokenConstructor render');53 return <div>{this.props.children}</div>;54 }55 UNSAFE_componentWillMount() {56 Scheduler.unstable_yieldValue('BrokenConstructor componentWillMount');57 }58 componentDidMount() {59 Scheduler.unstable_yieldValue('BrokenConstructor componentDidMount');60 }61 UNSAFE_componentWillReceiveProps() {62 Scheduler.unstable_yieldValue(63 'BrokenConstructor componentWillReceiveProps',64 );65 }66 UNSAFE_componentWillUpdate() {67 Scheduler.unstable_yieldValue('BrokenConstructor componentWillUpdate');68 }69 componentDidUpdate() {70 Scheduler.unstable_yieldValue('BrokenConstructor componentDidUpdate');71 }72 componentWillUnmount() {73 Scheduler.unstable_yieldValue('BrokenConstructor componentWillUnmount');74 }75 };76 BrokenComponentWillMount = class extends React.Component {77 constructor(props) {78 super(props);79 Scheduler.unstable_yieldValue('BrokenComponentWillMount constructor');80 }81 render() {82 Scheduler.unstable_yieldValue('BrokenComponentWillMount render');83 return <div>{this.props.children}</div>;84 }85 UNSAFE_componentWillMount() {86 Scheduler.unstable_yieldValue(87 'BrokenComponentWillMount componentWillMount [!]',88 );89 throw new Error('Hello');90 }91 componentDidMount() {92 Scheduler.unstable_yieldValue(93 'BrokenComponentWillMount componentDidMount',94 );95 }96 UNSAFE_componentWillReceiveProps() {97 Scheduler.unstable_yieldValue(98 'BrokenComponentWillMount componentWillReceiveProps',99 );100 }101 UNSAFE_componentWillUpdate() {102 Scheduler.unstable_yieldValue(103 'BrokenComponentWillMount componentWillUpdate',104 );105 }106 componentDidUpdate() {107 Scheduler.unstable_yieldValue(108 'BrokenComponentWillMount componentDidUpdate',109 );110 }111 componentWillUnmount() {112 Scheduler.unstable_yieldValue(113 'BrokenComponentWillMount componentWillUnmount',114 );115 }116 };117 BrokenComponentDidMount = class extends React.Component {118 constructor(props) {119 super(props);120 Scheduler.unstable_yieldValue('BrokenComponentDidMount constructor');121 }122 render() {123 Scheduler.unstable_yieldValue('BrokenComponentDidMount render');124 return <div>{this.props.children}</div>;125 }126 UNSAFE_componentWillMount() {127 Scheduler.unstable_yieldValue(128 'BrokenComponentDidMount componentWillMount',129 );130 }131 componentDidMount() {132 Scheduler.unstable_yieldValue(133 'BrokenComponentDidMount componentDidMount [!]',134 );135 throw new Error('Hello');136 }137 UNSAFE_componentWillReceiveProps() {138 Scheduler.unstable_yieldValue(139 'BrokenComponentDidMount componentWillReceiveProps',140 );141 }142 UNSAFE_componentWillUpdate() {143 Scheduler.unstable_yieldValue(144 'BrokenComponentDidMount componentWillUpdate',145 );146 }147 componentDidUpdate() {148 Scheduler.unstable_yieldValue(149 'BrokenComponentDidMount componentDidUpdate',150 );151 }152 componentWillUnmount() {153 Scheduler.unstable_yieldValue(154 'BrokenComponentDidMount componentWillUnmount',155 );156 }157 };158 BrokenComponentWillReceiveProps = class extends React.Component {159 constructor(props) {160 super(props);161 Scheduler.unstable_yieldValue(162 'BrokenComponentWillReceiveProps constructor',163 );164 }165 render() {166 Scheduler.unstable_yieldValue('BrokenComponentWillReceiveProps render');167 return <div>{this.props.children}</div>;168 }169 UNSAFE_componentWillMount() {170 Scheduler.unstable_yieldValue(171 'BrokenComponentWillReceiveProps componentWillMount',172 );173 }174 componentDidMount() {175 Scheduler.unstable_yieldValue(176 'BrokenComponentWillReceiveProps componentDidMount',177 );178 }179 UNSAFE_componentWillReceiveProps() {180 Scheduler.unstable_yieldValue(181 'BrokenComponentWillReceiveProps componentWillReceiveProps [!]',182 );183 throw new Error('Hello');184 }185 UNSAFE_componentWillUpdate() {186 Scheduler.unstable_yieldValue(187 'BrokenComponentWillReceiveProps componentWillUpdate',188 );189 }190 componentDidUpdate() {191 Scheduler.unstable_yieldValue(192 'BrokenComponentWillReceiveProps componentDidUpdate',193 );194 }195 componentWillUnmount() {196 Scheduler.unstable_yieldValue(197 'BrokenComponentWillReceiveProps componentWillUnmount',198 );199 }200 };201 BrokenComponentWillUpdate = class extends React.Component {202 constructor(props) {203 super(props);204 Scheduler.unstable_yieldValue('BrokenComponentWillUpdate constructor');205 }206 render() {207 Scheduler.unstable_yieldValue('BrokenComponentWillUpdate render');208 return <div>{this.props.children}</div>;209 }210 UNSAFE_componentWillMount() {211 Scheduler.unstable_yieldValue(212 'BrokenComponentWillUpdate componentWillMount',213 );214 }215 componentDidMount() {216 Scheduler.unstable_yieldValue(217 'BrokenComponentWillUpdate componentDidMount',218 );219 }220 UNSAFE_componentWillReceiveProps() {221 Scheduler.unstable_yieldValue(222 'BrokenComponentWillUpdate componentWillReceiveProps',223 );224 }225 UNSAFE_componentWillUpdate() {226 Scheduler.unstable_yieldValue(227 'BrokenComponentWillUpdate componentWillUpdate [!]',228 );229 throw new Error('Hello');230 }231 componentDidUpdate() {232 Scheduler.unstable_yieldValue(233 'BrokenComponentWillUpdate componentDidUpdate',234 );235 }236 componentWillUnmount() {237 Scheduler.unstable_yieldValue(238 'BrokenComponentWillUpdate componentWillUnmount',239 );240 }241 };242 BrokenComponentDidUpdate = class extends React.Component {243 static defaultProps = {244 errorText: 'Hello',245 };246 constructor(props) {247 super(props);248 Scheduler.unstable_yieldValue('BrokenComponentDidUpdate constructor');249 }250 render() {251 Scheduler.unstable_yieldValue('BrokenComponentDidUpdate render');252 return <div>{this.props.children}</div>;253 }254 UNSAFE_componentWillMount() {255 Scheduler.unstable_yieldValue(256 'BrokenComponentDidUpdate componentWillMount',257 );258 }259 componentDidMount() {260 Scheduler.unstable_yieldValue(261 'BrokenComponentDidUpdate componentDidMount',262 );263 }264 UNSAFE_componentWillReceiveProps() {265 Scheduler.unstable_yieldValue(266 'BrokenComponentDidUpdate componentWillReceiveProps',267 );268 }269 UNSAFE_componentWillUpdate() {270 Scheduler.unstable_yieldValue(271 'BrokenComponentDidUpdate componentWillUpdate',272 );273 }274 componentDidUpdate() {275 Scheduler.unstable_yieldValue(276 'BrokenComponentDidUpdate componentDidUpdate [!]',277 );278 throw new Error(this.props.errorText);279 }280 componentWillUnmount() {281 Scheduler.unstable_yieldValue(282 'BrokenComponentDidUpdate componentWillUnmount',283 );284 }285 };286 BrokenComponentWillUnmount = class extends React.Component {287 static defaultProps = {288 errorText: 'Hello',289 };290 constructor(props) {291 super(props);292 Scheduler.unstable_yieldValue('BrokenComponentWillUnmount constructor');293 }294 render() {295 Scheduler.unstable_yieldValue('BrokenComponentWillUnmount render');296 return <div>{this.props.children}</div>;297 }298 UNSAFE_componentWillMount() {299 Scheduler.unstable_yieldValue(300 'BrokenComponentWillUnmount componentWillMount',301 );302 }303 componentDidMount() {304 Scheduler.unstable_yieldValue(305 'BrokenComponentWillUnmount componentDidMount',306 );307 }308 UNSAFE_componentWillReceiveProps() {309 Scheduler.unstable_yieldValue(310 'BrokenComponentWillUnmount componentWillReceiveProps',311 );312 }313 UNSAFE_componentWillUpdate() {314 Scheduler.unstable_yieldValue(315 'BrokenComponentWillUnmount componentWillUpdate',316 );317 }318 componentDidUpdate() {319 Scheduler.unstable_yieldValue(320 'BrokenComponentWillUnmount componentDidUpdate',321 );322 }323 componentWillUnmount() {324 Scheduler.unstable_yieldValue(325 'BrokenComponentWillUnmount componentWillUnmount [!]',326 );327 throw new Error(this.props.errorText);328 }329 };330 BrokenComponentWillMountErrorBoundary = class extends React.Component {331 constructor(props) {332 super(props);333 this.state = {error: null};334 Scheduler.unstable_yieldValue(335 'BrokenComponentWillMountErrorBoundary constructor',336 );337 }338 render() {339 if (this.state.error) {340 Scheduler.unstable_yieldValue(341 'BrokenComponentWillMountErrorBoundary render error',342 );343 return <div>Caught an error: {this.state.error.message}.</div>;344 }345 Scheduler.unstable_yieldValue(346 'BrokenComponentWillMountErrorBoundary render success',347 );348 return <div>{this.props.children}</div>;349 }350 UNSAFE_componentWillMount() {351 Scheduler.unstable_yieldValue(352 'BrokenComponentWillMountErrorBoundary componentWillMount [!]',353 );354 throw new Error('Hello');355 }356 componentDidMount() {357 Scheduler.unstable_yieldValue(358 'BrokenComponentWillMountErrorBoundary componentDidMount',359 );360 }361 componentWillUnmount() {362 Scheduler.unstable_yieldValue(363 'BrokenComponentWillMountErrorBoundary componentWillUnmount',364 );365 }366 static getDerivedStateFromError(error) {367 Scheduler.unstable_yieldValue(368 'BrokenComponentWillMountErrorBoundary static getDerivedStateFromError',369 );370 return {error};371 }372 };373 BrokenComponentDidMountErrorBoundary = class extends React.Component {374 constructor(props) {375 super(props);376 this.state = {error: null};377 Scheduler.unstable_yieldValue(378 'BrokenComponentDidMountErrorBoundary constructor',379 );380 }381 render() {382 if (this.state.error) {383 Scheduler.unstable_yieldValue(384 'BrokenComponentDidMountErrorBoundary render error',385 );386 return <div>Caught an error: {this.state.error.message}.</div>;387 }388 Scheduler.unstable_yieldValue(389 'BrokenComponentDidMountErrorBoundary render success',390 );391 return <div>{this.props.children}</div>;392 }393 UNSAFE_componentWillMount() {394 Scheduler.unstable_yieldValue(395 'BrokenComponentDidMountErrorBoundary componentWillMount',396 );397 }398 componentDidMount() {399 Scheduler.unstable_yieldValue(400 'BrokenComponentDidMountErrorBoundary componentDidMount [!]',401 );402 throw new Error('Hello');403 }404 componentWillUnmount() {405 Scheduler.unstable_yieldValue(406 'BrokenComponentDidMountErrorBoundary componentWillUnmount',407 );408 }409 static getDerivedStateFromError(error) {410 Scheduler.unstable_yieldValue(411 'BrokenComponentDidMountErrorBoundary static getDerivedStateFromError',412 );413 return {error};414 }415 };416 BrokenRenderErrorBoundary = class extends React.Component {417 constructor(props) {418 super(props);419 this.state = {error: null};420 Scheduler.unstable_yieldValue('BrokenRenderErrorBoundary constructor');421 }422 render() {423 if (this.state.error) {424 Scheduler.unstable_yieldValue(425 'BrokenRenderErrorBoundary render error [!]',426 );427 throw new Error('Hello');428 }429 Scheduler.unstable_yieldValue(430 'BrokenRenderErrorBoundary render success',431 );432 return <div>{this.props.children}</div>;433 }434 UNSAFE_componentWillMount() {435 Scheduler.unstable_yieldValue(436 'BrokenRenderErrorBoundary componentWillMount',437 );438 }439 componentDidMount() {440 Scheduler.unstable_yieldValue(441 'BrokenRenderErrorBoundary componentDidMount',442 );443 }444 componentWillUnmount() {445 Scheduler.unstable_yieldValue(446 'BrokenRenderErrorBoundary componentWillUnmount',447 );448 }449 static getDerivedStateFromError(error) {450 Scheduler.unstable_yieldValue(451 'BrokenRenderErrorBoundary static getDerivedStateFromError',452 );453 return {error};454 }455 };456 BrokenRender = class extends React.Component {457 constructor(props) {458 super(props);459 Scheduler.unstable_yieldValue('BrokenRender constructor');460 }461 render() {462 Scheduler.unstable_yieldValue('BrokenRender render [!]');463 throw new Error('Hello');464 }465 UNSAFE_componentWillMount() {466 Scheduler.unstable_yieldValue('BrokenRender componentWillMount');467 }468 componentDidMount() {469 Scheduler.unstable_yieldValue('BrokenRender componentDidMount');470 }471 UNSAFE_componentWillReceiveProps() {472 Scheduler.unstable_yieldValue('BrokenRender componentWillReceiveProps');473 }474 UNSAFE_componentWillUpdate() {475 Scheduler.unstable_yieldValue('BrokenRender componentWillUpdate');476 }477 componentDidUpdate() {478 Scheduler.unstable_yieldValue('BrokenRender componentDidUpdate');479 }480 componentWillUnmount() {481 Scheduler.unstable_yieldValue('BrokenRender componentWillUnmount');482 }483 };484 BrokenUseEffect = ({children}) => {485 Scheduler.unstable_yieldValue('BrokenUseEffect render');486 React.useEffect(() => {487 Scheduler.unstable_yieldValue('BrokenUseEffect useEffect [!]');488 throw new Error('Hello');489 });490 return children;491 };492 BrokenUseLayoutEffect = ({children}) => {493 Scheduler.unstable_yieldValue('BrokenUseLayoutEffect render');494 React.useLayoutEffect(() => {495 Scheduler.unstable_yieldValue(496 'BrokenUseLayoutEffect useLayoutEffect [!]',497 );498 throw new Error('Hello');499 });500 return children;501 };502 NoopErrorBoundary = class extends React.Component {503 constructor(props) {504 super(props);505 Scheduler.unstable_yieldValue('NoopErrorBoundary constructor');506 }507 render() {508 Scheduler.unstable_yieldValue('NoopErrorBoundary render');509 return <BrokenRender />;510 }511 UNSAFE_componentWillMount() {512 Scheduler.unstable_yieldValue('NoopErrorBoundary componentWillMount');513 }514 componentDidMount() {515 Scheduler.unstable_yieldValue('NoopErrorBoundary componentDidMount');516 }517 componentWillUnmount() {518 Scheduler.unstable_yieldValue('NoopErrorBoundary componentWillUnmount');519 }520 static getDerivedStateFromError() {521 Scheduler.unstable_yieldValue(522 'NoopErrorBoundary static getDerivedStateFromError',523 );524 }525 };526 Normal = class extends React.Component {527 static defaultProps = {528 logName: 'Normal',529 };530 constructor(props) {531 super(props);532 Scheduler.unstable_yieldValue(`${this.props.logName} constructor`);533 }534 render() {535 Scheduler.unstable_yieldValue(`${this.props.logName} render`);536 return <div>{this.props.children}</div>;537 }538 UNSAFE_componentWillMount() {539 Scheduler.unstable_yieldValue(540 `${this.props.logName} componentWillMount`,541 );542 }543 componentDidMount() {544 Scheduler.unstable_yieldValue(545 `${this.props.logName} componentDidMount`,546 );547 }548 UNSAFE_componentWillReceiveProps() {549 Scheduler.unstable_yieldValue(550 `${this.props.logName} componentWillReceiveProps`,551 );552 }553 UNSAFE_componentWillUpdate() {554 Scheduler.unstable_yieldValue(555 `${this.props.logName} componentWillUpdate`,556 );557 }558 componentDidUpdate() {559 Scheduler.unstable_yieldValue(560 `${this.props.logName} componentDidUpdate`,561 );562 }563 componentWillUnmount() {564 Scheduler.unstable_yieldValue(565 `${this.props.logName} componentWillUnmount`,566 );567 }568 };569 ErrorBoundary = class extends React.Component {570 constructor(props) {571 super(props);572 this.state = {error: null};573 Scheduler.unstable_yieldValue(`${this.props.logName} constructor`);574 }575 render() {576 if (this.state.error && !this.props.forceRetry) {577 Scheduler.unstable_yieldValue(`${this.props.logName} render error`);578 return this.props.renderError(this.state.error, this.props);579 }580 Scheduler.unstable_yieldValue(`${this.props.logName} render success`);581 return <div>{this.props.children}</div>;582 }583 static getDerivedStateFromError(error) {584 Scheduler.unstable_yieldValue(585 'ErrorBoundary static getDerivedStateFromError',586 );587 return {error};588 }589 UNSAFE_componentWillMount() {590 Scheduler.unstable_yieldValue(591 `${this.props.logName} componentWillMount`,592 );593 }594 componentDidMount() {595 Scheduler.unstable_yieldValue(596 `${this.props.logName} componentDidMount`,597 );598 }599 UNSAFE_componentWillReceiveProps() {600 Scheduler.unstable_yieldValue(601 `${this.props.logName} componentWillReceiveProps`,602 );603 }604 UNSAFE_componentWillUpdate() {605 Scheduler.unstable_yieldValue(606 `${this.props.logName} componentWillUpdate`,607 );608 }609 componentDidUpdate() {610 Scheduler.unstable_yieldValue(611 `${this.props.logName} componentDidUpdate`,612 );613 }614 componentWillUnmount() {615 Scheduler.unstable_yieldValue(616 `${this.props.logName} componentWillUnmount`,617 );618 }619 };620 ErrorBoundary.defaultProps = {621 logName: 'ErrorBoundary',622 renderError(error, props) {623 return (624 <div ref={props.errorMessageRef}>625 Caught an error: {error.message}.626 </div>627 );628 },629 };630 RetryErrorBoundary = class extends React.Component {631 constructor(props) {632 super(props);633 Scheduler.unstable_yieldValue('RetryErrorBoundary constructor');634 }635 render() {636 Scheduler.unstable_yieldValue('RetryErrorBoundary render');637 return <BrokenRender />;638 }639 UNSAFE_componentWillMount() {640 Scheduler.unstable_yieldValue('RetryErrorBoundary componentWillMount');641 }642 componentDidMount() {643 Scheduler.unstable_yieldValue('RetryErrorBoundary componentDidMount');644 }645 componentWillUnmount() {646 Scheduler.unstable_yieldValue(647 'RetryErrorBoundary componentWillUnmount',648 );649 }650 static getDerivedStateFromError(error) {651 Scheduler.unstable_yieldValue(652 'RetryErrorBoundary static getDerivedStateFromError [!]',653 );654 // In Fiber, calling setState() (and failing) is treated as a rethrow.655 return {};656 }657 };658 ErrorMessage = class extends React.Component {659 constructor(props) {660 super(props);661 Scheduler.unstable_yieldValue('ErrorMessage constructor');662 }663 UNSAFE_componentWillMount() {664 Scheduler.unstable_yieldValue('ErrorMessage componentWillMount');665 }666 componentDidMount() {667 Scheduler.unstable_yieldValue('ErrorMessage componentDidMount');668 }669 componentWillUnmount() {670 Scheduler.unstable_yieldValue('ErrorMessage componentWillUnmount');671 }672 render() {673 Scheduler.unstable_yieldValue('ErrorMessage render');674 return <div>Caught an error: {this.props.message}.</div>;675 }676 };677 });678 it('does not swallow exceptions on mounting without boundaries', () => {679 let container = document.createElement('div');680 expect(() => {681 ReactDOM.render(<BrokenRender />, container);682 }).toThrow('Hello');683 container = document.createElement('div');684 expect(() => {685 ReactDOM.render(<BrokenComponentWillMount />, container);686 }).toThrow('Hello');687 container = document.createElement('div');688 expect(() => {689 ReactDOM.render(<BrokenComponentDidMount />, container);690 }).toThrow('Hello');691 });692 it('does not swallow exceptions on updating without boundaries', () => {693 let container = document.createElement('div');694 ReactDOM.render(<BrokenComponentWillUpdate />, container);695 expect(() => {696 ReactDOM.render(<BrokenComponentWillUpdate />, container);697 }).toThrow('Hello');698 container = document.createElement('div');699 ReactDOM.render(<BrokenComponentWillReceiveProps />, container);700 expect(() => {701 ReactDOM.render(<BrokenComponentWillReceiveProps />, container);702 }).toThrow('Hello');703 container = document.createElement('div');704 ReactDOM.render(<BrokenComponentDidUpdate />, container);705 expect(() => {706 ReactDOM.render(<BrokenComponentDidUpdate />, container);707 }).toThrow('Hello');708 });709 it('does not swallow exceptions on unmounting without boundaries', () => {710 const container = document.createElement('div');711 ReactDOM.render(<BrokenComponentWillUnmount />, container);712 expect(() => {713 ReactDOM.unmountComponentAtNode(container);714 }).toThrow('Hello');715 });716 it('prevents errors from leaking into other roots', () => {717 const container1 = document.createElement('div');718 const container2 = document.createElement('div');719 const container3 = document.createElement('div');720 ReactDOM.render(<span>Before 1</span>, container1);721 expect(() => {722 ReactDOM.render(<BrokenRender />, container2);723 }).toThrow('Hello');724 ReactDOM.render(725 <ErrorBoundary>726 <BrokenRender />727 </ErrorBoundary>,728 container3,729 );730 expect(container1.firstChild.textContent).toBe('Before 1');731 expect(container2.firstChild).toBe(null);732 expect(container3.firstChild.textContent).toBe('Caught an error: Hello.');733 ReactDOM.render(<span>After 1</span>, container1);734 ReactDOM.render(<span>After 2</span>, container2);735 ReactDOM.render(736 <ErrorBoundary forceRetry={true}>After 3</ErrorBoundary>,737 container3,738 );739 expect(container1.firstChild.textContent).toBe('After 1');740 expect(container2.firstChild.textContent).toBe('After 2');741 expect(container3.firstChild.textContent).toBe('After 3');742 ReactDOM.unmountComponentAtNode(container1);743 ReactDOM.unmountComponentAtNode(container2);744 ReactDOM.unmountComponentAtNode(container3);745 expect(container1.firstChild).toBe(null);746 expect(container2.firstChild).toBe(null);747 expect(container3.firstChild).toBe(null);748 });749 it('logs a single error when using error boundary', () => {750 const container = document.createElement('div');751 expect(() =>752 ReactDOM.render(753 <ErrorBoundary>754 <BrokenRender />755 </ErrorBoundary>,756 container,757 ),758 ).toErrorDev('The above error occurred in the <BrokenRender> component:', {759 logAllErrors: true,760 });761 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');762 expect(Scheduler).toHaveYielded([763 'ErrorBoundary constructor',764 'ErrorBoundary componentWillMount',765 'ErrorBoundary render success',766 'BrokenRender constructor',767 'BrokenRender componentWillMount',768 'BrokenRender render [!]',769 // Catch and render an error message770 'ErrorBoundary static getDerivedStateFromError',771 'ErrorBoundary componentWillMount',772 'ErrorBoundary render error',773 'ErrorBoundary componentDidMount',774 ]);775 ReactDOM.unmountComponentAtNode(container);776 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);777 });778 it('renders an error state if child throws in render', () => {779 const container = document.createElement('div');780 ReactDOM.render(781 <ErrorBoundary>782 <BrokenRender />783 </ErrorBoundary>,784 container,785 );786 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');787 expect(Scheduler).toHaveYielded([788 'ErrorBoundary constructor',789 'ErrorBoundary componentWillMount',790 'ErrorBoundary render success',791 'BrokenRender constructor',792 'BrokenRender componentWillMount',793 'BrokenRender render [!]',794 // Catch and render an error message795 'ErrorBoundary static getDerivedStateFromError',796 'ErrorBoundary componentWillMount',797 'ErrorBoundary render error',798 'ErrorBoundary componentDidMount',799 ]);800 ReactDOM.unmountComponentAtNode(container);801 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);802 });803 it('renders an error state if child throws in constructor', () => {804 const container = document.createElement('div');805 ReactDOM.render(806 <ErrorBoundary>807 <BrokenConstructor />808 </ErrorBoundary>,809 container,810 );811 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');812 expect(Scheduler).toHaveYielded([813 'ErrorBoundary constructor',814 'ErrorBoundary componentWillMount',815 'ErrorBoundary render success',816 'BrokenConstructor constructor [!]',817 // Catch and render an error message818 'ErrorBoundary static getDerivedStateFromError',819 'ErrorBoundary componentWillMount',820 'ErrorBoundary render error',821 'ErrorBoundary componentDidMount',822 ]);823 ReactDOM.unmountComponentAtNode(container);824 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);825 });826 it('renders an error state if child throws in componentWillMount', () => {827 const container = document.createElement('div');828 ReactDOM.render(829 <ErrorBoundary>830 <BrokenComponentWillMount />831 </ErrorBoundary>,832 container,833 );834 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');835 expect(Scheduler).toHaveYielded([836 'ErrorBoundary constructor',837 'ErrorBoundary componentWillMount',838 'ErrorBoundary render success',839 'BrokenComponentWillMount constructor',840 'BrokenComponentWillMount componentWillMount [!]',841 // Catch and render an error message842 'ErrorBoundary static getDerivedStateFromError',843 'ErrorBoundary componentWillMount',844 'ErrorBoundary render error',845 'ErrorBoundary componentDidMount',846 ]);847 ReactDOM.unmountComponentAtNode(container);848 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);849 });850 it('renders an error state if context provider throws in componentWillMount', () => {851 class BrokenComponentWillMountWithContext extends React.Component {852 static childContextTypes = {foo: PropTypes.number};853 getChildContext() {854 return {foo: 42};855 }856 render() {857 return <div>{this.props.children}</div>;858 }859 UNSAFE_componentWillMount() {860 throw new Error('Hello');861 }862 }863 const container = document.createElement('div');864 ReactDOM.render(865 <ErrorBoundary>866 <BrokenComponentWillMountWithContext />867 </ErrorBoundary>,868 container,869 );870 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');871 });872 if (!require('shared/ReactFeatureFlags').disableModulePatternComponents) {873 it('renders an error state if module-style context provider throws in componentWillMount', () => {874 function BrokenComponentWillMountWithContext() {875 return {876 getChildContext() {877 return {foo: 42};878 },879 render() {880 return <div>{this.props.children}</div>;881 },882 UNSAFE_componentWillMount() {883 throw new Error('Hello');884 },885 };886 }887 BrokenComponentWillMountWithContext.childContextTypes = {888 foo: PropTypes.number,889 };890 const container = document.createElement('div');891 expect(() =>892 ReactDOM.render(893 <ErrorBoundary>894 <BrokenComponentWillMountWithContext />895 </ErrorBoundary>,896 container,897 ),898 ).toErrorDev(899 'Warning: The <BrokenComponentWillMountWithContext /> component appears to be a function component that ' +900 'returns a class instance. ' +901 'Change BrokenComponentWillMountWithContext to a class that extends React.Component instead. ' +902 "If you can't use a class try assigning the prototype on the function as a workaround. " +903 '`BrokenComponentWillMountWithContext.prototype = React.Component.prototype`. ' +904 "Don't use an arrow function since it cannot be called with `new` by React.",905 );906 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');907 });908 }909 it('mounts the error message if mounting fails', () => {910 function renderError(error) {911 return <ErrorMessage message={error.message} />;912 }913 const container = document.createElement('div');914 ReactDOM.render(915 <ErrorBoundary renderError={renderError}>916 <BrokenRender />917 </ErrorBoundary>,918 container,919 );920 expect(Scheduler).toHaveYielded([921 'ErrorBoundary constructor',922 'ErrorBoundary componentWillMount',923 'ErrorBoundary render success',924 'BrokenRender constructor',925 'BrokenRender componentWillMount',926 'BrokenRender render [!]',927 'ErrorBoundary static getDerivedStateFromError',928 'ErrorBoundary componentWillMount',929 'ErrorBoundary render error',930 'ErrorMessage constructor',931 'ErrorMessage componentWillMount',932 'ErrorMessage render',933 'ErrorMessage componentDidMount',934 'ErrorBoundary componentDidMount',935 ]);936 ReactDOM.unmountComponentAtNode(container);937 expect(Scheduler).toHaveYielded([938 'ErrorBoundary componentWillUnmount',939 'ErrorMessage componentWillUnmount',940 ]);941 });942 it('propagates errors on retry on mounting', () => {943 const container = document.createElement('div');944 ReactDOM.render(945 <ErrorBoundary>946 <RetryErrorBoundary>947 <BrokenRender />948 </RetryErrorBoundary>949 </ErrorBoundary>,950 container,951 );952 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');953 expect(Scheduler).toHaveYielded([954 'ErrorBoundary constructor',955 'ErrorBoundary componentWillMount',956 'ErrorBoundary render success',957 'RetryErrorBoundary constructor',958 'RetryErrorBoundary componentWillMount',959 'RetryErrorBoundary render',960 'BrokenRender constructor',961 'BrokenRender componentWillMount',962 'BrokenRender render [!]',963 // Retry964 'RetryErrorBoundary static getDerivedStateFromError [!]',965 'RetryErrorBoundary componentWillMount',966 'RetryErrorBoundary render',967 'BrokenRender constructor',968 'BrokenRender componentWillMount',969 'BrokenRender render [!]',970 // This time, the error propagates to the higher boundary971 'ErrorBoundary static getDerivedStateFromError',972 'ErrorBoundary componentWillMount',973 'ErrorBoundary render error',974 'ErrorBoundary componentDidMount',975 ]);976 ReactDOM.unmountComponentAtNode(container);977 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);978 });979 it('propagates errors inside boundary during componentWillMount', () => {980 const container = document.createElement('div');981 ReactDOM.render(982 <ErrorBoundary>983 <BrokenComponentWillMountErrorBoundary />984 </ErrorBoundary>,985 container,986 );987 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');988 expect(Scheduler).toHaveYielded([989 'ErrorBoundary constructor',990 'ErrorBoundary componentWillMount',991 'ErrorBoundary render success',992 'BrokenComponentWillMountErrorBoundary constructor',993 'BrokenComponentWillMountErrorBoundary componentWillMount [!]',994 // The error propagates to the higher boundary995 'ErrorBoundary static getDerivedStateFromError',996 'ErrorBoundary componentWillMount',997 'ErrorBoundary render error',998 'ErrorBoundary componentDidMount',999 ]);1000 ReactDOM.unmountComponentAtNode(container);1001 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1002 });1003 it('propagates errors inside boundary while rendering error state', () => {1004 const container = document.createElement('div');1005 ReactDOM.render(1006 <ErrorBoundary>1007 <BrokenRenderErrorBoundary>1008 <BrokenRender />1009 </BrokenRenderErrorBoundary>1010 </ErrorBoundary>,1011 container,1012 );1013 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');1014 expect(Scheduler).toHaveYielded([1015 'ErrorBoundary constructor',1016 'ErrorBoundary componentWillMount',1017 'ErrorBoundary render success',1018 'BrokenRenderErrorBoundary constructor',1019 'BrokenRenderErrorBoundary componentWillMount',1020 'BrokenRenderErrorBoundary render success',1021 'BrokenRender constructor',1022 'BrokenRender componentWillMount',1023 'BrokenRender render [!]',1024 // Attempt to handle the error1025 'BrokenRenderErrorBoundary static getDerivedStateFromError',1026 'BrokenRenderErrorBoundary componentWillMount',1027 'BrokenRenderErrorBoundary render error [!]',1028 // Attempt to handle the error again1029 'ErrorBoundary static getDerivedStateFromError',1030 'ErrorBoundary componentWillMount',1031 'ErrorBoundary render error',1032 'ErrorBoundary componentDidMount',1033 ]);1034 ReactDOM.unmountComponentAtNode(container);1035 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1036 });1037 it('does not call componentWillUnmount when aborting initial mount', () => {1038 const container = document.createElement('div');1039 ReactDOM.render(1040 <ErrorBoundary>1041 <Normal />1042 <BrokenRender />1043 <Normal />1044 </ErrorBoundary>,1045 container,1046 );1047 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');1048 expect(Scheduler).toHaveYielded([1049 'ErrorBoundary constructor',1050 'ErrorBoundary componentWillMount',1051 'ErrorBoundary render success',1052 // Render first child1053 'Normal constructor',1054 'Normal componentWillMount',1055 'Normal render',1056 // Render second child (it throws)1057 'BrokenRender constructor',1058 'BrokenRender componentWillMount',1059 'BrokenRender render [!]',1060 // Render third child, even though an earlier sibling threw.1061 'Normal constructor',1062 'Normal componentWillMount',1063 'Normal render',1064 // Handle the error1065 'ErrorBoundary static getDerivedStateFromError',1066 'ErrorBoundary componentWillMount',1067 'ErrorBoundary render error',1068 'ErrorBoundary componentDidMount',1069 ]);1070 ReactDOM.unmountComponentAtNode(container);1071 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1072 });1073 it('resets callback refs if mounting aborts', () => {1074 function childRef(x) {1075 Scheduler.unstable_yieldValue('Child ref is set to ' + x);1076 }1077 function errorMessageRef(x) {1078 Scheduler.unstable_yieldValue('Error message ref is set to ' + x);1079 }1080 const container = document.createElement('div');1081 ReactDOM.render(1082 <ErrorBoundary errorMessageRef={errorMessageRef}>1083 <div ref={childRef} />1084 <BrokenRender />1085 </ErrorBoundary>,1086 container,1087 );1088 expect(container.textContent).toBe('Caught an error: Hello.');1089 expect(Scheduler).toHaveYielded([1090 'ErrorBoundary constructor',1091 'ErrorBoundary componentWillMount',1092 'ErrorBoundary render success',1093 'BrokenRender constructor',1094 'BrokenRender componentWillMount',1095 'BrokenRender render [!]',1096 // Handle the error1097 'ErrorBoundary static getDerivedStateFromError',1098 'ErrorBoundary componentWillMount',1099 'ErrorBoundary render error',1100 'Error message ref is set to [object HTMLDivElement]',1101 'ErrorBoundary componentDidMount',1102 ]);1103 ReactDOM.unmountComponentAtNode(container);1104 expect(Scheduler).toHaveYielded([1105 'ErrorBoundary componentWillUnmount',1106 'Error message ref is set to null',1107 ]);1108 });1109 it('resets object refs if mounting aborts', () => {1110 const childRef = React.createRef();1111 const errorMessageRef = React.createRef();1112 const container = document.createElement('div');1113 ReactDOM.render(1114 <ErrorBoundary errorMessageRef={errorMessageRef}>1115 <div ref={childRef} />1116 <BrokenRender />1117 </ErrorBoundary>,1118 container,1119 );1120 expect(container.textContent).toBe('Caught an error: Hello.');1121 expect(Scheduler).toHaveYielded([1122 'ErrorBoundary constructor',1123 'ErrorBoundary componentWillMount',1124 'ErrorBoundary render success',1125 'BrokenRender constructor',1126 'BrokenRender componentWillMount',1127 'BrokenRender render [!]',1128 // Handle the error1129 'ErrorBoundary static getDerivedStateFromError',1130 'ErrorBoundary componentWillMount',1131 'ErrorBoundary render error',1132 'ErrorBoundary componentDidMount',1133 ]);1134 expect(errorMessageRef.current.toString()).toEqual(1135 '[object HTMLDivElement]',1136 );1137 ReactDOM.unmountComponentAtNode(container);1138 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1139 expect(errorMessageRef.current).toEqual(null);1140 });1141 it('successfully mounts if no error occurs', () => {1142 const container = document.createElement('div');1143 ReactDOM.render(1144 <ErrorBoundary>1145 <div>Mounted successfully.</div>1146 </ErrorBoundary>,1147 container,1148 );1149 expect(container.firstChild.textContent).toBe('Mounted successfully.');1150 expect(Scheduler).toHaveYielded([1151 'ErrorBoundary constructor',1152 'ErrorBoundary componentWillMount',1153 'ErrorBoundary render success',1154 'ErrorBoundary componentDidMount',1155 ]);1156 ReactDOM.unmountComponentAtNode(container);1157 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1158 });1159 it('catches if child throws in constructor during update', () => {1160 const container = document.createElement('div');1161 ReactDOM.render(1162 <ErrorBoundary>1163 <Normal />1164 </ErrorBoundary>,1165 container,1166 );1167 Scheduler.unstable_clearYields();1168 ReactDOM.render(1169 <ErrorBoundary>1170 <Normal />1171 <Normal logName="Normal2" />1172 <BrokenConstructor />1173 </ErrorBoundary>,1174 container,1175 );1176 expect(container.textContent).toBe('Caught an error: Hello.');1177 expect(Scheduler).toHaveYielded([1178 'ErrorBoundary componentWillReceiveProps',1179 'ErrorBoundary componentWillUpdate',1180 'ErrorBoundary render success',1181 'Normal componentWillReceiveProps',1182 'Normal componentWillUpdate',1183 'Normal render',1184 // Normal2 will attempt to mount:1185 'Normal2 constructor',1186 'Normal2 componentWillMount',1187 'Normal2 render',1188 // BrokenConstructor will abort rendering:1189 'BrokenConstructor constructor [!]',1190 // Handle the error1191 'ErrorBoundary static getDerivedStateFromError',1192 // Render the error message1193 'ErrorBoundary componentWillUpdate',1194 'ErrorBoundary render error',1195 'Normal componentWillUnmount',1196 'ErrorBoundary componentDidUpdate',1197 ]);1198 ReactDOM.unmountComponentAtNode(container);1199 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1200 });1201 it('catches if child throws in componentWillMount during update', () => {1202 const container = document.createElement('div');1203 ReactDOM.render(1204 <ErrorBoundary>1205 <Normal />1206 </ErrorBoundary>,1207 container,1208 );1209 Scheduler.unstable_clearYields();1210 ReactDOM.render(1211 <ErrorBoundary>1212 <Normal />1213 <Normal logName="Normal2" />1214 <BrokenComponentWillMount />1215 </ErrorBoundary>,1216 container,1217 );1218 expect(container.textContent).toBe('Caught an error: Hello.');1219 expect(Scheduler).toHaveYielded([1220 'ErrorBoundary componentWillReceiveProps',1221 'ErrorBoundary componentWillUpdate',1222 'ErrorBoundary render success',1223 'Normal componentWillReceiveProps',1224 'Normal componentWillUpdate',1225 'Normal render',1226 // Normal2 will attempt to mount:1227 'Normal2 constructor',1228 'Normal2 componentWillMount',1229 'Normal2 render',1230 // BrokenComponentWillMount will abort rendering:1231 'BrokenComponentWillMount constructor',1232 'BrokenComponentWillMount componentWillMount [!]',1233 // Handle the error1234 'ErrorBoundary static getDerivedStateFromError',1235 // Render the error message1236 'ErrorBoundary componentWillUpdate',1237 'ErrorBoundary render error',1238 'Normal componentWillUnmount',1239 'ErrorBoundary componentDidUpdate',1240 ]);1241 ReactDOM.unmountComponentAtNode(container);1242 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1243 });1244 it('catches if child throws in componentWillReceiveProps during update', () => {1245 const container = document.createElement('div');1246 ReactDOM.render(1247 <ErrorBoundary>1248 <Normal />1249 <BrokenComponentWillReceiveProps />1250 </ErrorBoundary>,1251 container,1252 );1253 Scheduler.unstable_clearYields();1254 ReactDOM.render(1255 <ErrorBoundary>1256 <Normal />1257 <BrokenComponentWillReceiveProps />1258 </ErrorBoundary>,1259 container,1260 );1261 expect(container.textContent).toBe('Caught an error: Hello.');1262 expect(Scheduler).toHaveYielded([1263 'ErrorBoundary componentWillReceiveProps',1264 'ErrorBoundary componentWillUpdate',1265 'ErrorBoundary render success',1266 'Normal componentWillReceiveProps',1267 'Normal componentWillUpdate',1268 'Normal render',1269 // BrokenComponentWillReceiveProps will abort rendering:1270 'BrokenComponentWillReceiveProps componentWillReceiveProps [!]',1271 // Handle the error1272 'ErrorBoundary static getDerivedStateFromError',1273 // Render the error message1274 'ErrorBoundary componentWillUpdate',1275 'ErrorBoundary render error',1276 'Normal componentWillUnmount',1277 'BrokenComponentWillReceiveProps componentWillUnmount',1278 'ErrorBoundary componentDidUpdate',1279 ]);1280 ReactDOM.unmountComponentAtNode(container);1281 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1282 });1283 it('catches if child throws in componentWillUpdate during update', () => {1284 const container = document.createElement('div');1285 ReactDOM.render(1286 <ErrorBoundary>1287 <Normal />1288 <BrokenComponentWillUpdate />1289 </ErrorBoundary>,1290 container,1291 );1292 Scheduler.unstable_clearYields();1293 ReactDOM.render(1294 <ErrorBoundary>1295 <Normal />1296 <BrokenComponentWillUpdate />1297 </ErrorBoundary>,1298 container,1299 );1300 expect(container.textContent).toBe('Caught an error: Hello.');1301 expect(Scheduler).toHaveYielded([1302 'ErrorBoundary componentWillReceiveProps',1303 'ErrorBoundary componentWillUpdate',1304 'ErrorBoundary render success',1305 'Normal componentWillReceiveProps',1306 'Normal componentWillUpdate',1307 'Normal render',1308 // BrokenComponentWillUpdate will abort rendering:1309 'BrokenComponentWillUpdate componentWillReceiveProps',1310 'BrokenComponentWillUpdate componentWillUpdate [!]',1311 // Handle the error1312 'ErrorBoundary static getDerivedStateFromError',1313 'ErrorBoundary componentWillUpdate',1314 'ErrorBoundary render error',1315 'Normal componentWillUnmount',1316 'BrokenComponentWillUpdate componentWillUnmount',1317 'ErrorBoundary componentDidUpdate',1318 ]);1319 ReactDOM.unmountComponentAtNode(container);1320 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1321 });1322 it('catches if child throws in render during update', () => {1323 const container = document.createElement('div');1324 ReactDOM.render(1325 <ErrorBoundary>1326 <Normal />1327 </ErrorBoundary>,1328 container,1329 );1330 Scheduler.unstable_clearYields();1331 ReactDOM.render(1332 <ErrorBoundary>1333 <Normal />1334 <Normal logName="Normal2" />1335 <BrokenRender />1336 </ErrorBoundary>,1337 container,1338 );1339 expect(container.textContent).toBe('Caught an error: Hello.');1340 expect(Scheduler).toHaveYielded([1341 'ErrorBoundary componentWillReceiveProps',1342 'ErrorBoundary componentWillUpdate',1343 'ErrorBoundary render success',1344 'Normal componentWillReceiveProps',1345 'Normal componentWillUpdate',1346 'Normal render',1347 // Normal2 will attempt to mount:1348 'Normal2 constructor',1349 'Normal2 componentWillMount',1350 'Normal2 render',1351 // BrokenRender will abort rendering:1352 'BrokenRender constructor',1353 'BrokenRender componentWillMount',1354 'BrokenRender render [!]',1355 // Handle the error1356 'ErrorBoundary static getDerivedStateFromError',1357 'ErrorBoundary componentWillUpdate',1358 'ErrorBoundary render error',1359 'Normal componentWillUnmount',1360 'ErrorBoundary componentDidUpdate',1361 ]);1362 ReactDOM.unmountComponentAtNode(container);1363 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1364 });1365 it('keeps refs up-to-date during updates', () => {1366 function child1Ref(x) {1367 Scheduler.unstable_yieldValue('Child1 ref is set to ' + x);1368 }1369 function child2Ref(x) {1370 Scheduler.unstable_yieldValue('Child2 ref is set to ' + x);1371 }1372 function errorMessageRef(x) {1373 Scheduler.unstable_yieldValue('Error message ref is set to ' + x);1374 }1375 const container = document.createElement('div');1376 ReactDOM.render(1377 <ErrorBoundary errorMessageRef={errorMessageRef}>1378 <div ref={child1Ref} />1379 </ErrorBoundary>,1380 container,1381 );1382 expect(Scheduler).toHaveYielded([1383 'ErrorBoundary constructor',1384 'ErrorBoundary componentWillMount',1385 'ErrorBoundary render success',1386 'Child1 ref is set to [object HTMLDivElement]',1387 'ErrorBoundary componentDidMount',1388 ]);1389 ReactDOM.render(1390 <ErrorBoundary errorMessageRef={errorMessageRef}>1391 <div ref={child1Ref} />1392 <div ref={child2Ref} />1393 <BrokenRender />1394 </ErrorBoundary>,1395 container,1396 );1397 expect(container.textContent).toBe('Caught an error: Hello.');1398 expect(Scheduler).toHaveYielded([1399 'ErrorBoundary componentWillReceiveProps',1400 'ErrorBoundary componentWillUpdate',1401 'ErrorBoundary render success',1402 // BrokenRender will abort rendering:1403 'BrokenRender constructor',1404 'BrokenRender componentWillMount',1405 'BrokenRender render [!]',1406 // Handle the error1407 'ErrorBoundary static getDerivedStateFromError',1408 'ErrorBoundary componentWillUpdate',1409 'ErrorBoundary render error',1410 // Update Child1 ref since Child1 has been unmounted1411 // Child2 ref is never set because its mounting aborted1412 'Child1 ref is set to null',1413 'Error message ref is set to [object HTMLDivElement]',1414 'ErrorBoundary componentDidUpdate',1415 ]);1416 ReactDOM.unmountComponentAtNode(container);1417 expect(Scheduler).toHaveYielded([1418 'ErrorBoundary componentWillUnmount',1419 'Error message ref is set to null',1420 ]);1421 });1422 it('recovers from componentWillUnmount errors on update', () => {1423 const container = document.createElement('div');1424 ReactDOM.render(1425 <ErrorBoundary>1426 <BrokenComponentWillUnmount />1427 <BrokenComponentWillUnmount />1428 <Normal />1429 </ErrorBoundary>,1430 container,1431 );1432 Scheduler.unstable_clearYields();1433 ReactDOM.render(1434 <ErrorBoundary>1435 <BrokenComponentWillUnmount />1436 </ErrorBoundary>,1437 container,1438 );1439 expect(container.textContent).toBe('Caught an error: Hello.');1440 expect(Scheduler).toHaveYielded([1441 'ErrorBoundary componentWillReceiveProps',1442 'ErrorBoundary componentWillUpdate',1443 'ErrorBoundary render success',1444 // Update existing child:1445 'BrokenComponentWillUnmount componentWillReceiveProps',1446 'BrokenComponentWillUnmount componentWillUpdate',1447 'BrokenComponentWillUnmount render',1448 // Unmounting throws:1449 'BrokenComponentWillUnmount componentWillUnmount [!]',1450 // Fiber proceeds with lifecycles despite errors1451 'Normal componentWillUnmount',1452 // The components have updated in this phase1453 'BrokenComponentWillUnmount componentDidUpdate',1454 'ErrorBoundary componentDidUpdate',1455 // The initial render was aborted, so1456 // Fiber retries from the root.1457 'ErrorBoundary static getDerivedStateFromError',1458 'ErrorBoundary componentWillUpdate',1459 'ErrorBoundary render error',1460 'BrokenComponentWillUnmount componentWillUnmount [!]',1461 'ErrorBoundary componentDidUpdate',1462 // The second willUnmount error should be captured and logged, too.1463 'ErrorBoundary static getDerivedStateFromError',1464 'ErrorBoundary componentWillUpdate',1465 // Render an error now (stack will do it later)1466 'ErrorBoundary render error',1467 // Attempt to unmount previous child:1468 // Done1469 'ErrorBoundary componentDidUpdate',1470 ]);1471 ReactDOM.unmountComponentAtNode(container);1472 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1473 });1474 it('recovers from nested componentWillUnmount errors on update', () => {1475 const container = document.createElement('div');1476 ReactDOM.render(1477 <ErrorBoundary>1478 <Normal>1479 <BrokenComponentWillUnmount />1480 </Normal>1481 <BrokenComponentWillUnmount />1482 </ErrorBoundary>,1483 container,1484 );1485 Scheduler.unstable_clearYields();1486 ReactDOM.render(1487 <ErrorBoundary>1488 <Normal>1489 <BrokenComponentWillUnmount />1490 </Normal>1491 </ErrorBoundary>,1492 container,1493 );1494 expect(container.textContent).toBe('Caught an error: Hello.');1495 expect(Scheduler).toHaveYielded([1496 'ErrorBoundary componentWillReceiveProps',1497 'ErrorBoundary componentWillUpdate',1498 'ErrorBoundary render success',1499 // Update existing children:1500 'Normal componentWillReceiveProps',1501 'Normal componentWillUpdate',1502 'Normal render',1503 'BrokenComponentWillUnmount componentWillReceiveProps',1504 'BrokenComponentWillUnmount componentWillUpdate',1505 'BrokenComponentWillUnmount render',1506 // Unmounting throws:1507 'BrokenComponentWillUnmount componentWillUnmount [!]',1508 // Fiber proceeds with lifecycles despite errors1509 'BrokenComponentWillUnmount componentDidUpdate',1510 'Normal componentDidUpdate',1511 'ErrorBoundary componentDidUpdate',1512 // Now that commit phase is done, Fiber handles errors1513 'ErrorBoundary static getDerivedStateFromError',1514 'ErrorBoundary componentWillUpdate',1515 'ErrorBoundary render error',1516 'Normal componentWillUnmount',1517 'BrokenComponentWillUnmount componentWillUnmount [!]',1518 'ErrorBoundary componentDidUpdate',1519 // The second willUnmount error should be captured and logged, too.1520 'ErrorBoundary static getDerivedStateFromError',1521 'ErrorBoundary componentWillUpdate',1522 // Render an error now (stack will do it later)1523 'ErrorBoundary render error',1524 // Done1525 'ErrorBoundary componentDidUpdate',1526 ]);1527 ReactDOM.unmountComponentAtNode(container);1528 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1529 });1530 it('picks the right boundary when handling unmounting errors', () => {1531 function renderInnerError(error) {1532 return <div>Caught an inner error: {error.message}.</div>;1533 }1534 function renderOuterError(error) {1535 return <div>Caught an outer error: {error.message}.</div>;1536 }1537 const container = document.createElement('div');1538 ReactDOM.render(1539 <ErrorBoundary1540 logName="OuterErrorBoundary"1541 renderError={renderOuterError}>1542 <ErrorBoundary1543 logName="InnerErrorBoundary"1544 renderError={renderInnerError}>1545 <BrokenComponentWillUnmount />1546 </ErrorBoundary>1547 </ErrorBoundary>,1548 container,1549 );1550 Scheduler.unstable_clearYields();1551 ReactDOM.render(1552 <ErrorBoundary1553 logName="OuterErrorBoundary"1554 renderError={renderOuterError}>1555 <ErrorBoundary1556 logName="InnerErrorBoundary"1557 renderError={renderInnerError}1558 />1559 </ErrorBoundary>,1560 container,1561 );1562 expect(container.textContent).toBe('Caught an inner error: Hello.');1563 expect(Scheduler).toHaveYielded([1564 // Update outer boundary1565 'OuterErrorBoundary componentWillReceiveProps',1566 'OuterErrorBoundary componentWillUpdate',1567 'OuterErrorBoundary render success',1568 // Update inner boundary1569 'InnerErrorBoundary componentWillReceiveProps',1570 'InnerErrorBoundary componentWillUpdate',1571 'InnerErrorBoundary render success',1572 // Try unmounting child1573 'BrokenComponentWillUnmount componentWillUnmount [!]',1574 // Now that commit phase is done, Fiber handles errors1575 // Only inner boundary receives the error:1576 'InnerErrorBoundary componentDidUpdate',1577 'OuterErrorBoundary componentDidUpdate',1578 'ErrorBoundary static getDerivedStateFromError',1579 'InnerErrorBoundary componentWillUpdate',1580 // Render an error now1581 'InnerErrorBoundary render error',1582 // In Fiber, this was a local update to the1583 // inner boundary so only its hook fires1584 'InnerErrorBoundary componentDidUpdate',1585 ]);1586 ReactDOM.unmountComponentAtNode(container);1587 expect(Scheduler).toHaveYielded([1588 'OuterErrorBoundary componentWillUnmount',1589 'InnerErrorBoundary componentWillUnmount',1590 ]);1591 });1592 it('can recover from error state', () => {1593 const container = document.createElement('div');1594 ReactDOM.render(1595 <ErrorBoundary>1596 <BrokenRender />1597 </ErrorBoundary>,1598 container,1599 );1600 ReactDOM.render(1601 <ErrorBoundary>1602 <Normal />1603 </ErrorBoundary>,1604 container,1605 );1606 // Error boundary doesn't retry by itself:1607 expect(container.textContent).toBe('Caught an error: Hello.');1608 // Force the success path:1609 Scheduler.unstable_clearYields();1610 ReactDOM.render(1611 <ErrorBoundary forceRetry={true}>1612 <Normal />1613 </ErrorBoundary>,1614 container,1615 );1616 expect(container.textContent).not.toContain('Caught an error');1617 expect(Scheduler).toHaveYielded([1618 'ErrorBoundary componentWillReceiveProps',1619 'ErrorBoundary componentWillUpdate',1620 'ErrorBoundary render success',1621 // Mount children:1622 'Normal constructor',1623 'Normal componentWillMount',1624 'Normal render',1625 // Finalize updates:1626 'Normal componentDidMount',1627 'ErrorBoundary componentDidUpdate',1628 ]);1629 ReactDOM.unmountComponentAtNode(container);1630 expect(Scheduler).toHaveYielded([1631 'ErrorBoundary componentWillUnmount',1632 'Normal componentWillUnmount',1633 ]);1634 });1635 it('can update multiple times in error state', () => {1636 const container = document.createElement('div');1637 ReactDOM.render(1638 <ErrorBoundary>1639 <BrokenRender />1640 </ErrorBoundary>,1641 container,1642 );1643 expect(container.textContent).toBe('Caught an error: Hello.');1644 ReactDOM.render(1645 <ErrorBoundary>1646 <BrokenRender />1647 </ErrorBoundary>,1648 container,1649 );1650 expect(container.textContent).toBe('Caught an error: Hello.');1651 ReactDOM.render(<div>Other screen</div>, container);1652 expect(container.textContent).toBe('Other screen');1653 ReactDOM.unmountComponentAtNode(container);1654 });1655 it("doesn't get into inconsistent state during removals", () => {1656 const container = document.createElement('div');1657 ReactDOM.render(1658 <ErrorBoundary>1659 <Normal />1660 <BrokenComponentWillUnmount />1661 <Normal />1662 </ErrorBoundary>,1663 container,1664 );1665 ReactDOM.render(<ErrorBoundary />, container);1666 expect(container.textContent).toBe('Caught an error: Hello.');1667 Scheduler.unstable_clearYields();1668 ReactDOM.unmountComponentAtNode(container);1669 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1670 });1671 it("doesn't get into inconsistent state during additions", () => {1672 const container = document.createElement('div');1673 ReactDOM.render(<ErrorBoundary />, container);1674 ReactDOM.render(1675 <ErrorBoundary>1676 <Normal />1677 <BrokenRender />1678 <Normal />1679 </ErrorBoundary>,1680 container,1681 );1682 expect(container.textContent).toBe('Caught an error: Hello.');1683 Scheduler.unstable_clearYields();1684 ReactDOM.unmountComponentAtNode(container);1685 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1686 });1687 it("doesn't get into inconsistent state during reorders", () => {1688 function getAMixOfNormalAndBrokenRenderElements() {1689 const elements = [];1690 for (let i = 0; i < 100; i++) {1691 elements.push(<Normal key={i} />);1692 }1693 elements.push(<MaybeBrokenRender key={100} />);1694 let currentIndex = elements.length;1695 while (0 !== currentIndex) {1696 const randomIndex = Math.floor(Math.random() * currentIndex);1697 currentIndex -= 1;1698 const temporaryValue = elements[currentIndex];1699 elements[currentIndex] = elements[randomIndex];1700 elements[randomIndex] = temporaryValue;1701 }1702 return elements;1703 }1704 class MaybeBrokenRender extends React.Component {1705 render() {1706 if (fail) {1707 throw new Error('Hello');1708 }1709 return <div>{this.props.children}</div>;1710 }1711 }1712 let fail = false;1713 const container = document.createElement('div');1714 ReactDOM.render(1715 <ErrorBoundary>{getAMixOfNormalAndBrokenRenderElements()}</ErrorBoundary>,1716 container,1717 );1718 expect(container.textContent).not.toContain('Caught an error');1719 fail = true;1720 ReactDOM.render(1721 <ErrorBoundary>{getAMixOfNormalAndBrokenRenderElements()}</ErrorBoundary>,1722 container,1723 );1724 expect(container.textContent).toBe('Caught an error: Hello.');1725 Scheduler.unstable_clearYields();1726 ReactDOM.unmountComponentAtNode(container);1727 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1728 });1729 it('catches errors originating downstream', () => {1730 let fail = false;1731 class Stateful extends React.Component {1732 state = {shouldThrow: false};1733 render() {1734 if (fail) {1735 Scheduler.unstable_yieldValue('Stateful render [!]');1736 throw new Error('Hello');1737 }1738 return <div>{this.props.children}</div>;1739 }1740 }1741 let statefulInst;1742 const container = document.createElement('div');1743 ReactDOM.render(1744 <ErrorBoundary>1745 <Stateful ref={inst => (statefulInst = inst)} />1746 </ErrorBoundary>,1747 container,1748 );1749 Scheduler.unstable_clearYields();1750 expect(() => {1751 fail = true;1752 statefulInst.forceUpdate();1753 }).not.toThrow();1754 expect(Scheduler).toHaveYielded([1755 'Stateful render [!]',1756 'ErrorBoundary static getDerivedStateFromError',1757 'ErrorBoundary componentWillUpdate',1758 'ErrorBoundary render error',1759 'ErrorBoundary componentDidUpdate',1760 ]);1761 ReactDOM.unmountComponentAtNode(container);1762 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1763 });1764 it('catches errors in componentDidMount', () => {1765 const container = document.createElement('div');1766 ReactDOM.render(1767 <ErrorBoundary>1768 <BrokenComponentWillUnmount>1769 <Normal />1770 </BrokenComponentWillUnmount>1771 <BrokenComponentDidMount />1772 <Normal logName="LastChild" />1773 </ErrorBoundary>,1774 container,1775 );1776 expect(Scheduler).toHaveYielded([1777 'ErrorBoundary constructor',1778 'ErrorBoundary componentWillMount',1779 'ErrorBoundary render success',1780 'BrokenComponentWillUnmount constructor',1781 'BrokenComponentWillUnmount componentWillMount',1782 'BrokenComponentWillUnmount render',1783 'Normal constructor',1784 'Normal componentWillMount',1785 'Normal render',1786 'BrokenComponentDidMount constructor',1787 'BrokenComponentDidMount componentWillMount',1788 'BrokenComponentDidMount render',1789 'LastChild constructor',1790 'LastChild componentWillMount',1791 'LastChild render',1792 // Start flushing didMount queue1793 'Normal componentDidMount',1794 'BrokenComponentWillUnmount componentDidMount',1795 'BrokenComponentDidMount componentDidMount [!]',1796 // Continue despite the error1797 'LastChild componentDidMount',1798 // Now we are ready to handle the error1799 'ErrorBoundary componentDidMount',1800 'ErrorBoundary static getDerivedStateFromError',1801 'ErrorBoundary componentWillUpdate',1802 'ErrorBoundary render error',1803 // Safely unmount every child1804 'BrokenComponentWillUnmount componentWillUnmount [!]',1805 // Continue unmounting safely despite any errors1806 'Normal componentWillUnmount',1807 'BrokenComponentDidMount componentWillUnmount',1808 'LastChild componentWillUnmount',1809 // The willUnmount error should be captured and logged, too.1810 'ErrorBoundary componentDidUpdate',1811 'ErrorBoundary static getDerivedStateFromError',1812 'ErrorBoundary componentWillUpdate',1813 'ErrorBoundary render error',1814 // The update has finished1815 'ErrorBoundary componentDidUpdate',1816 ]);1817 ReactDOM.unmountComponentAtNode(container);1818 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1819 });1820 it('catches errors in componentDidUpdate', () => {1821 const container = document.createElement('div');1822 ReactDOM.render(1823 <ErrorBoundary>1824 <BrokenComponentDidUpdate />1825 </ErrorBoundary>,1826 container,1827 );1828 Scheduler.unstable_clearYields();1829 ReactDOM.render(1830 <ErrorBoundary>1831 <BrokenComponentDidUpdate />1832 </ErrorBoundary>,1833 container,1834 );1835 expect(Scheduler).toHaveYielded([1836 'ErrorBoundary componentWillReceiveProps',1837 'ErrorBoundary componentWillUpdate',1838 'ErrorBoundary render success',1839 'BrokenComponentDidUpdate componentWillReceiveProps',1840 'BrokenComponentDidUpdate componentWillUpdate',1841 'BrokenComponentDidUpdate render',1842 // All lifecycles run1843 'BrokenComponentDidUpdate componentDidUpdate [!]',1844 'ErrorBoundary componentDidUpdate',1845 // Then, error is handled1846 'ErrorBoundary static getDerivedStateFromError',1847 'ErrorBoundary componentWillUpdate',1848 'ErrorBoundary render error',1849 'BrokenComponentDidUpdate componentWillUnmount',1850 'ErrorBoundary componentDidUpdate',1851 ]);1852 ReactDOM.unmountComponentAtNode(container);1853 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1854 });1855 it('catches errors in useEffect', () => {1856 const container = document.createElement('div');1857 act(() => {1858 ReactDOM.render(1859 <ErrorBoundary>1860 <BrokenUseEffect>Initial value</BrokenUseEffect>1861 </ErrorBoundary>,1862 container,1863 );1864 expect(Scheduler).toHaveYielded([1865 'ErrorBoundary constructor',1866 'ErrorBoundary componentWillMount',1867 'ErrorBoundary render success',1868 'BrokenUseEffect render',1869 'ErrorBoundary componentDidMount',1870 ]);1871 expect(container.firstChild.textContent).toBe('Initial value');1872 Scheduler.unstable_clearYields();1873 });1874 // verify flushed passive effects and handle the error1875 expect(Scheduler).toHaveYielded([1876 'BrokenUseEffect useEffect [!]',1877 // Handle the error1878 'ErrorBoundary static getDerivedStateFromError',1879 'ErrorBoundary componentWillUpdate',1880 'ErrorBoundary render error',1881 'ErrorBoundary componentDidUpdate',1882 ]);1883 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');1884 });1885 it('catches errors in useLayoutEffect', () => {1886 const container = document.createElement('div');1887 ReactDOM.render(1888 <ErrorBoundary>1889 <BrokenUseLayoutEffect>Initial value</BrokenUseLayoutEffect>1890 </ErrorBoundary>,1891 container,1892 );1893 expect(Scheduler).toHaveYielded([1894 'ErrorBoundary constructor',1895 'ErrorBoundary componentWillMount',1896 'ErrorBoundary render success',1897 'BrokenUseLayoutEffect render',1898 'BrokenUseLayoutEffect useLayoutEffect [!]',1899 // Fiber proceeds with the hooks1900 'ErrorBoundary componentDidMount',1901 // The error propagates to the higher boundary1902 'ErrorBoundary static getDerivedStateFromError',1903 // Fiber retries from the root1904 'ErrorBoundary componentWillUpdate',1905 'ErrorBoundary render error',1906 'ErrorBoundary componentDidUpdate',1907 ]);1908 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');1909 });1910 it('propagates errors inside boundary during componentDidMount', () => {1911 const container = document.createElement('div');1912 ReactDOM.render(1913 <ErrorBoundary>1914 <BrokenComponentDidMountErrorBoundary1915 renderError={error => (1916 <div>We should never catch our own error: {error.message}.</div>1917 )}1918 />1919 </ErrorBoundary>,1920 container,1921 );1922 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');1923 expect(Scheduler).toHaveYielded([1924 'ErrorBoundary constructor',1925 'ErrorBoundary componentWillMount',1926 'ErrorBoundary render success',1927 'BrokenComponentDidMountErrorBoundary constructor',1928 'BrokenComponentDidMountErrorBoundary componentWillMount',1929 'BrokenComponentDidMountErrorBoundary render success',1930 'BrokenComponentDidMountErrorBoundary componentDidMount [!]',1931 // Fiber proceeds with the hooks1932 'ErrorBoundary componentDidMount',1933 // The error propagates to the higher boundary1934 'ErrorBoundary static getDerivedStateFromError',1935 // Fiber retries from the root1936 'ErrorBoundary componentWillUpdate',1937 'ErrorBoundary render error',1938 'BrokenComponentDidMountErrorBoundary componentWillUnmount',1939 'ErrorBoundary componentDidUpdate',1940 ]);1941 ReactDOM.unmountComponentAtNode(container);1942 expect(Scheduler).toHaveYielded(['ErrorBoundary componentWillUnmount']);1943 });1944 it('calls static getDerivedStateFromError for each error that is captured', () => {1945 function renderUnmountError(error) {1946 return <div>Caught an unmounting error: {error.message}.</div>;1947 }1948 function renderUpdateError(error) {1949 return <div>Caught an updating error: {error.message}.</div>;1950 }1951 const container = document.createElement('div');1952 ReactDOM.render(1953 <ErrorBoundary logName="OuterErrorBoundary">1954 <ErrorBoundary1955 logName="InnerUnmountBoundary"1956 renderError={renderUnmountError}>1957 <BrokenComponentWillUnmount errorText="E1" />1958 <BrokenComponentWillUnmount errorText="E2" />1959 </ErrorBoundary>1960 <ErrorBoundary1961 logName="InnerUpdateBoundary"1962 renderError={renderUpdateError}>1963 <BrokenComponentDidUpdate errorText="E3" />1964 <BrokenComponentDidUpdate errorText="E4" />1965 </ErrorBoundary>1966 </ErrorBoundary>,1967 container,1968 );1969 Scheduler.unstable_clearYields();1970 ReactDOM.render(1971 <ErrorBoundary logName="OuterErrorBoundary">1972 <ErrorBoundary1973 logName="InnerUnmountBoundary"1974 renderError={renderUnmountError}1975 />1976 <ErrorBoundary1977 logName="InnerUpdateBoundary"1978 renderError={renderUpdateError}>1979 <BrokenComponentDidUpdate errorText="E3" />1980 <BrokenComponentDidUpdate errorText="E4" />1981 </ErrorBoundary>1982 </ErrorBoundary>,1983 container,1984 );1985 expect(container.firstChild.textContent).toBe(1986 'Caught an unmounting error: E2.' + 'Caught an updating error: E4.',1987 );1988 expect(Scheduler).toHaveYielded([1989 // Begin update phase1990 'OuterErrorBoundary componentWillReceiveProps',1991 'OuterErrorBoundary componentWillUpdate',1992 'OuterErrorBoundary render success',1993 'InnerUnmountBoundary componentWillReceiveProps',1994 'InnerUnmountBoundary componentWillUpdate',1995 'InnerUnmountBoundary render success',1996 'InnerUpdateBoundary componentWillReceiveProps',1997 'InnerUpdateBoundary componentWillUpdate',1998 'InnerUpdateBoundary render success',1999 // First come the updates2000 'BrokenComponentDidUpdate componentWillReceiveProps',2001 'BrokenComponentDidUpdate componentWillUpdate',2002 'BrokenComponentDidUpdate render',2003 'BrokenComponentDidUpdate componentWillReceiveProps',2004 'BrokenComponentDidUpdate componentWillUpdate',2005 'BrokenComponentDidUpdate render',2006 // We're in commit phase now, deleting2007 'BrokenComponentWillUnmount componentWillUnmount [!]',2008 'BrokenComponentWillUnmount componentWillUnmount [!]',2009 // Continue despite errors, handle them after commit is done2010 'InnerUnmountBoundary componentDidUpdate',2011 // We're still in commit phase, now calling update lifecycles2012 'BrokenComponentDidUpdate componentDidUpdate [!]',2013 // Again, continue despite errors, we'll handle them later2014 'BrokenComponentDidUpdate componentDidUpdate [!]',2015 'InnerUpdateBoundary componentDidUpdate',2016 'OuterErrorBoundary componentDidUpdate',2017 // After the commit phase, attempt to recover from any errors that2018 // were captured2019 'ErrorBoundary static getDerivedStateFromError',2020 'ErrorBoundary static getDerivedStateFromError',2021 'InnerUnmountBoundary componentWillUpdate',2022 'InnerUnmountBoundary render error',2023 'ErrorBoundary static getDerivedStateFromError',2024 'ErrorBoundary static getDerivedStateFromError',2025 'InnerUpdateBoundary componentWillUpdate',2026 'InnerUpdateBoundary render error',2027 'BrokenComponentDidUpdate componentWillUnmount',2028 'BrokenComponentDidUpdate componentWillUnmount',2029 'InnerUnmountBoundary componentDidUpdate',2030 'InnerUpdateBoundary componentDidUpdate',2031 ]);2032 ReactDOM.unmountComponentAtNode(container);2033 expect(Scheduler).toHaveYielded([2034 'OuterErrorBoundary componentWillUnmount',2035 'InnerUnmountBoundary componentWillUnmount',2036 'InnerUpdateBoundary componentWillUnmount',2037 ]);2038 });2039 it('discards a bad root if the root component fails', () => {2040 const X = null;2041 const Y = undefined;2042 let err1;2043 let err2;2044 try {2045 const container = document.createElement('div');2046 expect(() => ReactDOM.render(<X />, container)).toErrorDev(2047 'React.createElement: type is invalid -- expected a string ' +2048 '(for built-in components) or a class/function ' +2049 '(for composite components) but got: null.',2050 );2051 } catch (err) {2052 err1 = err;2053 }2054 try {2055 const container = document.createElement('div');2056 expect(() => ReactDOM.render(<Y />, container)).toErrorDev(2057 'React.createElement: type is invalid -- expected a string ' +2058 '(for built-in components) or a class/function ' +2059 '(for composite components) but got: undefined.',2060 );2061 } catch (err) {2062 err2 = err;2063 }2064 expect(err1.message).toMatch(/got: null/);2065 expect(err2.message).toMatch(/got: undefined/);2066 });2067 it('renders empty output if error boundary does not handle the error', () => {2068 const container = document.createElement('div');2069 expect(() =>2070 ReactDOM.render(2071 <div>2072 Sibling2073 <NoopErrorBoundary>2074 <BrokenRender />2075 </NoopErrorBoundary>2076 </div>,2077 container,2078 ),2079 ).toThrow('Hello');2080 expect(container.innerHTML).toBe('');2081 expect(Scheduler).toHaveYielded([2082 'NoopErrorBoundary constructor',2083 'NoopErrorBoundary componentWillMount',2084 'NoopErrorBoundary render',2085 'BrokenRender constructor',2086 'BrokenRender componentWillMount',2087 'BrokenRender render [!]',2088 // Noop error boundaries retry render (and fail again)2089 'NoopErrorBoundary static getDerivedStateFromError',2090 'NoopErrorBoundary render',2091 'BrokenRender constructor',2092 'BrokenRender componentWillMount',2093 'BrokenRender render [!]',2094 ]);2095 });2096 it('passes first error when two errors happen in commit', () => {2097 const errors = [];2098 let caughtError;2099 class Parent extends React.Component {2100 render() {2101 return <Child />;2102 }2103 componentDidMount() {2104 errors.push('parent sad');2105 throw new Error('parent sad');2106 }2107 }2108 class Child extends React.Component {2109 render() {2110 return <div />;2111 }2112 componentDidMount() {2113 errors.push('child sad');2114 throw new Error('child sad');2115 }2116 }2117 const container = document.createElement('div');2118 try {2119 // Here, we test the behavior where there is no error boundary and we2120 // delegate to the host root.2121 ReactDOM.render(<Parent />, container);2122 } catch (e) {2123 if (e.message !== 'parent sad' && e.message !== 'child sad') {2124 throw e;2125 }2126 caughtError = e;2127 }2128 expect(errors).toEqual(['child sad', 'parent sad']);2129 // Error should be the first thrown2130 expect(caughtError.message).toBe('child sad');2131 });2132 it('propagates uncaught error inside unbatched initial mount', () => {2133 function Foo() {2134 throw new Error('foo error');2135 }2136 const container = document.createElement('div');2137 expect(() => {2138 ReactDOM.unstable_batchedUpdates(() => {2139 ReactDOM.render(<Foo />, container);2140 });2141 }).toThrow('foo error');2142 });2143 it('handles errors that occur in before-mutation commit hook', () => {2144 const errors = [];2145 let caughtError;2146 class Parent extends React.Component {2147 getSnapshotBeforeUpdate() {2148 errors.push('parent sad');2149 throw new Error('parent sad');2150 }2151 componentDidUpdate() {}2152 render() {2153 return <Child {...this.props} />;2154 }2155 }2156 class Child extends React.Component {2157 getSnapshotBeforeUpdate() {2158 errors.push('child sad');2159 throw new Error('child sad');2160 }2161 componentDidUpdate() {}2162 render() {2163 return <div />;2164 }2165 }2166 const container = document.createElement('div');2167 ReactDOM.render(<Parent value={1} />, container);2168 try {2169 ReactDOM.render(<Parent value={2} />, container);2170 } catch (e) {2171 if (e.message !== 'parent sad' && e.message !== 'child sad') {2172 throw e;2173 }2174 caughtError = e;2175 }2176 expect(errors).toEqual(['child sad', 'parent sad']);2177 // Error should be the first thrown2178 expect(caughtError.message).toBe('child sad');2179 });2180 it('should warn if an error boundary with only componentDidCatch does not update state', () => {2181 class InvalidErrorBoundary extends React.Component {2182 componentDidCatch(error, info) {2183 // This component does not define getDerivedStateFromError().2184 // It also doesn't call setState().2185 // So it would swallow errors (which is probably unintentional).2186 }2187 render() {2188 return this.props.children;2189 }2190 }2191 const Throws = () => {2192 throw new Error('expected');2193 };2194 const container = document.createElement('div');2195 expect(() => {2196 ReactDOM.render(2197 <InvalidErrorBoundary>2198 <Throws />2199 </InvalidErrorBoundary>,2200 container,2201 );2202 }).toErrorDev(2203 'InvalidErrorBoundary: Error boundaries should implement getDerivedStateFromError(). ' +2204 'In that method, return a state update to display an error message or fallback UI.',2205 );2206 expect(container.textContent).toBe('');2207 });2208 it('should call both componentDidCatch and getDerivedStateFromError if both exist on a component', () => {2209 let componentDidCatchError, getDerivedStateFromErrorError;2210 class ErrorBoundaryWithBothMethods extends React.Component {2211 state = {error: null};2212 static getDerivedStateFromError(error) {2213 getDerivedStateFromErrorError = error;2214 return {error};2215 }2216 componentDidCatch(error, info) {2217 componentDidCatchError = error;2218 }2219 render() {2220 return this.state.error ? 'ErrorBoundary' : this.props.children;2221 }2222 }2223 const thrownError = new Error('expected');2224 const Throws = () => {2225 throw thrownError;2226 };2227 const container = document.createElement('div');2228 ReactDOM.render(2229 <ErrorBoundaryWithBothMethods>2230 <Throws />2231 </ErrorBoundaryWithBothMethods>,2232 container,2233 );2234 expect(container.textContent).toBe('ErrorBoundary');2235 expect(componentDidCatchError).toBe(thrownError);2236 expect(getDerivedStateFromErrorError).toBe(thrownError);2237 });2238 it('should catch errors from invariants in completion phase', () => {2239 const container = document.createElement('div');2240 ReactDOM.render(2241 <ErrorBoundary>2242 <input>2243 <div />2244 </input>2245 </ErrorBoundary>,2246 container,2247 );2248 expect(container.textContent).toContain(2249 'Caught an error: input is a void element tag',2250 );2251 });2252 it('should catch errors from errors in the throw phase from boundaries', () => {2253 const container = document.createElement('div');2254 const thrownError = new Error('original error');2255 const Throws = () => {2256 throw thrownError;2257 };2258 class EvilErrorBoundary extends React.Component {2259 get componentDidCatch() {2260 throw new Error('gotta catch em all');2261 }2262 render() {2263 return this.props.children;2264 }2265 }2266 ReactDOM.render(2267 <ErrorBoundary>2268 <EvilErrorBoundary>2269 <Throws />2270 </EvilErrorBoundary>2271 </ErrorBoundary>,2272 container,2273 );2274 expect(container.textContent).toContain(2275 'Caught an error: gotta catch em all',2276 );2277 });2278 it('should protect errors from errors in the stack generation', () => {2279 const container = document.createElement('div');2280 const evilError = {2281 message: 'gotta catch em all',2282 get stack() {2283 throw new Error('gotta catch em all');2284 },2285 };2286 const Throws = () => {2287 throw evilError;2288 };2289 Object.defineProperty(Throws, 'displayName', {2290 get: function() {2291 throw new Error('gotta catch em all');2292 },2293 });2294 function Wrapper() {2295 return <Throws />;2296 }2297 ReactDOM.render(2298 <ErrorBoundary>2299 <Wrapper />2300 </ErrorBoundary>,2301 container,2302 );2303 expect(container.textContent).toContain(2304 'Caught an error: gotta catch em all.',2305 );2306 });2307 // @gate skipUnmountedBoundaries2308 it('catches errors thrown in componentWillUnmount', () => {2309 class LocalErrorBoundary extends React.Component {2310 state = {error: null};2311 static getDerivedStateFromError(error) {2312 Scheduler.unstable_yieldValue(2313 `ErrorBoundary static getDerivedStateFromError`,2314 );2315 return {error};2316 }2317 render() {2318 const {children, id, fallbackID} = this.props;2319 const {error} = this.state;2320 if (error) {2321 Scheduler.unstable_yieldValue(`${id} render error`);2322 return <Component id={fallbackID} />;2323 }2324 Scheduler.unstable_yieldValue(`${id} render success`);2325 return children || null;2326 }2327 }2328 class Component extends React.Component {2329 render() {2330 const {id} = this.props;2331 Scheduler.unstable_yieldValue('Component render ' + id);2332 return id;2333 }2334 }2335 class LocalBrokenComponentWillUnmount extends React.Component {2336 componentWillUnmount() {2337 Scheduler.unstable_yieldValue(2338 'BrokenComponentWillUnmount componentWillUnmount',2339 );2340 throw Error('Expected');2341 }2342 render() {2343 Scheduler.unstable_yieldValue('BrokenComponentWillUnmount render');2344 return 'broken';2345 }2346 }2347 const container = document.createElement('div');2348 ReactDOM.render(2349 <LocalErrorBoundary id="OuterBoundary" fallbackID="OuterFallback">2350 <Component id="sibling" />2351 <LocalErrorBoundary id="InnerBoundary" fallbackID="InnerFallback">2352 <LocalBrokenComponentWillUnmount />2353 </LocalErrorBoundary>2354 </LocalErrorBoundary>,2355 container,2356 );2357 expect(container.firstChild.textContent).toBe('sibling');2358 expect(container.lastChild.textContent).toBe('broken');2359 expect(Scheduler).toHaveYielded([2360 'OuterBoundary render success',2361 'Component render sibling',2362 'InnerBoundary render success',2363 'BrokenComponentWillUnmount render',2364 ]);2365 ReactDOM.render(2366 <LocalErrorBoundary id="OuterBoundary" fallbackID="OuterFallback">2367 <Component id="sibling" />2368 </LocalErrorBoundary>,2369 container,2370 );2371 // React should skip over the unmounting boundary and find the nearest still-mounted boundary.2372 expect(container.firstChild.textContent).toBe('OuterFallback');2373 expect(container.lastChild.textContent).toBe('OuterFallback');2374 expect(Scheduler).toHaveYielded([2375 'OuterBoundary render success',2376 'Component render sibling',2377 'BrokenComponentWillUnmount componentWillUnmount',2378 'ErrorBoundary static getDerivedStateFromError',2379 'OuterBoundary render error',2380 'Component render OuterFallback',2381 ]);2382 });2383 // @gate skipUnmountedBoundaries2384 it('catches errors thrown while detaching refs', () => {2385 class LocalErrorBoundary extends React.Component {2386 state = {error: null};2387 static getDerivedStateFromError(error) {2388 Scheduler.unstable_yieldValue(2389 `ErrorBoundary static getDerivedStateFromError`,2390 );2391 return {error};2392 }2393 render() {2394 const {children, id, fallbackID} = this.props;2395 const {error} = this.state;2396 if (error) {2397 Scheduler.unstable_yieldValue(`${id} render error`);2398 return <Component id={fallbackID} />;2399 }2400 Scheduler.unstable_yieldValue(`${id} render success`);2401 return children || null;2402 }2403 }2404 class Component extends React.Component {2405 render() {2406 const {id} = this.props;2407 Scheduler.unstable_yieldValue('Component render ' + id);2408 return id;2409 }2410 }2411 class LocalBrokenCallbackRef extends React.Component {2412 _ref = ref => {2413 Scheduler.unstable_yieldValue('LocalBrokenCallbackRef ref ' + !!ref);2414 if (ref === null) {2415 throw Error('Expected');2416 }2417 };2418 render() {2419 Scheduler.unstable_yieldValue('LocalBrokenCallbackRef render');2420 return <div ref={this._ref}>ref</div>;2421 }2422 }2423 const container = document.createElement('div');2424 ReactDOM.render(2425 <LocalErrorBoundary id="OuterBoundary" fallbackID="OuterFallback">2426 <Component id="sibling" />2427 <LocalErrorBoundary id="InnerBoundary" fallbackID="InnerFallback">2428 <LocalBrokenCallbackRef />2429 </LocalErrorBoundary>2430 </LocalErrorBoundary>,2431 container,2432 );2433 expect(container.firstChild.textContent).toBe('sibling');2434 expect(container.lastChild.textContent).toBe('ref');2435 expect(Scheduler).toHaveYielded([2436 'OuterBoundary render success',2437 'Component render sibling',2438 'InnerBoundary render success',2439 'LocalBrokenCallbackRef render',2440 'LocalBrokenCallbackRef ref true',2441 ]);2442 ReactDOM.render(2443 <LocalErrorBoundary id="OuterBoundary" fallbackID="OuterFallback">2444 <Component id="sibling" />2445 </LocalErrorBoundary>,2446 container,2447 );2448 // React should skip over the unmounting boundary and find the nearest still-mounted boundary.2449 expect(container.firstChild.textContent).toBe('OuterFallback');2450 expect(container.lastChild.textContent).toBe('OuterFallback');2451 expect(Scheduler).toHaveYielded([2452 'OuterBoundary render success',2453 'Component render sibling',2454 'LocalBrokenCallbackRef ref false',2455 'ErrorBoundary static getDerivedStateFromError',2456 'OuterBoundary render error',2457 'Component render OuterFallback',2458 ]);2459 });...
namespaceboost_1_1locale_1_1boundary.js
Source:namespaceboost_1_1locale_1_1boundary.js
1var namespaceboost_1_1locale_1_1boundary =2[3 [ "boundary_point", "classboost_1_1locale_1_1boundary_1_1boundary__point.html", null ],4 [ "break_info", "structboost_1_1locale_1_1boundary_1_1break__info.html", null ],5 [ "boundary_indexing", "classboost_1_1locale_1_1boundary_1_1boundary__indexing.html", null ],6 [ "segment_index", "classboost_1_1locale_1_1boundary_1_1segment__index.html", null ],7 [ "boundary_point_index", "classboost_1_1locale_1_1boundary_1_1boundary__point__index.html", null ],8 [ "segment", "classboost_1_1locale_1_1boundary_1_1segment.html", null ],9 [ "cboundary_point", "namespaceboost_1_1locale_1_1boundary.html#ade880ec8623692375afbfd460d28163c", null ],10 [ "cboundary_point_index", "group__boundary.html#ga31f0617de9388783205020a8679b40af", null ],11 [ "csegment", "group__boundary.html#ga7a89ba0de6cad23a0f1b0b90ca5296f0", null ],12 [ "csegment_index", "group__boundary.html#ga82c153957bff0be844a5ce4490d4e7f8", null ],13 [ "index_type", "group__boundary.html#ga7b4dd7af8fad53fabd77e629da24d466", null ],14 [ "rule_type", "group__boundary.html#ga25e193c81052ef1795f1b53b46bc2095", null ],15 [ "sboundary_point", "namespaceboost_1_1locale_1_1boundary.html#ae8869288e9cc33aa283078654ef0dae2", null ],16 [ "sboundary_point_index", "group__boundary.html#ga485e82cdd9debd15dc4fd6f57be10727", null ],17 [ "ssegment", "group__boundary.html#gaac5031c17bd3f7ddc5138546af121064", null ],18 [ "ssegment_index", "group__boundary.html#gad4785439a3f03ee455c93830b8f1366c", null ],19 [ "u16cboundary_point", "namespaceboost_1_1locale_1_1boundary.html#a79a665091fadab07227c0b129ddcde9d", null ],20 [ "u16cboundary_point_index", "group__boundary.html#ga1a89414f77d0b11b7fa8c3a5fa896266", null ],21 [ "u16csegment", "group__boundary.html#ga5ff9e98f81ad61dbcd480fc61780fee1", null ],22 [ "u16csegment_index", "group__boundary.html#gaa20a99d93e3202680bb0660481e1d414", null ],23 [ "u16sboundary_point", "namespaceboost_1_1locale_1_1boundary.html#a64be9f4ec7ff991f73fc793a80f1fadc", null ],24 [ "u16sboundary_point_index", "group__boundary.html#gaba43501d4ed1922c9446db3bf14a918f", null ],25 [ "u16ssegment", "group__boundary.html#ga5084d9529f752361d18c2196f38df3c0", null ],26 [ "u16ssegment_index", "group__boundary.html#ga6fff9ef7a0971ed3c686f3e8d5c56bf4", null ],27 [ "u32cboundary_point", "namespaceboost_1_1locale_1_1boundary.html#aaa106d43f8b06fec14964e19c55356fb", null ],28 [ "u32cboundary_point_index", "group__boundary.html#ga1d16a23d328240464f9068cf58fb38d7", null ],29 [ "u32csegment", "group__boundary.html#gaf2077b28c5de700fb5bff9688fe410d6", null ],30 [ "u32csegment_index", "group__boundary.html#gaacc781106af79ec27693fa8012d54cb9", null ],31 [ "u32sboundary_point", "namespaceboost_1_1locale_1_1boundary.html#a9eb3d6aa912102a115dc6ff80fe9c22d", null ],32 [ "u32sboundary_point_index", "group__boundary.html#ga1379f8968dd611be0b59d04218a1aae8", null ],33 [ "u32ssegment", "group__boundary.html#gaffcc722694a39291a9ea7f68a95e1e27", null ],34 [ "u32ssegment_index", "group__boundary.html#ga3a7b82f5a7e29bd079dd48ca13b79f20", null ],35 [ "wcboundary_point", "namespaceboost_1_1locale_1_1boundary.html#a1c06a716653700b74922e4cc9df0da1b", null ],36 [ "wcboundary_point_index", "group__boundary.html#gabcb5bcc788909afeb8c68d857284cb59", null ],37 [ "wcsegment", "group__boundary.html#gab9d26aae843dad891a3bfa736871e843", null ],38 [ "wcsegment_index", "group__boundary.html#ga29ce0d14d0466a28c205b5dc9d0d6a36", null ],39 [ "wsboundary_point", "namespaceboost_1_1locale_1_1boundary.html#a7828f6884b8a654b9b14fc1ab96ce0d9", null ],40 [ "wsboundary_point_index", "group__boundary.html#gad539aad8c788c8e90cdf08aeed5df4a3", null ],41 [ "wssegment", "group__boundary.html#gaca0e28d417ee314f3035c7561ed5134a", null ],42 [ "wssegment_index", "group__boundary.html#ga579cfdfccf9c682ac4dae5fb65d4a843", null ],43 [ "boundary_type", "group__boundary.html#ga15de9963ce9bb6037c8525901dfbf641", null ],44 [ "boundary_rule", "group__boundary.html#ga99daacb708289fe81def9f1ce4486515", null ],45 [ "operator!=", "group__boundary.html#gab92086846a31a6826c00a3df90027f0f", null ],46 [ "operator!=", "group__boundary.html#gae4458cb23aa62b0f94396d3300e838f9", null ],47 [ "operator!=", "group__boundary.html#gabb7b2978a45e993d6aa9922cbc381e8b", null ],48 [ "operator!=", "group__boundary.html#gab36f95a4500a4c2a31b2ece4a0ae9cd1", null ],49 [ "operator!=", "group__boundary.html#gab8256de904b797b2a57905d3a53f87d7", null ],50 [ "operator!=", "group__boundary.html#gaf50154c65385afc65e206b5fa34fc4ac", null ],51 [ "operator<", "group__boundary.html#ga01671fcf3519166189dff3664f68c870", null ],52 [ "operator<", "group__boundary.html#gac57b915b6feed86f731424c5a5ed531c", null ],53 [ "operator<", "group__boundary.html#gabf992487402ed47358bf790a6372059d", null ],54 [ "operator<", "group__boundary.html#ga5d3bf0c32d4deefe23fa474960b0dea6", null ],55 [ "operator<", "group__boundary.html#gad4be80936d6d852d8a07322ea46c49dd", null ],56 [ "operator<<", "group__boundary.html#ga66d8f6c9b1c81c36a55aecebd4960b5d", null ],57 [ "operator<=", "group__boundary.html#gaef3ac4dbd5172a67ec68e27fe6a7a008", null ],58 [ "operator<=", "group__boundary.html#gaec0814b0634157834f1ecd949ea4f935", null ],59 [ "operator<=", "group__boundary.html#gab800ff341ec09a99c803dd5fd56e5a81", null ],60 [ "operator<=", "group__boundary.html#gad8fc1bd6bf20fe5337dd91dab7f9084c", null ],61 [ "operator<=", "group__boundary.html#ga1f813e25280a6165cc270ced46bc8c58", null ],62 [ "operator==", "group__boundary.html#ga47bc5ece5c461aa4c538354a9e80a707", null ],63 [ "operator==", "group__boundary.html#ga5e70e909a5fb4d2cf87b485894c9b4db", null ],64 [ "operator==", "group__boundary.html#ga22e4d38b1dd21bd663847fdbc09fca46", null ],65 [ "operator==", "group__boundary.html#ga1e22ac8a99d4e743942c5d6e94270e27", null ],66 [ "operator==", "group__boundary.html#ga04c0513778ff3cf9712dd03244a7ecb3", null ],67 [ "operator==", "group__boundary.html#ga2aa32c6dabd5833c3f4806a7a40c0808", null ],68 [ "operator>", "group__boundary.html#ga458e3170d3967ae25c4a40a3970701ba", null ],69 [ "operator>", "group__boundary.html#gad19346448d1464f02f706a3d90932837", null ],70 [ "operator>", "group__boundary.html#gaf32c4f420aae266e1d6d4b37e716cc30", null ],71 [ "operator>", "group__boundary.html#gaa79f6bb9e721e55d071d7898a3010f8e", null ],72 [ "operator>", "group__boundary.html#ga4b12a40f6e30c03e064973a66f8697b8", null ],73 [ "operator>=", "group__boundary.html#ga4d9854493e000ea610108d4689d2f6f1", null ],74 [ "operator>=", "group__boundary.html#ga48fc6bd37670c164d9fcdf918d20ab9f", null ],75 [ "operator>=", "group__boundary.html#gadfbbd6c86914627ffdc08397023b020a", null ],76 [ "operator>=", "group__boundary.html#ga4fb2d214673569bf63a5ef97847d8bc3", null ],77 [ "operator>=", "group__boundary.html#gae867939516d7fd9cbca258414a0c8377", null ],78 [ "character_any", "group__boundary.html#ga9f9e97f7d234139cabe4c4df92a6d4b5", null ],79 [ "character_mask", "group__boundary.html#gad151135cfe341d3c1f63bf459f6a1f4c", null ],80 [ "line_any", "group__boundary.html#ga33fb765abbab27ee07cf70bfab8f47e0", null ],81 [ "line_hard", "group__boundary.html#ga04faac8129ca14e4e5a789652ee8ecab", null ],82 [ "line_mask", "group__boundary.html#gad5d8f2ac695f14b58d5df277aa5939f9", null ],83 [ "line_soft", "group__boundary.html#gaa6a7b6ea3c63a1101a945b82eb10ebd0", null ],84 [ "sentence_any", "group__boundary.html#gae2042518b20123ec14fbf71458ec9c79", null ],85 [ "sentence_mask", "group__boundary.html#gacd2a521edb550e75c624000a1089934c", null ],86 [ "sentence_sep", "group__boundary.html#gaf67883341dd3d8f786e7281d40790000", null ],87 [ "sentence_term", "group__boundary.html#ga3befefe67f79691c117bf5588741355b", null ],88 [ "word_any", "group__boundary.html#ga3ab98808dbb1cc4a346dcc2554c9d8dc", null ],89 [ "word_ideo", "group__boundary.html#ga705ab96f9e62810c8ed977c90d404ef8", null ],90 [ "word_kana", "group__boundary.html#ga52d8c63e1f3f8c898c645352206a78ef", null ],91 [ "word_kana_ideo", "group__boundary.html#ga5de65589628267ab7f2a51f4147d43f9", null ],92 [ "word_letter", "group__boundary.html#ga8b7e6ce2fcb185845fa85a1a4c42b3c4", null ],93 [ "word_letters", "group__boundary.html#gae412d31a918dc793500fed7278663047", null ],94 [ "word_mask", "group__boundary.html#gad11031065617b6be9d4662d2c06afd52", null ],95 [ "word_none", "group__boundary.html#ga90cf4f01b95658f659685377226677e7", null ],96 [ "word_number", "group__boundary.html#gaac78a3a6b9e671e253a2591cb56a479b", null ]
...
dateRangeSelectionStrategy.ts
Source:dateRangeSelectionStrategy.ts
1/*2 * Copyright 2016 Palantir Technologies, Inc. All rights reserved.3 *4 * Licensed under the Apache License, Version 2.0 (the "License");5 * you may not use this file except in compliance with the License.6 * You may obtain a copy of the License at7 *8 * http://www.apache.org/licenses/LICENSE-2.09 *10 * Unless required by applicable law or agreed to in writing, software11 * distributed under the License is distributed on an "AS IS" BASIS,12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13 * See the License for the specific language governing permissions and14 * limitations under the License.15 */16import { Boundary } from "@blueprintjs/core";17import { areSameDay, DateRange } from "./common/dateUtils";18export interface IDateRangeSelectionState {19 /**20 * The boundary that would be modified by clicking the provided `day`.21 */22 boundary?: Boundary;23 /**24 * The date range that would be selected after clicking the provided `day`.25 */26 dateRange: DateRange;27}28export class DateRangeSelectionStrategy {29 /**30 * Returns the new date-range and the boundary that would be affected if `day` were clicked. The31 * affected boundary may be different from the provided `boundary` in some cases. For example,32 * clicking a particular boundary's selected date will always deselect it regardless of which33 * `boundary` you provide to this function (because it's simply a more intuitive interaction).34 */35 public static getNextState(36 currentRange: DateRange,37 day: Date,38 allowSingleDayRange: boolean,39 boundary?: Boundary,40 ): IDateRangeSelectionState {41 if (boundary != null) {42 return this.getNextStateForBoundary(currentRange, day, allowSingleDayRange, boundary);43 } else {44 return this.getDefaultNextState(currentRange, day, allowSingleDayRange);45 }46 }47 private static getNextStateForBoundary(48 currentRange: DateRange,49 day: Date,50 allowSingleDayRange: boolean,51 boundary: Boundary,52 ): IDateRangeSelectionState {53 const boundaryDate = this.getBoundaryDate(boundary, currentRange);54 const otherBoundary = this.getOtherBoundary(boundary);55 const otherBoundaryDate = this.getBoundaryDate(otherBoundary, currentRange);56 let nextBoundary: Boundary;57 let nextDateRange: DateRange;58 if (boundaryDate == null && otherBoundaryDate == null) {59 nextBoundary = boundary;60 nextDateRange = this.createRangeForBoundary(boundary, day, null);61 } else if (boundaryDate != null && otherBoundaryDate == null) {62 const nextBoundaryDate = areSameDay(boundaryDate, day) ? null : day;63 nextBoundary = boundary;64 nextDateRange = this.createRangeForBoundary(boundary, nextBoundaryDate, null);65 } else if (boundaryDate == null && otherBoundaryDate != null) {66 if (areSameDay(day, otherBoundaryDate)) {67 let nextDate: Date;68 if (allowSingleDayRange) {69 nextBoundary = boundary;70 nextDate = otherBoundaryDate;71 } else {72 nextBoundary = otherBoundary;73 nextDate = null;74 }75 nextDateRange = this.createRangeForBoundary(boundary, nextDate, nextDate);76 } else if (this.isOverlappingOtherBoundary(boundary, day, otherBoundaryDate)) {77 nextBoundary = otherBoundary;78 nextDateRange = this.createRangeForBoundary(boundary, otherBoundaryDate, day);79 } else {80 nextBoundary = boundary;81 nextDateRange = this.createRangeForBoundary(boundary, day, otherBoundaryDate);82 }83 } else {84 // both boundaryDate and otherBoundaryDate are already defined85 if (areSameDay(boundaryDate, day)) {86 const isSingleDayRangeSelected = areSameDay(boundaryDate, otherBoundaryDate);87 const nextOtherBoundaryDate = isSingleDayRangeSelected ? null : otherBoundaryDate;88 nextBoundary = boundary;89 nextDateRange = this.createRangeForBoundary(boundary, null, nextOtherBoundaryDate);90 } else if (areSameDay(day, otherBoundaryDate)) {91 const [nextBoundaryDate, nextOtherBoundaryDate] = allowSingleDayRange92 ? [otherBoundaryDate, otherBoundaryDate]93 : [boundaryDate, null];94 nextBoundary = allowSingleDayRange ? boundary : otherBoundary;95 nextDateRange = this.createRangeForBoundary(boundary, nextBoundaryDate, nextOtherBoundaryDate);96 } else if (this.isOverlappingOtherBoundary(boundary, day, otherBoundaryDate)) {97 nextBoundary = boundary;98 nextDateRange = this.createRangeForBoundary(boundary, day, null);99 } else {100 // extend the date range with an earlier boundaryDate date101 nextBoundary = boundary;102 nextDateRange = this.createRangeForBoundary(boundary, day, otherBoundaryDate);103 }104 }105 return { dateRange: nextDateRange, boundary: nextBoundary };106 }107 private static getDefaultNextState(108 selectedRange: DateRange,109 day: Date,110 allowSingleDayRange: boolean,111 ): IDateRangeSelectionState {112 const [start, end] = selectedRange;113 let nextDateRange: DateRange;114 if (start == null && end == null) {115 nextDateRange = [day, null];116 } else if (start != null && end == null) {117 nextDateRange = this.createRange(day, start, allowSingleDayRange);118 } else if (start == null && end != null) {119 nextDateRange = this.createRange(day, end, allowSingleDayRange);120 } else {121 const isStart = areSameDay(start, day);122 const isEnd = areSameDay(end, day);123 if (isStart && isEnd) {124 nextDateRange = [null, null];125 } else if (isStart) {126 nextDateRange = [null, end];127 } else if (isEnd) {128 nextDateRange = [start, null];129 } else {130 nextDateRange = [day, null];131 }132 }133 return { dateRange: nextDateRange };134 }135 private static getOtherBoundary(boundary: Boundary) {136 return boundary === Boundary.START ? Boundary.END : Boundary.START;137 }138 private static getBoundaryDate(boundary: Boundary, dateRange: DateRange) {139 return boundary === Boundary.START ? dateRange[0] : dateRange[1];140 }141 private static isOverlappingOtherBoundary(boundary: Boundary, boundaryDate: Date, otherBoundaryDate: Date) {142 return boundary === Boundary.START ? boundaryDate > otherBoundaryDate : boundaryDate < otherBoundaryDate;143 }144 private static createRangeForBoundary(boundary: Boundary, boundaryDate: Date, otherBoundaryDate: Date) {145 return boundary === Boundary.START146 ? ([boundaryDate, otherBoundaryDate] as DateRange)147 : ([otherBoundaryDate, boundaryDate] as DateRange);148 }149 private static createRange(a: Date, b: Date, allowSingleDayRange: boolean): DateRange {150 // clicking the same date again will clear it151 if (!allowSingleDayRange && areSameDay(a, b)) {152 return [null, null];153 }154 return a < b ? [a, b] : [b, a];155 }...
Using AI Code Generation
1var wpt = require('webpagetest');2var client = wpt('www.webpagetest.org');3}, function (err, data) {4 if (err) return console.error(err);5 console.log(data.data.runs[1].firstView.videoFrames);6});7var wpt = require('webpagetest');8var client = wpt('www.webpagetest.org');9}, function (err, data) {10 if (err) return console.error(err);11 console.log(data.data.runs[1].firstView.videoFrames);12});13var wpt = require('webpagetest');14var client = wpt('www.webpagetest.org');15}, function (err, data) {16 if (err) return console.error(err);17 console.log(data.data.runs[1].firstView.videoFrames);18});19var wpt = require('webpagetest');20var client = wpt('www.webpagetest.org');
Using AI Code Generation
1var wptools = require('wptools');2var page = wptools.page('Barack Obama');3page.get(function(err, info) {4 if (!err) {5 console.log(info);6 } else {7 console.log(err);8 }9});10var wptools = require('wptools');11var page = wptools.page('Barack Obama');12page.get(function(err, info) {13 if (!err) {14 console.log(info);15 } else {16 console.log(err);17 }18});
Using AI Code Generation
1var wpt = require('wpt');2 if (err) throw err;3 console.log('Test status: ' + data.statusCode);4 console.log('Test ID: ' + data.data.testId);5 console.log('Test URL: ' + data.data.userUrl);6 console.log('Test results: ' + data.data.summaryCSV);7});
Using AI Code Generation
1var wptoolkit = require('wptoolkit');2var boundary = new wptoolkit.Boundary();3var point = new wptoolkit.Point(1, 2);4var line = new wptoolkit.Line(1, 1, 2, 2);5var polygon = new wptoolkit.Polygon({points: [{x: 1, y: 1}, {x: 2, y: 2}, {x: 3, y: 3}]});6var circle = new wptoolkit.Circle(1, 1, 1);7The MIT License (MIT)
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!!