summaryrefslogtreecommitdiff
path: root/preact/hooks/test/browser/hooks.options.test.js
diff options
context:
space:
mode:
Diffstat (limited to 'preact/hooks/test/browser/hooks.options.test.js')
-rw-r--r--preact/hooks/test/browser/hooks.options.test.js154
1 files changed, 154 insertions, 0 deletions
diff --git a/preact/hooks/test/browser/hooks.options.test.js b/preact/hooks/test/browser/hooks.options.test.js
new file mode 100644
index 0000000..ca88d1f
--- /dev/null
+++ b/preact/hooks/test/browser/hooks.options.test.js
@@ -0,0 +1,154 @@
+import {
+ afterDiffSpy,
+ beforeRenderSpy,
+ unmountSpy,
+ hookSpy
+} from '../../../test/_util/optionSpies';
+
+import { setupRerender, act } from 'preact/test-utils';
+import { createElement, render, createContext, options } from 'preact';
+import { setupScratch, teardown } from '../../../test/_util/helpers';
+import {
+ useState,
+ useReducer,
+ useEffect,
+ useLayoutEffect,
+ useRef,
+ useImperativeHandle,
+ useMemo,
+ useCallback,
+ useContext,
+ useErrorBoundary
+} from 'preact/hooks';
+
+/** @jsx createElement */
+
+describe('hook options', () => {
+ /** @type {HTMLDivElement} */
+ let scratch;
+
+ /** @type {() => void} */
+ let rerender;
+
+ /** @type {() => void} */
+ let increment;
+
+ beforeEach(() => {
+ scratch = setupScratch();
+ rerender = setupRerender();
+
+ afterDiffSpy.resetHistory();
+ unmountSpy.resetHistory();
+ beforeRenderSpy.resetHistory();
+ hookSpy.resetHistory();
+ });
+
+ afterEach(() => {
+ teardown(scratch);
+ });
+
+ function App() {
+ const [count, setCount] = useState(0);
+ increment = () => setCount(prevCount => prevCount + 1);
+ return <div>{count}</div>;
+ }
+
+ it('should call old options on mount', () => {
+ render(<App />, scratch);
+
+ expect(beforeRenderSpy).to.have.been.called;
+ expect(afterDiffSpy).to.have.been.called;
+ });
+
+ it('should call old options.diffed on update', () => {
+ render(<App />, scratch);
+
+ increment();
+ rerender();
+
+ expect(beforeRenderSpy).to.have.been.called;
+ expect(afterDiffSpy).to.have.been.called;
+ });
+
+ it('should call old options on unmount', () => {
+ render(<App />, scratch);
+ render(null, scratch);
+
+ expect(unmountSpy).to.have.been.called;
+ });
+
+ it('should detect hooks', () => {
+ const USE_STATE = 1;
+ const USE_REDUCER = 2;
+ const USE_EFFECT = 3;
+ const USE_LAYOUT_EFFECT = 4;
+ const USE_REF = 5;
+ const USE_IMPERATIVE_HANDLE = 6;
+ const USE_MEMO = 7;
+ const USE_CALLBACK = 8;
+ const USE_CONTEXT = 9;
+ const USE_ERROR_BOUNDARY = 10;
+
+ const Ctx = createContext(null);
+
+ function App() {
+ useState(0);
+ useReducer(x => x, 0);
+ useEffect(() => null, []);
+ useLayoutEffect(() => null, []);
+ const ref = useRef(null);
+ useImperativeHandle(ref, () => null);
+ useMemo(() => null, []);
+ useCallback(() => null, []);
+ useContext(Ctx);
+ useErrorBoundary(() => null);
+ }
+
+ render(
+ <Ctx.Provider value="a">
+ <App />
+ </Ctx.Provider>,
+ scratch
+ );
+
+ expect(hookSpy.args.map(arg => [arg[1], arg[2]])).to.deep.equal([
+ [0, USE_STATE],
+ [1, USE_REDUCER],
+ [2, USE_EFFECT],
+ [3, USE_LAYOUT_EFFECT],
+ [4, USE_REF],
+ [5, USE_IMPERATIVE_HANDLE],
+ [6, USE_MEMO],
+ [7, USE_CALLBACK],
+ [8, USE_CONTEXT],
+ [9, USE_ERROR_BOUNDARY],
+ // Belongs to useErrorBoundary that uses multiple native hooks.
+ [10, USE_STATE]
+ ]);
+ });
+
+ describe('Effects', () => {
+ beforeEach(() => {
+ options._skipEffects = options.__s = true;
+ });
+
+ afterEach(() => {
+ options._skipEffects = options.__s = false;
+ });
+
+ it('should skip effect hooks', () => {
+ const spy = sinon.spy();
+ function App() {
+ useEffect(spy, []);
+ useLayoutEffect(spy, []);
+ return null;
+ }
+
+ act(() => {
+ render(<App />, scratch);
+ });
+
+ expect(spy.callCount).to.equal(0);
+ });
+ });
+});