// Copyright (c) Abstract Machines // SPDX-License-Identifier: Apache-2.0 package reports_test import ( "fmt" "testing" "github.com/absmach/magistrala/reports" "github.com/stretchr/testify/assert" ) const ( validTemplate = `
Generated on: {{$.GeneratedDate}}
Time: {{formatTime .Time}}
Value: {{formatValue .}}
{{end}} ` templateWithoutRange = `No messages to display
` templateWithoutFormatTime = `Time: {{.Time}}
Value: {{formatValue .}}
{{end}} ` templateWithoutFormatValue = `Time: {{formatTime .Time}}
Value: {{.}}
{{end}} ` templateWithoutEnd = `Time: {{formatTime "test"}}
Value: {{formatValue "test"}}
No range block with end
` templateWithSyntaxError = `Time: {{formatTime .Time}}
Value: {{formatValue .}}
{{end ` templateWithUndefinedFunction = `Time: {{formatTime .Time}}
Value: {{formatValue .}}
Custom: {{customFunction .}}
{{end}} ` templateWithIfCondition = `Time: {{formatTime .Time}}
Value: {{formatValue .}}
{{end}} {{else}}No messages available
{{end}} ` templateWithWithCondition = `Time: {{formatTime .Time}}
Value: {{formatValue .}}
{{end}} {{else}}No data available
{{end}} ` templateWithNestedConditions = `Time: {{formatTime .Time}}
Value: {{formatValue .}}
{{end}} {{else}}Data not available
{{end}} {{else}}No messages flag set
{{end}} ` templateWithIfMissingFields = `Time: {{.Time}}
Value: {{.}}
{{end}} {{else}}No messages available
{{end}} ` templateWithWithMissingFields = `Time: {{.Time}}
Value: {{formatValue .}}
{{end}} {{else}}No data available
{{end}} ` ) func TestReportTemplate_Validate(t *testing.T) { cases := []struct { desc string template reports.ReportTemplate err error }{ { desc: "validate template successfully", template: reports.ReportTemplate(validTemplate), err: nil, }, { desc: "validate template without title field", template: reports.ReportTemplate(templateWithoutTitle), err: fmt.Errorf("missing essential template field: {{$.Title}}"), }, { desc: "validate template without range field", template: reports.ReportTemplate(templateWithoutRange), err: fmt.Errorf("missing essential template field: {{range .Messages}}"), }, { desc: "validate template without formatTime field", template: reports.ReportTemplate(templateWithoutFormatTime), err: fmt.Errorf("missing essential template field: {{formatTime .Time}}"), }, { desc: "validate template without formatValue field", template: reports.ReportTemplate(templateWithoutFormatValue), err: fmt.Errorf("missing essential template field: {{formatValue .}}"), }, { desc: "validate template without end field", template: reports.ReportTemplate(templateWithoutEnd), err: fmt.Errorf("missing essential template field: {{range .Messages}}"), }, { desc: "validate template with syntax error", template: reports.ReportTemplate(templateWithSyntaxError), err: fmt.Errorf("template syntax error"), }, { desc: "validate template with undefined function", template: reports.ReportTemplate(templateWithUndefinedFunction), err: fmt.Errorf("template syntax error"), }, { desc: "validate empty template", template: reports.ReportTemplate(""), err: fmt.Errorf("missing essential template field: {{$.Title}}"), }, { desc: "validate template with if condition successfully", template: reports.ReportTemplate(templateWithIfCondition), err: nil, }, { desc: "validate template `with` with condition successfully", template: reports.ReportTemplate(templateWithWithCondition), err: nil, }, { desc: "validate template with nested conditions successfully", template: reports.ReportTemplate(templateWithNestedConditions), err: nil, }, { desc: "validate template with if condition missing formatTime", template: reports.ReportTemplate(templateWithIfMissingFields), err: fmt.Errorf("missing essential template field: {{formatTime .Time}}"), }, { desc: "validate template `with` with condition missing formatTime", template: reports.ReportTemplate(templateWithWithMissingFields), err: fmt.Errorf("missing essential template field: {{formatTime .Time}}"), }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { err := tc.template.Validate() if tc.err != nil { assert.Error(t, err) assert.Contains(t, err.Error(), tc.err.Error()) } else { assert.NoError(t, err) } }) } } func TestReportTemplate_String(t *testing.T) { template := reports.ReportTemplate(validTemplate) result := template.String() assert.Equal(t, validTemplate, result) } func TestReportTemplate_MarshalJSON(t *testing.T) { template := reports.ReportTemplate("simple template") data, err := template.MarshalJSON() assert.NoError(t, err) assert.NotNil(t, data) assert.Equal(t, `"simple template"`, string(data)) } func TestReportTemplate_UnmarshalJSON(t *testing.T) { cases := []struct { desc string data []byte expected string err error }{ { desc: "unmarshal valid JSON successfully", data: []byte(`"simple template"`), expected: "simple template", err: nil, }, { desc: "unmarshal invalid JSON", data: []byte(`invalid json`), err: fmt.Errorf("invalid character"), }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { var template reports.ReportTemplate err := template.UnmarshalJSON(tc.data) if tc.err != nil { assert.Error(t, err) assert.Contains(t, err.Error(), tc.err.Error()) } else { assert.NoError(t, err) assert.Equal(t, tc.expected, string(template)) } }) } }