package pluginsimport ("errors". "github.com/onsi/ginkgo/v2". "github.com/onsi/gomega")var _ = Describe("Config Validation", func() {Describe("ValidateConfig", func() {Context("when manifest has no config schema", func() {It("returns an error", func() {manifest := &Manifest{Name: "test",Author: "test",Version: "1.0.0",}err := ValidateConfig(manifest, `{"key": "value"}`)Expect(err).To(HaveOccurred())Expect(err.Error()).To(ContainSubstring("no configurable options"))})})Context("when manifest has config schema", func() {var manifest *ManifestBeforeEach(func() {manifest = &Manifest{Name: "test",Author: "test",Version: "1.0.0",Config: &ConfigDefinition{Schema: map[string]any{"type": "object","properties": map[string]any{"apiKey": map[string]any{"type": "string","description": "API key for the service","minLength": float64(1),},"timeout": map[string]any{"type": "integer","minimum": float64(1),"maximum": float64(300),},"enabled": map[string]any{"type": "boolean",},},"required": []any{"apiKey"},},},}})It("accepts valid config", func() {err := ValidateConfig(manifest, `{"apiKey": "secret123", "timeout": 30}`)Expect(err).ToNot(HaveOccurred())})It("rejects empty config when required fields are missing", func() {err := ValidateConfig(manifest, "")Expect(err).To(HaveOccurred())Expect(err.Error()).To(ContainSubstring("apiKey"))err = ValidateConfig(manifest, "{}")Expect(err).To(HaveOccurred())Expect(err.Error()).To(ContainSubstring("apiKey"))})It("rejects config missing required field", func() {err := ValidateConfig(manifest, `{"timeout": 30}`)Expect(err).To(HaveOccurred())Expect(err.Error()).To(ContainSubstring("apiKey"))})It("rejects config with wrong type", func() {err := ValidateConfig(manifest, `{"apiKey": "secret", "timeout": "not a number"}`)Expect(err).To(HaveOccurred())Expect(err.Error()).To(ContainSubstring("timeout"))})It("rejects config with value out of range", func() {err := ValidateConfig(manifest, `{"apiKey": "secret", "timeout": 500}`)Expect(err).To(HaveOccurred())Expect(err.Error()).To(ContainSubstring("timeout"))})It("rejects config with empty required string", func() {err := ValidateConfig(manifest, `{"apiKey": ""}`)Expect(err).To(HaveOccurred())Expect(err.Error()).To(ContainSubstring("apiKey"))})It("rejects invalid JSON", func() {err := ValidateConfig(manifest, `{invalid json}`)Expect(err).To(HaveOccurred())var validationErr *ConfigValidationErrorsExpect(errors.As(err, &validationErr)).To(BeTrue())Expect(validationErr.Errors[0].Message).To(ContainSubstring("invalid JSON"))})})Context("with enum values", func() {It("accepts valid enum value", func() {manifest := &Manifest{Name: "test",Author: "test",Version: "1.0.0",Config: &ConfigDefinition{Schema: map[string]any{"type": "object","properties": map[string]any{"logLevel": map[string]any{"type": "string","enum": []any{"debug", "info", "warn", "error"},},},},},}err := ValidateConfig(manifest, `{"logLevel": "info"}`)Expect(err).ToNot(HaveOccurred())})It("rejects invalid enum value", func() {manifest := &Manifest{Name: "test",Author: "test",Version: "1.0.0",Config: &ConfigDefinition{Schema: map[string]any{"type": "object","properties": map[string]any{"logLevel": map[string]any{"type": "string","enum": []any{"debug", "info", "warn", "error"},},},},},}err := ValidateConfig(manifest, `{"logLevel": "verbose"}`)Expect(err).To(HaveOccurred())})})})Describe("HasConfigSchema", func() {It("returns false when config is nil", func() {manifest := &Manifest{Name: "test",Author: "test",Version: "1.0.0",}Expect(manifest.HasConfigSchema()).To(BeFalse())})It("returns false when schema is nil", func() {manifest := &Manifest{Name: "test",Author: "test",Version: "1.0.0",Config: &ConfigDefinition{},}Expect(manifest.HasConfigSchema()).To(BeFalse())})It("returns true when schema is present", func() {manifest := &Manifest{Name: "test",Author: "test",Version: "1.0.0",Config: &ConfigDefinition{Schema: map[string]any{"type": "object",},},}Expect(manifest.HasConfigSchema()).To(BeTrue())})})})