311 lines
8.2 KiB
TypeScript
311 lines
8.2 KiB
TypeScript
/*
|
|
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
|
*
|
|
* openGauss is licensed under Mulan PSL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
* You may obtain a copy of Mulan PSL v2 at:
|
|
*
|
|
* http://license.coscl.org.cn/MulanPSL2
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PSL v2 for more details.
|
|
*/
|
|
|
|
//@ts-ignore
|
|
import horizon, * as Horizon from '@cloudsop/horizon/index.ts';
|
|
import {
|
|
batch,
|
|
connect,
|
|
createStore,
|
|
Provider,
|
|
useDispatch,
|
|
useSelector,
|
|
useStore,
|
|
createSelectorHook,
|
|
createDispatchHook
|
|
} from '../../../../libs/horizon/src/horizonx/adapters/redux';
|
|
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'
|
|
|
|
function getE(id):HTMLElement {
|
|
return document.getElementById(id)||document.body;
|
|
}
|
|
|
|
describe('Redux/React binding adapter', () => {
|
|
beforeEach(() => {
|
|
const container = document.createElement('div');
|
|
container.id = CONTAINER;
|
|
document.body.appendChild(container);
|
|
});
|
|
|
|
afterEach(() => {
|
|
document.body.removeChild(getE(CONTAINER));
|
|
});
|
|
|
|
it('Should create provider context', async () => {
|
|
const reduxStore = createStore((state = 'state', action) => state);
|
|
|
|
const Child = () => {
|
|
const store = useStore() as unknown as ReduxStoreHandler;
|
|
return <div id={RESULT}>{store.getState()}</div>;
|
|
};
|
|
|
|
const Wrapper = () => {
|
|
return <Provider store={reduxStore}>
|
|
<Child/>
|
|
</Provider>;
|
|
};
|
|
|
|
Horizon.render(<Wrapper/>, getE(CONTAINER));
|
|
|
|
expect(getE(RESULT).innerHTML).toBe('state');
|
|
});
|
|
|
|
it('Should use dispatch', async () => {
|
|
const reduxStore = createStore((state = 0, action) => {
|
|
if (action.type === 'ADD') return state + 1;
|
|
return state;
|
|
});
|
|
|
|
const Child = () => {
|
|
const store = useStore() as unknown as ReduxStoreHandler;
|
|
const dispatch = useDispatch();
|
|
return <div>
|
|
<p id={RESULT}>{store.getState()}</p>
|
|
<button id={BUTTON} onClick={() => {
|
|
dispatch({type: 'ADD'});
|
|
}}></button>
|
|
</div>;
|
|
};
|
|
|
|
const Wrapper = () => {
|
|
return <Provider store={reduxStore}>
|
|
<Child/>
|
|
</Provider>;
|
|
};
|
|
|
|
Horizon.render(<Wrapper/>, getE(CONTAINER));
|
|
|
|
expect(reduxStore.getState()).toBe(0);
|
|
|
|
Horizon.act(() => {
|
|
triggerClickEvent(getE(CONTAINER), BUTTON);
|
|
});
|
|
|
|
expect(reduxStore.getState()).toBe(1);
|
|
});
|
|
|
|
it('Should use selector', async () => {
|
|
const reduxStore = createStore((state = 0, action) => {
|
|
if (action.type === 'ADD') return state + 1;
|
|
return state;
|
|
});
|
|
|
|
const Child = () => {
|
|
const count = useSelector((state) => state);
|
|
const dispatch = useDispatch();
|
|
return <div>
|
|
<p id={RESULT}>{count}</p>
|
|
<button id={BUTTON} onClick={() => {
|
|
dispatch({type: 'ADD'});
|
|
}}>click
|
|
</button>
|
|
</div>;
|
|
};
|
|
|
|
const Wrapper = () => {
|
|
return <Provider store={reduxStore}>
|
|
<Child/>
|
|
</Provider>;
|
|
};
|
|
|
|
Horizon.render(<Wrapper/>, getE(CONTAINER));
|
|
|
|
expect(getE(RESULT).innerHTML).toBe('0');
|
|
|
|
Horizon.act(() => {
|
|
triggerClickEvent(getE(CONTAINER), BUTTON);
|
|
triggerClickEvent(getE(CONTAINER), BUTTON);
|
|
});
|
|
|
|
expect(getE(RESULT).innerHTML).toBe('2');
|
|
});
|
|
|
|
it('Should use connect', async () => {
|
|
const reduxStore = createStore((state, action) => {
|
|
switch (action.type) {
|
|
case('INCREMENT'):
|
|
return {
|
|
...state,
|
|
value: state.negative ? state.value - action.amount : state.value + action.amount
|
|
};
|
|
case('TOGGLE'):
|
|
return {
|
|
...state,
|
|
negative: !state.negative
|
|
};
|
|
default:
|
|
return state;
|
|
}
|
|
}, {negative: false, value: 0});
|
|
|
|
const Child = connect((state, ownProps) => {
|
|
// map state to props
|
|
return {...state, ...ownProps};
|
|
}, (dispatch, ownProps) => {
|
|
// map dispatch to props
|
|
return {
|
|
// @ts-ignore
|
|
increment: () => dispatch({type: 'INCREMENT', amount: ownProps?.amount})
|
|
};
|
|
}, (stateProps, dispatchProps, ownProps) => {
|
|
//merge 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={() => {
|
|
props.dispatchProps.increment();
|
|
}}>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={() => {
|
|
setAmount(3);
|
|
}}>change amount
|
|
</button>
|
|
</Provider>;
|
|
};
|
|
|
|
Horizon.render(<Wrapper/>, getE(CONTAINER));
|
|
|
|
expect(getE(RESULT).innerHTML).toBe('+0');
|
|
|
|
Horizon.act(() => {
|
|
triggerClickEvent(getE(CONTAINER), BUTTON);
|
|
});
|
|
|
|
expect(getE(RESULT).innerHTML).toBe('+5');
|
|
|
|
Horizon.act(() => {
|
|
triggerClickEvent(getE(CONTAINER), BUTTON2);
|
|
});
|
|
|
|
Horizon.act(() => {
|
|
triggerClickEvent(getE(CONTAINER), BUTTON);
|
|
});
|
|
|
|
expect(getE(RESULT).innerHTML).toBe('+8');
|
|
})
|
|
|
|
it('Should batch dispatches', async () => {
|
|
const reduxStore = createStore((state = 0, action) => {
|
|
if (action.type == 'ADD') return state + 1;
|
|
return state;
|
|
});
|
|
|
|
let renderCounter = 0;
|
|
|
|
function Counter() {
|
|
renderCounter++;
|
|
|
|
const value = useSelector((state) => state);
|
|
const dispatch = useDispatch();
|
|
|
|
return <div>
|
|
<p id={RESULT}>{value}</p>
|
|
<button id={BUTTON} onClick={() => {
|
|
batch(() => {
|
|
for (let i = 0; i < 10; i++) {
|
|
dispatch({type: 'ADD'});
|
|
}
|
|
});
|
|
}}></button>
|
|
</div>;
|
|
}
|
|
|
|
Horizon.render(<Provider store={reduxStore}><Counter/></Provider>, getE(CONTAINER));
|
|
|
|
expect(getE(RESULT).innerHTML).toBe('0');
|
|
expect(renderCounter).toBe(1);
|
|
|
|
Horizon.act(() => {
|
|
triggerClickEvent(getE(CONTAINER), BUTTON);
|
|
});
|
|
|
|
expect(getE(RESULT).innerHTML).toBe('10');
|
|
expect(renderCounter).toBe(2);
|
|
});
|
|
|
|
it('Should use multiple contexts', async () => {
|
|
const counterStore = createStore((state = 0, action) => {
|
|
if (action.type === 'ADD') return state + 1;
|
|
return state;
|
|
});
|
|
|
|
const toggleStore = createStore((state = false, action) => {
|
|
if (action.type === 'TOGGLE') return !state;
|
|
return state;
|
|
});
|
|
|
|
const counterContext = horizon.createContext();
|
|
const toggleContext = horizon.createContext();
|
|
|
|
function Counter() {
|
|
const count = createSelectorHook(counterContext)();
|
|
const dispatch = createDispatchHook(counterContext)();
|
|
|
|
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>;
|
|
}
|
|
|
|
function Wrapper() {
|
|
return <div>
|
|
<Provider store={counterStore} context={counterContext}>
|
|
<Counter/>
|
|
</Provider>
|
|
|
|
<Provider store={toggleStore} context={toggleContext}>
|
|
<Toggle/>
|
|
</Provider>
|
|
</div>;
|
|
}
|
|
|
|
Horizon.render(<Wrapper/>, getE(CONTAINER));
|
|
|
|
expect(getE(BUTTON).innerHTML).toBe('0');
|
|
expect(getE(BUTTON2).innerHTML).toBe('false');
|
|
|
|
Horizon.act(() => {
|
|
triggerClickEvent(getE(CONTAINER), BUTTON);
|
|
triggerClickEvent(getE(CONTAINER), BUTTON2);
|
|
});
|
|
|
|
expect(getE(BUTTON).innerHTML).toBe('1');
|
|
expect(getE(BUTTON2).innerHTML).toBe('true');
|
|
});
|
|
}); |