package stacks import ( "errors" "strings" "testing" ) // D4 (felhom.eu architecture/16-storage-physical-identity.md §5, R-1068): a data-folder or media app on a // box with NO drive is refused in words with the way forward — never the field name, never sys_drive. // COMPANION RED-PROOF: delete the D4 branch in deploy.go → the plain required-field refusal comes back // („a(z) "Médiatár útvonal" (HDD_PATH) mező kitöltése kötelező", the OMV test's sentence) and this fails. func TestD4_NoDriveRefusalSpeaksInWords(t *testing.T) { for name, yml := range map[string]string{ "media app": "display_name: Jellyfin\nmedia_library:\n folder: films\ndeploy_fields:\n - env_var: HDD_PATH\n label: Médiatár útvonal\n type: path\n required: true\n", "data-folder app": "display_name: Paperless\ndeploy_fields:\n - env_var: HDD_PATH\n label: Adattárolási útvonal\n type: path\n required: true\n", } { t.Run(name, func(t *testing.T) { m := r553Manager(t, yml) _, err := m.DeployStack(DeployRequest{StackName: "r553app", Values: map[string]string{}}) if err == nil { t.Fatal("deploy was admitted on a box with no drive") } if !errors.Is(err, ErrNeedsDrive) { t.Fatalf("want ErrNeedsDrive, got %v", err) } msg := err.Error() if msg != "Ehhez az alkalmazáshoz egy adattároló kell. A Meghajtók oldalon adhatsz hozzá egyet." { t.Errorf("the D4 sentence moved: %q", msg) } for _, bad := range []string{"HDD_PATH", "útvonal", "sys_drive", "kötelező"} { if strings.Contains(msg, bad) { t.Errorf("the refusal names %q — it must speak in words, not fields: %q", bad, msg) } } }) } } // A path field the household FILLED is not a D4 case: a missing path keeps its own refusal. func TestD4_FilledPathKeepsItsOwnRefusal(t *testing.T) { m := r553Manager(t, "display_name: X\ndeploy_fields:\n - env_var: HDD_PATH\n label: Adat\n type: path\n required: true\n") _, err := m.DeployStack(DeployRequest{StackName: "r553app", Values: map[string]string{"HDD_PATH": "/definitely/not/here/d4"}}) if !errors.Is(err, ErrPathMissing) { t.Fatalf("want ErrPathMissing for a filled, missing path, got %v", err) } }