// SPDX-License-Identifier: AGPL-3.0-or-later import { test } from "node:test"; import { strict as assert } from "node:assert"; import { View } from "../../ui/system/core/view.js"; test("View — constructor requires an id", () => { assert.throws(() => new View({}), /requires an id/); }); test("View — fields default sensibly", () => { const v = new View({ id: "wv-1" }); assert.equal(v.id, "wv-1"); assert.equal(v.name, "Loading…"); assert.equal(v.host, ""); assert.equal(v.path, ""); assert.equal(v.themeColor, "transparent"); assert.equal(v.webView, null); }); test("View.setFromTitleEvent — updates name and reports change", () => { const v = new View({ id: "wv-1", name: "Old" }); assert.equal(v.setFromTitleEvent({ title: "New" }), true); assert.equal(v.name, "New"); }); test("View.setFromTitleEvent — keeps existing name on empty input", () => { const v = new View({ id: "wv-1", name: "Kept" }); assert.equal(v.setFromTitleEvent({ title: "" }), false); assert.equal(v.setFromTitleEvent({ title: null }), false); assert.equal(v.setFromTitleEvent({}), false); assert.equal(v.name, "Kept"); }); test("View.setFromTitleEvent — no-op when title unchanged", () => { const v = new View({ id: "wv-1", name: "Same" }); assert.equal(v.setFromTitleEvent({ title: "Same" }), false); }); test("View.setFromUrlEvent — splits host and path", () => { const v = new View({ id: "wv-1" }); assert.equal(v.setFromUrlEvent({ url: "https://example.com/foo?bar=1#x" }), true); assert.equal(v.host, "example.com"); assert.equal(v.path, "/foo?bar=1#x"); }); test("View.setFromUrlEvent — bare domain has empty path (not '/')", () => { const v = new View({ id: "wv-1" }); v.setFromUrlEvent({ url: "https://example.com/" }); assert.equal(v.host, "example.com"); assert.equal(v.path, ""); }); test("View.setFromUrlEvent — invalid URL is stored verbatim", () => { const v = new View({ id: "wv-1" }); // about:blank parses as a URL but with no host — we treat it as a fallback. v.setFromUrlEvent({ url: "not a url at all" }); assert.equal(v.host, "not a url at all"); assert.equal(v.path, ""); }); test("View.setFromUrlEvent — beaver:// scheme has its host segment", () => { const v = new View({ id: "wv-1" }); v.setFromUrlEvent({ url: "beaver://system/desktop/index.html" }); assert.equal(v.host, "system"); assert.equal(v.path, "/desktop/index.html"); }); test("View.setFromUrlEvent — opaque URL (about:blank) falls back to raw url", () => { const v = new View({ id: "wv-1" }); v.setFromUrlEvent({ url: "about:blank" }); assert.equal(v.host, "about:blank"); assert.equal(v.path, ""); }); test("View.setFromUrlEvent — empty/missing url is ignored", () => { const v = new View({ id: "wv-1", host: "kept.example", path: "/p" }); assert.equal(v.setFromUrlEvent({ url: "" }), false); assert.equal(v.setFromUrlEvent({}), false); assert.equal(v.host, "kept.example"); assert.equal(v.path, "/p"); }); test("View.displayHost — joins host + path", () => { const v = new View({ id: "wv-1", host: "example.com", path: "/foo" }); assert.equal(v.displayHost(), "example.com/foo"); }); test("View.displayHost — host only when no path", () => { const v = new View({ id: "wv-1", host: "example.com" }); assert.equal(v.displayHost(), "example.com"); }); test("View.displayHost — empty when no host", () => { const v = new View({ id: "wv-1" }); assert.equal(v.displayHost(), ""); }); test("View.shortHost — strips scheme and trims to first dot label", () => { assert.equal(View.shortHost("example.com"), "example"); assert.equal(View.shortHost("news.bbc.co.uk"), "news"); assert.equal(View.shortHost("https://example.com"), "example"); assert.equal(View.shortHost("singleword"), "singleword"); assert.equal(View.shortHost(""), ""); });