refactor(test): make JSON generation smarter by using structs

This commit is contained in:
shulcz 2024-11-18 23:26:45 +03:00 committed by Jan De Dobbeleer
parent 7de3419e21
commit 2c71d4e135

View file

@ -1,7 +1,7 @@
package segments package segments
import ( import (
"fmt" "encoding/json"
"testing" "testing"
"time" "time"
@ -19,128 +19,165 @@ const (
BFBatchReadingsURL = "https://api.brewfather.app/v1/batches/" + BFFakeBatchID + "/readings" BFBatchReadingsURL = "https://api.brewfather.app/v1/batches/" + BFFakeBatchID + "/readings"
) )
func TestBrewfatherSegment(t *testing.T) { var (
TimeNow := time.Now() TimeNow = time.Now()
// Create a fake timeline for the fake json, all in Unix milliseconds, to be used in all fake json responses // Create a fake timeline for the fake json, all in Unix milliseconds, to be used in all fake json responses
FakeBrewDate := TimeNow.Add(-time.Hour * 24 * 20) FakeBrewDate = TimeNow.Add(-time.Hour * 24 * 20)
FakeFermentationStartDate := FakeBrewDate.Add(time.Hour * 24) // 1 day after brew date = 19 days ago FakeFermentationStartDate = FakeBrewDate.Add(time.Hour * 24) // 1 day after brew date = 19 days ago
FakeReading1Date := FakeFermentationStartDate.Add(time.Minute * 35) // first reading 35 minutes FakeReading1Date = FakeFermentationStartDate.Add(time.Minute * 35) // first reading 35 minutes
FakeReading2Date := FakeReading1Date.Add(time.Hour) // second reading 1 hour later FakeReading2Date = FakeReading1Date.Add(time.Hour) // second reading 1 hour later
FakeReading3Date := FakeReading2Date.Add(time.Hour * 3) // 3 hours after last reading, 454 hours ago FakeReading3Date = FakeReading2Date.Add(time.Hour * 3) // 3 hours after last reading, 454 hours ago
FakeBottlingDate := FakeFermentationStartDate.Add(time.Hour * 24 * 14) // 14 days after ferm date = 5 days ago FakeBottlingDate = FakeFermentationStartDate.Add(time.Hour * 24 * 14) // 14 days after ferm date = 5 days ago
FakeBrewDateString := fmt.Sprintf("%d", FakeBrewDate.UnixMilli()) BrewDateMillis = FakeBrewDate.UnixMilli()
FakeFermStartDateString := fmt.Sprintf("%d", FakeFermentationStartDate.UnixMilli()) FermStartDateMillis = FakeFermentationStartDate.UnixMilli()
FakeReading1DateString := fmt.Sprintf("%d", FakeReading1Date.UnixMilli()) Reading1DateMillis = FakeReading1Date.UnixMilli()
FakeReading2DateString := fmt.Sprintf("%d", FakeReading2Date.UnixMilli()) Reading2DateMillis = FakeReading2Date.UnixMilli()
FakeReading3DateString := fmt.Sprintf("%d", FakeReading3Date.UnixMilli()) Reading3DateMillis = FakeReading3Date.UnixMilli()
FakeBottlingDateString := fmt.Sprintf("%d", FakeBottlingDate.UnixMilli()) BottlingDateMillis = FakeBottlingDate.UnixMilli()
// TODO: make this smarter BatchNumber = 18
BatchName = "Batch"
RecipeName = "Fake Beer"
MeasuredAbv = 1.3
)
beerRecipeText := `,"recipe":{"name":"Fake Beer"},"fermentationStartDate":` func createBatch(status string) *Batch {
bottlingDate := `,"bottlingDate":` return &Batch{
batchText := `,"name":"Batch","measuredAbv": 1.3}` Status: status,
batchNumberFermenting := `{"batchNo":18,"status":"Fermenting","brewDate":` BatchNumber: BatchNumber,
manualType := `,"type":"manual"}]` BrewDate: BrewDateMillis,
FermentStartDate: FermStartDateMillis,
BottlingDate: BottlingDateMillis,
BatchName: BatchName,
MeasuredAbv: MeasuredAbv,
Recipe: struct {
Name string `json:"name"`
}{
Name: RecipeName,
},
}
}
jsonFiller := FakeBrewDateString + bottlingDate + FakeBottlingDateString + beerRecipeText + FakeFermStartDateString + batchText func createReading(temp, gravity float64, millis int64) *BatchReading {
return &BatchReading{
batchReadingJSON := `[{"id":"manual","temp":19.5,"comment":"","sg":1.066,"time":` DeviceID: "manual",
batchReadingJSON2 := `,"type":"manual"}, {"id":"manual","temp":21,"comment":"","sg":1.063,"time":` Temperature: temp,
batchReadingJSON3 := `,"type":"manual"}, {"id":"manual","temp":15,"comment":"","sg":1.050,"time":` Comment: "",
Gravity: gravity,
Time: millis,
DeviceType: "manual",
}
}
func TestBrewfatherSegment(t *testing.T) {
cases := []struct { cases := []struct {
Error error Error error
Case string BatchResponse *Batch
BatchJSONResponse string Case string
BatchReadingsJSONResponse string ExpectedString string
ExpectedString string Template string
Template string BatchReadingsResponse []*BatchReading
CacheTimeout int CacheTimeout int
ExpectedEnabled bool ExpectedEnabled bool
CacheFoundFail bool CacheFoundFail bool
}{ }{
{ {
Case: "Planning Status", Case: "Planning Status",
BatchJSONResponse: `{"batchNo":18,"status":"Planning","brewDate":` + jsonFiller, BatchResponse: createBatch(BFStatusPlanning),
BatchReadingsJSONResponse: `[]`, BatchReadingsResponse: []*BatchReading{},
Template: "{{.StatusIcon}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll Template: "{{.StatusIcon}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll
ExpectedString: " Fake Beer 1.3%", ExpectedString: " Fake Beer 1.3%",
ExpectedEnabled: true, ExpectedEnabled: true,
}, },
{ {
Case: "Brewing Status", Case: "Brewing Status",
BatchJSONResponse: `{"batchNo":18,"status":"Brewing","brewDate":` + jsonFiller, BatchResponse: createBatch(BFStatusBrewing),
BatchReadingsJSONResponse: `[]`, BatchReadingsResponse: []*BatchReading{},
Template: "{{.StatusIcon}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll Template: "{{.StatusIcon}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll
ExpectedString: " Fake Beer 1.3%", ExpectedString: " Fake Beer 1.3%",
ExpectedEnabled: true, ExpectedEnabled: true,
}, },
{ {
Case: "Fermenting Status, no readings", Case: "Fermenting Status, no readings",
BatchJSONResponse: batchNumberFermenting + jsonFiller, BatchResponse: createBatch(BFStatusFermenting),
BatchReadingsJSONResponse: `[]`, BatchReadingsResponse: []*BatchReading{},
Template: "{{.StatusIcon}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll Template: "{{.StatusIcon}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll
ExpectedString: " 19d Fake Beer 1.3%", ExpectedString: " 19d Fake Beer 1.3%",
ExpectedEnabled: true, ExpectedEnabled: true,
}, },
{ {
Case: "Fermenting Status, one reading", Case: "Fermenting Status, one reading",
BatchJSONResponse: batchNumberFermenting + jsonFiller, BatchResponse: createBatch(BFStatusFermenting),
BatchReadingsJSONResponse: batchReadingJSON + FakeReading1DateString + manualType, BatchReadingsResponse: []*BatchReading{
Template: "{{.StatusIcon}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll createReading(19.5, 1.066, Reading1DateMillis),
ExpectedString: " 19d Fake Beer 1.3%: 1.066 19.5° →", },
ExpectedEnabled: true, Template: "{{.StatusIcon}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll
ExpectedString: " 19d Fake Beer 1.3%: 1.066 19.5° →",
ExpectedEnabled: true,
}, },
{ {
Case: "Fermenting Status, two readings, temp trending up", Case: "Fermenting Status, two readings, temp trending up",
BatchJSONResponse: batchNumberFermenting + jsonFiller, //nolint:lll BatchResponse: createBatch(BFStatusFermenting),
BatchReadingsJSONResponse: batchReadingJSON + FakeReading1DateString + batchReadingJSON2 + FakeReading2DateString + manualType, //nolint:lll BatchReadingsResponse: []*BatchReading{
Template: "{{.StatusIcon}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll createReading(21.0, 1.063, Reading2DateMillis),
ExpectedString: " 19d Fake Beer 1.3%: 1.063 21° ↗", createReading(19.5, 1.066, Reading1DateMillis),
ExpectedEnabled: true, },
Template: "{{.StatusIcon}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll
ExpectedString: " 19d Fake Beer 1.3%: 1.063 21° ↗",
ExpectedEnabled: true,
}, },
{ {
Case: "Fermenting Status, three readings, temp trending hard down, include age of most recent reading", Case: "Fermenting Status, three readings, temp trending hard down, include age of most recent reading",
BatchJSONResponse: batchNumberFermenting + jsonFiller, //nolint:lll BatchResponse: createBatch(BFStatusFermenting),
BatchReadingsJSONResponse: batchReadingJSON + FakeReading1DateString + batchReadingJSON2 + FakeReading2DateString + batchReadingJSON3 + FakeReading3DateString + manualType, //nolint:lll BatchReadingsResponse: []*BatchReading{
Template: "{{.StatusIcon}} {{.ReadingAge}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll createReading(15.0, 1.050, Reading3DateMillis),
ExpectedString: " 451 19d Fake Beer 1.3%: 1.05 15° ↓↓", createReading(21.0, 1.063, Reading2DateMillis),
ExpectedEnabled: true, createReading(19.5, 1.066, Reading1DateMillis),
},
Template: "{{.StatusIcon}} {{.ReadingAge}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll
ExpectedString: " 451 19d Fake Beer 1.3%: 1.05 15° ↓↓",
ExpectedEnabled: true,
}, },
{ {
Case: "Bad batch json, readings fine", Case: "Bad batch json, readings fine",
BatchJSONResponse: ``, BatchResponse: nil,
BatchReadingsJSONResponse: batchReadingJSON + FakeReading1DateString + batchReadingJSON2 + FakeReading2DateString + batchReadingJSON3 + FakeReading3DateString + manualType, //nolint:lll BatchReadingsResponse: []*BatchReading{
Template: "{{.StatusIcon}} {{.ReadingAge}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll createReading(15.0, 1.050, Reading3DateMillis),
ExpectedString: "", },
ExpectedEnabled: false, Template: "{{.StatusIcon}} {{.ReadingAge}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll
ExpectedString: "",
ExpectedEnabled: false,
}, },
{ {
Case: "Conditioning Status", Case: "Conditioning Status",
BatchJSONResponse: `{"batchNo":18,"status":"Conditioning","brewDate":` + jsonFiller, //nolint:lll BatchResponse: createBatch(BFStatusConditioning),
BatchReadingsJSONResponse: batchReadingJSON + FakeReading1DateString + batchReadingJSON2 + FakeReading2DateString + batchReadingJSON3 + FakeReading3DateString + manualType, //nolint:lll BatchReadingsResponse: []*BatchReading{
Template: "{{.StatusIcon}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll createReading(15.0, 1.050, Reading3DateMillis),
ExpectedString: " 5d Fake Beer 1.3%", },
ExpectedEnabled: true, Template: "{{.StatusIcon}} {{if .DaysBottledOrFermented}}{{.DaysBottledOrFermented}}d {{end}}{{.Recipe.Name}} {{.MeasuredAbv}}%{{ if and (.Reading) (eq .Status \"Fermenting\")}}: {{.Reading.Gravity}} {{.Reading.Temperature}}° {{.TemperatureTrendIcon}}{{end}}", //nolint:lll
ExpectedString: " 5d Fake Beer 1.3%",
ExpectedEnabled: true,
}, },
{ {
Case: "Fermenting Status, test all unit conversions", Case: "Fermenting Status, test all unit conversions",
BatchJSONResponse: batchNumberFermenting + jsonFiller, BatchResponse: createBatch(BFStatusFermenting),
BatchReadingsJSONResponse: `[{"id":"manual","temp":34.5,"comment":"","sg":1.066,"time":` + FakeReading1DateString + manualType, BatchReadingsResponse: []*BatchReading{
Template: "{{ if and (.Reading) (eq .Status \"Fermenting\") }}SG: ({{.Reading.Gravity}} Bx:{{.SGToBrix .Reading.Gravity}} P:{{.SGToPlato .Reading.Gravity}}), Temp: (C:{{.Reading.Temperature}} F:{{.DegCToF .Reading.Temperature}} K:{{.DegCToKelvin .Reading.Temperature}}){{end}}", //nolint:lll createReading(34.5, 1.066, Reading1DateMillis),
ExpectedString: "SG: (1.066 Bx:16.13 P:16.13), Temp: (C:34.5 F:94.1 K:307.7)", },
ExpectedEnabled: true, Template: "{{ if and (.Reading) (eq .Status \"Fermenting\") }}SG: ({{.Reading.Gravity}} Bx:{{.SGToBrix .Reading.Gravity}} P:{{.SGToPlato .Reading.Gravity}}), Temp: (C:{{.Reading.Temperature}} F:{{.DegCToF .Reading.Temperature}} K:{{.DegCToKelvin .Reading.Temperature}}){{end}}", //nolint:lll
ExpectedString: "SG: (1.066 Bx:16.13 P:16.13), Temp: (C:34.5 F:94.1 K:307.7)",
ExpectedEnabled: true,
}, },
{ {
Case: "Fermenting Status, test all unit conversions 2", Case: "Fermenting Status, test all unit conversions 2",
BatchJSONResponse: batchNumberFermenting + jsonFiller, BatchResponse: createBatch(BFStatusFermenting),
BatchReadingsJSONResponse: `[{"id":"manual","temp":3.5,"comment":"","sg":1.004,"time":` + FakeReading1DateString + manualType, BatchReadingsResponse: []*BatchReading{
Template: "{{ if and (.Reading) (eq .Status \"Fermenting\") }}SG: ({{.Reading.Gravity}} Bx:{{.SGToBrix .Reading.Gravity}} P:{{.SGToPlato .Reading.Gravity}}), Temp: (C:{{.Reading.Temperature}} F:{{.DegCToF .Reading.Temperature}} K:{{.DegCToKelvin .Reading.Temperature}}){{end}}", //nolint:lll createReading(3.5, 1.004, Reading1DateMillis),
ExpectedString: "SG: (1.004 Bx:1.03 P:1.03), Temp: (C:3.5 F:38.3 K:276.7)", },
ExpectedEnabled: true, Template: "{{ if and (.Reading) (eq .Status \"Fermenting\") }}SG: ({{.Reading.Gravity}} Bx:{{.SGToBrix .Reading.Gravity}} P:{{.SGToPlato .Reading.Gravity}}), Temp: (C:{{.Reading.Temperature}} F:{{.DegCToF .Reading.Temperature}} K:{{.DegCToKelvin .Reading.Temperature}}){{end}}", //nolint:lll
ExpectedString: "SG: (1.004 Bx:1.03 P:1.03), Temp: (C:3.5 F:38.3 K:276.7)",
ExpectedEnabled: true,
}, },
} }
@ -152,8 +189,21 @@ func TestBrewfatherSegment(t *testing.T) {
BFUserID: "FAKE", BFUserID: "FAKE",
} }
env.On("HTTPRequest", BFBatchURL).Return([]byte(tc.BatchJSONResponse), tc.Error) var batchJSON []byte
env.On("HTTPRequest", BFBatchReadingsURL).Return([]byte(tc.BatchReadingsJSONResponse), tc.Error) var err error
if tc.BatchResponse != nil {
batchJSON, err = json.Marshal(tc.BatchResponse)
assert.NoError(t, err)
} else {
// bad JSON
batchJSON = []byte("invalid json")
}
batchReadingsJSON, err := json.Marshal(tc.BatchReadingsResponse)
assert.NoError(t, err)
env.On("HTTPRequest", BFBatchURL).Return(batchJSON, tc.Error)
env.On("HTTPRequest", BFBatchReadingsURL).Return(batchReadingsJSON, tc.Error)
env.On("Flags").Return(&runtime.Flags{}) env.On("Flags").Return(&runtime.Flags{})
brew := &Brewfather{} brew := &Brewfather{}