import ReactTestUtils from "../../lib/ReactTestUtils";
import React from '../../src/May';
import { render, unmountComponentAtNode, findDOMNode } from '../../src/may-dom/MayDom'
var ReactDOM = {
    render: render,
    unmountComponentAtNode: unmountComponentAtNode,
    findDOMNode: findDOMNode
}
React.render = render;
// var React = require('react');
// var ReactDOM = require('react-dom');
// import React from "../../dist/ReactANU";
// var ReactDOM = React;
// var ReactTestUtils = { Simulate: {} };
// "click,change,keyDown,keyUp,KeyPress,mouseDown,mouseUp,mouseMove".replace(/\w+/g, function (name) {
//     ReactTestUtils.Simulate[name] = function (node, opts) {
//         if (!node || node.nodeType !== 1) {
//             throw "第一个参数必须为元素节点";
//         }
//         var fakeNativeEvent = opts || {};
//         fakeNativeEvent.target = node;
//         fakeNativeEvent.simulated = true;
//         fakeNativeEvent.type = name.toLowerCase();
//         React.eventSystem.dispatchEvent(fakeNativeEvent, name.toLowerCase());
//     };
// });
describe('node模块', function () {
    var body = document.body, div
    beforeEach(function () {
        div = document.createElement('div')
        body.appendChild(div)
    })
    afterEach(function () {
        body.removeChild(div)
    })
    // it('连续点击一个DIV', async () => {
    //     div.innerHTML = '看到我吗?'
    //     var a = 1
    //     div.onclick = function () {
    //         a++
    //     }
    //     await browser.click(div).pause(100).$apply()
    //     expect(a).toBe(2)
    //     await browser.click(div).pause(100).$apply()
    //     expect(a).toBe(3)
    // });
    it('输出简单的元素', async () => {
        var s = React.render(
222
, div)
        //组件直接返回元素节点
        expect(s.nodeName).toBe('DIV');
    });
    it('InputControlES6', async () => {
        class InputControlES6 extends React.Component {
            constructor(props) {
                super(props);
                // 设置 initial state
                this.state = {
                    text: props.initialValue || 'placeholder'
                }
                // ES6 类中函数必须手动绑定
                this.handleChange = this
                    .handleChange
                    .bind(this);
            }
            handleChange(event) {
                this.setState({ text: event.target.value });
            }
            render() {
                return (
                    
                        Type something:
                        
                    
                )
            }
        }
        InputControlES6.defaultProps = {
            initialValue: '请输入内容'
        }
        var s = React.render(, div)
        var input = s.refs.input
        expect(input.value).toBe('请输入内容')
        //input已经是dom 暂不做这个兼容了
        // expect(input.getDOMNode()).toBe(input)
    })
    it('forceUpdate', async () => {
        class App extends React.Component {
            constructor(props) {
                super(props);
                // 设置 initial state
                this.state = {
                    text: 'xxx'
                };
            }
            shouldComponentUpdate() {
                return false
            }
            render() {
                return (
                    
                        Type something:
                        
                    
                );
            }
        }
        App.defaultProps = {
            initialValue: '请输入内容'
        };
        div.innerHTML = 'remove'
        var s = React.render(, div)
        var index = 0
        expect(s.mayInst.hostNode.nodeName).toBe('DIV')
        s.forceUpdate(function () {
            index++
        })
        expect(index).toBe(1)
        s.forceUpdate(function () {
            index++
        })
        expect(index).toBe(2)
    })
    it('下拉菜单的选择', async () => {
        class Select extends React.Component {
            constructor() {
                super()
                this.state = {
                    city: "bj"
                }
            }
            handleCity(e) {
                // expect(e.type).toBe('change')
                console.warn(e.type);
                var value = e.target.value;
                this.setState({ city: value })
            }
            render() {
                return 
            }
        }
        var s = React.render(, div)
        expect(div.firstChild.children[1].selected).toBe(true)
        // await browser.selectByVisibleText('#node2', '上海').pause(100).$apply()
        // expect(div.firstChild.children[2].selected).toBe(true)
        // await browser.selectByVisibleText('#node2', '杭州').pause(100).$apply()
        // expect(div.firstChild.children[0].selected).toBe(true)
    })
    it('下拉菜单的options重排后确保selected正确', async () => {
        class Select extends React.Component {
            constructor() {
                super()
                this.state = {
                    city: "bj",
                    cities: [
                        {
                            value: 'bj',
                            text: '北京'
                        }, {
                            value: 'hj',
                            text: '杭州'
                        }, {
                            value: 'nj',
                            text: '南京'
                        }
                    ]
                }
            }
            change() {
                this.setState({
                    cities: [
                        {
                            value: 'hj',
                            text: '杭州'
                        }, {
                            value: 'nj',
                            text: '南京'
                        }, {
                            value: 'bj',
                            text: '北京'
                        }
                    ]
                })
            }
            handleCity(e) {
                var value = e.target.value;
                this.setState({ city: value })
            }
            render() {
                return 
            }
        }
        ;
        var s = React.render(, div)
        expect(s.mayInst.hostNode.children[0].text).toBe('北京')
        expect(s.mayInst.hostNode.children[1].text).toBe('杭州')
        expect(s.mayInst.hostNode.children[2].text).toBe('南京')
        s.change()
        expect(s.mayInst.hostNode.children[0].text).toBe('杭州')
        expect(s.mayInst.hostNode.children[1].text).toBe('南京')
        expect(s.mayInst.hostNode.children[2].text).toBe('北京')
    })
    it('测试radio的onchange事件', async () => {
        class Radio extends React.Component {
            constructor() {
                super()
                this.state = {
                    checkedIndex: 2
                }
            }
            handleChange(index) {
                this.setState({ checkedIndex: index })
            }
            // webdriver.io不支持触发
            // checkbox的onchange事件,只能browsers.click它,然后在一个onClick回调中手动调用onChange回调
            onClick(index) {
                var me = this
                me.handleChange(index);
                // setTimeout(function () {
                //     me.handleChange(index)
                // })
            }
            render() {
                return 
                    {[1, 2, 3]
                        .map(function (el) {
                            return 
                        }, this)
                    }
                
            }
        }
        var s = React.render(, div)
        expect(s.mayInst.hostNode.children[0].checked).toBe(false)
        expect(s.mayInst.hostNode.children[1].checked).toBe(true)
        expect(s.mayInst.hostNode.children[2].checked).toBe(false)
        ReactTestUtils.Simulate.click(document.getElementById('radio3'));
        expect(s.mayInst.hostNode.children[0].checked).toBe(false)
        expect(s.mayInst.hostNode.children[1].checked).toBe(false)
        expect(s.mayInst.hostNode.children[2].checked).toBe(true)
    })
    it('测试input元素的oninput事件', async () => {
        var values = ['x', 'xx', 'xxx', 'xxxx']
        var el = ''
        class Input extends React.Component {
            constructor() {
                super()
                this.state = {
                    value: 2
                }
            }
            onInput(e) {
                console.log('oninput', e.type, e.target.value)
                el = values.shift()
                this.setState({ value: e.target.value })
            }
            componentDidUpdate() {
                // console.warn(s.mayInst.hostNode.children[0].value);
                // expect(s.mayInst.hostNode.children[0].value).toBe(el)
            }
            render() {
                return 
                    {this.state.value}
                    
                    
                
            }
        }
        var s = React.render(, div)
        expect(s.mayInst.hostNode.children[0].value).toBe('2')
    })
    it('测试textarea元素的oninput事件', async () => {
        var values = ['y', 'yy', 'yyy', 'yyyy']
        var el = ''
        class TextArea extends React.Component {
            constructor() {
                super()
                this.state = {
                    value: 4
                }
            }
            onInput(e) {
                el = values.shift()
                this.setState({ value: e.target.value })
            }
            componentDidUpdate() {
                // expect(s._renderedVnode._hostNode.children[0].value).toBe(el)
            }
            render() {
                return 
                    {this.state.value}
                
            }
        }
        var s = React.render(, div)
        expect(s.mayInst.hostNode.children[0].value).toBe('4')
        // await browser
        //     .setValue('#node5', 'yyyy').pause(300).$apply()
    })
    it('非受控组件textarea的value不可变', async () => {
        class TextArea extends React.Component {
            constructor() {
                super()
                this.state = {
                    value: 5
                }
            }
            render() {
                return 
                    {this.state.value}
                
            }
        }
        var s = React.render(, div)
        // expect(s.mayInst.hostNode.children[0].value).toBe('5')
    })
    it('非受控组件checkbox的checked不可变', async () => {
        class Checkbox extends React.Component {
            constructor() {
                super()
                this.state = {
                    value: true
                }
            }
            render() {
                return 
                    
                
            }
        }
        var s = React.render(, div)
  
        expect(s.mayInst.hostNode.children[0].checked).toBe(true)
    })
    it('非受控组件radio的checked不可变', async () => {
        class Radio extends React.Component {
            constructor() {
                super()
                this.state = {
                    value: false
                }
            }
            render() {
                return 
                    
                
            }
        }
        var s = React.render(, div)
        expect(s.mayInst.hostNode.children[0].checked).toBe(false)
        ReactTestUtils.Simulate.click(document.getElementById('radio7'));
        expect(s.mayInst.hostNode.children[0].checked).toBe(false)
    })
   it('元素节点存在dangerouslySetInnerHTML', async () => {
        class App extends React.Component {
            constructor() {
                super()
                this.state = {
                    aaa: 0
                }
            }
            change(s) {
                this.setState({
                    aaa: 1
                })
            }
            render() {
                return {this.state.aaa === 1 ? 
111222
 :
                    
222
                }
                    
            }
        }
        var s = React.render(, div)
        expect(s.refs.a.value).toBe('南京')
        // await browser.setValue(s.refs.a, '北京').pause(100)
        //     .$apply()
        // expect(s.refs.a.value).toBe('北京')
    })
    it('移除组件', async () => {
        var str = ''
        class Component1 extends React.Component {
            componentWillUnmount() {
                str += 'xxxx'
            }
            render() {
                return {this.props.children}
            }
        }
        class Component2 extends React.Component {
            componentWillUnmount() {
                str += ' yyyy'
            }
            render() {
                return xxx
            }
        }
        var index = 1
        function detect(a) {
            console.log('detect 方法', index, a)
            if (index === 1) {
                expect(typeof a).toBe('object')
            } else {
                expect(a).toBeNull()
            }
        }
        class App extends React.Component {
            constructor(props) {
                super(props)
                this.handleClick = this.handleClick.bind(this)
            }
            handleClick() {
                index = 0
                this.forceUpdate()
                setTimeout(function () {
                    console.warn('应该输出', str)
                })
            }
            render() {
                return index ?
                     : 文本节点
            }
        };
        var s = React.render(, div)
        ReactTestUtils.Simulate.click(s.refs.a);
        // await browser.pause(100).click(s.refs.a).pause(100)
        //     .$apply()
        expect(str).toBe('xxxx yyyy')
    })
    it('移除组件2', async () => {
        var index = 1
        class App extends React.Component {
            constructor(props) {
                super(props)
                this.handleClick = this.handleClick.bind(this)
            }
            handleClick() {
                index = 0
                this.forceUpdate()
            }
            render() {
                return index ?
                     : 
            }
        };
        var s = React.render(, div)
        ReactTestUtils.Simulate.click(s.refs.a);
        // await browser.pause(100).click(s.refs.a).pause(100)
        //     .$apply()
        expect(div.getElementsByTagName('p').length).toBe(1)
    })
    it('removedChildren', async () => {
        var index = 1
        class App extends React.Component {
            constructor(props) {
                super(props)
                this.handleClick = this.handleClick.bind(this)
            }
            handleClick() {
                index = 0
                this.forceUpdate()
            }
            render() {
                return index ?
                     : 
            }
        };
        var s = React.render(, div)
        expect(div.getElementsByTagName('p').length).toBe(4)
        ReactTestUtils.Simulate.click(s.refs.a);
        expect(div.getElementsByTagName('p').length).toBe(1)
    })
    it('一个元素拥有多个实例', async () => {
        var arr = ['111', '222', '333']
        class App extends React.Component {
            constructor(props) {
                super(props)
                this.state = {
                    title: 111
                }
            }
            handleClick() {
                this.setState({
                    title: arr.shift() || new Date - 0
                })
            }
            render() {
                return 
            }
        }
        class B extends React.Component {
            componentWillReceiveProps() {
                this.forceUpdate()
            }
            render() {
                return {new Date - 0}
;
            }
        }
        class C extends React.Component {
            render() {
                return {new Date - 0};
            }
        }
        var s = React.render(, div)
        expect(div.getElementsByTagName('strong').length).toBe(1)
        expect(s instanceof App).toBe(true)
        //expect(div.getElementsByTagName('p').length).toBe(1)
    })
    it('一个元素拥有多个实例2', async () => {
        var arr = ['111', '222', '333']
        class App extends React.Component {
            render() {
                return 
            }
        }
        class A extends React.Component {
            constructor(props) {
                super(props)
                this.state = {
                    title: 111
                }
            }
            handleClick() {
                this.setState({
                    title: arr.shift() || new Date - 0
                })
            }
            render() {
                return 
            }
        }
        class B extends React.Component {
            componentWillReceiveProps() {
                this.forceUpdate()
            }
            render() {
                return {new Date - 0}
;
            }
        }
        class C extends React.Component {
            render() {
                return {new Date - 0};
            }
        }
        var s = React.render(, div)
        expect(div.getElementsByTagName('strong').length).toBe(1)
        s.forceUpdate()
        expect(div.getElementsByTagName('strong').length).toBe(1)
        //expect(div.getElementsByTagName('p').length).toBe(1)
    })
    it('用一个新组件替换另一个组件', async () => {
        var index = 1
        class App extends React.Component {
            handleClick() {
                index = 0
                this.forceUpdate()
            }
            render() {
                return 
            }
        }
        class A extends React.Component {
            render() {
                return 111
            }
        }
        class B extends React.Component {
            render() {
                return 111
            }
        }
        var s = React.render(, div)
        expect(div.getElementsByTagName('strong').length).toBe(1)
        s.handleClick()
        expect(div.getElementsByTagName('em').length).toBe(1)
        //expect(div.getElementsByTagName('p').length).toBe(1)
    })
   it('复杂的孩子转换', async () => {
        var index = 0
        var map = [
            ,
            新的111222333444
,
            33
        ]
        function Link() {
            return index == 1 ? ddd : ddd
        }
        class App extends React.Component {
            constructor(props) {
                super(props)
                this.state = {
                    aaa: 'aaa'
                }
            }
            change(a) {
                this.setState({
                    aaa: a
                })
            }
            componentDidMount() {
                console.log('App componentDidMount')
            }
            componentWillUpdate() {
                console.log('App componentWillUpdate')
            }
            render() {
                return map[index++]
            }
        }
        var s = React.render(, div)
        function getString(nodes) {
            var str = []
            for (var i = 0, node; node = nodes[i++];) {
                str.push(node.nodeName.toLowerCase())
            }
            return str.join(' ')
        }
        expect(getString(div.firstChild.childNodes)).toBe('#text p span strong')
        s.change(100)
        expect(getString(div.firstChild.childNodes)).toBe('em span #text span b i')
        s.change(100)
        expect(getString(div.firstChild.childNodes)).toBe('span')
    })
     it('对一个容器节点反复渲染组件或元素 ', async () => {
        class Comp extends React.Component {
            render() {
                return span in a component;
            }
        }
        let root;
        function test(content) {
            root = React.render(content, div);
        }
        test();
        test(just a div
);
        test();
        expect(div.firstChild.innerHTML).toBe('span in a component');
    });
    it('切换style对象', async () => {
        var index = 1
        class Comp extends React.Component {
            render() {
                return span in a component;
            }
        }
        let root;
        function test(content) {
            root = React.render(content, div);
        }
        test();
        expect(div.firstChild.style.color).toBe('red');
        index = 0
        test();
        expect(div.firstChild.style.color).toBe('');
    });
    it('子组件的DOM节点改变了,会同步父节点的DOM', async () => {
        var s, s2
        class App extends React.Component {
            constructor(props) {
                super(props);
            }
            render() {
                return 
            }
        }
        class A extends React.Component {
            constructor(props) {
                super(props);
            }
            render() {
                return 
            }
        }
        class B extends React.Component {
            constructor(props) {
                super(props);
                this.state = {
                    value: '3333'
                };
            }
            componentDidMount() {
                s2 = this
            }
            render() {
                return this.state.value ? 111
 : 3333
            }
        }
        var s = React.render(, div);
        expect(s.mayInst.hostNode ).toBe(s2.mayInst.rendered.mayInfo.hostNode);
        s2.setState({value: 0});//子组件改变后 父组件的ref跟着变动
        // expect(s.updater._hostNode ).toBe(s2.updater._hostNode);
        // expect(s.updater._hostNode.nodeName).toBe('STRONG');
    })
})