From 2bff70f3d7d698d4a926eb3f929299cfd9bfbf20 Mon Sep 17 00:00:00 2001
From: * <8>
Date: Fri, 22 Apr 2022 18:24:44 +0800
Subject: [PATCH] Match-id-a90510ae54d3c1219ba977e400db2b3cdf8035fe
---
.../__tests__/ComponentTest/Context.test.js | 361 +++++++++++++
.../ComponentTest/FunctionComponent.test.js | 48 ++
.../ComponentTest/HookTest/UseEffect.test.js | 3 +-
.../HookTest/UseImperativeHandle.test.js | 5 +-
.../HookTest/UseLayoutEffect.test.js | 4 +-
.../ComponentTest/HookTest/UseMemo.test.js | 5 +-
.../ComponentTest/HookTest/UseRef.test.js | 5 +-
.../ComponentTest/HookTest/UseState.test.js | 5 +-
.../__tests__/ComponentTest/LifeCycle.test.js | 475 ++++++++++++++++++
scripts/__tests__/DomTest/DomInput.test.js | 3 +-
scripts/__tests__/DomTest/DomSelect.test.js | 2 +-
scripts/__tests__/DomTest/DomTextarea.test.js | 150 ++++++
.../__snapshots__/DomTextarea.test.js.snap | 5 +
scripts/__tests__/EventTest/EventMain.test.js | 2 +-
.../__tests__/EventTest/FocusEvent.test.js | 5 +-
.../__tests__/EventTest/KeyboardEvent.test.js | 3 +-
.../__tests__/EventTest/MouseEvent.test.js | 4 +-
.../__tests__/EventTest/WheelEvent.test.js | 4 +-
scripts/__tests__/jest/commonComponents.js | 9 +-
scripts/__tests__/jest/jestSetting.js | 7 +-
scripts/__tests__/jest/logUtils.js | 26 -
scripts/__tests__/jest/testUtils.js | 46 +-
22 files changed, 1120 insertions(+), 57 deletions(-)
create mode 100644 scripts/__tests__/ComponentTest/Context.test.js
create mode 100644 scripts/__tests__/ComponentTest/FunctionComponent.test.js
create mode 100644 scripts/__tests__/ComponentTest/LifeCycle.test.js
create mode 100644 scripts/__tests__/DomTest/DomTextarea.test.js
create mode 100644 scripts/__tests__/DomTest/__snapshots__/DomTextarea.test.js.snap
delete mode 100755 scripts/__tests__/jest/logUtils.js
diff --git a/scripts/__tests__/ComponentTest/Context.test.js b/scripts/__tests__/ComponentTest/Context.test.js
new file mode 100644
index 00000000..03760244
--- /dev/null
+++ b/scripts/__tests__/ComponentTest/Context.test.js
@@ -0,0 +1,361 @@
+import * as Horizon from '@cloudsop/horizon/index.ts';
+import { getLogUtils } from '../jest/testUtils';
+
+describe('Context Test', () => {
+ const LogUtils =getLogUtils();
+ it('Provider及其内部consumer组件都不受制于shouldComponentUpdate函数或者Horizon.memo()', () => {
+ const LanguageTypes = {
+ JAVA: 'Java',
+ JAVASCRIPT: 'JavaScript',
+ };
+ const defaultValue = { type: LanguageTypes.JAVASCRIPT };
+ const SystemLanguageContext = Horizon.createContext(defaultValue);
+ const SystemLanguageConsumer = SystemLanguageContext.Consumer;
+ const SystemLanguageProvider = (props) => {
+ LogUtils.log('SystemLanguageProvider');
+ return (
+
+ {props.children}
+
+ );
+ };
+
+ const Consumer = () => {
+ LogUtils.log('Consumer');
+ return (
+
+ {type => {
+ LogUtils.log('Consumer DOM mutations');
+ return {type}
;
+ }}
+
+ );
+ };
+
+ class Middle extends Horizon.Component {
+ shouldComponentUpdate() {
+ return false;
+ }
+ render() {
+ LogUtils.log('Middle');
+ return this.props.children;
+ }
+ }
+
+ const App = (props) => {
+ LogUtils.log('App');
+ return (
+
+
+
+
+
+
+
+ );
+ };
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('Java');
+ expect(LogUtils.getAndClear()).toEqual([
+ 'App',
+ 'SystemLanguageProvider',
+ 'Middle',
+ 'Middle',
+ 'Consumer',
+ 'Consumer DOM mutations'
+ ]);
+
+ // 组件不变,Middle没有更新,消费者也不会执行
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('Java');
+ expect(LogUtils.getAndClear()).toEqual([
+ 'App',
+ 'SystemLanguageProvider'
+ ]);
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('JavaScript');
+ // 组件更新,但是Middle没有更新,会绕过Middle
+ expect(LogUtils.getAndClear()).toEqual([
+ 'App',
+ 'SystemLanguageProvider',
+ 'Consumer DOM mutations'
+ ]);
+ });
+
+ it('嵌套consumer provider', () => {
+ const Num = {
+ ONE: 1,
+ TWO: 2,
+ };
+ const NumberContext = Horizon.createContext(0);
+ const NumberConsumer = NumberContext.Consumer;
+ const NumberProvider = (props) => {
+ LogUtils.log(`SystemLanguageProvider: ${props.type}`);
+ return (
+
+ {props.children}
+
+ );
+ };
+
+ const Consumer = () => {
+ LogUtils.log('Consumer');
+ return (
+
+ {type => {
+ LogUtils.log('Consumer DOM mutations');
+ return {type}
;
+ }}
+
+ );
+ };
+
+ class Middle extends Horizon.Component {
+ shouldComponentUpdate() {
+ return false;
+ }
+ render() {
+ LogUtils.log('Middle');
+ return this.props.children;
+ }
+ }
+
+ const App = (props) => {
+ LogUtils.log('App');
+ return (
+
+
+
+
+
+
+
+ );
+ };
+
+ // Consumer决定于距离它最近的provider
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('2');
+ expect(LogUtils.getAndClear()).toEqual([
+ 'App',
+ 'SystemLanguageProvider: 1',
+ 'SystemLanguageProvider: 2',
+ 'Middle',
+ 'Consumer',
+ 'Consumer DOM mutations'
+ ]);
+ // 更新
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('3');
+ expect(LogUtils.getAndClear()).toEqual([
+ 'App',
+ 'SystemLanguageProvider: 2',
+ 'SystemLanguageProvider: 3',
+ 'Consumer DOM mutations'
+ ]);
+ });
+
+ it('设置defaultValue', () => {
+ const Num = {
+ ONE: 1,
+ TWO: 2,
+ };
+ const NumberContext = Horizon.createContext(0);
+ const NewNumberContext = Horizon.createContext(1);
+ const NumberConsumer = NumberContext.Consumer;
+ const NumberProvider = props => {
+ return (
+
+ {props.children}
+
+ );
+ };
+ const NewNumberProvider = props => {
+ return (
+
+ {props.children}
+
+ );
+ };
+
+ class Middle extends Horizon.Component {
+ shouldComponentUpdate() {
+ return false;
+ }
+ render() {
+ return this.props.children;
+ }
+ }
+
+ const NewApp = (props) => {
+ return (
+
+
+
+ {type => {
+ LogUtils.log('Consumer DOM mutations');
+ return {type}
;
+ }}
+
+
+
+ );
+ };
+
+ const App = (props) => {
+ return (
+
+
+
+ {type => {
+ LogUtils.log('Consumer DOM mutations');
+ return {type}
;
+ }}
+
+
+
+ );
+ };
+
+ Horizon.render(, container);
+ // 没有匹配到Provider,会使用defaultValue
+ expect(container.querySelector('p').innerHTML).toBe('0');
+
+ // 更新,设置value为undefined
+ Horizon.render(, container);
+ // 设置value为undefined时,defaultValue不生效
+ expect(container.querySelector('p').innerHTML).toBe('');
+ });
+
+ it('不同provider下的多个consumer', () => {
+ const NumContext = Horizon.createContext(1);
+ const Consumer = NumContext.Consumer;
+
+ function Provider(props) {
+ return (
+
+ {value => (
+
+ {props.children}
+
+ )}
+
+ );
+ }
+
+ class Middle extends Horizon.Component {
+ shouldComponentUpdate() {
+ return false;
+ }
+ render() {
+ return this.props.children;
+ }
+ }
+
+ const App = props => {
+ return (
+
+
+
+
+
+ {value => {value}
}
+
+
+
+
+
+ {value => {value}
}
+
+
+
+
+ );
+ };
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('4');
+ expect(container.querySelector('#p').innerHTML).toBe('2');
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('6');
+ expect(container.querySelector('#p').innerHTML).toBe('3');
+ });
+
+ it('consumer里的child更新是不会重新渲染', () => {
+ const NumContext = Horizon.createContext(1);
+ const Consumer = NumContext.Consumer;
+
+ let setNum;
+ const ReturnDom = props => {
+ const [num, _setNum] = Horizon.useState(0);
+ setNum = _setNum;
+ LogUtils.log('ReturnDom');
+ return (
+
{`Context: ${props.context}, Num: ${num}`}
+ );
+ };
+
+ const App = props => {
+ return (
+
+
+ {value => {
+ LogUtils.log('Consumer');
+ return ;
+ }}
+
+
+ );
+ };
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('Context: 2, Num: 0');
+ expect(LogUtils.getAndClear()).toEqual([
+ 'Consumer',
+ 'ReturnDom'
+ ]);
+ setNum(3);
+ expect(container.querySelector('p').innerHTML).toBe('Context: 2, Num: 3');
+ expect(LogUtils.getAndClear()).toEqual(['ReturnDom']);
+ });
+
+
+ it('consumer可以拿到其他context的值', () => {
+ const NumContext = Horizon.createContext(1);
+ const TypeContext = Horizon.createContext('typeA');
+
+ const NumAndType = () => {
+ const type = Horizon.useContext(TypeContext);
+ return (
+
+ {value => {
+ LogUtils.log('Consumer');
+ return {`Num: ${value}, Type: ${type}`}
;
+ }}
+
+ );
+ };
+
+ const App = props => {
+ return (
+
+
+
+
+
+ );
+ };
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('Num: 2, Type: typeB');
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('Num: 2, Type: typeR');
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('Num: 8, Type: typeR');
+ });
+});
diff --git a/scripts/__tests__/ComponentTest/FunctionComponent.test.js b/scripts/__tests__/ComponentTest/FunctionComponent.test.js
new file mode 100644
index 00000000..004dc15d
--- /dev/null
+++ b/scripts/__tests__/ComponentTest/FunctionComponent.test.js
@@ -0,0 +1,48 @@
+import * as Horizon from '@cloudsop/horizon/index.ts';
+describe('FunctionComponent Test', () => {
+ it('渲染无状态组件', () => {
+ const App = (props) => {
+ return {props.text}
;
+ };
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('app');
+ });
+
+ it('更新无状态组件', () => {
+ const App = (props) => {
+ return {props.text}
;
+ };
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('app');
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('ABC');
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('abc');
+ });
+
+ it('卸载无状态组件', () => {
+ const App = (props) => {
+ return {props.text}
;
+ };
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('app');
+
+ Horizon.unmountComponentAtNode(container);
+ expect(container.querySelector('p')).toBe(null);
+ });
+
+ it('渲染空组件返回空子节点', () => {
+ const App = () => {
+ return ;
+ };
+
+ const realNode = Horizon.render(, container);
+ expect(realNode).toBe(null);
+ });
+
+});
\ No newline at end of file
diff --git a/scripts/__tests__/ComponentTest/HookTest/UseEffect.test.js b/scripts/__tests__/ComponentTest/HookTest/UseEffect.test.js
index 38ab9e71..0acee64f 100644
--- a/scripts/__tests__/ComponentTest/HookTest/UseEffect.test.js
+++ b/scripts/__tests__/ComponentTest/HookTest/UseEffect.test.js
@@ -1,5 +1,5 @@
import * as Horizon from '@cloudsop/horizon/index.ts';
-import * as LogUtils from '../../jest/logUtils';
+import { getLogUtils } from '../../jest/testUtils';
import { Text } from '../../jest/commonComponents';
describe('useEffect Hook Test', () => {
@@ -12,6 +12,7 @@ describe('useEffect Hook Test', () => {
act,
} = Horizon;
+ const LogUtils =getLogUtils();
it('简单使用useEffect', () => {
const App = () => {
const [num, setNum] = useState(0);
diff --git a/scripts/__tests__/ComponentTest/HookTest/UseImperativeHandle.test.js b/scripts/__tests__/ComponentTest/HookTest/UseImperativeHandle.test.js
index 6924610c..f4efe0ef 100644
--- a/scripts/__tests__/ComponentTest/HookTest/UseImperativeHandle.test.js
+++ b/scripts/__tests__/ComponentTest/HookTest/UseImperativeHandle.test.js
@@ -1,6 +1,6 @@
import * as Horizon from '@cloudsop/horizon/index.ts';
-import * as LogUtils from '../../jest/logUtils';
import { Text } from '../../jest/commonComponents';
+import { getLogUtils } from '../../jest/testUtils';
describe('useImperativeHandle Hook Test', () => {
const {
@@ -10,7 +10,7 @@ describe('useImperativeHandle Hook Test', () => {
act,
} = Horizon;
const { unmountComponentAtNode } = Horizon;
-
+ const LogUtils =getLogUtils();
it('测试useImperativeHandle', () => {
let App = (props, ref) => {
@@ -48,7 +48,6 @@ describe('useImperativeHandle Hook Test', () => {
});
it('useImperativeHandle没有配置dep时自动更新', () => {
-
let App = (props, ref) => {
const [num, setNum] = useState(0);
useImperativeHandle(ref, () => ({ num, setNum }));
diff --git a/scripts/__tests__/ComponentTest/HookTest/UseLayoutEffect.test.js b/scripts/__tests__/ComponentTest/HookTest/UseLayoutEffect.test.js
index 4a087112..e5951589 100644
--- a/scripts/__tests__/ComponentTest/HookTest/UseLayoutEffect.test.js
+++ b/scripts/__tests__/ComponentTest/HookTest/UseLayoutEffect.test.js
@@ -1,5 +1,5 @@
import * as Horizon from '@cloudsop/horizon/index.ts';
-import * as LogUtils from '../../jest/logUtils';
+import { getLogUtils } from '../../jest/testUtils';
import { Text } from '../../jest/commonComponents';
describe('useLayoutEffect Hook Test', () => {
@@ -9,7 +9,7 @@ describe('useLayoutEffect Hook Test', () => {
useLayoutEffect,
act,
} = Horizon;
-
+ const LogUtils =getLogUtils();
it('简单使用useLayoutEffect', () => {
const App = () => {
const [num, setNum] = useState(0);
diff --git a/scripts/__tests__/ComponentTest/HookTest/UseMemo.test.js b/scripts/__tests__/ComponentTest/HookTest/UseMemo.test.js
index 1170e6ee..8d379f85 100644
--- a/scripts/__tests__/ComponentTest/HookTest/UseMemo.test.js
+++ b/scripts/__tests__/ComponentTest/HookTest/UseMemo.test.js
@@ -1,10 +1,11 @@
import * as Horizon from '@cloudsop/horizon/index.ts';
-import * as LogUtils from '../../jest/logUtils';
+import { getLogUtils } from '../../jest/testUtils';
import { Text } from '../../jest/commonComponents';
describe('useMemo Hook Test', () => {
const { useMemo, useState } = Horizon;
-
+ const LogUtils =getLogUtils();
+
it('测试useMemo', () => {
let setMemo;
const App = () => {
diff --git a/scripts/__tests__/ComponentTest/HookTest/UseRef.test.js b/scripts/__tests__/ComponentTest/HookTest/UseRef.test.js
index a873a0d4..13110d1c 100644
--- a/scripts/__tests__/ComponentTest/HookTest/UseRef.test.js
+++ b/scripts/__tests__/ComponentTest/HookTest/UseRef.test.js
@@ -1,10 +1,11 @@
import * as Horizon from '@cloudsop/horizon/index.ts';
-import * as LogUtils from '../../jest/logUtils';
+import { getLogUtils } from '../../jest/testUtils';
import { Text } from '../../jest/commonComponents';
describe('useRef Hook Test', () => {
const { useState, useRef } = Horizon;
-
+ const LogUtils =getLogUtils();
+
it('测试useRef', () => {
const App = () => {
const [num, setNum] = useState(1);
diff --git a/scripts/__tests__/ComponentTest/HookTest/UseState.test.js b/scripts/__tests__/ComponentTest/HookTest/UseState.test.js
index 01db57c1..b015fcc5 100644
--- a/scripts/__tests__/ComponentTest/HookTest/UseState.test.js
+++ b/scripts/__tests__/ComponentTest/HookTest/UseState.test.js
@@ -1,5 +1,5 @@
import * as Horizon from '@cloudsop/horizon/index.ts';
-import * as LogUtils from '../../jest/logUtils';
+import { getLogUtils } from '../../jest/testUtils';
import { Text } from '../../jest/commonComponents';
describe('useState Hook Test', () => {
@@ -10,6 +10,7 @@ describe('useState Hook Test', () => {
memo,
act,
} = Horizon;
+ const LogUtils =getLogUtils();
it('简单使用useState', () => {
const App = () => {
@@ -112,7 +113,7 @@ describe('useState Hook Test', () => {
it('useState与memo一起使用', () => {
let setNum;
- const App = memo((props) => {
+ const App = memo(() => {
const [num, _setNum] = useState(0);
setNum = _setNum;
return ;
diff --git a/scripts/__tests__/ComponentTest/LifeCycle.test.js b/scripts/__tests__/ComponentTest/LifeCycle.test.js
new file mode 100644
index 00000000..1e975acf
--- /dev/null
+++ b/scripts/__tests__/ComponentTest/LifeCycle.test.js
@@ -0,0 +1,475 @@
+import * as Horizon from '@cloudsop/horizon/index.ts';
+import { getLogUtils } from '../jest/testUtils';
+
+describe('LifeCycle Test', () => {
+ const LogUtils =getLogUtils();
+ describe('LifeCycle function', () => {
+ it('不能在componentWillMount里setState', () => {
+ class App extends Horizon.Component {
+ state = {};
+
+ UNSAFE_componentWillMount() {
+ this.setState = {
+ num: 1
+ };
+ }
+
+ render() {
+ return {this.state.num}
;
+ }
+ }
+
+ const realNode = Horizon.render(, container);
+ // 不能在componentWillMount里setState
+ expect(realNode.textContent).toBe(undefined);
+ });
+
+ it('componentDidMount里调用setState()将触发额外渲染', () => {
+ class ChildApp extends Horizon.Component {
+ constructor(props) {
+ super(props);
+ }
+
+ componentDidMount() {
+ LogUtils.log(this.props.isShow);
+ }
+
+ render() {
+ return {this.props.isShow}
;
+ }
+ }
+
+ class App extends Horizon.Component {
+ constructor(props) {
+ super(props);
+ LogUtils.log('constructor');
+ this.state = { shouldShowChild: false };
+ }
+
+ componentDidMount() {
+ LogUtils.log('componentDidMount');
+ this.setState({ shouldShowChild: true });
+ }
+
+ render() {
+ return (
+
+ {this.state.shouldShowChild ?
:
}
+
+ );
+ }
+ }
+
+ const realNode = Horizon.render(, container);
+ // 确实触发了额外渲染
+ expect(LogUtils.getAndClear()).toEqual([
+ 'constructor',
+ 'componentDidMount',
+ true
+ ]);
+ // 可以在 componentDidMount() 里直接调用 setState()。它将触发额外渲染,但此渲染会发生在浏览器更新屏幕之前
+ expect(container.querySelector('p').innerHTML).toBe('');
+ // 在 componentDidMount() 里可以更新state
+ expect(realNode.state).toStrictEqual({ 'shouldShowChild': true });
+ });
+
+ it('调用 this.setState() 通常不会触发 UNSAFE_componentWillReceiveProps()', () => {
+ class App extends Horizon.Component {
+ state = {};
+
+ update = () => {
+ this.setState({ num: 4 });
+ }
+
+ UNSAFE_componentWillReceiveProps() {
+ LogUtils.log('componentWillReceiveProps');
+ this.setState = {
+ num: 1
+ };
+ }
+
+ render() {
+ return {this.state.num}
;
+ }
+ }
+
+ const realNode = Horizon.render(, container);
+ expect(realNode.textContent).toBe(undefined);
+ realNode.update();
+ expect(LogUtils.getAndClear()).toEqual([]);
+ });
+
+ it('不能在componentWillReceiveProps里setState', () => {
+ class ChildApp extends Horizon.Component {
+ state = {};
+
+ UNSAFE_componentWillReceiveProps() {
+ this.state = { text: 'text' };
+ }
+
+ render() {
+ LogUtils.log(this.state.text);
+ return {this.state.text}
;
+ }
+ }
+ class App extends Horizon.Component {
+ state = {};
+
+ update = () => {
+ this.setState({ num: 4 });
+ }
+
+ render() {
+ return ;
+ }
+ }
+
+ const realNode = Horizon.render(, container);
+ expect(realNode.textContent).toBe(undefined);
+ realNode.update();
+ expect(LogUtils.getAndClear()).toEqual([
+ undefined,
+ 'text',
+ ]);
+ // 不能在componentWillMount里setState
+ expect(realNode.textContent).toBe(undefined);
+ });
+
+ it('shouldComponentUpdate与getDerivedStateFromProps', () => {
+ class App extends Horizon.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ num: props.num,
+ };
+ }
+ static getDerivedStateFromProps(nextProps, prevState) {
+ if (nextProps.num === prevState.num) {
+ return null;
+ }
+ return { num: nextProps.num };
+ }
+
+ shouldComponentUpdate(nextProps, nextState) {
+ LogUtils.log('shouldComponentUpdate');
+ return nextState.num !== this.state.num;
+ }
+
+ render() {
+ return {this.state.num}
;
+ }
+ }
+
+ Horizon.render(, container);
+ // 初次渲染不会调用shouldComponentUpdate
+ expect(LogUtils.getAndClear()).toEqual([]);
+ expect(container.querySelector('p').innerHTML).toBe('1');
+
+ Horizon.render(, container);
+ // getDerivedStateFromProps判断state没有变化时,会调用shouldComponentUpdate
+ expect(LogUtils.getAndClear()).toEqual(['shouldComponentUpdate']);
+ expect(container.querySelector('p').innerHTML).toBe('1');
+
+ Horizon.render(, container);
+ // getDerivedStateFromProps判断state变化时,会调用shouldComponentUpdate
+ expect(LogUtils.getAndClear()).toEqual(['shouldComponentUpdate']);
+ expect(container.querySelector('p').innerHTML).toBe('2');
+ });
+
+ it('如果shouldComponentUpdate()返回值为false,则不会调用componentDidUpdate()', () => {
+ class App extends Horizon.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ num: props.num,
+ };
+ }
+ static getDerivedStateFromProps(nextProps, prevState) {
+ if (nextProps.num === prevState.num) {
+ return null;
+ }
+ return { num: nextProps.num };
+ }
+
+ shouldComponentUpdate(nextProps, nextState) {
+ return nextState.num !== this.state.num;
+ }
+
+ componentDidUpdate(){
+ LogUtils.log('componentDidUpdate');
+ }
+
+ render() {
+ return {this.state.num}
;
+ }
+ }
+
+ Horizon.render(, container);
+ expect(container.querySelector('p').innerHTML).toBe('1');
+
+ Horizon.render(, container);
+ // 不会调用componentDidUpdate()
+ expect(LogUtils.getAndClear()).toEqual([]);
+ expect(container.querySelector('p').innerHTML).toBe('1');
+
+ Horizon.render(, container);
+ // 调用componentDidUpdate()
+ expect(LogUtils.getAndClear()).toEqual(['componentDidUpdate']);
+ expect(container.querySelector('p').innerHTML).toBe('2');
+ });
+
+ it('getSnapshotBeforeUpdate()的返回值会作为componentDidUpdate()的第三个参数', () => {
+ class App extends Horizon.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ num: 0,
+ };
+ }
+ static getDerivedStateFromProps(nextProps, prevState) {
+ if (nextProps.num === prevState.num) {
+ return null;
+ }
+ return { num: nextProps.num };
+ }
+ getSnapshotBeforeUpdate(prevProps, prevState) {
+ LogUtils.log(
+ `getSnapshotBeforeUpdate prevProps:${prevProps.num} prevState:${prevState.num}`,
+ );
+ return 'Snapshot';
+ }
+ componentDidUpdate(prevProps, prevState, snapshot) {
+ LogUtils.log(
+ `componentDidUpdate prevProps:${prevProps.num} prevState:${prevState.num} snapshot:${snapshot}`,
+ );
+ }
+
+ render() {
+ return {this.state.num}
;
+ }
+ }
+ Horizon.render(, container);
+ expect(LogUtils.getAndClear()).toEqual([]);
+ expect(container.querySelector('p').innerHTML).toBe('');
+
+ Horizon.render(, container);
+ // Snapshot作为componentDidUpdate()的第三个参数
+ expect(LogUtils.getAndClear()).toEqual([
+ 'getSnapshotBeforeUpdate prevProps:undefined prevState:undefined',
+ 'componentDidUpdate prevProps:undefined prevState:undefined snapshot:Snapshot',
+ ]);
+ expect(container.querySelector('p').innerHTML).toBe('1');
+
+ Horizon.render(, container);
+ expect(LogUtils.getAndClear()).toEqual([
+ 'getSnapshotBeforeUpdate prevProps:1 prevState:1',
+ 'componentDidUpdate prevProps:1 prevState:1 snapshot:Snapshot',
+ ]);
+ expect(container.querySelector('p').innerHTML).toBe('1');
+
+ Horizon.render(, container);
+ expect(LogUtils.getAndClear()).toEqual([
+ 'getSnapshotBeforeUpdate prevProps:1 prevState:1',
+ 'componentDidUpdate prevProps:1 prevState:1 snapshot:Snapshot',
+ ]);
+ expect(container.querySelector('p').innerHTML).toBe('2');
+ });
+
+ it('无论什么原因触发了渲染,只要有渲染就会触发getDerivedStateFromProps',() => {
+ class App extends Horizon.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ num: 0,
+ };
+ }
+ static getDerivedStateFromProps(nextProps, prevState) {
+ LogUtils.log(
+ `getDerivedStateFromProps nextProps:${nextProps.num} prevState:${prevState.num}`,
+ );
+ }
+
+ render() {
+ return {this.state.num}
;
+ }
+ }
+ let realNode = Horizon.render(, container);
+ realNode = Horizon.render(, container);
+ realNode.forceUpdate();
+ // 触发了3次渲染
+ expect(LogUtils.getAndClear()).toEqual([
+ 'getDerivedStateFromProps nextProps:undefined prevState:0',
+ 'getDerivedStateFromProps nextProps:1 prevState:0',
+ 'getDerivedStateFromProps nextProps:1 prevState:0',
+ ]);
+ });
+ });
+
+ it('生命周期执行顺序', () => {
+ class InnerApp extends Horizon.Component {
+ UNSAFE_componentWillMount() {
+ LogUtils.log('Inner componentWillMount');
+ }
+ componentDidMount() {
+ LogUtils.log('Inner componentDidMount');
+ }
+ UNSAFE_componentWillReceiveProps() {
+ LogUtils.log('Inner componentWillReceiveProps');
+ }
+ shouldComponentUpdate(nextProps, nextState) {
+ LogUtils.log('Inner shouldComponentUpdates');
+ return this.props.number !== nextProps.number;
+ }
+ UNSAFE_componentWillUpdate() {
+ LogUtils.log('Inner componentWillUpdate');
+ }
+ componentDidUpdate() {
+ LogUtils.log('Inner componentDidUpdate');
+ }
+ componentWillUnmount() {
+ LogUtils.log('Inner componentWillUnmount');
+ }
+
+ render() {
+ return {this.props.number}
;
+ }
+ }
+
+ class App extends Horizon.Component {
+ UNSAFE_componentWillMount() {
+ LogUtils.log('componentWillMount');
+ }
+ componentDidMount() {
+ LogUtils.log('componentDidMount');
+ }
+ UNSAFE_componentWillReceiveProps() {
+ LogUtils.log('componentWillReceiveProps');
+ }
+ shouldComponentUpdate(nextProps, nextState) {
+ LogUtils.log('shouldComponentUpdates');
+ return this.props.num !== nextProps.num;
+ }
+ UNSAFE_componentWillUpdate() {
+ LogUtils.log('componentWillUpdate');
+ }
+ componentDidUpdate() {
+ LogUtils.log('componentDidUpdate');
+ }
+ componentWillUnmount() {
+ LogUtils.log('componentWillUnmount');
+ }
+
+ render() {
+ return ;
+ }
+ }
+
+ Horizon.render(, container);
+ expect(container.textContent).toBe('1');
+ expect(LogUtils.getAndClear()).toEqual([
+ 'componentWillMount',
+ 'Inner componentWillMount',
+ 'Inner componentDidMount',
+ 'componentDidMount'
+ ]);
+ Horizon.render(, container);
+ expect(container.textContent).toBe('2');
+ expect(LogUtils.getAndClear()).toEqual([
+ 'componentWillReceiveProps',
+ 'shouldComponentUpdates',
+ 'componentWillUpdate',
+ 'Inner componentWillReceiveProps',
+ 'Inner shouldComponentUpdates',
+ 'Inner componentWillUpdate',
+ 'Inner componentDidUpdate',
+ 'componentDidUpdate'
+ ]);
+ Horizon.unmountComponentAtNode(container);
+ expect(container.textContent).toBe('');
+ expect(LogUtils.getAndClear()).toEqual([
+ 'componentWillUnmount',
+ 'Inner componentWillUnmount'
+ ]);
+ });
+
+ it('新生命周期执行顺序', () => {
+ class InnerApp extends Horizon.Component {
+ static getDerivedStateFromProps(props, state) {
+ LogUtils.log('Inner getDerivedStateFromProps');
+ }
+ componentDidMount() {
+ LogUtils.log('Inner componentDidMount');
+ }
+ shouldComponentUpdate(nextProps, nextState) {
+ LogUtils.log('Inner shouldComponentUpdates');
+ return this.props.number !== nextProps.number;
+ }
+ componentDidUpdate() {
+ LogUtils.log('Inner componentDidUpdate');
+ }
+ getSnapshotBeforeUpdate() {
+ LogUtils.log('Inner getSnapshotBeforeUpdate');
+ }
+ componentWillUnmount() {
+ LogUtils.log('Inner componentWillUnmount');
+ }
+
+ render() {
+ return {this.props.number}
;
+ }
+ }
+
+ class App extends Horizon.Component {
+ static getDerivedStateFromProps(props, state) {
+ LogUtils.log('getDerivedStateFromProps');
+ }
+ componentDidMount() {
+ LogUtils.log('componentDidMount');
+ }
+ shouldComponentUpdate(nextProps, nextState) {
+ LogUtils.log('shouldComponentUpdates');
+ return this.props.num !== nextProps.num;
+ }
+ getSnapshotBeforeUpdate() {
+ LogUtils.log('getSnapshotBeforeUpdate');
+ }
+ componentDidUpdate() {
+ LogUtils.log('componentDidUpdate');
+ }
+ componentWillUnmount() {
+ LogUtils.log('componentWillUnmount');
+ }
+
+ render() {
+ return ;
+ }
+ }
+
+ Horizon.render(, container);
+ expect(container.textContent).toBe('1');
+ expect(LogUtils.getAndClear()).toEqual([
+ 'getDerivedStateFromProps',
+ 'Inner getDerivedStateFromProps',
+ 'Inner componentDidMount',
+ 'componentDidMount'
+ ]);
+ Horizon.render(, container);
+ expect(container.textContent).toBe('2');
+ expect(LogUtils.getAndClear()).toEqual([
+ 'getDerivedStateFromProps',
+ 'shouldComponentUpdates',
+ 'Inner getDerivedStateFromProps',
+ 'Inner shouldComponentUpdates',
+ 'Inner getSnapshotBeforeUpdate',
+ 'getSnapshotBeforeUpdate',
+ 'Inner componentDidUpdate',
+ 'componentDidUpdate'
+ ]);
+ Horizon.unmountComponentAtNode(container);
+ expect(container.textContent).toBe('');
+ expect(LogUtils.getAndClear()).toEqual([
+ 'componentWillUnmount',
+ 'Inner componentWillUnmount'
+ ]);
+ });
+});
diff --git a/scripts/__tests__/DomTest/DomInput.test.js b/scripts/__tests__/DomTest/DomInput.test.js
index 218cecc6..33ee5efd 100755
--- a/scripts/__tests__/DomTest/DomInput.test.js
+++ b/scripts/__tests__/DomTest/DomInput.test.js
@@ -1,9 +1,10 @@
/* eslint-disable @typescript-eslint/no-empty-function */
import * as Horizon from '@cloudsop/horizon/index.ts';
-import * as LogUtils from '../jest/logUtils';
+import { getLogUtils } from '../jest/testUtils';
describe('Dom Input', () => {
const { act } = Horizon;
+ const LogUtils =getLogUtils();
describe('type checkbox', () => {
it('没有设置checked属性时,控制台不会报错', () => {
diff --git a/scripts/__tests__/DomTest/DomSelect.test.js b/scripts/__tests__/DomTest/DomSelect.test.js
index 29548fc8..dfd1828e 100755
--- a/scripts/__tests__/DomTest/DomSelect.test.js
+++ b/scripts/__tests__/DomTest/DomSelect.test.js
@@ -130,7 +130,7 @@ describe('Dom Select', () => {
expect(realNode.options[1].selected).toBe(true);
});
- it('设置defaultValue后,select不受控', () => {
+ it('设置defaultValue后,select不受控', () => {
const selectNode = (