Files
magpie/internal/omarchy/omarchy_test.go
T
yetone 23c26c2dba site, omarchy: the site in Omarchy's style follows a theme set in Omarchy without a reload (owner: 现在系统换完主题后网页需要手动刷新一下才能切换到对应主题) — a browser that hasn't let usemagpie.ai reach this computer (Chromium's local network access, which nothing on the page asked for) left the page on Omarchy's default for light or dark, chosen from prefers-color-scheme once at load, and a page that had been let through could lose magpie for 30 s when one answer was slow. Now: while not let through, the page repaints as prefers-color-scheme turns (omarchy-theme-set turns GNOME's color-scheme, so Chromium's), and a "Follow my Omarchy theme" / 跟随 Omarchy 主题 button beside the chip asks the browser in one click; a permission turned to granted (the prompt, site settings) starts following at once, denied stops it; once magpie has answered, one failed or slow answer (5 s, was 3 s) keeps the page following and it asks again in 3 s (two in a row mark it absent, still asked every 3 s), and two permissions turning together poll once. The gateway's /v1/magpie/omarchy no longer asks omarchy-font-current and hyprctl again on every theme change, only when the font's or Hyprland's own files change, since a theme set reloads Hyprland and hyprctl asked meanwhile can stall (2 s timeouts each); TestCurrent checks a theme switch keeps the font without asking and fonts.conf changing asks again (fails on the old code). Tried in the Omarchy VM's Chromium with the new omarchy.js/css: not let through, the page went tokyo-night ↔ catppuccin-latte with the desktop; the button raised Chromium's "Access other apps and services on this device" prompt and the page went live on vantablack once granted, no reload; with access allowed, catppuccin-latte, tokyo-night, rose-pine and vantablack came through within 1.5–3 s each, no failed request. go vet, builds (darwin, GOOS=linux -tags nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. The prompt's Allow itself wasn't pressed (granted through the profile and CDP instead).
2026-10-04 04:17:42 +08:00

169 lines
5.3 KiB
Go

package omarchy
import (
"os"
"path/filepath"
"testing"
)
const tokyoColors = `mode = "dark"
accent = "#7aa2f7"
selection = "#292e42"
muted = "#414868"
background = "#1a1b26"
foreground = "#a9b1d6"
dark_foreground = "#565f89"
bright_foreground = "#c0caf5"
red = "#f7768e"
yellow = "#e0af68"
green = "#9ece6a"
`
const tokyoShell = `# comment
[hyprland]
active-border = "#7aa2f7"
active-border-foreground = "#a9b1d6"
[controls]
normal-fill-alpha = 0.04 # inline
hover-cursor-fill-alpha = 0.08
[font]
base-size = 12
[popups]
background = "#1a1b26"
text = "#a9b1d6"
border = "hyprland.active-border"
[menu]
selected-background = "#a9b1d6"
selected-background-alpha = 0.08
selected-text = "#7aa2f7"
`
func TestParse(t *testing.T) {
m := Parse([]byte(tokyoShell))
for k, want := range map[string]string{
"hyprland.active-border": "#7aa2f7",
"controls.normal-fill-alpha": "0.04",
"font.base-size": "12",
"popups.border": "hyprland.active-border",
} {
if m[k] != want {
t.Errorf("%s = %q, want %q", k, m[k], want)
}
}
}
func TestParseColor(t *testing.T) {
for in, want := range map[string]string{
"#7aa2f7": "#7aa2f7",
"#fff": "#ffffff",
"rgb(7aa2f7)": "#7aa2f7",
"rgba(7aa2f780)": "rgba(122, 162, 247, 0.502)",
"rgba(33ccffee) rgba(00ff99ee) 45deg": "rgba(51, 204, 255, 0.933)",
"rgba(10, 20, 30, 0.5)": "rgba(10, 20, 30, 0.500)",
} {
c, ok := parseColor(in)
if !ok || c.css() != want {
t.Errorf("parseColor(%q) = %q %v, want %q", in, c.css(), ok, want)
}
}
if _, ok := parseColor("hyprland.active-border"); ok {
t.Error("a token's name read as a colour")
}
}
func TestVars(t *testing.T) {
v, mode := Vars(Parse([]byte(tokyoColors)), Parse([]byte(tokyoShell)), "JetBrainsMono Nerd Font", 0, 2)
if mode != "dark" {
t.Errorf("mode %q", mode)
}
for k, want := range map[string]string{
"--bg": "#1a1b26",
"--fg": "#a9b1d6",
"--accent": "#7aa2f7",
"--muted": "#565f89",
"--red": "#f7768e",
"--om-edge": "#7aa2f7", // popups.border names the Hyprland border
"--om-radius": "0px",
"--om-border": "2px",
"--om-size": "12px",
"--logo-invert": "1",
"--om-sel": "rgba(169, 177, 214, 0.080)",
"--card": "#20212d", // the foreground at 4% over the background
} {
if v[k] != want {
t.Errorf("%s = %q, want %q", k, v[k], want)
}
}
if want := `"JetBrainsMono Nerd Font", "JetBrainsMono Nerd Font", "JetBrains Mono", ui-monospace, monospace`; v["--font"] != want {
t.Errorf("--font = %s", v["--font"])
}
// a light theme that doesn't say so is told by its background
v, mode = Vars(map[string]string{"background": "#f5f5f5", "foreground": "#222222"}, nil, "", 8, 1)
if mode != "light" || v["--logo-invert"] != "0" || v["--om-radius"] != "8px" {
t.Errorf("light: %s %s %s", mode, v["--logo-invert"], v["--om-radius"])
}
}
func TestCurrent(t *testing.T) {
dir := filepath.Join(t.TempDir(), "current", "theme")
os.MkdirAll(dir, 0o755)
os.WriteFile(filepath.Join(dir, "colors.toml"), []byte(tokyoColors), 0o644)
os.WriteFile(filepath.Join(dir, "shell.toml"), []byte(tokyoShell), 0o644)
os.WriteFile(filepath.Join(filepath.Dir(dir), "theme.name"), []byte("tokyo-night\n"), 0o644)
t.Setenv("MAGPIE_OMARCHY", "1")
t.Setenv("MAGPIE_OMARCHY_THEME", dir)
t.Setenv("MAGPIE_OMARCHY_FONT", "Iosevka")
t.Setenv("XDG_CONFIG_HOME", t.TempDir())
if !Detect() {
t.Fatal("not detected")
}
th, ok := Current()
if !ok || th.Name != "tokyo-night" || th.Vars["--bg"] != "#1a1b26" || th.Stamp == "" {
t.Fatalf("%v %+v", ok, th)
}
// a new theme is read within a second or so
os.WriteFile(filepath.Join(dir, "shell.toml"), []byte("[font]\nbase-size = 13\n"), 0o644)
os.WriteFile(filepath.Join(dir, "colors.toml"), []byte("mode = \"light\"\nbackground = \"#fafafa\"\nforeground = \"#111111\"\n"), 0o644)
mu.Lock()
asked = asked.Add(-2e9)
mu.Unlock()
th2, _ := Current()
if th2.Stamp == th.Stamp || th2.Mode != "light" || th2.Vars["--bg"] != "#fafafa" {
t.Fatalf("not read again: %+v", th2)
}
// a theme set asks neither omarchy-font-current nor hyprctl (Hyprland
// reloads meanwhile and hyprctl stalls): the font stays as it was asked
if th2.Vars["--font"] != th.Vars["--font"] || th.Vars["--font"] == "" {
t.Fatalf("font %q then %q", th.Vars["--font"], th2.Vars["--font"])
}
t.Setenv("MAGPIE_OMARCHY_FONT", "JetBrains Mono")
os.WriteFile(filepath.Join(dir, "colors.toml"), []byte(tokyoColors), 0o644)
mu.Lock()
asked = asked.Add(-2e9)
mu.Unlock()
if th3, _ := Current(); th3.Vars["--bg"] != "#1a1b26" || th3.Vars["--font"] != th.Vars["--font"] {
t.Fatalf("the theme set asked for the font again: %q", th3.Vars["--font"])
}
// omarchy-font-set (fontconfig's file) does
cfg := os.Getenv("XDG_CONFIG_HOME")
os.MkdirAll(filepath.Join(cfg, "fontconfig"), 0o755)
os.WriteFile(filepath.Join(cfg, "fontconfig", "fonts.conf"), []byte("<fontconfig/>"), 0o644)
mu.Lock()
asked = asked.Add(-2e9)
mu.Unlock()
if th4, _ := Current(); th4.Vars["--font"] == th.Vars["--font"] {
t.Fatalf("a new font not asked: %q", th4.Vars["--font"])
}
t.Setenv("MAGPIE_OMARCHY", "0")
if Detect() {
t.Error("MAGPIE_OMARCHY=0 detected")
}
}