Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add backup e2e scenarios #242

Merged
merged 1 commit into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions integration-tests/e2e-tests/features/backup.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@backup
Feature: Backup
The Edge Agent should be able to create and restore a backup

Scenario: Create and restore a backup
Given Edge Agent has created a backup
Then a new SDK can be restored from Edge Agent

Scenario: Agent without a seed should not be able to restore the backup
Given Edge Agent has created a backup
Then a new SDK cannot be restored from Edge Agent with wrong seed

Scenario: Restored backup should be functional
Given Cloud Agent is connected to Edge Agent
And Edge Agent has '1' jwt credentials issued by Cloud Agent
And Edge Agent creates '5' peer DIDs
And Edge Agent creates '3' prism DIDs
And Edge Agent has created a backup
Then a new Restored Agent is restored from Edge Agent
And Restored Agent should have the expected values from Edge Agent
And Edge Agent is dismissed
Given Cloud Agent is connected to Restored Agent
And Cloud Agent asks for present-proof
And Restored Agent sends the present-proof
Then Cloud Agent should see the present-proof is verified
8 changes: 5 additions & 3 deletions integration-tests/e2e-tests/src/abilities/WalletSdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class WalletSdk extends Ability implements Initialisable, Discardable {
}
}

async initialise(): Promise<void> {
async createSdk(seed: SDK.Domain.Seed = undefined) {
const apollo = new Apollo()
this.store = new SDK.Store({
name: [...Array(30)].map(() => Math.random().toString(36)[2]).join(""),
Expand All @@ -80,7 +80,7 @@ export class WalletSdk extends Ability implements Initialisable, Discardable {
})
const pluto = new SDK.Pluto(this.store, apollo)
const mediatorDID = Domain.DID.fromString(await WalletSdk.getMediatorDidThroughOob())
this.sdk = Agent.initialize({ apollo, pluto, mediatorDID })
this.sdk = Agent.initialize({ seed, apollo, pluto, mediatorDID })

this.sdk.addListener(
ListenerKey.MESSAGE, (messages: SDK.Domain.Message[]) => {
Expand All @@ -89,7 +89,10 @@ export class WalletSdk extends Ability implements Initialisable, Discardable {
}
}
)
}

async initialise(): Promise<void> {
await this.createSdk()
await this.sdk.start()
}

Expand All @@ -114,7 +117,6 @@ class MessageQueue {
revocationStack: Message[] = []
receivedMessages: string[] = []


enqueue(message: Message) {
this.queue.push(message)

Expand Down
81 changes: 70 additions & 11 deletions integration-tests/e2e-tests/src/steps/EdgeAgentSteps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,26 @@ Given("{actor} has '{int}' anonymous credentials issued by {actor}",
await EdgeAgentWorkflow.processIssuedCredential(edgeAgent, recordId)
})
await cloudAgent.attemptsTo(Notepad.notes().set("recordIdList", recordIdList))
})
}
)

Given("{actor} has created a backup",
async function(edgeAgent: Actor) {
await EdgeAgentWorkflow.createBackup(edgeAgent)
}
)

Given("{actor} creates '{}' peer DIDs",
async function(edgeAgent: Actor, numberOfDids: number) {
await EdgeAgentWorkflow.createPeerDids(edgeAgent, numberOfDids)
}
)

Given("{actor} creates '{}' prism DIDs",
async function(edgeAgent: Actor, numberOfDids: number) {
await EdgeAgentWorkflow.createPrismDids(edgeAgent, numberOfDids)
}
)

When("{actor} accepts {int} jwt credential offer sequentially from {actor}",
async function (edgeAgent: Actor, numberOfCredentialOffers: number, cloudAgent: Actor) {
Expand All @@ -48,7 +67,8 @@ When("{actor} accepts {int} jwt credential offer sequentially from {actor}",
recordIdList.push(recordId)
})
await cloudAgent.attemptsTo(Notepad.notes().set("recordIdList", recordIdList))
})
}
)

When("{actor} accepts {int} jwt credentials offer at once from {actor}",
async function (edgeAgent: Actor, numberOfCredentials: number, cloudAgent: Actor) {
Expand All @@ -65,55 +85,94 @@ When("{actor} accepts {int} jwt credentials offer at once from {actor}",
await Utils.repeat(numberOfCredentials, async () => {
await EdgeAgentWorkflow.acceptCredential(edgeAgent)
})
})
}
)

When("{actor} connects through the invite",
async function (edgeAgent: Actor) {
await EdgeAgentWorkflow.connect(edgeAgent)
})
}
)

