1+ /*
2+ * Copyright (c) 2026 Metaform Systems, Inc.
3+ *
4+ * This program and the accompanying materials are made available under the
5+ * terms of the Apache License, Version 2.0 which is available at
6+ * https://www.apache.org/licenses/LICENSE-2.0
7+ *
8+ * SPDX-License-Identifier: Apache-2.0
9+ *
10+ * Contributors:
11+ * Metaform Systems, Inc. - initial API and implementation
12+ *
13+ */
14+
15+ package org .eclipse .edc .identityhub .defaults ;
16+
17+ import com .fasterxml .jackson .core .JsonProcessingException ;
18+ import com .fasterxml .jackson .databind .ObjectMapper ;
19+ import org .eclipse .edc .iam .verifiablecredentials .spi .model .CredentialFormat ;
20+ import org .eclipse .edc .iam .verifiablecredentials .spi .model .VerifiableCredential ;
21+ import org .eclipse .edc .iam .verifiablecredentials .spi .model .VerifiableCredentialContainer ;
22+ import org .eclipse .edc .identityhub .spi .verifiablecredentials .model .VcStatus ;
23+ import org .eclipse .edc .identityhub .spi .verifiablecredentials .model .VerifiableCredentialResource ;
24+ import org .eclipse .edc .jsonld .util .JacksonJsonLd ;
25+ import org .junit .jupiter .api .BeforeEach ;
26+ import org .junit .jupiter .api .Test ;
27+
28+ import java .time .Instant ;
29+ import java .util .List ;
30+ import java .util .Map ;
31+
32+ import static org .assertj .core .api .Assertions .assertThat ;
33+
34+ class CredentialResourceLookupTest {
35+
36+ private static final String VC_JSON = """
37+ {
38+ "@context": [
39+ "https://www.w3.org/2018/credentials/v1",
40+ "https://www.w3.org/2018/credentials/examples/v1",
41+ "https://example.org/2026/foo/bar"
42+ ],
43+ "id": "http://example.edu/credentials/1872",
44+ "type": [
45+ "VerifiableCredential",
46+ "AlumniCredential"
47+ ],
48+ "issuer": "https://example.edu/issuers/565049",
49+ "issuanceDate": "2010-01-01T19:23:24Z",
50+ "expirationDate": "2999-01-01T19:23:24Z",
51+ "credentialSubject": {
52+ "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
53+ "alumniOf": {
54+ "id": "did:example:c276e12ec21ebfeb1f712ebc6f1",
55+ "name": "Example University"
56+ }
57+ },
58+ "proof": {
59+ "type": "RsaSignature2018",
60+ "created": "2017-06-18T21:19:10Z",
61+ "proofPurpose": "assertionMethod",
62+ "verificationMethod": "https://example.edu/issuers/565049#key-1",
63+ "jws": "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..TCYt5X"
64+ }
65+ }
66+ """ ;
67+
68+ private final ObjectMapper objectMapper = JacksonJsonLd .createObjectMapper ();
69+ private CredentialResourceLookup lookup ;
70+
71+ @ BeforeEach
72+ void setUp () {
73+ lookup = new CredentialResourceLookup ();
74+ }
75+
76+ @ Test
77+ void getProperty_whenContextFieldRequested_shouldReplaceAtSymbol () {
78+ var resource = createTestResource ();
79+
80+ var result = lookup .getProperty ("verifiableCredential.credential.@context" , resource );
81+
82+ assertThat (result ).isNotNull ();
83+ }
84+
85+ @ Test
86+ void getProperty_whenInstantField_shouldReturnString () {
87+ var timestamp = Instant .parse ("2024-01-01T10:00:00Z" );
88+ var resource = VerifiableCredentialResource .Builder .newHolder ()
89+ .id ("test-id" )
90+ .issuerId ("test-issuer" )
91+ .holderId ("test-holder" )
92+ .build ();
93+ resource .setCredentialStatus (VcStatus .INITIAL );
94+
95+ var result = lookup .getProperty ("timeOfLastStatusUpdate" , resource );
96+
97+ assertThat (result ).isInstanceOf (String .class );
98+ }
99+
100+ @ Test
101+ void getProperty_whenRawVcField_shouldRemoveNewlines () {
102+ var resource = createTestResource ();
103+
104+ var result = lookup .getProperty ("verifiableCredential.rawVc" , resource );
105+
106+ assertThat (result ).isInstanceOf (String .class );
107+ assertThat ((String ) result ).doesNotContain ("\n " );
108+ }
109+
110+ @ Test
111+ void getProperty_whenCredentialSubjectClaim_shouldExtractFromClaims () {
112+ var resource = createTestResource ();
113+
114+ var result = lookup .getProperty ("verifiableCredential.credential.credentialSubject.alumniOf" , resource );
115+
116+ assertThat (result ).isNotNull ();
117+ assertThat (result ).isInstanceOf (Map .class );
118+ @ SuppressWarnings ("unchecked" )
119+ var alumniOf = (Map <String , Object >) result ;
120+ assertThat (alumniOf ).containsEntry ("name" , "Example University" );
121+ }
122+
123+ @ Test
124+ void getProperty_whenCredentialSubjectNestedClaim_shouldExtractNestedValue () {
125+ var resource = createTestResource ();
126+
127+ var result = lookup .getProperty ("verifiableCredential.credential.credentialSubject.alumniOf.name" , resource );
128+
129+ assertThat (result ).isEqualTo ("Example University" );
130+ }
131+
132+ @ Test
133+ void getProperty_whenCredentialSubjectClaimNotFound_shouldReturnNull () {
134+ var resource = createTestResource ();
135+
136+ var result = lookup .getProperty ("verifiableCredential.credential.credentialSubject.nonExistentField" , resource );
137+
138+ assertThat (result ).isNull ();
139+ }
140+
141+ @ Test
142+ void getProperty_whenCredentialSubjectId_shouldExtractId () {
143+ var resource = createTestResource ();
144+
145+ var result = lookup .getProperty ("verifiableCredential.credential.credentialSubject.id" , resource );
146+
147+ assertThat (result ).isInstanceOf (List .class );
148+ assertThat ((List <String >) result ).contains ("did:example:ebfeb1f712ebc6f1c276e12ec21" );
149+ }
150+
151+ @ Test
152+ void getProperty_whenStandardField_shouldReturnValue () {
153+ var resource = VerifiableCredentialResource .Builder .newHolder ()
154+ .id ("test-resource-id" )
155+ .issuerId ("test-issuer" )
156+ .holderId ("test-holder" )
157+ .build ();
158+
159+ var result = lookup .getProperty ("id" , resource );
160+
161+ assertThat (result ).isEqualTo ("test-resource-id" );
162+ }
163+
164+ @ Test
165+ void getProperty_whenNestedCredentialField_shouldReturnValue () {
166+ var resource = createTestResource ();
167+
168+ var result = lookup .getProperty ("verifiableCredential.credential.issuer" , resource );
169+
170+ assertThat (result ).isNotNull ();
171+ }
172+
173+ @ Test
174+ void getProperty_whenNonExistentField_shouldReturnNull () {
175+ var resource = createTestResource ();
176+
177+ var result = lookup .getProperty ("nonExistentField" , resource );
178+
179+ assertThat (result ).isNull ();
180+ }
181+
182+ @ Test
183+ void getProperty_whenCredentialType_shouldReturnTypeList () {
184+ var resource = createTestResource ();
185+
186+ var result = lookup .getProperty ("verifiableCredential.credential.type" , resource );
187+
188+ assertThat (result ).isInstanceOf (List .class );
189+ @ SuppressWarnings ("unchecked" )
190+ var types = (List <String >) result ;
191+ assertThat (types ).containsExactlyInAnyOrder ("VerifiableCredential" , "AlumniCredential" );
192+ }
193+
194+ private VerifiableCredentialResource createTestResource () {
195+ try {
196+ var credential = objectMapper .readValue (VC_JSON , VerifiableCredential .class );
197+ var container = new VerifiableCredentialContainer (VC_JSON , CredentialFormat .VC1_0_LD , credential );
198+
199+ return VerifiableCredentialResource .Builder .newHolder ()
200+ .id ("test-id" )
201+ .credential (container )
202+ .state (VcStatus .INITIAL )
203+ .issuerId ("test-issuer" )
204+ .holderId ("test-holder" )
205+ .build ();
206+ } catch (JsonProcessingException e ) {
207+ throw new RuntimeException (e );
208+ }
209+ }
210+ }
0 commit comments