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(div.getElementsByTagName('strong').length).toBe(1)
s.change(1)
expect(div.getElementsByTagName('span').length).toBe(1)
})
it('非受控组件select的value不可变', async () => {
class Com extends React.Component {
constructor() {
super()
this.state = {
value: 'bbb'
}
}
render() {
return
}
}
var s = React.render(, div)
// expect(s.mayInst.hostNode.children[1].selected).toBe(true)
// expect(s.mayInst.hostNode.children[2].selected).toBe(false)
// expect(s.mayInst.hostNode.children[1].selected).toBe(true)
})
it('父子组件间的通信', async () => {
class Select extends React.Component {
constructor(props) {
super(props)
this.state = {
value: props.value
}
this.onUpdate = props.onUpdate
this.onChange = this.onChange.bind(this)
}
componentWillReceiveProps(props) {
this.state = { //更新自己
value: props.value
}
}
onChange(e) {//让父组件更新自己
this.onUpdate(e.target.value)
}
render() {
return
}
}
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
value: '南京'
}
}
onUpdate(value) { //让子组件调用这个父组件的方法
this.setState({
value: value
})
}
onChange(e) {
this.onUpdate(e.target.value)
}
render() {
return
}
}
var s = React.render(, div)
expect(s.refs.sss.value).toBe('南京')
})
it('empty Component', async () => {
class Empty extends React.Component {
render() {
return null
}
}
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
value: '南京'
}
}
onUpdate(value) { //让子组件调用这个父组件的方法
this.setState({
value: value
})
}
onChange(e) {//让父组件更新自己
this.onUpdate(e.target.value)
}
render() {
return
}
}
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');
})
})