When("{actor} accepts the credentials offer from {actor}",
async function (edgeAgent: Actor, cloudAgent: Actor) {
const recordIdList = await cloudAgent.answer(Notepad.notes().get("recordIdList"))
Utils.repeat(recordIdList.length, async () => {
await EdgeAgentWorkflow.acceptCredential(edgeAgent)
})
})
}
)

When("{actor} sends the present-proof",
async function (edgeAgent: Actor) {
await EdgeAgentWorkflow.waitForProofRequest(edgeAgent)
await EdgeAgentWorkflow.presentProof(edgeAgent)
})
}
)

Then("{actor} should receive the credentials offer from {actor}",
async function (edgeAgent: Actor, cloudAgent: Actor) {
const recordIdList = await cloudAgent.answer(Notepad.notes().get("recordIdList"))
await EdgeAgentWorkflow.waitForCredentialOffer(edgeAgent, recordIdList.length)
})
}
)

Then("{actor} waits to receive the revocation notifications from {actor}",
async function (edgeAgent: Actor, cloudAgent: Actor) {
const revokedRecordIdList = await cloudAgent.answer(Notepad.notes().get("revokedRecordIdList"))
await EdgeAgentWorkflow.waitForCredentialRevocationMessage(edgeAgent, revokedRecordIdList.length)
})
}
)

Then("{actor} should see the credentials were revoked by {actor}",
async function (edgeAgent: Actor, cloudAgent: Actor) {
const revokedRecordIdList = await cloudAgent.answer(Notepad.notes().get("revokedRecordIdList"))
await EdgeAgentWorkflow.waitUntilCredentialIsRevoked(edgeAgent, revokedRecordIdList)
})
}
)

Then("{actor} process issued credentials from {actor}",
async function (edgeAgent: Actor, cloudAgent: Actor) {
const recordIdList = await cloudAgent.answer<string[]>(Notepad.notes().get("recordIdList"))
for (const recordId of recordIdList) {
await EdgeAgentWorkflow.processIssuedCredential(edgeAgent, recordId)
}
})
}
)

Then("{actor} wait to receive issued credentials from {actor}",
async function (edgeAgent: Actor, cloudAgent: Actor) {
const recordIdList = await cloudAgent.answer(Notepad.notes().get("recordIdList"))
await EdgeAgentWorkflow.waitToReceiveCredentialIssuance(edgeAgent, recordIdList.length)
})
}
)

Then("a new SDK can be restored from {actor}",
async function(edgeAgent: Actor) {
await EdgeAgentWorkflow.createNewWalletFromBackup(edgeAgent)
}
)

Then("a new SDK cannot be restored from {actor} with wrong seed",
async function(edgeAgent: Actor) {
await EdgeAgentWorkflow.createNewWalletFromBackupWithWrongSeed(edgeAgent)
}
)

Then("a new {actor} is restored from {actor}",
async function(newAgent: Actor, edgeAgent: Actor) {
await EdgeAgentWorkflow.backupAndRestoreToNewAgent(newAgent, edgeAgent)
}
)

Then("{actor} should have the expected values from {actor}",
async function(copyEdgeAgent: Actor, originalEdgeAgent: Actor) {
await EdgeAgentWorkflow.copyAgentShouldMatchOriginalAgent(copyEdgeAgent, originalEdgeAgent)
}
)

Then("{actor} is dismissed",
async function(edgeAgent: Actor) {
await edgeAgent.dismiss()
}
)
3 changes: 1 addition & 2 deletions integration-tests/e2e-tests/src/steps/LifecycleSteps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class Actors implements Cast {
actors.add(cloudAgent)
actors.add(edgeAgent)
actors.add(verifierEdgeAgent)

engage(actors)
}

