From c0e487eb0918ea86df4612347910f8da6a5cd38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Fri, 26 Apr 2024 09:19:35 +0200 Subject: [PATCH 1/7] ci: test with react 19 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef952a9..34b4f68 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,8 +37,8 @@ jobs: name: Tests strategy: matrix: - node-version: [14.x, 16.x, 17.x] - react-version: [17.x, 18.x] + node-version: [16.x, 18.x, 20.x] + react-version: [17.x, 18.x, beta] include: - node-version: 14.x react-version: 16.0.0 From a3f05007a46b2be1e987901da544ff60bb68304f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 12 Jun 2024 08:19:00 +0200 Subject: [PATCH 2/7] fail-fast:false --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34b4f68..ba0b859 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,7 @@ jobs: test: name: Tests strategy: + fail-fast: false matrix: node-version: [16.x, 18.x, 20.x] react-version: [17.x, 18.x, beta] From 51437bb0c50856cf787aa5e484dfb0bda8e70643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 12 Jun 2024 08:32:47 +0200 Subject: [PATCH 3/7] harness update for react 18/19 --- .babelrc.js | 3 +++ .eslintrc.js | 4 ++++ package.json | 1 + test/test.js | 26 +++++++++++++------------- test/util/render.js | 41 +++++++++++++++++++++++++++-------------- 5 files changed, 48 insertions(+), 27 deletions(-) diff --git a/.babelrc.js b/.babelrc.js index 0075d94..a29ad66 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -10,4 +10,7 @@ module.exports = { }], '@babel/react', ], + plugins: TEST ? [ + 'dynamic-import-node', + ] : [], }; diff --git a/.eslintrc.js b/.eslintrc.js index eb15afb..2a91a70 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,5 +1,9 @@ module.exports = { extends: 'airbnb', + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, rules: { // I disagree 'react/jsx-filename-extension': 'off', diff --git a/package.json b/package.json index b5ba8a6..0d93289 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@babel/register": "^7.12.10", "@rollup/plugin-babel": "^6.0.0", "@u-wave/react-vimeo-example": "file:example", + "babel-plugin-dynamic-import-node": "^2.3.3", "cross-env": "^7.0.3", "eslint": "^8.2.0", "eslint-config-airbnb": "^19.0.0", diff --git a/test/test.js b/test/test.js index 7acde90..018f91d 100644 --- a/test/test.js +++ b/test/test.js @@ -4,7 +4,7 @@ import render from './util/render'; describe('Vimeo', () => { it('should create a Vimeo player when mounted', async () => { const onReady = createSpy(); - const { sdkMock, playerMock } = render({ + const { sdkMock, playerMock } = await render({ video: 169408731, onReady, }); @@ -16,14 +16,14 @@ describe('Vimeo', () => { }); it('should use `url` prop for full vimeo URLs', async () => { - const { sdkMock } = render({ video: 'https://vimeo.com/179290396' }); + const { sdkMock } = await render({ video: 'https://vimeo.com/179290396' }); expect(sdkMock).toHaveBeenCalled(); expect(sdkMock.calls[0].arguments[1]).toMatch({ url: 'https://vimeo.com/179290396' }); }); it('should all onError when `ready()` fails', async () => { const onError = createSpy(); - const { sdkMock } = render({ + const { sdkMock } = await render({ video: 404, shouldFail: true, onError, @@ -36,7 +36,7 @@ describe('Vimeo', () => { }); it('should load a different video when "video" prop changes', async () => { - const { sdkMock, playerMock, rerender } = render({ + const { sdkMock, playerMock, rerender } = await render({ video: 169408731, }); expect(sdkMock).toHaveBeenCalled(); @@ -49,7 +49,7 @@ describe('Vimeo', () => { }); it('should pause the video using the "paused" prop', async () => { - const { playerMock, rerender } = render({ + const { playerMock, rerender } = await render({ video: 169408731, autoplay: true, }); @@ -66,7 +66,7 @@ describe('Vimeo', () => { }); it('should set the volume using the "volume" prop', async () => { - const { playerMock, rerender } = render({ + const { playerMock, rerender } = await render({ video: 169408731, volume: 0.5, }); @@ -78,7 +78,7 @@ describe('Vimeo', () => { }); it('should set the start time using the "start" prop', async () => { - const { playerMock, rerender } = render({ + const { playerMock, rerender } = await render({ video: 169408731, start: 60, }); @@ -93,7 +93,7 @@ describe('Vimeo', () => { }); it('should set the player color using the "color" prop', async () => { - const { playerMock, sdkMock, rerender } = render({ + const { playerMock, sdkMock, rerender } = await render({ video: 169408731, color: '#0000ff', }); @@ -107,7 +107,7 @@ describe('Vimeo', () => { }); it('should set the looping flag using the "loop" prop', async () => { - const { playerMock, sdkMock, rerender } = render({ + const { playerMock, sdkMock, rerender } = await render({ video: 169408731, loop: false, }); @@ -121,7 +121,7 @@ describe('Vimeo', () => { }); it('should set the iframe width/height using the width/height props', async () => { - const { sdkMock, playerMock, rerender } = render({ + const { sdkMock, playerMock, rerender } = await render({ video: 169408731, width: 640, height: 320, @@ -141,7 +141,7 @@ describe('Vimeo', () => { }); it('should set the playback rate using the "playbackRate" props', async () => { - const { playerMock, rerender } = render({ + const { playerMock, rerender } = await render({ video: 169408731, playbackRate: 0.5, }); @@ -154,13 +154,13 @@ describe('Vimeo', () => { }); it('should destroy player when unmounting', async () => { - const { playerMock, unmount } = render({ + const { playerMock, unmount } = await render({ video: 169408731, width: 640, height: 320, }); - await unmount(); + unmount(); expect(playerMock.destroy).toHaveBeenCalled(); }); diff --git a/test/util/render.js b/test/util/render.js index f45161d..17b5aaf 100644 --- a/test/util/render.js +++ b/test/util/render.js @@ -5,12 +5,15 @@ import React from 'react'; import ReactDOM from 'react-dom'; +import { act } from 'react-dom/test-utils'; import env from 'min-react-env'; import createVimeo from './createVimeo'; Object.assign(global, env); -const render = (initialProps) => { +const reactMajor = parseInt(ReactDOM.version.split('.')[0], 10); + +async function render(initialProps) { const { Vimeo, sdkMock, playerMock } = createVimeo({ shouldFail: initialProps.shouldFail, }); @@ -37,24 +40,34 @@ const render = (initialProps) => { } const div = env.document.createElement('div'); - const container = new Promise((resolve) => { - // eslint-disable-next-line react/no-deprecated - ReactDOM.render(, div); + let root; + if (reactMajor >= 18) { + const { createRoot } = await import('react-dom/client'); + root = createRoot(div); + } else { + root = { + render(element) { + // eslint-disable-next-line react/no-deprecated + ReactDOM.render(element, div); + }, + unmount() { + // eslint-disable-next-line react/no-deprecated + ReactDOM.unmountComponentAtNode(div); + }, + }; + } + const container = await new Promise((resolve) => { + root.render(); }); function rerender(newProps) { - return container.then((wrapper) => ( - new Promise((resolve) => { - wrapper.setState({ props: newProps }, () => { - Promise.resolve().then(resolve); - }); - }) - )); + return act(async () => { + container.setState({ props: newProps }); + }); } function unmount() { - // eslint-disable-next-line react/no-deprecated - ReactDOM.unmountComponentAtNode(div); + root.unmount(); } return { @@ -64,6 +77,6 @@ const render = (initialProps) => { rerender, unmount, }; -}; +} export default render; From 7b14ff1269a0892f37c75c33b1420db6a5cf87e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 12 Jun 2024 08:34:35 +0200 Subject: [PATCH 4/7] pseudofill navigator --- test/util/render.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/util/render.js b/test/util/render.js index 17b5aaf..93c13e7 100644 --- a/test/util/render.js +++ b/test/util/render.js @@ -9,7 +9,9 @@ import { act } from 'react-dom/test-utils'; import env from 'min-react-env'; import createVimeo from './createVimeo'; -Object.assign(global, env); +Object.assign(global, env, { + navigator: {}, +}); const reactMajor = parseInt(ReactDOM.version.split('.')[0], 10); From a72ec9596b6f133224feeb87c4f52c64a92f8e5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 12 Jun 2024 08:38:18 +0200 Subject: [PATCH 5/7] ua --- test/util/render.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/util/render.js b/test/util/render.js index 93c13e7..a89c9c3 100644 --- a/test/util/render.js +++ b/test/util/render.js @@ -10,7 +10,7 @@ import env from 'min-react-env'; import createVimeo from './createVimeo'; Object.assign(global, env, { - navigator: {}, + navigator: { userAgent: 'min-react-env' }, }); const reactMajor = parseInt(ReactDOM.version.split('.')[0], 10); From c3a0a4aef842a5fda17506c0a255ced2aa673891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 12 Jun 2024 08:39:49 +0200 Subject: [PATCH 6/7] very old react 16 --- test/util/render.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/util/render.js b/test/util/render.js index a89c9c3..b2e3a57 100644 --- a/test/util/render.js +++ b/test/util/render.js @@ -13,7 +13,7 @@ Object.assign(global, env, { navigator: { userAgent: 'min-react-env' }, }); -const reactMajor = parseInt(ReactDOM.version.split('.')[0], 10); +const reactMajor = parseInt((ReactDOM.version || '16').split('.')[0], 10); async function render(initialProps) { const { Vimeo, sdkMock, playerMock } = createVimeo({ From 6bf1364aac0df14d77c91e3a0c291efae492f832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 12 Jun 2024 08:48:59 +0200 Subject: [PATCH 7/7] oldest react --- test/util/render.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/util/render.js b/test/util/render.js index b2e3a57..bef2c64 100644 --- a/test/util/render.js +++ b/test/util/render.js @@ -15,6 +15,10 @@ Object.assign(global, env, { const reactMajor = parseInt((ReactDOM.version || '16').split('.')[0], 10); +function noAct(fn) { + return fn(); +} + async function render(initialProps) { const { Vimeo, sdkMock, playerMock } = createVimeo({ shouldFail: initialProps.shouldFail, @@ -63,7 +67,7 @@ async function render(initialProps) { }); function rerender(newProps) { - return act(async () => { + return (act || noAct)(async () => { container.setState({ props: newProps }); }); }