cli/internal/bnp/mixed_test.go
Alex Dunmow 42789ffd0f refactor: migrate plugin SDK imports from block/core to block/pluginsdk
Rewrite import prefix git.dev.alexdunmow.com/block/core/{plugin,blocks,
templates,abi} to git.dev.alexdunmow.com/block/pluginsdk/* across the CLI's
plugin build/verify logic (internal/bnp), plugin commands (cmd/ninja/cmd),
and the wasm build fixtures (testdata/fixture, testdata/capfixture). go.mod
adds pluginsdk@v0.1.0; core is retained only for cmd/ninja/cmd/theme.go
(ParseModFull), which is left untouched as in-flight work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 11:39:22 +08:00

80 lines
2.9 KiB
Go

package bnp
import (
"testing"
abiv1 "git.dev.alexdunmow.com/block/pluginsdk/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": `<main>{{ title }}</main>`,
"templates/email/newsletter.ninjatpl": `<table>{{ body|safe }}</table>`,
})
// 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))
}
}