diff --git a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials-auto-accept.e2e.test.ts b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials-auto-accept.e2e.test.ts index 09612c9877..5036232d4a 100644 --- a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials-auto-accept.e2e.test.ts +++ b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials-auto-accept.e2e.test.ts @@ -5,9 +5,7 @@ import type { Schema } from 'indy-sdk' import { setupCredentialTests, waitForCredentialRecord } from '../../../../../../tests/helpers' import testLogger from '../../../../../../tests/logger' -import { AriesFrameworkError } from '../../../../../error/AriesFrameworkError' import { JsonTransformer } from '../../../../../utils/JsonTransformer' -import { sleep } from '../../../../../utils/sleep' import { AutoAcceptCredential } from '../../../models/CredentialAutoAcceptType' import { CredentialState } from '../../../models/CredentialState' import { CredentialExchangeRecord } from '../../../repository/CredentialExchangeRecord' @@ -50,9 +48,18 @@ describe('v2 credentials', () => { }) test('Alice starts with V2 credential proposal to Faber, both with autoAcceptCredential on `always`', async () => { - testLogger.test('Alice sends credential proposal to Faber') + testLogger.test('Alice begins listening for credential') + const aliceCredReceivedPromise = waitForCredentialRecord(aliceAgent, { + state: CredentialState.CredentialReceived, + }) - const aliceCredentialExchangeRecord = await aliceAgent.credentials.proposeCredential({ + testLogger.test('Faber begins listening for credential ack') + const faberCredAckPromise = waitForCredentialRecord(faberAgent, { + state: CredentialState.Done, + }) + + testLogger.test('Alice sends credential proposal to Faber') + await aliceAgent.credentials.proposeCredential({ connectionId: aliceConnection.id, protocolVersion: 'v2', credentialFormats: { @@ -65,16 +72,10 @@ describe('v2 credentials', () => { }) testLogger.test('Alice waits for credential from Faber') - let aliceCredentialRecord = await waitForCredentialRecord(aliceAgent, { - threadId: aliceCredentialExchangeRecord.threadId, - state: CredentialState.CredentialReceived, - }) + let aliceCredentialRecord = await aliceCredReceivedPromise testLogger.test('Faber waits for credential ack from Alice') - aliceCredentialRecord = await waitForCredentialRecord(faberAgent, { - threadId: aliceCredentialRecord.threadId, - state: CredentialState.Done, - }) + aliceCredentialRecord = await faberCredAckPromise expect(aliceCredentialRecord).toMatchObject({ type: CredentialExchangeRecord.type, @@ -93,9 +94,19 @@ describe('v2 credentials', () => { }) test('Faber starts with V2 credential offer to Alice, both with autoAcceptCredential on `always`', async () => { + testLogger.test('Alice begins listening for credential') + const aliceCredReceivedPromise = waitForCredentialRecord(aliceAgent, { + state: CredentialState.CredentialReceived, + }) + + testLogger.test('Faber begins listening for credential ack') + const faberCredAckPromise = waitForCredentialRecord(faberAgent, { + state: CredentialState.Done, + }) + testLogger.test('Faber sends credential offer to Alice') const schemaId = schema.id - const faberCredentialExchangeRecord = await faberAgent.credentials.offerCredential({ + await faberAgent.credentials.offerCredential({ comment: 'some comment about credential', connectionId: faberConnection.id, credentialFormats: { @@ -107,15 +118,7 @@ describe('v2 credentials', () => { protocolVersion: 'v2', }) testLogger.test('Alice waits for credential from Faber') - const aliceCredentialRecord = await waitForCredentialRecord(aliceAgent, { - threadId: faberCredentialExchangeRecord.threadId, - state: CredentialState.CredentialReceived, - }) - testLogger.test('Faber waits for credential ack from Alice') - const faberCredentialRecord: CredentialExchangeRecord = await waitForCredentialRecord(faberAgent, { - threadId: faberCredentialExchangeRecord.threadId, - state: CredentialState.Done, - }) + const aliceCredentialRecord = await aliceCredReceivedPromise expect(aliceCredentialRecord).toMatchObject({ type: CredentialExchangeRecord.type, id: expect.any(String), @@ -137,6 +140,9 @@ describe('v2 credentials', () => { ], state: CredentialState.CredentialReceived, }) + + testLogger.test('Faber waits for credential ack from Alice') + const faberCredentialRecord: CredentialExchangeRecord = await faberCredAckPromise expect(faberCredentialRecord).toMatchObject({ type: CredentialExchangeRecord.type, id: expect.any(String), @@ -168,10 +174,13 @@ describe('v2 credentials', () => { test('Alice starts with V2 credential proposal to Faber, both with autoAcceptCredential on `contentApproved`', async () => { testLogger.test('Alice sends credential proposal to Faber') const schemaId = schema.id - let faberCredentialExchangeRecord: CredentialExchangeRecord - let aliceCredentialExchangeRecord: CredentialExchangeRecord - aliceCredentialExchangeRecord = await aliceAgent.credentials.proposeCredential({ + testLogger.test('Faber starts listening for credential proposal from Alice') + const faberPropReceivedPromise = waitForCredentialRecord(faberAgent, { + state: CredentialState.ProposalReceived, + }) + + await aliceAgent.credentials.proposeCredential({ connectionId: aliceConnection.id, protocolVersion: 'v2', credentialFormats: { @@ -183,13 +192,20 @@ describe('v2 credentials', () => { }) testLogger.test('Faber waits for credential proposal from Alice') - faberCredentialExchangeRecord = await waitForCredentialRecord(faberAgent, { - threadId: aliceCredentialExchangeRecord.threadId, - state: CredentialState.ProposalReceived, + const faberPropReceivedRecord = await faberPropReceivedPromise + + const aliceCredReceivedPromise = waitForCredentialRecord(aliceAgent, { + threadId: faberPropReceivedRecord.threadId, + state: CredentialState.CredentialReceived, + }) + + const faberCredAckPromise = waitForCredentialRecord(faberAgent, { + threadId: faberPropReceivedRecord.threadId, + state: CredentialState.Done, }) const options: AcceptProposalOptions = { - credentialRecordId: faberCredentialExchangeRecord.id, + credentialRecordId: faberPropReceivedRecord.id, comment: 'V2 Indy Offer', credentialFormats: { indy: { @@ -199,22 +215,13 @@ describe('v2 credentials', () => { }, } testLogger.test('Faber sends credential offer to Alice') - options.credentialRecordId = faberCredentialExchangeRecord.id - faberCredentialExchangeRecord = await faberAgent.credentials.acceptProposal(options) + options.credentialRecordId = faberPropReceivedRecord.id + await faberAgent.credentials.acceptProposal(options) testLogger.test('Alice waits for credential from Faber') - aliceCredentialExchangeRecord = await waitForCredentialRecord(aliceAgent, { - threadId: faberCredentialExchangeRecord.threadId, - state: CredentialState.CredentialReceived, - }) - - testLogger.test('Faber waits for credential ack from Alice') - faberCredentialExchangeRecord = await waitForCredentialRecord(faberAgent, { - threadId: faberCredentialExchangeRecord.threadId, - state: CredentialState.Done, - }) + const aliceCredReceivedRecord = await aliceCredReceivedPromise - expect(aliceCredentialExchangeRecord).toMatchObject({ + expect(aliceCredReceivedRecord).toMatchObject({ type: CredentialExchangeRecord.type, id: expect.any(String), createdAt: expect.any(Date), @@ -236,7 +243,10 @@ describe('v2 credentials', () => { state: CredentialState.CredentialReceived, }) - expect(faberCredentialExchangeRecord).toMatchObject({ + testLogger.test('Faber waits for credential ack from Alice') + const faberCredAckRecord = await faberCredAckPromise + + expect(faberCredAckRecord).toMatchObject({ type: CredentialExchangeRecord.type, id: expect.any(String), createdAt: expect.any(Date), @@ -253,12 +263,14 @@ describe('v2 credentials', () => { }) test('Faber starts with V2 credential offer to Alice, both with autoAcceptCredential on `contentApproved`', async () => { + testLogger.test('Alice starts listening for credential offer from Faber') + const aliceOfferReceivedPromise = waitForCredentialRecord(aliceAgent, { + state: CredentialState.OfferReceived, + }) + testLogger.test('Faber sends credential offer to Alice') const schemaId = schema.id - let aliceCredentialExchangeRecord: CredentialExchangeRecord - let faberCredentialExchangeRecord: CredentialExchangeRecord - - faberCredentialExchangeRecord = await faberAgent.credentials.offerCredential({ + await faberAgent.credentials.offerCredential({ comment: 'some comment about credential', connectionId: faberConnection.id, credentialFormats: { @@ -271,79 +283,80 @@ describe('v2 credentials', () => { }) testLogger.test('Alice waits for credential offer from Faber') - aliceCredentialExchangeRecord = await waitForCredentialRecord(aliceAgent, { - threadId: faberCredentialExchangeRecord.threadId, - state: CredentialState.OfferReceived, - }) + const aliceOfferReceivedRecord = await aliceOfferReceivedPromise - expect(JsonTransformer.toJSON(aliceCredentialExchangeRecord)).toMatchObject({ + expect(JsonTransformer.toJSON(aliceOfferReceivedRecord)).toMatchObject({ state: CredentialState.OfferReceived, }) // below values are not in json object - expect(aliceCredentialExchangeRecord.id).not.toBeNull() - expect(aliceCredentialExchangeRecord.getTags()).toEqual({ - threadId: aliceCredentialExchangeRecord.threadId, - state: aliceCredentialExchangeRecord.state, + expect(aliceOfferReceivedRecord.id).not.toBeNull() + expect(aliceOfferReceivedRecord.getTags()).toEqual({ + threadId: aliceOfferReceivedRecord.threadId, + state: aliceOfferReceivedRecord.state, connectionId: aliceConnection.id, credentialIds: [], }) + testLogger.test('Alice received credential offer from Faber') + + testLogger.test('Alice starts listening for credential from Faber') + const aliceCredReceivedPromise = waitForCredentialRecord(aliceAgent, { + state: CredentialState.CredentialReceived, + }) + + const faberCredAckPromise = waitForCredentialRecord(faberAgent, { + state: CredentialState.Done, + }) + + const acceptOfferOptions: AcceptOfferOptions = { + credentialRecordId: aliceOfferReceivedRecord.id, + } + testLogger.test('alice sends credential request to faber') + await aliceAgent.credentials.acceptOffer(acceptOfferOptions) - if (aliceCredentialExchangeRecord.connectionId) { - const acceptOfferOptions: AcceptOfferOptions = { - credentialRecordId: aliceCredentialExchangeRecord.id, - } - testLogger.test('alice sends credential request to faber') - faberCredentialExchangeRecord = await aliceAgent.credentials.acceptOffer(acceptOfferOptions) - - testLogger.test('Alice waits for credential from Faber') - aliceCredentialExchangeRecord = await waitForCredentialRecord(aliceAgent, { - threadId: faberCredentialExchangeRecord.threadId, - state: CredentialState.CredentialReceived, - }) - - testLogger.test('Faber waits for credential ack from Alice') - faberCredentialExchangeRecord = await waitForCredentialRecord(faberAgent, { - threadId: faberCredentialExchangeRecord.threadId, - state: CredentialState.Done, - }) - - expect(aliceCredentialExchangeRecord).toMatchObject({ - type: CredentialExchangeRecord.type, - id: expect.any(String), - createdAt: expect.any(Date), - metadata: { - data: { - '_internal/indyRequest': expect.any(Object), - '_internal/indyCredential': { - schemaId, - credentialDefinitionId: credDefId, - }, + testLogger.test('Alice waits for credential from Faber') + const aliceCredReceivedRecord = await aliceCredReceivedPromise + expect(aliceCredReceivedRecord).toMatchObject({ + type: CredentialExchangeRecord.type, + id: expect.any(String), + createdAt: expect.any(Date), + metadata: { + data: { + '_internal/indyRequest': expect.any(Object), + '_internal/indyCredential': { + schemaId, + credentialDefinitionId: credDefId, }, }, - credentials: [ - { - credentialRecordType: 'indy', - credentialRecordId: expect.any(String), - }, - ], - state: CredentialState.CredentialReceived, - }) - - expect(faberCredentialExchangeRecord).toMatchObject({ - type: CredentialExchangeRecord.type, - id: expect.any(String), - createdAt: expect.any(Date), - state: CredentialState.Done, - }) - } else { - throw new AriesFrameworkError('missing alice connection id') - } + }, + credentials: [ + { + credentialRecordType: 'indy', + credentialRecordId: expect.any(String), + }, + ], + state: CredentialState.CredentialReceived, + }) + + testLogger.test('Faber waits for credential ack from Alice') + const faberCredAckRecord = await faberCredAckPromise + + expect(faberCredAckRecord).toMatchObject({ + type: CredentialExchangeRecord.type, + id: expect.any(String), + createdAt: expect.any(Date), + state: CredentialState.Done, + }) }) test('Alice starts with V2 credential proposal to Faber, both have autoAcceptCredential on `contentApproved` and attributes did change', async () => { + testLogger.test('Faber starts listening for proposal from Alice') + const faberPropReceivedPromise = waitForCredentialRecord(faberAgent, { + state: CredentialState.ProposalReceived, + }) + testLogger.test('Alice sends credential proposal to Faber') - const aliceCredentialExchangeRecord = await aliceAgent.credentials.proposeCredential({ + const aliceCredProposal = await aliceAgent.credentials.proposeCredential({ connectionId: aliceConnection.id, protocolVersion: 'v2', credentialFormats: { @@ -354,15 +367,19 @@ describe('v2 credentials', () => { }, comment: 'v2 propose credential test', }) + expect(aliceCredProposal.state).toBe(CredentialState.ProposalSent) testLogger.test('Faber waits for credential proposal from Alice') - let faberCredentialExchangeRecord = await waitForCredentialRecord(faberAgent, { - threadId: aliceCredentialExchangeRecord.threadId, - state: CredentialState.ProposalReceived, + const faberPropReceivedRecord = await faberPropReceivedPromise + + testLogger.test('Alice starts listening for credential offer from Faber') + const aliceOfferReceivedPromise = waitForCredentialRecord(aliceAgent, { + state: CredentialState.OfferReceived, }) - await faberAgent.credentials.negotiateProposal({ - credentialRecordId: faberCredentialExchangeRecord.id, + testLogger.test('Faber negotiated proposal, sending credential offer to Alice') + const faberOfferSentRecord = await faberAgent.credentials.negotiateProposal({ + credentialRecordId: faberPropReceivedRecord.id, credentialFormats: { indy: { credentialDefinitionId: credDefId, @@ -372,32 +389,33 @@ describe('v2 credentials', () => { }) testLogger.test('Alice waits for credential offer from Faber') - - const record = await waitForCredentialRecord(aliceAgent, { - threadId: faberCredentialExchangeRecord.threadId, - state: CredentialState.OfferReceived, - }) + const aliceOfferReceivedRecord = await aliceOfferReceivedPromise // below values are not in json object - expect(record.id).not.toBeNull() - expect(record.getTags()).toEqual({ - threadId: record.threadId, - state: record.state, + expect(aliceOfferReceivedRecord.id).not.toBeNull() + expect(aliceOfferReceivedRecord.getTags()).toEqual({ + threadId: aliceOfferReceivedRecord.threadId, + state: aliceOfferReceivedRecord.state, connectionId: aliceConnection.id, credentialIds: [], }) // Check if the state of the credential records did not change - faberCredentialExchangeRecord = await faberAgent.credentials.getById(faberCredentialExchangeRecord.id) - faberCredentialExchangeRecord.assertState(CredentialState.OfferSent) + const faberRecord = await faberAgent.credentials.getById(faberOfferSentRecord.id) + faberRecord.assertState(CredentialState.OfferSent) - const aliceRecord = await aliceAgent.credentials.getById(record.id) + const aliceRecord = await aliceAgent.credentials.getById(aliceOfferReceivedRecord.id) aliceRecord.assertState(CredentialState.OfferReceived) }) test('Faber starts with V2 credential offer to Alice, both have autoAcceptCredential on `contentApproved` and attributes did change', async () => { + testLogger.test('Alice starts listening for offer from Faber') + const aliceCredentialExchangeRecordPromise = waitForCredentialRecord(aliceAgent, { + state: CredentialState.OfferReceived, + }) + testLogger.test('Faber sends credential offer to Alice') - let faberCredentialExchangeRecord = await faberAgent.credentials.offerCredential({ + await faberAgent.credentials.offerCredential({ comment: 'some comment about credential', connectionId: faberConnection.id, credentialFormats: { @@ -410,23 +428,25 @@ describe('v2 credentials', () => { }) testLogger.test('Alice waits for credential offer from Faber') - let aliceCredentialExchangeRecord = await waitForCredentialRecord(aliceAgent, { - threadId: faberCredentialExchangeRecord.threadId, - state: CredentialState.OfferReceived, - }) + const aliceOfferReceivedRecord = await aliceCredentialExchangeRecordPromise // below values are not in json object - expect(aliceCredentialExchangeRecord.id).not.toBeNull() - expect(aliceCredentialExchangeRecord.getTags()).toEqual({ - threadId: aliceCredentialExchangeRecord.threadId, - state: aliceCredentialExchangeRecord.state, + expect(aliceOfferReceivedRecord.id).not.toBeNull() + expect(aliceOfferReceivedRecord.getTags()).toEqual({ + threadId: aliceOfferReceivedRecord.threadId, + state: aliceOfferReceivedRecord.state, connectionId: aliceConnection.id, credentialIds: [], }) + testLogger.test('Faber starts listening for proposal received') + const faberProposalReceivedPromise = waitForCredentialRecord(faberAgent, { + state: CredentialState.ProposalReceived, + }) + testLogger.test('Alice sends credential request to Faber') - const aliceExchangeCredentialRecord = await aliceAgent.credentials.negotiateOffer({ - credentialRecordId: aliceCredentialExchangeRecord.id, + const aliceCredRequestRecord = await aliceAgent.credentials.negotiateOffer({ + credentialRecordId: aliceOfferReceivedRecord.id, credentialFormats: { indy: { attributes: newCredentialPreview.attributes, @@ -437,19 +457,14 @@ describe('v2 credentials', () => { }) testLogger.test('Faber waits for credential proposal from Alice') - faberCredentialExchangeRecord = await waitForCredentialRecord(faberAgent, { - threadId: aliceExchangeCredentialRecord.threadId, - state: CredentialState.ProposalReceived, - }) - - await sleep(5000) + const faberCredProposalRecord = await faberProposalReceivedPromise // Check if the state of fabers credential record did not change - const faberRecord = await faberAgent.credentials.getById(faberCredentialExchangeRecord.id) + const faberRecord = await faberAgent.credentials.getById(faberCredProposalRecord.id) faberRecord.assertState(CredentialState.ProposalReceived) - aliceCredentialExchangeRecord = await aliceAgent.credentials.getById(aliceCredentialExchangeRecord.id) - aliceCredentialExchangeRecord.assertState(CredentialState.ProposalSent) + const aliceRecord = await aliceAgent.credentials.getById(aliceCredRequestRecord.id) + aliceRecord.assertState(CredentialState.ProposalSent) }) }) }) diff --git a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials.e2e.test.ts b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials.e2e.test.ts index 0fa0e2c9f2..e8c7905e73 100644 --- a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials.e2e.test.ts +++ b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials.e2e.test.ts @@ -1,8 +1,15 @@ import type { Agent } from '../../../../../agent/Agent' import type { ConnectionRecord } from '../../../../connections' +import type { CredentialStateChangedEvent } from '../../../CredentialEvents' import type { IndyCredPropose } from '../../../formats/indy/models/IndyCredPropose' +import type { ReplaySubject } from 'rxjs' -import { issueCredential, setupCredentialTests, waitForCredentialRecord } from '../../../../../../tests/helpers' +import { + issueCredential, + setupCredentialTests, + waitForCredentialRecord, + waitForCredentialRecordSubject, +} from '../../../../../../tests/helpers' import testLogger from '../../../../../../tests/logger' import { DidCommMessageRepository } from '../../../../../storage' import { JsonTransformer } from '../../../../../utils' @@ -32,6 +39,9 @@ describe('v2 credentials', () => { let aliceConnection: ConnectionRecord let aliceCredentialRecord: CredentialExchangeRecord let faberCredentialRecord: CredentialExchangeRecord + let faberReplay: ReplaySubject + let aliceReplay: ReplaySubject + let credPropose: IndyCredPropose const newCredentialPreview = V2CredentialPreview.fromRecord({ @@ -42,10 +52,9 @@ describe('v2 credentials', () => { }) beforeAll(async () => { - ;({ faberAgent, aliceAgent, credDefId, faberConnection, aliceConnection } = await setupCredentialTests( - 'Faber Agent Credentials v2', - 'Alice Agent Credentials v2' - )) + ;({ faberAgent, aliceAgent, credDefId, faberConnection, aliceConnection, faberReplay, aliceReplay } = + await setupCredentialTests('Faber Agent Credentials v2', 'Alice Agent Credentials v2')) + credPropose = { credentialDefinitionId: credDefId, schemaIssuerDid: 'GMm4vMw8LLrLJjp81kRRLp', @@ -91,7 +100,7 @@ describe('v2 credentials', () => { }) testLogger.test('Faber waits for credential proposal from Alice') - faberCredentialRecord = await waitForCredentialRecord(faberAgent, { + faberCredentialRecord = await waitForCredentialRecordSubject(faberReplay, { threadId: credentialExchangeRecord.threadId, state: CredentialState.ProposalReceived, }) @@ -109,7 +118,7 @@ describe('v2 credentials', () => { }) testLogger.test('Alice waits for credential offer from Faber') - aliceCredentialRecord = await waitForCredentialRecord(aliceAgent, { + aliceCredentialRecord = await waitForCredentialRecordSubject(aliceReplay, { threadId: faberCredentialRecord.threadId, state: CredentialState.OfferReceived, }) @@ -178,7 +187,7 @@ describe('v2 credentials', () => { }) testLogger.test('Faber waits for credential request from Alice') - faberCredentialRecord = await waitForCredentialRecord(faberAgent, { + faberCredentialRecord = await waitForCredentialRecordSubject(faberReplay, { threadId: aliceCredentialRecord.threadId, state: CredentialState.RequestReceived, }) @@ -190,7 +199,7 @@ describe('v2 credentials', () => { }) testLogger.test('Alice waits for credential from Faber') - aliceCredentialRecord = await waitForCredentialRecord(aliceAgent, { + aliceCredentialRecord = await waitForCredentialRecordSubject(aliceReplay, { threadId: faberCredentialRecord.threadId, state: CredentialState.CredentialReceived, }) @@ -200,7 +209,7 @@ describe('v2 credentials', () => { }) testLogger.test('Faber waits for state done') - await waitForCredentialRecord(faberAgent, { + await waitForCredentialRecordSubject(faberReplay, { threadId: faberCredentialRecord.threadId, state: CredentialState.Done, }) @@ -237,6 +246,10 @@ describe('v2 credentials', () => { test('Alice starts with proposal, faber sends a counter offer, alice sends second proposal, faber sends second offer', async () => { // proposeCredential -> negotiateProposal -> negotiateOffer -> negotiateProposal -> acceptOffer -> acceptRequest -> DONE (credential issued) + let faberCredentialRecordPromise = waitForCredentialRecord(faberAgent, { + state: CredentialState.ProposalReceived, + }) + testLogger.test('Alice sends credential proposal to Faber') let aliceCredentialExchangeRecord = await aliceAgent.credentials.proposeCredential({ connectionId: aliceConnection.id, @@ -252,9 +265,11 @@ describe('v2 credentials', () => { expect(aliceCredentialExchangeRecord.state).toBe(CredentialState.ProposalSent) testLogger.test('Faber waits for credential proposal from Alice') - let faberCredentialRecord = await waitForCredentialRecord(faberAgent, { - threadId: aliceCredentialExchangeRecord.threadId, - state: CredentialState.ProposalReceived, + let faberCredentialRecord = await faberCredentialRecordPromise + + let aliceCredentialRecordPromise = waitForCredentialRecord(aliceAgent, { + threadId: faberCredentialRecord.threadId, + state: CredentialState.OfferReceived, }) faberCredentialRecord = await faberAgent.credentials.negotiateProposal({ @@ -268,10 +283,7 @@ describe('v2 credentials', () => { }) testLogger.test('Alice waits for credential offer from Faber') - let aliceCredentialRecord = await waitForCredentialRecord(aliceAgent, { - threadId: faberCredentialRecord.threadId, - state: CredentialState.OfferReceived, - }) + let aliceCredentialRecord = await aliceCredentialRecordPromise // Check if the state of the credential records did not change faberCredentialRecord = await faberAgent.credentials.getById(faberCredentialRecord.id) @@ -280,6 +292,11 @@ describe('v2 credentials', () => { aliceCredentialRecord = await aliceAgent.credentials.getById(aliceCredentialRecord.id) aliceCredentialRecord.assertState(CredentialState.OfferReceived) + faberCredentialRecordPromise = waitForCredentialRecord(faberAgent, { + threadId: aliceCredentialExchangeRecord.threadId, + state: CredentialState.ProposalReceived, + }) + // second proposal aliceCredentialExchangeRecord = await aliceAgent.credentials.negotiateOffer({ credentialRecordId: aliceCredentialRecord.id, @@ -294,9 +311,11 @@ describe('v2 credentials', () => { expect(aliceCredentialExchangeRecord.state).toBe(CredentialState.ProposalSent) testLogger.test('Faber waits for credential proposal from Alice') - faberCredentialRecord = await waitForCredentialRecord(faberAgent, { - threadId: aliceCredentialExchangeRecord.threadId, - state: CredentialState.ProposalReceived, + faberCredentialRecord = await faberCredentialRecordPromise + + aliceCredentialRecordPromise = waitForCredentialRecord(aliceAgent, { + threadId: faberCredentialRecord.threadId, + state: CredentialState.OfferReceived, }) faberCredentialRecord = await faberAgent.credentials.negotiateProposal({ @@ -311,10 +330,7 @@ describe('v2 credentials', () => { testLogger.test('Alice waits for credential offer from Faber') - aliceCredentialRecord = await waitForCredentialRecord(aliceAgent, { - threadId: faberCredentialRecord.threadId, - state: CredentialState.OfferReceived, - }) + aliceCredentialRecord = await aliceCredentialRecordPromise const offerCredentialExchangeRecord = await aliceAgent.credentials.acceptOffer({ credentialRecordId: aliceCredentialExchangeRecord.id, @@ -328,7 +344,7 @@ describe('v2 credentials', () => { }) testLogger.test('Faber waits for credential request from Alice') - faberCredentialRecord = await waitForCredentialRecord(faberAgent, { + faberCredentialRecord = await waitForCredentialRecordSubject(faberReplay, { threadId: aliceCredentialExchangeRecord.threadId, state: CredentialState.RequestReceived, }) @@ -340,16 +356,15 @@ describe('v2 credentials', () => { }) testLogger.test('Alice waits for credential from Faber') - aliceCredentialRecord = await waitForCredentialRecord(aliceAgent, { + aliceCredentialRecord = await waitForCredentialRecordSubject(aliceReplay, { threadId: faberCredentialRecord.threadId, state: CredentialState.CredentialReceived, }) - // testLogger.test('Alice sends credential ack to Faber') await aliceAgent.credentials.acceptCredential({ credentialRecordId: aliceCredentialRecord.id }) testLogger.test('Faber waits for credential ack from Alice') - faberCredentialRecord = await waitForCredentialRecord(faberAgent, { + faberCredentialRecord = await waitForCredentialRecordSubject(faberReplay, { threadId: faberCredentialRecord.threadId, state: CredentialState.Done, }) @@ -364,8 +379,12 @@ describe('v2 credentials', () => { }) test('Faber starts with offer, alice sends counter proposal, faber sends second offer, alice sends second proposal', async () => { + let aliceCredentialRecordPromise = waitForCredentialRecord(aliceAgent, { + state: CredentialState.OfferReceived, + }) + testLogger.test('Faber sends credential offer to Alice') - const faberCredentialExchangeRecord = await faberAgent.credentials.offerCredential({ + let faberCredentialRecord = await faberAgent.credentials.offerCredential({ comment: 'some comment about credential', connectionId: faberConnection.id, credentialFormats: { @@ -378,9 +397,11 @@ describe('v2 credentials', () => { }) testLogger.test('Alice waits for credential offer from Faber') - aliceCredentialRecord = await waitForCredentialRecord(aliceAgent, { - threadId: faberCredentialExchangeRecord.threadId, - state: CredentialState.OfferReceived, + aliceCredentialRecord = await aliceCredentialRecordPromise + + let faberCredentialRecordPromise = waitForCredentialRecord(faberAgent, { + threadId: aliceCredentialRecord.threadId, + state: CredentialState.ProposalReceived, }) aliceCredentialRecord = await aliceAgent.credentials.negotiateOffer({ @@ -396,10 +417,13 @@ describe('v2 credentials', () => { expect(aliceCredentialRecord.state).toBe(CredentialState.ProposalSent) testLogger.test('Faber waits for credential proposal from Alice') - faberCredentialRecord = await waitForCredentialRecord(faberAgent, { - threadId: aliceCredentialRecord.threadId, - state: CredentialState.ProposalReceived, + faberCredentialRecord = await faberCredentialRecordPromise + + aliceCredentialRecordPromise = waitForCredentialRecord(aliceAgent, { + threadId: faberCredentialRecord.threadId, + state: CredentialState.OfferReceived, }) + faberCredentialRecord = await faberAgent.credentials.negotiateProposal({ credentialRecordId: faberCredentialRecord.id, credentialFormats: { @@ -412,9 +436,11 @@ describe('v2 credentials', () => { testLogger.test('Alice waits for credential offer from Faber') - aliceCredentialRecord = await waitForCredentialRecord(aliceAgent, { - threadId: faberCredentialRecord.threadId, - state: CredentialState.OfferReceived, + aliceCredentialRecord = await aliceCredentialRecordPromise + + faberCredentialRecordPromise = waitForCredentialRecord(faberAgent, { + threadId: aliceCredentialRecord.threadId, + state: CredentialState.ProposalReceived, }) aliceCredentialRecord = await aliceAgent.credentials.negotiateOffer({ @@ -430,9 +456,11 @@ describe('v2 credentials', () => { expect(aliceCredentialRecord.state).toBe(CredentialState.ProposalSent) testLogger.test('Faber waits for credential proposal from Alice') - faberCredentialRecord = await waitForCredentialRecord(faberAgent, { - threadId: aliceCredentialRecord.threadId, - state: CredentialState.ProposalReceived, + faberCredentialRecord = await faberCredentialRecordPromise + + aliceCredentialRecordPromise = waitForCredentialRecord(aliceAgent, { + threadId: faberCredentialRecord.threadId, + state: CredentialState.OfferReceived, }) testLogger.test('Faber sends credential offer to Alice') @@ -448,9 +476,11 @@ describe('v2 credentials', () => { }) testLogger.test('Alice waits for credential offer from Faber') - aliceCredentialRecord = await waitForCredentialRecord(aliceAgent, { - threadId: faberCredentialRecord.threadId, - state: CredentialState.OfferReceived, + aliceCredentialRecord = await aliceCredentialRecordPromise + + faberCredentialRecordPromise = waitForCredentialRecord(faberAgent, { + threadId: aliceCredentialRecord.threadId, + state: CredentialState.RequestReceived, }) const offerCredentialExchangeRecord = await aliceAgent.credentials.acceptOffer({ @@ -464,9 +494,11 @@ describe('v2 credentials', () => { }) testLogger.test('Faber waits for credential request from Alice') - faberCredentialRecord = await waitForCredentialRecord(faberAgent, { - threadId: aliceCredentialRecord.threadId, - state: CredentialState.RequestReceived, + faberCredentialRecord = await faberCredentialRecordPromise + + aliceCredentialRecordPromise = waitForCredentialRecord(aliceAgent, { + threadId: faberCredentialRecord.threadId, + state: CredentialState.CredentialReceived, }) testLogger.test('Faber sends credential to Alice') @@ -476,10 +508,7 @@ describe('v2 credentials', () => { }) testLogger.test('Alice waits for credential from Faber') - aliceCredentialRecord = await waitForCredentialRecord(aliceAgent, { - threadId: faberCredentialRecord.threadId, - state: CredentialState.CredentialReceived, - }) + aliceCredentialRecord = await aliceCredentialRecordPromise const proposalMessage = await aliceAgent.credentials.findProposalMessage(aliceCredentialRecord.id) const offerMessage = await aliceAgent.credentials.findOfferMessage(aliceCredentialRecord.id) @@ -608,7 +637,7 @@ describe('v2 credentials', () => { }) testLogger.test('Alice waits for credential offer from Faber') - aliceCredentialRecord = await waitForCredentialRecord(aliceAgent, { + aliceCredentialRecord = await waitForCredentialRecordSubject(aliceReplay, { threadId: faberCredentialExchangeRecord.threadId, state: CredentialState.OfferReceived, }) diff --git a/packages/core/tests/helpers.ts b/packages/core/tests/helpers.ts index c6e72564d7..d021344fb8 100644 --- a/packages/core/tests/helpers.ts +++ b/packages/core/tests/helpers.ts @@ -638,7 +638,17 @@ export async function setupCredentialTests( const [faberConnection, aliceConnection] = await makeConnection(faberAgent, aliceAgent) - return { faberAgent, aliceAgent, credDefId, schema, faberConnection, aliceConnection } + const faberReplay = new ReplaySubject() + const aliceReplay = new ReplaySubject() + + faberAgent.events + .observable(CredentialEventTypes.CredentialStateChanged) + .subscribe(faberReplay) + aliceAgent.events + .observable(CredentialEventTypes.CredentialStateChanged) + .subscribe(aliceReplay) + + return { faberAgent, aliceAgent, credDefId, schema, faberConnection, aliceConnection, faberReplay, aliceReplay } } export async function setupProofsTest(faberName: string, aliceName: string, autoAcceptProofs?: AutoAcceptProof) {