From d54a18d7a396a340ccbd781a494a10cd17135539 Mon Sep 17 00:00:00 2001 From: Yurii Shynbuiev Date: Mon, 20 Jan 2025 17:38:22 +0700 Subject: [PATCH] test: add AnonCreds API e2e tests Signed-off-by: Yurii Shynbuiev --- tests/integration-tests/build.gradle.kts | 2 +- .../common/CreateCredentialOfferAPIVersion.kt | 102 +++++++++++++++++- .../test/kotlin/common/CredentialClaims.kt | 7 ++ .../kotlin/steps/credentials/AnoncredSteps.kt | 37 +++++++ .../steps/credentials/CredentialSteps.kt | 7 +- .../anoncred/issuance-refactoring.feature | 23 ++++ 6 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 tests/integration-tests/src/test/resources/features/credential/anoncred/issuance-refactoring.feature diff --git a/tests/integration-tests/build.gradle.kts b/tests/integration-tests/build.gradle.kts index 2c4973cc9e..7ed76b81cd 100644 --- a/tests/integration-tests/build.gradle.kts +++ b/tests/integration-tests/build.gradle.kts @@ -33,7 +33,7 @@ dependencies { testImplementation("io.ktor:ktor-server-netty:2.3.0") testImplementation("io.ktor:ktor-client-apache:2.3.0") // RestAPI client - testImplementation("org.hyperledger.identus:cloud-agent-client-kotlin:1.40.1-8363d1e") + testImplementation("org.hyperledger.identus:cloud-agent-client-kotlin:1.40.1-1766228") // Test helpers library testImplementation("io.iohk.atala:atala-automation:0.4.0") // Hoplite for configuration diff --git a/tests/integration-tests/src/test/kotlin/common/CreateCredentialOfferAPIVersion.kt b/tests/integration-tests/src/test/kotlin/common/CreateCredentialOfferAPIVersion.kt index a081747eca..d5c2e566b9 100644 --- a/tests/integration-tests/src/test/kotlin/common/CreateCredentialOfferAPIVersion.kt +++ b/tests/integration-tests/src/test/kotlin/common/CreateCredentialOfferAPIVersion.kt @@ -5,7 +5,7 @@ import java.util.UUID enum class CreateCredentialOfferAPIVersion { V0 { - override fun buildCredentialOfferRequest( + override fun buildJWTCredentialOfferRequest( credentialType: CredentialType, did: String, assertionKey: String, @@ -23,10 +23,46 @@ enum class CreateCredentialOfferAPIVersion { credentialFormat = credentialType.format, automaticIssuance = false, ) + + override fun buildSDJWTCredentialOfferRequest( + credentialType: CredentialType, + did: String, + assertionKey: String, + schemaUrl: String?, + claims: Map, + connectionId: UUID, + validityPeriod: Double?, + ): CreateIssueCredentialRecordRequest = CreateIssueCredentialRecordRequest( + schemaId = schemaUrl, + claims = claims, + issuingDID = did, + issuingKid = assertionKey, + connectionId = connectionId, + validityPeriod = validityPeriod ?: 3600.0, + credentialFormat = credentialType.format, + automaticIssuance = false, + ) + + override fun buildAnonCredsCredentialOfferRequest( + credentialType: CredentialType, + did: String, + credentialDefinitionId: UUID, + claims: Map, + connectionId: UUID, + validityPeriod: Double?, + ) = CreateIssueCredentialRecordRequest( + credentialDefinitionId = credentialDefinitionId, + claims = claims, + issuingDID = did, + connectionId = connectionId, + validityPeriod = validityPeriod ?: 3600.0, + credentialFormat = credentialType.format, + automaticIssuance = false, + ) }, V1 { - override fun buildCredentialOfferRequest( + override fun buildJWTCredentialOfferRequest( credentialType: CredentialType, did: String, assertionKey: String, @@ -53,8 +89,25 @@ enum class CreateCredentialOfferAPIVersion { validityPeriod = validityPeriod ?: 3600.0, ) } else { - null + throw IllegalArgumentException("Unsupported credential type: $credentialType") }, + ) + + override fun buildSDJWTCredentialOfferRequest( + credentialType: CredentialType, + did: String, + assertionKey: String, + schemaUrl: String?, + claims: Map, + connectionId: UUID, + validityPeriod: Double?, + ): CreateIssueCredentialRecordRequest = CreateIssueCredentialRecordRequest( + issuingKid = assertionKey, + connectionId = connectionId, + credentialFormat = credentialType.format, + automaticIssuance = false, + claims = null, + issuingDID = null, sdJwtVcPropertiesV1 = if (credentialType == CredentialType.SD_JWT_VCDM_1_1) { SDJWTVCPropertiesV1( credentialSchema = CredentialSchemaRef( @@ -67,13 +120,43 @@ enum class CreateCredentialOfferAPIVersion { validityPeriod = validityPeriod ?: 3600.0, ) } else { - null + throw IllegalArgumentException("Unsupported credential type: $credentialType") }, ) + + override fun buildAnonCredsCredentialOfferRequest( + credentialType: CredentialType, + did: String, + credentialDefinitionId: UUID, + claims: Map, + connectionId: UUID, + validityPeriod: Double? + ) = CreateIssueCredentialRecordRequest( + connectionId = connectionId, + credentialFormat = credentialType.format, + automaticIssuance = false, + anoncredsVcPropertiesV1 = + AnonCredsVCPropertiesV1( + issuingDID = did, + credentialDefinitionId = credentialDefinitionId, + claims = claims, + validityPeriod = validityPeriod ?: 3600.0, + ) + ) }, ; - abstract fun buildCredentialOfferRequest( + abstract fun buildJWTCredentialOfferRequest( + credentialType: CredentialType, + did: String, + assertionKey: String, + schemaUrl: String?, + claims: Map, + connectionId: UUID, + validityPeriod: Double? = null, + ): CreateIssueCredentialRecordRequest + + abstract fun buildSDJWTCredentialOfferRequest( credentialType: CredentialType, did: String, assertionKey: String, @@ -82,4 +165,13 @@ enum class CreateCredentialOfferAPIVersion { connectionId: UUID, validityPeriod: Double? = null, ): CreateIssueCredentialRecordRequest + + abstract fun buildAnonCredsCredentialOfferRequest( + credentialType: CredentialType, + did: String, + credentialDefinitionId: UUID, + claims: Map, + connectionId: UUID, + validityPeriod: Double? = null, + ): CreateIssueCredentialRecordRequest } diff --git a/tests/integration-tests/src/test/kotlin/common/CredentialClaims.kt b/tests/integration-tests/src/test/kotlin/common/CredentialClaims.kt index dc11f219ac..97221838b8 100644 --- a/tests/integration-tests/src/test/kotlin/common/CredentialClaims.kt +++ b/tests/integration-tests/src/test/kotlin/common/CredentialClaims.kt @@ -13,6 +13,13 @@ enum class CredentialClaims { "lastName" to "Doe", ) }, + ANONCREDS_STUDENT_CLAIMS { + override val claims: Map = linkedMapOf( + "name" to "Bob", + "age" to "21", + "sex" to "M", + ) + } ; abstract val claims: Map diff --git a/tests/integration-tests/src/test/kotlin/steps/credentials/AnoncredSteps.kt b/tests/integration-tests/src/test/kotlin/steps/credentials/AnoncredSteps.kt index 2cddddb2b6..e8c2b71286 100644 --- a/tests/integration-tests/src/test/kotlin/steps/credentials/AnoncredSteps.kt +++ b/tests/integration-tests/src/test/kotlin/steps/credentials/AnoncredSteps.kt @@ -1,5 +1,7 @@ package steps.credentials +import common.CreateCredentialOfferAPIVersion +import common.CredentialType import interactions.Post import interactions.body import io.cucumber.java.en.When @@ -47,4 +49,39 @@ class AnoncredSteps { issuer.remember("thid", credentialRecord.thid) holder.remember("thid", credentialRecord.thid) } + + @When("{actor} sends the prepared anoncreds credential offer to {actor}") + fun issuerSendsThePreparedAnonCredsOfferToHolder(issuer: Actor, holder: Actor) { + val api = issuer.recall("currentAPI") + val credentialType = issuer.recall("currentCredentialType") + val did = issuer.recall("currentDID") + val claims = issuer.recall>("currentClaims") + val connectionId = issuer.recall("connection-with-${holder.name}").connectionId + val credentialDefinitionId = issuer.recall("anoncredsCredentialDefinition").guid + + val request = api.buildAnonCredsCredentialOfferRequest(credentialType, did, credentialDefinitionId, claims, connectionId) + + val credentialOfferRequest = CreateIssueCredentialRecordRequest( + credentialDefinitionId = issuer.recall("anoncredsCredentialDefinition").guid, + claims = linkedMapOf( + "name" to "Bob", + "age" to "21", + "sex" to "M", + ), + issuingDID = issuer.recall("shortFormDid"), + connectionId = issuer.recall("connection-with-${holder.name}").connectionId, + validityPeriod = 3600.0, + credentialFormat = "AnonCreds", + automaticIssuance = false, + ) + + issuer.attemptsTo( + Post.to("/issue-credentials/credential-offers").body(credentialOfferRequest), + Ensure.thatTheLastResponse().statusCode().isEqualTo(SC_CREATED), + ) + + val credentialRecord = SerenityRest.lastResponse().get() + issuer.remember("thid", credentialRecord.thid) + holder.remember("thid", credentialRecord.thid) + } } diff --git a/tests/integration-tests/src/test/kotlin/steps/credentials/CredentialSteps.kt b/tests/integration-tests/src/test/kotlin/steps/credentials/CredentialSteps.kt index 1ad3fa1c07..4692c37a2f 100644 --- a/tests/integration-tests/src/test/kotlin/steps/credentials/CredentialSteps.kt +++ b/tests/integration-tests/src/test/kotlin/steps/credentials/CredentialSteps.kt @@ -78,6 +78,7 @@ class CredentialSteps { val api = issuer.recall("currentAPI") val credentialType = issuer.recall("currentCredentialType") val did = issuer.recall("currentDID") + val assertionKey = issuer.recall("currentAssertionKey") val schema = issuer.recall("currentSchema") val schemaGuid = issuer.recall(schema.name) @@ -89,7 +90,11 @@ class CredentialSteps { "${issuer.recall("baseUrl")}/schema-registry/schemas/$it" } - val credentialOfferRequest = api.buildCredentialOfferRequest(credentialType, did, assertionKey, schemaUrl!!, claims, connectionId) + val credentialOfferRequest = when (credentialType) { + CredentialType.JWT_VCDM_1_1 -> api.buildJWTCredentialOfferRequest(credentialType, did, assertionKey, schemaUrl!!, claims, connectionId) + CredentialType.SD_JWT_VCDM_1_1 -> api.buildSDJWTCredentialOfferRequest(credentialType, did, assertionKey, schemaUrl!!, claims, connectionId) + else -> throw IllegalArgumentException("Unsupported credential type: $credentialType") + } issuer.attemptsTo( Post.to("/issue-credentials/credential-offers").body(credentialOfferRequest), diff --git a/tests/integration-tests/src/test/resources/features/credential/anoncred/issuance-refactoring.feature b/tests/integration-tests/src/test/resources/features/credential/anoncred/issuance-refactoring.feature new file mode 100644 index 0000000000..316ffba424 --- /dev/null +++ b/tests/integration-tests/src/test/resources/features/credential/anoncred/issuance-refactoring.feature @@ -0,0 +1,23 @@ +@anoncred @issuance @refactoring +Feature: Issue Anoncreds credential using different REST API request versions + + Background: + Given Issuer and Holder have an existing connection + And Issuer has a published DID for 'ANONCRED' + And Issuer has an anoncred schema definition + And Holder has an unpublished DID for 'ANONCRED' + + Scenario Outline: Issuing jwt credential using different API version + When Issuer prepares the credential in 'ANONCREDS_V1' format using the '' API + And Issuer prepares to use a 'short' form of DID with key id 'assertion-1' + And Issuer prepares the claims '' for the credential + And Issuer sends the prepared anoncreds credential offer to Holder + And Holder receives the credential offer + And Holder accepts anoncred credential offer + And Issuer issues the credential + Then Holder receives the issued credential + Examples: + | createCredentialOfferApiVersion | claims | + | V0 | ANONCREDS_STUDENT_CLAIMS | + | V1 | ANONCREDS_STUDENT_CLAIMS | +