diff options
Diffstat (limited to 'internal/api/plc_compatibility_test.go')
| -rw-r--r-- | internal/api/plc_compatibility_test.go | 122 |
1 files changed, 109 insertions, 13 deletions
diff --git a/internal/api/plc_compatibility_test.go b/internal/api/plc_compatibility_test.go index fe7ee82..45428d8 100644 --- a/internal/api/plc_compatibility_test.go +++ b/internal/api/plc_compatibility_test.go @@ -21,25 +21,55 @@ import ( "time" ) -func TestPLCCompatibilityGetDIDMatchesStoredDocument(t *testing.T) { - ts, store, _, cleanup := newCompatibilityServer(t) +func TestPLCCompatibilityGetDIDShape(t *testing.T) { + ts, _, _, cleanup := newCompatibilityServer(t) defer cleanup() - state, ok, err := store.GetState("did:plc:alice") + resp, err := http.Get(ts.URL + "/did:plc:alice") if err != nil { - t.Fatalf("get state: %v", err) + t.Fatalf("get did: %v", err) } - if !ok { - t.Fatalf("state not found") + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + t.Fatalf("status: got %d want 200", resp.StatusCode) } - resp, err := http.Get(ts.URL + "/did:plc:alice") + if got := resp.Header.Get("Content-Type"); !strings.Contains(got, "application/did+ld+json") { + t.Fatalf("content-type mismatch: %s", got) + } + + var body map[string]any + + if err := json.NewDecoder(resp.Body).Decode(&body); err != nil { + t.Fatalf("decode body: %v", err) + } + + if _, ok := body["@context"].([]any); !ok { + t.Fatalf("missing or invalid @context: %#v", body["@context"]) + } + + if got, _ := body["id"].(string); got != "did:plc:alice" { + t.Fatalf("id mismatch: got %q want %q", got, "did:plc:alice") + } + + if _, ok := body["authentication"]; ok { + t.Fatalf("unexpected authentication field in compatibility did document") + } +} + +func TestPLCCompatibilityGetDataShape(t *testing.T) { + ts, _, _, cleanup := newCompatibilityServer(t) + + defer cleanup() + + resp, err := http.Get(ts.URL + "/did:plc:alice/data") if err != nil { - t.Fatalf("get did: %v", err) + t.Fatalf("get data: %v", err) } defer resp.Body.Close() @@ -48,14 +78,34 @@ func TestPLCCompatibilityGetDIDMatchesStoredDocument(t *testing.T) { t.Fatalf("status: got %d want 200", resp.StatusCode) } - if got := resp.Header.Get("Content-Type"); !strings.Contains(got, "application/did+ld+json") { - t.Fatalf("content-type mismatch: %s", got) + var body map[string]any + + if err := json.NewDecoder(resp.Body).Decode(&body); err != nil { + t.Fatalf("decode body: %v", err) } - body, _ := io.ReadAll(resp.Body) + required := []string{"did", "verificationMethods", "rotationKeys", "alsoKnownAs", "services"} + + for _, key := range required { + if _, ok := body[key]; !ok { + t.Fatalf("missing key %q in /data response", key) + } + } - if strings.TrimSpace(string(body)) != strings.TrimSpace(string(state.DIDDocument)) { - t.Fatalf("did document mismatch\n got: %s\nwant: %s", string(body), string(state.DIDDocument)) + if _, ok := body["verificationMethods"].(map[string]any); !ok { + t.Fatalf("verificationMethods has wrong type: %#v", body["verificationMethods"]) + } + + if _, ok := body["rotationKeys"].([]any); !ok { + t.Fatalf("rotationKeys has wrong type: %#v", body["rotationKeys"]) + } + + if _, ok := body["alsoKnownAs"].([]any); !ok { + t.Fatalf("alsoKnownAs has wrong type: %#v", body["alsoKnownAs"]) + } + + if _, ok := body["services"].(map[string]any); !ok { + t.Fatalf("services has wrong type: %#v", body["services"]) } } @@ -164,6 +214,20 @@ func TestPLCCompatibilityPostIsMethodNotAllowed(t *testing.T) { if allow := resp.Header.Get("Allow"); allow != http.MethodGet { t.Fatalf("allow header mismatch: got %q want %q", allow, http.MethodGet) } + + var body map[string]any + + if err := json.NewDecoder(resp.Body).Decode(&body); err != nil { + t.Fatalf("decode body: %v", err) + } + + if _, ok := body["message"].(string); !ok { + t.Fatalf("expected PLC-style message field, got: %v", body) + } + + if _, ok := body["error"]; ok { + t.Fatalf("unexpected internal error field in compatibility response: %v", body) + } } func TestPLCCompatibilityNoVerificationMetadataLeak(t *testing.T) { @@ -206,6 +270,38 @@ func TestPLCCompatibilityProofEndpointStillWorks(t *testing.T) { } } +func TestPLCCompatibilityNotFoundUsesPLCErrorShape(t *testing.T) { + ts, _, _, cleanup := newCompatibilityServer(t) + + defer cleanup() + + resp, err := http.Get(ts.URL + "/did:plc:not-registered") + + if err != nil { + t.Fatalf("get missing did: %v", err) + } + + defer resp.Body.Close() + + if resp.StatusCode != http.StatusNotFound { + t.Fatalf("status: got %d want 404", resp.StatusCode) + } + + var body map[string]any + + if err := json.NewDecoder(resp.Body).Decode(&body); err != nil { + t.Fatalf("decode body: %v", err) + } + + if _, ok := body["message"].(string); !ok { + t.Fatalf("expected message field for 404, got: %v", body) + } + + if _, ok := body["error"]; ok { + t.Fatalf("unexpected error field in compatibility 404 body: %v", body) + } +} + func newCompatibilityServer(t *testing.T) (*httptest.Server, *storage.PebbleStore, []types.ExportRecord, func()) { t.Helper() |