Files
paseo/packages/app/src/desktop/browser/store/state.test.ts
T
Mohamed BoudraandGitHub 5a30affd7f Skip unrelated required checks without losing their names (#2542)
* 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
2026-08-02 00:56:05 +08:00

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);
});
});