Skip to content

Commit

Permalink
Updates TS and other dependencies. NodeJS v16 is now the minimum (#5)
Browse files Browse the repository at this point in the history
* Upgrades all dependencies and fixes resulting bugs.

* Updates package version.

* Increases minimum node version to 16 and changes this to a major release version.
  • Loading branch information
traviswimer authored Aug 25, 2023
1 parent f557df3 commit 9fcfa8f
Show file tree
Hide file tree
Showing 12 changed files with 931 additions and 875 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:

strategy:
matrix:
node-version: [14.x, 16.x, 18.x]
node-version: [16.x, 18.x, 20.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- run: yarn install --frozen-lockfile
- run: yarn build
- run: yarn ci_test
Expand All @@ -26,7 +26,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
registry-url: https://registry.npmjs.org/
- run: yarn install --frozen-lockfile
- run: yarn build
Expand Down
5 changes: 5 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ export default {
functions: 100,
},
},
transform: { "\\.[jt]sx?$": ["ts-jest", { useESM: true }] },
moduleNameMapper: {
"(.+)\\.js": "$1",
},
extensionsToTreatAsEsm: [".ts"],
};
30 changes: 15 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-hydration-provider",
"version": "1.0.2",
"version": "2.0.0",
"license": "MIT",
"type": "module",
"description": "React tools for controlling what your app renders before and after app hydration.",
Expand All @@ -16,21 +16,21 @@
],
"dependencies": {},
"devDependencies": {
"@tsconfig/node14": "^1.0.3",
"@types/jest": "^28.1.4",
"@types/jsdom": "^16.2.14",
"@types/node": "^18.0.0",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"jest": "^28.1.2",
"jest-environment-jsdom": "^28.1.3",
"jsdom": "^20.0.0",
"@tsconfig/node14": "^14.1.0",
"@types/jest": "^29.5.4",
"@types/jsdom": "^21.1.2",
"@types/node": "^20.5.6",
"@types/react": "^18.2.21",
"@types/react-dom": "^18.2.7",
"jest": "^29.6.4",
"jest-environment-jsdom": "^29.6.4",
"jsdom": "^22.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"ts-jest": "^28.0.5",
"ts-node": "^10.8.2",
"tsup": "^6.1.3",
"typescript": "^4.7.4",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"tsup": "^7.2.0",
"typescript": "^5.2.2",
"wait-for-expect": "^3.0.2"
},
"peerDependencies": {
Expand All @@ -50,7 +50,7 @@
"/dist/"
],
"engines": {
"node": ">=14.0.0"
"node": ">=16.0.0"
},
"scripts": {
"build": "tsup",
Expand Down
12 changes: 7 additions & 5 deletions src/createComponents.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
* @jest-environment jsdom
*/

import { jest } from "@jest/globals";

// "react-dom/server" throws an error if `TextEncoder` isn't global.
// This is a workaround for running the tests in jsdom environment.
import { TextEncoder } from "util";
global.TextEncoder = TextEncoder;

import React from "react";
import * as ReactDOMServer from "react-dom/server";
import { renderToString } from "react-dom/server";

import createComponents from "./createComponents";

Expand All @@ -26,8 +28,8 @@ test(`Renders only <Server> when not hydrated`, async () => {
</>
);

expect(ReactDOMServer.renderToString(jsx_element)).toEqual(
ReactDOMServer.renderToString(TestServerComponent)
expect(renderToString(jsx_element)).toEqual(
renderToString(TestServerComponent)
);
});
test(`Renders only <Client> component when hydrated`, async () => {
Expand All @@ -41,7 +43,7 @@ test(`Renders only <Client> component when hydrated`, async () => {
</>
);

expect(ReactDOMServer.renderToString(jsx_element)).toEqual(
ReactDOMServer.renderToString(TestClientComponent)
expect(renderToString(jsx_element)).toEqual(
renderToString(TestClientComponent)
);
});
8 changes: 4 additions & 4 deletions src/createHydration.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from "react";
import createHydrationProvider from "./createHydrationProvider";
import createComponents from "./createComponents";
import type { HydrationComponents } from "./createComponents";
export { useComponentHydrated } from "./useComponentHydrated";
import createHydrationProvider from "./createHydrationProvider.js";
import createComponents from "./createComponents.js";
import type { HydrationComponents } from "./createComponents.js";
export { useComponentHydrated } from "./useComponentHydrated.js";

export default function createHydration() {
const HydrationContext: React.Context<boolean> = React.createContext(false);
Expand Down
2 changes: 1 addition & 1 deletion src/createHydrationProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { useComponentHydrated } from "./useComponentHydrated";
import { useComponentHydrated } from "./useComponentHydrated.js";

export default function createHydrationProvider(
HydrationContext: React.Context<boolean>
Expand Down
66 changes: 26 additions & 40 deletions src/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
* @jest-environment jsdom
*/

import { jest } from "@jest/globals";

// "react-dom/server" throws an error if `TextEncoder` isn't global.
// This is a workaround for running the tests in jsdom environment.
import { TextEncoder } from "util";
global.TextEncoder = TextEncoder;

import React from "react";
import * as ReactDOMServer from "react-dom/server";
import * as ReactDOMClient from "react-dom/client";
import waitForExpect from "wait-for-expect";
import { renderToString } from "react-dom/server";
import { hydrateRoot } from "react-dom/client";
const waitForExpect = require("wait-for-expect");

import { addElementToPage } from "../utils/test_utils";
import {
Expand Down Expand Up @@ -42,13 +44,11 @@ test(`Errors if there is a hydration mismatch`, async () => {
const mismatched_client = <div>This does not match the server</div>;

const parent_element = addElementToPage(mismatched_server);
ReactDOMClient.hydrateRoot(parent_element, mismatched_client);
hydrateRoot(parent_element, mismatched_client);

// Wait for hydration to complete (and fail)
await waitForExpect(() => {
expect(parent_element.innerHTML).toEqual(
ReactDOMServer.renderToString(mismatched_client)
);
expect(parent_element.innerHTML).toEqual(renderToString(mismatched_client));
});

expect(jest.mocked(console.error).mock.calls[0][0]).toEqual(
Expand Down Expand Up @@ -76,15 +76,13 @@ test(`Renders <Server>, followed by <Client> after hydration`, async () => {
</HydrationProvider>
);
const parent_element = addElementToPage(jsx_element);
ReactDOMClient.hydrateRoot(parent_element, jsx_element);
hydrateRoot(parent_element, jsx_element);

expect(parent_element.innerHTML).toEqual(
ReactDOMServer.renderToString(TestServerComponent)
);
expect(parent_element.innerHTML).toEqual(renderToString(TestServerComponent));

await waitForExpect(() => {
expect(parent_element.innerHTML).toEqual(
ReactDOMServer.renderToString(TestClientComponent)
renderToString(TestClientComponent)
);
});

Expand All @@ -99,14 +97,14 @@ test(`Renders <Client> after hydration when no <Server> is provided`, async () =
);

const parent_element = addElementToPage(jsx_element);
ReactDOMClient.hydrateRoot(parent_element, jsx_element);
hydrateRoot(parent_element, jsx_element);

// No server component
expect(parent_element.innerHTML).toEqual("");

await waitForExpect(() => {
expect(parent_element.innerHTML).toEqual(
ReactDOMServer.renderToString(TestClientComponent)
renderToString(TestClientComponent)
);
});

Expand All @@ -121,11 +119,9 @@ test(`Renders <Server> before hydration when no <Client> is provided`, async ()
);

const parent_element = addElementToPage(jsx_element);
ReactDOMClient.hydrateRoot(parent_element, jsx_element);
hydrateRoot(parent_element, jsx_element);

expect(parent_element.innerHTML).toEqual(
ReactDOMServer.renderToString(TestServerComponent)
);
expect(parent_element.innerHTML).toEqual(renderToString(TestServerComponent));

await waitForExpect(() => {
expect(parent_element.innerHTML).toEqual("");
Expand All @@ -138,7 +134,7 @@ test(`Renders empty before and after hydration if no <Client> or <Server> is pro
let jsx_element = <HydrationProvider></HydrationProvider>;

const parent_element = addElementToPage(jsx_element);
ReactDOMClient.hydrateRoot(parent_element, jsx_element);
hydrateRoot(parent_element, jsx_element);

expect(parent_element.innerHTML).toEqual("");

Expand All @@ -164,16 +160,14 @@ test(`Renders normal HTML/components when inside <HydrationProvider>`, async ()
);

const parent_element = addElementToPage(jsx_element);
ReactDOMClient.hydrateRoot(parent_element, jsx_element);
hydrateRoot(parent_element, jsx_element);

// Snapshot of server render
expect(parent_element.innerHTML).toMatchSnapshot();

await waitForExpect(() => {
expect(parent_element.innerHTML).toEqual(
expect.stringContaining(
ReactDOMServer.renderToString(TestClientComponent)
)
expect.stringContaining(renderToString(TestClientComponent))
);
});

Expand Down Expand Up @@ -202,15 +196,15 @@ test(`Renders array of ReactElements on both <Client> and <Server> (For cases su
</HydrationProvider>
);
const parent_element = addElementToPage(jsx_element);
ReactDOMClient.hydrateRoot(parent_element, jsx_element);
hydrateRoot(parent_element, jsx_element);

expect(parent_element.innerHTML).toEqual(
ReactDOMServer.renderToString(<>{TestServerArray}</>)
renderToString(<>{TestServerArray}</>)
);

await waitForExpect(() => {
expect(parent_element.innerHTML).toEqual(
ReactDOMServer.renderToString(<>{TestClientArray}</>)
renderToString(<>{TestClientArray}</>)
);
});

Expand All @@ -233,16 +227,12 @@ test(`useHydrated() correctly returns whether the app is hydrated`, async () =>
);

const parent_element = addElementToPage(jsx_element);
ReactDOMClient.hydrateRoot(parent_element, jsx_element);
hydrateRoot(parent_element, jsx_element);

expect(parent_element.innerHTML).toEqual(
ReactDOMServer.renderToString(unhydrated_element)
);
expect(parent_element.innerHTML).toEqual(renderToString(unhydrated_element));

await waitForExpect(() => {
expect(parent_element.innerHTML).toEqual(
ReactDOMServer.renderToString(hydrated_element)
);
expect(parent_element.innerHTML).toEqual(renderToString(hydrated_element));
});

expect(console.error).not.toHaveBeenCalled();
Expand All @@ -260,16 +250,12 @@ test(`useComponentHydrated() correctly returns whether the app is hydrated witho
let jsx_element = <TestComponent />;

const parent_element = addElementToPage(jsx_element);
ReactDOMClient.hydrateRoot(parent_element, jsx_element);
hydrateRoot(parent_element, jsx_element);

expect(parent_element.innerHTML).toEqual(
ReactDOMServer.renderToString(unhydrated_element)
);
expect(parent_element.innerHTML).toEqual(renderToString(unhydrated_element));

await waitForExpect(() => {
expect(parent_element.innerHTML).toEqual(
ReactDOMServer.renderToString(hydrated_element)
);
expect(parent_element.innerHTML).toEqual(renderToString(hydrated_element));
});

expect(console.error).not.toHaveBeenCalled();
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import createHydration, { useComponentHydrated } from "./createHydration";
import createHydration, { useComponentHydrated } from "./createHydration.js";

const { HydrationContext, HydrationProvider, useHydrated, Server, Client } =
createHydration();
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"extends": "@tsconfig/node14/tsconfig.json",
"compilerOptions": {
"outDir": "./dist/THIS_IS_UNUSED/USE_tsup.config.ts_INSTEAD",
"module": "NodeNext",
"esModuleInterop": true,
"declaration": true,
"sourceMap": true,
Expand Down
6 changes: 3 additions & 3 deletions utils/test_utils.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from "react";
import * as ReactDOMServer from "react-dom/server";
import { renderToString } from "react-dom/server";

// Adds a ReactElement to the DOM (jsdom)
export function addElementToPage(element: React.ReactElement) {
const html = ReactDOMServer.renderToString(element);
export function addElementToPage(element: React.ReactElement<any, string>) {
const html = renderToString(element);

const body_element: any = document.querySelector("body");
body_element.innerHTML = `<main>${html}</main>`;
Expand Down
Loading

0 comments on commit 9fcfa8f

Please sign in to comment.