/* * MIT License * * Copyright (c) 2023 Nicolas JUHEL * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * */ package retro_test import ( "encoding/json" "time" . "github.com/nabbar/golib/retro" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/pelletier/go-toml" "gopkg.in/yaml.v3" ) // Test models type TestModel struct { Version string `json:"version,omitempty" yaml:"version,omitempty" toml:"version,omitempty"` Name string `json:"name" yaml:"name" toml:"name" retro:">v1.0.0"` Age int `json:"age,omitempty" yaml:"age,omitempty" toml:"age,omitempty"` Active bool `json:"active,omitempty" yaml:"active,omitempty" toml:"active,omitempty" retro:">=v1.0.0"` Legacy string `json:"legacy" yaml:"legacy" toml:"legacy" retro:"v1.0.0,=v1.0.0"` } type SimpleModel struct { ID int `json:"id" yaml:"id" toml:"id"` Name string `json:"name" yaml:"name" toml:"name"` } type StandardModel struct { A int `json:"a" yaml:"a" toml:"a"` B string `json:"b" yaml:"b" toml:"b"` C []string `json:"c" yaml:"c" toml:"c"` } var _ = Describe("Model", func() { Describe("Model structure", func() { Context("when creating a new model", func() { It("should initialize with default values", func() { model := Model[TestModel]{} Expect(model.Struct).To(Equal(TestModel{})) Expect(model.Standard).To(BeFalse()) }) It("should allow setting Standard flag", func() { model := Model[TestModel]{Standard: true} Expect(model.Standard).To(BeTrue()) }) It("should hold the struct data", func() { data := TestModel{Name: "John", Age: 30} model := Model[TestModel]{Struct: data} Expect(model.Struct.Name).To(Equal("John")) Expect(model.Struct.Age).To(Equal(30)) }) }) }) Describe("JSON marshaling", func() { Context("when marshaling with no version (default)", func() { It("should include only fields with default tag and no retro tag", func() { model := Model[TestModel]{ Struct: TestModel{ Age: 25, DefaultField: "test", Name: "John", }, } data, err := json.Marshal(model) Expect(err).ToNot(HaveOccurred()) var result map[string]interface{} err = json.Unmarshal(data, &result) Expect(err).ToNot(HaveOccurred()) Expect(result).To(HaveKey("age")) Expect(result).To(HaveKey("default_field")) Expect(result).ToNot(HaveKey("name")) // requires >v1.0.0 }) }) Context("when marshaling with version v1.0.0", func() { It("should include fields matching version constraints", func() { model := Model[TestModel]{ Struct: TestModel{ Version: "v1.0.0", Age: 25, Active: true, Salary: 50000, Phone: "123-456", Name: "test", }, } data, err := json.Marshal(model) Expect(err).ToNot(HaveOccurred()) var result map[string]interface{} err = json.Unmarshal(data, &result) Expect(err).ToNot(HaveOccurred()) Expect(result).To(HaveKey("version")) Expect(result).To(HaveKey("age")) Expect(result).To(HaveKey("active")) // >=v1.0.0 Expect(result).To(HaveKey("salary")) // <=v1.0.0 Expect(result).To(HaveKey("phone")) // v1.0.0,v2.0.0 Expect(result).ToNot(HaveKey("name")) // >v1.0.0 Expect(result).ToNot(HaveKey("email")) // >v1.0.0,v1.0.0 Expect(result).To(HaveKey("email")) // >v1.0.0,