Match-id-275aac869fd1826485112c6e5cf9a2a28ebbb370
This commit is contained in:
commit
7ccc3953ed
|
@ -1,12 +1,20 @@
|
||||||
import {
|
import {
|
||||||
Children,
|
TYPE_FRAGMENT as Fragment,
|
||||||
createRef,
|
TYPE_PROFILER as Profiler,
|
||||||
Component,
|
TYPE_STRICT_MODE as StrictMode,
|
||||||
PureComponent,
|
TYPE_SUSPENSE as Suspense,
|
||||||
createContext,
|
} from './src/external/JSXElementType';
|
||||||
forwardRef,
|
|
||||||
lazy,
|
import { Component, PureComponent } from './src/renderer/components/BaseClassComponent';
|
||||||
memo,
|
import { createRef } from './src/renderer/components/CreateRef';
|
||||||
|
import { Children } from './src/external/ChildrenUtil';
|
||||||
|
import { createElement, cloneElement, isValidElement } from './src/external/JSXElement';
|
||||||
|
import { createContext } from './src/renderer/components/context/CreateContext';
|
||||||
|
import { lazy } from './src/renderer/components/Lazy';
|
||||||
|
import { forwardRef } from './src/renderer/components/ForwardRef';
|
||||||
|
import { memo } from './src/renderer/components/Memo';
|
||||||
|
|
||||||
|
import {
|
||||||
useCallback,
|
useCallback,
|
||||||
useContext,
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
|
@ -16,14 +24,18 @@ import {
|
||||||
useReducer,
|
useReducer,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
Fragment,
|
} from './src/renderer/hooks/HookExternal';
|
||||||
Profiler,
|
import { launchUpdateFromVNode as _launchUpdateFromVNode, asyncUpdates } from './src/renderer/TreeBuilder';
|
||||||
StrictMode,
|
import { callRenderQueueImmediate } from './src/renderer/taskExecutor/RenderQueue';
|
||||||
Suspense,
|
import { runAsyncEffects } from './src/renderer/submit/HookEffectHandler';
|
||||||
createElement,
|
import { getProcessingVNode as _getProcessingVNode } from './src/renderer/hooks/BaseHook';
|
||||||
cloneElement,
|
|
||||||
isValidElement,
|
// act用于测试,作用是:如果fun触发了刷新(包含了异步刷新),可以保证在act后面的代码是在刷新完成后才执行。
|
||||||
} from './src/external/Horizon';
|
const act = fun => {
|
||||||
|
asyncUpdates(fun);
|
||||||
|
callRenderQueueImmediate();
|
||||||
|
runAsyncEffects();
|
||||||
|
};
|
||||||
|
|
||||||
import {
|
import {
|
||||||
render,
|
render,
|
||||||
|
@ -63,6 +75,9 @@ const Horizon = {
|
||||||
unstable_batchedUpdates,
|
unstable_batchedUpdates,
|
||||||
findDOMNode,
|
findDOMNode,
|
||||||
unmountComponentAtNode,
|
unmountComponentAtNode,
|
||||||
|
act,
|
||||||
|
_launchUpdateFromVNode,
|
||||||
|
_getProcessingVNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -95,6 +110,11 @@ export {
|
||||||
unstable_batchedUpdates,
|
unstable_batchedUpdates,
|
||||||
findDOMNode,
|
findDOMNode,
|
||||||
unmountComponentAtNode,
|
unmountComponentAtNode,
|
||||||
|
act,
|
||||||
|
|
||||||
|
// 暂时给HorizonX使用
|
||||||
|
_launchUpdateFromVNode,
|
||||||
|
_getProcessingVNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Horizon;
|
export default Horizon;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import * as Horizon from '../../external/Horizon';
|
import { Children } from '../../external/ChildrenUtil';
|
||||||
import {IProperty} from '../utils/Interface';
|
import { IProperty } from '../utils/Interface';
|
||||||
|
|
||||||
// 把 const a = 'a'; <option>gir{a}ffe</option> 转成 giraffe
|
// 把 const a = 'a'; <option>gir{a}ffe</option> 转成 giraffe
|
||||||
function concatChildren(children) {
|
function concatChildren(children) {
|
||||||
let content = '';
|
let content = '';
|
||||||
Horizon.Children.forEach(children, function(child) {
|
Children.forEach(children, function(child) {
|
||||||
content += child;
|
content += child;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
import {
|
|
||||||
TYPE_FRAGMENT,
|
|
||||||
TYPE_PROFILER,
|
|
||||||
TYPE_STRICT_MODE,
|
|
||||||
TYPE_SUSPENSE,
|
|
||||||
} from './JSXElementType';
|
|
||||||
|
|
||||||
import {Component, PureComponent} from '../renderer/components/BaseClassComponent';
|
|
||||||
import {createRef} from '../renderer/components/CreateRef';
|
|
||||||
import {Children} from './ChildrenUtil';
|
|
||||||
import {
|
|
||||||
createElement,
|
|
||||||
cloneElement,
|
|
||||||
isValidElement,
|
|
||||||
} from './JSXElement';
|
|
||||||
import {createContext} from '../renderer/components/context/CreateContext';
|
|
||||||
import {lazy} from '../renderer/components/Lazy';
|
|
||||||
import {forwardRef} from '../renderer/components/ForwardRef';
|
|
||||||
import {memo} from '../renderer/components/Memo';
|
|
||||||
import hookMapping from '../renderer/hooks/HookMapping';
|
|
||||||
|
|
||||||
import {
|
|
||||||
useCallback,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useImperativeHandle,
|
|
||||||
useLayoutEffect,
|
|
||||||
useMemo,
|
|
||||||
useReducer,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
} from '../renderer/hooks/HookExternal';
|
|
||||||
|
|
||||||
export {
|
|
||||||
Children,
|
|
||||||
createRef,
|
|
||||||
Component,
|
|
||||||
PureComponent,
|
|
||||||
createContext,
|
|
||||||
forwardRef,
|
|
||||||
lazy,
|
|
||||||
memo,
|
|
||||||
useCallback,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useImperativeHandle,
|
|
||||||
useLayoutEffect,
|
|
||||||
useMemo,
|
|
||||||
useReducer,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
TYPE_FRAGMENT as Fragment,
|
|
||||||
TYPE_PROFILER as Profiler,
|
|
||||||
TYPE_STRICT_MODE as StrictMode,
|
|
||||||
TYPE_SUSPENSE as Suspense,
|
|
||||||
createElement,
|
|
||||||
cloneElement,
|
|
||||||
isValidElement,
|
|
||||||
hookMapping,
|
|
||||||
};
|
|
|
@ -1,17 +1,15 @@
|
||||||
import type {ContextType} from '../Types';
|
import type {ContextType} from '../Types';
|
||||||
|
|
||||||
import hookMapping from './HookMapping';
|
|
||||||
import {useRefImpl} from './UseRefHook';
|
import {useRefImpl} from './UseRefHook';
|
||||||
import {useEffectImpl, useLayoutEffectImpl} from './UseEffectHook';
|
import {useEffectImpl, useLayoutEffectImpl} from './UseEffectHook';
|
||||||
import {useCallbackImpl} from './UseCallbackHook';
|
import {useCallbackImpl} from './UseCallbackHook';
|
||||||
import {useMemoImpl} from './UseMemoHook';
|
import {useMemoImpl} from './UseMemoHook';
|
||||||
import {useImperativeHandleImpl} from './UseImperativeHook';
|
import {useImperativeHandleImpl} from './UseImperativeHook';
|
||||||
|
import {useReducerImpl} from './UseReducerHook';
|
||||||
const {
|
import {useStateImpl} from './UseStateHook';
|
||||||
UseContextHookMapping,
|
import {getNewContext} from '../components/context/Context';
|
||||||
UseReducerHookMapping,
|
import {getProcessingVNode} from './BaseHook';
|
||||||
UseStateHookMapping
|
import {Ref, Trigger} from './HookType';
|
||||||
} = hookMapping;
|
|
||||||
|
|
||||||
type BasicStateAction<S> = ((S) => S) | S;
|
type BasicStateAction<S> = ((S) => S) | S;
|
||||||
type Dispatch<A> = (A) => void;
|
type Dispatch<A> = (A) => void;
|
||||||
|
@ -20,22 +18,23 @@ type Dispatch<A> = (A) => void;
|
||||||
export function useContext<T>(
|
export function useContext<T>(
|
||||||
Context: ContextType<T>,
|
Context: ContextType<T>,
|
||||||
): T {
|
): T {
|
||||||
return UseContextHookMapping.val.useContext(Context);
|
const processingVNode = getProcessingVNode();
|
||||||
|
return getNewContext(processingVNode!, Context, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useState<S>(initialState: (() => S) | S,): [S, Dispatch<BasicStateAction<S>>] {
|
export function useState<S>(initialState: (() => S) | S,): [S, Dispatch<BasicStateAction<S>>] {
|
||||||
return UseStateHookMapping.val.useState(initialState);
|
return useStateImpl(initialState);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useReducer<S, I, A>(
|
export function useReducer<S, I, A>(
|
||||||
reducer: (S, A) => S,
|
reducer: (S, A) => S,
|
||||||
initialArg: I,
|
initialArg: I,
|
||||||
init?: (I) => S,
|
init?: (I) => S,
|
||||||
): [S, Dispatch<A>] {
|
): [S, Trigger<A>] | void {
|
||||||
return UseReducerHookMapping.val.useReducer(reducer, initialArg, init);
|
return useReducerImpl(reducer, initialArg, init);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useRef<T>(initialValue: T): {current: T} {
|
export function useRef<T>(initialValue: T): Ref<T> {
|
||||||
return useRefImpl(initialValue);
|
return useRefImpl(initialValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,11 @@
|
||||||
import type {VNode} from '../Types';
|
import type {VNode} from '../Types';
|
||||||
import hookMapping from './HookMapping';
|
|
||||||
|
|
||||||
const {
|
|
||||||
UseStateHookMapping,
|
|
||||||
UseReducerHookMapping,
|
|
||||||
UseContextHookMapping,
|
|
||||||
} = hookMapping;
|
|
||||||
|
|
||||||
import {getNewContext} from '../components/context/Context';
|
|
||||||
import {
|
import {
|
||||||
getLastTimeHook,
|
getLastTimeHook,
|
||||||
getProcessingVNode,
|
|
||||||
setLastTimeHook,
|
setLastTimeHook,
|
||||||
setProcessingVNode,
|
setProcessingVNode,
|
||||||
setCurrentHook, getNextHook
|
setCurrentHook, getNextHook
|
||||||
} from './BaseHook';
|
} from './BaseHook';
|
||||||
import {useStateImpl} from './UseStateHook';
|
|
||||||
import {useReducerImpl} from './UseReducerHook';
|
|
||||||
import {HookStage, setHookStage} from './HookStage';
|
import {HookStage, setHookStage} from './HookStage';
|
||||||
|
|
||||||
// hook对外入口
|
// hook对外入口
|
||||||
|
@ -29,9 +18,6 @@ export function runFunctionWithHooks<Props extends Record<string, any>, Arg>(
|
||||||
// 重置全局变量
|
// 重置全局变量
|
||||||
resetGlobalVariable();
|
resetGlobalVariable();
|
||||||
|
|
||||||
// 初始化hook实现函数
|
|
||||||
initHookMapping();
|
|
||||||
|
|
||||||
setProcessingVNode(processing);
|
setProcessingVNode(processing);
|
||||||
|
|
||||||
processing.oldHooks = processing.hooks;
|
processing.oldHooks = processing.hooks;
|
||||||
|
@ -71,8 +57,3 @@ function resetGlobalVariable() {
|
||||||
setCurrentHook(null);
|
setCurrentHook(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initHookMapping() {
|
|
||||||
UseContextHookMapping.val = {useContext: context => getNewContext(getProcessingVNode(), context, true)};
|
|
||||||
UseReducerHookMapping.val = {useReducer: useReducerImpl};
|
|
||||||
UseStateHookMapping.val = {useState: useStateImpl};
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
/**
|
|
||||||
* 暂时用于解决测试代码无法运行问题,估计是:测试代码会循环或者重复依赖
|
|
||||||
*/
|
|
||||||
|
|
||||||
import type {
|
|
||||||
UseContextHookType,
|
|
||||||
UseReducerHookType,
|
|
||||||
UseStateHookType
|
|
||||||
} from '../Types';
|
|
||||||
|
|
||||||
const UseStateHookMapping: {val: (null | UseStateHookType)} = {val: null};
|
|
||||||
const UseReducerHookMapping: {val: (null | UseReducerHookType)} = {val: null};
|
|
||||||
const UseContextHookMapping: {val: (null | UseContextHookType)} = {val: null};
|
|
||||||
|
|
||||||
const hookMapping = {
|
|
||||||
UseStateHookMapping,
|
|
||||||
UseReducerHookMapping,
|
|
||||||
UseContextHookMapping,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default hookMapping;
|
|
|
@ -56,12 +56,14 @@ export function captureFunctionComponent(
|
||||||
);
|
);
|
||||||
|
|
||||||
// 这里需要判断是否可以复用,因为函数组件比起其他组价,多了context和stateChange两个因素
|
// 这里需要判断是否可以复用,因为函数组件比起其他组价,多了context和stateChange两个因素
|
||||||
if (isCanReuse && !isStateChange()) {
|
if (isCanReuse && !isStateChange() && !processing.isStoreChange) {
|
||||||
FlagUtils.removeFlag(processing, Update);
|
FlagUtils.removeFlag(processing, Update);
|
||||||
|
|
||||||
return onlyUpdateChildVNodes(processing);
|
return onlyUpdateChildVNodes(processing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processing.isStoreChange = false;
|
||||||
|
|
||||||
processing.child = createChildrenByDiff(processing, processing.child, newElements, !processing.isCreated);
|
processing.child = createChildrenByDiff(processing, processing.child, newElements, !processing.isCreated);
|
||||||
return processing.child;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,10 @@ export class VNode {
|
||||||
|
|
||||||
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode,处理ref的时候使用
|
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode,处理ref的时候使用
|
||||||
|
|
||||||
|
// 状态管理器使用
|
||||||
|
isStoreChange: boolean;
|
||||||
|
functionToObserver: FunctionToObserver | null; // 记录这个函数组件依赖哪些Observer
|
||||||
|
|
||||||
constructor(tag: VNodeTag, props: any, key: null | string, realNode) {
|
constructor(tag: VNodeTag, props: any, key: null | string, realNode) {
|
||||||
this.tag = tag; // 对应组件的类型,比如ClassComponent等
|
this.tag = tag; // 对应组件的类型,比如ClassComponent等
|
||||||
this.key = key;
|
this.key = key;
|
||||||
|
@ -102,6 +106,8 @@ export class VNode {
|
||||||
this.depContexts = null;
|
this.depContexts = null;
|
||||||
this.isDepContextChange = false;
|
this.isDepContextChange = false;
|
||||||
this.oldHooks = null;
|
this.oldHooks = null;
|
||||||
|
this.isStoreChange = false;
|
||||||
|
this.functionToObserver = null;
|
||||||
break;
|
break;
|
||||||
case ClassComponent:
|
case ClassComponent:
|
||||||
this.realNode = null;
|
this.realNode = null;
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||||
import { act } from '../../jest/customMatcher';
|
|
||||||
|
|
||||||
describe('useContext Hook Test', () => {
|
describe('useContext Hook Test', () => {;
|
||||||
const { useState, useContext, createContext } = Horizon;
|
const { useState, useContext, createContext, act, unmountComponentAtNode } = Horizon;
|
||||||
const { unmountComponentAtNode } = Horizon;
|
|
||||||
|
|
||||||
it('简单使用useContext', () => {
|
it('简单使用useContext', () => {
|
||||||
const LanguageTypes = {
|
const LanguageTypes = {
|
||||||
|
@ -14,12 +12,16 @@ describe('useContext Hook Test', () => {
|
||||||
const SystemLanguageContext = Horizon.createContext(defaultValue);
|
const SystemLanguageContext = Horizon.createContext(defaultValue);
|
||||||
|
|
||||||
const SystemLanguageProvider = ({ type, children }) => {
|
const SystemLanguageProvider = ({ type, children }) => {
|
||||||
return <SystemLanguageContext.Provider value={{ type }}>{children}</SystemLanguageContext.Provider>;
|
return (
|
||||||
|
<SystemLanguageContext.Provider value={{ type }}>
|
||||||
|
{children}
|
||||||
|
</SystemLanguageContext.Provider>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
const TestFunction = () => {
|
const TestFunction = () => {
|
||||||
const context = useContext(SystemLanguageContext);
|
const context = useContext(SystemLanguageContext);
|
||||||
return <p id="p">{context.type}</p>;
|
return <p id="p">{context.type}</p>;
|
||||||
};
|
}
|
||||||
let setValue;
|
let setValue;
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [value, _setValue] = useState(LanguageTypes.JAVA);
|
const [value, _setValue] = useState(LanguageTypes.JAVA);
|
||||||
|
@ -30,8 +32,8 @@ describe('useContext Hook Test', () => {
|
||||||
<TestFunction />
|
<TestFunction />
|
||||||
</SystemLanguageProvider>
|
</SystemLanguageProvider>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
Horizon.render(<TestFunction />, container);
|
Horizon.render(<TestFunction />, container);
|
||||||
// 测试当Provider未提供时,获取到的默认值'JavaScript'。
|
// 测试当Provider未提供时,获取到的默认值'JavaScript'。
|
||||||
expect(container.querySelector('p').innerHTML).toBe('JavaScript');
|
expect(container.querySelector('p').innerHTML).toBe('JavaScript');
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||||
import * as LogUtils from '../../jest/logUtils';
|
import * as LogUtils from '../../jest/logUtils';
|
||||||
import { act } from '../../jest/customMatcher';
|
import { Text } from '../../jest/commonComponents';
|
||||||
import Text from '../../jest/Text';
|
|
||||||
|
|
||||||
describe('useEffect Hook Test', () => {
|
describe('useEffect Hook Test', () => {
|
||||||
const {
|
const {
|
||||||
|
@ -9,7 +8,8 @@ describe('useEffect Hook Test', () => {
|
||||||
useLayoutEffect,
|
useLayoutEffect,
|
||||||
useState,
|
useState,
|
||||||
memo,
|
memo,
|
||||||
forwardRef
|
forwardRef,
|
||||||
|
act,
|
||||||
} = Horizon;
|
} = Horizon;
|
||||||
|
|
||||||
it('简单使用useEffect', () => {
|
it('简单使用useEffect', () => {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||||
import * as LogUtils from '../../jest/logUtils';
|
import * as LogUtils from '../../jest/logUtils';
|
||||||
import { act } from '../../jest/customMatcher';
|
import { Text } from '../../jest/commonComponents';
|
||||||
import Text from '../../jest/Text';
|
|
||||||
|
|
||||||
describe('useImperativeHandle Hook Test', () => {
|
describe('useImperativeHandle Hook Test', () => {
|
||||||
const {
|
const {
|
||||||
useState,
|
useState,
|
||||||
useImperativeHandle,
|
useImperativeHandle,
|
||||||
forwardRef
|
forwardRef,
|
||||||
|
act,
|
||||||
} = Horizon;
|
} = Horizon;
|
||||||
const { unmountComponentAtNode } = Horizon;
|
const { unmountComponentAtNode } = Horizon;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||||
import * as LogUtils from '../../jest/logUtils';
|
import * as LogUtils from '../../jest/logUtils';
|
||||||
import { act } from '../../jest/customMatcher';
|
import { Text } from '../../jest/commonComponents';
|
||||||
import Text from '../../jest/Text';
|
|
||||||
|
|
||||||
describe('useLayoutEffect Hook Test', () => {
|
describe('useLayoutEffect Hook Test', () => {
|
||||||
const {
|
const {
|
||||||
useState,
|
useState,
|
||||||
useEffect,
|
useEffect,
|
||||||
useLayoutEffect
|
useLayoutEffect,
|
||||||
|
act,
|
||||||
} = Horizon;
|
} = Horizon;
|
||||||
|
|
||||||
it('简单使用useLayoutEffect', () => {
|
it('简单使用useLayoutEffect', () => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||||
import * as LogUtils from '../../jest/logUtils';
|
import * as LogUtils from '../../jest/logUtils';
|
||||||
import Text from '../../jest/Text';
|
import { Text } from '../../jest/commonComponents';
|
||||||
|
|
||||||
describe('useMemo Hook Test', () => {
|
describe('useMemo Hook Test', () => {
|
||||||
const { useMemo, useState } = Horizon;
|
const { useMemo, useState } = Horizon;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||||
import * as LogUtils from '../../jest/logUtils';
|
import * as LogUtils from '../../jest/logUtils';
|
||||||
import Text from '../../jest/Text';
|
import { Text } from '../../jest/commonComponents';
|
||||||
|
|
||||||
describe('useRef Hook Test', () => {
|
describe('useRef Hook Test', () => {
|
||||||
const { useState, useRef } = Horizon;
|
const { useState, useRef } = Horizon;
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||||
import * as LogUtils from '../../jest/logUtils';
|
import * as LogUtils from '../../jest/logUtils';
|
||||||
import { act } from '../../jest/customMatcher';
|
import { Text } from '../../jest/commonComponents';
|
||||||
import Text from '../../jest/Text';
|
|
||||||
|
|
||||||
describe('useState Hook Test', () => {
|
describe('useState Hook Test', () => {
|
||||||
const {
|
const {
|
||||||
useState,
|
useState,
|
||||||
forwardRef,
|
forwardRef,
|
||||||
useImperativeHandle,
|
useImperativeHandle,
|
||||||
memo
|
memo,
|
||||||
|
act,
|
||||||
} = Horizon;
|
} = Horizon;
|
||||||
|
|
||||||
it('简单使用useState', () => {
|
it('简单使用useState', () => {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||||
import * as LogUtils from '../jest/logUtils';
|
import * as LogUtils from '../jest/logUtils';
|
||||||
import { act } from '../jest/customMatcher';
|
|
||||||
|
|
||||||
describe('合成焦点事件', () => {
|
describe('合成焦点事件', () => {
|
||||||
|
|
||||||
|
@ -43,4 +42,4 @@ describe('合成焦点事件', () => {
|
||||||
'onBlur: blur',
|
'onBlur: blur',
|
||||||
]);
|
]);
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
|
||||||
import * as LogUtils from '../jest/logUtils';
|
|
||||||
|
|
||||||
const Text = (props) => {
|
|
||||||
LogUtils.log(props.text);
|
|
||||||
return <p>{props.text}</p>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Text;
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||||
|
import * as LogUtils from './logUtils';
|
||||||
|
|
||||||
|
export const App = (props) => {
|
||||||
|
const Parent = props.parent;
|
||||||
|
const Child = props.child;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Parent>
|
||||||
|
<Child />
|
||||||
|
</Parent>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Text = (props) => {
|
||||||
|
LogUtils.log(props.text);
|
||||||
|
return <p id={props.id}>{props.text}</p>;
|
||||||
|
}
|
|
@ -1,33 +0,0 @@
|
||||||
import { runAsyncEffects } from '../../../libs/horizon/src/renderer/submit/HookEffectHandler';
|
|
||||||
import { callRenderQueueImmediate } from '../../../libs/horizon/src/renderer/taskExecutor/RenderQueue';
|
|
||||||
import { asyncUpdates } from '../../../libs/horizon/src/renderer/TreeBuilder';
|
|
||||||
|
|
||||||
function runAssertion(fn) {
|
|
||||||
try {
|
|
||||||
fn();
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
pass: false,
|
|
||||||
message: () => error.message,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return { pass: true };
|
|
||||||
}
|
|
||||||
|
|
||||||
function toMatchValue(LogUtils, expectedValues) {
|
|
||||||
return runAssertion(() => {
|
|
||||||
const actualValues = LogUtils.getAndClear();
|
|
||||||
expect(actualValues).toEqual(expectedValues);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const act = (fun) => {
|
|
||||||
asyncUpdates(fun);
|
|
||||||
callRenderQueueImmediate();
|
|
||||||
runAsyncEffects();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
toMatchValue,
|
|
||||||
act
|
|
||||||
};
|
|
|
@ -17,7 +17,27 @@ global.afterEach(() => {
|
||||||
LogUtils.clear();
|
LogUtils.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function runAssertion(fn) {
|
||||||
|
try {
|
||||||
|
fn();
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
pass: false,
|
||||||
|
message: () => error.message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { pass: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
function toMatchValue(LogUtils, expectedValues) {
|
||||||
|
return runAssertion(() => {
|
||||||
|
const actualValues = LogUtils.getAndClear();
|
||||||
|
expect(actualValues).toEqual(expectedValues);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 使Jest感知自定义匹配器
|
// 使Jest感知自定义匹配器
|
||||||
expect.extend({
|
expect.extend({
|
||||||
...require('./customMatcher'),
|
toMatchValue,
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,7 +9,7 @@ export const stopBubbleOrCapture = (e, value) => {
|
||||||
export const getEventListeners = (dom) => {
|
export const getEventListeners = (dom) => {
|
||||||
let ret = true
|
let ret = true
|
||||||
let keyArray = [];
|
let keyArray = [];
|
||||||
for (var key in dom) {
|
for (let key in dom) {
|
||||||
keyArray.push(key);
|
keyArray.push(key);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -23,4 +23,11 @@ export const getEventListeners = (dom) => {
|
||||||
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function triggerClickEvent(container, id) {
|
||||||
|
const event = new MouseEvent('click', {
|
||||||
|
bubbles: true,
|
||||||
|
});
|
||||||
|
container.querySelector(`#${id}`).dispatchEvent(event);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue