From e3b31f9ccfa577f0325331ee9d83d80bae8ee56d Mon Sep 17 00:00:00 2001 From: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com> Date: Sat, 30 Aug 2025 19:14:19 +0700 Subject: [PATCH 1/2] feat: support react 19 --- .github/workflows/unit-tests.yml | 8 ++++++-- package.json | 4 ++-- pnpm-lock.yaml | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 27acb17b..1b491d80 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -30,11 +30,15 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - react-version: [16, 17] - testing-library-version: [12] include: + - react-version: 16 + testing-library-version: 12 + - react-version: 17 + testing-library-version: 12 - react-version: 18 testing-library-version: 16 + - react-version: 19 + testing-library-version: 16 steps: - name: Checkout uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 diff --git a/package.json b/package.json index 3c8af6e6..f27217ae 100644 --- a/package.json +++ b/package.json @@ -58,8 +58,8 @@ "prismjs": "1.30.0" }, "peerDependencies": { - "react": "^16.14.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0" + "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "devDependencies": { "@babel/core": "7.28.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 28764a1d..dce8a95b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,10 +30,10 @@ importers: specifier: 1.30.0 version: 1.30.0 react: - specifier: ^16.14.0 || ^17.0.0 || ^18.0.0 + specifier: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 version: 16.14.0 react-dom: - specifier: ^16.14.0 || ^17.0.0 || ^18.0.0 + specifier: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 version: 16.14.0(react@16.14.0) devDependencies: '@babel/core': From 672966ec094ec9fc8b3cda96514a519cb4bdd78b Mon Sep 17 00:00:00 2001 From: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com> Date: Thu, 12 Feb 2026 02:36:51 +0700 Subject: [PATCH 2/2] fix: add renderHook test util --- .github/workflows/unit-tests.yml | 2 +- src/quiz/use-quiz.test.ts | 2 +- src/test-utils/renderHook.ts | 48 ++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/test-utils/renderHook.ts diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 77ff9c4a..82920e42 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -38,7 +38,7 @@ jobs: - react-version: 18 testing-library-version: 16 - react-version: 19 - testing-library-version: 16 + testing-library-version: 16.3.2 steps: - name: Checkout uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 diff --git a/src/quiz/use-quiz.test.ts b/src/quiz/use-quiz.test.ts index f1b71d97..eb640be8 100644 --- a/src/quiz/use-quiz.test.ts +++ b/src/quiz/use-quiz.test.ts @@ -1,4 +1,4 @@ -import { renderHook, act } from "@testing-library/react-hooks"; +import { renderHook, act } from "../test-utils/renderHook"; import { useQuiz } from "./use-quiz"; diff --git a/src/test-utils/renderHook.ts b/src/test-utils/renderHook.ts new file mode 100644 index 00000000..4f1fdfac --- /dev/null +++ b/src/test-utils/renderHook.ts @@ -0,0 +1,48 @@ +/** + * Runtime `renderHook` helper that picks a compatible implementation based on + * the installed testing-library packages: + * + * - Prefer `@testing-library/react`'s `renderHook` (available in newer RTL). + * - Fallback to `@testing-library/react-hooks` for older setups. + * + * This keeps tests working across React versions (React 16/17/18 with RHTL, + * React 18/19 with RTL's `renderHook`). + */ + +import * as rtl from "@testing-library/react"; +import * as rhtl from "@testing-library/react-hooks"; + +type ActFn = (cb: () => void) => void; + +type RenderHookResult = { + result: { current: T }; +}; + +// Generic renderHook signature used by our tests: accepts a callback returning +// a value and returns an object with a `result.current` property. +let renderHook: (cb: () => T) => RenderHookResult; +let actImpl: ActFn | undefined; + +type RTLLike = { + renderHook?: (cb: () => T) => RenderHookResult; + act?: ActFn; +}; + +if (typeof (rtl as unknown as RTLLike).renderHook === "function") { + const r = rtl as unknown as Required; + renderHook = r.renderHook; + actImpl = r.act; +} else { + const h = rhtl as unknown as Required; + renderHook = h.renderHook; + actImpl = h.act; +} + +const act: ActFn = (cb: () => void) => { + if (actImpl) return actImpl(cb); + // Fallback synchronous runner for environments without `act`. + return cb(); +}; + +export { renderHook, act }; +export default renderHook;