Skip to content

Commit

Permalink
Setup react-transform E2E test infra
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewiggins committed Jul 6, 2023
1 parent 6802bfc commit 08d73c9
Show file tree
Hide file tree
Showing 6 changed files with 604 additions and 248 deletions.
11 changes: 11 additions & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ function createEsbuildPlugin() {
};
});

// Mock fs module to run babel in a browser environment
build.onResolve({ filter: /^fs$/ }, () => {
return { path: path.join(__dirname, "test/browser/mockFs.js") };
});

// Apply babel pass whenever we load a .js file
build.onLoad({ filter: /\.[mc]?[jt]sx?$/ }, async args => {
const contents = await fs.readFile(args.path, "utf-8");
Expand Down Expand Up @@ -255,6 +260,12 @@ module.exports = function (config) {
customLaunchers: localLaunchers,

files: [
{
// Provide some NodeJS globals to run babel in a browser environment
pattern: "test/browser/nodeGlobals.js",
watched: false,
type: "js",
},
{
pattern:
process.env.TESTS ||
Expand Down
6 changes: 6 additions & 0 deletions packages/react-transform/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,19 @@
},
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/standalone": "^7.22.6",
"@babel/plugin-syntax-jsx": "^7.21.4",
"@babel/plugin-transform-react-jsx": "^7.21.4",
"@types/babel__core": "^7.20.0",
"@types/babel__helper-module-imports": "^7.18.0",
"@types/babel__helper-plugin-utils": "^7.10.0",
"@types/babel__standalone": "^7.1.4",
"@types/react": "^18.0.18",
"@types/react-dom": "^18.0.6",
"@types/use-sync-external-store": "^0.0.3",
"assert": "^2.0.0",
"buffer": "^6.0.3",
"path": "^0.12.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.9.0"
Expand Down
87 changes: 87 additions & 0 deletions packages/react-transform/test/browser/e2e.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// @ts-expect-error - missing types
import syntaxJsx from "@babel/plugin-syntax-jsx";
// @ts-expect-error - missing types
import transformReactJsx from "@babel/plugin-transform-react-jsx";
import { transform } from "@babel/standalone";
import { signal } from "@preact/signals-core";
import { useSignals } from "@preact/signals-react/runtime";
import React, { createElement } from "react";
import {
Root,
createRoot,
act,
checkHangingAct,
getConsoleErrorSpy,
checkConsoleErrorLogs,
} from "../../../react/test/shared/utils";
import signalsTransform, { PluginOptions } from "../../src/index";

function transformCode(code: string, options?: PluginOptions) {
const signalsPluginConfig: any[] = [signalsTransform];
if (options) {
signalsPluginConfig.push(options);
}

const result = transform(code, {
plugins: [signalsPluginConfig, syntaxJsx, transformReactJsx],
});

return result?.code || "";
}

function createComponent(code: string, options?: PluginOptions) {
const transformedCode = transformCode(code, options)
// Remove the `import { useSignals } from "@preact/signals-react/runtime";`
// line since we compiling code on the fly and can't use import statements.
.trim()
.split("\n")
.slice(1)
.join("\n");

const factory = new Function(
"React",
"_useSignals",
`return ${transformedCode}`
);
return factory(React, useSignals);
}

describe("React Signals babel transfrom - browser E2E tests", () => {
let scratch: HTMLDivElement;
let root: Root;

async function render(element: Parameters<Root["render"]>[0]) {
await act(() => root.render(element));
}

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

afterEach(async () => {
await act(() => root.unmount());
scratch.remove();

checkConsoleErrorLogs();
checkHangingAct();
});

it("should rerender components when signals they use change", async () => {
const App = createComponent(`
function App({ name }) {
return <div>Hello {name.value}</div>;
}`);

const name = signal("John");
await render(<App name={name} />);
expect(scratch.innerHTML).to.equal("<div>Hello John</div>");

await act(() => {
name.value = "Jane";
});
expect(scratch.innerHTML).to.equal("<div>Hello Jane</div>");
});
});
Loading

0 comments on commit 08d73c9

Please sign in to comment.