From 7b4a9c1f8e1cb0b16d2da9b57e80d41cb2b5d478 Mon Sep 17 00:00:00 2001 From: Allain Magyar Date: Wed, 2 Oct 2024 16:00:34 -0300 Subject: [PATCH] test: add oid4vci negative scenario tests (#1380) Signed-off-by: Allain Magyar Signed-off-by: Hyperledger Bot Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Hyperledger Bot --- tests/integration-tests/README.md | 4 - .../src/test/kotlin/config/services/Agent.kt | 1 - .../test/kotlin/config/services/Keycloak.kt | 1 - .../kotlin/config/services/ServiceBase.kt | 5 +- .../src/test/kotlin/config/services/Vault.kt | 1 - .../config/services/VerifiableDataRegistry.kt | 1 - .../steps/oid4vci/IssueCredentialSteps.kt | 18 ++- .../oid4vci/ManageCredentialConfigSteps.kt | 125 ++++++++++++++--- .../kotlin/steps/oid4vci/ManageIssuerSteps.kt | 129 +++++++++++++++--- .../features/oid4vci/issue_jwt.feature | 6 +- .../oid4vci/manage_credential_config.feature | 31 ++++- .../features/oid4vci/manage_issuer.feature | 27 +++- 12 files changed, 280 insertions(+), 69 deletions(-) diff --git a/tests/integration-tests/README.md b/tests/integration-tests/README.md index 2fef57bf71..4b0e925bcd 100644 --- a/tests/integration-tests/README.md +++ b/tests/integration-tests/README.md @@ -116,10 +116,6 @@ The configuration files are divided into the following sections: * `agents`: contains the configuration for the agents (ICA) that will be started. By default, all agents will be destroyed after the test run is finished. * `roles`: contains the configuration for the roles (Issuer, Holder, Verifier, Admin). A role can be assigned to one or more agents that we set in `agents` section or already running locally or in the cloud. -> You could keep services and agents running for debugging purposes -> by specifying `keep_running = true` for the service or agent -> in the configuration file and setting `TESTCONTAINERS_RYUK_DISABLED` variable to `true`. - Please, check [test/resources/configs/basic.conf](./src/test/resources/configs/basic.conf) for a quick example of a basic configuration. You could explore the `configs` directory for more complex examples. diff --git a/tests/integration-tests/src/test/kotlin/config/services/Agent.kt b/tests/integration-tests/src/test/kotlin/config/services/Agent.kt index f4d7cc0962..a4e97a603d 100644 --- a/tests/integration-tests/src/test/kotlin/config/services/Agent.kt +++ b/tests/integration-tests/src/test/kotlin/config/services/Agent.kt @@ -16,7 +16,6 @@ data class Agent( @ConfigAlias("prism_node") val prismNode: VerifiableDataRegistry?, val keycloak: Keycloak?, val vault: Vault?, - @ConfigAlias("keep_running") override val keepRunning: Boolean = false, ) : ServiceBase() { override val logServices = listOf("identus-cloud-agent") diff --git a/tests/integration-tests/src/test/kotlin/config/services/Keycloak.kt b/tests/integration-tests/src/test/kotlin/config/services/Keycloak.kt index d73a8814b5..86027fe3ad 100644 --- a/tests/integration-tests/src/test/kotlin/config/services/Keycloak.kt +++ b/tests/integration-tests/src/test/kotlin/config/services/Keycloak.kt @@ -17,7 +17,6 @@ data class Keycloak( val realm: String = "atala-demo", @ConfigAlias("client_id") val clientId: String = "cloud-agent", @ConfigAlias("client_secret") val clientSecret: String = "cloud-agent-secret", - @ConfigAlias("keep_running") override val keepRunning: Boolean = false, @ConfigAlias("compose_file") val keycloakComposeFile: String = "src/test/resources/containers/keycloak.yml", @ConfigAlias("logger_name") val loggerName: String = "keycloak", @ConfigAlias("extra_envs") val extraEnvs: Map = emptyMap(), diff --git a/tests/integration-tests/src/test/kotlin/config/services/ServiceBase.kt b/tests/integration-tests/src/test/kotlin/config/services/ServiceBase.kt index 8c598b61d6..9c2483084a 100644 --- a/tests/integration-tests/src/test/kotlin/config/services/ServiceBase.kt +++ b/tests/integration-tests/src/test/kotlin/config/services/ServiceBase.kt @@ -15,7 +15,6 @@ abstract class ServiceBase : Startable { } abstract val container: ComposeContainer - abstract val keepRunning: Boolean open val logServices: List = emptyList() private val logWriters: MutableList = mutableListOf() @@ -41,8 +40,6 @@ abstract class ServiceBase : Startable { logWriters.forEach { it.close() } - if (!keepRunning) { - container.stop() - } + container.stop() } } diff --git a/tests/integration-tests/src/test/kotlin/config/services/Vault.kt b/tests/integration-tests/src/test/kotlin/config/services/Vault.kt index 85f1a02b27..a14a44620b 100644 --- a/tests/integration-tests/src/test/kotlin/config/services/Vault.kt +++ b/tests/integration-tests/src/test/kotlin/config/services/Vault.kt @@ -14,7 +14,6 @@ import java.io.File data class Vault( @ConfigAlias("http_port") val httpPort: Int, @ConfigAlias("vault_auth_type") val authType: VaultAuthType = VaultAuthType.APP_ROLE, - @ConfigAlias("keep_running") override val keepRunning: Boolean = false, ) : ServiceBase() { private val logger = Logger.get() override val logServices: List = listOf("vault") diff --git a/tests/integration-tests/src/test/kotlin/config/services/VerifiableDataRegistry.kt b/tests/integration-tests/src/test/kotlin/config/services/VerifiableDataRegistry.kt index 2997f567cc..f4fbcdba66 100644 --- a/tests/integration-tests/src/test/kotlin/config/services/VerifiableDataRegistry.kt +++ b/tests/integration-tests/src/test/kotlin/config/services/VerifiableDataRegistry.kt @@ -8,7 +8,6 @@ import java.io.File data class VerifiableDataRegistry( @ConfigAlias("http_port") val httpPort: Int, val version: String, - @ConfigAlias("keep_running") override val keepRunning: Boolean = false, ) : ServiceBase() { override val logServices: List = listOf("prism-node") private val vdrComposeFile = "src/test/resources/containers/vdr.yml" diff --git a/tests/integration-tests/src/test/kotlin/steps/oid4vci/IssueCredentialSteps.kt b/tests/integration-tests/src/test/kotlin/steps/oid4vci/IssueCredentialSteps.kt index 3cd1873033..6a2e906361 100644 --- a/tests/integration-tests/src/test/kotlin/steps/oid4vci/IssueCredentialSteps.kt +++ b/tests/integration-tests/src/test/kotlin/steps/oid4vci/IssueCredentialSteps.kt @@ -5,6 +5,7 @@ import com.nimbusds.jose.JWSAlgorithm import com.nimbusds.jose.jwk.JWK import eu.europa.ec.eudi.openid4vci.* import interactions.Post +import interactions.body import io.cucumber.java.en.Then import io.cucumber.java.en.When import io.iohk.atala.automation.extensions.get @@ -40,16 +41,13 @@ class IssueCredentialSteps { issuer.recall("longFormDid") } issuer.attemptsTo( - Post.to("/oid4vci/issuers/${credentialIssuer.id}/credential-offers") - .with { - it.body( - CredentialOfferRequest( - credentialConfigurationId = configurationId, - issuingDID = did, - claims = claims, - ), - ) - }, + Post.to("/oid4vci/issuers/${credentialIssuer.id}/credential-offers").body( + CredentialOfferRequest( + credentialConfigurationId = configurationId, + issuingDID = did, + claims = claims, + ), + ), Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_CREATED), ) val offerUri = SerenityRest.lastResponse().get().credentialOffer diff --git a/tests/integration-tests/src/test/kotlin/steps/oid4vci/ManageCredentialConfigSteps.kt b/tests/integration-tests/src/test/kotlin/steps/oid4vci/ManageCredentialConfigSteps.kt index 470babb703..8a53c311f9 100644 --- a/tests/integration-tests/src/test/kotlin/steps/oid4vci/ManageCredentialConfigSteps.kt +++ b/tests/integration-tests/src/test/kotlin/steps/oid4vci/ManageCredentialConfigSteps.kt @@ -1,20 +1,37 @@ package steps.oid4vci +import com.google.gson.JsonObject import common.CredentialSchema -import interactions.* -import io.cucumber.java.en.* +import interactions.Delete +import interactions.Get +import interactions.Post +import interactions.body +import io.cucumber.java.en.Given +import io.cucumber.java.en.Then +import io.cucumber.java.en.When import io.iohk.atala.automation.extensions.get import io.iohk.atala.automation.serenity.ensure.Ensure import net.serenitybdd.rest.SerenityRest import net.serenitybdd.screenplay.Actor import org.apache.http.HttpStatus -import org.hyperledger.identus.client.models.* +import org.apache.http.HttpStatus.SC_OK +import org.hyperledger.identus.client.models.CreateCredentialConfigurationRequest +import org.hyperledger.identus.client.models.CredentialFormat +import org.hyperledger.identus.client.models.CredentialIssuer +import org.hyperledger.identus.client.models.IssuerMetadata +import java.util.UUID class ManageCredentialConfigSteps { @Given("{actor} has {string} credential configuration created from {}") fun issuerHasExistingCredentialConfig(issuer: Actor, configurationId: String, schema: CredentialSchema) { ManageIssuerSteps().issuerHasExistingCredentialIssuer(issuer) - issuerCreateCredentialConfiguration(issuer, schema, configurationId) + val credentialIssuer = issuer.recall("oid4vciCredentialIssuer") + issuer.attemptsTo( + Get("/oid4vci/issuers/${credentialIssuer.id}/credential-configurations/$configurationId"), + ) + if (SerenityRest.lastResponse().statusCode != SC_OK) { + issuerCreateCredentialConfiguration(issuer, schema, configurationId) + } } @When("{actor} uses {} to create a credential configuration {string}") @@ -22,17 +39,15 @@ class ManageCredentialConfigSteps { val credentialIssuer = issuer.recall("oid4vciCredentialIssuer") val schemaGuid = issuer.recall(schema.name) val baseUrl = issuer.recall("baseUrl") + issuer.attemptsTo( - Post.to("/oid4vci/issuers/${credentialIssuer.id}/credential-configurations") - .with { - it.body( - CreateCredentialConfigurationRequest( - configurationId = configurationId, - format = CredentialFormat.JWT_VC_JSON, - schemaId = "$baseUrl/schema-registry/schemas/$schemaGuid/schema", - ), - ) - }, + Post.to("/oid4vci/issuers/${credentialIssuer.id}/credential-configurations").body( + CreateCredentialConfigurationRequest( + configurationId = configurationId, + format = CredentialFormat.JWT_VC_JSON, + schemaId = "$baseUrl/schema-registry/schemas/$schemaGuid/schema", + ), + ), Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_CREATED), ) } @@ -42,7 +57,75 @@ class ManageCredentialConfigSteps { val credentialIssuer = issuer.recall("oid4vciCredentialIssuer") issuer.attemptsTo( Delete("/oid4vci/issuers/${credentialIssuer.id}/credential-configurations/$configurationId"), - Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_OK), + Ensure.thatTheLastResponse().statusCode().isEqualTo(SC_OK), + ) + } + + @When("{actor} deletes a non existent {} credential configuration") + fun issuerDeletesANonExistentCredentialConfiguration(issuer: Actor, configurationId: String) { + val credentialIssuer = issuer.recall("oid4vciCredentialIssuer") + issuer.attemptsTo( + Delete("/oid4vci/issuers/${credentialIssuer.id}/credential-configurations/$configurationId"), + ) + } + + @When("{actor} creates a new credential configuration request") + fun issuerCreatesANewConfigurationRequest(issuer: Actor) { + val credentialConfiguration = JsonObject() + issuer.remember("credentialConfiguration", credentialConfiguration) + } + + @When("{actor} uses {} issuer id for credential configuration") + fun issuerUsesIssuerId(issuer: Actor, issuerId: String) { + if (issuerId == "existing") { + val credentialIssuer = issuer.recall("oid4vciCredentialIssuer") + issuer.remember("credentialConfigurationId", credentialIssuer.id) + } else if (issuerId == "wrong") { + issuer.remember("credentialConfigurationId", UUID.randomUUID().toString()) + } + } + + @When("{actor} adds '{}' configuration id for credential configuration request") + fun issuerAddsConfigurationIdToCredentialConfigurationRequest(issuer: Actor, configurationId: String) { + val credentialIssuer = issuer.recall("credentialConfiguration") + val configurationIdProperty = if (configurationId == "null") { + null + } else { + configurationId + } + credentialIssuer.addProperty("configurationId", configurationIdProperty) + } + + @When("{actor} adds '{}' format for credential configuration request") + fun issuerAddsFormatToCredentialConfigurationRequest(issuer: Actor, format: String) { + val credentialIssuer = issuer.recall("credentialConfiguration") + val formatProperty = if (format == "null") { + null + } else { + format + } + credentialIssuer.addProperty("format", formatProperty) + } + + @When("{actor} adds '{}' schemaId for credential configuration request") + fun issuerAddsSchemaIdToCredentialConfigurationRequest(issuer: Actor, schema: String) { + val credentialIssuer = issuer.recall("credentialConfiguration") + val schemaIdProperty = if (schema == "null") { + null + } else { + val baseUrl = issuer.recall("baseUrl") + val schemaGuid = issuer.recall(schema) + "$baseUrl/schema-registry/schemas/$schemaGuid/schema" + } + credentialIssuer.addProperty("schemaId", schemaIdProperty) + } + + @When("{actor} sends the create a credential configuration request") + fun issuerSendsTheCredentialConfigurationRequest(issuer: Actor) { + val credentialConfiguration = issuer.recall("credentialConfiguration") + val credentialIssuerId = issuer.recall("credentialConfigurationId").toString() + issuer.attemptsTo( + Post.to("/oid4vci/issuers/$credentialIssuerId/credential-configurations").body(credentialConfiguration), ) } @@ -51,7 +134,7 @@ class ManageCredentialConfigSteps { val credentialIssuer = issuer.recall("oid4vciCredentialIssuer") issuer.attemptsTo( Get("/oid4vci/issuers/${credentialIssuer.id}/.well-known/openid-credential-issuer"), - Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_OK), + Ensure.thatTheLastResponse().statusCode().isEqualTo(SC_OK), ) val metadata = SerenityRest.lastResponse().get() val credConfig = metadata.credentialConfigurationsSupported[configurationId]!! @@ -65,11 +148,19 @@ class ManageCredentialConfigSteps { val credentialIssuer = issuer.recall("oid4vciCredentialIssuer") issuer.attemptsTo( Get("/oid4vci/issuers/${credentialIssuer.id}/.well-known/openid-credential-issuer"), - Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_OK), + Ensure.thatTheLastResponse().statusCode().isEqualTo(SC_OK), ) val metadata = SerenityRest.lastResponse().get() issuer.attemptsTo( Ensure.that(metadata.credentialConfigurationsSupported.keys).doesNotContain(configurationId), ) } + + @Then("{actor} should see that create credential configuration has failed with '{}' status code and '{}' detail") + fun issuerShouldSeeCredentialConfigurationRequestHasFailed(issuer: Actor, statusCode: Int, errorDetail: String) { + issuer.attemptsTo( + Ensure.thatTheLastResponse().statusCode().isEqualTo(statusCode), + Ensure.that(SerenityRest.lastResponse().body.asString()).contains(errorDetail), + ) + } } diff --git a/tests/integration-tests/src/test/kotlin/steps/oid4vci/ManageIssuerSteps.kt b/tests/integration-tests/src/test/kotlin/steps/oid4vci/ManageIssuerSteps.kt index 7db69f0b41..e78408078f 100644 --- a/tests/integration-tests/src/test/kotlin/steps/oid4vci/ManageIssuerSteps.kt +++ b/tests/integration-tests/src/test/kotlin/steps/oid4vci/ManageIssuerSteps.kt @@ -1,7 +1,15 @@ package steps.oid4vci -import interactions.* -import io.cucumber.java.en.* +import com.google.gson.GsonBuilder +import com.google.gson.JsonObject +import interactions.Delete +import interactions.Get +import interactions.Patch +import interactions.Post +import interactions.body +import io.cucumber.java.en.Given +import io.cucumber.java.en.Then +import io.cucumber.java.en.When import io.iohk.atala.automation.extensions.get import io.iohk.atala.automation.serenity.ensure.Ensure import net.serenitybdd.rest.SerenityRest @@ -9,16 +17,26 @@ import net.serenitybdd.screenplay.Actor import org.apache.http.HttpStatus import org.apache.http.HttpStatus.SC_CREATED import org.apache.http.HttpStatus.SC_OK -import org.hyperledger.identus.client.models.* +import org.hyperledger.identus.client.models.AuthorizationServer +import org.hyperledger.identus.client.models.CreateCredentialIssuerRequest +import org.hyperledger.identus.client.models.CredentialIssuer +import org.hyperledger.identus.client.models.CredentialIssuerPage +import org.hyperledger.identus.client.models.IssuerMetadata +import org.hyperledger.identus.client.models.PatchAuthorizationServer +import org.hyperledger.identus.client.models.PatchCredentialIssuerRequest class ManageIssuerSteps { - private val UPDATE_AUTH_SERVER_URL = "http://example.com" - private val UPDATE_AUTH_SERVER_CLIENT_ID = "foo" - private val UPDATE_AUTH_SERVER_CLIENT_SECRET = "bar" + companion object { + private const val UPDATE_AUTH_SERVER_URL = "http://example.com" + private const val UPDATE_AUTH_SERVER_CLIENT_ID = "foo" + private const val UPDATE_AUTH_SERVER_CLIENT_SECRET = "bar" + } @Given("{actor} has an existing oid4vci issuer") fun issuerHasExistingCredentialIssuer(issuer: Actor) { - issuerCreateCredentialIssuer(issuer) + if (!issuer.recallAll().containsKey("oid4vciCredentialIssuer")) { + issuerCreateCredentialIssuer(issuer) + } } @When("{actor} creates an oid4vci issuer") @@ -69,19 +87,29 @@ class ManageIssuerSteps { fun issuerUpdateCredentialIssuer(issuer: Actor) { val credentialIssuer = issuer.recall("oid4vciCredentialIssuer") issuer.attemptsTo( - Patch.to("/oid4vci/issuers/${credentialIssuer.id}") - .with { - it.body( - PatchCredentialIssuerRequest( - authorizationServer = PatchAuthorizationServer( - url = UPDATE_AUTH_SERVER_URL, - clientId = UPDATE_AUTH_SERVER_CLIENT_ID, - clientSecret = UPDATE_AUTH_SERVER_CLIENT_SECRET, - ), - ), - ) - }, - Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_OK), + Patch.to("/oid4vci/issuers/${credentialIssuer.id}").body( + PatchCredentialIssuerRequest( + authorizationServer = PatchAuthorizationServer( + url = UPDATE_AUTH_SERVER_URL, + clientId = UPDATE_AUTH_SERVER_CLIENT_ID, + clientSecret = UPDATE_AUTH_SERVER_CLIENT_SECRET, + ), + ), + ), + Ensure.thatTheLastResponse().statusCode().isEqualTo(SC_OK), + ) + } + + @When("{actor} tries to update the oid4vci issuer '{}' property using '{}' value") + fun issuerTriesToUpdateTheOID4VCIIssuer(issuer: Actor, property: String, value: String) { + val credentialIssuer = issuer.recall("oid4vciCredentialIssuer") + val body = JsonObject() + val propertyValue = if (value == "null") { null } else { value } + body.addProperty(property, propertyValue) + + val gson = GsonBuilder().serializeNulls().create() + issuer.attemptsTo( + Patch.to("/oid4vci/issuers/${credentialIssuer.id}").body(gson.toJson(body)), ) } @@ -94,6 +122,60 @@ class ManageIssuerSteps { ) } + @When("{actor} tries to create oid4vci issuer with '{}', '{}', '{}' and '{}'") + fun issuerTriesToCreateOIDCIssuer( + issuer: Actor, + id: String, + url: String, + clientId: String, + clientSecret: String, + ) { + val idProperty = if (id == "null") { + null + } else { + id + } + val urlProperty = if (url == "null") { + null + } else { + url + } + val clientIdProperty = if (clientId == "null") { + null + } else { + clientId + } + val clientSecretProperty = if (clientSecret == "null") { + null + } else { + clientSecret + } + + val body = JsonObject() + val authorizationServer = JsonObject() + + body.addProperty("id", idProperty) + body.add("authorizationServer", authorizationServer) + + authorizationServer.addProperty("url", urlProperty) + authorizationServer.addProperty("clientId", clientIdProperty) + authorizationServer.addProperty("clientSecret", clientSecretProperty) + + val gson = GsonBuilder().serializeNulls().create() + issuer.attemptsTo( + Post.to("/oid4vci/issuers").body(gson.toJson(body)), + ) + } + + @Then("{actor} should see the oid4vci '{}' http status response with '{}' detail") + fun issuerShouldSeeTheOIDC4VCIError(issuer: Actor, httpStatus: Int, errorDetail: String) { + SerenityRest.lastResponse().body.prettyPrint() + issuer.attemptsTo( + Ensure.that(SerenityRest.lastResponse().statusCode).isEqualTo(httpStatus), + Ensure.that(SerenityRest.lastResponse().body.asString()).contains(errorDetail), + ) + } + @Then("{actor} sees the oid4vci issuer updated with new values") fun issuerSeesUpdatedCredentialIssuer(issuer: Actor) { val credentialIssuer = issuer.recall("oid4vciCredentialIssuer") @@ -143,4 +225,11 @@ class ManageIssuerSteps { Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_NOT_FOUND), ) } + + @Then("{actor} should see the update oid4vci issuer returned '{}' http status") + fun issuerShouldSeeTheUpdateOID4VCIIssuerReturnedHttpStatus(issuer: Actor, statusCode: Int) { + issuer.attemptsTo( + Ensure.thatTheLastResponse().statusCode().isEqualTo(statusCode), + ) + } } diff --git a/tests/integration-tests/src/test/resources/features/oid4vci/issue_jwt.feature b/tests/integration-tests/src/test/resources/features/oid4vci/issue_jwt.feature index 2f30658ad8..53d010c2c5 100644 --- a/tests/integration-tests/src/test/resources/features/oid4vci/issue_jwt.feature +++ b/tests/integration-tests/src/test/resources/features/oid4vci/issue_jwt.feature @@ -1,20 +1,20 @@ @oid4vci Feature: Issue JWT Credentials using OID4VCI authorization code flow -Background: + Background: Given Issuer has a published DID for JWT And Issuer has published STUDENT_SCHEMA schema And Issuer has an existing oid4vci issuer And Issuer has "StudentProfile" credential configuration created from STUDENT_SCHEMA -Scenario: Issuing credential with published PRISM DID + Scenario: Issuing credential with published PRISM DID When Issuer creates an offer using "StudentProfile" configuration with "short" form DID And Holder receives oid4vci offer from Issuer And Holder resolves oid4vci issuer metadata and login via front-end channel And Holder presents the access token with JWT proof on CredentialEndpoint Then Holder sees credential issued successfully from CredentialEndpoint -Scenario: Issuing credential with unpublished PRISM DID + Scenario: Issuing credential with unpublished PRISM DID When Issuer creates an offer using "StudentProfile" configuration with "long" form DID And Holder receives oid4vci offer from Issuer And Holder resolves oid4vci issuer metadata and login via front-end channel diff --git a/tests/integration-tests/src/test/resources/features/oid4vci/manage_credential_config.feature b/tests/integration-tests/src/test/resources/features/oid4vci/manage_credential_config.feature index 3253069abe..cacdeb6cdb 100644 --- a/tests/integration-tests/src/test/resources/features/oid4vci/manage_credential_config.feature +++ b/tests/integration-tests/src/test/resources/features/oid4vci/manage_credential_config.feature @@ -1,16 +1,39 @@ @oid4vci Feature: Manage OID4VCI credential configuration -Background: + Background: Given Issuer has a published DID for JWT And Issuer has published STUDENT_SCHEMA schema And Issuer has an existing oid4vci issuer -Scenario: Successfully create credential configuration - When Issuer uses STUDENT_SCHEMA to create a credential configuration "StudentProfile" + Scenario: Successfully create credential configuration + Given Issuer has "StudentProfile" credential configuration created from STUDENT_SCHEMA Then Issuer sees the "StudentProfile" configuration on IssuerMetadata endpoint -Scenario: Successfully delete credential configuration + Scenario: Successfully delete credential configuration Given Issuer has "StudentProfile" credential configuration created from STUDENT_SCHEMA When Issuer deletes "StudentProfile" credential configuration Then Issuer cannot see the "StudentProfile" configuration on IssuerMetadata endpoint + + Scenario Outline: Create configuration with expect code + When Issuer creates a new credential configuration request + And Issuer uses issuer id for credential configuration + And Issuer adds '' configuration id for credential configuration request + And Issuer adds '' format for credential configuration request + And Issuer adds '' schemaId for credential configuration request + And Issuer sends the create a credential configuration request + Then Issuer should see that create credential configuration has failed with '' status code and '' detail + Examples: + | issuerId | configurationId | format | schemaId | httpStatus | errorDetail | description | + | wrong | StudentProfile | jwt_vc_json | STUDENT_SCHEMA | 404 | There is no credential issue | wrong issuer id | + | existing | null | jwt_vc_json | STUDENT_SCHEMA | 400 | configurationId | null configuration id | + | existing | StudentProfile | null | STUDENT_SCHEMA | 400 | format | null format | + | existing | StudentProfile | wrong-format | STUDENT_SCHEMA | 400 | format | wrong format | + | existing | StudentProfile | jwt_vc_json | null | 400 | schemaId | null schema | + | existing | StudentProfile | jwt_vc_json | malformed-schema | 400 | | malformed schema | + | existing | StudentProfile | jwt_vc_json | STUDENT_SCHEMA | 201 | | right values | + | existing | StudentProfile | jwt_vc_json | STUDENT_SCHEMA | 409 | Duplicated credential | duplicated configuration id | + + Scenario: Delete non existent credential configuration + When Issuer deletes a non existent "NonExistentProfile" credential configuration + Then Issuer should see that create credential configuration has failed with '404' status code and 'There is no credential configuration' detail diff --git a/tests/integration-tests/src/test/resources/features/oid4vci/manage_issuer.feature b/tests/integration-tests/src/test/resources/features/oid4vci/manage_issuer.feature index d2b6bd4aa6..6259934824 100644 --- a/tests/integration-tests/src/test/resources/features/oid4vci/manage_issuer.feature +++ b/tests/integration-tests/src/test/resources/features/oid4vci/manage_issuer.feature @@ -1,19 +1,40 @@ @oid4vci Feature: Manage OID4VCI credential issuer -Scenario: Successfully create credential issuer + Scenario: Successfully create credential issuer When Issuer creates an oid4vci issuer Then Issuer sees the oid4vci issuer exists on the agent And Issuer sees the oid4vci issuer on IssuerMetadata endpoint -Scenario: Successfully update credential issuer + Scenario: Successfully update credential issuer Given Issuer has an existing oid4vci issuer When Issuer updates the oid4vci issuer Then Issuer sees the oid4vci issuer updated with new values And Issuer sees the oid4vci IssuerMetadata endpoint updated with new values -Scenario: Successfully delete credential issuer + Scenario: Successfully delete credential issuer Given Issuer has an existing oid4vci issuer When Issuer deletes the oid4vci issuer Then Issuer cannot see the oid4vci issuer on the agent And Issuer cannot see the oid4vci IssuerMetadata endpoint + + Scenario Outline: Create issuer with expect response + When Issuer tries to create oid4vci issuer with '', '', '' and '' + Then Issuer should see the oid4vci '' http status response with '' detail + Examples: + | id | url | clientId | clientSecret | httpStatus | errorDetail | description | + | null | null | null | null | 400 | authorizationServer.url | null values | + | null | malformed | id | secret | 400 | Relative URL 'malformed' is not | malformed url | + | null | http://example.com | id | null | 400 | authorizationServer.clientSecret | null client secret | + | null | http://example.com | null | secret | 400 | authorizationServer.clientId | null client id | + | null | null | id | secret | 400 | authorizationServer.url | null url | + | 4048ef76-749d-4296-8c6c-07c8a20733a0 | http://example.com | id | secret | 201 | | right values | + | 4048ef76-749d-4296-8c6c-07c8a20733a0 | http://example.com | id | secret | 500 | | duplicated id | + + Scenario Outline: Update issuer with expect response + Given Issuer has an existing oid4vci issuer + When Issuer tries to update the oid4vci issuer '' property using '' value + Then Issuer should see the oid4vci '' http status response with '' detail + Examples: + | property | value | httpStatus | errorDetail | description | + | url | malformed | 404 | | Invalid URL |