diff --git a/internal/domains/sensors/domain_test.go b/internal/domains/sensors/domain_test.go index bf8ed13..12e08f1 100644 --- a/internal/domains/sensors/domain_test.go +++ b/internal/domains/sensors/domain_test.go @@ -195,6 +195,136 @@ func Test_SensorValidate(t *testing.T) { } } +func Test_SensorData_Validate(t *testing.T) { + type testCase struct { + name string + given SensorData + expected SensorData + expecErr bool + } + + timestamp := time.Now() + + tests := []testCase{ + { + name: "success with all fields", + given: SensorData{ + SensorID: "temp-001", + Value: ptr(25.5), + Timestamp: ptr(timestamp), + }, + expected: SensorData{ + SensorID: "temp-001", + Value: ptr(25.5), + Timestamp: ptr(timestamp), + }, + expecErr: false, + }, + { + name: "error when sensor_id is empty", + given: SensorData{ + SensorID: "", + Value: ptr(25.5), + }, + expecErr: true, + }, + { + name: "error when value is nil", + given: SensorData{ + SensorID: "temp-001", + Value: nil, + }, + expecErr: true, + }, + { + name: "default timestamp when nil", + given: SensorData{ + SensorID: "temp-001", + Value: ptr(30.0), + Timestamp: nil, + }, + expected: SensorData{ + SensorID: "temp-001", + Value: ptr(30.0), + Timestamp: nil, // Will be set by Validate + }, + expecErr: false, + }, + { + name: "zero value is preserved", + given: SensorData{ + SensorID: "temp-001", + Value: ptr(0.0), + Timestamp: ptr(timestamp), + }, + expected: SensorData{ + SensorID: "temp-001", + Value: ptr(0.0), + Timestamp: ptr(timestamp), + }, + expecErr: false, + }, + { + name: "negative value is valid", + given: SensorData{ + SensorID: "temp-001", + Value: ptr(-15.5), + Timestamp: ptr(timestamp), + }, + expected: SensorData{ + SensorID: "temp-001", + Value: ptr(-15.5), + Timestamp: ptr(timestamp), + }, + expecErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.given.Validate() + + if tt.expecErr && err == nil { + t.Errorf("expected error, got nil") + return + } + + if !tt.expecErr && err != nil { + t.Errorf("unexpected error: %v", err) + return + } + + if tt.expecErr { + return + } + + if tt.given.SensorID != tt.expected.SensorID { + t.Errorf("SensorID: expected %q, got %q", tt.expected.SensorID, tt.given.SensorID) + } + + if tt.given.Value == nil || tt.expected.Value == nil { + if tt.given.Value != tt.expected.Value { + t.Errorf("Value: expected %v, got %v", tt.expected.Value, tt.given.Value) + } + } else if *tt.given.Value != *tt.expected.Value { + t.Errorf("Value: expected %v, got %v", *tt.expected.Value, *tt.given.Value) + } + + if tt.expected.Timestamp == nil && tt.given.Timestamp != nil { + if time.Since(*tt.given.Timestamp) > time.Minute { + t.Errorf("Timestamp: expected default to be approximately now, got %v", *tt.given.Timestamp) + } + } else if tt.given.Timestamp == nil || tt.expected.Timestamp == nil { + if tt.given.Timestamp != tt.expected.Timestamp { + t.Errorf("Timestamp: expected %v, got %v", tt.expected.Timestamp, tt.given.Timestamp) + } + } else if !tt.given.Timestamp.Equal(*tt.expected.Timestamp) { + t.Errorf("Timestamp: expected %v, got %v", *tt.expected.Timestamp, *tt.given.Timestamp) + } + }) + } +} + func Test_SensorData_IsOutOfRangeAbove(t *testing.T) { type testCase struct { name string