Skip to content

Commit

Permalink
test: new e2e scenarios (#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
amagyar-iohk authored Sep 22, 2023
1 parent 154ec78 commit b423238
Show file tree
Hide file tree
Showing 13 changed files with 153 additions and 71 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ on:
mediatorOobUrl:
required: true
description: Mediator out-of-band url
default: https://mediator.rootsid.cloud/oob_url
default: https://sit-prism-mediator.atalaprism.io/invitationOOB
prismAgentUrl:
required: true
description: Prism-agent server url
default: https://k8s-dev.atalaprism.io/prism-agent
default: https://sit-prism-agent-issuer.atalaprism.io/prism-agent
publishedDid:
required: false
description: Published DID
Expand All @@ -29,6 +29,9 @@ on:
pull_request:
branches:
- main
push:
branches:
- main

env:
ATALA_GITHUB_ACTOR: ${{ secrets.ATALA_GITHUB_ACTOR }}
Expand Down Expand Up @@ -79,6 +82,6 @@ jobs:
- name: Publish Serenity report
uses: actions/upload-artifact@v3
with:
name: atala-prism-sdk-kmm.zip
name: atala-prism-sdk-kmm
path: tests/end-to-end/target/site/serenity
if-no-files-found: error
4 changes: 2 additions & 2 deletions tests/end-to-end/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ plugins {
idea
java
id("com.github.ben-manes.versions") version "0.47.0"
id("net.serenity-bdd.serenity-gradle-plugin") version "3.7.0"
id("net.serenity-bdd.serenity-gradle-plugin") version "4.0.1"
}

group = "io.iohk.atala.prism"
version = "1.0-SNAPSHOT"

repositories {
mavenLocal()
mavenCentral()
maven {
url = uri("https://maven.pkg.github.com/input-output-hk/atala-automation/")
Expand All @@ -19,6 +18,7 @@ repositories {
password = System.getenv("ATALA_GITHUB_TOKEN")
}
}
mavenLocal()
}

dependencies {
Expand Down
1 change: 1 addition & 0 deletions tests/end-to-end/serenity.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ serenity.simplified.stack.traces=false
serenity.report.accessibility=true
json.pretty.printing=true
serenity.console.headings=normal
serenity.console.colors=true
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.iohk.atala.prism

import io.cucumber.java.BeforeAll
import io.cucumber.junit.CucumberOptions
import io.iohk.atala.prism.configuration.Environment
import net.serenitybdd.cucumber.CucumberWithSerenity
import org.junit.runner.RunWith

Expand All @@ -10,3 +12,9 @@ import org.junit.runner.RunWith
plugin = ["pretty"]
)
class TestSuite

// https://cucumber.io/docs/cucumber/api/?lang=kotlin
@BeforeAll
fun setupEnvironment() {
Environment.setup()
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class UseWalletSdk : Ability {

private val logger = Logger.get<EdgeAgentWorkflow>()
private val context: SdkContext
private val receivedMessages = mutableListOf<String>()

init {
val apollo = ApolloImpl()
Expand Down Expand Up @@ -119,6 +120,10 @@ class UseWalletSdk : Ability {
CoroutineScope(Dispatchers.Default).launch {
sdk.handleReceivedMessagesEvents().collect { messageList: List<Message> ->
messageList.forEach { message ->
if (receivedMessages.contains(message.id)) {
return@forEach
}
receivedMessages.add(message.id)
when (message.piuri) {
ProtocolType.DidcommOfferCredential.value -> context.credentialOfferStack.add(message)
ProtocolType.DidcommIssueCredential.value -> context.issuedCredentialStack.add(message)
Expand Down Expand Up @@ -148,4 +153,4 @@ data class SdkContext(
)

class ActorCannotUseWalletSdk(actor: Actor) :
Throwable("The actor [${actor.name}] does not have the ability to use wallet-sdk")
Throwable("The actor [${actor.name}] does not have the ability to use wallet-sdk")
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,22 @@ import io.restassured.response.Response
import net.serenitybdd.rest.SerenityRest
import org.apache.http.HttpStatus
import org.assertj.core.api.Assertions
import java.io.File
import java.util.*
import kotlin.time.Duration.Companion.seconds

object Environment {
private val logger = Logger.get<Environment>()

val agentUrl: String
val mediatorOobUrl: String
lateinit var agentUrl: String
lateinit var mediatorOobUrl: String
lateinit var publishedDid: String
lateinit var schemaId: String

/**
* Set up the variables based on the properties config file
*/
init {
fun setup() {
// prepare notes
Notes.prepareNotes()

Expand Down Expand Up @@ -58,6 +59,14 @@ object Environment {
Notes.appendMessage("Agent: $agentUrl")
Notes.appendMessage("DID: $publishedDid")
Notes.appendMessage("Schema: $schemaId")
Notes.appendMessage("SDK Version: ${getSdkVersion()}")
}

private fun getSdkVersion(): String {
val file = File("build.gradle.kts")
val input = file.readText()
val regex = Regex("prism-sdk:(.*)(?=\")")
return regex.find(input)!!.groups[1]!!.value
}

/**
Expand All @@ -74,7 +83,7 @@ object Environment {
this.publishedDid = publishedDid!!
return
} catch (e: AssertionError) {
logger.warn("DID not found. Creating a new one.")
Notes.appendMessage("DID [${publishedDid}] not found. Creating a new one.")
}

val publicKey = ManagedDIDKeyTemplate(
Expand Down Expand Up @@ -113,14 +122,12 @@ object Environment {
response.body.jsonPath().getString("status") == "PUBLISHED"
}
this.publishedDid = response.body.jsonPath().getString("did")

Notes.appendMessage("Created new DID: ${this.publishedDid}")
}

/**
* Checks if the environment SCHEMA_ID variable exists in prism-agent, otherwise it creates a new one.
*/
fun checkSchema(schemaId: String?) {
private fun checkSchema(schemaId: String?) {
try {
RestAssured
.given()
Expand All @@ -131,7 +138,7 @@ object Environment {
this.schemaId = schemaId!!
return
} catch (e: AssertionError) {
logger.warn("Schema not found. Creating a new one.")
Notes.appendMessage("Schema [${schemaId}] not found. Creating a new one.")
}

val schemaName = "automation-schema-" + UUID.randomUUID()
Expand Down Expand Up @@ -161,7 +168,6 @@ object Environment {
.thenReturn()

this.schemaId = schemaCreationResponse.body.jsonPath().getString("guid")
Notes.appendMessage("Created new schema: ${this.schemaId}")
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ class CloudAgentSteps {

@When("{actor} should see the credential was accepted")
fun `Cloud Agent should see the credential was accepted`(cloudAgent: Actor) {
cloudAgentWorkflow.verifyCredentialState(cloudAgent, "CredentialSent")
val recordId = cloudAgent.recall<String>("recordId")
cloudAgentWorkflow.verifyCredentialState(cloudAgent, recordId, "CredentialSent")
}

@When("{actor} asks for present-proof")
Expand All @@ -58,4 +59,12 @@ class CloudAgentSteps {
fun `Cloud Agent should see the present-proof is verified`(cloudAgent: Actor) {
cloudAgentWorkflow.verifyPresentProof(cloudAgent, "PresentationVerified")
}

@Then("{actor} should see all credentials were accepted")
fun `Cloud Agent should see all credentials were accepted`(cloudAgent: Actor) {
val recordIdList = cloudAgent.recall<List<String>>("recordIdList")
for (recordId in recordIdList) {
cloudAgentWorkflow.verifyCredentialState(cloudAgent, recordId, "CredentialSent")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.cucumber.java.After
import io.cucumber.java.en.Then
import io.cucumber.java.en.When
import io.iohk.atala.prism.abilities.UseWalletSdk
import io.iohk.atala.prism.workflow.CloudAgentWorkflow
import io.iohk.atala.prism.workflow.EdgeAgentWorkflow
import net.serenitybdd.screenplay.Actor
import net.serenitybdd.screenplay.actors.OnStage
Expand All @@ -14,11 +15,67 @@ class EdgeAgentSteps {
@Inject
private lateinit var edgeAgentWorkflow: EdgeAgentWorkflow

@Inject
private lateinit var cloudAgentWorkflow: CloudAgentWorkflow

@When("{actor} connects through the invite")
fun `Edge Agent connects through the invite`(edgeAgent: Actor) {
edgeAgentWorkflow.connect(edgeAgent)
}

@When("{actor} has {} credentials issued by {actor}")
fun `Edge Agent has {} issued credential`(edgeAgent: Actor, numberOfCredentialsIssued: Int, cloudAgent: Actor) {
repeat(numberOfCredentialsIssued) {
cloudAgentWorkflow.offerCredential(cloudAgent)
edgeAgentWorkflow.waitForCredentialOffer(edgeAgent, 1)
edgeAgentWorkflow.acceptCredential(edgeAgent)
cloudAgentWorkflow.verifyCredentialState(cloudAgent, cloudAgent.recall("recordId"), "CredentialSent")
edgeAgentWorkflow.waitToReceiveCredentialIssuance(edgeAgent, 1)
edgeAgentWorkflow.processIssuedCredential(edgeAgent, 1)
}
}

@When("{actor} accepts {} credential offer sequentially from {actor}")
fun `Edge Agent accepts multiple credentials offer sequentially from Cloud Agent`(
edgeAgent: Actor,
numberOfCredentials: Int,
cloudAgent: Actor
) {
val recordIdList = mutableListOf<String>()
repeat(numberOfCredentials) {
cloudAgentWorkflow.offerCredential(cloudAgent)
edgeAgentWorkflow.waitForCredentialOffer(edgeAgent, 1)
edgeAgentWorkflow.acceptCredential(edgeAgent)
cloudAgentWorkflow.verifyCredentialState(cloudAgent, cloudAgent.recall("recordId"), "CredentialSent")
recordIdList.add(cloudAgent.recall("recordId"))
}
cloudAgent.remember("recordIdList", recordIdList)
}

@When("{actor} accepts {} credentials offer at once from {actor}")
fun `Edge Agent accepts multiple credentials offer at once from Cloud Agent`(
edgeAgent: Actor,
numberOfCredentials: Int,
cloudAgent: Actor
) {
val recordIdList = mutableListOf<String>()

// offer multiple credentials
repeat(numberOfCredentials) {
cloudAgentWorkflow.offerCredential(cloudAgent)
recordIdList.add(cloudAgent.recall("recordId"))
}
cloudAgent.remember("recordIdList", recordIdList)

// wait to receive
edgeAgentWorkflow.waitForCredentialOffer(edgeAgent, numberOfCredentials)

// accept all
repeat(numberOfCredentials) {
edgeAgentWorkflow.acceptCredential(edgeAgent)
}
}

@When("{actor} accepts the credential")
fun `Edge Agent accepts the credential`(edgeAgent: Actor) {
edgeAgentWorkflow.acceptCredential(edgeAgent)
Expand All @@ -32,17 +89,17 @@ class EdgeAgentSteps {

@Then("{actor} should receive the credential")
fun `Edge Agent should receive the credential`(edgeAgent: Actor) {
edgeAgentWorkflow.waitForCredentialOffer(edgeAgent)
edgeAgentWorkflow.waitForCredentialOffer(edgeAgent, 1)
}

@Then("{actor} wait to receive an issued credential")
fun `Edge Agent wait to receive an issued credential`(edgeAgent: Actor) {
edgeAgentWorkflow.waitToReceiveIssuedCredential(edgeAgent)
@Then("{actor} wait to receive {} issued credentials")
fun `Edge Agent wait to receive issued credentials`(edgeAgent: Actor, expectedNumberOfCredentials: Int) {
edgeAgentWorkflow.waitToReceiveCredentialIssuance(edgeAgent, expectedNumberOfCredentials)
}

@Then("{actor} process the issued credential")
fun `Edge Agent process the issued credential`(edgeAgent: Actor) {
edgeAgentWorkflow.processIssuedCredential(edgeAgent)
@Then("{actor} process {} issued credentials")
fun `Edge Agent process multiple issued credentials`(edgeAgent: Actor, numberOfCredentials: Int) {
edgeAgentWorkflow.processIssuedCredential(edgeAgent, numberOfCredentials)
}

@After
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class CloudAgentWorkflow {
fun offerCredential(cloudAgent: Actor) {
val connectionId = cloudAgent.recall<String>("connectionId")
val credential = CreateIssueCredentialRecordRequest(
claims = mapOf(Pair("automation-required", "required value")),
claims = mapOf(Pair("automation-required", UUID.randomUUID())),
issuingDID = Environment.publishedDid,
connectionId = connectionId,
schemaId = "${Environment.agentUrl}/schema-registry/schemas/${Environment.schemaId}"
Expand Down Expand Up @@ -79,8 +79,7 @@ class CloudAgentWorkflow {
cloudAgent.remember("presentationId", lastResponse().get<String>("presentationId"))
}

fun verifyCredentialState(cloudAgent: Actor, state: String) {
val recordId = cloudAgent.recall<String>("recordId")
fun verifyCredentialState(cloudAgent: Actor, recordId: String, state: String) {
cloudAgent.attemptsTo(
PollingWait.until(
HttpRequest.get("/issue-credentials/records/$recordId"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,37 +65,33 @@ class EdgeAgentWorkflow {
)
}

fun waitForCredentialOffer(edgeAgent: Actor) {
fun waitForCredentialOffer(edgeAgent: Actor, numberOfCredentialOffer: Int) {
edgeAgent.attemptsTo(
PollingWait.until(
UseWalletSdk.credentialOfferStackSize(),
equalTo(1)
equalTo(numberOfCredentialOffer)
)
)
}

fun waitToReceiveIssuedCredential(edgeAgent: Actor) {
fun waitToReceiveCredentialIssuance(edgeAgent: Actor, expectedNumberOfCredentials: Int) {
edgeAgent.attemptsTo(
PollingWait.until(
UseWalletSdk.issuedCredentialStackSize(),
equalTo(1)
equalTo(expectedNumberOfCredentials)
)
)
}

fun processIssuedCredential(edgeAgent: Actor) {
fun processIssuedCredential(edgeAgent: Actor, numberOfCredentials: Int) {
edgeAgent.attemptsTo(
UseWalletSdk.execute {
val issuedCredentialMessage = it.issuedCredentialStack.removeFirst()
val issuedCredential = IssueCredential.fromMessage(issuedCredentialMessage)
it.sdk.processIssuedCredentialMessage(issuedCredential)
UseWalletSdk.execute { sdkContext ->
repeat(numberOfCredentials) {
val issuedCredentialMessage = sdkContext.issuedCredentialStack.removeFirst()
val issuedCredential = IssueCredential.fromMessage(issuedCredentialMessage)
sdkContext.sdk.processIssuedCredentialMessage(issuedCredential)
}
}
)
}

fun stopSdk(edgeAgent: Actor) {
edgeAgent.attemptsTo(
UseWalletSdk.stop()
)
}
}
Loading

0 comments on commit b423238

Please sign in to comment.