Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(encode): accept any input type #67

Merged
merged 1 commit into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions pkg/yam/formatted/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,25 @@ func (enc Encoder) UseOptions(options EncodeOptions) (Encoder, error) {
return enc, nil
}

// Encode writes out the formatted YAML from the given yaml.Node to the
// encoder's io.Writer.
func (enc Encoder) Encode(node *yaml.Node) error {
// Encode writes out the formatted YAML from the given value to the encoder's
// io.Writer.
func (enc Encoder) Encode(in any) error {
var node *yaml.Node
switch n := in.(type) {
case *yaml.Node:
node = n

case yaml.Node:
node = &n

default:
node = new(yaml.Node)
err := node.Encode(in)
if err != nil {
return fmt.Errorf("encoding input to YAML AST node: %w", err)
}
}

b, err := enc.marshalRoot(node)
if err != nil {
return err
Expand Down
91 changes: 91 additions & 0 deletions pkg/yam/formatted/encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,94 @@ func TestSortingSequence(t *testing.T) {
}
}
}

func TestEncoder_Encode(t *testing.T) {
// Sample data as yaml.Node
node := &yaml.Node{
Kind: yaml.MappingNode,
Content: []*yaml.Node{
{Kind: yaml.ScalarNode, Value: "update"},
{Kind: yaml.MappingNode, Content: []*yaml.Node{
{Kind: yaml.ScalarNode, Value: "enabled"},
{Kind: yaml.ScalarNode, Value: "true"},
{Kind: yaml.ScalarNode, Value: "git"},
{Kind: yaml.MappingNode, Style: yaml.FlowStyle},
{Kind: yaml.ScalarNode, Value: "schedule"},
{Kind: yaml.MappingNode, Content: []*yaml.Node{
{Kind: yaml.ScalarNode, Value: "daily"},
{Kind: yaml.ScalarNode, Value: "true"},
{Kind: yaml.ScalarNode, Value: "reason"},
{Kind: yaml.ScalarNode, Value: "upstream does not maintain tags or releases, it uses a branch"},
}},
}},
},
}

// Sample data as user-defined type
type Schedule struct {
Daily bool `yaml:"daily"`
Reason string `yaml:"reason"`
}
type Update struct {
Enabled bool `yaml:"enabled"`
Git struct{} `yaml:"git"`
Schedule Schedule `yaml:"schedule"`
}
type Document struct {
Update Update `yaml:"update"`
}
document := Document{
Update: Update{
Enabled: true,
Schedule: Schedule{
Daily: true,
Reason: "upstream does not maintain tags or releases, it uses a branch",
},
},
}

// Expected YAML output
expectedYAML := `update:
enabled: true
git: {}
schedule:
daily: true
reason: upstream does not maintain tags or releases, it uses a branch
`

t.Run("yaml.Node", func(t *testing.T) {
var outNode bytes.Buffer
encoderNode := NewEncoder(&outNode)
err := encoderNode.Encode(node)
require.NoError(t, err)

checkDiff(t, expectedYAML, outNode.String())
})

t.Run("user-defined type", func(t *testing.T) {
// Encode user-defined type
var outStruct bytes.Buffer
encoderStruct := NewEncoder(&outStruct)
err := encoderStruct.Encode(document)
require.NoError(t, err)

checkDiff(t, expectedYAML, outStruct.String())
})
}

func checkDiff(t *testing.T, expected, actual any) {
t.Helper()

if diff := cmp.Diff(expected, actual); diff != "" {
t.Errorf(`unexpected document (-want +got):
%s

full expected:

%s

full actual:

%s`, diff, expected, actual)
}
}