inula/scripts/__tests__/ComponentTest/SimpleUseHook.test.js

313 lines
9.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import * as React from '../../../libs/horizon/src/external/Horizon';
import * as HorizonDOM from '../../../libs/horizon/src/dom/DOMExternal';
import { act } from '../jest/customMatcher';
describe('Hook Test', () => {
const {
useState,
useReducer,
useEffect,
useLayoutEffect,
useContext,
useMemo,
useCallback,
useRef,
useImperativeHandle,
forwardRef
} = React;
const { unmountComponentAtNode } = HorizonDOM;
let container = null;
beforeEach(() => {
// 创建一个 DOM 元素作为渲染目标
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
// 退出时进行清理
unmountComponentAtNode(container);
container.remove();
container = null;
});
it('简单使用useState', () => {
const App = () => {
const [num, setNum] = useState(0);
return (
<>
<p>{num}</p>
<button onClick={() => setNum(num + 1)} />
</>
)
}
HorizonDOM.render(<App />, container);
expect(container.querySelector('p').innerHTML).toBe('0');
// 点击按钮触发num加1
container.querySelector('button').click();
expect(container.querySelector('p').innerHTML).toBe('1');
});
it('简单使用useEffect', () => {
const App = () => {
const [num, setNum] = useState(0);
useEffect(() => {
document.getElementById('p').style.display = num === 0 ? 'none' : 'inline';
});
return (
<>
<p style={{ display: 'block' }} id="p">{num}</p>
<button onClick={() => setNum(num + 1)} />
</>
)
}
HorizonDOM.render(<App />, container);
expect(document.getElementById('p').style.display).toBe('block');
// 点击按钮触发num加1
container.querySelector('button').click();
expect(document.getElementById('p').style.display).toBe('none');
container.querySelector('button').click();
expect(container.querySelector('p').style.display).toBe('inline');
});
it('简单使用useLayoutEffect', () => {
const App = () => {
const [num, setNum] = useState(0);
useLayoutEffect(() => {
document.getElementById('p').style.display = num === 0 ? 'none' : 'inline';
});
return (
<>
<p style={{ display: 'block' }} id="p">{num}</p>
<button onClick={() => setNum(num + 1)} />
</>
)
}
HorizonDOM.render(<App />, container);
expect(document.getElementById('p').style.display).toBe('none');
container.querySelector('button').click();
expect(container.querySelector('p').style.display).toBe('inline');
});
it('简单使用useContext', () => {
const LanguageTypes = {
JAVA: 'Java',
JAVASCRIPT: 'JavaScript',
};
const defaultValue = { type: LanguageTypes.JAVASCRIPT };
const SystemLanguageContext = React.createContext(defaultValue);
const SystemLanguageProvider = ({ type, children }) => {
return (
<SystemLanguageContext.Provider value={{ type }}>
{children}
</SystemLanguageContext.Provider>
);
};
const TestFunction = () => {
const context = useContext(SystemLanguageContext);
return <p id="p">{context.type}</p>;
}
let setValue;
const App = () => {
const [value, _setValue] = useState(LanguageTypes.JAVA);
setValue = _setValue;
return (
<div className="App">
<SystemLanguageProvider type={value}>
<TestFunction />
</SystemLanguageProvider>
</div>
)
}
HorizonDOM.render(<TestFunction />, container);
// 测试当Provider未提供时获取到的默认值'JavaScript'。
expect(container.querySelector('p').innerHTML).toBe('JavaScript');
unmountComponentAtNode(container);
HorizonDOM.render(<App />, container);
// 测试当Provider提供时可以获取到Provider的值'Java'。
expect(container.querySelector('p').innerHTML).toBe('Java');
// 测试当Provider改变时可以获取到最新Provider的值。
act(() => setValue(LanguageTypes.JAVASCRIPT));
expect(container.querySelector('p').innerHTML).toBe('JavaScript');
});
it('简单使用useReducer', () => {
const intlCar = { logo: '', price: 0 };
let dispatch;
const App = () => {
const carReducer = (state, action) => {
switch (action.logo) {
case 'ford':
return {
...intlCar,
logo: 'ford',
price: 76
};
case 'bmw':
return {
...intlCar,
logo: 'bmw',
price: 100
};
case 'benz':
return {
...intlCar,
logo: 'benz',
price: 80
};
default:
return {
...intlCar,
logo: 'audi',
price: 88
};
}
}
const [car, carDispatch] = useReducer(carReducer, intlCar);
dispatch = carDispatch;
return (
<div>
<p>{car.logo}</p>
<p id={'senP'}>{car.price}</p>
</div>
)
}
HorizonDOM.render(<App />, container);
expect(container.querySelector('p').innerHTML).toBe('');
expect(container.querySelector('#senP').innerHTML).toBe('0');
// 触发bmw
dispatch({ logo: 'bmw' });
expect(container.querySelector('p').innerHTML).toBe('bmw');
expect(container.querySelector('#senP').innerHTML).toBe('100');
// 触发carReducer里的switch的default项
dispatch({ logo: 'wrong logo' });
expect(container.querySelector('p').innerHTML).toBe('audi');
expect(container.querySelector('#senP').innerHTML).toBe('88');
});
it('测试useMemo', () => {
let setMemo;
const App = () => {
const [num, setNum] = useState(0);
const [memoDependent, _setMemo] = useState('App');
setMemo = _setMemo;
const text = useMemo(() => {
setNum(num + 1);
return memoDependent;
}, [memoDependent])
return (
<>
<p>{text}</p>
<p id="p">{num}</p>
</>
);
}
HorizonDOM.render(<App words="App" />, container);
expect(container.querySelector('p').innerHTML).toBe('App');
expect(container.querySelector('#p').innerHTML).toBe('1');
// 修改useMemo的依赖项num会加一text会改变。
setMemo('Apps')
expect(container.querySelector('p').innerHTML).toBe('Apps');
expect(container.querySelector('#p').innerHTML).toBe('2');
// useMemo的依赖项不变num不会加一text不会改变。
setMemo('Apps')
expect(container.querySelector('p').innerHTML).toBe('Apps');
expect(container.querySelector('#p').innerHTML).toBe('2');
// 修改useMemo的依赖项num会加一text会改变。
setMemo('App')
expect(container.querySelector('p').innerHTML).toBe('App');
expect(container.querySelector('#p').innerHTML).toBe('3');
});
it('测试useCallback', () => {
const App = (props) => {
const [num, setNum] = useState(0);
const NumUseCallback = useCallback(() => {
setNum(num + props.text)
}, [props]);
return (
<>
<p>{num}</p>
<button onClick={NumUseCallback} />
</>
)
}
HorizonDOM.render(<App text={1} />, container);
expect(container.querySelector('p').innerHTML).toBe('0');
// 点击按钮触发num加1
container.querySelector('button').click();
expect(container.querySelector('p').innerHTML).toBe('1');
// 再次点击依赖项没变num不增加
container.querySelector('button').click();
expect(container.querySelector('p').innerHTML).toBe('1');
HorizonDOM.render(<App text={2} />, container);
expect(container.querySelector('p').innerHTML).toBe('1');
// 依赖项有变化点击按钮num增加
container.querySelector('button').click();
expect(container.querySelector('p').innerHTML).toBe('3');
});
it('测试useRef', () => {
const App = () => {
const [num, setNum] = useState(1);
const ref = useRef();
if (!ref.current) {
ref.current = num;
}
return (
<>
<p>{num}</p>
<p id="sp">{ref.current}</p>
<button onClick={() => setNum(num + 1)} />
</>
)
}
HorizonDOM.render(<App />, container);
expect(container.querySelector('p').innerHTML).toBe('1');
expect(container.querySelector('#sp').innerHTML).toBe('1');
// 点击按钮触发num加1,ref不变
container.querySelector('button').click();
expect(container.querySelector('p').innerHTML).toBe('2');
expect(container.querySelector('#sp').innerHTML).toBe('1');
});
it('测试useImperativeHandle', () => {
let App = (props, ref) => {
const [num, setNum] = useState(0);
useImperativeHandle(ref, () => ({num, setNum}), []);
return <p>{num}</p>;
}
let App1 = (props, ref) => {
const [num1, setNum1] = useState(0);
useImperativeHandle(ref, () => ({num1, setNum1}), [num1]);
return <p>{num1}</p>;
}
App = forwardRef(App);
App1 = forwardRef(App1);
const counter = React.createRef(null);
const counter1 = React.createRef(null);
HorizonDOM.render(<App ref={counter} />, container);
expect(counter.current.num).toBe(0);
act(() => {
counter.current.setNum(1);
});
// useImperativeHandle的dep为[],所以不会变
expect(counter.current.num).toBe(0);
// 清空container
unmountComponentAtNode(container);
HorizonDOM.render(<App1 ref={counter1} />, container);
expect(counter1.current.num1).toBe(0);
act(() => {
counter1.current.setNum1(1);
});
// useImperativeHandle的dep为[num1],所以会变
expect(counter1.current.num1).toBe(1);
});
});