mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-08-10 05:00:43 +02:00
117 lines
3.9 KiB
JavaScript
117 lines
3.9 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import {
|
|
DEFAULT_DECORATION_LAYOUT,
|
|
parseDecorationLayout,
|
|
} from "./window-decorations.ts";
|
|
|
|
/**
|
|
* The app draws its own titlebar on Linux, so it owns the window controls —
|
|
* and where they go is a desktop-wide user preference. This parser is the only
|
|
* thing standing between that preference and the buttons we render, and only
|
|
* GNOME can be exercised on the machine this was written on, so KDE's real
|
|
* layout strings are pinned here instead.
|
|
*/
|
|
|
|
test("GNOME's default puts every control on the right", () => {
|
|
assert.deepEqual(parseDecorationLayout(":minimize,maximize,close"), {
|
|
left: [],
|
|
right: ["minimize", "maximize", "close"],
|
|
});
|
|
});
|
|
|
|
test("a left-hand layout is honored", () => {
|
|
// GNOME users who prefer macOS ordering set exactly this.
|
|
assert.deepEqual(parseDecorationLayout("close,minimize,maximize:"), {
|
|
left: ["close", "minimize", "maximize"],
|
|
right: [],
|
|
});
|
|
});
|
|
|
|
test("controls can be split across both sides", () => {
|
|
assert.deepEqual(parseDecorationLayout("close:minimize,maximize"), {
|
|
left: ["close"],
|
|
right: ["minimize", "maximize"],
|
|
});
|
|
});
|
|
|
|
test("GTK's own default drops the appmenu it cannot draw", () => {
|
|
assert.deepEqual(parseDecorationLayout("appmenu:close"), {
|
|
left: [],
|
|
right: ["close"],
|
|
});
|
|
});
|
|
|
|
test("non-button tokens are ignored rather than rendered", () => {
|
|
// `icon`, `menu`, `appmenu` and `spacer` are all legal GTK tokens for things
|
|
// this titlebar does not draw.
|
|
assert.deepEqual(parseDecorationLayout("icon,menu:spacer,close"), {
|
|
left: [],
|
|
right: ["close"],
|
|
});
|
|
});
|
|
|
|
test("KDE's extra decoration buttons are ignored", () => {
|
|
// KWin offers buttons GTK has no concept of. kde-gtk-config maps what it can
|
|
// and may pass these through; rendering an unknown box would be worse than
|
|
// dropping it, which is what GTK itself does.
|
|
assert.deepEqual(
|
|
parseDecorationLayout(
|
|
"menu,applicationmenu:shade,keepabove,keepbelow,help,minimize,maximize,close",
|
|
),
|
|
{ left: [], right: ["minimize", "maximize", "close"] },
|
|
);
|
|
});
|
|
|
|
test("a duplicated control is rendered once", () => {
|
|
assert.deepEqual(parseDecorationLayout("close:close,minimize"), {
|
|
left: ["close"],
|
|
right: ["minimize"],
|
|
});
|
|
});
|
|
|
|
test("whitespace and capitalization are tolerated", () => {
|
|
assert.deepEqual(parseDecorationLayout(" : Minimize , CLOSE "), {
|
|
left: [],
|
|
right: ["minimize", "close"],
|
|
});
|
|
});
|
|
|
|
test("a string with no colon is entirely the left side, as GTK reads it", () => {
|
|
// `g_strsplit(layout, ":", 2)` leaves the right-hand token NULL, so GTK puts
|
|
// every button on the left. No mainstream desktop emits this, but matching
|
|
// GTK is the only defensible reading.
|
|
assert.deepEqual(parseDecorationLayout("minimize,close"), {
|
|
left: ["minimize", "close"],
|
|
right: [],
|
|
});
|
|
});
|
|
|
|
test("only the first colon splits the sides", () => {
|
|
// GTK's split has a limit of 2, so the second colon is not a separator: the
|
|
// right side becomes the single token "minimize:maximize", which matches no
|
|
// button name and is dropped — exactly as GTK drops it.
|
|
assert.deepEqual(parseDecorationLayout("close:minimize:maximize"), {
|
|
left: ["close"],
|
|
right: [],
|
|
});
|
|
});
|
|
|
|
test("missing, empty and unusable layouts fall back to the default", () => {
|
|
const fallback = { left: [], right: ["minimize", "maximize", "close"] };
|
|
for (const input of [null, undefined, "", " "]) {
|
|
assert.deepEqual(parseDecorationLayout(input), fallback, `input: ${input}`);
|
|
}
|
|
// A layout naming only buttons we cannot draw would otherwise leave the user
|
|
// with no way to close the window.
|
|
assert.deepEqual(parseDecorationLayout("appmenu:spacer"), fallback);
|
|
assert.deepEqual(parseDecorationLayout(":"), fallback);
|
|
});
|
|
|
|
test("the documented default parses to the default", () => {
|
|
assert.deepEqual(parseDecorationLayout(DEFAULT_DECORATION_LAYOUT), {
|
|
left: [],
|
|
right: ["minimize", "maximize", "close"],
|
|
});
|
|
});
|