Files
mysubaru/mysubaru_test.go
Alex Savin aec4b8435b
All checks were successful
Golan Testing / testing (1.24.x, ubuntu-latest) (push) Successful in 25s
Enhance MySubaru API integration with improved error handling and new utility functions
- Refactor Response struct's parse method to return detailed error messages based on API error codes.
- Introduce UnixTime type for handling Unix timestamps in JSON marshaling and unmarshaling.
- Add email masking utility function to obfuscate email addresses for privacy.
- Implement containsValueInStruct function to check for substring presence in struct fields.
- Create comprehensive unit tests for UnixTime, email masking, and struct value checking.
- Update vehicle service request method documentation for clarity.
2025-07-08 11:26:45 -04:00

205 lines
5.2 KiB
Go

package mysubaru
import (
"encoding/json"
"testing"
"time"
)
func TestUnixTime_UnmarshalJSON(t *testing.T) {
tests := []struct {
name string
input string
wantTime time.Time
wantError bool
}{
{
name: "valid unix timestamp",
input: "1700000000",
wantTime: time.Unix(1700000000, 0),
},
{
name: "invalid string",
input: "\"notanumber\"",
wantError: true,
},
{
name: "empty input",
input: "",
wantError: true,
},
{
name: "float value",
input: "1700000000.123",
wantError: true,
},
{
name: "zero timestamp",
input: "0",
wantTime: time.Unix(0, 0),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var ut UnixTime
err := ut.UnmarshalJSON([]byte(tt.input))
if (err != nil) != tt.wantError {
t.Errorf("UnmarshalJSON() error = %v, wantError %v", err, tt.wantError)
return
}
if !tt.wantError && !ut.Time.Equal(tt.wantTime) {
t.Errorf("UnmarshalJSON() got = %v, want %v", ut.Time, tt.wantTime)
}
})
}
}
func TestUnixTime_UnmarshalJSON_withJSONUnmarshal(t *testing.T) {
type testStruct struct {
Time UnixTime `json:"time"`
}
input := `{"time":1700000000}`
var ts testStruct
err := json.Unmarshal([]byte(input), &ts)
if err != nil {
t.Fatalf("json.Unmarshal failed: %v", err)
}
want := time.Unix(1700000000, 0)
if !ts.Time.Time.Equal(want) {
t.Errorf("UnmarshalJSON() got = %v, want %v", ts.Time.Time, want)
}
}
func TestUnixTime_MarshalJSON(t *testing.T) {
tests := []struct {
name string
input time.Time
want string
}{
{
name: "epoch",
input: time.Unix(0, 0),
want: "0",
},
{
name: "positive unix time",
input: time.Unix(1700000000, 0),
want: "1700000000",
},
{
name: "negative unix time",
input: time.Unix(-100, 0),
want: "-100",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ut := UnixTime{Time: tt.input}
got, err := ut.MarshalJSON()
if err != nil {
t.Fatalf("MarshalJSON() error = %v", err)
}
if string(got) != tt.want {
t.Errorf("MarshalJSON() = %s, want %s", string(got), tt.want)
}
})
}
}
func TestUnixTime_MarshalJSON_withJSONMarshal(t *testing.T) {
type testStruct struct {
Time UnixTime `json:"time"`
}
ts := testStruct{Time: UnixTime{Time: time.Unix(1700000000, 0)}}
b, err := json.Marshal(ts)
if err != nil {
t.Fatalf("json.Marshal failed: %v", err)
}
want := `{"time":1700000000}`
if string(b) != want {
t.Errorf("json.Marshal() = %s, want %s", string(b), want)
}
}
// func TestResponse_parse(t *testing.T) {
// tests := []struct {
// name string
// input string
// wantErr error
// wantCode string
// wantLog string
// }{
// {
// name: "success response",
// input: `{"success":true,"dataName":"foo","data":{}}`,
// wantErr: nil,
// },
// {
// name: "invalid json",
// input: `{"success":tru`,
// wantErr: errors.New("error while parsing json:"),
// wantLog: "error while parsing json",
// },
// {
// name: "API_ERROR_NO_ACCOUNT",
// input: `{"success":false,"errorCode":"noAccount","dataName":"errorResponse","data":{}}`,
// wantErr: errors.New("error in response: Account not found"),
// wantCode: "noAccount",
// wantLog: "error in response",
// },
// {
// name: "API_ERROR_INVALID_CREDENTIALS",
// input: `{"success":false,"errorCode":"invalidCredentials","dataName":"errorResponse","data":{}}`,
// wantErr: errors.New("error in response: Invalid Credentials"),
// wantCode: "invalidCredentials",
// wantLog: "error in response",
// },
// {
// name: "API_ERROR_SOA_403",
// input: `{"success":false,"errorCode":"404-soa-unableToParseResponseBody","dataName":"errorResponse","data":{}}`,
// wantErr: errors.New("error in response: Unable to parse response body, SOA 403 error"),
// wantCode: "404-soa-unableToParseResponseBody",
// wantLog: "error in response",
// },
// {
// name: "unknown error code",
// input: `{"success":false,"errorCode":"somethingElse","dataName":"errorResponse","data":{}}`,
// wantErr: errors.New("error in response: somethingElse"),
// wantCode: "somethingElse",
// wantLog: "error in response",
// },
// {
// name: "no errorCode but not success",
// input: `{"success":false,"dataName":"errorResponse","data":{}}`,
// wantErr: nil,
// },
// }
// for _, tt := range tests {
// t.Run(tt.name, func(t *testing.T) {
// var resp Response
// logger := slog.New(slog.NewTextHandler(nil, nil))
// got, err := resp.parse([]byte(tt.input), logger)
// if tt.wantErr != nil {
// if err == nil {
// t.Fatalf("expected error, got nil")
// }
// if !contains(err.Error(), tt.wantErr.Error()) {
// t.Errorf("parse() error = %v, want %v", err, tt.wantErr)
// }
// } else if err != nil {
// t.Errorf("parse() unexpected error: %v", err)
// }
// if tt.wantCode != "" && got != nil && got.ErrorCode != tt.wantCode {
// t.Errorf("parse() got.ErrorCode = %v, want %v", got.ErrorCode, tt.wantCode)
// }
// })
// }
// }
// // contains is a helper for substring matching.
// func contains(s, substr string) bool {
// return bytes.Contains([]byte(s), []byte(substr))
// }