Skip to content

Commit

Permalink
make devtools support non-browser environment
Browse files Browse the repository at this point in the history
  • Loading branch information
ysmood committed Nov 3, 2024
1 parent d73f631 commit fee1088
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 68 deletions.
18 changes: 5 additions & 13 deletions chrome-extension/src/communicator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getDevtools, DEVTOOLS, Devtools, encode } from "stalo/lib/devtools";
import { onDevtools, encode, Devtools } from "stalo/lib/devtools";
import { initName } from "@stalo/devtools-ui/lib/constants";
import { sendMessage, setNamespace, onMessage } from "webext-bridge/window";
import {
Expand All @@ -18,21 +18,13 @@ async function connectAll() {

const list: Record<string, Devtools<object>> = {};

function updateList() {
getDevtools<object>().forEach((d) => {
if (list[d.id]) return;
onDevtools<object>((d) => {
if (list[d.id]) return;

list[d.id] = d;
connect(d);
});
}

window.addEventListener(DEVTOOLS, () => {
updateList();
list[d.id] = d;
connect(d);
});

setInterval(updateList, 1000);

onMessage<Set>(eventSet, ({ data }) => {
list[data.id].state = JSON.parse(data.state);
});
Expand Down
8 changes: 4 additions & 4 deletions chrome-extension/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ export const eventInit = "@@stalo-init";
export const eventRecord = "@@stalo-record";
export const eventSet = "@@stalo-set";

type StoreRecord = {
type StoreRecord<T> = {
name: string;
state: string | undefined;
state: T;
description?: string;
createdAt: number;
};

export type Init = {
sessionID: string;
name: string;
record: StoreRecord;
record: StoreRecord<string>;
};

export type Set = {
Expand All @@ -24,5 +24,5 @@ export type Set = {

export type Record = {
id: string;
record: StoreRecord;
record: StoreRecord<string | undefined>;
};
10 changes: 6 additions & 4 deletions chrome-extension/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,22 @@ import {
} from "./constants";
import { unplug, Connection, Panel, plug } from "@stalo/devtools-ui";

connect();
render();
main();

function main() {
connect();

function render() {
const root = document.createElement("div");

document.body.appendChild(root);

ReactDOM.createRoot(root).render(<Panel chromeExtension />);
ReactDOM.createRoot(root).render(<Panel customConnect />);
}

function connect() {
const list: Record<string, Connection> = {};

// Just acknowledge connection don't need to do anything
onMessage(eventConnect, () => {});

chrome.runtime.onConnect.addListener((port) => {
Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"immer",
"immerable",
"okaidia",
"onwarn",
"recordx",
"Stackframe",
"stalo",
Expand Down
15 changes: 7 additions & 8 deletions devtools-ui/src/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@ import connect from "./store/connect";
import { useEffect } from "react";

export default function Panel({
chromeExtension,
width,
height,
customConnect,
}: {
chromeExtension?: boolean;
width?: number;
height?: number;
customConnect?: boolean;
}) {
useEffect(() => {
if (!chromeExtension) {
const stop = new AbortController();
connect(stop.signal);
return () => stop.abort();
}
}, [chromeExtension]);
if (customConnect) return;
const stop = new AbortController();
connect(stop.signal);
return () => stop.abort();
}, [customConnect]);

return (
<div className={style} style={{ width, height }}>
Expand Down
24 changes: 7 additions & 17 deletions devtools-ui/src/store/connect.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import { Devtools, getDevtools, encode } from "stalo/lib/devtools";
import { onDevtools, encode } from "stalo/lib/devtools";
import { plug, unplug } from ".";
import { Connection } from "./constants";
import { initName } from "../constants";

export default async function connect(stop: AbortSignal) {
const connected = new Set<Devtools<unknown>>();

while (!stop.aborted) {
getDevtools<unknown>().forEach((d) => {
if (connected.has(d)) return;

connected.add(d);

export default function connect(stop: AbortSignal) {
stop.addEventListener(
"abort",
onDevtools((d) => {
const conn: Connection = {
id: d.id,
name: d.name,
Expand Down Expand Up @@ -39,11 +34,6 @@ export default async function connect(stop: AbortSignal) {
close();
unplug(conn.id);
});
});

await new Promise((r) => {
const timer = setTimeout(r, 1000);
stop.addEventListener("abort", () => clearTimeout(timer));
});
}
})
);
}
19 changes: 19 additions & 0 deletions examples/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,22 @@ test("todo-app", async ({ page }) => {
await expect(todoToggle.first()).toBeDisabled();
await expect(input).toHaveCount(0);
});

test("devtools", async ({ page }) => {
await page.goto("/examples/Devtools.tsx");

const btn = page.locator("button", { hasText: "Increase by 10" });
const record02 = page.locator(".records .item:nth-child(2)");
const sessions = page.locator(".sessions select");
const editor = page.locator(".editor .view-lines");

await sessions.selectOption({ label: "Demo" });

await btn.click();

await record02.click();

await expect(record02).toContainText("Increase the count by 10");

await expect(editor).toHaveText("10");
});
2 changes: 2 additions & 0 deletions examples/playwright.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ async function serve() {
hmr: false,
};

viteConfig.logLevel = "error";

const vite = await createServer(viteConfig);

app.use(vite.middlewares);
Expand Down
65 changes: 54 additions & 11 deletions src/devtools.test.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import { it, expect, describe, afterEach } from "vitest";
import { it, expect, describe, afterEach, vi } from "vitest";
import create, { produce } from ".";
import { compose, Middleware } from "./utils";
import devtools, {
DEVTOOLS,
Devtools,
encode,
getDevtools,
immerWithPatch,
meta,
onDevtools,
StoreRecord,
} from "./devtools";
import { render } from "@testing-library/react";

describe("devtools", () => {
vi.useFakeTimers();

afterEach(() => {
getDevtools().forEach((d) => {
d.close();
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(globalThis as any)[DEVTOOLS] = undefined;
});

it("basic", async () => {
it("basic", async ({ onTestFinished }) => {
const init = 1;
const [use, set] = create(init);

Expand All @@ -27,13 +30,12 @@ describe("devtools", () => {
}, ctx);
};

expect(getDevtools()).toHaveLength(0);

const setStore = compose(set, addOne, devtools(init));

compose(set, addOne, devtools(init));

const d = Array.from(getDevtools<number>())[0];
const d = await getDevtools<number>();
onTestFinished(() => d.close());

expect(d.state).toBe(1);

Expand Down Expand Up @@ -83,7 +85,7 @@ describe("devtools", () => {
const setStore = compose(set, immerWithPatch(), devtools(init));

const records: StoreRecord<number>[] = [];
const d = Array.from(getDevtools<number>())[0];
const d = await getDevtools<number>();

d.subscribe((record) => {
records.push(record);
Expand Down Expand Up @@ -114,7 +116,7 @@ describe("devtools", () => {
const setStore = compose(set, immerWithPatch(), devtools(init));

const records: StoreRecord<number>[] = [];
const d = Array.from(getDevtools<number>())[0];
const d = await getDevtools<number>();

d.subscribe((record) => {
records.push(record);
Expand All @@ -141,4 +143,45 @@ describe("devtools", () => {
it("encode", async () => {
expect(encode({ a: 1 })).toEqual('{\n "a": 1\n}');
});

it("can't get devtools", async () => {
let count = 0;
const close = onDevtools(() => {
count++;
});

Array.from({ length: 11 }).forEach(() => {
vi.advanceTimersToNextTimer();
});

expect(count).toBe(0);

close();
});

it("has devtools", async () => {
let count = 0;
const close = onDevtools(() => {
count++;
});

expect(count).toBe(0);

devtools(1)(() => 0);

vi.advanceTimersToNextTimer();
vi.advanceTimersToNextTimer();

expect(count).toBe(1);

close();
});
});

function getDevtools<S>() {
return new Promise<Devtools<S>>((resolve) => {
onDevtools<S>((d) => {
resolve(d);
});
});
}
Loading

0 comments on commit fee1088

Please sign in to comment.