From 58d10fc0d4f7fabd21d7400a8d0c247851424b39 Mon Sep 17 00:00:00 2001 From: Stephen Fraser Date: Tue, 19 May 2020 14:49:59 +0100 Subject: [PATCH 1/5] Updated useIsTouchDevice to work when rendering with SSR Server side rendering causes an error when rendering a component using this hook when it looks for `navigator`. Added checks for `navigator` and `window` to avoid the look up. --- src/hooks/useIsTouchDevice.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/hooks/useIsTouchDevice.ts b/src/hooks/useIsTouchDevice.ts index c75400b6..4b35aa6c 100644 --- a/src/hooks/useIsTouchDevice.ts +++ b/src/hooks/useIsTouchDevice.ts @@ -8,6 +8,12 @@ export const useIsTouchDevice = (): boolean => { const isTouchDevice = useRef(null); if (isTouchDevice.current === null) { + // Check for SSR where navigator and window may not be defined. + if (navigator === undefined || window === undefined) { + isTouchDevice.current = false; + return isTouchDevice.current; + } + isTouchDevice.current = ('ontouchstart' in window || !!navigator.maxTouchPoints); return isTouchDevice.current; } From a3a35764619545a4cd09adb1889c0f73301fcee6 Mon Sep 17 00:00:00 2001 From: Stephen Fraser Date: Tue, 19 May 2020 15:07:57 +0100 Subject: [PATCH 2/5] Updated to check if variable has been defined --- src/hooks/useIsTouchDevice.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hooks/useIsTouchDevice.ts b/src/hooks/useIsTouchDevice.ts index 4b35aa6c..0fa1f591 100644 --- a/src/hooks/useIsTouchDevice.ts +++ b/src/hooks/useIsTouchDevice.ts @@ -9,7 +9,8 @@ export const useIsTouchDevice = (): boolean => { if (isTouchDevice.current === null) { // Check for SSR where navigator and window may not be defined. - if (navigator === undefined || window === undefined) { + // tslint:disable-next-line:no-typeof-undefined + if (typeof navigator === 'undefined' || typeof window === 'undefined') { isTouchDevice.current = false; return isTouchDevice.current; } From 350a89c834bbfbdca07640332a9d22c8d85c3cd5 Mon Sep 17 00:00:00 2001 From: Stephen Fraser Date: Tue, 19 May 2020 15:08:16 +0100 Subject: [PATCH 3/5] Update isEdgeOrIE to work with React SSR --- src/utils.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils.ts b/src/utils.ts index a26243b5..f80a4859 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -87,6 +87,8 @@ function smoothScrollTo( * Determines if the current browser is IE or Edge (standard/chromium). */ export const isEdgeOrIE = (): boolean => IE_EDGE_BROWSER_REGEXP.test(navigator.userAgent); +// tslint:disable-next-line:no-typeof-undefined +export const isEdgeOrIE = (): boolean => typeof navigator !== 'undefined' && IE_EDGE_BROWSER_REGEXP.test(navigator.userAgent); /** * Tests object for type of array with a length of at least 1. From 7272cbb776e9aa6988f0a28a01b705b8fd52328e Mon Sep 17 00:00:00 2001 From: Stephen Fraser Date: Tue, 19 May 2020 15:09:18 +0100 Subject: [PATCH 4/5] Updated tests set up to allow for non js-dom envrionment tests When jest-environment is set to `node` window is not defined and the mutation observer polyfil cannot be added. --- .test/setupTests.ts | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/.test/setupTests.ts b/.test/setupTests.ts index bfcbc65d..28f071db 100644 --- a/.test/setupTests.ts +++ b/.test/setupTests.ts @@ -1,18 +1,21 @@ /* eslint-disable prettier/prettier */ import '@testing-library/jest-dom/extend-expect'; -import MutationObserver from 'mutation-observer'; -// Global MutationObserver Mocks -window.MutationObserver = MutationObserver; +// React SSR when environment is not js-dom +if (global.window !== undefined) { -// Global Test Environment Mocks -window.matchMedia = jest.fn((query: string): MediaQueryList => ({ - media: query, - onchange: null, - matches: false, - addListener: jest.fn(), - dispatchEvent: jest.fn(), - removeListener: jest.fn(), - addEventListener: jest.fn(), - removeEventListener: jest.fn() -})); \ No newline at end of file + // Global MutationObserver Mocks + window.MutationObserver = require('mutation-observer'); + + // Global Test Environment Mocks + window.matchMedia = jest.fn((query: string): MediaQueryList => ({ + media: query, + onchange: null, + matches: false, + addListener: jest.fn(), + dispatchEvent: jest.fn(), + removeListener: jest.fn(), + addEventListener: jest.fn(), + removeEventListener: jest.fn() + })); +} From c1b8db5af591bee87d1dacc867d495679112096c Mon Sep 17 00:00:00 2001 From: Stephen Fraser Date: Tue, 19 May 2020 15:09:32 +0100 Subject: [PATCH 5/5] Added test covering React SSR rendering --- __tests__/ReactSSR.test.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 __tests__/ReactSSR.test.tsx diff --git a/__tests__/ReactSSR.test.tsx b/__tests__/ReactSSR.test.tsx new file mode 100644 index 00000000..be551408 --- /dev/null +++ b/__tests__/ReactSSR.test.tsx @@ -0,0 +1,13 @@ +/** + * @jest-environment node + */ + +import React from 'react'; +import { renderToString } from 'react-dom/server'; +import { Select } from '../src'; + +test('select element can be rendered using react-dom/server', () => { + + expect(() => renderToString(