package main import ( "encoding/json" "os" "path/filepath" "reflect" "strings" "testing" ) // betterbird's shape (novox/hq issue 345, ADR 0208): no package (Betterbird comes from the AUR, and the // node-engine installs from the official repositories only), no seat, no start of its own (the operator // starts it from the launcher); the X display on its own machine; one directory and one file of its own, // the user.js the setting prefs fills; and the Go bundle serving exactly the listed betterbird_ tools. type manifest struct { Module string `json:"module"` Version string `json:"version"` Requires []string `json:"requires"` Settings map[string]any `json:"settings"` Tools []string `json:"tools"` Resources []map[string]any `json:"resources"` Build struct { Artifacts []map[string]any `json:"artifacts"` } `json:"build"` } func readManifest(t *testing.T) (manifest, string) { t.Helper() raw, err := os.ReadFile(filepath.Join("..", "..", "module.json")) if err != nil { t.Fatal(err) } dec := json.NewDecoder(strings.NewReader(string(raw))) dec.DisallowUnknownFields() var m manifest if err := dec.Decode(&m); err != nil { t.Fatalf("module.json: %v", err) } return m, string(raw) } func TestItOwnsTheUserJSAndNothingOfTheProfile(t *testing.T) { m, raw := readManifest(t) if m.Module != "betterbird" || !reflect.DeepEqual(m.Requires, []string{"x11-display"}) { t.Fatalf("%+v", m) } var ids []string for _, r := range m.Resources { ids = append(ids, r["id"].(string)) if r["type"] == "package" { t.Errorf("betterbird-bin is the AUR's: a package resource asks the node-engine for what it cannot install") } if p, _ := r["path"].(string); !strings.HasPrefix(p, "${machine:account-home}/.config/betterbird") { t.Errorf("a path outside the module's directory: %s", p) } } if strings.Join(ids, ",") != "configuration-dir,user-js" { t.Fatalf("%v", ids) } for _, never := range []string{".thunderbird", "prefs.js", "logins.json", "key4.db"} { if strings.Contains(raw, never) { t.Errorf("module.json names %q", never) } } file := m.Resources[1] content := file["content"].(string) if !strings.HasPrefix(content, mark) || !strings.Contains(content, "${setting:prefs}") || file["trusted"] != nil { t.Fatalf("the user.js begins with the mark, holds the setting, and stays trusted (only the terminal sets it): %v", file) } // The default is a comment, so a machine without the setting places a valid, empty user.js. def := m.Settings["prefs"].(map[string]any)["default"].(string) if err := validUserJS(strings.ReplaceAll(content, "${setting:prefs}", def)); err != nil { t.Fatal(err) } } func TestTheToolsAgreeWithTheManifest(t *testing.T) { m, raw := readManifest(t) served := map[string]bool{} for _, tool := range tools() { served[tool.Name] = true if !strings.HasPrefix(tool.Name, "betterbird_") || strings.TrimSpace(tool.Description) == "" { t.Errorf("%s: prefixed betterbird_ and described", tool.Name) } } for _, name := range m.Tools { if !served[name] { t.Errorf("module.json lists %s, which the bundle does not serve", name) } delete(served, name) } for name := range served { t.Errorf("the bundle serves %s, which module.json does not list", name) } if len(m.Build.Artifacts) != 1 { t.Fatalf("%v", m.Build.Artifacts) } b := m.Build.Artifacts[0] if b["kind"] != "bundle" || b["language"] != "go" || b["from"] != "cmd/betterbird-tools" || b["binary"] != "betterbird-tools" { t.Errorf("the Go tools bundle: %v", b) } s := strings.ToLower(raw) for _, never := range []string{"/home/", "jochen", "g14", "shanks", "novox.be", "http"} { if strings.Contains(s, never) { t.Errorf("module.json names %q", never) } } }