package wire import ( "encoding/json" "net/http" "net/http/httptest" "regexp" "testing" "time" ) // carbonOffsetRe is tide/normalize.go's Carbon +00:00 form, copied so wire // does not import tide. var carbonOffsetRe = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+00:00$`) func TestTimeMarshalJSONCarbonOffset(t *testing.T) { tm := Time{Time: time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC)} b, err := json.Marshal(tm) if err != nil { t.Fatal(err) } var s string if err := json.Unmarshal(b, &s); err != nil { t.Fatal(err) } if !carbonOffsetRe.MatchString(s) { t.Fatalf("got %q, want carbon +00:00 form", s) } if string(b) != `"2024-01-02T03:04:05+00:00"` { t.Fatalf("bytes = %s", b) } } func TestTimeUnmarshalJSONAcceptsOffsetAndZ(t *testing.T) { var offset Time if err := json.Unmarshal([]byte(`"2024-01-02T03:04:05+00:00"`), &offset); err != nil { t.Fatal(err) } if !offset.Equal(time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC)) { t.Fatalf("offset = %v", offset.Time) } var z Time if err := json.Unmarshal([]byte(`"2024-01-02T03:04:05Z"`), &z); err != nil { t.Fatal(err) } if !z.Equal(time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC)) { t.Fatalf("z = %v", z.Time) } } func TestTriBoolMarshalJSON(t *testing.T) { null, err := json.Marshal(TriBool{Valid: false}) if err != nil { t.Fatal(err) } if string(null) != "null" { t.Fatalf("invalid = %s", null) } f, err := json.Marshal(TriBool{Valid: true, Value: false}) if err != nil { t.Fatal(err) } if string(f) != "false" { t.Fatalf("false = %s", f) } tr, err := json.Marshal(TriBool{Valid: true, Value: true}) if err != nil { t.Fatal(err) } if string(tr) != "true" { t.Fatalf("true = %s", tr) } } func TestSliceNilMarshalsEmptyArray(t *testing.T) { s := Slice[int](nil) if s == nil { t.Fatal("Slice(nil) returned nil") } b, err := json.Marshal(s) if err != nil { t.Fatal(err) } if string(b) != "[]" { t.Fatalf("got %s", b) } } func TestWriteJSONNoHTMLEscapeNoTrailingNewline(t *testing.T) { rec := httptest.NewRecorder() WriteJSON(rec, http.StatusOK, map[string]string{"a": "x