* fix(ci): skip unrelated required checks cleanly Matrix jobs had to start no-op runners to preserve interpolated required-check names. Static named jobs let GitHub report genuine skipped conclusions while keeping those names stable. * fix(ci): gate changes to install patching script * fix(ci): route cross-package test contracts narrowly * fix(ci): keep routed contracts merge-blocking * fix(server): exclude nested test utilities from builds * fix(ci): cover app-owned native and browser domains * refactor(ci): align tests with runtime domains Own browser specs, desktop specs, and Electron-only app code by stable directories so PR routing does not depend on filename conventions. Keep desktop integration coverage inside the required desktop check. * fix(ci): keep routing and desktop suites isolated The routing regression must run before dependency installation, and desktop Vitest must not collect Playwright-owned specs. * fix(ci): isolate desktop e2e runtime * perf(test): isolate Playwright workers * perf(test): parallelize Playwright within specs * fix(test): keep Playwright file scheduling * fix(test): share dynamic Metro fixture * fix(test): preserve own-host restart fixtures * fix(ci): preserve routed contracts after rebase * Stabilize Playwright wheel-scroll assertions
149 lines
4.9 KiB
TypeScript
149 lines
4.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
applyBrowserPatch,
|
|
type BrowserIndexState,
|
|
createBrowserRecord,
|
|
normalizeBrowserUrl,
|
|
removeBrowserFromIndex,
|
|
sanitizeBrowsersForPersist,
|
|
} from "./state";
|
|
|
|
function withRecords(records: ReturnType<typeof createBrowserRecord>[]): BrowserIndexState {
|
|
return {
|
|
browsersById: Object.fromEntries(records.map((record) => [record.browserId, record])),
|
|
};
|
|
}
|
|
|
|
describe("normalizeBrowserUrl", () => {
|
|
it("normalizes local development hosts to http by default", () => {
|
|
expect(normalizeBrowserUrl("localhost:8081")).toBe("http://localhost:8081");
|
|
expect(normalizeBrowserUrl("localhost/path")).toBe("http://localhost/path");
|
|
expect(normalizeBrowserUrl("127.0.0.1:3000/path")).toBe("http://127.0.0.1:3000/path");
|
|
expect(normalizeBrowserUrl("192.168.0.8")).toBe("http://192.168.0.8");
|
|
expect(normalizeBrowserUrl("[::1]:5173")).toBe("http://[::1]:5173");
|
|
});
|
|
|
|
it("normalizes public hosts to https by default", () => {
|
|
expect(normalizeBrowserUrl("example.com")).toBe("https://example.com");
|
|
expect(normalizeBrowserUrl("//example.com/path")).toBe("https://example.com/path");
|
|
});
|
|
|
|
it("keeps explicit protocols unchanged", () => {
|
|
expect(normalizeBrowserUrl("http://localhost:8081")).toBe("http://localhost:8081");
|
|
expect(normalizeBrowserUrl("https://localhost:8081")).toBe("https://localhost:8081");
|
|
expect(normalizeBrowserUrl("file:///tmp/example.html")).toBe("file:///tmp/example.html");
|
|
});
|
|
|
|
it("falls back to a default URL when input is blank", () => {
|
|
expect(normalizeBrowserUrl(null)).toBe("https://example.com");
|
|
expect(normalizeBrowserUrl(" ")).toBe("https://example.com");
|
|
});
|
|
});
|
|
|
|
describe("createBrowserRecord", () => {
|
|
it("normalizes the initial URL and starts with idle state", () => {
|
|
const record = createBrowserRecord({
|
|
browserId: "b1",
|
|
initialUrl: "localhost:8081",
|
|
now: 1000,
|
|
});
|
|
|
|
expect(record).toEqual({
|
|
browserId: "b1",
|
|
url: "http://localhost:8081",
|
|
title: "",
|
|
isLoading: false,
|
|
canGoBack: false,
|
|
canGoForward: false,
|
|
faviconUrl: null,
|
|
lastError: null,
|
|
createdAt: 1000,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("applyBrowserPatch", () => {
|
|
it("normalizes URL updates", () => {
|
|
const initial = withRecords([
|
|
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
|
|
]);
|
|
|
|
const next = applyBrowserPatch(initial, "b1", { url: "example.com/path" });
|
|
|
|
expect(next.browsersById.b1?.url).toBe("https://example.com/path");
|
|
});
|
|
|
|
it("returns the same state reference when nothing changes", () => {
|
|
const initial = withRecords([
|
|
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
|
|
]);
|
|
|
|
const next = applyBrowserPatch(initial, "b1", { url: "https://a.test", title: "" });
|
|
|
|
expect(next).toBe(initial);
|
|
});
|
|
|
|
it("returns the same state when the browser id is unknown", () => {
|
|
const initial = withRecords([
|
|
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
|
|
]);
|
|
|
|
const next = applyBrowserPatch(initial, "missing", { title: "x" });
|
|
|
|
expect(next).toBe(initial);
|
|
});
|
|
|
|
it("returns the same state when the browser id is blank", () => {
|
|
const initial = withRecords([
|
|
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
|
|
]);
|
|
|
|
expect(applyBrowserPatch(initial, " ", { title: "x" })).toBe(initial);
|
|
});
|
|
});
|
|
|
|
describe("removeBrowserFromIndex", () => {
|
|
it("removes the named browser", () => {
|
|
const initial = withRecords([
|
|
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
|
|
createBrowserRecord({ browserId: "b2", initialUrl: "https://b.test", now: 0 }),
|
|
]);
|
|
|
|
const next = removeBrowserFromIndex(initial, "b1");
|
|
|
|
expect(Object.keys(next.browsersById)).toEqual(["b2"]);
|
|
});
|
|
|
|
it("returns the same state when the browser id is unknown", () => {
|
|
const initial = withRecords([
|
|
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
|
|
]);
|
|
|
|
expect(removeBrowserFromIndex(initial, "missing")).toBe(initial);
|
|
});
|
|
|
|
it("returns the same state when the browser id is blank", () => {
|
|
const initial = withRecords([
|
|
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
|
|
]);
|
|
|
|
expect(removeBrowserFromIndex(initial, " ")).toBe(initial);
|
|
});
|
|
});
|
|
|
|
describe("sanitizeBrowsersForPersist", () => {
|
|
it("clears transient fields on every record", () => {
|
|
const base = createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 });
|
|
const state: BrowserIndexState = {
|
|
browsersById: {
|
|
b1: { ...base, isLoading: true, lastError: "network down" },
|
|
},
|
|
};
|
|
|
|
const persisted = sanitizeBrowsersForPersist(state);
|
|
|
|
expect(persisted.browsersById.b1?.isLoading).toBe(false);
|
|
expect(persisted.browsersById.b1?.lastError).toBe(null);
|
|
});
|
|
});
|