Skip to content

Commit

Permalink
Add support for JSX in test suite
Browse files Browse the repository at this point in the history
  • Loading branch information
marvinhagemeister committed Sep 9, 2022
1 parent f0608e3 commit 6836f6b
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 62 deletions.
4 changes: 4 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,9 @@ module.exports = {
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{ varsIgnorePattern: "createElement" },
],
},
};
32 changes: 29 additions & 3 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ function createEsbuildPlugin() {
});

// Apply babel pass whenever we load a .js file
build.onLoad({ filter: /\.[mc]?js$/ }, async args => {
build.onLoad({ filter: /\.[mc]?[jt]sx?$/ }, async args => {
const contents = await fs.readFile(args.path, "utf-8");

// Using a cache is crucial as babel is 30x slower than esbuild
Expand All @@ -112,11 +112,29 @@ function createEsbuildPlugin() {
if (!pending.has(args.path)) {
pending.set(args.path, []);

const jsx = [
"@babel/preset-react",
{
runtime: "classic",
pragma: "createElement",
pragmaFrag: "Fragment",
},
];
const ts = [
"@babel/preset-typescript",
{
jsxPragma: "createElement",
jsxPragmaFrag: "Fragment",
},
];

const tmp = await babel.transformAsync(result, {
filename: args.path,
sourceMaps: "inline",
presets: downlevel
? [
ts,
jsx,
[
"@babel/preset-env",
{
Expand All @@ -128,7 +146,7 @@ function createEsbuildPlugin() {
},
],
]
: [],
: [ts, jsx],
plugins: [
coverage && [
"istanbul",
Expand All @@ -139,6 +157,12 @@ function createEsbuildPlugin() {
].filter(Boolean),
});
result = tmp.code || result;
if (!args.path.includes(".pnpm")) {
console.log(args.path);
}
if (/\/preact\//.test(args.path)) {
// console.log("done", result);
}
cache.set(args.path, { input: contents, result });

// Fire all pending listeners that are waiting on the same
Expand Down Expand Up @@ -173,6 +197,7 @@ module.exports = function (config) {
reporters: ["mocha"].concat(coverage ? "coverage" : []),

formatError(msg) {
console.log("MSAG", msg);
let stack = msg;
// Karma prints error twice if it's an infinite loop
if (/^\s*Uncaught/.test(msg)) {
Expand Down Expand Up @@ -228,7 +253,7 @@ module.exports = function (config) {

files: [
{
pattern: process.env.TESTS || "packages/*/test/**/*.test.ts",
pattern: process.env.TESTS || "packages/*/test/**/*.test.tsx",
watched: false,
type: "js",
},
Expand All @@ -254,6 +279,7 @@ module.exports = function (config) {
esbuild: {
// karma-esbuild options
singleBundle: false,
jsx: "preserve",

// esbuild options
target: downlevel ? "es5" : "es2015",
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@babel/core": "^7.18.10",
"@babel/preset-env": "^7.18.10",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
"@changesets/cli": "^2.24.2",
"@types/chai": "^4.3.3",
"@types/mocha": "^9.1.1",
Expand All @@ -50,7 +51,7 @@
"karma-chai-sinon": "^0.1.5",
"karma-chrome-launcher": "^3.1.1",
"karma-coverage": "^2.2.0",
"karma-esbuild": "^2.2.4",
"karma-esbuild": "^2.2.5",
"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"karma-sinon": "^1.0.5",
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { signal, useComputed } from "@preact/signals";
import { h, render } from "preact";
import { useMemo } from "preact/hooks";
import { createElement, render } from "preact";
import { setupRerender } from "preact/test-utils";

const sleep = (ms?: number) => new Promise(r => setTimeout(r, ms));
Expand All @@ -20,15 +19,15 @@ describe("@preact/signals", () => {

describe("Text bindings", () => {
it("should render text without signals", () => {
render(h("span", null, "test"), scratch);
render(<span>test</span>, scratch);
const span = scratch.firstChild;
const text = span?.firstChild;
expect(text).to.have.property("data", "test");
});

it("should render Signals as Text", () => {
const sig = signal("test");
render(h("span", null, sig), scratch);
render(<span>{sig}</span>, scratch);
const span = scratch.firstChild;
expect(span).to.have.property("firstChild").that.is.an.instanceOf(Text);
const text = span?.firstChild;
Expand All @@ -37,7 +36,7 @@ describe("@preact/signals", () => {

it("should update Signal-based Text (no parent component)", () => {
const sig = signal("test");
render(h("span", null, sig), scratch);
render(<span>{sig}</span>, scratch);

const text = scratch.firstChild!.firstChild!;
expect(text).to.have.property("data", "test");
Expand All @@ -55,9 +54,9 @@ describe("@preact/signals", () => {
const spy = sinon.spy();
function App({ x }: { x: typeof sig }) {
spy();
return h("span", null, x);
return <span>{x}</span>;
}
render(h(App, { x: sig }), scratch);
render(<App x={sig} />, scratch);
spy.resetHistory();

const text = scratch.firstChild!.firstChild!;
Expand All @@ -79,16 +78,16 @@ describe("@preact/signals", () => {
const spy = sinon.spy();
function App({ x }: { x: typeof sig }) {
spy();
return h("span", null, x);
return <span>{x}</span>;
}
render(h(App, { x: sig }), scratch);
render(<App x={sig} />, scratch);
spy.resetHistory();

const text = scratch.firstChild!.firstChild!;
expect(text).to.have.property("data", "test");

const sig2 = signal("different");
render(h(App, { x: sig2 }), scratch);
render(<App x={sig2} />, scratch);
expect(spy).to.have.been.called;
spy.resetHistory();

Expand Down Expand Up @@ -123,10 +122,10 @@ describe("@preact/signals", () => {

function App() {
const value = sig.value;
return h("p", null, value);
return <p>{value}</p>;
}

render(h(App, {}), scratch);
render(<App />, scratch);
expect(scratch.textContent).to.equal("foo");

sig.value = "bar";
Expand All @@ -146,10 +145,10 @@ describe("@preact/signals", () => {
});

const str = arr.value.join(", ");
return h("p", null, str);
return <p>{str}</p>;
}

const fn = () => render(h(App, {}), scratch);
const fn = () => render(<App />, scratch);
expect(fn).not.to.throw;
});

Expand All @@ -158,16 +157,16 @@ describe("@preact/signals", () => {

function Child() {
const value = sig.value;
return h("p", null, value);
return <p>{value}</p>;
}

const spy = sinon.spy();
function App() {
spy();
return h(Child, null);
return <Child />;
}

render(h(App, {}), scratch);
render(<App />, scratch);
expect(scratch.textContent).to.equal("foo");

sig.value = "bar";
Expand All @@ -180,7 +179,7 @@ describe("@preact/signals", () => {
it("should set the initial value of the checked property", () => {
const s = signal(true);
// @ts-ignore
render(h("input", { checked: s }), scratch);
render(<input checked={s} />, scratch);

expect(scratch.firstChild).to.have.property("checked", true);
expect(s.value).to.equal(true);
Expand All @@ -189,7 +188,7 @@ describe("@preact/signals", () => {
it("should update the checked property on change", () => {
const s = signal(true);
// @ts-ignore
render(h("input", { checked: s }), scratch);
render(<input checked={s} />, scratch);

expect(scratch.firstChild).to.have.property("checked", true);

Expand All @@ -204,9 +203,9 @@ describe("@preact/signals", () => {
function Wrap() {
spy();
// @ts-ignore
return h("input", { value: s });
return <input value={s} />;
}
render(h(Wrap, {}), scratch);
render(<Wrap />, scratch);
spy.resetHistory();

expect(scratch.firstChild).to.have.property("value", "initial");
Expand Down Expand Up @@ -234,9 +233,9 @@ describe("@preact/signals", () => {
function Wrap() {
spy();
// @ts-ignore
return h("div", { style });
return <div style={style} />;
}
render(h(Wrap, {}), scratch);
render(<Wrap />, scratch);
spy.resetHistory();

const div = scratch.firstChild as HTMLDivElement;
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
globalThis.IS_REACT_ACT_ENVIRONMENT = true;

import { signal, useComputed } from "@preact/signals-react";
import { createElement as h, useMemo } from "react";
import { createElement, useMemo } from "react";
import { createRoot, Root } from "react-dom/client";
import { act } from "react-dom/test-utils";

Expand All @@ -24,15 +24,15 @@ describe("@preact/signals-react", () => {

describe("Text bindings", () => {
it("should render text without signals", () => {
render(h("span", null, "test"));
render(<span>test</span>);
const span = scratch.firstChild;
const text = span?.firstChild;
expect(text).to.have.property("data", "test");
});

it("should render Signals as Text", () => {
const sig = signal("test");
render(h("span", null, sig));
render(<span>{sig}</span>);
const span = scratch.firstChild;
expect(span).to.have.property("firstChild").that.is.an.instanceOf(Text);
const text = span?.firstChild;
Expand All @@ -41,7 +41,7 @@ describe("@preact/signals-react", () => {

it("should update Signal-based Text (no parent component)", () => {
const sig = signal("test");
render(h("span", null, sig));
render(<span>{sig}</span>);

const text = scratch.firstChild!.firstChild!;
expect(text).to.have.property("data", "test");
Expand All @@ -59,9 +59,9 @@ describe("@preact/signals-react", () => {
it("should update Signal-based Text (in a parent component)", () => {
const sig = signal("test");
function App({ x }: { x: typeof sig }) {
return h("span", null, x);
return <span>{x}</span>;
}
render(h(App, { x: sig }));
render(<App x={sig} />);

const text = scratch.firstChild!.firstChild!;
expect(text).to.have.property("data", "test");
Expand All @@ -83,10 +83,10 @@ describe("@preact/signals-react", () => {

function App() {
const value = sig.value;
return h("p", null, value);
return <p>{value}</p>;
}

render(h(App, {}));
render(<App />);
expect(scratch.textContent).to.equal("foo");

act(() => {
Expand All @@ -107,10 +107,10 @@ describe("@preact/signals-react", () => {
});

const str = arr.value.join(", ");
return h("p", null, str);
return <p>{str}</p>;
}

const fn = () => render(h(App, {}));
const fn = () => render(<App />);
expect(fn).not.to.throw;
});

Expand All @@ -119,16 +119,16 @@ describe("@preact/signals-react", () => {

function Child() {
const value = sig.value;
return h("p", null, value);
return <p>{value}</p>;
}

const spy = sinon.spy();
function App() {
spy();
return h(Child, null);
return <Child />;
}

render(h(App, {}));
render(<App />);
expect(scratch.textContent).to.equal("foo");

act(() => {
Expand All @@ -142,15 +142,15 @@ describe("@preact/signals-react", () => {

function Inner() {
const value = sig.value;
return h("p", null, value);
return <p>{value}</p>;
}

function App() {
sig.value;
return useMemo(() => h(Inner, { foo: 1 }), []);
return useMemo(() => <Inner foo={1} />, []);
}

render(h(App, {}));
render(<App />);
expect(scratch.textContent).to.equal("foo");

act(() => {
Expand Down
Loading

0 comments on commit 6836f6b

Please sign in to comment.