From a087deb48e57b1f0a23a2d0a28d0c2d10a640cd6 Mon Sep 17 00:00:00 2001 From: xobotyi Date: Sun, 31 Jan 2021 10:33:48 +0300 Subject: [PATCH] fix: proper definition for isBrowser and isNavigator states. should fix: #1777 Also introduce jest config for ssr tests (it fails hard now). --- jest.config.base.ts | 13 +++++++++++++ jest.config.node.ts | 9 +++++++++ jest.config.ts | 9 +++++++++ package.json | 14 ++------------ src/misc/util.ts | 3 ++- src/useBattery.ts | 4 ++-- src/useIsomorphicLayoutEffect.ts | 3 ++- src/useMediaDevices.ts | 4 ++-- src/useNetworkState.ts | 4 ++-- src/useVibrate.ts | 4 ++-- tests/setupTests.ts | 14 ++++++++++---- tsconfig.json | 4 +++- 12 files changed, 58 insertions(+), 27 deletions(-) create mode 100644 jest.config.base.ts create mode 100644 jest.config.node.ts create mode 100644 jest.config.ts diff --git a/jest.config.base.ts b/jest.config.base.ts new file mode 100644 index 00000000..cd95d9ef --- /dev/null +++ b/jest.config.base.ts @@ -0,0 +1,13 @@ +import type { Config } from '@jest/types'; + +export const baseJestConfig: Config.InitialOptions = { + 'preset': 'ts-jest', + 'clearMocks': true, + 'coverageDirectory': 'coverage', + 'testMatch': [ + '/tests/**/*.test.(ts|tsx)' + ], + 'setupFiles': [ + '/tests/setupTests.ts' + ] +} diff --git a/jest.config.node.ts b/jest.config.node.ts new file mode 100644 index 00000000..c0f51543 --- /dev/null +++ b/jest.config.node.ts @@ -0,0 +1,9 @@ +import type { Config } from '@jest/types'; +import { baseJestConfig } from './jest.config.base'; + +const config: Config.InitialOptions = { + ...baseJestConfig, + testEnvironment: 'node', // browser-like +} + +export default config; diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 00000000..10a1f21e --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,9 @@ +import type { Config } from '@jest/types'; +import { baseJestConfig } from './jest.config.base'; + +const config: Config.InitialOptions = { + ...baseJestConfig, + testEnvironment: 'jsdom', // browser-like +} + +export default config; diff --git a/package.json b/package.json index 76c26460..8f29244b 100644 --- a/package.json +++ b/package.json @@ -14,11 +14,12 @@ "scripts": { "start": "yarn storybook", "test": "jest --maxWorkers 2", + "test:ssr": "jest --maxWorkers 2 --config ./jest.config.node.ts", "test:watch": "jest --watch", "test:coverage": "jest --coverage", "lint": "eslint {src,tests}/**/*.{ts,tsx}", "lint:fix": "yarn lint --fix", - "lint:types": "tsc --noEmit", + "lint:types": "tsc --noEmit ", "lint:prettier": "prettier --write src/**/**/*.{ts,tsx}", "build:cjs": "tsc", "build:es": "tsc -m esNext --outDir esm", @@ -162,16 +163,5 @@ "collective": { "type": "opencollective", "url": "https://opencollective.com/react-use" - }, - "jest": { - "preset": "ts-jest", - "clearMocks": true, - "coverageDirectory": "coverage", - "testMatch": [ - "/tests/**/*.test.(ts|tsx)" - ], - "setupFiles": [ - "/tests/setupTests.ts" - ] } } diff --git a/src/misc/util.ts b/src/misc/util.ts index a8d54552..f47f4331 100644 --- a/src/misc/util.ts +++ b/src/misc/util.ts @@ -18,4 +18,5 @@ export function off( } } -export const isBrowser = typeof window === 'object'; +export const isBrowser = typeof window !== 'undefined'; +export const isNavigator = typeof navigator !== 'undefined'; diff --git a/src/useBattery.ts b/src/useBattery.ts index e100f886..80d118ac 100644 --- a/src/useBattery.ts +++ b/src/useBattery.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { off, on } from './misc/util'; +import { isNavigator, off, on } from './misc/util'; import isDeepEqual from './misc/isDeepEqual'; export interface BatteryState { @@ -25,7 +25,7 @@ type UseBatteryState = | { isSupported: true; fetched: false } // battery API supported but not fetched yet | (BatteryState & { isSupported: true; fetched: true }); // battery API supported and fetched -const nav: NavigatorWithPossibleBattery | undefined = typeof navigator === 'object' ? navigator : undefined; +const nav: NavigatorWithPossibleBattery | undefined = isNavigator ? navigator : undefined; const isBatteryApiSupported = nav && typeof nav.getBattery === 'function'; function useBatteryMock(): UseBatteryState { diff --git a/src/useIsomorphicLayoutEffect.ts b/src/useIsomorphicLayoutEffect.ts index b285db78..71f7c342 100644 --- a/src/useIsomorphicLayoutEffect.ts +++ b/src/useIsomorphicLayoutEffect.ts @@ -1,5 +1,6 @@ import { useEffect, useLayoutEffect } from 'react'; +import { isBrowser } from './misc/util'; -const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect; +const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect; export default useIsomorphicLayoutEffect; diff --git a/src/useMediaDevices.ts b/src/useMediaDevices.ts index 5b3b2f5f..3929d22e 100644 --- a/src/useMediaDevices.ts +++ b/src/useMediaDevices.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { noop, off, on } from './misc/util'; +import { isNavigator, noop, off, on } from './misc/util'; const useMediaDevices = () => { const [state, setState] = useState({}); @@ -34,4 +34,4 @@ const useMediaDevices = () => { const useMediaDevicesMock = () => ({}); -export default typeof navigator === 'object' && !!navigator.mediaDevices ? useMediaDevices : useMediaDevicesMock; +export default isNavigator && !!navigator.mediaDevices ? useMediaDevices : useMediaDevicesMock; diff --git a/src/useNetworkState.ts b/src/useNetworkState.ts index dc17a4ff..f8d816a6 100644 --- a/src/useNetworkState.ts +++ b/src/useNetworkState.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { off, on } from './misc/util'; +import { isNavigator, off, on } from './misc/util'; import { IHookStateInitAction } from './misc/hookState'; export interface INetworkInformation extends EventTarget { @@ -69,7 +69,7 @@ export interface IUseNetworkState { const nav: | (Navigator & Partial>) - | undefined = navigator; + | undefined = isNavigator ? navigator : undefined; const conn: INetworkInformation | undefined = nav && (nav.connection || nav.mozConnection || nav.webkitConnection); function getConnectionState(previousState?: IUseNetworkState): IUseNetworkState { diff --git a/src/useVibrate.ts b/src/useVibrate.ts index 61d61287..b3542b3d 100644 --- a/src/useVibrate.ts +++ b/src/useVibrate.ts @@ -1,9 +1,9 @@ import { useEffect } from 'react'; -import { noop } from './misc/util'; +import { isNavigator, noop } from './misc/util'; export type VibrationPattern = number | number[]; -const isVibrationApiSupported = typeof navigator === 'object' && 'vibrate' in navigator; +const isVibrationApiSupported = isNavigator && 'vibrate' in navigator; function useVibrate(enabled: boolean = true, pattern: VibrationPattern = [1000, 1000], loop: boolean = true): void { useEffect(() => { diff --git a/tests/setupTests.ts b/tests/setupTests.ts index c0ced93c..365fc373 100644 --- a/tests/setupTests.ts +++ b/tests/setupTests.ts @@ -1,6 +1,12 @@ import 'jest-localstorage-mock'; +import { isBrowser } from '../src/misc/util'; -(window as any).ResizeObserver = class ResizeObserver { - observe() {} - disconnect() {} -}; +if (isBrowser) { + (window as any).ResizeObserver = class ResizeObserver { + observe() { + } + + disconnect() { + } + }; +} diff --git a/tsconfig.json b/tsconfig.json index 4067d045..4a070b46 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,6 +27,8 @@ "lib", "esm", "tests", - "stories" + "stories", + "jest.config.ts", + "jest.config.*.ts" ] }