diff --git a/libs/horizon/src/external/TestUtil.ts b/libs/horizon/src/external/TestUtil.ts index 26d87660..dc9e3dbd 100644 --- a/libs/horizon/src/external/TestUtil.ts +++ b/libs/horizon/src/external/TestUtil.ts @@ -16,7 +16,7 @@ import {asyncUpdates} from '../renderer/TreeBuilder'; import {callRenderQueueImmediate} from '../renderer/taskExecutor/RenderQueue'; -import {runAsyncEffects} from '../renderer/submit/HookEffectHandler'; +import {hasAsyncEffects, runAsyncEffects} from '../renderer/submit/HookEffectHandler'; import {isPromise} from '../renderer/ErrorHandler'; interface Thenable { @@ -62,11 +62,18 @@ function act(fun: () => void | Thenable): Thenable { } } +// 防止死循环 +const LOOPING_LIMIT = 50; +let loopingCount = 0; function callRenderQueue() { callRenderQueueImmediate(); - runAsyncEffects(); - // effects可能产生刷新任务,这里再执行一次 - callRenderQueueImmediate(); + + while (hasAsyncEffects() && loopingCount < LOOPING_LIMIT) { + loopingCount++; + runAsyncEffects(); + // effects可能产生刷新任务,这里再执行一次 + callRenderQueueImmediate(); + } } export { diff --git a/libs/horizon/src/renderer/submit/HookEffectHandler.ts b/libs/horizon/src/renderer/submit/HookEffectHandler.ts index 140eceef..c7db9c32 100644 --- a/libs/horizon/src/renderer/submit/HookEffectHandler.ts +++ b/libs/horizon/src/renderer/submit/HookEffectHandler.ts @@ -25,6 +25,11 @@ import { EffectConstant } from '../hooks/EffectConstant'; let hookEffects: Array = []; let hookRemoveEffects: Array = []; + +export function hasAsyncEffects() { + return hookEffects.length > 0 || hookRemoveEffects.length > 0; +} + // 是否正在异步调度effects let isScheduling = false; diff --git a/scripts/__tests__/ActTest/act.test.js b/scripts/__tests__/ActTest/act.test.js new file mode 100644 index 00000000..3ee055df --- /dev/null +++ b/scripts/__tests__/ActTest/act.test.js @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020 Huawei Technologies Co.,Ltd. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +import Horizon, { render, useState, act, useEffect } from '@cloudsop/horizon/index.ts'; + +describe('Horizon.act function Test', () => { + it('Parent can get Child instance by refs', function () { + const Parent = props => { + const [buttonOptions, setBtn] = useState([]); + const [checkedRows, setCheckedRows] = useState([]); + + useEffect(() => { + setBtn([1, 2, 3]); + }, [checkedRows.length]); + + return ( +
+ +
+ ); + }; + + const Child = props => { + const { buttonOptions } = props; + const [btnList, setBtnList] = useState(0); + + useEffect(() => { + setBtnList(buttonOptions.length); + }, [buttonOptions]); + + return
{btnList}
; + }; + + act(() => { + render(, container); + }); + + // act能够等待useEffect触发的update完成 + expect(container.querySelector('#childDiv').innerHTML).toEqual('3'); + }); +}); diff --git a/scripts/__tests__/ComponentTest/ClassRefs.test.js b/scripts/__tests__/ComponentTest/ClassRefs.test.js new file mode 100644 index 00000000..d5e91d29 --- /dev/null +++ b/scripts/__tests__/ComponentTest/ClassRefs.test.js @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020 Huawei Technologies Co.,Ltd. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +import * as Horizon from '@cloudsop/horizon/index.ts'; + +describe('Class refs Test', () => { + it('Parent can get Child instance by refs', function () { + let pInst; + + class Parent extends Horizon.Component { + componentDidMount() { + pInst = this; + } + + render() { + return ( +
+ +
childDiv
+
+
+ ); + } + } + + class Child extends Horizon.Component { + state = { y: 0 }; + + render() { + return
{this.props.children}
; + } + } + + Horizon.render(, container); + + expect(pInst.refs['child'].state.y).toEqual(0); + expect(pInst.refs['childDiv'].innerHTML).toEqual('childDiv'); + }); +});