package bnp import ( "testing" abiv1 "git.dev.alexdunmow.com/block/core/abi/v1" ) // TestApplyManifestYAMLSupplementsWithoutWiping proves the WO-WZ-021 mixed-form // builder semantics: folding manifest.yaml onto a manifest that already carries // guest DESCRIBE output SUPPLEMENTS the declarative surfaces and OVERRIDES only // the keys it actually declares — an undeclared scalar key never wipes a // guest-populated field. func TestApplyManifestYAMLSupplementsWithoutWiping(t *testing.T) { dir := t.TempDir() writeFixture(t, dir, map[string]string{ "manifest.yaml": "" + "bundled_fonts: fonts.json\n" + "page_templates:\n" + " - {system: blog, key: listing, title: Listing}\n" + "email_wrappers: [newsletter]\n", "fonts.json": `{"fonts":["Inter"]}`, "templates/blog/listing.ninjatpl": `
{{ title }}
`, "templates/email/newsletter.ninjatpl": `{{ body|safe }}
`, }) // Simulate a guest DESCRIBE result: theme_presets set by the guest, plus a // guest-rendered page template the manifest.yaml does NOT list. m := &abiv1.PluginManifest{ AbiVersion: 1, Name: "fixture-mixed", Version: "0.1.0", ThemePresets: []byte(`{"guest":true}`), PageTemplates: []*abiv1.PageTemplateMeta{ {SystemKey: "blog", Key: "guestonly", Title: "Guest Only"}, }, } if err := applyManifestYAML(dir, m); err != nil { t.Fatalf("applyManifestYAML: %v", err) } // Undeclared theme_presets must be PRESERVED, not wiped to nil. if string(m.ThemePresets) != `{"guest":true}` { t.Errorf("theme_presets wiped/altered: %q", string(m.ThemePresets)) } // Declared bundled_fonts folded in. if string(m.BundledFonts) != `{"fonts":["Inter"]}` { t.Errorf("bundled_fonts = %q", string(m.BundledFonts)) } // Declared page template appended alongside the guest one (2 total). if len(m.PageTemplates) != 2 { t.Fatalf("page templates = %d, want 2 (guest + declarative)", len(m.PageTemplates)) } // Declared email wrapper folded in. if len(m.EmailWrapperSystemKeys) != 1 || m.EmailWrapperSystemKeys[0] != "newsletter" { t.Errorf("email wrappers = %v", m.EmailWrapperSystemKeys) } } // TestWasmBuildFoldsManifestYAML end-to-end: a repo with Go source AND a // manifest.yaml builds a (non-codeless) wasm artifact whose manifest.pb carries // the folded declarative surfaces. The absence of a manifest.yaml is a no-op — // covered by every existing wasm build test. func TestApplyManifestYAMLNoFileIsNoop(t *testing.T) { dir := t.TempDir() // no manifest.yaml m := &abiv1.PluginManifest{ AbiVersion: 1, Name: "fixture-pure", Version: "0.1.0", ThemePresets: []byte(`{"guest":true}`), } if err := applyManifestYAML(dir, m); err != nil { t.Fatalf("applyManifestYAML (no file): %v", err) } if string(m.ThemePresets) != `{"guest":true}` { t.Errorf("no-manifest.yaml build mutated the manifest: %q", string(m.ThemePresets)) } }