import React from "dist/React";
import getTestDocument from "./getTestDocument";
import ReactTestUtils from "lib/ReactTestUtils";

import ReactDOMServer from "dist/ReactDOMServer";
//https://github.com/facebook/react/blob/master/src/isomorphic/children/__tests__/ReactChildren-test.js
var ReactDOM = window.ReactDOM || React;

describe("ReactCompositeComponent", function() {
    this.timeout(200000);


    it("should support module pattern components", () => {
        function Child({test}) {
            return {
                render() {
                    return <div>{test}</div>;
                },
            };
        }

        var el = document.createElement("div");
        ReactDOM.render(<Child test="test" />, el);

        expect(el.textContent).toBe("test");
    });

    it("should support rendering to different child types over time", () => {
        var instance = ReactTestUtils.renderIntoDocument(<MorphingComponent />);
        var el = ReactDOM.findDOMNode(instance);
        expect(el.tagName).toBe("A");

        instance._toggleActivatedState();
        el = ReactDOM.findDOMNode(instance);
        expect(el.tagName).toBe("B");

        instance._toggleActivatedState();
        el = ReactDOM.findDOMNode(instance);
        expect(el.tagName).toBe("A");
    });
    var MorphingComponent = class extends React.Component {
      state = {activated: false};

      _toggleActivatedState = () => {
        this.setState({activated: !this.state.activated});
      };

      render() {
        var toggleActivatedState = this._toggleActivatedState;
        return !this.state.activated
          ? <a ref="x" onClick={toggleActivatedState} />
          : <b ref="x" onClick={toggleActivatedState} />;
      }
    };
    it("should react to state changes from callbacks", () => {
        var instance = ReactTestUtils.renderIntoDocument(<MorphingComponent />);
        var el = ReactDOM.findDOMNode(instance);
        expect(el.tagName).toBe("A");

        ReactTestUtils.Simulate.click(el);
        el = ReactDOM.findDOMNode(instance);
        expect(el.tagName).toBe("B");
    });



  it('should rewire refs when rendering to different child types', () => {
    var instance = ReactTestUtils.renderIntoDocument(<MorphingComponent />);

    expect(ReactDOM.findDOMNode(instance.refs.x).tagName).toBe('A');
    instance._toggleActivatedState();
    expect(ReactDOM.findDOMNode(instance.refs.x).tagName).toBe('B');
    instance._toggleActivatedState();
    expect(ReactDOM.findDOMNode(instance.refs.x).tagName).toBe('A');
  });
  var ChildUpdates = class extends React.Component {
    getAnchor = () => {
      return this.refs.anch;
    };

    render() {
      var className = this.props.anchorClassOn ? 'anchorClass' : '';
      return this.props.renderAnchor
        ? <a ref="anch" className={className} />
        : <b />;
    }
  };
  it('should not cache old DOM nodes when switching constructors', () => {
    var container = document.createElement('div');
    var instance = ReactDOM.render(
      <ChildUpdates renderAnchor={true} anchorClassOn={false} />,
      container,
    );
    ReactDOM.render(
      // Warm any cache
      <ChildUpdates renderAnchor={true} anchorClassOn={true} />,
      container,
    );
    ReactDOM.render(
      // Clear out the anchor
      <ChildUpdates renderAnchor={false} anchorClassOn={true} />,
      container,
    );
    ReactDOM.render(
      // rerender
      <ChildUpdates renderAnchor={true} anchorClassOn={false} />,
      container,
    );
    expect(instance.getAnchor().className).toBe('');
  });

  it('should use default values for undefined props', () => {
    class Component extends React.Component {
      static defaultProps = {prop: 'testKey'};

      render() {
        return <span />;
      }
    }

    var instance1 = ReactTestUtils.renderIntoDocument(<Component />);
    expect(instance1.props).toEqual({prop: 'testKey'});

    var instance2 = ReactTestUtils.renderIntoDocument(
      <Component prop={undefined} />,
    );
    expect(instance2.props).toEqual({prop: 'testKey'});

    var instance3 = ReactTestUtils.renderIntoDocument(
      <Component prop={null} />,
    );
    expect(instance3.props).toEqual({prop: null});
  });


  it('should not mutate passed-in props object', () => {
    class Component extends React.Component {
      static defaultProps = {prop: 'testKey'};

      render() {
        return <span />;
      }
    }

    var inputProps = {};
    var instance1 = <Component {...inputProps} />;
    instance1 = ReactTestUtils.renderIntoDocument(instance1);
    expect(instance1.props.prop).toBe('testKey');

    // We don't mutate the input, just in case the caller wants to do something
    // with it after using it to instantiate a component
    expect(inputProps.prop).toBe(void 666);
  });

  it('should warn about `forceUpdate` on unmounted components', () => {

    var container = document.createElement('div');
    document.body.appendChild(container);

    class Component extends React.Component {
      render() {
        return <div />;
      }
    }

    var instance = <Component />;
    expect(instance.forceUpdate).not.toBeDefined();

    instance = ReactDOM.render(instance, container);
    instance.forceUpdate();

    ReactDOM.unmountComponentAtNode(container);

    instance.forceUpdate();
  });
});