Skip to content

Commit

Permalink
feat(useWindowSize): A bit changed lyfecycle and added types;
Browse files Browse the repository at this point in the history
feat(useWindowSize): Rewritten tests - covers more cases and will work on next @testing-library/react-hooks release (been broken before);
  • Loading branch information
xobotyi committed Nov 3, 2019
1 parent d4ff80a commit 03bdecf
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 45 deletions.
93 changes: 54 additions & 39 deletions src/__tests__/useWindowSize.test.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,88 @@
import { act, renderHook } from '@testing-library/react-hooks';
import { replaceRaf } from 'raf-stub';
import useWindowSize from '../useWindowSize';
import { isClient } from '../util';

interface RequestAnimationFrame {
reset(): void;
step(): void;
}
declare var requestAnimationFrame: {
reset: () => void;
step: (steps?: number, duration?: number) => void;
};

declare var requestAnimationFrame: RequestAnimationFrame;
describe('useWindowSize', () => {
beforeAll(() => {
replaceRaf();
});

replaceRaf();
afterEach(() => {
requestAnimationFrame.reset();
});

beforeEach(() => {
requestAnimationFrame.reset();
});
it('should be defined', () => {
expect(useWindowSize).toBeDefined();
});

afterEach(() => {
requestAnimationFrame.reset();
});
function getHook(...args) {
return renderHook(() => useWindowSize(...args));
}

function triggerResize(dimension: 'width' | 'height', value: number) {
if (dimension === 'width') {
(window.innerWidth as number) = value;
} else if (dimension === 'height') {
(window.innerHeight as number) = value;
}

// simulate window resize
function fireResize(type, value) {
switch (type) {
case 'width':
(window.innerWidth as number) = value; // assert type of window.innerWidth as it is typed as readonly.
break;
case 'height':
(window.innerHeight as number) = value; // assert type of window.innerHeight as it is typed as readonly.
break;
default:
break;
window.dispatchEvent(new Event('resize'));
}

window.dispatchEvent(new Event('resize'));
}
it('should return current window dimensions', () => {
const hook = getHook();

describe('useWindowSize', () => {
it('should be defined', () => {
expect(useWindowSize).toBeDefined();
expect(typeof hook.result.current).toBe('object');
expect(typeof hook.result.current.height).toBe('number');
expect(typeof hook.result.current.width).toBe('number');
});

it('should use passed parameters as initial values in case of non-browser use', () => {
const hook = getHook(1, 1);

expect(hook.result.current.height).toBe(isClient ? window.innerHeight : 1);
expect(hook.result.current.width).toBe(isClient ? window.innerWidth : 1);
});

const hook = renderHook(() => useWindowSize());
it('should re-render after height change on closest RAF', () => {
const hook = getHook();

it('should update width', () => {
act(() => {
fireResize('width', 320);
triggerResize('height', 360);
requestAnimationFrame.step();
});

expect(hook.result.current.width).toBe(320);
expect(hook.result.current.height).toBe(360);

act(() => {
fireResize('width', 640);
triggerResize('height', 2048);
requestAnimationFrame.step();
});
expect(hook.result.current.width).toBe(640);

expect(hook.result.current.height).toBe(2048);
});

it('should update height', () => {
it('should re-render after width change on closest RAF', () => {
const hook = getHook();

act(() => {
fireResize('height', 500);
triggerResize('width', 360);
requestAnimationFrame.step();
});
expect(hook.result.current.height).toBe(500);

expect(hook.result.current.width).toBe(360);

act(() => {
fireResize('height', 1000);
triggerResize('width', 2048);
requestAnimationFrame.step();
});
expect(hook.result.current.height).toBe(1000);

expect(hook.result.current.width).toBe(2048);
});
});
4 changes: 2 additions & 2 deletions src/createReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ interface Store<Action, State> {

type Middleware<Action, State> = (store: Store<Action, State>) => (next: Dispatch<Action>) => (action: Action) => void;

function composeMiddleware<Action, State>(chain: Array<Middleware<Action, State>>) {
function composeMiddleware<Action, State>(chain: Middleware<Action, State>[]) {
return (context: Store<Action, State>, dispatch: Dispatch<Action>) => {
return chain.reduceRight((res, middleware) => {
return middleware(context)(res);
}, dispatch);
};
}

const createReducer = <Action, State>(...middlewares: Array<Middleware<Action, State>>) => {
const createReducer = <Action, State>(...middlewares: Middleware<Action, State>[]) => {
const composedMiddleware = composeMiddleware<Action, State>(middlewares);

return (
Expand Down
4 changes: 1 addition & 3 deletions src/useWindowSize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const useWindowSize = (initialWidth = Infinity, initialHeight = Infinity) => {
height: isClient ? window.innerHeight : initialHeight,
});

useEffect(() => {
useEffect((): (() => void) | void => {
if (isClient) {
const handler = () => {
setState({
Expand All @@ -23,8 +23,6 @@ const useWindowSize = (initialWidth = Infinity, initialHeight = Infinity) => {
return () => {
window.removeEventListener('resize', handler);
};
} else {
return undefined;
}
}, []);

Expand Down
2 changes: 1 addition & 1 deletion src/util/parseTimeRanges.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const parseTimeRanges = ranges => {
const result: Array<{ start: number; end: number }> = [];
const result: { start: number; end: number }[] = [];

for (let i = 0; i < ranges.length; i++) {
result.push({
Expand Down

0 comments on commit 03bdecf

Please sign in to comment.