package atp import ( "context" "errors" "testing" ) // mockFetcher implements RecordFetcher for testing. type mockFetcher struct { record *Record err error } func (m *mockFetcher) GetRecord(ctx context.Context, collection, rkey string) (*Record, error) { return m.record, m.err } func TestResolveRecord(t *testing.T) { ctx := context.Background() t.Run("empty URI returns nil", func(t *testing.T) { result, err := ResolveRecord(ctx, &mockFetcher{}, "", "some.collection", func(v map[string]any, uri string) (*string, error) { s := "should not be called" return &s, nil }) if err != nil { t.Fatalf("unexpected error: %v", err) } if result != nil { t.Fatalf("expected nil, got %v", *result) } }) t.Run("invalid URI returns error", func(t *testing.T) { convert := func(v map[string]any, uri string) (*string, error) { s := "" return &s, nil } _, err := ResolveRecord(ctx, &mockFetcher{}, "not-a-uri", "some.collection", convert) if err == nil { t.Fatal("expected error for invalid URI") } }) t.Run("wrong collection returns error", func(t *testing.T) { convert := func(v map[string]any, uri string) (*string, error) { s := "val" return &s, nil } _, err := ResolveRecord(ctx, &mockFetcher{ record: &Record{URI: "at://did:plc:abc/social.example.wrong/rk1", Value: map[string]any{}}, }, "at://did:plc:abc/social.example.wrong/rk1", "social.example.expected", convert) if err == nil { t.Fatal("expected error for mismatched collection") } }) t.Run("fetcher error is propagated", func(t *testing.T) { fetchErr := errors.New("pds error") _, err := ResolveRecord(ctx, &mockFetcher{err: fetchErr}, "at://did:plc:abc/social.example.test/rk1", "social.example.test", func(v map[string]any, uri string) (*string, error) { s := "val" return &s, nil }) if err == nil { t.Fatal("expected error from fetcher") } }) t.Run("successful resolve and convert", func(t *testing.T) { type TestRecord struct { Name string } convert := func(v map[string]any, uri string) (*TestRecord, error) { name, _ := v["name"].(string) return &TestRecord{Name: name}, nil } result, err := ResolveRecord(ctx, &mockFetcher{ record: &Record{ URI: "at://did:plc:abc/social.example.test/rk1", Value: map[string]any{"name": "test-value"}, }, }, "at://did:plc:abc/social.example.test/rk1", "social.example.test", convert) if err != nil { t.Fatalf("unexpected error: %v", err) } if result == nil { t.Fatal("expected non-nil result") } if result.Name != "test-value" { t.Fatalf("expected Name=test-value, got %q", result.Name) } }) t.Run("convert error is propagated", func(t *testing.T) { convertErr := errors.New("convert failed") _, err := ResolveRecord(ctx, &mockFetcher{ record: &Record{ URI: "at://did:plc:abc/social.example.test/rk1", Value: map[string]any{}, }, }, "at://did:plc:abc/social.example.test/rk1", "social.example.test", func(v map[string]any, uri string) (*string, error) { return nil, convertErr }) if err == nil { t.Fatal("expected convert error") } }) }