Match-id-0b029a7f0823812017af1a6f83f4b34a1bcff165
This commit is contained in:
parent
d820471f30
commit
8bf64ab1c1
|
@ -11,7 +11,8 @@ module.exports = {
|
|||
testEnvironment: 'jest-environment-jsdom-sixteen',
|
||||
|
||||
testMatch: [
|
||||
'<rootDir>/scripts/__tests__/**/*.test.js'
|
||||
'<rootDir>/scripts/__tests__/**/*.test.js',
|
||||
'<rootDir>/scripts/__tests__/**/*.test.tsx'
|
||||
],
|
||||
|
||||
timers: 'fake',
|
||||
|
|
|
@ -1,14 +1,38 @@
|
|||
import { createStore as createStoreX } from '../store/StoreHandler';
|
||||
|
||||
import { ReduxStoreHandler, ReduxAction, ReduxMiddleware } from '../types';
|
||||
import { ReduxStoreHandler } from '../store/StoreHandler';
|
||||
|
||||
export { thunk } from './reduxThunk';
|
||||
|
||||
export { Provider, useSelector, useStore, useDispatch, connect, createSelectorHook, createDispatchHook } from './reduxReact';
|
||||
export {
|
||||
Provider,
|
||||
useSelector,
|
||||
useStore,
|
||||
useDispatch,
|
||||
connect,
|
||||
createSelectorHook,
|
||||
createDispatchHook,
|
||||
} from './reduxReact';
|
||||
|
||||
export type ReduxAction = {
|
||||
type: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
export type ReduxMiddleware = (
|
||||
store: ReduxStoreHandler,
|
||||
extraArgument?: any
|
||||
) => (
|
||||
next: (action: ReduxAction) => any
|
||||
) => (
|
||||
action:
|
||||
| ReduxAction
|
||||
| ((dispatch: (action: ReduxAction) => void, store: ReduxStoreHandler, extraArgument?: any) => any)
|
||||
) => ReduxStoreHandler;
|
||||
|
||||
type Reducer = (state: any, action: ReduxAction) => any;
|
||||
|
||||
export function createStore(reducer: Reducer, preloadedState: any, enhancers): ReduxStoreHandler {
|
||||
export function createStore(reducer: Reducer, preloadedState?: any, enhancers?): ReduxStoreHandler {
|
||||
const store = createStoreX({
|
||||
id: 'defaultStore',
|
||||
state: { stateWrapper: preloadedState },
|
||||
|
@ -35,7 +59,7 @@ export function createStore(reducer: Reducer, preloadedState: any, enhancers): R
|
|||
const result = {
|
||||
reducer,
|
||||
getState: function() {
|
||||
return store.$state.stateWrapper;
|
||||
return store.$s.stateWrapper;
|
||||
},
|
||||
subscribe: listener => {
|
||||
store.$subscribe(listener);
|
||||
|
@ -48,7 +72,7 @@ export function createStore(reducer: Reducer, preloadedState: any, enhancers): R
|
|||
reducer = newReducer;
|
||||
},
|
||||
_horizonXstore: store,
|
||||
dispatch: store.$actions.dispatch,
|
||||
dispatch: store.$a.dispatch,
|
||||
};
|
||||
|
||||
enhancers && enhancers(result);
|
||||
|
@ -117,7 +141,6 @@ export function compose(middlewares: ReduxMiddleware[]) {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
// HorizonX batches updates by default, this function is only for backwards compatibility
|
||||
export function batch(fn: () => void) {
|
||||
fn();
|
||||
|
|
|
@ -3,9 +3,10 @@ import { useState, useContext, useEffect, useRef } from '../../renderer/hooks/Ho
|
|||
import { createContext } from '../../renderer/components/context/CreateContext';
|
||||
import { createElement } from '../../external/JSXElement';
|
||||
import { BoundActionCreator } from './redux';
|
||||
import { ReduxAction, ReduxStoreHandler } from '../types';
|
||||
import { ReduxAction } from './redux';
|
||||
import { ReduxStoreHandler } from '../store/StoreHandler'
|
||||
|
||||
const DefaultContext = createContext();
|
||||
const DefaultContext = createContext(null);
|
||||
type Context = typeof DefaultContext;
|
||||
|
||||
export function Provider({
|
||||
|
@ -27,8 +28,8 @@ export function createStoreHook(context: Context) {
|
|||
};
|
||||
}
|
||||
|
||||
export function createSelectorHook(context: Context): (selector: (any) => any) => any {
|
||||
const store = createStoreHook(context)();
|
||||
export function createSelectorHook(context: Context): (selector?: (any) => any) => any {
|
||||
const store = (createStoreHook(context)() as unknown) as ReduxStoreHandler;
|
||||
return function(selector = state => state) {
|
||||
const [b, fr] = useState(false);
|
||||
|
||||
|
@ -37,22 +38,18 @@ export function createSelectorHook(context: Context): (selector: (any) => any) =
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
const unsubscribe = store.subscribe(listener);
|
||||
|
||||
return () => {
|
||||
unsubscribe(listener);
|
||||
};
|
||||
return store.subscribe(listener);
|
||||
});
|
||||
|
||||
return selector(store.getState());
|
||||
};
|
||||
}
|
||||
|
||||
export function createDispatchHook(context: Context): BoundActionCreator {
|
||||
const store = createStoreHook(context)();
|
||||
export function createDispatchHook(context: Context): ()=>BoundActionCreator {
|
||||
const store = (createStoreHook(context)() as unknown) as ReduxStoreHandler;
|
||||
return function() {
|
||||
return action => {
|
||||
this.dispatch(action);
|
||||
store.dispatch(action);
|
||||
};
|
||||
}.bind(store);
|
||||
}
|
||||
|
@ -104,26 +101,32 @@ export function connect(
|
|||
}
|
||||
|
||||
return Component => {
|
||||
const useStore = createStoreHook(options.context || DefaultContext);
|
||||
const useStore = createStoreHook(options?.context || DefaultContext);
|
||||
|
||||
function Wrapper(props) {
|
||||
const [f, forceReload] = useState(true);
|
||||
|
||||
const store = useStore();
|
||||
const store = (useStore() as unknown) as ReduxStoreHandler;
|
||||
|
||||
useEffect(() => {
|
||||
const unsubscribe = store.subscribe(() => forceReload(!f));
|
||||
() => {
|
||||
unsubscribe(() => forceReload(!f));
|
||||
unsubscribe();
|
||||
};
|
||||
});
|
||||
|
||||
const previous = useRef({
|
||||
state: {},
|
||||
});
|
||||
mappedState: {},
|
||||
}) as {
|
||||
current: {
|
||||
state: {};
|
||||
mappedState: {};
|
||||
};
|
||||
};
|
||||
|
||||
let mappedState;
|
||||
if (options.areStatesEqual) {
|
||||
if (options?.areStatesEqual) {
|
||||
if (options.areStatesEqual(previous.current.state, store.getState())) {
|
||||
mappedState = previous.current.mappedState;
|
||||
} else {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { ReduxStoreHandler, ReduxAction, ReduxMiddleware } from '../types';
|
||||
import { ReduxAction, ReduxMiddleware } from './redux';
|
||||
import { ReduxStoreHandler } from '../store/StoreHandler';
|
||||
|
||||
function createThunkMiddleware(extraArgument?: any): ReduxMiddleware {
|
||||
return (store: ReduxStoreHandler) => (next: (action: ReduxAction) => any) => (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// TODO: implement vNode type
|
||||
|
||||
import {IObserver} from '../types';
|
||||
import {IObserver} from './Observer';
|
||||
|
||||
/**
|
||||
* 一个对象(对象、数组、集合)对应一个Observer
|
||||
|
|
|
@ -6,7 +6,24 @@
|
|||
import { launchUpdateFromVNode } from '../../renderer/TreeBuilder';
|
||||
import { getProcessingVNode } from '../../renderer/GlobalVar';
|
||||
import { VNode } from '../../renderer/vnode/VNode';
|
||||
import { IObserver } from '../types';
|
||||
export interface IObserver {
|
||||
|
||||
useProp: (key: string) => void;
|
||||
|
||||
addListener: (listener: () => void) => void;
|
||||
|
||||
removeListener: (listener: () => void) => void;
|
||||
|
||||
setProp: (key: string) => void;
|
||||
|
||||
triggerChangeListeners: () => void;
|
||||
|
||||
triggerUpdate: (vNode: any) => void;
|
||||
|
||||
allChange: () => void;
|
||||
|
||||
clearByVNode: (vNode: any) => void;
|
||||
}
|
||||
|
||||
export class Observer implements IObserver {
|
||||
|
||||
|
|
|
@ -3,31 +3,88 @@ import { useEffect, useRef } from '../../renderer/hooks/HookExternal';
|
|||
import { getProcessingVNode } from '../../renderer/GlobalVar';
|
||||
import { createProxy } from '../proxy/ProxyHandler';
|
||||
import readonlyProxy from '../proxy/readonlyProxy';
|
||||
import { StoreHandler, StoreConfig, UserActions, UserComputedValues, StoreActions, ComputedValues, ActionFunction, Action, QueuedStoreActions } from '../types';
|
||||
import { Observer } from '../proxy/Observer';
|
||||
import { FunctionComponent, ClassComponent } from '../Constants';
|
||||
import { VNode } from '../../renderer/Types';
|
||||
|
||||
const storeMap = new Map<string,StoreHandler<any,any,any>>();
|
||||
const storeMap = new Map<string, StoreHandler<any, any, any>>();
|
||||
|
||||
function isPromise(obj: any): boolean {
|
||||
return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
|
||||
}
|
||||
|
||||
type PlannedAction<S extends object,F extends ActionFunction<S>>={
|
||||
action:string,
|
||||
payload: any[],
|
||||
resolve: ReturnType<F>
|
||||
}
|
||||
type StoreConfig<S extends object, A extends UserActions<S>, C extends UserComputedValues<S>> = {
|
||||
state?: S;
|
||||
options?: { suppressHooks?: boolean };
|
||||
actions?: A;
|
||||
id?: string;
|
||||
computed?: C;
|
||||
};
|
||||
|
||||
export function createStore<S extends object,A extends UserActions<S>,C extends UserComputedValues<S>>(config: StoreConfig<S,A,C>): () => StoreHandler<S,A,C> {
|
||||
export type ReduxStoreHandler = {
|
||||
reducer: (state: any, action: { type: string }) => any;
|
||||
dispatch: (action: { type: string }) => void;
|
||||
getState: () => any;
|
||||
subscribe: (listener: () => void) => () => void;
|
||||
replaceReducer: (reducer: (state: any, action: { type: string }) => any) => void;
|
||||
_horizonXstore: StoreHandler<any, any, any>;
|
||||
};
|
||||
|
||||
type StoreHandler<S extends object, A extends UserActions<S>, C extends UserComputedValues<S>> = {
|
||||
$subscribe: (listener: () => void) => void;
|
||||
$unsubscribe: (listener: () => void) => void;
|
||||
$s: S;
|
||||
$config: StoreConfig<S, A, C>;
|
||||
$queue: QueuedStoreActions<S, A>;
|
||||
$a: StoreActions<S, A>;
|
||||
$c: UserComputedValues<S>;
|
||||
reduxHandler?: ReduxStoreHandler;
|
||||
} & { [K in keyof S]: S[K] } &
|
||||
{ [K in keyof A]: Action<A[K], S> } &
|
||||
{ [K in keyof C]: ReturnType<C[K]> };
|
||||
|
||||
type PlannedAction<S extends object, F extends ActionFunction<S>> = {
|
||||
action: string;
|
||||
payload: any[];
|
||||
resolve: ReturnType<F>;
|
||||
};
|
||||
type RemoveFirstFromTuple<T extends any[]> = T['length'] extends 0
|
||||
? []
|
||||
: ((...b: T) => void) extends (a, ...b: infer I) => void
|
||||
? I
|
||||
: [];
|
||||
|
||||
type UserActions<S extends object> = { [K: string]: ActionFunction<S> };
|
||||
type UserComputedValues<S extends object> = { [K: string]: ComputedFunction<S> };
|
||||
|
||||
type ActionFunction<S extends object> = (this: StoreHandler<S, any, any>, state: S, ...args: any[]) => any;
|
||||
type ComputedFunction<S extends object> = (state: S) => any;
|
||||
type Action<T extends ActionFunction<any>, S extends object> = (
|
||||
this: StoreHandler<S, any, any>,
|
||||
...args: RemoveFirstFromTuple<Parameters<T>>
|
||||
) => ReturnType<T>;
|
||||
type AsyncAction<T extends ActionFunction<any>, S extends object> = (
|
||||
this: StoreHandler<S, any, any>,
|
||||
...args: RemoveFirstFromTuple<Parameters<T>>
|
||||
) => Promise<ReturnType<T>>;
|
||||
|
||||
type StoreActions<S extends object, A extends UserActions<S>> = { [K in keyof A]: Action<A[K], S> };
|
||||
type QueuedStoreActions<S extends object, A extends UserActions<S>> = { [K in keyof A]: AsyncAction<A[K], S> };
|
||||
type ComputedValues<S extends object, C extends UserComputedValues<S>> = { [K in keyof C]: ReturnType<C[K]> };
|
||||
type PostponedAction = (state: object, ...args: any[]) => Promise<any>;
|
||||
type PostponedActions = { [key: string]: PostponedAction };
|
||||
|
||||
export function createStore<S extends object, A extends UserActions<S>, C extends UserComputedValues<S>>(
|
||||
config: StoreConfig<S, A, C>
|
||||
): () => StoreHandler<S, A, C> {
|
||||
//create a local shalow copy to ensure consistency (if user would change the config object after store creation)
|
||||
config = {
|
||||
id:config.id,
|
||||
id: config.id,
|
||||
options: config.options,
|
||||
state: config.state,
|
||||
actions: config.actions ? {...config.actions}:undefined,
|
||||
computed: config.computed ? {...config.computed}:undefined
|
||||
}
|
||||
actions: config.actions ? { ...config.actions } : undefined,
|
||||
computed: config.computed ? { ...config.computed } : undefined,
|
||||
};
|
||||
|
||||
// 校验
|
||||
if (Object.prototype.toString.call(config) !== '[object Object]') {
|
||||
|
@ -38,27 +95,27 @@ export function createStore<S extends object,A extends UserActions<S>,C extends
|
|||
|
||||
proxyObj.$pending = false;
|
||||
|
||||
const $subscribe = (listener) => {
|
||||
const $subscribe = listener => {
|
||||
proxyObj.addListener(listener);
|
||||
};
|
||||
|
||||
const $unsubscribe = (listener) => {
|
||||
const $unsubscribe = listener => {
|
||||
proxyObj.removeListener(listener);
|
||||
};
|
||||
|
||||
const plannedActions:PlannedAction<S,ActionFunction<S>>[] = [];
|
||||
const $actions:Partial<StoreActions<S,A>>={}
|
||||
const $queue:Partial<StoreActions<S,A>> = {};
|
||||
const $computed:Partial<ComputedValues<S,C>>={}
|
||||
const handler = {
|
||||
const plannedActions: PlannedAction<S, ActionFunction<S>>[] = [];
|
||||
const $a: Partial<StoreActions<S, A>> = {};
|
||||
const $queue: Partial<StoreActions<S, A>> = {};
|
||||
const $c: Partial<ComputedValues<S, C>> = {};
|
||||
const handler = ({
|
||||
$subscribe,
|
||||
$unsubscribe,
|
||||
$actions:$actions as StoreActions<S,A>,
|
||||
$state:proxyObj,
|
||||
$computed: $computed as ComputedValues<S,C>,
|
||||
$config:config,
|
||||
$queue: $queue as QueuedStoreActions<S,A>,
|
||||
} as StoreHandler<S,A,C>;
|
||||
$a: $a as StoreActions<S, A>,
|
||||
$s: proxyObj,
|
||||
$c: $c as ComputedValues<S, C>,
|
||||
$config: config,
|
||||
$queue: $queue as QueuedStoreActions<S, A>,
|
||||
} as unknown) as StoreHandler<S, A, C>;
|
||||
|
||||
function tryNextAction() {
|
||||
if (!plannedActions.length) {
|
||||
|
@ -67,7 +124,9 @@ export function createStore<S extends object,A extends UserActions<S>,C extends
|
|||
}
|
||||
|
||||
const nextAction = plannedActions.shift()!;
|
||||
const result = config.actions ? config.actions[nextAction.action].bind(self, proxyObj)(...nextAction.payload) : undefined;
|
||||
const result = config.actions
|
||||
? config.actions[nextAction.action].bind(handler, proxyObj)(...nextAction.payload)
|
||||
: undefined;
|
||||
|
||||
if (isPromise(result)) {
|
||||
result.then(value => {
|
||||
|
@ -81,16 +140,16 @@ export function createStore<S extends object,A extends UserActions<S>,C extends
|
|||
}
|
||||
|
||||
// 包装actions
|
||||
if(config.actions){
|
||||
if (config.actions) {
|
||||
Object.keys(config.actions).forEach(action => {
|
||||
($queue as any)[action] = (...payload) => {
|
||||
return new Promise((resolve) => {
|
||||
return new Promise(resolve => {
|
||||
if (!proxyObj.$pending) {
|
||||
proxyObj.$pending = true;
|
||||
const result = config.actions![action].bind(self, proxyObj)(...payload);
|
||||
const result = config.actions![action].bind(handler, proxyObj)(...payload);
|
||||
|
||||
if (isPromise(result)) {
|
||||
result.then((value) => {
|
||||
result.then(value => {
|
||||
resolve(value);
|
||||
tryNextAction();
|
||||
});
|
||||
|
@ -102,40 +161,42 @@ export function createStore<S extends object,A extends UserActions<S>,C extends
|
|||
plannedActions.push({
|
||||
action,
|
||||
payload,
|
||||
resolve
|
||||
resolve,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
($actions as any)[action] = function Wrapped(...payload) {
|
||||
return config.actions![action].bind(self, proxyObj)(...payload);
|
||||
($a as any)[action] = function Wrapped(...payload) {
|
||||
return config.actions![action].bind(handler, proxyObj)(...payload);
|
||||
};
|
||||
|
||||
// direct store access
|
||||
Object.defineProperty(handler, action, {
|
||||
writable: false,
|
||||
value: $actions[action]
|
||||
value: (...payload) => {
|
||||
return config.actions![action].bind(handler, proxyObj)(...payload);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (config.computed) {
|
||||
Object.keys(config.computed).forEach((key) => {
|
||||
($computed as any)[key] = config.computed![key].bind(handler, readonlyProxy(proxyObj));
|
||||
Object.keys(config.computed).forEach(key => {
|
||||
($c as any)[key] = config.computed![key].bind(handler, readonlyProxy(proxyObj));
|
||||
|
||||
// direct store access
|
||||
Object.defineProperty(handler, key, {
|
||||
get: $computed[key] as ()=>any
|
||||
get: $c[key] as () => any,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// direct state access
|
||||
if(config.state){
|
||||
if (config.state) {
|
||||
Object.keys(config.state).forEach(key => {
|
||||
Object.defineProperty(handler, key, {
|
||||
get: () => proxyObj[key]
|
||||
get: () => proxyObj[key],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -172,7 +233,7 @@ function hookStore() {
|
|||
|
||||
if (processingVNode.tag === FunctionComponent) {
|
||||
// from FunctionComponent
|
||||
const vNodeRef = useRef(null);
|
||||
const vNodeRef = (useRef(null) as unknown) as { current: VNode };
|
||||
vNodeRef.current = processingVNode;
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -211,9 +272,9 @@ export function useStore<S extends object, A extends UserActions<S>, C extends U
|
|||
|
||||
if (storeObj && !storeObj.$config.options?.suppressHooks) hookStore();
|
||||
|
||||
return storeObj as StoreHandler<S,A,C>;
|
||||
return storeObj as StoreHandler<S, A, C>;
|
||||
}
|
||||
|
||||
export function clearStore(id:string):void {
|
||||
export function clearStore(id: string): void {
|
||||
storeMap.delete(id);
|
||||
}
|
|
@ -5,11 +5,12 @@
|
|||
],
|
||||
"scripts": {
|
||||
"lint": "eslint . --ext .ts",
|
||||
"build": " rollup --config ./scripts/rollup/rollup.config.js",
|
||||
"build:watch": " rollup --watch --config ./scripts/rollup/rollup.config.js",
|
||||
"build": "rollup --config ./scripts/rollup/rollup.config.js",
|
||||
"build:watch": "rollup --watch --config ./scripts/rollup/rollup.config.js",
|
||||
"build-3rdLib": "node ./scripts/gen3rdLib.js",
|
||||
"build-3rdLib-dev": "npm run build & node ./scripts/gen3rdLib.js --dev",
|
||||
"build-horizon3rdLib-dev": "npm run build & node ./scripts/gen3rdLib.js --dev --type horizon",
|
||||
"build-types": "tsc -p ./libs/horizon/index.ts --emitDeclarationOnly --declaration --declarationDir ./build/horizon/@types --skipLibCheck",
|
||||
"debug-test": "yarn test --debug",
|
||||
"test": "jest --config=jest.config.js",
|
||||
"watch-test": "yarn test --watch --dev"
|
||||
|
@ -56,6 +57,7 @@
|
|||
"jest-environment-jsdom-sixteen": "^1.0.3",
|
||||
"prettier": "2.6.2",
|
||||
"rollup": "^2.75.5",
|
||||
"rollup-plugin-execute": "^1.1.1",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"typescript": "4.2.3"
|
||||
},
|
||||
|
|
|
@ -1,201 +0,0 @@
|
|||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { clearStore, createStore, useStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { App, Text, triggerClickEvent } from '../../jest/commonComponents';
|
||||
|
||||
describe('测试store中的Array', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
const persons = [
|
||||
{ name: 'p1', age: 1 },
|
||||
{ name: 'p2', age: 2 },
|
||||
];
|
||||
|
||||
createStore({
|
||||
id: 'user',
|
||||
state: {
|
||||
type: 'bing dun dun',
|
||||
persons: persons,
|
||||
},
|
||||
actions: {
|
||||
addOnePerson: (state, person) => {
|
||||
state.persons.push(person);
|
||||
},
|
||||
delOnePerson: state => {
|
||||
state.persons.pop();
|
||||
},
|
||||
clearPersons: state => {
|
||||
state.persons = null;
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container = null;
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
||||
const newPerson = { name: 'p3', age: 3 };
|
||||
|
||||
function Parent(props) {
|
||||
const userStore = useStore('user');
|
||||
const addOnePerson = function() {
|
||||
userStore.addOnePerson(newPerson);
|
||||
};
|
||||
const delOnePerson = function() {
|
||||
userStore.delOnePerson();
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<button id={'addBtn'} onClick={addOnePerson}>
|
||||
add person
|
||||
</button>
|
||||
<button id={'delBtn'} onClick={delOnePerson}>
|
||||
delete person
|
||||
</button>
|
||||
<div>{props.children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
it('测试Array方法: push()、pop()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'hasPerson'} text={`has new person: ${userStore.$state.persons.length}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: 2');
|
||||
// 在Array中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: 3');
|
||||
|
||||
// 在Array中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: 2');
|
||||
});
|
||||
|
||||
it('测试Array方法: entries()、push()、shift()、unshift、直接赋值', () => {
|
||||
let globalStore = null;
|
||||
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
globalStore = userStore;
|
||||
|
||||
const nameList = [];
|
||||
const entries = userStore.$state.persons?.entries();
|
||||
if (entries) {
|
||||
for (const entry of entries) {
|
||||
nameList.push(entry[1].name);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'nameList'} text={`name list: ${nameList.join(' ')}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
// push
|
||||
globalStore.$state.persons.push(newPerson);
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// shift
|
||||
globalStore.$state.persons.shift({ name: 'p0', age: 0 });
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p2 p3');
|
||||
|
||||
// 赋值[2]
|
||||
globalStore.$state.persons[2] = { name: 'p4', age: 4 };
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p2 p3 p4');
|
||||
|
||||
// 重新赋值[2]
|
||||
globalStore.$state.persons[2] = { name: 'p5', age: 5 };
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p2 p3 p5');
|
||||
|
||||
// unshift
|
||||
globalStore.$state.persons.unshift({ name: 'p1', age: 1 });
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3 p5');
|
||||
|
||||
// 重新赋值 null
|
||||
globalStore.$state.persons = null;
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
|
||||
// 重新赋值 [{ name: 'p1', age: 1 }]
|
||||
globalStore.$state.persons = [{ name: 'p1', age: 1 }];
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1');
|
||||
});
|
||||
|
||||
it('测试Array方法: forEach()', () => {
|
||||
let globalStore = null;
|
||||
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
globalStore = userStore;
|
||||
|
||||
const nameList = [];
|
||||
userStore.$state.persons?.forEach(per => {
|
||||
nameList.push(per.name);
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'nameList'} text={`name list: ${nameList.join(' ')}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
// push
|
||||
globalStore.$state.persons.push(newPerson);
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// shift
|
||||
globalStore.$state.persons.shift({ name: 'p0', age: 0 });
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p2 p3');
|
||||
|
||||
// 赋值[2]
|
||||
globalStore.$state.persons[2] = { name: 'p4', age: 4 };
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p2 p3 p4');
|
||||
|
||||
// 重新赋值[2]
|
||||
globalStore.$state.persons[2] = { name: 'p5', age: 5 };
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p2 p3 p5');
|
||||
|
||||
// unshift
|
||||
globalStore.$state.persons.unshift({ name: 'p1', age: 1 });
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3 p5');
|
||||
|
||||
// 重新赋值 null
|
||||
globalStore.$state.persons = null;
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
|
||||
// 重新赋值 [{ name: 'p1', age: 1 }]
|
||||
globalStore.$state.persons = [{ name: 'p1', age: 1 }];
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,208 @@
|
|||
//@ts-ignore
|
||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import * as LogUtils from '../../jest/logUtils';
|
||||
import { clearStore, createStore, useStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { App, Text, triggerClickEvent } from '../../jest/commonComponents';
|
||||
import { describe, beforeEach, afterEach, it, expect } from '@jest/globals';
|
||||
|
||||
const useUserStore = createStore({
|
||||
id: 'user',
|
||||
state: {
|
||||
type: 'bing dun dun',
|
||||
persons: [
|
||||
{ name: 'p1', age: 1 },
|
||||
{ name: 'p2', age: 2 },
|
||||
],
|
||||
},
|
||||
actions: {
|
||||
addOnePerson: (state, person) => {
|
||||
state.persons.push(person);
|
||||
},
|
||||
delOnePerson: state => {
|
||||
state.persons.pop();
|
||||
},
|
||||
clearPersons: state => {
|
||||
state.persons = [];
|
||||
},
|
||||
reset: state => {
|
||||
state.persons = [
|
||||
{ name: 'p1', age: 1 },
|
||||
{ name: 'p2', age: 2 },
|
||||
];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
describe('测试store中的Array', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container: HTMLElement | null = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
useUserStore().reset();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container?.remove();
|
||||
container = null;
|
||||
LogUtils.clear();
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
||||
const newPerson = { name: 'p3', age: 3 };
|
||||
function Parent(props) {
|
||||
const userStore = useUserStore();
|
||||
const addOnePerson = function() {
|
||||
userStore.addOnePerson(newPerson);
|
||||
};
|
||||
const delOnePerson = function() {
|
||||
userStore.delOnePerson();
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<button id={'addBtn'} onClick={addOnePerson}>
|
||||
add person
|
||||
</button>
|
||||
<button id={'delBtn'} onClick={delOnePerson}>
|
||||
delete person
|
||||
</button>
|
||||
<div>{props.children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
it('测试Array方法: push()、pop()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useUserStore();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'hasPerson'} text={`has new person: ${userStore.$s.persons.length}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: 2');
|
||||
// 在Array中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: 3');
|
||||
|
||||
// 在Array中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: 2');
|
||||
});
|
||||
|
||||
it('测试Array方法: entries()、push()、shift()、unshift、直接赋值', () => {
|
||||
let globalStore = useUserStore();
|
||||
function Child(props) {
|
||||
const userStore = useUserStore();
|
||||
|
||||
const nameList: string[] = [];
|
||||
const entries = userStore.$s.persons?.entries();
|
||||
if (entries) {
|
||||
for (const entry of entries) {
|
||||
nameList.push(entry[1].name);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'nameList'} text={`name list: ${nameList.join(' ')}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// push
|
||||
globalStore.$s.persons.push(newPerson);
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// shift
|
||||
//@ts-ignore TODO:why is this argument here?
|
||||
globalStore.$s.persons.shift({ name: 'p0', age: 0 });
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p2 p3');
|
||||
|
||||
// 赋值[2]
|
||||
globalStore.$s.persons[2] = { name: 'p4', age: 4 };
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p2 p3 p4');
|
||||
|
||||
// 重新赋值[2]
|
||||
globalStore.$s.persons[2] = { name: 'p5', age: 5 };
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p2 p3 p5');
|
||||
|
||||
// unshift
|
||||
globalStore.$s.persons.unshift({ name: 'p1', age: 1 });
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3 p5');
|
||||
|
||||
// 重新赋值 []
|
||||
globalStore.$s.persons = [];
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
|
||||
// 重新赋值 [{ name: 'p1', age: 1 }]
|
||||
globalStore.$s.persons = [{ name: 'p1', age: 1 }];
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1');
|
||||
});
|
||||
|
||||
it('测试Array方法: forEach()', () => {
|
||||
let globalStore = useUserStore();
|
||||
function Child(props) {
|
||||
const userStore = useUserStore();
|
||||
|
||||
const nameList: string[] = [];
|
||||
userStore.$s.persons?.forEach(per => {
|
||||
nameList.push(per.name);
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'nameList'} text={`name list: ${nameList.join(' ')}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// push
|
||||
globalStore.$s.persons.push(newPerson);
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// shift
|
||||
//@ts-ignore TODO: why is this argument here?
|
||||
globalStore.$s.persons.shift({ name: 'p0', age: 0 });
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p2 p3');
|
||||
|
||||
// 赋值[2]
|
||||
globalStore.$s.persons[2] = { name: 'p4', age: 4 };
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p2 p3 p4');
|
||||
|
||||
// 重新赋值[2]
|
||||
globalStore.$s.persons[2] = { name: 'p5', age: 5 };
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p2 p3 p5');
|
||||
|
||||
// unshift
|
||||
globalStore.$s.persons.unshift({ name: 'p1', age: 1 });
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3 p5');
|
||||
|
||||
// 重新赋值 []
|
||||
globalStore.$s.persons = [];
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
|
||||
// 重新赋值 [{ name: 'p1', age: 1 }]
|
||||
globalStore.$s.persons = [{ name: 'p1', age: 1 }];
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1');
|
||||
});
|
||||
});
|
|
@ -1,25 +1,18 @@
|
|||
//@ts-ignore
|
||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import * as LogUtils from '../../jest/logUtils';
|
||||
import { clearStore, createStore, useStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { App, Text, triggerClickEvent } from '../../jest/commonComponents';
|
||||
import { describe, beforeEach, afterEach, it, expect } from '@jest/globals';
|
||||
|
||||
describe('测试store中的Map', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
const persons = new Map([
|
||||
['p1', 1],
|
||||
['p2', 2],
|
||||
]);
|
||||
|
||||
createStore({
|
||||
const useUserStore = createStore({
|
||||
id: 'user',
|
||||
state: {
|
||||
type: 'bing dun dun',
|
||||
persons: persons,
|
||||
persons: new Map([
|
||||
['p1', 1],
|
||||
['p2', 2],
|
||||
]),
|
||||
},
|
||||
actions: {
|
||||
addOnePerson: (state, person) => {
|
||||
|
@ -31,15 +24,32 @@ describe('测试store中的Map', () => {
|
|||
clearPersons: state => {
|
||||
state.persons.clear();
|
||||
},
|
||||
reset: state => {
|
||||
state.persons = new Map([
|
||||
['p1', 1],
|
||||
['p2', 2],
|
||||
]);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
describe('测试store中的Map', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container: HTMLElement | null = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
useUserStore().reset();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container?.remove();
|
||||
container = null;
|
||||
LogUtils.clear();
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
@ -47,7 +57,7 @@ describe('测试store中的Map', () => {
|
|||
const newPerson = { name: 'p3', age: 3 };
|
||||
|
||||
function Parent(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
const addOnePerson = function() {
|
||||
userStore.addOnePerson(newPerson);
|
||||
};
|
||||
|
@ -76,43 +86,43 @@ describe('测试store中的Map', () => {
|
|||
|
||||
it('测试Map方法: set()、delete()、clear()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'size'} text={`persons number: ${userStore.$state.persons.size}`} />
|
||||
<Text id={'size'} text={`persons number: ${userStore.$s.persons.size}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#size').innerHTML).toBe('persons number: 2');
|
||||
expect(container?.querySelector('#size')?.innerHTML).toBe('persons number: 2');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#size').innerHTML).toBe('persons number: 3');
|
||||
expect(container?.querySelector('#size')?.innerHTML).toBe('persons number: 3');
|
||||
|
||||
// 在Map中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#size').innerHTML).toBe('persons number: 2');
|
||||
expect(container?.querySelector('#size')?.innerHTML).toBe('persons number: 2');
|
||||
|
||||
// clear Map
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#size').innerHTML).toBe('persons number: 0');
|
||||
expect(container?.querySelector('#size')?.innerHTML).toBe('persons number: 0');
|
||||
});
|
||||
|
||||
it('测试Map方法: keys()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
const nameList = [];
|
||||
const keys = userStore.$state.persons.keys();
|
||||
const nameList: string[] = [];
|
||||
const keys = userStore.$s.persons.keys();
|
||||
for (const key of keys) {
|
||||
nameList.push(key);
|
||||
}
|
||||
|
@ -126,32 +136,32 @@ describe('测试store中的Map', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// 在Map中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
|
||||
// clear Map
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
});
|
||||
|
||||
it('测试Map方法: values()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
const ageList = [];
|
||||
const values = userStore.$state.persons.values();
|
||||
const ageList: number[] = [];
|
||||
const values = userStore.$s.persons.values();
|
||||
for (const val of values) {
|
||||
ageList.push(val);
|
||||
}
|
||||
|
@ -165,32 +175,32 @@ describe('测试store中的Map', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#ageList').innerHTML).toBe('age list: 1 2');
|
||||
expect(container?.querySelector('#ageList')?.innerHTML).toBe('age list: 1 2');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#ageList').innerHTML).toBe('age list: 1 2 3');
|
||||
expect(container?.querySelector('#ageList')?.innerHTML).toBe('age list: 1 2 3');
|
||||
|
||||
// 在Map中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#ageList').innerHTML).toBe('age list: 1 2');
|
||||
expect(container?.querySelector('#ageList')?.innerHTML).toBe('age list: 1 2');
|
||||
|
||||
// clear Map
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#ageList').innerHTML).toBe('age list: ');
|
||||
expect(container?.querySelector('#ageList')?.innerHTML).toBe('age list: ');
|
||||
});
|
||||
|
||||
it('测试Map方法: entries()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
const nameList = [];
|
||||
const entries = userStore.$state.persons.entries();
|
||||
const nameList: string[] = [];
|
||||
const entries = userStore.$s.persons.entries();
|
||||
for (const entry of entries) {
|
||||
nameList.push(entry[0]);
|
||||
}
|
||||
|
@ -204,32 +214,32 @@ describe('测试store中的Map', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// 在Map中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
|
||||
// clear Map
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
});
|
||||
|
||||
it('测试Map方法: forEach()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
const nameList = [];
|
||||
userStore.$state.persons.forEach((val, key) => {
|
||||
const nameList: string[] = [];
|
||||
userStore.$s.persons.forEach((val, key) => {
|
||||
nameList.push(key);
|
||||
});
|
||||
|
||||
|
@ -242,53 +252,53 @@ describe('测试store中的Map', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// 在Map中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
|
||||
// clear Map
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
});
|
||||
|
||||
it('测试Map方法: has()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'hasPerson'} text={`has new person: ${userStore.$state.persons.has(newPerson.name)}`} />
|
||||
<Text id={'hasPerson'} text={`has new person: ${userStore.$s.persons.has(newPerson.name)}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: false');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: false');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: true');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: true');
|
||||
});
|
||||
|
||||
it('测试Map方法: for of()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
const nameList = [];
|
||||
for (const per of userStore.$state.persons) {
|
||||
const nameList: string[] = [];
|
||||
for (const per of userStore.$s.persons) {
|
||||
nameList.push(per[0]);
|
||||
}
|
||||
|
||||
|
@ -301,23 +311,23 @@ describe('测试store中的Map', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// 在Map中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
|
||||
// clear Map
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
});
|
||||
});
|
|
@ -1,10 +1,12 @@
|
|||
//@ts-ignore
|
||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import * as LogUtils from '../../jest/logUtils';
|
||||
import { clearStore, createStore, useStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { App, Text, triggerClickEvent } from '../../jest/commonComponents';
|
||||
|
||||
describe('测试store中的混合类型变化', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container = null;
|
||||
let container: HTMLElement | null = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
|
@ -42,8 +44,9 @@ describe('测试store中的混合类型变化', () => {
|
|||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
(container as HTMLElement).remove();
|
||||
container = null;
|
||||
LogUtils.clear();
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
@ -68,7 +71,7 @@ describe('测试store中的混合类型变化', () => {
|
|||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
|
||||
const days = userStore.$state.persons
|
||||
const days = userStore.persons
|
||||
.values()
|
||||
.next()
|
||||
.value.love.get('lanqiu').days;
|
||||
|
@ -82,11 +85,11 @@ describe('测试store中的混合类型变化', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#dayList').innerHTML).toBe('love: 1 3 5');
|
||||
expect(container?.querySelector('#dayList')?.innerHTML).toBe('love: 1 3 5');
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#dayList').innerHTML).toBe('love: 1 3 5 7');
|
||||
expect(container?.querySelector('#dayList')?.innerHTML).toBe('love: 1 3 5 7');
|
||||
});
|
||||
|
||||
it('属性是个class实例', () => {
|
||||
|
@ -103,7 +106,6 @@ describe('测试store中的混合类型变化', () => {
|
|||
setName(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
@ -111,7 +113,6 @@ describe('测试store中的混合类型变化', () => {
|
|||
setAge(age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
getAge() {
|
||||
return this.age;
|
||||
}
|
||||
|
@ -119,7 +120,6 @@ describe('测试store中的混合类型变化', () => {
|
|||
addLove(lv) {
|
||||
this.loves.add(lv);
|
||||
}
|
||||
|
||||
getLoves() {
|
||||
return this.loves;
|
||||
}
|
||||
|
@ -127,14 +127,19 @@ describe('测试store中的混合类型变化', () => {
|
|||
|
||||
let globalPerson;
|
||||
let globalStore;
|
||||
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
globalStore = userStore;
|
||||
|
||||
const nameList = [];
|
||||
const valIterator = userStore.$state.persons.values();
|
||||
let per = valIterator.next();
|
||||
const nameList: string[] = [];
|
||||
const valIterator = userStore.persons.values();
|
||||
let per = valIterator.next() as {
|
||||
value: {
|
||||
name: string;
|
||||
getName: () => string;
|
||||
};
|
||||
done: boolean;
|
||||
};
|
||||
while (!per.done) {
|
||||
nameList.push(per.value.name ?? per.value.getName());
|
||||
globalPerson = per.value;
|
||||
|
@ -150,15 +155,15 @@ describe('测试store中的混合类型变化', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('p1 p2');
|
||||
|
||||
// 动态增加一个Person实例
|
||||
globalStore.$state.persons.add(new Person('ClassPerson', 5));
|
||||
globalStore.$s.persons.add(new Person('ClassPerson', 5));
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('p1 p2 ClassPerson');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('p1 p2 ClassPerson');
|
||||
|
||||
globalPerson.setName('ClassPerson1');
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('p1 p2 ClassPerson1');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('p1 p2 ClassPerson1');
|
||||
});
|
||||
});
|
|
@ -1,25 +1,18 @@
|
|||
//@ts-ignore
|
||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import * as LogUtils from '../../jest/logUtils';
|
||||
import { clearStore, createStore, useStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { App, Text, triggerClickEvent } from '../../jest/commonComponents';
|
||||
import { describe, beforeEach, afterEach, it, expect } from '@jest/globals';
|
||||
|
||||
describe('测试store中的Set', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
const persons = new Set([
|
||||
{ name: 'p1', age: 1 },
|
||||
{ name: 'p2', age: 2 },
|
||||
]);
|
||||
|
||||
createStore({
|
||||
const useUserStore = createStore({
|
||||
id: 'user',
|
||||
state: {
|
||||
type: 'bing dun dun',
|
||||
persons: persons,
|
||||
persons: new Set([
|
||||
{ name: 'p1', age: 1 },
|
||||
{ name: 'p2', age: 2 },
|
||||
]),
|
||||
},
|
||||
actions: {
|
||||
addOnePerson: (state, person) => {
|
||||
|
@ -31,23 +24,39 @@ describe('测试store中的Set', () => {
|
|||
clearPersons: state => {
|
||||
state.persons.clear();
|
||||
},
|
||||
reset: state => {
|
||||
state.persons = new Set([
|
||||
{ name: 'p1', age: 1 },
|
||||
{ name: 'p2', age: 2 },
|
||||
]);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
describe('测试store中的Set', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container: HTMLElement | null = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
useUserStore().reset();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container?.remove();
|
||||
container = null;
|
||||
LogUtils.clear();
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
||||
const newPerson = { name: 'p3', age: 3 };
|
||||
|
||||
function Parent(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
const addOnePerson = function() {
|
||||
userStore.addOnePerson(newPerson);
|
||||
};
|
||||
|
@ -76,17 +85,17 @@ describe('测试store中的Set', () => {
|
|||
|
||||
it('测试Set方法: add()、delete()、clear()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const personArr = Array.from(userStore.$state.persons);
|
||||
const nameList = [];
|
||||
const keys = userStore.$state.persons.keys();
|
||||
const userStore = useUserStore();
|
||||
const personArr = Array.from(userStore.$s.persons);
|
||||
const nameList: string[] = [];
|
||||
const keys = userStore.$s.persons.keys();
|
||||
for (const key of keys) {
|
||||
nameList.push(key.name);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'size'} text={`persons number: ${userStore.$state.persons.size}`} />
|
||||
<Text id={'size'} text={`persons number: ${userStore.$s.persons.size}`} />
|
||||
<Text id={'lastAge'} text={`last person age: ${personArr[personArr.length - 1]?.age ?? 0}`} />
|
||||
</div>
|
||||
);
|
||||
|
@ -94,35 +103,35 @@ describe('测试store中的Set', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#size').innerHTML).toBe('persons number: 2');
|
||||
expect(container.querySelector('#lastAge').innerHTML).toBe('last person age: 2');
|
||||
expect(container?.querySelector('#size')?.innerHTML).toBe('persons number: 2');
|
||||
expect(container?.querySelector('#lastAge')?.innerHTML).toBe('last person age: 2');
|
||||
// 在set中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#size').innerHTML).toBe('persons number: 3');
|
||||
expect(container?.querySelector('#size')?.innerHTML).toBe('persons number: 3');
|
||||
|
||||
// 在set中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#size').innerHTML).toBe('persons number: 2');
|
||||
expect(container?.querySelector('#size')?.innerHTML).toBe('persons number: 2');
|
||||
|
||||
// clear set
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#size').innerHTML).toBe('persons number: 0');
|
||||
expect(container.querySelector('#lastAge').innerHTML).toBe('last person age: 0');
|
||||
expect(container?.querySelector('#size')?.innerHTML).toBe('persons number: 0');
|
||||
expect(container?.querySelector('#lastAge')?.innerHTML).toBe('last person age: 0');
|
||||
});
|
||||
|
||||
it('测试Set方法: keys()、values()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
const nameList = [];
|
||||
const keys = userStore.$state.persons.keys();
|
||||
// const keys = userStore.$state.persons.values();
|
||||
const nameList: string[] = [];
|
||||
const keys = userStore.$s.persons.keys();
|
||||
// const keys = userStore.$s.persons.values();
|
||||
for (const key of keys) {
|
||||
nameList.push(key.name);
|
||||
}
|
||||
|
@ -136,32 +145,32 @@ describe('测试store中的Set', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// 在set中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// 在set中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
|
||||
// clear set
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
});
|
||||
|
||||
it('测试Set方法: entries()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
const nameList = [];
|
||||
const entries = userStore.$state.persons.entries();
|
||||
const nameList: string[] = [];
|
||||
const entries = userStore.$s.persons.entries();
|
||||
for (const entry of entries) {
|
||||
nameList.push(entry[0].name);
|
||||
}
|
||||
|
@ -175,32 +184,32 @@ describe('测试store中的Set', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// 在set中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// 在set中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
|
||||
// clear set
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
});
|
||||
|
||||
it('测试Set方法: forEach()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
const nameList = [];
|
||||
userStore.$state.persons.forEach(per => {
|
||||
const nameList: string[] = [];
|
||||
userStore.$s.persons.forEach(per => {
|
||||
nameList.push(per.name);
|
||||
});
|
||||
|
||||
|
@ -213,53 +222,53 @@ describe('测试store中的Set', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// 在set中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// 在set中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
|
||||
// clear set
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
});
|
||||
|
||||
it('测试Set方法: has()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'hasPerson'} text={`has new person: ${userStore.$state.persons.has(newPerson)}`} />
|
||||
<Text id={'hasPerson'} text={`has new person: ${userStore.$s.persons.has(newPerson)}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: false');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: false');
|
||||
// 在set中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: true');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: true');
|
||||
});
|
||||
|
||||
it('测试Set方法: for of()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
const nameList = [];
|
||||
for (const per of userStore.$state.persons) {
|
||||
const nameList: string[] = [];
|
||||
for (const per of userStore.$s.persons) {
|
||||
nameList.push(per.name);
|
||||
}
|
||||
|
||||
|
@ -272,23 +281,23 @@ describe('测试store中的Set', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// 在set中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// 在set中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
|
||||
// clear set
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
});
|
||||
});
|
|
@ -1,25 +1,18 @@
|
|||
//@ts-ignore
|
||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import * as LogUtils from '../../jest/logUtils';
|
||||
import { clearStore, createStore, useStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { App, Text, triggerClickEvent } from '../../jest/commonComponents';
|
||||
import { describe, beforeEach, afterEach, it, expect } from '@jest/globals';
|
||||
|
||||
describe('测试store中的WeakMap', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
const persons = new WeakMap([
|
||||
[{ name: 'p1' }, 1],
|
||||
[{ name: 'p2' }, 2],
|
||||
]);
|
||||
|
||||
createStore({
|
||||
const useUserStore = createStore({
|
||||
id: 'user',
|
||||
state: {
|
||||
type: 'bing dun dun',
|
||||
persons: persons,
|
||||
persons: new WeakMap([
|
||||
[{ name: 'p1' }, 1],
|
||||
[{ name: 'p2' }, 2],
|
||||
]),
|
||||
},
|
||||
actions: {
|
||||
addOnePerson: (state, person) => {
|
||||
|
@ -29,17 +22,34 @@ describe('测试store中的WeakMap', () => {
|
|||
state.persons.delete(person);
|
||||
},
|
||||
clearPersons: state => {
|
||||
state.persons.clear();
|
||||
state.persons = new WeakMap([]);
|
||||
},
|
||||
reset: state => {
|
||||
state.persons = new WeakMap([
|
||||
[{ name: 'p1' }, 1],
|
||||
[{ name: 'p2' }, 2],
|
||||
]);
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('测试store中的WeakMap', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container: HTMLElement | null = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
useUserStore().reset();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container?.remove();
|
||||
container = null;
|
||||
LogUtils.clear();
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
@ -47,7 +57,7 @@ describe('测试store中的WeakMap', () => {
|
|||
const newPerson = { name: 'p3' };
|
||||
|
||||
function Parent(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
const addOnePerson = function() {
|
||||
userStore.addOnePerson(newPerson);
|
||||
};
|
||||
|
@ -76,49 +86,49 @@ describe('测试store中的WeakMap', () => {
|
|||
|
||||
it('测试WeakMap方法: set()、delete()、has()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'hasPerson'} text={`has new person: ${userStore.$state.persons.has(newPerson)}`} />
|
||||
<Text id={'hasPerson'} text={`has new person: ${userStore.$s.persons.has(newPerson)}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: false');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: false');
|
||||
// 在WeakMap中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: true');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: true');
|
||||
|
||||
// 在WeakMap中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: false');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: false');
|
||||
});
|
||||
|
||||
it('测试WeakMap方法: get()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'hasPerson'} text={`has new person: ${userStore.$state.persons.get(newPerson)}`} />
|
||||
<Text id={'hasPerson'} text={`has new person: ${userStore.$s.persons.get(newPerson)}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: undefined');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: undefined');
|
||||
// 在WeakMap中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: 3');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: 3');
|
||||
});
|
||||
});
|
|
@ -1,25 +1,18 @@
|
|||
//@ts-ignore
|
||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import * as LogUtils from '../../jest/logUtils';
|
||||
import { clearStore, createStore, useStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { App, Text, triggerClickEvent } from '../../jest/commonComponents';
|
||||
import { describe, beforeEach, afterEach, it, expect } from '@jest/globals';
|
||||
|
||||
describe('测试store中的WeakSet', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
const persons = new WeakSet([
|
||||
{ name: 'p1', age: 1 },
|
||||
{ name: 'p2', age: 2 },
|
||||
]);
|
||||
|
||||
createStore({
|
||||
const useUserStore = createStore({
|
||||
id: 'user',
|
||||
state: {
|
||||
type: 'bing dun dun',
|
||||
persons: persons,
|
||||
persons: new WeakSet([
|
||||
{ name: 'p1', age: 1 },
|
||||
{ name: 'p2', age: 2 },
|
||||
]),
|
||||
},
|
||||
actions: {
|
||||
addOnePerson: (state, person) => {
|
||||
|
@ -29,25 +22,41 @@ describe('测试store中的WeakSet', () => {
|
|||
state.persons.delete(person);
|
||||
},
|
||||
clearPersons: state => {
|
||||
state.persons.clear();
|
||||
state.persons = new WeakSet([]);
|
||||
},
|
||||
reset: state => {
|
||||
state.persons = new WeakSet([
|
||||
{ name: 'p1', age: 1 },
|
||||
{ name: 'p2', age: 2 },
|
||||
]);
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('测试store中的WeakSet', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container: HTMLElement | null = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
useUserStore().reset();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container?.remove();
|
||||
container = null;
|
||||
LogUtils.clear();
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
||||
const newPerson = { name: 'p3', age: 3 };
|
||||
|
||||
function Parent(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
const addOnePerson = function() {
|
||||
userStore.addOnePerson(newPerson);
|
||||
};
|
||||
|
@ -69,28 +78,28 @@ describe('测试store中的WeakSet', () => {
|
|||
|
||||
it('测试WeakSet方法: add()、delete()、has()', () => {
|
||||
function Child(props) {
|
||||
const userStore = useStore('user');
|
||||
const userStore = useUserStore();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'hasPerson'} text={`has new person: ${userStore.$state.persons.has(newPerson)}`} />
|
||||
<Text id={'hasPerson'} text={`has new person: ${userStore.$s.persons.has(newPerson)}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: false');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: false');
|
||||
// 在WeakSet中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: true');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: true');
|
||||
|
||||
// 在WeakSet中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: false');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: false');
|
||||
});
|
||||
});
|
|
@ -1,6 +1,8 @@
|
|||
//@ts-ignore
|
||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { createStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { triggerClickEvent } from '../../jest/commonComponents';
|
||||
import { describe, beforeEach, afterEach, it, expect } from '@jest/globals';
|
||||
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
|
||||
|
@ -13,7 +15,7 @@ function postpone(timer, func) {
|
|||
}
|
||||
|
||||
describe('Asynchronous functions', () => {
|
||||
let container = null;
|
||||
let container: HTMLElement | null = null;
|
||||
|
||||
const COUNTER_ID = 'counter';
|
||||
const TOGGLE_ID = 'toggle';
|
||||
|
@ -33,7 +35,7 @@ describe('Asynchronous functions', () => {
|
|||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
state.counter++;
|
||||
resolve();
|
||||
resolve(true);
|
||||
}, 100);
|
||||
});
|
||||
},
|
||||
|
@ -53,11 +55,12 @@ describe('Asynchronous functions', () => {
|
|||
|
||||
afterEach(() => {
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container?.remove();
|
||||
container = null;
|
||||
});
|
||||
|
||||
it('Should wait for async actions', async () => {
|
||||
// @ts-ignore
|
||||
jest.useRealTimers();
|
||||
let globalStore;
|
||||
|
||||
|
@ -84,14 +87,14 @@ describe('Asynchronous functions', () => {
|
|||
Horizon.render(<App />, container);
|
||||
|
||||
// initial state
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('false0');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('false0');
|
||||
|
||||
// slow toggle has nothing to wait for, it is resolved immediately
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, TOGGLE_ID);
|
||||
});
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('true0');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('true0');
|
||||
|
||||
// counter increment is slow. slow toggle waits for result
|
||||
Horizon.act(() => {
|
||||
|
@ -101,18 +104,18 @@ describe('Asynchronous functions', () => {
|
|||
triggerClickEvent(container, TOGGLE_ID);
|
||||
});
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('true0');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('true0');
|
||||
|
||||
// fast toggle does not wait for counter and it is resolved immediately
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, TOGGLE_FAST_ID);
|
||||
});
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('false0');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('false0');
|
||||
|
||||
// at 150ms counter increment will be resolved and slow toggle immediately after
|
||||
const t150 = postpone(150, () => {
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('true1');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('true1');
|
||||
});
|
||||
|
||||
// before that, two more actions are added to queue - another counter and slow toggle
|
||||
|
@ -125,13 +128,14 @@ describe('Asynchronous functions', () => {
|
|||
|
||||
// at 250ms they should be already resolved
|
||||
const t250 = postpone(250, () => {
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('false2');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('false2');
|
||||
});
|
||||
|
||||
await Promise.all([t150, t250]);
|
||||
});
|
||||
|
||||
it('call async action by then', async () => {
|
||||
// @ts-ignore
|
||||
jest.useFakeTimers();
|
||||
let globalStore;
|
||||
|
||||
|
@ -150,12 +154,13 @@ describe('Asynchronous functions', () => {
|
|||
|
||||
// call async action by then
|
||||
globalStore.$queue.increment().then(() => {
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('false1');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('false1');
|
||||
});
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('false0');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('false0');
|
||||
|
||||
// past 150 ms
|
||||
// @ts-ignore
|
||||
jest.advanceTimersByTime(150);
|
||||
});
|
||||
});
|
|
@ -1,63 +0,0 @@
|
|||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { triggerClickEvent } from '../../jest/commonComponents';
|
||||
import { useLogStore } from './store';
|
||||
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
|
||||
describe('Basic store manipulation', () => {
|
||||
let container = null;
|
||||
|
||||
const BUTTON_ID = 'btn';
|
||||
const RESULT_ID = 'result';
|
||||
|
||||
beforeEach(() => {
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container = null;
|
||||
});
|
||||
|
||||
it('Should use getters', () => {
|
||||
function App() {
|
||||
const logStore = useLogStore();
|
||||
|
||||
return <div id={RESULT_ID}>{logStore.length}</div>;
|
||||
}
|
||||
|
||||
Horizon.render(<App />, container);
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('1');
|
||||
});
|
||||
|
||||
it('Should use actions and update components', () => {
|
||||
function App() {
|
||||
const logStore = useLogStore();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
id={BUTTON_ID}
|
||||
onClick={() => {
|
||||
logStore.addLog('a');
|
||||
}}
|
||||
>
|
||||
add
|
||||
</button>
|
||||
<p id={RESULT_ID}>{logStore.length}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App />, container);
|
||||
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, BUTTON_ID);
|
||||
});
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('2');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,110 @@
|
|||
//@ts-ignore
|
||||
import Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { triggerClickEvent } from '../../jest/commonComponents';
|
||||
import { useLogStore } from './store';
|
||||
import { describe, beforeEach, afterEach, it, expect } from '@jest/globals';
|
||||
import { createStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
|
||||
describe('Basic store manipulation', () => {
|
||||
let container: HTMLElement | null = null;
|
||||
|
||||
const BUTTON_ID = 'btn';
|
||||
const RESULT_ID = 'result';
|
||||
|
||||
beforeEach(() => {
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
unmountComponentAtNode(container);
|
||||
container?.remove();
|
||||
container = null;
|
||||
});
|
||||
|
||||
it('Should use getters', () => {
|
||||
function App() {
|
||||
const logStore = useLogStore();
|
||||
|
||||
return <div id={RESULT_ID}>{logStore.length}</div>;
|
||||
}
|
||||
|
||||
Horizon.render(<App />, container);
|
||||
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('1');
|
||||
});
|
||||
|
||||
it('Should use actions and update components', () => {
|
||||
function App() {
|
||||
const logStore = useLogStore();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
id={BUTTON_ID}
|
||||
onClick={() => {
|
||||
logStore.addLog('a');
|
||||
}}
|
||||
>
|
||||
add
|
||||
</button>
|
||||
<p id={RESULT_ID}>{logStore.length}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App />, container);
|
||||
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, BUTTON_ID);
|
||||
});
|
||||
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('2');
|
||||
});
|
||||
|
||||
it('should call actions from own actions', () => {
|
||||
const useIncrementStore = createStore({
|
||||
id: 'incrementStore',
|
||||
state: {
|
||||
count: 2,
|
||||
},
|
||||
actions: {
|
||||
increment: state => {
|
||||
state.count++;
|
||||
},
|
||||
doublePlusOne: function(state) {
|
||||
state.count = state.count * 2;
|
||||
this.increment();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
function App() {
|
||||
const incrementStore = useIncrementStore();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
id={BUTTON_ID}
|
||||
onClick={() => {
|
||||
incrementStore.doublePlusOne();
|
||||
}}
|
||||
>
|
||||
+
|
||||
</button>
|
||||
<p id={RESULT_ID}>{incrementStore.count}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App />, container);
|
||||
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, BUTTON_ID);
|
||||
});
|
||||
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('5');
|
||||
});
|
||||
});
|
|
@ -1,11 +1,13 @@
|
|||
//@ts-ignore
|
||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { triggerClickEvent } from '../../jest/commonComponents';
|
||||
import { useLogStore } from './store';
|
||||
import { describe, beforeEach, afterEach, it, expect } from '@jest/globals';
|
||||
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
|
||||
describe('Dollar store access', () => {
|
||||
let container = null;
|
||||
let container: HTMLElement | null = null;
|
||||
|
||||
const BUTTON_ID = 'btn';
|
||||
const RESULT_ID = 'result';
|
||||
|
@ -17,23 +19,23 @@ describe('Dollar store access', () => {
|
|||
|
||||
afterEach(() => {
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container?.remove();
|
||||
container = null;
|
||||
});
|
||||
|
||||
it('Should use $state and $computed', () => {
|
||||
it('Should use $s and $c', () => {
|
||||
function App() {
|
||||
const logStore = useLogStore();
|
||||
|
||||
return <div id={RESULT_ID}>{logStore.$computed.length()}</div>;
|
||||
return <div id={RESULT_ID}>{logStore.$c.length()}</div>;
|
||||
}
|
||||
|
||||
Horizon.render(<App />, container);
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('1');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('1');
|
||||
});
|
||||
|
||||
it('Should use $actions and update components', () => {
|
||||
it('Should use $a and update components', () => {
|
||||
function App() {
|
||||
const logStore = useLogStore();
|
||||
|
||||
|
@ -42,12 +44,12 @@ describe('Dollar store access', () => {
|
|||
<button
|
||||
id={BUTTON_ID}
|
||||
onClick={() => {
|
||||
logStore.$actions.addLog();
|
||||
logStore.$a.addLog('data');
|
||||
}}
|
||||
>
|
||||
add
|
||||
</button>
|
||||
<p id={RESULT_ID}>{logStore.$computed.length()}</p>
|
||||
<p id={RESULT_ID}>{logStore.$c.length()}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -58,6 +60,6 @@ describe('Dollar store access', () => {
|
|||
triggerClickEvent(container, BUTTON_ID);
|
||||
});
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('2');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('2');
|
||||
});
|
||||
});
|
|
@ -1,11 +1,13 @@
|
|||
//@ts-ignore
|
||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { createStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { triggerClickEvent } from '../../jest/commonComponents';
|
||||
import { describe, beforeEach, afterEach, it, expect } from '@jest/globals';
|
||||
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
|
||||
describe('Self referencing', () => {
|
||||
let container = null;
|
||||
let container: HTMLElement | null = null;
|
||||
|
||||
const BUTTON_ID = 'btn';
|
||||
const RESULT_ID = 'result';
|
||||
|
@ -15,7 +17,7 @@ describe('Self referencing', () => {
|
|||
val: 2,
|
||||
},
|
||||
actions: {
|
||||
magic: function(state) {
|
||||
increaseVal: function(state) {
|
||||
state.val = state.val * 2 - 1;
|
||||
},
|
||||
},
|
||||
|
@ -34,7 +36,7 @@ describe('Self referencing', () => {
|
|||
|
||||
afterEach(() => {
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container?.remove();
|
||||
container = null;
|
||||
});
|
||||
|
||||
|
@ -45,8 +47,8 @@ describe('Self referencing', () => {
|
|||
return (
|
||||
<div>
|
||||
<p id={RESULT_ID}>{store.double}</p>
|
||||
<button onClick={store.magic} id={BUTTON_ID}>
|
||||
do magic
|
||||
<button onClick={store.increaseVal} id={BUTTON_ID}>
|
||||
increase value
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
@ -54,29 +56,29 @@ describe('Self referencing', () => {
|
|||
|
||||
Horizon.render(<App />, container);
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('4');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('4');
|
||||
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, BUTTON_ID);
|
||||
});
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('6');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('6');
|
||||
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, BUTTON_ID);
|
||||
});
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('10');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('10');
|
||||
});
|
||||
|
||||
it('should access other stores', () => {
|
||||
const useOtherStore = createStore({
|
||||
state: {},
|
||||
actions: {
|
||||
doMagic: () => useSelfRefStore().magic(),
|
||||
doIncreaseVal: () => useSelfRefStore().increaseVal(),
|
||||
},
|
||||
computed: {
|
||||
magicConstant: () => useSelfRefStore().value,
|
||||
selfRefStoreValue: () => useSelfRefStore().value,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -85,9 +87,9 @@ describe('Self referencing', () => {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<p id={RESULT_ID}>{store.magicConstant}</p>
|
||||
<button onClick={store.doMagic} id={BUTTON_ID}>
|
||||
do magic
|
||||
<p id={RESULT_ID}>{store.selfRefStoreValue}</p>
|
||||
<button onClick={store.doIncreaseVal} id={BUTTON_ID}>
|
||||
increase value in other store
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
@ -95,13 +97,13 @@ describe('Self referencing', () => {
|
|||
|
||||
Horizon.render(<App />, container);
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('5');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('5');
|
||||
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, BUTTON_ID);
|
||||
});
|
||||
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('9');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('9');
|
||||
});
|
||||
|
||||
it('should use parametric getters', () => {
|
||||
|
@ -138,11 +140,11 @@ describe('Self referencing', () => {
|
|||
}
|
||||
|
||||
Horizon.render(<App />, container);
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('abc');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('abc');
|
||||
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, BUTTON_ID);
|
||||
});
|
||||
expect(document.getElementById(RESULT_ID).innerHTML).toBe('def');
|
||||
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('def');
|
||||
});
|
||||
});
|
|
@ -1,14 +1,14 @@
|
|||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { createStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { triggerClickEvent } from '../../jest/commonComponents';
|
||||
import {createStore} from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import {triggerClickEvent} from '../../jest/commonComponents';
|
||||
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
const {unmountComponentAtNode} = Horizon;
|
||||
|
||||
describe('Reset', () => {
|
||||
it('RESET NOT IMPLEMENTED', async () => {
|
||||
// console.log('reset functionality is not yet implemented')
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
})
|
||||
return;
|
||||
|
||||
let container = null;
|
||||
|
@ -19,14 +19,14 @@ describe('Reset', () => {
|
|||
|
||||
const useCounter = createStore({
|
||||
state: {
|
||||
counter: 0,
|
||||
counter: 0
|
||||
},
|
||||
actions: {
|
||||
increment: function(state) {
|
||||
increment: function (state) {
|
||||
state.counter++;
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {},
|
||||
computed: {}
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -44,25 +44,17 @@ describe('Reset', () => {
|
|||
function App() {
|
||||
const store = useCounter();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p id={RESULT_ID}>{store.$state.counter}</p>
|
||||
<button onClick={store.increment} id={BUTTON_ID}>
|
||||
add
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
return <div>
|
||||
<p id={RESULT_ID}>{store.$s.counter}</p>
|
||||
<button onClick={store.increment} id={BUTTON_ID}>add</button>
|
||||
<button onClick={() => {
|
||||
store.$reset();
|
||||
}}
|
||||
id={RESET_ID}
|
||||
>
|
||||
reset
|
||||
}} id={RESET_ID}>reset
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Horizon.render(<App />, container);
|
||||
Horizon.render(<App/>, container);
|
||||
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, BUTTON_ID);
|
|
@ -1,9 +1,12 @@
|
|||
//@ts-ignore
|
||||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import {
|
||||
createStore,
|
||||
applyMiddleware,
|
||||
combineReducers,
|
||||
bindActionCreators,
|
||||
} from '../../../../libs/horizon/src/horizonx/adapters/redux';
|
||||
import { describe, it, expect } from '@jest/globals';
|
||||
|
||||
describe('Redux adapter', () => {
|
||||
it('should use getState()', async () => {
|
||||
|
@ -142,7 +145,7 @@ describe('Redux adapter', () => {
|
|||
|
||||
it('Should apply enhancers', async () => {
|
||||
let counter = 0;
|
||||
let middlewareCallList = [];
|
||||
let middlewareCallList: string[] = [];
|
||||
|
||||
const callCounter = store => next => action => {
|
||||
middlewareCallList.push('callCounter');
|
||||
|
@ -175,7 +178,7 @@ describe('Redux adapter', () => {
|
|||
it('Should apply multiple enhancers', async () => {
|
||||
let counter = 0;
|
||||
let lastAction = '';
|
||||
let middlewareCallList = [];
|
||||
let middlewareCallList: string[] = [];
|
||||
|
||||
const callCounter = store => next => action => {
|
||||
middlewareCallList.push('callCounter');
|
|
@ -1,34 +0,0 @@
|
|||
import { createStore, applyMiddleware, thunk } from '../../../../libs/horizon/src/horizonx/adapters/redux';
|
||||
|
||||
describe('Redux thunk', () => {
|
||||
it('should use apply thunk middleware', async () => {
|
||||
const MAX_TODOS = 5;
|
||||
|
||||
function addTodosIfAllowed(todoText) {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
|
||||
if (state.todos.length < MAX_TODOS) {
|
||||
dispatch({ type: 'ADD_TODO', text: todoText });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const todoStore = createStore(
|
||||
(state = { todos: [] }, action) => {
|
||||
if (action.type === 'ADD_TODO') {
|
||||
return { todos: state.todos?.concat(action.text) };
|
||||
}
|
||||
return state;
|
||||
},
|
||||
null,
|
||||
applyMiddleware(thunk)
|
||||
);
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
todoStore.dispatch(addTodosIfAllowed('todo no.' + i));
|
||||
}
|
||||
|
||||
expect(todoStore.getState().todos.length).toBe(5);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,33 @@
|
|||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { createStore, applyMiddleware, thunk } from '../../../../libs/horizon/src/horizonx/adapters/redux';
|
||||
import {describe, it, expect} from '@jest/globals';
|
||||
|
||||
describe('Redux thunk', () => {
|
||||
it('should use apply thunk middleware', async () => {
|
||||
const MAX_TODOS = 5;
|
||||
|
||||
function addTodosIfAllowed(todoText) {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
|
||||
if (state.todos.length < MAX_TODOS) {
|
||||
dispatch({type: 'ADD_TODO', text: todoText});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const todoStore = createStore((state = {todos: []}, action) => {
|
||||
if (action.type === 'ADD_TODO') {
|
||||
return {todos: state.todos?.concat(action.text)};
|
||||
}
|
||||
return state;
|
||||
}, null, applyMiddleware(thunk));
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
//TODO: resolve thunk problems
|
||||
(todoStore.dispatch as unknown as (delayedAction:(dispatch,getState)=>void)=>void)(addTodosIfAllowed('todo no.' + i));
|
||||
}
|
||||
|
||||
expect(todoStore.getState().todos.length).toBe(5);
|
||||
});
|
||||
});
|
|
@ -1,3 +1,4 @@
|
|||
//@ts-ignore
|
||||
import horizon, * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import {
|
||||
batch,
|
||||
|
@ -8,17 +9,19 @@ import {
|
|||
useSelector,
|
||||
useStore,
|
||||
createSelectorHook,
|
||||
createDispatchHook,
|
||||
createDispatchHook
|
||||
} from '../../../../libs/horizon/src/horizonx/adapters/redux';
|
||||
import { triggerClickEvent } from '../../jest/commonComponents';
|
||||
import {triggerClickEvent} from '../../jest/commonComponents';
|
||||
import {describe, it, beforeEach, afterEach, expect} from '@jest/globals';
|
||||
import { ReduxStoreHandler } from '@cloudsop/horizon/src/horizonx/types';
|
||||
|
||||
const BUTTON = 'button';
|
||||
const BUTTON2 = 'button2';
|
||||
const RESULT = 'result';
|
||||
const CONTAINER = 'container';
|
||||
const CONTAINER = 'container'
|
||||
|
||||
function getE(id) {
|
||||
return document.getElementById(id);
|
||||
function getE(id):HTMLElement {
|
||||
return document.getElementById(id)||document.body;
|
||||
}
|
||||
|
||||
describe('Redux/React binding adapter', () => {
|
||||
|
@ -36,19 +39,17 @@ describe('Redux/React binding adapter', () => {
|
|||
const reduxStore = createStore((state = 'state', action) => state);
|
||||
|
||||
const Child = () => {
|
||||
const store = useStore();
|
||||
const store = useStore() as unknown as ReduxStoreHandler;
|
||||
return <div id={RESULT}>{store.getState()}</div>;
|
||||
};
|
||||
|
||||
const Wrapper = () => {
|
||||
return (
|
||||
<Provider store={reduxStore}>
|
||||
<Child />
|
||||
</Provider>
|
||||
);
|
||||
return <Provider store={reduxStore}>
|
||||
<Child/>
|
||||
</Provider>;
|
||||
};
|
||||
|
||||
Horizon.render(<Wrapper />, getE(CONTAINER));
|
||||
Horizon.render(<Wrapper/>, getE(CONTAINER));
|
||||
|
||||
expect(getE(RESULT).innerHTML).toBe('state');
|
||||
});
|
||||
|
@ -60,30 +61,23 @@ describe('Redux/React binding adapter', () => {
|
|||
});
|
||||
|
||||
const Child = () => {
|
||||
const store = useStore();
|
||||
const store = useStore() as unknown as ReduxStoreHandler;
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<div>
|
||||
return <div>
|
||||
<p id={RESULT}>{store.getState()}</p>
|
||||
<button
|
||||
id={BUTTON}
|
||||
onClick={() => {
|
||||
dispatch({ type: 'ADD' });
|
||||
}}
|
||||
></button>
|
||||
</div>
|
||||
);
|
||||
<button id={BUTTON} onClick={() => {
|
||||
dispatch({type: 'ADD'});
|
||||
}}></button>
|
||||
</div>;
|
||||
};
|
||||
|
||||
const Wrapper = () => {
|
||||
return (
|
||||
<Provider store={reduxStore}>
|
||||
<Child />
|
||||
</Provider>
|
||||
);
|
||||
return <Provider store={reduxStore}>
|
||||
<Child/>
|
||||
</Provider>;
|
||||
};
|
||||
|
||||
Horizon.render(<Wrapper />, getE(CONTAINER));
|
||||
Horizon.render(<Wrapper/>, getE(CONTAINER));
|
||||
|
||||
expect(reduxStore.getState()).toBe(0);
|
||||
|
||||
|
@ -101,32 +95,24 @@ describe('Redux/React binding adapter', () => {
|
|||
});
|
||||
|
||||
const Child = () => {
|
||||
const count = useSelector(state => state);
|
||||
const count = useSelector((state) => state);
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<div>
|
||||
return <div>
|
||||
<p id={RESULT}>{count}</p>
|
||||
<button
|
||||
id={BUTTON}
|
||||
onClick={() => {
|
||||
dispatch({ type: 'ADD' });
|
||||
}}
|
||||
>
|
||||
click
|
||||
<button id={BUTTON} onClick={() => {
|
||||
dispatch({type: 'ADD'});
|
||||
}}>click
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
</div>;
|
||||
};
|
||||
|
||||
const Wrapper = () => {
|
||||
return (
|
||||
<Provider store={reduxStore}>
|
||||
<Child />
|
||||
</Provider>
|
||||
);
|
||||
return <Provider store={reduxStore}>
|
||||
<Child/>
|
||||
</Provider>;
|
||||
};
|
||||
|
||||
Horizon.render(<Wrapper />, getE(CONTAINER));
|
||||
Horizon.render(<Wrapper/>, getE(CONTAINER));
|
||||
|
||||
expect(getE(RESULT).innerHTML).toBe('0');
|
||||
|
||||
|
@ -139,80 +125,58 @@ describe('Redux/React binding adapter', () => {
|
|||
});
|
||||
|
||||
it('Should use connect', async () => {
|
||||
const reduxStore = createStore(
|
||||
(state, action) => {
|
||||
const reduxStore = createStore((state, action) => {
|
||||
switch (action.type) {
|
||||
case 'INCREMENT':
|
||||
case('INCREMENT'):
|
||||
return {
|
||||
...state,
|
||||
value: state.negative ? state.value - action.amount : state.value + action.amount,
|
||||
value: state.negative ? state.value - action.amount : state.value + action.amount
|
||||
};
|
||||
case 'TOGGLE':
|
||||
case('TOGGLE'):
|
||||
return {
|
||||
...state,
|
||||
negative: !state.negative,
|
||||
negative: !state.negative
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
},
|
||||
{ negative: false, value: 0 }
|
||||
);
|
||||
}, {negative: false, value: 0});
|
||||
|
||||
const Child = connect(
|
||||
(state, ownProps) => {
|
||||
const Child = connect((state, ownProps) => {
|
||||
// map state to props
|
||||
return { ...state, ...ownProps };
|
||||
},
|
||||
(dispatch, ownProps) => {
|
||||
return {...state, ...ownProps};
|
||||
}, (dispatch, ownProps) => {
|
||||
// map dispatch to props
|
||||
return {
|
||||
increment: () => dispatch({ type: 'INCREMENT', amount: ownProps.amount }),
|
||||
// @ts-ignore
|
||||
increment: () => dispatch({type: 'INCREMENT', amount: ownProps?.amount})
|
||||
};
|
||||
},
|
||||
(stateProps, dispatchProps, ownProps) => {
|
||||
}, (stateProps, dispatchProps, ownProps) => {
|
||||
//merge props
|
||||
return { stateProps, dispatchProps, ownProps };
|
||||
},
|
||||
{}
|
||||
)(props => {
|
||||
return {stateProps, dispatchProps, ownProps};
|
||||
}, {})((props) => {
|
||||
const n = props.stateProps.negative;
|
||||
return (
|
||||
<div>
|
||||
<div id={RESULT}>
|
||||
{n ? '-' : '+'}
|
||||
{props.stateProps.value}
|
||||
</div>
|
||||
<button
|
||||
id={BUTTON}
|
||||
onClick={() => {
|
||||
return <div>
|
||||
<div id={RESULT}>{n ? '-' : '+'}{props.stateProps.value}</div>
|
||||
<button id={BUTTON} onClick={() => {
|
||||
props.dispatchProps.increment();
|
||||
}}
|
||||
>
|
||||
add {props.ownProps.amount}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}}>add {props.ownProps.amount}</button>
|
||||
</div>;
|
||||
});
|
||||
|
||||
const Wrapper = () => {
|
||||
//@ts-ignore
|
||||
const [amount, setAmount] = Horizon.useState(5);
|
||||
return (
|
||||
<Provider store={reduxStore}>
|
||||
<Child amount={amount} />
|
||||
<button
|
||||
id={BUTTON2}
|
||||
onClick={() => {
|
||||
return <Provider store={reduxStore}>
|
||||
<Child amount={amount}/>
|
||||
<button id={BUTTON2} onClick={() => {
|
||||
setAmount(3);
|
||||
}}
|
||||
>
|
||||
change amount
|
||||
}}>change amount
|
||||
</button>
|
||||
</Provider>
|
||||
);
|
||||
</Provider>;
|
||||
};
|
||||
|
||||
Horizon.render(<Wrapper />, getE(CONTAINER));
|
||||
Horizon.render(<Wrapper/>, getE(CONTAINER));
|
||||
|
||||
expect(getE(RESULT).innerHTML).toBe('+0');
|
||||
|
||||
|
@ -231,7 +195,7 @@ describe('Redux/React binding adapter', () => {
|
|||
});
|
||||
|
||||
expect(getE(RESULT).innerHTML).toBe('+8');
|
||||
});
|
||||
})
|
||||
|
||||
it('Should batch dispatches', async () => {
|
||||
const reduxStore = createStore((state = 0, action) => {
|
||||
|
@ -244,32 +208,22 @@ describe('Redux/React binding adapter', () => {
|
|||
function Counter() {
|
||||
renderCounter++;
|
||||
|
||||
const value = useSelector(state => state);
|
||||
const value = useSelector((state) => state);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div>
|
||||
return <div>
|
||||
<p id={RESULT}>{value}</p>
|
||||
<button
|
||||
id={BUTTON}
|
||||
onClick={() => {
|
||||
<button id={BUTTON} onClick={() => {
|
||||
batch(() => {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
dispatch({ type: 'ADD' });
|
||||
dispatch({type: 'ADD'});
|
||||
}
|
||||
});
|
||||
}}
|
||||
></button>
|
||||
</div>
|
||||
);
|
||||
}}></button>
|
||||
</div>;
|
||||
}
|
||||
|
||||
Horizon.render(
|
||||
<Provider store={reduxStore}>
|
||||
<Counter />
|
||||
</Provider>,
|
||||
getE(CONTAINER)
|
||||
);
|
||||
Horizon.render(<Provider store={reduxStore}><Counter/></Provider>, getE(CONTAINER));
|
||||
|
||||
expect(getE(RESULT).innerHTML).toBe('0');
|
||||
expect(renderCounter).toBe(1);
|
||||
|
@ -300,49 +254,33 @@ describe('Redux/React binding adapter', () => {
|
|||
const count = createSelectorHook(counterContext)();
|
||||
const dispatch = createDispatchHook(counterContext)();
|
||||
|
||||
return (
|
||||
<button
|
||||
id={BUTTON}
|
||||
onClick={() => {
|
||||
dispatch({ type: 'ADD' });
|
||||
}}
|
||||
>
|
||||
{count}
|
||||
</button>
|
||||
);
|
||||
return <button id={BUTTON} onClick={() => {
|
||||
dispatch({type: 'ADD'});
|
||||
}}>{count}</button>;
|
||||
}
|
||||
|
||||
function Toggle() {
|
||||
const check = createSelectorHook(toggleContext)();
|
||||
const dispatch = createDispatchHook(toggleContext)();
|
||||
|
||||
return (
|
||||
<button
|
||||
id={BUTTON2}
|
||||
onClick={() => {
|
||||
dispatch({ type: 'TOGGLE' });
|
||||
}}
|
||||
>
|
||||
{check ? 'true' : 'false'}
|
||||
</button>
|
||||
);
|
||||
return <button id={BUTTON2} onClick={() => {
|
||||
dispatch({type: 'TOGGLE'});
|
||||
}}>{check ? 'true' : 'false'}</button>;
|
||||
}
|
||||
|
||||
function Wrapper() {
|
||||
return (
|
||||
<div>
|
||||
return <div>
|
||||
<Provider store={counterStore} context={counterContext}>
|
||||
<Counter />
|
||||
<Counter/>
|
||||
</Provider>
|
||||
|
||||
<Provider store={toggleStore} context={toggleContext}>
|
||||
<Toggle />
|
||||
<Toggle/>
|
||||
</Provider>
|
||||
</div>
|
||||
);
|
||||
</div>;
|
||||
}
|
||||
|
||||
Horizon.render(<Wrapper />, getE(CONTAINER));
|
||||
Horizon.render(<Wrapper/>, getE(CONTAINER));
|
||||
|
||||
expect(getE(BUTTON).innerHTML).toBe('0');
|
||||
expect(getE(BUTTON2).innerHTML).toBe('false');
|
|
@ -1,14 +1,17 @@
|
|||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { clearStore, createStore, useStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { Text } from '../../jest/commonComponents';
|
||||
import * as LogUtils from '../../jest/logUtils';
|
||||
import {clearStore, createStore, useStore} from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import {Text, triggerClickEvent} from '../../jest/commonComponents';
|
||||
import {getObserver} from '../../../../libs/horizon/src/horizonx/proxy/ProxyHandler';
|
||||
import {describe, beforeEach, afterEach, it, expect} from '@jest/globals';
|
||||
|
||||
describe('测试 Class VNode 清除时,对引用清除', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container = null;
|
||||
const {unmountComponentAtNode} = Horizon;
|
||||
let container:HTMLElement|null = null;
|
||||
let globalState = {
|
||||
name: 'bing dun dun',
|
||||
isWin: true,
|
||||
isShow: true,
|
||||
isShow: true
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -23,7 +26,7 @@ describe('测试 Class VNode 清除时,对引用清除', () => {
|
|||
setWin: (state, val) => {
|
||||
state.isWin = val;
|
||||
},
|
||||
hide: state => {
|
||||
hide: (state) => {
|
||||
state.isShow = false;
|
||||
},
|
||||
updateName: (state, val) => {
|
||||
|
@ -36,8 +39,9 @@ describe('测试 Class VNode 清除时,对引用清除', () => {
|
|||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container?.remove();
|
||||
container = null;
|
||||
LogUtils.clear();
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
@ -47,23 +51,21 @@ describe('测试 Class VNode 清除时,对引用清除', () => {
|
|||
userStore = useStore('user');
|
||||
|
||||
render() {
|
||||
if(!this.userStore) return <div />;
|
||||
// Do not modify the store data in the render method. Otherwise, an infinite loop may occur.
|
||||
this.userStore.updateName(this.userStore.name === 'bing dun dun' ? 'huo dun dun' : 'bing dun dun');
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'name'} text={`name: ${this.userStore.name}`} />
|
||||
<Text id={'isWin'} text={`isWin: ${this.userStore.isWin}`} />
|
||||
</div>
|
||||
);
|
||||
return <div>
|
||||
<Text id={'name'} text={`name: ${this.userStore.name}`}/>
|
||||
<Text id={'isWin'} text={`isWin: ${this.userStore.isWin}`}/>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
expect(() => {
|
||||
Horizon.render(<Child />, container);
|
||||
}).toThrow(
|
||||
'The number of updates exceeds the upper limit 50.\n' +
|
||||
' A component maybe repeatedly invokes setState on componentWillUpdate or componentDidUpdate.'
|
||||
);
|
||||
Horizon.render(<Child/>, container);
|
||||
}).toThrow('The number of updates exceeds the upper limit 50.\n' +
|
||||
' A component maybe repeatedly invokes setState on componentWillUpdate or componentDidUpdate.');
|
||||
|
||||
});
|
||||
});
|
|
@ -1,220 +0,0 @@
|
|||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { clearStore, createStore, useStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { App, Text, triggerClickEvent } from '../../jest/commonComponents';
|
||||
|
||||
describe('在Class组件中,测试store中的Array', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
const persons = [
|
||||
{ name: 'p1', age: 1 },
|
||||
{ name: 'p2', age: 2 },
|
||||
];
|
||||
|
||||
createStore({
|
||||
id: 'user',
|
||||
state: {
|
||||
type: 'bing dun dun',
|
||||
persons: persons,
|
||||
},
|
||||
actions: {
|
||||
addOnePerson: (state, person) => {
|
||||
state.persons.push(person);
|
||||
},
|
||||
delOnePerson: state => {
|
||||
state.persons.pop();
|
||||
},
|
||||
clearPersons: state => {
|
||||
state.persons = null;
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container = null;
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
||||
const newPerson = { name: 'p3', age: 3 };
|
||||
|
||||
class Parent extends Horizon.Component {
|
||||
userStore = useStore('user');
|
||||
|
||||
addOnePerson = () => {
|
||||
this.userStore.addOnePerson(newPerson);
|
||||
};
|
||||
|
||||
delOnePerson = () => {
|
||||
this.userStore.delOnePerson();
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<button id={'addBtn'} onClick={this.addOnePerson}>
|
||||
add person
|
||||
</button>
|
||||
<button id={'delBtn'} onClick={this.delOnePerson}>
|
||||
delete person
|
||||
</button>
|
||||
<div>{this.props.children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
it('测试Array方法: push()、pop()', () => {
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useStore('user');
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Text id={'hasPerson'} text={`has new person: ${this.userStore.persons.length}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: 2');
|
||||
// 在Array中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: 3');
|
||||
|
||||
// 在Array中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: 2');
|
||||
});
|
||||
|
||||
it('测试Array方法: entries()、push()、shift()、unshift、直接赋值', () => {
|
||||
let globalStore = null;
|
||||
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useStore('user');
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
globalStore = this.userStore;
|
||||
}
|
||||
|
||||
render() {
|
||||
const nameList = [];
|
||||
const entries = this.userStore.$state.persons?.entries();
|
||||
if (entries) {
|
||||
for (const entry of entries) {
|
||||
nameList.push(entry[1].name);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'nameList'} text={`name list: ${nameList.join(' ')}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
// push
|
||||
globalStore.$state.persons.push(newPerson);
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// shift
|
||||
globalStore.$state.persons.shift({ name: 'p0', age: 0 });
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p2 p3');
|
||||
|
||||
// 赋值[2]
|
||||
globalStore.$state.persons[2] = { name: 'p4', age: 4 };
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p2 p3 p4');
|
||||
|
||||
// 重新赋值[2]
|
||||
globalStore.$state.persons[2] = { name: 'p5', age: 5 };
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p2 p3 p5');
|
||||
|
||||
// unshift
|
||||
globalStore.$state.persons.unshift({ name: 'p1', age: 1 });
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3 p5');
|
||||
|
||||
// 重新赋值 null
|
||||
globalStore.$state.persons = null;
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
|
||||
// 重新赋值 [{ name: 'p1', age: 1 }]
|
||||
globalStore.$state.persons = [{ name: 'p1', age: 1 }];
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1');
|
||||
});
|
||||
|
||||
it('测试Array方法: forEach()', () => {
|
||||
let globalStore = null;
|
||||
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useStore('user');
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
globalStore = this.userStore;
|
||||
}
|
||||
|
||||
render() {
|
||||
const nameList = [];
|
||||
this.userStore.$state.persons?.forEach(per => {
|
||||
nameList.push(per.name);
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'nameList'} text={`name list: ${nameList.join(' ')}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
// push
|
||||
globalStore.$state.persons.push(newPerson);
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// shift
|
||||
globalStore.$state.persons.shift({ name: 'p0', age: 0 });
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p2 p3');
|
||||
|
||||
// 赋值[2]
|
||||
globalStore.$state.persons[2] = { name: 'p4', age: 4 };
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p2 p3 p4');
|
||||
|
||||
// 重新赋值[2]
|
||||
globalStore.$state.persons[2] = { name: 'p5', age: 5 };
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p2 p3 p5');
|
||||
|
||||
// unshift
|
||||
globalStore.$state.persons.unshift({ name: 'p1', age: 1 });
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3 p5');
|
||||
|
||||
// 重新赋值 null
|
||||
globalStore.$state.persons = null;
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
|
||||
// 重新赋值 [{ name: 'p1', age: 1 }]
|
||||
globalStore.$state.persons = [{ name: 'p1', age: 1 }];
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,231 @@
|
|||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import * as LogUtils from '../../jest/logUtils';
|
||||
import {clearStore, createStore, useStore} from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import {App, Text, triggerClickEvent} from '../../jest/commonComponents';
|
||||
import {describe, beforeEach, afterEach, it, expect} from '@jest/globals';
|
||||
|
||||
type Person = {name:string,age:number};
|
||||
|
||||
const persons:Person[] = [{ name: 'p1', age: 1 }, { name: 'p2', age: 2 }];
|
||||
let useUserStore = createStore({
|
||||
id: 'user',
|
||||
state: {
|
||||
type: 'bing dun dun',
|
||||
persons: persons,
|
||||
},
|
||||
actions: {
|
||||
addOnePerson: (state, person) => {
|
||||
state.persons.push(person);
|
||||
},
|
||||
delOnePerson: (state) => {
|
||||
state.persons.pop();
|
||||
},
|
||||
clearPersons: (state) => {
|
||||
state.persons = [];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
describe('在Class组件中,测试store中的Array', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container:HTMLElement|null = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container?.remove();
|
||||
container = null;
|
||||
LogUtils.clear();
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
||||
const newPerson = { name: 'p3', age: 3 };
|
||||
class Parent extends Horizon.Component {
|
||||
userStore = useUserStore();
|
||||
props:{
|
||||
children:any[]
|
||||
};
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
addOnePerson = () => {
|
||||
this.userStore.addOnePerson(newPerson);
|
||||
}
|
||||
|
||||
delOnePerson = () => {
|
||||
this.userStore.delOnePerson();
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div>
|
||||
<button id={'addBtn'} onClick={this.addOnePerson}>
|
||||
add person
|
||||
</button>
|
||||
<button id={'delBtn'} onClick={this.delOnePerson}>
|
||||
delete person
|
||||
</button>
|
||||
<div>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
it('测试Array方法: push()、pop()', () => {
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useUserStore();
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Text id={'hasPerson'} text={`has new person: ${this.userStore.persons.length}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: 2');
|
||||
// 在Array中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: 3');
|
||||
|
||||
// 在Array中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: 2');
|
||||
});
|
||||
|
||||
it('测试Array方法: entries()、push()、shift()、unshift、直接赋值', () => {
|
||||
let globalStore = useUserStore();
|
||||
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useUserStore();
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
globalStore = this.userStore;
|
||||
}
|
||||
|
||||
render() {
|
||||
const nameList:string[] = [];
|
||||
const entries = this.userStore.$s.persons?.entries();
|
||||
if (entries) {
|
||||
for (const entry of entries) {
|
||||
nameList.push(entry[1].name);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'nameList'} text={`name list: ${nameList.join(' ')}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// push
|
||||
globalStore?.$s.persons.push(newPerson);
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// shift
|
||||
// @ts-ignore TODO:why has this function argument?
|
||||
globalStore.$s.persons.shift({ name: 'p0', age: 0 });
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p2 p3');
|
||||
|
||||
// 赋值[2]
|
||||
globalStore.$s.persons[2] = { name: 'p4', age: 4 };
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p2 p3 p4');
|
||||
|
||||
// 重新赋值[2]
|
||||
globalStore.$s.persons[2] = { name: 'p5', age: 5 };
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p2 p3 p5');
|
||||
|
||||
// unshift
|
||||
globalStore.$s.persons.unshift({ name: 'p1', age: 1 });
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3 p5');
|
||||
|
||||
// 重新赋值 []
|
||||
globalStore.$s.persons = [];
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
|
||||
// 重新赋值 [{ name: 'p1', age: 1 }]
|
||||
globalStore.$s.persons = [{ name: 'p1', age: 1 }];
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1');
|
||||
});
|
||||
|
||||
it('测试Array方法: forEach()', () => {
|
||||
let globalStore = useUserStore();
|
||||
globalStore.$s.persons.push({ name: 'p2', age: 2 });
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useUserStore();
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
globalStore = this.userStore;
|
||||
}
|
||||
|
||||
render() {
|
||||
const nameList:string[] = [];
|
||||
this.userStore.$s.persons.forEach((per:Person) => {
|
||||
nameList.push(per.name);
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'nameList'} text={`name list: ${nameList.join(' ')}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// push
|
||||
globalStore.$s.persons.push(newPerson);
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// shift
|
||||
// @ts-ignore TODO:why has this function argument?
|
||||
globalStore.$s.persons.shift({ name: 'p0', age: 0 });
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p2 p3');
|
||||
|
||||
// 赋值[2]
|
||||
globalStore.$s.persons[2] = { name: 'p4', age: 4 };
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p2 p3 p4');
|
||||
|
||||
// 重新赋值[2]
|
||||
globalStore.$s.persons[2] = { name: 'p5', age: 5 };
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p2 p3 p5');
|
||||
|
||||
// unshift
|
||||
globalStore.$s.persons.unshift({ name: 'p1', age: 1 });
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3 p5');
|
||||
|
||||
// 重新赋值 []
|
||||
globalStore.$s.persons = [];
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
|
||||
// 重新赋值 [{ name: 'p1', age: 1 }]
|
||||
globalStore.$s.persons = [{ name: 'p1', age: 1 }];
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1');
|
||||
});
|
||||
|
||||
});
|
|
@ -1,25 +1,14 @@
|
|||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { clearStore, createStore, useStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { App, Text, triggerClickEvent } from '../../jest/commonComponents';
|
||||
import * as LogUtils from '../../jest/logUtils';
|
||||
import {clearStore, createStore, useStore} from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import {App, Text, triggerClickEvent} from '../../jest/commonComponents';
|
||||
import {describe, beforeEach, afterEach, it, expect} from '@jest/globals';
|
||||
|
||||
describe('在Class组件中,测试store中的Map', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
const persons = new Map([
|
||||
['p1', 1],
|
||||
['p2', 2],
|
||||
]);
|
||||
|
||||
createStore({
|
||||
const useUserStore = createStore({
|
||||
id: 'user',
|
||||
state: {
|
||||
type: 'bing dun dun',
|
||||
persons: persons,
|
||||
persons: new Map([['p1', 1], ['p2', 2]]),
|
||||
},
|
||||
actions: {
|
||||
addOnePerson: (state, person) => {
|
||||
|
@ -28,18 +17,32 @@ describe('在Class组件中,测试store中的Map', () => {
|
|||
delOnePerson: (state, person) => {
|
||||
state.persons.delete(person.name);
|
||||
},
|
||||
clearPersons: state => {
|
||||
clearPersons: (state) => {
|
||||
state.persons.clear();
|
||||
},
|
||||
reset: (state)=>{
|
||||
state.persons=new Map([['p1', 1], ['p2', 2]]);
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('在Class组件中,测试store中的Map', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container:HTMLElement|null = null;
|
||||
beforeEach(() => {
|
||||
// 创建一个 DOM 元素作为渲染目标
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
useUserStore().reset();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container?.remove();
|
||||
container = null;
|
||||
LogUtils.clear();
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
@ -47,17 +50,23 @@ describe('在Class组件中,测试store中的Map', () => {
|
|||
const newPerson = { name: 'p3', age: 3 };
|
||||
|
||||
class Parent extends Horizon.Component {
|
||||
userStore = useStore('user');
|
||||
userStore = useUserStore();
|
||||
props = {children:[]}
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
addOnePerson = () => {
|
||||
this.userStore.addOnePerson(newPerson);
|
||||
};
|
||||
}
|
||||
delOnePerson = () => {
|
||||
this.userStore.delOnePerson(newPerson);
|
||||
};
|
||||
}
|
||||
clearPersons = () => {
|
||||
this.userStore.clearPersons();
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
@ -71,7 +80,9 @@ describe('在Class组件中,测试store中的Map', () => {
|
|||
<button id={'clearBtn'} onClick={this.clearPersons}>
|
||||
clear persons
|
||||
</button>
|
||||
<div>{this.props.children}</div>
|
||||
<div>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -79,12 +90,12 @@ describe('在Class组件中,测试store中的Map', () => {
|
|||
|
||||
it('测试Map方法: set()、delete()、clear()', () => {
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useStore('user');
|
||||
userStore = useUserStore();
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Text id={'size'} text={`persons number: ${this.userStore.$state.persons.size}`} />
|
||||
<Text id={'size'} text={`persons number: ${this.userStore.$s.persons.size}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -92,33 +103,33 @@ describe('在Class组件中,测试store中的Map', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#size').innerHTML).toBe('persons number: 2');
|
||||
expect(container?.querySelector('#size')?.innerHTML).toBe('persons number: 2');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#size').innerHTML).toBe('persons number: 3');
|
||||
expect(container?.querySelector('#size')?.innerHTML).toBe('persons number: 3');
|
||||
|
||||
// 在Map中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#size').innerHTML).toBe('persons number: 2');
|
||||
expect(container?.querySelector('#size')?.innerHTML).toBe('persons number: 2');
|
||||
|
||||
// clear Map
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#size').innerHTML).toBe('persons number: 0');
|
||||
expect(container?.querySelector('#size')?.innerHTML).toBe('persons number: 0');
|
||||
});
|
||||
|
||||
it('测试Map方法: keys()', () => {
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useStore('user');
|
||||
userStore = useUserStore();
|
||||
|
||||
render() {
|
||||
const nameList = [];
|
||||
const keys = this.userStore.$state.persons.keys();
|
||||
const nameList:string[] = [];
|
||||
const keys = this.userStore.$s.persons.keys();
|
||||
for (const key of keys) {
|
||||
nameList.push(key);
|
||||
}
|
||||
|
@ -133,33 +144,33 @@ describe('在Class组件中,测试store中的Map', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// 在Map中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
|
||||
// clear Map
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
});
|
||||
|
||||
it('测试Map方法: values()', () => {
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useStore('user');
|
||||
userStore = useUserStore();
|
||||
|
||||
render() {
|
||||
const ageList = [];
|
||||
const values = this.userStore.$state.persons.values();
|
||||
const ageList:number[] = [];
|
||||
const values = this.userStore.$s.persons.values();
|
||||
for (const val of values) {
|
||||
ageList.push(val);
|
||||
}
|
||||
|
@ -174,33 +185,33 @@ describe('在Class组件中,测试store中的Map', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#ageList').innerHTML).toBe('age list: 1 2');
|
||||
expect(container?.querySelector('#ageList')?.innerHTML).toBe('age list: 1 2');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#ageList').innerHTML).toBe('age list: 1 2 3');
|
||||
expect(container?.querySelector('#ageList')?.innerHTML).toBe('age list: 1 2 3');
|
||||
|
||||
// 在Map中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#ageList').innerHTML).toBe('age list: 1 2');
|
||||
expect(container?.querySelector('#ageList')?.innerHTML).toBe('age list: 1 2');
|
||||
|
||||
// clear Map
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#ageList').innerHTML).toBe('age list: ');
|
||||
expect(container?.querySelector('#ageList')?.innerHTML).toBe('age list: ');
|
||||
});
|
||||
|
||||
it('测试Map方法: entries()', () => {
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useStore('user');
|
||||
userStore = useUserStore();
|
||||
|
||||
render() {
|
||||
const nameList = [];
|
||||
const entries = this.userStore.$state.persons.entries();
|
||||
const nameList:string[] = [];
|
||||
const entries = this.userStore.$s.persons.entries();
|
||||
for (const entry of entries) {
|
||||
nameList.push(entry[0]);
|
||||
}
|
||||
|
@ -215,33 +226,33 @@ describe('在Class组件中,测试store中的Map', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// 在Map中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
|
||||
// clear Map
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
});
|
||||
|
||||
it('测试Map方法: forEach()', () => {
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useStore('user');
|
||||
userStore = useUserStore();
|
||||
|
||||
render() {
|
||||
const nameList = [];
|
||||
this.userStore.$state.persons.forEach((val, key) => {
|
||||
const nameList:string[] = [];
|
||||
this.userStore.$s.persons.forEach((val, key) => {
|
||||
nameList.push(key);
|
||||
});
|
||||
|
||||
|
@ -255,34 +266,34 @@ describe('在Class组件中,测试store中的Map', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// 在Map中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
|
||||
// clear Map
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
});
|
||||
|
||||
it('测试Map方法: has()', () => {
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useStore('user');
|
||||
userStore = useUserStore();
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Text id={'hasPerson'} text={`has new person: ${this.userStore.$state.persons.has(newPerson.name)}`} />
|
||||
<Text id={'hasPerson'} text={`has new person: ${this.userStore.$s.persons.has(newPerson.name)}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -290,21 +301,21 @@ describe('在Class组件中,测试store中的Map', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: false');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: false');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#hasPerson').innerHTML).toBe('has new person: true');
|
||||
expect(container?.querySelector('#hasPerson')?.innerHTML).toBe('has new person: true');
|
||||
});
|
||||
|
||||
it('测试Map方法: for of()', () => {
|
||||
class Child extends Horizon.Component {
|
||||
userStore = useStore('user');
|
||||
userStore = useUserStore();
|
||||
|
||||
render() {
|
||||
const nameList = [];
|
||||
for (const per of this.userStore.$state.persons) {
|
||||
const nameList:string[] = [];
|
||||
for (const per of this.userStore.$s.persons) {
|
||||
nameList.push(per[0]);
|
||||
}
|
||||
|
||||
|
@ -318,23 +329,23 @@ describe('在Class组件中,测试store中的Map', () => {
|
|||
|
||||
Horizon.render(<App parent={Parent} child={Child} />, container);
|
||||
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
// 在Map中增加一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'addBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2 p3');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2 p3');
|
||||
|
||||
// 在Map中删除一个对象
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'delBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: p1 p2');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: p1 p2');
|
||||
|
||||
// clear Map
|
||||
Horizon.act(() => {
|
||||
triggerClickEvent(container, 'clearBtn');
|
||||
});
|
||||
expect(container.querySelector('#nameList').innerHTML).toBe('name list: ');
|
||||
expect(container?.querySelector('#nameList')?.innerHTML).toBe('name list: ');
|
||||
});
|
||||
});
|
|
@ -1,15 +1,17 @@
|
|||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { clearStore, createStore, useStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { Text, triggerClickEvent } from '../../jest/commonComponents';
|
||||
import { getObserver } from '../../../../libs/horizon/src/horizonx/proxy/ProxyHandler';
|
||||
import * as LogUtils from '../../jest/logUtils';
|
||||
import {clearStore, createStore, useStore} from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import {Text, triggerClickEvent} from '../../jest/commonComponents';
|
||||
import {getObserver} from '../../../../libs/horizon/src/horizonx/proxy/ProxyHandler';
|
||||
import {describe, it, beforeEach, afterEach, expect} from '@jest/globals';
|
||||
|
||||
describe('测试 Class VNode 清除时,对引用清除', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container = null;
|
||||
const {unmountComponentAtNode} = Horizon;
|
||||
let container:HTMLElement|null = null;
|
||||
let globalState = {
|
||||
name: 'bing dun dun',
|
||||
isWin: true,
|
||||
isShow: true,
|
||||
isShow: true
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -24,7 +26,7 @@ describe('测试 Class VNode 清除时,对引用清除', () => {
|
|||
setWin: (state, val) => {
|
||||
state.isWin = val;
|
||||
},
|
||||
hide: state => {
|
||||
hide: (state) => {
|
||||
state.isShow = false;
|
||||
},
|
||||
updateName: (state, val) => {
|
||||
|
@ -37,8 +39,9 @@ describe('测试 Class VNode 清除时,对引用清除', () => {
|
|||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container?.remove();
|
||||
container = null;
|
||||
LogUtils.clear();
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
@ -48,14 +51,12 @@ describe('测试 Class VNode 清除时,对引用清除', () => {
|
|||
userStore = useStore('user');
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<button id={'hideBtn'} onClick={this.userStore.hide}>
|
||||
return <div>
|
||||
<button id={'hideBtn'} onClick={this.userStore?.hide}>
|
||||
toggle
|
||||
</button>
|
||||
{this.userStore.isShow && <Parent />}
|
||||
</div>
|
||||
);
|
||||
{this.userStore?.isShow && <Parent/>}
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,18 +64,16 @@ describe('测试 Class VNode 清除时,对引用清除', () => {
|
|||
userStore = useStore('user');
|
||||
|
||||
setWin = () => {
|
||||
this.userStore.setWin(!this.userStore.isWin);
|
||||
};
|
||||
this.userStore?.setWin(!this.userStore?.isWin);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
return <div>
|
||||
<button id={'toggleBtn'} onClick={this.setWin}>
|
||||
toggle
|
||||
</button>
|
||||
{this.userStore.isWin && <Child />}
|
||||
</div>
|
||||
);
|
||||
{this.userStore?.isWin && <Child/>}
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,16 +83,14 @@ describe('测试 Class VNode 清除时,对引用清除', () => {
|
|||
render() {
|
||||
// this.userStore.updateName(this.userStore.name === 'bing dun dun' ? 'huo dun dun' : 'bing dun dun');
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text id={'name'} text={`name: ${this.userStore.name}`} />
|
||||
<Text id={'isWin'} text={`isWin: ${this.userStore.isWin}`} />
|
||||
</div>
|
||||
);
|
||||
return <div>
|
||||
<Text id={'name'} text={`name: ${this.userStore?.name}`}/>
|
||||
<Text id={'isWin'} text={`isWin: ${this.userStore?.isWin}`}/>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
Horizon.render(<App />, container);
|
||||
Horizon.render(<App/>, container);
|
||||
|
||||
// Parent and Child hold the isWin key
|
||||
expect(getObserver(globalState).keyVNodes.get('isWin').size).toBe(2);
|
|
@ -1,15 +1,17 @@
|
|||
import * as Horizon from '@cloudsop/horizon/index.ts';
|
||||
import { clearStore, createStore, useStore } from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import { Text, triggerClickEvent } from '../../jest/commonComponents';
|
||||
import { getObserver } from '../../../../libs/horizon/src/horizonx/proxy/ProxyHandler';
|
||||
import * as LogUtils from '../../jest/logUtils';
|
||||
import {clearStore, createStore, useStore} from '../../../../libs/horizon/src/horizonx/store/StoreHandler';
|
||||
import {Text, triggerClickEvent} from '../../jest/commonComponents';
|
||||
import {getObserver} from '../../../../libs/horizon/src/horizonx/proxy/ProxyHandler';
|
||||
import {describe, it, beforeEach, afterEach, expect} from '@jest/globals';
|
||||
|
||||
describe('测试VNode清除时,对引用清除', () => {
|
||||
const { unmountComponentAtNode } = Horizon;
|
||||
let container = null;
|
||||
const {unmountComponentAtNode} = Horizon;
|
||||
let container:HTMLElement|null = null;
|
||||
let globalState = {
|
||||
name: 'bing dun dun',
|
||||
isWin: true,
|
||||
isShow: true,
|
||||
isShow: true
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -24,9 +26,9 @@ describe('测试VNode清除时,对引用清除', () => {
|
|||
setWin: (state, val) => {
|
||||
state.isWin = val;
|
||||
},
|
||||
hide: state => {
|
||||
hide: (state) => {
|
||||
state.isShow = false;
|
||||
},
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -34,8 +36,9 @@ describe('测试VNode清除时,对引用清除', () => {
|
|||
afterEach(() => {
|
||||
// 退出时进行清理
|
||||
unmountComponentAtNode(container);
|
||||
container.remove();
|
||||
container?.remove();
|
||||
container = null;
|
||||
LogUtils.clear();
|
||||
|
||||
clearStore('user');
|
||||
});
|
||||
|
@ -45,14 +48,12 @@ describe('测试VNode清除时,对引用清除', () => {
|
|||
userStore = useStore('user');
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<button id={'hideBtn'} onClick={this.userStore.hide}>
|
||||
return <div>
|
||||
<button id={'hideBtn'} onClick={this.userStore?.hide}>
|
||||
toggle
|
||||
</button>
|
||||
{this.userStore.isShow && <Parent />}
|
||||
</div>
|
||||
);
|
||||
{this.userStore?.isShow && <Parent/>}
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,18 +61,16 @@ describe('测试VNode清除时,对引用清除', () => {
|
|||
userStore = useStore('user');
|
||||
|
||||
setWin = () => {
|
||||
this.userStore.setWin(!this.userStore.isWin);
|
||||
};
|
||||
this.userStore?.setWin(!this.userStore.isWin);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
return <div>
|
||||
<button id={'toggleBtn'} onClick={this.setWin}>
|
||||
toggle
|
||||
</button>
|
||||
{this.userStore.isWin && <Child />}
|
||||
</div>
|
||||
);
|
||||
{this.userStore?.isWin && <Child/>}
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,16 +78,14 @@ describe('测试VNode清除时,对引用清除', () => {
|
|||
userStore = useStore('user');
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Text id={'name'} text={`name: ${this.userStore.name}`} />
|
||||
<Text id={'isWin'} text={`isWin: ${this.userStore.isWin}`} />
|
||||
</div>
|
||||
);
|
||||
return <div>
|
||||
<Text id={'name'} text={`name: ${this.userStore?.name}`}/>
|
||||
<Text id={'isWin'} text={`isWin: ${this.userStore?.isWin}`}/>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
Horizon.render(<App />, container);
|
||||
Horizon.render(<App/>, container);
|
||||
|
||||
// Parent and Child hold the isWin key
|
||||
expect(getObserver(globalState).keyVNodes.get('isWin').size).toBe(2);
|
|
@ -1,21 +0,0 @@
|
|||
import { createProxy } from '../../../../libs/horizon/src/horizonx/proxy/ProxyHandler';
|
||||
|
||||
describe('Proxy', () => {
|
||||
const arr = [];
|
||||
|
||||
it('Should not double wrap proxies', async () => {
|
||||
const proxy1 = createProxy(arr);
|
||||
|
||||
const proxy2 = createProxy(proxy1);
|
||||
|
||||
expect(proxy1 === proxy2).toBe(true);
|
||||
});
|
||||
|
||||
it('Should re-use existing proxy of same object', async () => {
|
||||
const proxy1 = createProxy(arr);
|
||||
|
||||
const proxy2 = createProxy(arr);
|
||||
|
||||
expect(proxy1 === proxy2).toBe(true);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,48 @@
|
|||
import {createProxy} from '../../../../libs/horizon/src/horizonx/proxy/ProxyHandler';
|
||||
import {readonlyProxy} from '../../../../libs/horizon/src/horizonx/proxy/readonlyProxy';
|
||||
import {describe, beforeEach, afterEach, it, expect} from '@jest/globals';
|
||||
|
||||
describe('Proxy', () => {
|
||||
const arr = [];
|
||||
|
||||
it('Should not double wrap proxies', async () => {
|
||||
const proxy1 = createProxy(arr);
|
||||
|
||||
const proxy2 = createProxy(proxy1);
|
||||
|
||||
expect(proxy1 === proxy2).toBe(true);
|
||||
});
|
||||
|
||||
it('Should re-use existing proxy of same object', async () => {
|
||||
const proxy1 = createProxy(arr);
|
||||
|
||||
const proxy2 = createProxy(arr);
|
||||
|
||||
expect(proxy1 === proxy2).toBe(true);
|
||||
});
|
||||
|
||||
it('Readonly proxy should prevent changes', async () => {
|
||||
const proxy1 = readonlyProxy([1]);
|
||||
|
||||
try{
|
||||
proxy1.push('a');
|
||||
expect(true).toBe(false);//we expect exception above
|
||||
}catch(e){
|
||||
//expected
|
||||
}
|
||||
|
||||
try{
|
||||
proxy1[0]=null;
|
||||
expect(true).toBe(false);//we expect exception above
|
||||
}catch(e){
|
||||
//expected
|
||||
}
|
||||
|
||||
try{
|
||||
delete proxy1[0];
|
||||
expect(true).toBe(false);//we expect exception above
|
||||
}catch(e){
|
||||
//expected
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,26 @@
|
|||
let dataArray = null;
|
||||
|
||||
const log = value => {
|
||||
if (dataArray === null) {
|
||||
dataArray = [value];
|
||||
} else {
|
||||
dataArray.push(value);
|
||||
}
|
||||
};
|
||||
|
||||
const getAndClear = () => {
|
||||
if (dataArray === null) {
|
||||
return [];
|
||||
}
|
||||
const values = dataArray;
|
||||
dataArray = null;
|
||||
return values;
|
||||
};
|
||||
|
||||
const clear = () => {
|
||||
dataArray = dataArray ? null : dataArray;
|
||||
};
|
||||
|
||||
exports.clear = clear;
|
||||
exports.log = log;
|
||||
exports.getAndClear = getAndClear;
|
|
@ -4,6 +4,7 @@ import path from 'path';
|
|||
import fs from 'fs';
|
||||
import replace from '@rollup/plugin-replace';
|
||||
import copy from './copy-plugin';
|
||||
import execute from 'rollup-plugin-execute';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
import { version as horizonVersion } from '@cloudsop/horizon/package.json';
|
||||
|
||||
|
@ -60,6 +61,7 @@ function genConfig(mode) {
|
|||
},
|
||||
preventAssignment: true,
|
||||
}),
|
||||
execute('npm run build-types'),
|
||||
mode === 'production' && terser(),
|
||||
copy([
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue