UNPKG

hm-react-cli

Version:

Create a Huimei React project by module

250 lines (206 loc) 6.81 kB
'use strict'; describe('forwardRef', () => { let React; let ReactFeatureFlags; let ReactNoop; ReactNoop = require('react-noop-renderer'); beforeEach(() => { jest.resetModules(); // ReactFeatureFlags = require('shared/ReactFeatureFlags'); // ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false; //ReactNoop = require('react-noop-renderer'); React = ReactNoop }); afterEach(() => { ReactNoop.reset() }) it('should work without a ref to be forwarded', () => { class Child extends React.Component { render() { ReactNoop.yield(this.props.value); return null; } } function Wrapper(props) { return <Child {...props} ref={props.forwardedRef} />; } const RefForwardingComponent = React.forwardRef((props, ref) => ( <Wrapper {...props} forwardedRef={ref} /> )); ReactNoop.render(<RefForwardingComponent value={123} />); expect(ReactNoop.flush()).toEqual([123]); }); it('should forward a ref for a single child', () => { class Child extends React.Component { render() { ReactNoop.yield(this.props.value); return null; } } function Wrapper(props) { return <Child {...props} ref={props.forwardedRef} />; } const RefForwardingComponent = React.forwardRef((props, ref) => ( <Wrapper {...props} forwardedRef={ref} /> )); const ref = React.createRef(); ReactNoop.render(<RefForwardingComponent ref={ref} value={123} />); expect(ReactNoop.flush()).toEqual([123]); expect(ref.current instanceof Child).toBe(true); }); it('should forward a ref for multiple children', () => { class Child extends React.Component { render() { ReactNoop.yield(this.props.value); return null; } } function Wrapper(props) { return <Child {...props} ref={props.forwardedRef} />; } const RefForwardingComponent = React.forwardRef((props, ref) => ( <Wrapper {...props} forwardedRef={ref} /> )); const ref = React.createRef(); ReactNoop.render( <div> <div /> <RefForwardingComponent ref={ref} value={123} /> <div /> </div>, ); expect(ReactNoop.flush()).toEqual([123]); expect(ref.current instanceof Child).toBe(true); }); it('should update refs when switching between children', () => { function FunctionalComponent({forwardedRef, setRefOnDiv}) { return ( <section> <div ref={setRefOnDiv ? forwardedRef : null}>First</div> <span ref={setRefOnDiv ? null : forwardedRef}>Second</span> </section> ); } const RefForwardingComponent = React.forwardRef((props, ref) => ( <FunctionalComponent {...props} forwardedRef={ref} /> )); const ref = React.createRef(); ReactNoop.render(<RefForwardingComponent ref={ref} setRefOnDiv={true} />); ReactNoop.flush(); expect(ref.current.type).toBe('div'); ReactNoop.render(<RefForwardingComponent ref={ref} setRefOnDiv={false} />); ReactNoop.flush(); expect(ref.current.type).toBe('span'); }); it('should maintain child instance and ref through updates', () => { class Child extends React.Component { constructor(props) { super(props); } render() { ReactNoop.yield(this.props.value); return null; } } function Wrapper(props) { return <Child {...props} ref={props.forwardedRef} />; } const RefForwardingComponent = React.forwardRef((props, ref) => ( <Wrapper {...props} forwardedRef={ref} /> )); let setRefCount = 0; let ref; const setRef = r => { setRefCount++; ref = r; }; ReactNoop.render(<RefForwardingComponent ref={setRef} value={123} />); expect(ReactNoop.flush()).toEqual([123]); expect(ref instanceof Child).toBe(true); expect(setRefCount).toBe(1); ReactNoop.render(<RefForwardingComponent ref={setRef} value={456} />); expect(ReactNoop.flush()).toEqual([456]); expect(ref instanceof Child).toBe(true); expect(setRefCount).toBe(1); }); it('should not break lifecycle error handling', () => { class ErrorBoundary extends React.Component { state = {error: null}; componentDidCatch(error) { ReactNoop.yield('ErrorBoundary.componentDidCatch'); this.setState({error}); } render() { if (this.state.error) { ReactNoop.yield('ErrorBoundary.render: catch'); return null; } ReactNoop.yield('ErrorBoundary.render: try'); return this.props.children; } } class BadRender extends React.Component { render() { ReactNoop.yield('BadRender throw'); throw new Error('oops!'); } } function Wrapper(props) { ReactNoop.yield('Wrapper'); return <BadRender {...props} ref={props.forwardedRef} />; } const RefForwardingComponent = React.forwardRef((props, ref) => ( <Wrapper {...props} forwardedRef={ref} /> )); const ref = React.createRef(); ReactNoop.render( <ErrorBoundary> <RefForwardingComponent ref={ref} /> </ErrorBoundary>, ); expect(ReactNoop.flush()).toEqual([ 'ErrorBoundary.render: try', 'Wrapper', 'BadRender throw', 'ErrorBoundary.componentDidCatch', 'ErrorBoundary.render: catch', ]); expect(ref.current).toBe(null); }); it('should support rendering null', () => { const RefForwardingComponent = React.forwardRef((props, ref) => null); const ref = React.createRef(); ReactNoop.render(<RefForwardingComponent ref={ref} />); ReactNoop.flush(); expect(ref.current).toBe(null); }); it('should support rendering null for multiple children', () => { const RefForwardingComponent = React.forwardRef((props, ref) => null); const ref = React.createRef(); ReactNoop.render( <div> <div /> <RefForwardingComponent ref={ref} /> <div /> </div>, ); ReactNoop.flush(); expect(ref.current).toBe(null); }); it('should warn if not provided a callback during creation', () => { expect(() => React.forwardRef(undefined)).toWarnDev( 'forwardRef requires a render function but was given undefined.', ); expect(() => React.forwardRef(null)).toWarnDev( 'forwardRef requires a render function but was given null.', ); expect(() => React.forwardRef('foo')).toWarnDev( 'forwardRef requires a render function but was given string.', ); }); it('should warn if no render function is provided', () => { expect(React.forwardRef).toWarnDev( 'forwardRef requires a render function but was given undefined.', ); }); });