Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add auto pkg & run react runtimes tests against auto & transform runtimes #443

Merged
merged 11 commits into from
Nov 21, 2023
Merged
5 changes: 5 additions & 0 deletions .changeset/curly-paws-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@preact/signals-react": patch
---

Setup internal infrastructure for upcoming major change
33 changes: 32 additions & 1 deletion karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ var localLaunchers = {
},
};

/* eslint-disable no-console */
const signalsTransformPath = require.resolve("./packages/react-transform");
console.log(`Transforming tests using ${signalsTransformPath}.`);
console.log(
`Manually re-compile & re-run tests to validate changes to react-transform`
);

const subPkgPath = pkgName => {
if (!minify) {
return path.join(__dirname, pkgName, "src", "index.ts");
Expand Down Expand Up @@ -62,6 +69,8 @@ function createEsbuildPlugin() {
"@preact/signals-core": subPkgPath("./packages/core"),
"@preact/signals": subPkgPath("./packages/preact"),
"@preact/signals-react": subPkgPath("./packages/react"),
"@preact/signals-react/auto": subPkgPath("./packages/react/auto"),
"@preact/signals-react/runtime": subPkgPath("./packages/react/runtime"),
"@preact/signals-react-transform": subPkgPath("./packages/react-transform"),
};

Expand Down Expand Up @@ -145,6 +154,20 @@ function createEsbuildPlugin() {
},
];

/** @type {any} */
let signalsTransform = false;
if (
args.path.includes("packages/react/test/shared") ||
args.path.includes("packages/react/runtime/test")
) {
signalsTransform = [
signalsTransformPath,
{
mode: "auto",
},
];
}

const downlevelPlugin = [
"@babel/preset-env",
{
Expand All @@ -168,6 +191,7 @@ function createEsbuildPlugin() {
sourceMaps: "inline",
presets: downlevel ? [ts, jsx, downlevelPlugin] : [ts, jsx],
plugins: [
signalsTransform,
coverage && coveragePlugin,
minify && renamePlugin,
].filter(Boolean),
Expand Down Expand Up @@ -198,7 +222,14 @@ function createEsbuildPlugin() {
};
}

const pkgList = ["core", "preact", "react", "react/runtime", "react-transform"];
const pkgList = [
"core",
"preact",
"react",
"react/auto",
"react/runtime",
"react-transform",
];

module.exports = function (config) {
config.set({
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@
"private": true,
"scripts": {
"prebuild": "rimraf packages/core/dist/ packages/preact/dist",
"build": "pnpm build:core && pnpm build:preact && pnpm build:react-runtime && pnpm build:react && pnpm build:react-transform",
"build": "pnpm build:core && pnpm build:preact && pnpm build:react-runtime && pnpm build:react-auto && pnpm build:react && pnpm build:react-transform",
"_build": "microbundle --raw --globals @preact/signals-core=preactSignalsCore,preact/hooks=preactHooks",
"build:core": "pnpm _build --cwd packages/core && pnpm postbuild:core",
"build:preact": "pnpm _build --cwd packages/preact && pnpm postbuild:preact",
"build:react": "pnpm _build --cwd packages/react && pnpm postbuild:react",
"build:react-auto": "pnpm _build --cwd packages/react/auto && pnpm postbuild:react-auto",
"build:react-runtime": "pnpm _build --cwd packages/react/runtime && pnpm postbuild:react-runtime",
"build:react-transform": "pnpm _build --no-compress --cwd packages/react-transform",
"postbuild:core": "cd packages/core/dist && mv -f index.d.ts signals-core.d.ts",
"postbuild:preact": "cd packages/preact/dist && mv -f preact/src/index.d.ts signals.d.ts && rm -dr preact",
"postbuild:react": "cd packages/react/dist && mv -f react/src/index.d.ts signals.d.ts && rm -dr react",
"postbuild:react-auto": "cd packages/react/auto/dist && mv -f react/auto/src/*.d.ts . && rm -dr react",
"postbuild:react-runtime": "cd packages/react/runtime/dist && mv -f react/runtime/src/*.d.ts . && rm -dr react",
"postbuild": "node ./scripts/node-13-exports.js",
"lint": "pnpm lint:eslint && pnpm lint:tsc",
Expand Down
25 changes: 25 additions & 0 deletions packages/react/auto/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "@preact/signals-react-auto",
"description": "Sub package for @preact/signals-react that patches React to automatically update when signals change",
"private": true,
"amdName": "reactSignalsAuto",
"main": "dist/auto.js",
"module": "dist/auto.module.js",
"unpkg": "dist/auto.min.js",
"types": "dist/index.d.ts",
"mangle": "../../../mangle.json",
"exports": {
".": {
"types": "./dist/index.d.ts",
"browser": "./dist/auto.module.js",
"import": "./dist/auto.mjs",
"require": "./dist/auto.js"
}
},
"dependencies": {},
"peerDependencies": {
"@preact/signals-core": "workspace:^1.3.0",
"@preact/signals-react": "workspace:*",
"react": "^16.14.0 || 17.x || 18.x"
}
}
2 changes: 2 additions & 0 deletions packages/react/auto/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { installAutoSignalTracking } from "@preact/signals-react/runtime";
installAutoSignalTracking();
42 changes: 42 additions & 0 deletions packages/react/auto/test/browser/mounts.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// @ts-ignore-next-line
globalThis.IS_REACT_ACT_ENVIRONMENT = true;

import { mountSignalsTests } from "../../../test/shared/mounting";
import {
act,
getConsoleErrorSpy,
checkConsoleErrorLogs,
createRoot,
type Root,
} from "../../../test/shared/utils.js";

import "@preact/signals-react/auto";

describe("@preact/signals-react/auto", () => {
describe("mounting", () => {
let scratch: HTMLDivElement;
let root: Root;

async function render(element: JSX.Element): Promise<string> {
await act(() => {
root.render(element);
});
return scratch.innerHTML;
}

beforeEach(async () => {
scratch = document.createElement("div");
document.body.appendChild(scratch);
getConsoleErrorSpy().resetHistory();

root = await createRoot(scratch);
});

afterEach(async () => {
scratch.remove();
checkConsoleErrorLogs();
});

mountSignalsTests(render);
});
});
12 changes: 12 additions & 0 deletions packages/react/auto/test/browser/updates.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// @ts-ignore-next-line
andrewiggins marked this conversation as resolved.
Show resolved Hide resolved
globalThis.IS_REACT_ACT_ENVIRONMENT = true;

import { updateSignalsTests } from "../../../test/shared/updates";
import "@preact/signals-react/auto";

describe("@preact/signals-react/auto", () => {
describe("updating", () => {
// calledOnce
updateSignalsTests();
});
});
24 changes: 24 additions & 0 deletions packages/react/auto/test/node/renderToStaticMarkup.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { signal, useSignalEffect } from "@preact/signals-react";
import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { mountSignalsTests } from "../../../test/shared/mounting";

describe("@preact/signals-react/auto", () => {
describe("renderToStaticMarkup", () => {
mountSignalsTests(el => Promise.resolve(renderToStaticMarkup(el)));

it("should not invoke useSignalEffect", async () => {
const spy = sinon.spy();
const sig = signal("foo");

function App() {
useSignalEffect(() => spy(sig.value));
return <p>{sig.value}</p>;
}

const html = await renderToStaticMarkup(<App />);
expect(html).to.equal("<p>foo</p>");
expect(spy.called).to.be.false;
});
});
});
2 changes: 1 addition & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"README.md"
],
"scripts": {
"prepublishOnly": "cd ../.. && pnpm build:react-runtime && pnpm build:react"
"prepublishOnly": "cd ../.. && pnpm build:react-runtime && pnpm build:react-auto && pnpm build:react"
},
"dependencies": {
"@preact/signals-core": "workspace:^1.4.0",
Expand Down
40 changes: 40 additions & 0 deletions packages/react/runtime/test/browser/mounts.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// @ts-ignore-next-line
globalThis.IS_REACT_ACT_ENVIRONMENT = true;

import { mountSignalsTests } from "../../../test/shared/mounting";
import {
act,
getConsoleErrorSpy,
checkConsoleErrorLogs,
createRoot,
type Root,
} from "../../../test/shared/utils.js";

describe("@preact/signals-react/runtime", () => {
describe("mounting", () => {
let scratch: HTMLDivElement;
let root: Root;

async function render(element: JSX.Element): Promise<string> {
await act(() => {
root.render(element);
});
return scratch.innerHTML;
}

beforeEach(async () => {
scratch = document.createElement("div");
document.body.appendChild(scratch);
getConsoleErrorSpy().resetHistory();

root = await createRoot(scratch);
});

afterEach(async () => {
scratch.remove();
checkConsoleErrorLogs();
});

mountSignalsTests(render);
});
});
10 changes: 10 additions & 0 deletions packages/react/runtime/test/browser/updates.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// @ts-ignore-next-line
globalThis.IS_REACT_ACT_ENVIRONMENT = true;

import { updateSignalsTests } from "../../../test/shared/updates";

describe("@preact/signals-react/runtime", () => {
describe("updating", () => {
updateSignalsTests(true);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
checkHangingAct,
getConsoleErrorSpy,
checkConsoleErrorLogs,
} from "../../test/shared/utils";
} from "../../../test/shared/utils";

describe("useSignals", () => {
let scratch: HTMLDivElement;
Expand Down
24 changes: 24 additions & 0 deletions packages/react/runtime/test/node/renderToStaticMarkup.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { signal, useSignalEffect } from "@preact/signals-react";
import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { mountSignalsTests } from "../../../test/shared/mounting";

describe("@preact/signals-react/runtime", () => {
describe("renderToStaticMarkup", () => {
mountSignalsTests(el => Promise.resolve(renderToStaticMarkup(el)));

it("should not invoke useSignalEffect", async () => {
const spy = sinon.spy();
const sig = signal("foo");

function App() {
useSignalEffect(() => spy(sig.value));
return <p>{sig.value}</p>;
}

const html = await renderToStaticMarkup(<App />);
expect(html).to.equal("<p>foo</p>");
expect(spy.called).to.be.false;
});
});
});
8 changes: 6 additions & 2 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ import {
untracked,
} from "@preact/signals-core";
import type { ReactElement } from "react";
import { useSignal, useComputed, useSignalEffect } from "../runtime";
import { installAutoSignalTracking } from "../runtime/src/auto";
Comment on lines -11 to -12
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This double import caused some duplicate code in the final bundle. Combining them is what caused this PR to reduce the overall bundle size shown in the size-bot comment.

import {
useSignal,
useComputed,
useSignalEffect,
installAutoSignalTracking,
} from "../runtime/src/index"; // TODO: This duplicates runtime code between main and sub runtime packages

export {
signal,
Expand Down
32 changes: 0 additions & 32 deletions packages/react/test/browser/mounts.test.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion packages/react/test/node/renderToStaticMarkup.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { renderToStaticMarkup } from "react-dom/server";
import { mountSignalsTests } from "../shared/mounting";

describe("renderToStaticMarkup", () => {
mountSignalsTests(renderToStaticMarkup);
mountSignalsTests(el => Promise.resolve(renderToStaticMarkup(el)));

it("should not invoke useSignalEffect", async () => {
const spy = sinon.spy();
Expand Down
23 changes: 3 additions & 20 deletions packages/react/test/shared/mounting.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,11 @@
// @ts-ignore-next-line
globalThis.IS_REACT_ACT_ENVIRONMENT = true;

import {
signal,
computed,
useComputed,
useSignal,
} from "@preact/signals-react";
import { signal, computed } from "@preact/signals-core";
import { useComputed, useSignal } from "@preact/signals-react/runtime";
import { expect } from "chai";
import { createElement, useReducer, StrictMode, useState } from "react";

import { getConsoleErrorSpy, checkConsoleErrorLogs } from "./utils";

export function mountSignalsTests(
render: (element: JSX.Element) => string | Promise<string>
render: (element: JSX.Element) => Promise<string>
) {
beforeEach(async () => {
getConsoleErrorSpy().resetHistory();
});

afterEach(async () => {
checkConsoleErrorLogs();
});

describe("mount text bindings", () => {
it("should render text without signals", async () => {
const html = await render(<span>test</span>);
Expand Down
Loading
Loading