package parser import ( "encoding/json" "os" "testing" "time" "mqqt-scrubber/internal/model" ) type fixtureCase struct { Name string `json:"name"` Topic string `json:"topic"` Payload string `json:"payload"` ReceivedAt string `json:"received_at"` ExpectedMeasurement string `json:"expected_measurement"` ExpectedTimestamp string `json:"expected_timestamp"` ExpectedTags map[string]string `json:"expected_tags"` ExpectedFields map[string]any `json:"expected_fields"` } func TestParseTasmotaFixtures(t *testing.T) { contents, err := os.ReadFile("testdata/tasmota_samples.json") if err != nil { t.Fatalf("read fixture file: %v", err) } var fixtures []fixtureCase if err := json.Unmarshal(contents, &fixtures); err != nil { t.Fatalf("parse fixture file: %v", err) } for _, fixture := range fixtures { t.Run(fixture.Name, func(t *testing.T) { receivedAt, err := time.Parse(time.RFC3339, fixture.ReceivedAt) if err != nil { t.Fatalf("parse receivedAt: %v", err) } expectedTimestamp, err := time.Parse(time.RFC3339, fixture.ExpectedTimestamp) if err != nil { t.Fatalf("parse expected timestamp: %v", err) } records, err := ParseTasmota(model.RawMessage{ Topic: fixture.Topic, Payload: []byte(fixture.Payload), ReceivedAt: receivedAt, }) if err != nil { t.Fatalf("ParseTasmota returned error: %v", err) } if len(records) != 1 { t.Fatalf("expected 1 record, got %d", len(records)) } record := records[0] if record.Measurement != fixture.ExpectedMeasurement { t.Fatalf("unexpected measurement: got %s want %s", record.Measurement, fixture.ExpectedMeasurement) } if !record.Timestamp.Equal(expectedTimestamp) { t.Fatalf("unexpected timestamp: got %s want %s", record.Timestamp.Format(time.RFC3339), expectedTimestamp.Format(time.RFC3339)) } for key, value := range fixture.ExpectedTags { if record.Tags[key] != value { t.Fatalf("unexpected tag %s: got %q want %q", key, record.Tags[key], value) } } for key, value := range fixture.ExpectedFields { fieldValue, ok := record.Fields[key] if !ok { t.Fatalf("expected field %s to be present", key) } if !fieldEquals(fieldValue, value) { t.Fatalf("unexpected field %s: got %#v want %#v", key, fieldValue, value) } } }) } } func fieldEquals(got any, want any) bool { switch typedWant := want.(type) { case float64: typedGot, ok := got.(float64) return ok && typedGot == typedWant case string: typedGot, ok := got.(string) return ok && typedGot == typedWant case bool: typedGot, ok := got.(bool) return ok && typedGot == typedWant default: return false } }