140 lines
4.6 KiB
Go
140 lines
4.6 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
"testing"
|
|
|
|
ck "go.maximumdirect.net/configkit"
|
|
)
|
|
|
|
func TestGlossarySourcesComposeAndRetainExtensions(t *testing.T) {
|
|
dir := t.TempDir()
|
|
write := func(name, data string) {
|
|
t.Helper()
|
|
file := filepath.Join(dir, name)
|
|
if err := os.MkdirAll(filepath.Dir(file), 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(file, []byte(data), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
write("config.yml", `version: 3
|
|
config:
|
|
imports: []
|
|
glossary_collections:
|
|
party:
|
|
entries:
|
|
- id: hero
|
|
name: Revised
|
|
category: character
|
|
level: 5
|
|
`)
|
|
write("glossary.yml", `config:
|
|
imports:
|
|
- path: shared/extra.yml
|
|
required: true
|
|
party:
|
|
entries:
|
|
- id: hero
|
|
name: Original
|
|
category: character
|
|
aliases: [Old]
|
|
- id: other
|
|
name: Other
|
|
category: place
|
|
`)
|
|
write("shared/extra.yml", "lore:\n entries:\n - id: hero\n name: Ancient\n category: lore\n")
|
|
write("glossary/nested/spells.yaml", "spells:\n entries:\n - id: bolt\n name: Bolt\n category: spell\n aliases: [Spark]\n plural: Bolts\n extra: {rank: 2}\n")
|
|
result, err := Load(ck.Input{Source: ck.File(filepath.Join(dir, "config.yml"))}, "")
|
|
if err != nil {
|
|
t.Fatalf("%v: %+v", err, err.(*ck.LoadError).Diagnostics())
|
|
}
|
|
party := result.Config.GlossaryCollections["party"].Entries
|
|
if len(party) != 2 || party[0].Name != "Revised" || len(party[0].Aliases) != 0 || party[1].ID != "other" {
|
|
t.Fatalf("party=%+v", party)
|
|
}
|
|
if party[0].Extra["level"] == nil {
|
|
t.Fatalf("extension missing: %+v", party[0])
|
|
}
|
|
if got := result.Config.GlossaryCollections["lore"].Entries; len(got) != 1 || got[0].ID != "hero" {
|
|
t.Fatalf("lore=%+v", got)
|
|
}
|
|
discovered, err := Load(ck.Input{Source: ck.SearchConfig("audita", ck.SearchDirectory(dir))}, "")
|
|
if err != nil || len(discovered.Config.GlossaryCollections["party"].Entries) != 2 {
|
|
t.Fatalf("discovered glossary: %+v %v", discovered, err)
|
|
}
|
|
spells := result.Config.GlossaryCollections["spells"].Entries
|
|
if len(spells) != 1 || spells[0].Plural == nil || *spells[0].Plural != "Bolts" || spells[0].Extra["extra"] == nil {
|
|
t.Fatalf("spells=%+v", spells)
|
|
}
|
|
var paths []string
|
|
for _, source := range result.Sources() {
|
|
if source.Kind == ck.SourceKindFile {
|
|
paths = append(paths, source.Path)
|
|
}
|
|
}
|
|
for _, name := range []string{"glossary.yml", "shared/extra.yml", "glossary/nested/spells.yaml"} {
|
|
if !slices.Contains(paths, filepath.Join(dir, name)) {
|
|
t.Errorf("missing source %s: %v", name, paths)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGlossaryValidationAndPeerConflicts(t *testing.T) {
|
|
dir := t.TempDir()
|
|
main := filepath.Join(dir, "config.yml")
|
|
write := func(path, data string) {
|
|
t.Helper()
|
|
if err := os.WriteFile(path, []byte(data), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
for _, data := range []string{
|
|
"glossary_collections:\n empty: {entries: []}\n",
|
|
"glossary_collections:\n x:\n entries:\n - {id: 'id with spaces', name: N, category: C}\n",
|
|
} {
|
|
write(main, data)
|
|
if _, err := Load(ck.Input{Source: ck.File(main)}, ""); err != nil {
|
|
t.Fatalf("valid %q: %v", data, err)
|
|
}
|
|
}
|
|
for _, data := range []string{
|
|
"glossary_collections:\n x:\n entries:\n - {id: '', name: N, category: C}\n",
|
|
"glossary_collections:\n x:\n entries:\n - {id: x, name: '', category: C}\n",
|
|
"glossary_collections:\n x:\n entries:\n - {id: x, name: N, category: C, aliases: ['']}\n",
|
|
"glossary_collections:\n x:\n entries:\n - {id: x, name: N, category: C, plural: ''}\n",
|
|
} {
|
|
write(main, data)
|
|
if _, err := Load(ck.Input{Source: ck.File(main)}, ""); err == nil {
|
|
t.Fatalf("accepted %q", data)
|
|
}
|
|
}
|
|
write(main, "version: 3\n")
|
|
write(filepath.Join(dir, "glossary.yml"), "x:\n entries:\n - {id: same, name: One, category: C}\n")
|
|
if err := os.Mkdir(filepath.Join(dir, "glossary"), 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
write(filepath.Join(dir, "glossary", "other.yml"), "x:\n entries:\n - {id: same, name: Two, category: C}\n")
|
|
if _, err := Load(ck.Input{Source: ck.File(main)}, ""); err == nil {
|
|
t.Fatal("peer conflict accepted")
|
|
}
|
|
}
|
|
|
|
func TestGlossaryUnderlaySkipsAbsentMain(t *testing.T) {
|
|
dir := t.TempDir()
|
|
if err := os.WriteFile(filepath.Join(dir, "glossary.yml"), []byte("leak:\n entries:\n - {id: a, name: A, category: C}\n"), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Chdir(dir)
|
|
result, err := Load(ck.Input{Source: ck.NoSource()}, "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(result.Config.GlossaryCollections) != 0 {
|
|
t.Fatalf("unanchored glossary loaded: %+v", result.Config.GlossaryCollections)
|
|
}
|
|
}
|