package model import ( "encoding/json" "testing" "go.mongodb.org/mongo-driver/v2/bson" ) // TestOwnerJSONFlattensRef locks in the on-wire shape documented on Owner: // owner.ref and owner.kind must both be top-level keys. Ref must stay // anonymously embedded — a NAMED field with a `json:",inline"` tag is a // BSON-only convention and is not flattened by encoding/json, which would // silently nest it under the Go field name instead (a real regression this // test caught: {"Ref":{"ref":"..."},"kind":"..."} instead of // {"ref":"...","kind":"..."}), breaking every JSON consumer of owner.ref. func TestOwnerJSONFlattensRef(t *testing.T) { ownerRef := bson.NewObjectID() owner := Owner{Kind: OwnerKindAccount} owner.Ref.Ref = ownerRef b, err := json.Marshal(owner) if err != nil { t.Fatalf("marshal owner: %v", err) } var decoded map[string]any if err := json.Unmarshal(b, &decoded); err != nil { t.Fatalf("unmarshal owner json: %v", err) } if got, want := decoded["ref"], ownerRef.Hex(); got != want { t.Fatalf("top-level owner.ref = %v, want %q (got JSON: %s)", got, want, b) } if got, want := decoded["kind"], string(OwnerKindAccount); got != want { t.Fatalf("top-level owner.kind = %v, want %q (got JSON: %s)", got, want, b) } if _, nested := decoded["Ref"]; nested { t.Fatalf("owner.ref must not nest under the Go field name \"Ref\", got JSON: %s", b) } } func TestRecipientJSONRoundTripsOwner(t *testing.T) { r := &Recipient{} r.SetOwnerKind(OwnerKindOrganization) r.SetOwnerRef(bson.NewObjectID()) b, err := json.Marshal(r) if err != nil { t.Fatalf("marshal recipient: %v", err) } var roundTripped Recipient if err := json.Unmarshal(b, &roundTripped); err != nil { t.Fatalf("unmarshal recipient json: %v", err) } if roundTripped.GetOwnerKind() != r.GetOwnerKind() { t.Fatalf("owner kind round-trip = %v, want %v", roundTripped.GetOwnerKind(), r.GetOwnerKind()) } if roundTripped.GetOwnerRef() != r.GetOwnerRef() { t.Fatalf("owner ref round-trip = %v, want %v", roundTripped.GetOwnerRef(), r.GetOwnerRef()) } }