Expand All @@ -48,7 +47,7 @@ class Actors implements Cast {

prepare(actor: Actor): Actor {
if (!this.actors.has(actor.name)) {
throw new Error(`Unable to find actor ${actor.name}`)
return actor
}
return this.actors.get(actor.name)!
}
Expand Down
113 changes: 111 additions & 2 deletions integration-tests/e2e-tests/src/workflow/EdgeAgentWorkflow.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import SDK from "@atala/prism-wallet-sdk"
import { Actor, Duration, Notepad, Wait } from "@serenity-js/core"
import { Actor, Duration, Notepad, TakeNotes, Wait } from "@serenity-js/core"
import { Ensure, equals } from "@serenity-js/assertions"
import { WalletSdk } from "../abilities/WalletSdk"
import { Utils } from "../Utils"
import { randomUUID } from "crypto"
import _ from "lodash"
import { assert } from "chai"

const { IssueCredential, OfferCredential, RequestPresentation, } = SDK

export class EdgeAgentWorkflow {


static async connect(edgeAgent: Actor) {
const url = await edgeAgent.answer<string>(Notepad.notes().get("invitation"))
await edgeAgent.attemptsTo(
Expand Down Expand Up @@ -120,4 +122,111 @@ export class EdgeAgentWorkflow {
})
)
}

static async createPeerDids(edgeAgent: Actor, numberOfDids: number) {
await edgeAgent.attemptsTo(
WalletSdk.execute(async sdk => {
await Utils.repeat(numberOfDids, async () => {
await sdk.createNewPeerDID()
})
})
)
}

static async createPrismDids(edgeAgent: Actor, numberOfDids: number) {
await edgeAgent.attemptsTo(
WalletSdk.execute(async sdk => {
await Utils.repeat(numberOfDids, async () => {
await sdk.createNewPrismDID(randomUUID())
})
})
)
}

static async copyAgentShouldMatchOriginalAgent(copyEdgeAgent: Actor, originalEdgeAgent: Actor) {
let expectedCredentials: SDK.Domain.Credential[]
let expectedPeerDids: SDK.PeerDID[]
let expectedPrismDids: SDK.Domain.PrismDID[]
let expectedDidPairs: SDK.Domain.DIDPair[]

await originalEdgeAgent.attemptsTo(
WalletSdk.execute(async sdk => {
expectedCredentials = await sdk.verifiableCredentials()
expectedPeerDids = await sdk.pluto.getAllPeerDIDs()
expectedPrismDids = await sdk.pluto.getAllPrismDIDs()
expectedDidPairs = await sdk.pluto.getAllDidPairs()
})
)

await copyEdgeAgent.attemptsTo(
WalletSdk.execute(async sdk => {
const credentials = await sdk.verifiableCredentials()
const peerDids = await sdk.pluto.getAllPeerDIDs()
const prismDids = await sdk.pluto.getAllPrismDIDs()
const didPairs = await sdk.pluto.getAllDidPairs()

await copyEdgeAgent.attemptsTo(
Ensure.that(credentials.length, equals(expectedCredentials.length)),
Ensure.that(peerDids.length, equals(expectedPeerDids.length)),
Ensure.that(prismDids.length, equals(expectedPrismDids.length)),
Ensure.that(didPairs.length, equals(expectedDidPairs.length)),
)

assert.isTrue(_.isEqual(expectedCredentials.map(it => it.id), credentials.map(it => it.id)))
assert.isTrue(_.isEqual(expectedPeerDids.map(it => it.did.uuid), peerDids.map(it => it.did.uuid)))
assert.isTrue(_.isEqual(expectedPrismDids.map(it => it.did.uuid), prismDids.map(it => it.did.uuid)))
assert.isTrue(_.isEqual(expectedDidPairs.map(it => it.name), expectedDidPairs.map(it => it.name)))
})
)
}


static async createBackup(edgeAgent: Actor) {
await edgeAgent.attemptsTo(
WalletSdk.execute(async (sdk) => {
const backup = await sdk.backup.createJWE()
await edgeAgent.attemptsTo(
Notepad.notes().set("backup", backup),
Notepad.notes().set("seed", sdk.seed)
)
})
)
}

static async createNewWalletFromBackup(edgeAgent: Actor) {
const backup = await edgeAgent.answer(Notepad.notes().get("backup"))
const seed = await edgeAgent.answer(Notepad.notes().get("seed"))
const walletSdk = new WalletSdk()
await walletSdk.createSdk(seed)
await walletSdk.sdk.pluto.start()
await walletSdk.sdk.backup.restore(backup)
await walletSdk.sdk.start()
await walletSdk.sdk.stop()
}

static async createNewWalletFromBackupWithWrongSeed(edgeAgent: Actor) {
const backup = await edgeAgent.answer(Notepad.notes().get("backup"))
const walletSdk = new WalletSdk()
const seed = new SDK.Apollo().createRandomSeed().seed
await walletSdk.createSdk(seed)
await walletSdk.sdk.pluto.start()

try {
await walletSdk.sdk.backup.restore(backup)
assert.fail("SDK should not be able to restore with wrong seed phrase.")
} catch (e) {
assert.isTrue(e != undefined)
}
}

static async backupAndRestoreToNewAgent(newAgent: Actor, edgeAgent: Actor) {
const backup = await edgeAgent.answer(Notepad.notes().get("backup"))
const seed = await edgeAgent.answer(Notepad.notes().get("seed"))
const walletSdk = new WalletSdk()
await walletSdk.createSdk(seed)
await walletSdk.sdk.pluto.start()
await walletSdk.sdk.backup.restore(backup)
await walletSdk.sdk.start()
newAgent.whoCan(walletSdk, TakeNotes.usingAnEmptyNotepad())
}
}
Loading