import { Schema } from "effect";import { describe, expect, it } from "vite-plus/test"; import { DiscoveredLocalServer, PreviewEvent, PreviewNavStatus, PreviewSessionSnapshot,} from "./preview.ts"; const decodePreviewEvent = Schema.decodeUnknownSync(PreviewEvent);const decodeSnapshot = Schema.decodeUnknownSync(PreviewSessionSnapshot);const decodeNavStatus = Schema.decodeUnknownSync(PreviewNavStatus);const decodeServer = Schema.decodeUnknownSync(DiscoveredLocalServer); describe("PreviewNavStatus", () => { it("decodes Idle", () => { expect(decodeNavStatus({ _tag: "Idle" })).toEqual({ _tag: "Idle" }); }); it("decodes Loading with title", () => { expect(decodeNavStatus({ _tag: "Loading", url: "http://localhost:5173/", title: "" })).toEqual({ _tag: "Loading", url: "http://localhost:5173/", title: "", }); }); it("decodes LoadFailed with code/description", () => { expect( decodeNavStatus({ _tag: "LoadFailed", url: "https://example.com/", title: "Example", code: -105, description: "ERR_NAME_NOT_RESOLVED", }), ).toEqual({ _tag: "LoadFailed", url: "https://example.com/", title: "Example", code: -105, description: "ERR_NAME_NOT_RESOLVED", }); }); it("rejects empty url", () => { expect(() => decodeNavStatus({ _tag: "Loading", url: "", title: "" })).toThrow(); });}); describe("PreviewSessionSnapshot", () => { it("round-trips a Success snapshot", () => { const snapshot = decodeSnapshot({ threadId: "thread-1", tabId: "preview-thread-1", navStatus: { _tag: "Success", url: "http://localhost:5173/", title: "Vite App", }, canGoBack: false, canGoForward: false, updatedAt: "2026-01-01T00:00:00.000Z", }); expect(snapshot.tabId).toBe("preview-thread-1"); expect(snapshot.navStatus._tag).toBe("Success"); });}); describe("PreviewEvent", () => { it("decodes opened", () => { const event = decodePreviewEvent({ type: "opened", threadId: "t", tabId: "preview-t", createdAt: "2026-01-01T00:00:00.000Z", snapshot: { threadId: "t", tabId: "preview-t", navStatus: { _tag: "Idle" }, canGoBack: false, canGoForward: false, updatedAt: "2026-01-01T00:00:00.000Z", }, }); expect(event.type).toBe("opened"); }); it("decodes failed with code/description", () => { const event = decodePreviewEvent({ type: "failed", threadId: "t", tabId: "preview-t", createdAt: "2026-01-01T00:00:00.000Z", url: "https://example.com/", title: "", code: -105, description: "ERR_NAME_NOT_RESOLVED", }); expect(event.type).toBe("failed"); if (event.type === "failed") { expect(event.code).toBe(-105); } }); it("decodes closed without snapshot", () => { const event = decodePreviewEvent({ type: "closed", threadId: "t", tabId: "preview-t", createdAt: "2026-01-01T00:00:00.000Z", }); expect(event.type).toBe("closed"); });}); describe("DiscoveredLocalServer", () => { it("decodes a server with process metadata", () => { const server = decodeServer({ host: "localhost", port: 5173, url: "http://localhost:5173", processName: "node", pid: 12345, terminal: null, }); expect(server.port).toBe(5173); expect(server.processName).toBe("node"); }); it("decodes a server without process metadata", () => { const server = decodeServer({ host: "localhost", port: 3000, url: "http://localhost:3000", processName: null, pid: null, terminal: null, }); expect(server.processName).toBeNull(); }); it("rejects invalid ports", () => { expect(() => decodeServer({ host: "localhost", port: 0, url: "http://localhost:0", processName: null, pid: null, terminal: null, }), ).toThrow(); expect(() => decodeServer({ host: "localhost", port: 70000, url: "http://localhost:70000", processName: null, pid: null, terminal: null, }), ).toThrow(); });});
import { Schema } from "effect";
import { describe, expect, it } from "vite-plus/test";
import {
DiscoveredLocalServer,
PreviewEvent,
PreviewNavStatus,
PreviewSessionSnapshot,
} from "./preview.ts";
const decodePreviewEvent = Schema.decodeUnknownSync(PreviewEvent);
const decodeSnapshot = Schema.decodeUnknownSync(PreviewSessionSnapshot);
const decodeNavStatus = Schema.decodeUnknownSync(PreviewNavStatus);
const decodeServer = Schema.decodeUnknownSync(DiscoveredLocalServer);
describe("PreviewNavStatus", () => {
it("decodes Idle", () => {
expect(decodeNavStatus({ _tag: "Idle" })).toEqual({ _tag: "Idle" });
});
it("decodes Loading with title", () => {
expect(decodeNavStatus({ _tag: "Loading", url: "http://localhost:5173/", title: "" })).toEqual({
_tag: "Loading",
url: "http://localhost:5173/",
title: "",
});
});
it("decodes LoadFailed with code/description", () => {
expect(
decodeNavStatus({
_tag: "LoadFailed",
url: "https://example.com/",
title: "Example",
code: -105,
description: "ERR_NAME_NOT_RESOLVED",
}),
).toEqual({
_tag: "LoadFailed",
url: "https://example.com/",
title: "Example",
code: -105,
description: "ERR_NAME_NOT_RESOLVED",
});
});
it("rejects empty url", () => {
expect(() => decodeNavStatus({ _tag: "Loading", url: "", title: "" })).toThrow();
});
});
describe("PreviewSessionSnapshot", () => {
it("round-trips a Success snapshot", () => {
const snapshot = decodeSnapshot({
threadId: "thread-1",
tabId: "preview-thread-1",
navStatus: {
_tag: "Success",
url: "http://localhost:5173/",
title: "Vite App",
},
canGoBack: false,
canGoForward: false,
updatedAt: "2026-01-01T00:00:00.000Z",
});
expect(snapshot.tabId).toBe("preview-thread-1");
expect(snapshot.navStatus._tag).toBe("Success");
});
});
describe("PreviewEvent", () => {
it("decodes opened", () => {
const event = decodePreviewEvent({
type: "opened",
threadId: "t",
tabId: "preview-t",
createdAt: "2026-01-01T00:00:00.000Z",
snapshot: {
threadId: "t",
tabId: "preview-t",
navStatus: { _tag: "Idle" },
canGoBack: false,
canGoForward: false,
updatedAt: "2026-01-01T00:00:00.000Z",
},
});
expect(event.type).toBe("opened");
});
it("decodes failed with code/description", () => {
const event = decodePreviewEvent({
type: "failed",
threadId: "t",
tabId: "preview-t",
createdAt: "2026-01-01T00:00:00.000Z",
url: "https://example.com/",
title: "",
code: -105,
description: "ERR_NAME_NOT_RESOLVED",
});
expect(event.type).toBe("failed");
if (event.type === "failed") {
expect(event.code).toBe(-105);
}
});
it("decodes closed without snapshot", () => {
const event = decodePreviewEvent({
type: "closed",
threadId: "t",
tabId: "preview-t",
createdAt: "2026-01-01T00:00:00.000Z",
});
expect(event.type).toBe("closed");
});
});
describe("DiscoveredLocalServer", () => {
it("decodes a server with process metadata", () => {
const server = decodeServer({
host: "localhost",
port: 5173,
url: "http://localhost:5173",
processName: "node",
pid: 12345,
terminal: null,
});
expect(server.port).toBe(5173);
expect(server.processName).toBe("node");
});
it("decodes a server without process metadata", () => {
const server = decodeServer({
host: "localhost",
port: 3000,
url: "http://localhost:3000",
processName: null,
pid: null,
terminal: null,
});
expect(server.processName).toBeNull();
});
it("rejects invalid ports", () => {
expect(() =>
decodeServer({
host: "localhost",
port: 0,
url: "http://localhost:0",
processName: null,
pid: null,
terminal: null,
}),
).toThrow();
expect(() =>
decodeServer({
host: "localhost",
port: 70000,
url: "http://localhost:70000",
processName: null,
pid: null,
terminal: null,
}),
).toThrow();
});
});