All checks were successful
Golan Testing / testing (1.24.x, ubuntu-latest) (push) Successful in 25s
- 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.
205 lines
5.2 KiB
Go
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))
|
|
// }
|