Skip to content

Commit

Permalink
Merge branch 'main' into tests/tag-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
yshyn-iohk authored May 23, 2024
2 parents f8cf017 + cbd72a8 commit e9e8845
Show file tree
Hide file tree
Showing 22 changed files with 505 additions and 406 deletions.
1 change: 1 addition & 0 deletions .mega-linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

APPLY_FIXES: all
DEFAULT_BRANCH: main
FAIL_IF_UPDATED_SOURCES: true
DISABLE_LINTERS:
- REPOSITORY_DEVSKIM
- REPOSITORY_GITLEAKS
Expand Down
4 changes: 2 additions & 2 deletions tests/integration-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ The project structure is represented below:
│ ├── abilities -> contains the abilities of the actors
│ ├── common -> contains the common classes (test constants and helper functions)
│ ├── config -> contains the configuration classes (Hoplite)
│ ├── features -> contains the features implementation steps
│ ├── interactions -> contains the interactions of the actors
│ └── runners -> contains the test runners to execute the tests
│ ├── models -> contains the models
│ ├── steps -> contains the features implementation steps
└── resources -> contains the test resources
├── configs -> contains the test configuration files
├── containers -> contains the Docker Compose files to start the test environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ open class ListenToEvents(
TestConstants.EVENT_TYPE_CONNECTION_UPDATED -> connectionEvents.add(gson.fromJson(eventString, ConnectionEvent::class.java))
TestConstants.EVENT_TYPE_ISSUE_CREDENTIAL_RECORD_UPDATED -> credentialEvents.add(gson.fromJson(eventString, CredentialEvent::class.java))
TestConstants.EVENT_TYPE_PRESENTATION_UPDATED -> presentationEvents.add(gson.fromJson(eventString, PresentationEvent::class.java))
TestConstants.EVENT_TYPE_DID_STATUS_UPDATED -> {
didEvents.add(gson.fromJson(eventString, DidEvent::class.java))
}
TestConstants.EVENT_TYPE_DID_STATUS_UPDATED -> didEvents.add(gson.fromJson(eventString, DidEvent::class.java))
else -> {
throw IllegalArgumentException("ERROR: unknown event type ${event.type}")
}
Expand All @@ -56,7 +54,7 @@ open class ListenToEvents(
return ListenToEvents(url, webhookPort)
}

fun `as`(actor: Actor): ListenToEvents {
fun with(actor: Actor): ListenToEvents {
return actor.abilityTo(ListenToEvents::class.java)
}
}
Expand Down
28 changes: 0 additions & 28 deletions tests/integration-tests/src/test/kotlin/common/Utils.kt

This file was deleted.

65 changes: 60 additions & 5 deletions tests/integration-tests/src/test/kotlin/models/Events.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ package models

import com.google.gson.JsonElement
import com.google.gson.annotations.SerializedName
import org.hyperledger.identus.client.models.Connection
import org.hyperledger.identus.client.models.IssueCredentialRecord
import org.hyperledger.identus.client.models.ManagedDID
import org.hyperledger.identus.client.models.PresentationStatus
import org.hyperledger.identus.client.models.*

data class Event(
@SerializedName("type") var type: String,
Expand Down Expand Up @@ -35,10 +32,68 @@ data class PresentationEvent(
@SerializedName("type") var type: String,
@SerializedName("id") var id: String,
@SerializedName("ts") var ts: String,
@SerializedName("data") var data: PresentationStatus,
@SerializedName("data") var data: PresentationStatusAdapter, // FIXME: rollback to PresentationStatus when Status is fixed
@SerializedName("walletId") var walletId: String,
)

data class PresentationStatusAdapter( // FIXME: delete this class when PresentationStatus.Status is fixed
@SerializedName("presentationId") val presentationId: String,
@SerializedName("thid") val thid: String,
@SerializedName("role") val role: PresentationStatus.Role,
@SerializedName("status") val status: Status,
@SerializedName("metaRetries") val metaRetries: Int,
@SerializedName("proofs") val proofs: List<ProofRequestAux>? = null,
@SerializedName("data") val `data`: List<String>? = null,
@SerializedName("connectionId") val connectionId: String? = null,
) {
enum class Status(val value: String) {
@SerializedName(value = "RequestPending")
REQUEST_PENDING("RequestPending"),

@SerializedName(value = "RequestSent")
REQUEST_SENT("RequestSent"),

@SerializedName(value = "RequestReceived")
REQUEST_RECEIVED("RequestReceived"),

@SerializedName(value = "RequestRejected")
REQUEST_REJECTED("RequestRejected"),

@SerializedName(value = "PresentationPending")
PRESENTATION_PENDING("PresentationPending"),

@SerializedName(value = "PresentationGenerated")
PRESENTATION_GENERATED("PresentationGenerated"),

@SerializedName(value = "PresentationSent")
PRESENTATION_SENT("PresentationSent"),

@SerializedName(value = "PresentationReceived")
PRESENTATION_RECEIVED("PresentationReceived"),

@SerializedName(value = "PresentationVerified")
PRESENTATION_VERIFIED("PresentationVerified"),

@SerializedName(value = "PresentationAccepted")
PRESENTATION_ACCEPTED("PresentationAccepted"),

@SerializedName(value = "PresentationRejected")
PRESENTATION_REJECTED("PresentationRejected"),

@SerializedName(value = "ProblemReportPending")
PROBLEM_REPORT_PENDING("ProblemReportPending"),

@SerializedName(value = "ProblemReportSent")
PROBLEM_REPORT_SENT("ProblemReportSent"),

@SerializedName(value = "ProblemReportReceived")
PROBLEM_REPORT_RECEIVED("ProblemReportReceived"),

@SerializedName(value = "PresentationVerificationFailed")
PRESENTATION_VERIFICATION_FAILED("PresentationVerificationFailed"),
}
}

data class DidEvent(
@SerializedName("type") var type: String,
@SerializedName("id") var id: String,
Expand Down
20 changes: 20 additions & 0 deletions tests/integration-tests/src/test/kotlin/models/JwtCredential.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package models

import com.jayway.jsonpath.DocumentContext
import com.jayway.jsonpath.JsonPath
import java.util.Base64

class JwtCredential(base64: String) {
private val payload: DocumentContext

init {
val jwt = String(Base64.getDecoder().decode(base64))
val parts = jwt.split(".")
payload = JsonPath.parse(String(Base64.getUrlDecoder().decode(parts[1])))
}

fun statusListId(): String {
val listUrl = payload.read<String>("$.vc.credentialStatus.statusListCredential")
return listUrl.split("/credential-status/")[1]
}
}
35 changes: 11 additions & 24 deletions tests/integration-tests/src/test/kotlin/steps/common/CommonSteps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,18 @@ class CommonSteps {

@Given("{actor} has an issued credential from {actor}")
fun holderHasIssuedCredentialFromIssuer(holder: Actor, issuer: Actor) {
holder.attemptsTo(
Get.resource("/issue-credentials/records"),
)
holder.attemptsTo(
Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_OK),
)
val receivedCredential = SerenityRest.lastResponse().get<IssueCredentialRecordPage>().contents!!.findLast { credential ->
credential.protocolState == IssueCredentialRecord.ProtocolState.CREDENTIAL_RECEIVED &&
credential.credentialFormat == IssueCredentialRecord.CredentialFormat.JWT
}
actorsHaveExistingConnection(issuer, holder)

if (receivedCredential != null) {
holder.remember("issuedCredential", receivedCredential)
} else {
val publishDidSteps = PublishDidSteps()
val issueSteps = IssueCredentialsSteps()
actorsHaveExistingConnection(issuer, holder)
publishDidSteps.agentHasAnUnpublishedDID(holder)
publishDidSteps.agentHasAPublishedDID(issuer)
issueSteps.issuerOffersACredential(issuer, holder, "short")
issueSteps.holderReceivesCredentialOffer(holder)
issueSteps.holderAcceptsCredentialOfferForJwt(holder)
issueSteps.acmeIssuesTheCredential(issuer)
issueSteps.bobHasTheCredentialIssued(holder)
}
val publishDidSteps = PublishDidSteps()
publishDidSteps.createsUnpublishedDid(holder)
publishDidSteps.agentHasAPublishedDID(issuer)

val issueSteps = IssueCredentialsSteps()
issueSteps.issuerOffersACredential(issuer, holder, "short")
issueSteps.holderReceivesCredentialOffer(holder)
issueSteps.holderAcceptsCredentialOfferForJwt(holder)
issueSteps.acmeIssuesTheCredential(issuer)
issueSteps.bobHasTheCredentialIssued(holder)
}

@Given("{actor} and {actor} have an existing connection")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
package steps.connection

import abilities.ListenToEvents
import common.Utils.wait
import interactions.Get
import interactions.Post
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 io.iohk.atala.automation.utils.Wait
import net.serenitybdd.rest.SerenityRest
import net.serenitybdd.screenplay.Actor
import org.apache.http.HttpStatus.SC_CREATED
import org.apache.http.HttpStatus.SC_OK
import org.assertj.core.api.Assertions.assertThat
import org.hyperledger.identus.client.models.AcceptConnectionInvitationRequest
import org.hyperledger.identus.client.models.Connection
import org.hyperledger.identus.client.models.CreateConnectionRequest
import org.hyperledger.identus.client.models.*

class ConnectionSteps {

Expand Down Expand Up @@ -66,7 +64,8 @@ class ConnectionSteps {
Ensure.thatTheLastResponse().statusCode().isEqualTo(SC_OK),
Ensure.that(inviteeConnection.invitation.from).isEqualTo(inviterConnection.invitation.from),
Ensure.that(inviteeConnection.invitation.id).isEqualTo(inviterConnection.invitation.id),
Ensure.that(inviteeConnection.invitation.invitationUrl).isEqualTo(inviterConnection.invitation.invitationUrl),
Ensure.that(inviteeConnection.invitation.invitationUrl)
.isEqualTo(inviterConnection.invitation.invitationUrl),
Ensure.that(inviteeConnection.invitation.type).isEqualTo(inviterConnection.invitation.type),
Ensure.that(inviteeConnection.state).isEqualTo(Connection.State.CONNECTION_REQUEST_PENDING),
Ensure.that(inviteeConnection.role).isEqualTo(Connection.Role.INVITEE),
Expand All @@ -77,31 +76,27 @@ class ConnectionSteps {

@When("{actor} receives the connection request and sends back the response")
fun inviterReceivesTheConnectionRequest(inviter: Actor) {
wait(
{
val lastEvent = ListenToEvents.`as`(inviter).connectionEvents.lastOrNull {
it.data.thid == inviter.recall<Connection>("connection").thid
}
lastEvent != null &&
lastEvent.data.state == Connection.State.CONNECTION_RESPONSE_SENT
},
"Inviter connection didn't reach ${Connection.State.CONNECTION_RESPONSE_SENT} state",
)
Wait.until(
errorMessage = "Inviter connection didn't reach ${Connection.State.CONNECTION_RESPONSE_SENT} state",
) {
val lastEvent = ListenToEvents.with(inviter).connectionEvents.lastOrNull {
it.data.thid == inviter.recall<Connection>("connection").thid
}
lastEvent != null && lastEvent.data.state == Connection.State.CONNECTION_RESPONSE_SENT
}
}

@When("{actor} receives the connection response")
fun inviteeReceivesTheConnectionResponse(invitee: Actor) {
// Bob (Holder) receives final connection response
wait(
{
val lastEvent = ListenToEvents.`as`(invitee).connectionEvents.lastOrNull {
it.data.thid == invitee.recall<Connection>("connection").thid
}
lastEvent != null &&
lastEvent.data.state == Connection.State.CONNECTION_RESPONSE_RECEIVED
},
"Invitee connection didn't reach ${Connection.State.CONNECTION_RESPONSE_RECEIVED} state.",
)
Wait.until(
errorMessage = "Invitee connection didn't reach ${Connection.State.CONNECTION_RESPONSE_RECEIVED} state.",
) {
val lastEvent = ListenToEvents.with(invitee).connectionEvents.lastOrNull {
it.data.thid == invitee.recall<Connection>("connection").thid
}
lastEvent != null &&
lastEvent.data.state == Connection.State.CONNECTION_RESPONSE_RECEIVED
}
}

@Then("{actor} and {actor} have a connection")
Expand Down
Loading

0 comments on commit e9e8845

Please sign in to comment.