mirror of
https://github.com/hanzoai/status.git
synced 2026-10-30 18:21:48 +00:00
Hanzo and Lux status pages run the same image digest. Three of the tab-icon links were brand-templated, but the paths a browser reaches for on its own were not: /favicon.ico, /apple-touch-icon.png, /logo-192x192.png and /logo-512x512.png were real files at the web root, and git records this commit moving them into brands/hanzo/ because that is what they always were. Every brand got Hanzo's bytes. Saving status.lux.network to an iOS home screen saved the Hanzo mark, md5-identical. Artwork now has one home, /brands/<brand>/, and one name to reach it by: ui.brand. Tab icon, home screen icon, PWA icons and the header logo all derive from that name, so a deployment cannot title itself one company and hand out another's mark. The bare root paths are served from the same place rather than being a second copy that drifts, and a brand missing an asset is a boot failure instead of a page quietly wearing nobody. manifest.json was a checked-in static file: it called itself "Status" on a page titled "Hanzo Status", described itself in upstream Gatus's words, and splashed #f7f9fb light grey in front of a UI that paints #020817. It is now rendered from the same config that renders the page, and the theme-color meta reads the colour the app actually paints instead of a rounder-looking #000000. The 180/192/512 sizes were rasterised from each brand's own canonical SVG with rsvg-convert, the same pipeline that produced the existing 16/32 — it reproduces every shipped icon byte for byte, and Hanzo's icons are unchanged from what production serves today. Config drops `logo` and the three-field `favicon` block for the single `brand` key. TestNoBrandWearsAnothersMark asserts the property that was silently false: distinct bytes per brand at every size. Co-authored-by: Hanzo Dev <[email protected]>
89 lines
2.3 KiB
Go
89 lines
2.3 KiB
Go
package static
|
|
|
|
import (
|
|
"io/fs"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestEmbed(t *testing.T) {
|
|
scenarios := []struct {
|
|
path string
|
|
shouldExist bool
|
|
expectedContainString string
|
|
}{
|
|
{
|
|
path: "index.html",
|
|
shouldExist: true,
|
|
expectedContainString: "</body>",
|
|
},
|
|
{
|
|
path: "brands/hanzo/favicon.ico",
|
|
shouldExist: true,
|
|
expectedContainString: "", // not checking because it's an image
|
|
},
|
|
{
|
|
// Artwork has one home. A file here would be a second copy, and a
|
|
// second copy served to whichever brand did not put it there.
|
|
path: "favicon.ico",
|
|
shouldExist: false,
|
|
},
|
|
{
|
|
path: "file-that-does-not-exist.html",
|
|
shouldExist: false,
|
|
},
|
|
}
|
|
staticFileSystem, err := fs.Sub(FileSystem, RootPath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, scenario := range scenarios {
|
|
t.Run(scenario.path, func(t *testing.T) {
|
|
content, err := fs.ReadFile(staticFileSystem, scenario.path)
|
|
if !scenario.shouldExist {
|
|
if err == nil {
|
|
t.Errorf("%s should not have existed", scenario.path)
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Errorf("opening %s should not have returned an error, got %s", scenario.path, err.Error())
|
|
}
|
|
if len(content) == 0 {
|
|
t.Errorf("%s should have existed in the static FileSystem, but was empty", scenario.path)
|
|
}
|
|
if len(scenario.expectedContainString) > 0 && !strings.Contains(string(content), scenario.expectedContainString) {
|
|
t.Errorf("%s should have contained %s, but did not", scenario.path, scenario.expectedContainString)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
// Verify Vite static assets directory exists
|
|
t.Run("assets", func(t *testing.T) {
|
|
entries, err := fs.ReadDir(staticFileSystem, "assets")
|
|
if err != nil {
|
|
t.Errorf("assets directory should exist, got error: %s", err.Error())
|
|
return
|
|
}
|
|
if len(entries) == 0 {
|
|
t.Error("assets directory should not be empty")
|
|
}
|
|
hasJS := false
|
|
hasCSS := false
|
|
for _, entry := range entries {
|
|
if strings.HasSuffix(entry.Name(), ".js") {
|
|
hasJS = true
|
|
}
|
|
if strings.HasSuffix(entry.Name(), ".css") {
|
|
hasCSS = true
|
|
}
|
|
}
|
|
if !hasJS {
|
|
t.Error("assets should contain at least one .js file")
|
|
}
|
|
if !hasCSS {
|
|
t.Error("assets should contain at least one .css file")
|
|
}
|
|
})
|
|
}
|