github.com/hyperledger/aries-framework-go@v0.3.2/pkg/wallet/didcomm_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package wallet 8 9 import ( 10 _ "embed" 11 "encoding/json" 12 "errors" 13 "fmt" 14 "testing" 15 "time" 16 17 "github.com/golang/mock/gomock" 18 "github.com/google/uuid" 19 "github.com/stretchr/testify/require" 20 21 "github.com/hyperledger/aries-framework-go/pkg/client/outofband" 22 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/model" 23 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" 24 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/didexchange" 25 issuecredentialsvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/issuecredential" 26 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/mediator" 27 outofbandSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/outofband" 28 oobv2 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/outofbandv2" 29 presentproofSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/presentproof" 30 "github.com/hyperledger/aries-framework-go/pkg/doc/verifiable" 31 mockoutofbandv2 "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/client/outofbandv2" 32 "github.com/hyperledger/aries-framework-go/pkg/internal/ldtestutil" 33 mockdidexchange "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/didexchange" 34 mockissuecredential "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/issuecredential" 35 mockmediator "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/mediator" 36 mockoutofband "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/outofband" 37 mockpresentproof "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/presentproof" 38 mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider" 39 mockstorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage" 40 "github.com/hyperledger/aries-framework-go/pkg/store/connection" 41 ) 42 43 const ( 44 exampleWebRedirect = "http://example.com/sample" 45 sampleMsgComment = "sample mock msg" 46 ) 47 48 func TestNewDidComm(t *testing.T) { 49 t.Run("test get wallet failure - present proof client initialize error", func(t *testing.T) { 50 mockctx := newDidCommMockProvider(t) 51 delete(mockctx.ServiceMap, presentproofSvc.Name) 52 53 err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase)) 54 require.NoError(t, err) 55 56 wallet, err := New(sampleUserID, mockctx) 57 require.NoError(t, err) 58 require.NotEmpty(t, wallet) 59 60 didcomm, err := NewDidComm(wallet, mockctx) 61 require.Error(t, err) 62 require.Empty(t, didcomm) 63 64 require.Contains(t, err.Error(), "failed to initialize present proof client") 65 }) 66 67 t.Run("test get wallet failure - oob client initialize error", func(t *testing.T) { 68 mockctx := newDidCommMockProvider(t) 69 delete(mockctx.ServiceMap, outofbandSvc.Name) 70 71 err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase)) 72 require.NoError(t, err) 73 74 wallet, err := New(sampleUserID, mockctx) 75 require.NoError(t, err) 76 require.NotEmpty(t, wallet) 77 78 didcomm, err := NewDidComm(wallet, mockctx) 79 require.Error(t, err) 80 require.Empty(t, didcomm) 81 require.Contains(t, err.Error(), "failed to initialize out-of-band client") 82 }) 83 84 t.Run("test get wallet failure - oob client initialize error", func(t *testing.T) { 85 mockctx := newDidCommMockProvider(t) 86 delete(mockctx.ServiceMap, didexchange.DIDExchange) 87 88 err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase)) 89 require.NoError(t, err) 90 91 wallet, err := New(sampleUserID, mockctx) 92 require.NoError(t, err) 93 require.NotEmpty(t, wallet) 94 95 didcomm, err := NewDidComm(wallet, mockctx) 96 require.Error(t, err) 97 require.Empty(t, didcomm) 98 require.Contains(t, err.Error(), "failed to initialize didexchange client") 99 }) 100 101 t.Run("test get wallet failure - connection lookup initialize error", func(t *testing.T) { 102 mockctx := newDidCommMockProvider(t) 103 mockStoreProvider := mockstorage.NewMockStoreProvider() 104 mockStoreProvider.FailNamespace = "didexchange" 105 mockctx.StorageProviderValue = mockStoreProvider 106 107 err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase)) 108 require.NoError(t, err) 109 110 wallet, err := New(sampleUserID, mockctx) 111 require.NoError(t, err) 112 require.NotEmpty(t, wallet) 113 114 didcomm, err := NewDidComm(wallet, mockctx) 115 require.Error(t, err) 116 require.Empty(t, didcomm) 117 require.Contains(t, err.Error(), "failed to initialize connection lookup") 118 }) 119 } 120 121 func TestWallet_Connect(t *testing.T) { 122 sampleDIDCommUser := uuid.New().String() 123 mockctx := newDidCommMockProvider(t) 124 err := CreateProfile(sampleDIDCommUser, mockctx, WithPassphrase(samplePassPhrase)) 125 require.NoError(t, err) 126 127 t.Run("test did connect success", func(t *testing.T) { 128 sampleConnID := uuid.New().String() 129 130 oobSvc := &mockoutofband.MockOobService{ 131 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 132 return sampleConnID, nil 133 }, 134 } 135 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 136 137 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 138 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 139 ch <- service.StateMsg{ 140 Type: service.PostState, 141 StateID: didexchange.StateIDCompleted, 142 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 143 } 144 145 return nil 146 }, 147 } 148 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 149 150 wallet, err := New(sampleDIDCommUser, mockctx) 151 require.NoError(t, err) 152 require.NotEmpty(t, wallet) 153 154 didcomm, err := NewDidComm(wallet, mockctx) 155 require.NoError(t, err) 156 require.NotEmpty(t, didcomm) 157 158 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 159 require.NoError(t, err) 160 require.NotEmpty(t, token) 161 162 defer wallet.Close() 163 164 connectionID, err := didcomm.Connect(token, &outofband.Invitation{}) 165 require.NoError(t, err) 166 require.Equal(t, sampleConnID, connectionID) 167 }) 168 169 t.Run("test did connect failure - accept invitation failure", func(t *testing.T) { 170 oobSvc := &mockoutofband.MockOobService{ 171 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 172 return "", fmt.Errorf(sampleWalletErr) 173 }, 174 } 175 176 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 177 178 wallet, err := New(sampleDIDCommUser, mockctx) 179 require.NoError(t, err) 180 require.NotEmpty(t, wallet) 181 182 didcomm, err := NewDidComm(wallet, mockctx) 183 require.NoError(t, err) 184 require.NotEmpty(t, didcomm) 185 186 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 187 require.NoError(t, err) 188 require.NotEmpty(t, token) 189 190 defer wallet.Close() 191 192 connectionID, err := didcomm.Connect(token, &outofband.Invitation{}, WithConnectTimeout(1*time.Millisecond)) 193 require.Error(t, err) 194 require.Contains(t, err.Error(), sampleWalletErr) 195 require.Contains(t, err.Error(), "failed to accept invitation") 196 require.Empty(t, connectionID) 197 }) 198 199 t.Run("test did connect failure - register event failure", func(t *testing.T) { 200 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 201 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 202 return fmt.Errorf(sampleWalletErr) 203 }, 204 } 205 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 206 207 wallet, err := New(sampleDIDCommUser, mockctx) 208 require.NoError(t, err) 209 require.NotEmpty(t, wallet) 210 211 didcomm, err := NewDidComm(wallet, mockctx) 212 require.NoError(t, err) 213 require.NotEmpty(t, didcomm) 214 215 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 216 require.NoError(t, err) 217 require.NotEmpty(t, token) 218 219 defer wallet.Close() 220 221 connectionID, err := didcomm.Connect(token, &outofband.Invitation{}, WithConnectTimeout(1*time.Millisecond)) 222 require.Error(t, err) 223 require.Contains(t, err.Error(), sampleWalletErr) 224 require.Contains(t, err.Error(), "failed to register msg event") 225 require.Empty(t, connectionID) 226 }) 227 228 t.Run("test did connect failure - state not completed", func(t *testing.T) { 229 mockctx.ServiceMap[outofbandSvc.Name] = &mockoutofband.MockOobService{} 230 mockctx.ServiceMap[didexchange.DIDExchange] = &mockdidexchange.MockDIDExchangeSvc{} 231 232 wallet, err := New(sampleDIDCommUser, mockctx) 233 require.NoError(t, err) 234 require.NotEmpty(t, wallet) 235 236 didcomm, err := NewDidComm(wallet, mockctx) 237 require.NoError(t, err) 238 require.NotEmpty(t, didcomm) 239 240 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 241 require.NoError(t, err) 242 require.NotEmpty(t, token) 243 244 defer wallet.Close() 245 246 connectionID, err := didcomm.Connect(token, &outofband.Invitation{}, WithConnectTimeout(1*time.Millisecond)) 247 require.Error(t, err) 248 require.Contains(t, err.Error(), "time out waiting for did exchange state 'completed'") 249 require.Empty(t, connectionID) 250 }) 251 252 t.Run("test did connect success - with warnings", func(t *testing.T) { 253 sampleConnID := uuid.New().String() 254 255 oobSvc := &mockoutofband.MockOobService{ 256 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 257 return sampleConnID, nil 258 }, 259 } 260 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 261 262 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 263 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 264 ch <- service.StateMsg{ 265 Type: service.PreState, 266 StateID: didexchange.StateIDCompleted, 267 } 268 269 ch <- service.StateMsg{ 270 Type: service.PostState, 271 StateID: didexchange.StateIDCompleted, 272 } 273 274 ch <- service.StateMsg{ 275 Type: service.PostState, 276 StateID: didexchange.StateIDCompleted, 277 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 278 } 279 280 return nil 281 }, 282 UnregisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 283 return fmt.Errorf(sampleWalletErr) 284 }, 285 } 286 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 287 288 wallet, err := New(sampleDIDCommUser, mockctx) 289 require.NoError(t, err) 290 require.NotEmpty(t, wallet) 291 292 didcomm, err := NewDidComm(wallet, mockctx) 293 require.NoError(t, err) 294 require.NotEmpty(t, didcomm) 295 296 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 297 require.NoError(t, err) 298 require.NotEmpty(t, token) 299 300 defer wallet.Close() 301 302 connectionID, err := didcomm.Connect(token, &outofband.Invitation{}) 303 require.NoError(t, err) 304 require.Equal(t, sampleConnID, connectionID) 305 }) 306 307 t.Run("test oob connect options", func(t *testing.T) { 308 options := []ConnectOptions{ 309 WithConnectTimeout(10 * time.Second), 310 WithRouterConnections("sample-conn"), 311 WithMyLabel("sample-label"), 312 WithReuseAnyConnection(true), 313 WithReuseDID("sample-did"), 314 } 315 316 opts := &connectOpts{} 317 for _, opt := range options { 318 opt(opts) 319 } 320 321 require.Equal(t, opts.timeout, 10*time.Second) 322 require.Equal(t, opts.Connections[0], "sample-conn") 323 require.Equal(t, opts.MyLabel(), "sample-label") 324 require.Equal(t, opts.ReuseDID, "sample-did") 325 require.True(t, opts.ReuseAny) 326 327 require.Len(t, getOobMessageOptions(opts), 3) 328 }) 329 } 330 331 func TestWallet_ProposePresentation(t *testing.T) { 332 sampleDIDCommUser := uuid.New().String() 333 mockctx := newDidCommMockProvider(t) 334 err := CreateProfile(sampleDIDCommUser, mockctx, WithPassphrase(samplePassPhrase)) 335 require.NoError(t, err) 336 337 const ( 338 myDID = "did:mydid:123" 339 theirDID = "did:theirdid:123" 340 ) 341 342 t.Run("test propose presentation success - didcomm v1", func(t *testing.T) { 343 sampleConnID := uuid.New().String() 344 345 oobSvc := &mockoutofband.MockOobService{ 346 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 347 return sampleConnID, nil 348 }, 349 } 350 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 351 352 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 353 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 354 ch <- service.StateMsg{ 355 Type: service.PostState, 356 StateID: didexchange.StateIDCompleted, 357 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 358 } 359 360 return nil 361 }, 362 } 363 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 364 365 thID := uuid.New().String() 366 367 ppSvc := &mockpresentproof.MockPresentProofSvc{ 368 ActionsFunc: func() ([]presentproofSvc.Action, error) { 369 return []presentproofSvc.Action{ 370 { 371 PIID: thID, 372 Msg: service.NewDIDCommMsgMap(&presentproofSvc.RequestPresentationV2{ 373 Comment: "mock msg", 374 }), 375 MyDID: myDID, 376 TheirDID: theirDID, 377 }, 378 }, nil 379 }, 380 HandleFunc: func(service.DIDCommMsg) (string, error) { 381 return thID, nil 382 }, 383 } 384 385 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 386 mockctx.ServiceMap[presentproofSvc.Name] = ppSvc 387 388 store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) 389 require.NoError(t, err) 390 391 record := &connection.Record{ 392 ConnectionID: sampleConnID, 393 MyDID: myDID, 394 TheirDID: theirDID, 395 } 396 recordBytes, err := json.Marshal(record) 397 require.NoError(t, err) 398 require.NoError(t, store.Put(fmt.Sprintf("conn_%s", sampleConnID), recordBytes)) 399 400 wallet, err := New(sampleDIDCommUser, mockctx) 401 require.NoError(t, err) 402 require.NotEmpty(t, wallet) 403 404 didcomm, err := NewDidComm(wallet, mockctx) 405 require.NoError(t, err) 406 require.NotEmpty(t, didcomm) 407 408 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 409 require.NoError(t, err) 410 require.NotEmpty(t, token) 411 412 defer wallet.Close() 413 414 invitation := GenericInvitation{} 415 err = json.Unmarshal([]byte(`{ 416 "@id": "abc123", 417 "@type": "https://didcomm.org/out-of-band/1.0/invitation" 418 }`), &invitation) 419 require.NoError(t, err) 420 421 msg, err := didcomm.ProposePresentation(token, &invitation, 422 WithConnectOptions(WithConnectTimeout(1*time.Millisecond))) 423 require.NoError(t, err) 424 require.NotEmpty(t, msg) 425 426 // empty invitation defaults to DIDComm v1 427 msg, err = didcomm.ProposePresentation(token, &GenericInvitation{}, 428 WithConnectOptions(WithConnectTimeout(1*time.Millisecond))) 429 require.NoError(t, err) 430 require.NotEmpty(t, msg) 431 432 // invitation with unknown version defaults to DIDComm v1 433 msg, err = didcomm.ProposePresentation(token, &GenericInvitation{version: "unknown"}, 434 WithConnectOptions(WithConnectTimeout(1*time.Millisecond))) 435 require.NoError(t, err) 436 require.NotEmpty(t, msg) 437 }) 438 439 t.Run("test propose presentation success - didcomm v2", func(t *testing.T) { 440 sampleConnID := uuid.New().String() 441 442 ctrl := gomock.NewController(t) 443 defer ctrl.Finish() 444 445 oobv2Svc := mockoutofbandv2.NewMockOobService(ctrl) 446 oobv2Svc.EXPECT().AcceptInvitation(gomock.Any(), gomock.Any()).Return(sampleConnID, nil).AnyTimes() 447 448 mockctx.ServiceMap[oobv2.Name] = oobv2Svc 449 450 thID := uuid.New().String() 451 452 ppSvc := &mockpresentproof.MockPresentProofSvc{ 453 ActionsFunc: func() ([]presentproofSvc.Action, error) { 454 return []presentproofSvc.Action{ 455 { 456 PIID: thID, 457 Msg: service.NewDIDCommMsgMap(&presentproofSvc.RequestPresentationV3{ 458 Body: presentproofSvc.RequestPresentationV3Body{ 459 Comment: "mock msg", 460 }, 461 }), 462 MyDID: myDID, 463 TheirDID: theirDID, 464 }, 465 }, nil 466 }, 467 HandleFunc: func(service.DIDCommMsg) (string, error) { 468 return thID, nil 469 }, 470 } 471 472 mockctx.ServiceMap[presentproofSvc.Name] = ppSvc 473 474 connRec, err := connection.NewRecorder(mockctx) 475 require.NoError(t, err) 476 477 record := &connection.Record{ 478 ConnectionID: sampleConnID, 479 MyDID: myDID, 480 TheirDID: theirDID, 481 DIDCommVersion: service.V2, 482 State: connection.StateNameCompleted, 483 } 484 485 err = connRec.SaveConnectionRecord(record) 486 require.NoError(t, err) 487 488 wallet, err := New(sampleDIDCommUser, mockctx) 489 require.NoError(t, err) 490 require.NotEmpty(t, wallet) 491 492 didcomm, err := NewDidComm(wallet, mockctx) 493 require.NoError(t, err) 494 require.NotEmpty(t, didcomm) 495 496 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 497 require.NoError(t, err) 498 require.NotEmpty(t, token) 499 500 defer wallet.Close() 501 502 invitation := GenericInvitation{} 503 err = json.Unmarshal([]byte(`{ 504 "id": "abc123", 505 "type": "https://didcomm.org/out-of-band/2.0/invitation" 506 }`), &invitation) 507 require.NoError(t, err) 508 509 msg, err := didcomm.ProposePresentation(token, &invitation, 510 WithConnectOptions(WithConnectTimeout(1*time.Millisecond))) 511 require.NoError(t, err) 512 require.NotEmpty(t, msg) 513 }) 514 515 t.Run("test propose presentation failure - did connect failure", func(t *testing.T) { 516 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 517 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 518 return fmt.Errorf(sampleWalletErr) 519 }, 520 } 521 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 522 523 wallet, err := New(sampleDIDCommUser, mockctx) 524 require.NoError(t, err) 525 require.NotEmpty(t, wallet) 526 527 didcomm, err := NewDidComm(wallet, mockctx) 528 require.NoError(t, err) 529 require.NotEmpty(t, didcomm) 530 531 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 532 require.NoError(t, err) 533 require.NotEmpty(t, token) 534 535 defer wallet.Close() 536 537 msg, err := didcomm.ProposePresentation(token, &GenericInvitation{}) 538 require.Error(t, err) 539 require.Contains(t, err.Error(), sampleWalletErr) 540 require.Contains(t, err.Error(), "failed to perform did connection") 541 require.Empty(t, msg) 542 }) 543 544 t.Run("test propose presentation failure - no connection found", func(t *testing.T) { 545 sampleConnID := uuid.New().String() 546 547 oobSvc := &mockoutofband.MockOobService{ 548 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 549 return sampleConnID, nil 550 }, 551 } 552 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 553 554 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 555 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 556 ch <- service.StateMsg{ 557 Type: service.PostState, 558 StateID: didexchange.StateIDCompleted, 559 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 560 } 561 562 return nil 563 }, 564 } 565 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 566 567 wallet, err := New(sampleDIDCommUser, mockctx) 568 require.NoError(t, err) 569 require.NotEmpty(t, wallet) 570 571 didcomm, err := NewDidComm(wallet, mockctx) 572 require.NoError(t, err) 573 require.NotEmpty(t, didcomm) 574 575 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 576 require.NoError(t, err) 577 require.NotEmpty(t, token) 578 579 defer wallet.Close() 580 581 msg, err := didcomm.ProposePresentation(token, &GenericInvitation{}) 582 require.Error(t, err) 583 require.Contains(t, err.Error(), "failed to lookup connection") 584 require.Empty(t, msg) 585 }) 586 587 t.Run("test propose presentation failure - failed to send", func(t *testing.T) { 588 sampleConnID := uuid.New().String() 589 590 oobSvc := &mockoutofband.MockOobService{ 591 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 592 return sampleConnID, nil 593 }, 594 } 595 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 596 597 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 598 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 599 ch <- service.StateMsg{ 600 Type: service.PostState, 601 StateID: didexchange.StateIDCompleted, 602 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 603 } 604 605 return nil 606 }, 607 } 608 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 609 610 ppSvc := &mockpresentproof.MockPresentProofSvc{ 611 HandleFunc: func(service.DIDCommMsg) (string, error) { 612 return "", fmt.Errorf(sampleWalletErr) 613 }, 614 HandleOutboundFunc: func(service.DIDCommMsg, string, string) (string, error) { 615 return "", fmt.Errorf(sampleWalletErr) 616 }, 617 } 618 mockctx.ServiceMap[presentproofSvc.Name] = ppSvc 619 620 store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) 621 require.NoError(t, err) 622 623 record := &connection.Record{ 624 ConnectionID: sampleConnID, 625 MyDID: myDID, 626 TheirDID: theirDID, 627 } 628 recordBytes, err := json.Marshal(record) 629 require.NoError(t, err) 630 require.NoError(t, store.Put(fmt.Sprintf("conn_%s", sampleConnID), recordBytes)) 631 632 wallet, err := New(sampleDIDCommUser, mockctx) 633 require.NoError(t, err) 634 require.NotEmpty(t, wallet) 635 636 didcomm, err := NewDidComm(wallet, mockctx) 637 require.NoError(t, err) 638 require.NotEmpty(t, didcomm) 639 640 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 641 require.NoError(t, err) 642 require.NotEmpty(t, token) 643 644 defer wallet.Close() 645 646 msg, err := didcomm.ProposePresentation(token, &GenericInvitation{}) 647 require.Error(t, err) 648 require.Contains(t, err.Error(), sampleWalletErr) 649 require.Contains(t, err.Error(), "failed to propose presentation from wallet") 650 require.Empty(t, msg) 651 }) 652 653 t.Run("test propose presentation failure - timeout waiting for presentation request", func(t *testing.T) { 654 sampleConnID := uuid.New().String() 655 656 oobSvc := &mockoutofband.MockOobService{ 657 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 658 return sampleConnID, nil 659 }, 660 } 661 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 662 663 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 664 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 665 ch <- service.StateMsg{ 666 Type: service.PostState, 667 StateID: didexchange.StateIDCompleted, 668 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 669 } 670 671 return nil 672 }, 673 } 674 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 675 676 ppSvc := &mockpresentproof.MockPresentProofSvc{ 677 HandleFunc: func(service.DIDCommMsg) (string, error) { 678 return uuid.New().String(), nil 679 }, 680 } 681 mockctx.ServiceMap[presentproofSvc.Name] = ppSvc 682 683 store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) 684 require.NoError(t, err) 685 686 record := &connection.Record{ 687 ConnectionID: sampleConnID, 688 MyDID: myDID, 689 TheirDID: theirDID, 690 } 691 recordBytes, err := json.Marshal(record) 692 require.NoError(t, err) 693 require.NoError(t, store.Put(fmt.Sprintf("conn_%s", sampleConnID), recordBytes)) 694 695 wallet, err := New(sampleDIDCommUser, mockctx) 696 require.NoError(t, err) 697 require.NotEmpty(t, wallet) 698 699 didcomm, err := NewDidComm(wallet, mockctx) 700 require.NoError(t, err) 701 require.NotEmpty(t, didcomm) 702 703 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 704 require.NoError(t, err) 705 require.NotEmpty(t, token) 706 707 defer wallet.Close() 708 709 msg, err := didcomm.ProposePresentation(token, &GenericInvitation{}, WithInitiateTimeout(600*time.Millisecond)) 710 require.Error(t, err) 711 require.Contains(t, err.Error(), "timeout waiting for request presentation message") 712 require.Empty(t, msg) 713 }) 714 715 t.Run("test propose presentation failure - action error", func(t *testing.T) { 716 sampleConnID := uuid.New().String() 717 718 oobSvc := &mockoutofband.MockOobService{ 719 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 720 return sampleConnID, nil 721 }, 722 } 723 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 724 725 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 726 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 727 ch <- service.StateMsg{ 728 Type: service.PostState, 729 StateID: didexchange.StateIDCompleted, 730 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 731 } 732 733 return nil 734 }, 735 } 736 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 737 738 ppSvc := &mockpresentproof.MockPresentProofSvc{ 739 HandleFunc: func(service.DIDCommMsg) (string, error) { 740 return uuid.New().String(), nil 741 }, 742 ActionsFunc: func() ([]presentproofSvc.Action, error) { 743 return nil, fmt.Errorf(sampleWalletErr) 744 }, 745 } 746 mockctx.ServiceMap[presentproofSvc.Name] = ppSvc 747 748 store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) 749 require.NoError(t, err) 750 751 record := &connection.Record{ 752 ConnectionID: sampleConnID, 753 TheirDID: theirDID, 754 } 755 recordBytes, err := json.Marshal(record) 756 require.NoError(t, err) 757 require.NoError(t, store.Put(fmt.Sprintf("conn_%s", sampleConnID), recordBytes)) 758 759 wallet, err := New(sampleDIDCommUser, mockctx) 760 require.NoError(t, err) 761 require.NotEmpty(t, wallet) 762 763 didcomm, err := NewDidComm(wallet, mockctx) 764 require.NoError(t, err) 765 require.NotEmpty(t, didcomm) 766 767 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 768 require.NoError(t, err) 769 require.NotEmpty(t, token) 770 771 defer wallet.Close() 772 773 msg, err := didcomm.ProposePresentation(token, &GenericInvitation{}, WithInitiateTimeout(1*time.Millisecond), 774 WithFromDID("did:sample:from")) 775 require.Error(t, err) 776 require.Contains(t, err.Error(), "timeout waiting for request presentation message") 777 require.Empty(t, msg) 778 }) 779 780 t.Run("test propose presentation failure - oob v2 accept error", func(t *testing.T) { 781 ctrl := gomock.NewController(t) 782 defer ctrl.Finish() 783 784 expectErr := fmt.Errorf("expected error") 785 786 oobv2Svc := mockoutofbandv2.NewMockOobService(ctrl) 787 oobv2Svc.EXPECT().AcceptInvitation(gomock.Any(), gomock.Any()).Return("", expectErr).AnyTimes() 788 789 mockctx.ServiceMap[oobv2.Name] = oobv2Svc 790 791 wallet, err := New(sampleDIDCommUser, mockctx) 792 require.NoError(t, err) 793 require.NotEmpty(t, wallet) 794 795 didcomm, err := NewDidComm(wallet, mockctx) 796 require.NoError(t, err) 797 require.NotEmpty(t, didcomm) 798 799 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 800 require.NoError(t, err) 801 require.NotEmpty(t, token) 802 803 defer wallet.Close() 804 805 invitation := GenericInvitation{} 806 err = json.Unmarshal([]byte(`{ 807 "id": "abc123", 808 "type": "https://didcomm.org/out-of-band/2.0/invitation" 809 }`), &invitation) 810 require.NoError(t, err) 811 812 _, err = didcomm.ProposePresentation(token, &invitation, 813 WithConnectOptions(WithConnectTimeout(1*time.Millisecond))) 814 require.Error(t, err) 815 require.ErrorIs(t, err, expectErr) 816 require.Contains(t, err.Error(), "failed to accept OOB v2 invitation") 817 }) 818 } 819 820 func TestWallet_PresentProof(t *testing.T) { 821 sampleDIDCommUser := uuid.New().String() 822 mockctx := newDidCommMockProvider(t) 823 err := CreateProfile(sampleDIDCommUser, mockctx, WithPassphrase(samplePassPhrase)) 824 require.NoError(t, err) 825 826 t.Run("test present proof success", func(t *testing.T) { 827 wallet, err := New(sampleDIDCommUser, mockctx) 828 require.NoError(t, err) 829 require.NotEmpty(t, wallet) 830 831 didcomm, err := NewDidComm(wallet, mockctx) 832 require.NoError(t, err) 833 require.NotEmpty(t, didcomm) 834 835 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 836 require.NoError(t, err) 837 require.NotEmpty(t, token) 838 839 defer wallet.Close() 840 841 response, err := didcomm.PresentProof(token, uuid.New().String(), FromPresentation(&verifiable.Presentation{})) 842 require.NoError(t, err) 843 require.NotEmpty(t, response) 844 require.Equal(t, model.AckStatusPENDING, response.Status) 845 }) 846 847 t.Run("test present proof success - wait for done with redirect", func(t *testing.T) { 848 thID := uuid.New().String() 849 mockPresentProofSvc := &mockpresentproof.MockPresentProofSvc{ 850 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 851 ch <- service.StateMsg{ 852 Type: service.PostState, 853 StateID: presentproofSvc.StateNameDone, 854 Properties: &mockdidexchange.MockEventProperties{ 855 Properties: map[string]interface{}{ 856 webRedirectStatusKey: model.AckStatusOK, 857 webRedirectURLKey: exampleWebRedirect, 858 }, 859 }, 860 Msg: &mockMsg{thID: thID}, 861 } 862 863 return nil 864 }, 865 } 866 mockctx.ServiceMap[presentproofSvc.Name] = mockPresentProofSvc 867 868 wallet, err := New(sampleDIDCommUser, mockctx) 869 require.NoError(t, err) 870 require.NotEmpty(t, wallet) 871 872 didcomm, err := NewDidComm(wallet, mockctx) 873 require.NoError(t, err) 874 require.NotEmpty(t, didcomm) 875 876 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 877 require.NoError(t, err) 878 require.NotEmpty(t, token) 879 880 defer wallet.Close() 881 882 response, err := didcomm.PresentProof(token, thID, FromPresentation(&verifiable.Presentation{}), 883 WaitForDone(1*time.Millisecond)) 884 require.NoError(t, err) 885 require.NotEmpty(t, response) 886 require.Equal(t, model.AckStatusOK, response.Status) 887 require.Equal(t, exampleWebRedirect, response.RedirectURL) 888 }) 889 890 t.Run("test present proof success - wait for abandoned with redirect", func(t *testing.T) { 891 thID := uuid.New().String() 892 mockPresentProofSvc := &mockpresentproof.MockPresentProofSvc{ 893 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 894 ch <- service.StateMsg{ 895 Type: service.PostState, 896 StateID: presentproofSvc.StateNameAbandoned, 897 Properties: &mockdidexchange.MockEventProperties{ 898 Properties: map[string]interface{}{ 899 webRedirectStatusKey: model.AckStatusFAIL, 900 webRedirectURLKey: exampleWebRedirect, 901 }, 902 }, 903 Msg: &mockMsg{thID: thID}, 904 } 905 906 return nil 907 }, 908 } 909 mockctx.ServiceMap[presentproofSvc.Name] = mockPresentProofSvc 910 911 wallet, err := New(sampleDIDCommUser, mockctx) 912 require.NoError(t, err) 913 require.NotEmpty(t, wallet) 914 915 didcomm, err := NewDidComm(wallet, mockctx) 916 require.NoError(t, err) 917 require.NotEmpty(t, didcomm) 918 919 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 920 require.NoError(t, err) 921 require.NotEmpty(t, token) 922 923 defer wallet.Close() 924 925 response, err := didcomm.PresentProof(token, thID, FromPresentation(&verifiable.Presentation{}), 926 WaitForDone(1*time.Millisecond)) 927 require.NoError(t, err) 928 require.NotEmpty(t, response) 929 require.Equal(t, model.AckStatusFAIL, response.Status) 930 require.Equal(t, exampleWebRedirect, response.RedirectURL) 931 }) 932 933 t.Run("test present proof success - wait for done no redirect", func(t *testing.T) { 934 thID := uuid.New().String() 935 mockPresentProofSvc := &mockpresentproof.MockPresentProofSvc{ 936 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 937 ch <- service.StateMsg{ 938 Type: service.PostState, 939 StateID: presentproofSvc.StateNameDone, 940 Properties: &mockdidexchange.MockEventProperties{}, 941 Msg: &mockMsg{thID: thID}, 942 } 943 944 return nil 945 }, 946 } 947 mockctx.ServiceMap[presentproofSvc.Name] = mockPresentProofSvc 948 949 wallet, err := New(sampleDIDCommUser, mockctx) 950 require.NoError(t, err) 951 require.NotEmpty(t, wallet) 952 953 didcomm, err := NewDidComm(wallet, mockctx) 954 require.NoError(t, err) 955 require.NotEmpty(t, didcomm) 956 957 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 958 require.NoError(t, err) 959 require.NotEmpty(t, token) 960 961 defer wallet.Close() 962 963 response, err := didcomm.PresentProof(token, thID, FromPresentation(&verifiable.Presentation{}), 964 WaitForDone(1*time.Millisecond)) 965 require.NoError(t, err) 966 require.NotEmpty(t, response) 967 require.Equal(t, model.AckStatusOK, response.Status) 968 require.Empty(t, response.RedirectURL) 969 }) 970 971 t.Run("test present proof failure - wait for abandoned no redirect", func(t *testing.T) { 972 thID := uuid.New().String() 973 mockPresentProofSvc := &mockpresentproof.MockPresentProofSvc{ 974 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 975 ch <- service.StateMsg{ 976 Type: service.PostState, 977 StateID: presentproofSvc.StateNameAbandoned, 978 Properties: &mockdidexchange.MockEventProperties{}, 979 Msg: &mockMsg{thID: thID}, 980 } 981 982 return nil 983 }, 984 } 985 mockctx.ServiceMap[presentproofSvc.Name] = mockPresentProofSvc 986 987 wallet, err := New(sampleDIDCommUser, mockctx) 988 require.NoError(t, err) 989 require.NotEmpty(t, wallet) 990 991 didcomm, err := NewDidComm(wallet, mockctx) 992 require.NoError(t, err) 993 require.NotEmpty(t, didcomm) 994 995 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 996 require.NoError(t, err) 997 require.NotEmpty(t, token) 998 999 defer wallet.Close() 1000 1001 response, err := didcomm.PresentProof(token, thID, FromPresentation(&verifiable.Presentation{}), 1002 WaitForDone(1*time.Millisecond)) 1003 require.NoError(t, err) 1004 require.NotEmpty(t, response) 1005 require.Equal(t, model.AckStatusFAIL, response.Status) 1006 require.Empty(t, response.RedirectURL) 1007 }) 1008 1009 t.Run("test present proof failure", func(t *testing.T) { 1010 ppSvc := &mockpresentproof.MockPresentProofSvc{ 1011 ActionContinueFunc: func(string, ...presentproofSvc.Opt) error { 1012 return fmt.Errorf(sampleWalletErr) 1013 }, 1014 } 1015 1016 mockctx.ServiceMap[presentproofSvc.Name] = ppSvc 1017 1018 wallet, err := New(sampleDIDCommUser, mockctx) 1019 require.NoError(t, err) 1020 require.NotEmpty(t, wallet) 1021 1022 didcomm, err := NewDidComm(wallet, mockctx) 1023 require.NoError(t, err) 1024 require.NotEmpty(t, didcomm) 1025 1026 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1027 require.NoError(t, err) 1028 require.NotEmpty(t, token) 1029 1030 defer wallet.Close() 1031 1032 response, err := didcomm.PresentProof(token, uuid.New().String(), FromRawPresentation([]byte("{}"))) 1033 require.Error(t, err) 1034 require.Contains(t, err.Error(), sampleWalletErr) 1035 require.Empty(t, response) 1036 }) 1037 1038 t.Run("test present proof failure - failed to register message event", func(t *testing.T) { 1039 thID := uuid.New().String() 1040 mockPresentProofSvc := &mockpresentproof.MockPresentProofSvc{ 1041 RegisterMsgEventErr: errors.New(sampleWalletErr), 1042 } 1043 mockctx.ServiceMap[presentproofSvc.Name] = mockPresentProofSvc 1044 1045 wallet, err := New(sampleDIDCommUser, mockctx) 1046 require.NoError(t, err) 1047 require.NotEmpty(t, wallet) 1048 1049 didcomm, err := NewDidComm(wallet, mockctx) 1050 require.NoError(t, err) 1051 require.NotEmpty(t, didcomm) 1052 1053 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1054 require.NoError(t, err) 1055 require.NotEmpty(t, token) 1056 1057 defer wallet.Close() 1058 1059 response, err := didcomm.PresentProof(token, thID, FromPresentation(&verifiable.Presentation{}), 1060 WaitForDone(1*time.Millisecond)) 1061 require.Error(t, err) 1062 require.Contains(t, err.Error(), sampleWalletErr) 1063 require.Empty(t, response) 1064 }) 1065 1066 t.Run("test present proof failure - wait for done timeout", func(t *testing.T) { 1067 thID := uuid.New().String() 1068 mockPresentProofSvc := &mockpresentproof.MockPresentProofSvc{ 1069 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1070 ch <- service.StateMsg{ 1071 Type: service.PreState, 1072 } 1073 1074 ch <- service.StateMsg{ 1075 Type: service.PostState, 1076 } 1077 1078 ch <- service.StateMsg{ 1079 Type: service.PostState, 1080 Msg: &mockMsg{thID: "invalid"}, 1081 } 1082 1083 ch <- service.StateMsg{ 1084 Type: service.PostState, 1085 StateID: "invalid", 1086 Msg: &mockMsg{thID: thID, fail: errors.New(sampleWalletErr)}, 1087 } 1088 1089 ch <- service.StateMsg{ 1090 Type: service.PostState, 1091 StateID: "invalid", 1092 Msg: &mockMsg{thID: thID}, 1093 } 1094 1095 return nil 1096 }, 1097 UnregisterMsgEventErr: errors.New(sampleWalletErr), 1098 } 1099 mockctx.ServiceMap[presentproofSvc.Name] = mockPresentProofSvc 1100 1101 wallet, err := New(sampleDIDCommUser, mockctx) 1102 require.NoError(t, err) 1103 require.NotEmpty(t, wallet) 1104 1105 didcomm, err := NewDidComm(wallet, mockctx) 1106 require.NoError(t, err) 1107 require.NotEmpty(t, didcomm) 1108 1109 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1110 require.NoError(t, err) 1111 require.NotEmpty(t, token) 1112 1113 defer wallet.Close() 1114 1115 response, err := didcomm.PresentProof(token, thID, FromPresentation(&verifiable.Presentation{}), 1116 WaitForDone(1*time.Millisecond)) 1117 require.Error(t, err) 1118 require.Contains(t, err.Error(), "time out waiting for credential interaction to get completed") 1119 require.Empty(t, response) 1120 }) 1121 } 1122 1123 func TestWallet_ProposeCredential(t *testing.T) { 1124 sampleDIDCommUser := uuid.New().String() 1125 mockctx := newDidCommMockProvider(t) 1126 err := CreateProfile(sampleDIDCommUser, mockctx, WithPassphrase(samplePassPhrase)) 1127 require.NoError(t, err) 1128 1129 const ( 1130 myDID = "did:mydid:123" 1131 theirDID = "did:theirdid:123" 1132 ) 1133 1134 t.Run("test propose credential success", func(t *testing.T) { 1135 sampleConnID := uuid.New().String() 1136 1137 oobSvc := &mockoutofband.MockOobService{ 1138 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 1139 return sampleConnID, nil 1140 }, 1141 } 1142 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 1143 1144 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 1145 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1146 ch <- service.StateMsg{ 1147 Type: service.PostState, 1148 StateID: didexchange.StateIDCompleted, 1149 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 1150 } 1151 1152 return nil 1153 }, 1154 } 1155 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 1156 1157 thID := uuid.New().String() 1158 1159 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1160 ActionsFunc: func() ([]issuecredentialsvc.Action, error) { 1161 return []issuecredentialsvc.Action{ 1162 { 1163 PIID: thID, 1164 Msg: service.NewDIDCommMsgMap(&issuecredentialsvc.OfferCredentialV2{ 1165 Comment: sampleMsgComment, 1166 }), 1167 MyDID: myDID, 1168 TheirDID: theirDID, 1169 }, 1170 }, nil 1171 }, 1172 HandleFunc: func(service.DIDCommMsg) (string, error) { 1173 return thID, nil 1174 }, 1175 } 1176 1177 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 1178 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1179 1180 store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) 1181 require.NoError(t, err) 1182 1183 record := &connection.Record{ 1184 ConnectionID: sampleConnID, 1185 MyDID: myDID, 1186 TheirDID: theirDID, 1187 } 1188 recordBytes, err := json.Marshal(record) 1189 require.NoError(t, err) 1190 require.NoError(t, store.Put(fmt.Sprintf("conn_%s", sampleConnID), recordBytes)) 1191 1192 wallet, err := New(sampleDIDCommUser, mockctx) 1193 require.NoError(t, err) 1194 require.NotEmpty(t, wallet) 1195 1196 didcomm, err := NewDidComm(wallet, mockctx) 1197 require.NoError(t, err) 1198 require.NotEmpty(t, didcomm) 1199 1200 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1201 require.NoError(t, err) 1202 require.NotEmpty(t, token) 1203 1204 defer wallet.Close() 1205 1206 msg, err := didcomm.ProposeCredential(token, &GenericInvitation{}, 1207 WithConnectOptions(WithConnectTimeout(1*time.Millisecond))) 1208 require.NoError(t, err) 1209 require.NotEmpty(t, msg) 1210 1211 offer := &issuecredentialsvc.OfferCredentialV2{} 1212 1213 err = msg.Decode(offer) 1214 require.NoError(t, err) 1215 require.NotEmpty(t, offer) 1216 require.Equal(t, sampleMsgComment, offer.Comment) 1217 }) 1218 1219 t.Run("test propose credential failure - did connect failure", func(t *testing.T) { 1220 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 1221 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1222 return fmt.Errorf(sampleWalletErr) 1223 }, 1224 } 1225 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 1226 1227 wallet, err := New(sampleDIDCommUser, mockctx) 1228 require.NoError(t, err) 1229 require.NotEmpty(t, wallet) 1230 1231 didcomm, err := NewDidComm(wallet, mockctx) 1232 require.NoError(t, err) 1233 require.NotEmpty(t, didcomm) 1234 1235 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1236 require.NoError(t, err) 1237 require.NotEmpty(t, token) 1238 1239 defer wallet.Close() 1240 1241 msg, err := didcomm.ProposeCredential(token, &GenericInvitation{}) 1242 require.Error(t, err) 1243 require.Contains(t, err.Error(), sampleWalletErr) 1244 require.Contains(t, err.Error(), "failed to perform did connection") 1245 require.Empty(t, msg) 1246 }) 1247 1248 t.Run("test propose credential failure - oobv2 accept error", func(t *testing.T) { 1249 ctrl := gomock.NewController(t) 1250 defer ctrl.Finish() 1251 1252 expectErr := fmt.Errorf("expected error") 1253 1254 oobv2Svc := mockoutofbandv2.NewMockOobService(ctrl) 1255 oobv2Svc.EXPECT().AcceptInvitation(gomock.Any(), gomock.Any()).Return("", expectErr).AnyTimes() 1256 1257 mockctx.ServiceMap[oobv2.Name] = oobv2Svc 1258 1259 wallet, err := New(sampleDIDCommUser, mockctx) 1260 require.NoError(t, err) 1261 require.NotEmpty(t, wallet) 1262 1263 didcomm, err := NewDidComm(wallet, mockctx) 1264 require.NoError(t, err) 1265 require.NotEmpty(t, didcomm) 1266 1267 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1268 require.NoError(t, err) 1269 require.NotEmpty(t, token) 1270 1271 defer wallet.Close() 1272 1273 invitation := GenericInvitation{} 1274 err = json.Unmarshal([]byte(`{ 1275 "id": "abc123", 1276 "type": "https://didcomm.org/out-of-band/2.0/invitation" 1277 }`), &invitation) 1278 require.NoError(t, err) 1279 1280 _, err = didcomm.ProposeCredential(token, &invitation, 1281 WithConnectOptions(WithConnectTimeout(1*time.Millisecond))) 1282 require.Error(t, err) 1283 require.ErrorIs(t, err, expectErr) 1284 require.Contains(t, err.Error(), "failed to accept OOB v2 invitation") 1285 }) 1286 1287 t.Run("test propose credential failure - no connection found", func(t *testing.T) { 1288 sampleConnID := uuid.New().String() 1289 1290 oobSvc := &mockoutofband.MockOobService{ 1291 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 1292 return sampleConnID, nil 1293 }, 1294 } 1295 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 1296 1297 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 1298 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1299 ch <- service.StateMsg{ 1300 Type: service.PostState, 1301 StateID: didexchange.StateIDCompleted, 1302 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 1303 } 1304 1305 return nil 1306 }, 1307 } 1308 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 1309 1310 wallet, err := New(sampleDIDCommUser, mockctx) 1311 require.NoError(t, err) 1312 require.NotEmpty(t, wallet) 1313 1314 didcomm, err := NewDidComm(wallet, mockctx) 1315 require.NoError(t, err) 1316 require.NotEmpty(t, didcomm) 1317 1318 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1319 require.NoError(t, err) 1320 require.NotEmpty(t, token) 1321 1322 defer wallet.Close() 1323 1324 msg, err := didcomm.ProposeCredential(token, &GenericInvitation{}) 1325 require.Error(t, err) 1326 require.Contains(t, err.Error(), "failed to lookup connection") 1327 require.Empty(t, msg) 1328 }) 1329 1330 t.Run("test propose credential failure - failed to send", func(t *testing.T) { 1331 sampleConnID := uuid.New().String() 1332 1333 oobSvc := &mockoutofband.MockOobService{ 1334 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 1335 return sampleConnID, nil 1336 }, 1337 } 1338 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 1339 1340 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 1341 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1342 ch <- service.StateMsg{ 1343 Type: service.PostState, 1344 StateID: didexchange.StateIDCompleted, 1345 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 1346 } 1347 1348 return nil 1349 }, 1350 } 1351 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 1352 1353 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1354 HandleFunc: func(service.DIDCommMsg) (string, error) { 1355 return "", fmt.Errorf(sampleWalletErr) 1356 }, 1357 HandleOutboundFunc: func(service.DIDCommMsg, string, string) (string, error) { 1358 return "", fmt.Errorf(sampleWalletErr) 1359 }, 1360 } 1361 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1362 1363 store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) 1364 require.NoError(t, err) 1365 1366 record := &connection.Record{ 1367 ConnectionID: sampleConnID, 1368 MyDID: myDID, 1369 TheirDID: theirDID, 1370 } 1371 recordBytes, err := json.Marshal(record) 1372 require.NoError(t, err) 1373 require.NoError(t, store.Put(fmt.Sprintf("conn_%s", sampleConnID), recordBytes)) 1374 1375 wallet, err := New(sampleDIDCommUser, mockctx) 1376 require.NoError(t, err) 1377 require.NotEmpty(t, wallet) 1378 1379 didcomm, err := NewDidComm(wallet, mockctx) 1380 require.NoError(t, err) 1381 require.NotEmpty(t, didcomm) 1382 1383 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1384 require.NoError(t, err) 1385 require.NotEmpty(t, token) 1386 1387 defer wallet.Close() 1388 1389 msg, err := didcomm.ProposeCredential(token, &GenericInvitation{}) 1390 require.Error(t, err) 1391 require.Contains(t, err.Error(), sampleWalletErr) 1392 require.Contains(t, err.Error(), "failed to propose credential from wallet") 1393 require.Empty(t, msg) 1394 }) 1395 1396 t.Run("test propose credential failure - timeout waiting for offer credential msg", func(t *testing.T) { 1397 sampleConnID := uuid.New().String() 1398 1399 oobSvc := &mockoutofband.MockOobService{ 1400 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 1401 return sampleConnID, nil 1402 }, 1403 } 1404 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 1405 1406 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 1407 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1408 ch <- service.StateMsg{ 1409 Type: service.PostState, 1410 StateID: didexchange.StateIDCompleted, 1411 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 1412 } 1413 1414 return nil 1415 }, 1416 } 1417 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 1418 1419 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1420 HandleFunc: func(service.DIDCommMsg) (string, error) { 1421 return uuid.New().String(), nil 1422 }, 1423 } 1424 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1425 1426 store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) 1427 require.NoError(t, err) 1428 1429 record := &connection.Record{ 1430 ConnectionID: sampleConnID, 1431 MyDID: myDID, 1432 TheirDID: theirDID, 1433 } 1434 recordBytes, err := json.Marshal(record) 1435 require.NoError(t, err) 1436 require.NoError(t, store.Put(fmt.Sprintf("conn_%s", sampleConnID), recordBytes)) 1437 1438 wallet, err := New(sampleDIDCommUser, mockctx) 1439 require.NoError(t, err) 1440 require.NotEmpty(t, wallet) 1441 1442 didcomm, err := NewDidComm(wallet, mockctx) 1443 require.NoError(t, err) 1444 require.NotEmpty(t, didcomm) 1445 1446 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1447 require.NoError(t, err) 1448 require.NotEmpty(t, token) 1449 1450 defer wallet.Close() 1451 1452 msg, err := didcomm.ProposeCredential(token, &GenericInvitation{}, WithInitiateTimeout(600*time.Millisecond)) 1453 require.Error(t, err) 1454 require.Contains(t, err.Error(), "timeout waiting for offer credential message") 1455 require.Empty(t, msg) 1456 }) 1457 1458 t.Run("test propose presentation failure - action error", func(t *testing.T) { 1459 sampleConnID := uuid.New().String() 1460 1461 oobSvc := &mockoutofband.MockOobService{ 1462 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 1463 return sampleConnID, nil 1464 }, 1465 } 1466 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 1467 1468 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 1469 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1470 ch <- service.StateMsg{ 1471 Type: service.PostState, 1472 StateID: didexchange.StateIDCompleted, 1473 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 1474 } 1475 1476 return nil 1477 }, 1478 } 1479 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 1480 1481 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1482 HandleFunc: func(service.DIDCommMsg) (string, error) { 1483 return uuid.New().String(), nil 1484 }, 1485 ActionsFunc: func() ([]issuecredentialsvc.Action, error) { 1486 return nil, fmt.Errorf(sampleWalletErr) 1487 }, 1488 } 1489 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1490 1491 store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) 1492 require.NoError(t, err) 1493 1494 record := &connection.Record{ 1495 ConnectionID: sampleConnID, 1496 TheirDID: theirDID, 1497 } 1498 recordBytes, err := json.Marshal(record) 1499 require.NoError(t, err) 1500 require.NoError(t, store.Put(fmt.Sprintf("conn_%s", sampleConnID), recordBytes)) 1501 1502 wallet, err := New(sampleDIDCommUser, mockctx) 1503 require.NoError(t, err) 1504 require.NotEmpty(t, wallet) 1505 1506 didcomm, err := NewDidComm(wallet, mockctx) 1507 require.NoError(t, err) 1508 require.NotEmpty(t, didcomm) 1509 1510 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1511 require.NoError(t, err) 1512 require.NotEmpty(t, token) 1513 1514 defer wallet.Close() 1515 1516 msg, err := didcomm.ProposeCredential(token, &GenericInvitation{}, WithInitiateTimeout(1*time.Millisecond), 1517 WithFromDID("did:sample:from")) 1518 require.Error(t, err) 1519 require.Contains(t, err.Error(), "timeout waiting for offer credential message") 1520 require.Empty(t, msg) 1521 }) 1522 } 1523 1524 func TestWallet_RequestCredential(t *testing.T) { 1525 sampleDIDCommUser := uuid.New().String() 1526 mockctx := newDidCommMockProvider(t) 1527 err := CreateProfile(sampleDIDCommUser, mockctx, WithPassphrase(samplePassPhrase)) 1528 require.NoError(t, err) 1529 1530 t.Run("test request credential success", func(t *testing.T) { 1531 wallet, err := New(sampleDIDCommUser, mockctx) 1532 require.NoError(t, err) 1533 require.NotEmpty(t, wallet) 1534 1535 didcomm, err := NewDidComm(wallet, mockctx) 1536 require.NoError(t, err) 1537 require.NotEmpty(t, didcomm) 1538 1539 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1540 require.NoError(t, err) 1541 require.NotEmpty(t, token) 1542 1543 defer wallet.Close() 1544 1545 response, err := didcomm.RequestCredential(token, uuid.New().String(), FromPresentation(&verifiable.Presentation{})) 1546 require.NoError(t, err) 1547 require.NotEmpty(t, response) 1548 require.Equal(t, model.AckStatusPENDING, response.Status) 1549 }) 1550 1551 t.Run("test request credential success - wait for done with redirect", func(t *testing.T) { 1552 thID := uuid.New().String() 1553 1554 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1555 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1556 ch <- service.StateMsg{ 1557 Type: service.PostState, 1558 StateID: stateNameDone, 1559 Properties: &mockdidexchange.MockEventProperties{ 1560 Properties: map[string]interface{}{ 1561 webRedirectStatusKey: model.AckStatusOK, 1562 webRedirectURLKey: exampleWebRedirect, 1563 }, 1564 }, 1565 Msg: &mockMsg{thID: thID}, 1566 } 1567 1568 return nil 1569 }, 1570 } 1571 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1572 1573 wallet, err := New(sampleDIDCommUser, mockctx) 1574 require.NoError(t, err) 1575 require.NotEmpty(t, wallet) 1576 1577 didcomm, err := NewDidComm(wallet, mockctx) 1578 require.NoError(t, err) 1579 require.NotEmpty(t, didcomm) 1580 1581 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1582 require.NoError(t, err) 1583 require.NotEmpty(t, token) 1584 1585 defer wallet.Close() 1586 1587 response, err := didcomm.RequestCredential(token, thID, FromPresentation(&verifiable.Presentation{}), 1588 WaitForDone(0)) 1589 require.NoError(t, err) 1590 require.NotEmpty(t, response) 1591 require.Equal(t, model.AckStatusOK, response.Status) 1592 require.Equal(t, exampleWebRedirect, response.RedirectURL) 1593 }) 1594 1595 t.Run("test for request credential - wait for problem report with redirect", func(t *testing.T) { 1596 thID := uuid.New().String() 1597 1598 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1599 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1600 ch <- service.StateMsg{ 1601 Type: service.PostState, 1602 StateID: stateNameAbandoned, 1603 Properties: &mockdidexchange.MockEventProperties{ 1604 Properties: map[string]interface{}{ 1605 webRedirectStatusKey: model.AckStatusFAIL, 1606 webRedirectURLKey: exampleWebRedirect, 1607 }, 1608 }, 1609 Msg: &mockMsg{thID: thID}, 1610 } 1611 1612 return nil 1613 }, 1614 } 1615 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1616 1617 wallet, err := New(sampleDIDCommUser, mockctx) 1618 require.NoError(t, err) 1619 require.NotEmpty(t, wallet) 1620 1621 didcomm, err := NewDidComm(wallet, mockctx) 1622 require.NoError(t, err) 1623 require.NotEmpty(t, didcomm) 1624 1625 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1626 require.NoError(t, err) 1627 require.NotEmpty(t, token) 1628 1629 defer wallet.Close() 1630 1631 response, err := didcomm.RequestCredential(token, thID, FromPresentation(&verifiable.Presentation{}), 1632 WaitForDone(1*time.Millisecond)) 1633 require.NoError(t, err) 1634 require.NotEmpty(t, response) 1635 require.Equal(t, model.AckStatusFAIL, response.Status) 1636 require.Equal(t, exampleWebRedirect, response.RedirectURL) 1637 }) 1638 1639 t.Run("test request credential success - wait for done no redirect", func(t *testing.T) { 1640 thID := uuid.New().String() 1641 1642 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1643 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1644 ch <- service.StateMsg{ 1645 Type: service.PostState, 1646 StateID: stateNameDone, 1647 Properties: &mockdidexchange.MockEventProperties{}, 1648 Msg: &mockMsg{thID: thID}, 1649 } 1650 1651 return nil 1652 }, 1653 } 1654 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1655 1656 wallet, err := New(sampleDIDCommUser, mockctx) 1657 require.NoError(t, err) 1658 require.NotEmpty(t, wallet) 1659 1660 didcomm, err := NewDidComm(wallet, mockctx) 1661 require.NoError(t, err) 1662 require.NotEmpty(t, didcomm) 1663 1664 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1665 require.NoError(t, err) 1666 require.NotEmpty(t, token) 1667 1668 defer wallet.Close() 1669 1670 response, err := didcomm.RequestCredential(token, thID, FromPresentation(&verifiable.Presentation{}), 1671 WaitForDone(10*time.Millisecond)) 1672 require.NoError(t, err) 1673 require.NotEmpty(t, response) 1674 require.Equal(t, model.AckStatusOK, response.Status) 1675 require.Empty(t, response.RedirectURL) 1676 }) 1677 1678 t.Run("test request credential failure - wait for problem report no redirect", func(t *testing.T) { 1679 thID := uuid.New().String() 1680 1681 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1682 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1683 ch <- service.StateMsg{ 1684 Type: service.PostState, 1685 StateID: stateNameAbandoned, 1686 Properties: &mockdidexchange.MockEventProperties{}, 1687 Msg: &mockMsg{thID: thID}, 1688 } 1689 1690 return nil 1691 }, 1692 } 1693 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1694 1695 wallet, err := New(sampleDIDCommUser, mockctx) 1696 require.NoError(t, err) 1697 require.NotEmpty(t, wallet) 1698 1699 didcomm, err := NewDidComm(wallet, mockctx) 1700 require.NoError(t, err) 1701 require.NotEmpty(t, didcomm) 1702 1703 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1704 require.NoError(t, err) 1705 require.NotEmpty(t, token) 1706 1707 defer wallet.Close() 1708 1709 response, err := didcomm.RequestCredential(token, thID, FromPresentation(&verifiable.Presentation{}), 1710 WaitForDone(1*time.Millisecond)) 1711 require.NoError(t, err) 1712 require.NotEmpty(t, response) 1713 require.Equal(t, model.AckStatusFAIL, response.Status) 1714 require.Empty(t, response.RedirectURL) 1715 }) 1716 1717 t.Run("test request credential failure", func(t *testing.T) { 1718 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1719 ActionContinueFunc: func(string, ...issuecredentialsvc.Opt) error { 1720 return fmt.Errorf(sampleWalletErr) 1721 }, 1722 } 1723 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1724 1725 wallet, err := New(sampleDIDCommUser, mockctx) 1726 require.NoError(t, err) 1727 require.NotEmpty(t, wallet) 1728 1729 didcomm, err := NewDidComm(wallet, mockctx) 1730 require.NoError(t, err) 1731 require.NotEmpty(t, didcomm) 1732 1733 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1734 require.NoError(t, err) 1735 require.NotEmpty(t, token) 1736 1737 defer wallet.Close() 1738 1739 response, err := didcomm.RequestCredential(token, uuid.New().String(), FromRawPresentation([]byte("{}"))) 1740 require.Error(t, err) 1741 require.Contains(t, err.Error(), sampleWalletErr) 1742 require.Empty(t, response) 1743 }) 1744 1745 t.Run("test request credential failure - failed to register msg event", func(t *testing.T) { 1746 thID := uuid.New().String() 1747 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1748 RegisterMsgEventErr: errors.New(sampleWalletErr), 1749 } 1750 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1751 1752 wallet, err := New(sampleDIDCommUser, mockctx) 1753 require.NoError(t, err) 1754 require.NotEmpty(t, wallet) 1755 1756 didcomm, err := NewDidComm(wallet, mockctx) 1757 require.NoError(t, err) 1758 require.NotEmpty(t, didcomm) 1759 1760 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1761 require.NoError(t, err) 1762 require.NotEmpty(t, token) 1763 1764 defer wallet.Close() 1765 1766 response, err := didcomm.RequestCredential(token, thID, FromPresentation(&verifiable.Presentation{}), 1767 WaitForDone(1*time.Millisecond)) 1768 require.Error(t, err) 1769 require.Contains(t, err.Error(), sampleWalletErr) 1770 require.Empty(t, response) 1771 }) 1772 1773 t.Run("test request credential success - wait for done timeout", func(t *testing.T) { 1774 thID := uuid.New().String() 1775 1776 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1777 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1778 ch <- service.StateMsg{ 1779 Type: service.PreState, 1780 } 1781 1782 ch <- service.StateMsg{ 1783 Type: service.PostState, 1784 } 1785 1786 ch <- service.StateMsg{ 1787 Type: service.PostState, 1788 Msg: &mockMsg{thID: "invalid"}, 1789 } 1790 1791 ch <- service.StateMsg{ 1792 Type: service.PostState, 1793 StateID: "invalid", 1794 Msg: &mockMsg{thID: thID, fail: errors.New(sampleWalletErr)}, 1795 } 1796 1797 ch <- service.StateMsg{ 1798 Type: service.PostState, 1799 StateID: "invalid", 1800 Msg: &mockMsg{thID: thID}, 1801 } 1802 1803 return nil 1804 }, 1805 UnregisterMsgEventErr: errors.New(sampleWalletErr), 1806 } 1807 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1808 1809 wallet, err := New(sampleDIDCommUser, mockctx) 1810 require.NoError(t, err) 1811 require.NotEmpty(t, wallet) 1812 1813 didcomm, err := NewDidComm(wallet, mockctx) 1814 require.NoError(t, err) 1815 require.NotEmpty(t, didcomm) 1816 1817 token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase)) 1818 require.NoError(t, err) 1819 require.NotEmpty(t, token) 1820 1821 defer wallet.Close() 1822 1823 response, err := didcomm.RequestCredential(token, thID, FromPresentation(&verifiable.Presentation{}), 1824 WaitForDone(700*time.Millisecond)) 1825 require.Error(t, err) 1826 require.Contains(t, err.Error(), "time out waiting for credential interaction to get completed") 1827 require.Empty(t, response) 1828 }) 1829 } 1830 1831 func newDidCommMockProvider(t *testing.T) *mockprovider.Provider { 1832 t.Helper() 1833 1834 loader, err := ldtestutil.DocumentLoader() 1835 require.NoError(t, err) 1836 1837 serviceMap := map[string]interface{}{ 1838 presentproofSvc.Name: &mockpresentproof.MockPresentProofSvc{}, 1839 outofbandSvc.Name: &mockoutofband.MockOobService{}, 1840 didexchange.DIDExchange: &mockdidexchange.MockDIDExchangeSvc{}, 1841 mediator.Coordination: &mockmediator.MockMediatorSvc{}, 1842 issuecredentialsvc.Name: &mockissuecredential.MockIssueCredentialSvc{}, 1843 oobv2.Name: &mockoutofbandv2.MockOobService{}, 1844 } 1845 1846 return &mockprovider.Provider{ 1847 StorageProviderValue: mockstorage.NewMockStoreProvider(), 1848 ProtocolStateStorageProviderValue: mockstorage.NewMockStoreProvider(), 1849 DocumentLoaderValue: loader, 1850 ServiceMap: serviceMap, 1851 } 1852 } 1853 1854 // mockMsg containing custom parent thread ID. 1855 type mockMsg struct { 1856 *service.DIDCommMsgMap 1857 thID string 1858 fail error 1859 msgType string 1860 } 1861 1862 func (m *mockMsg) ParentThreadID() string { 1863 return m.thID 1864 } 1865 1866 func (m *mockMsg) ThreadID() (string, error) { 1867 return m.thID, m.fail 1868 } 1869 1870 func (m *mockMsg) Type() string { 1871 if m.msgType != "" { 1872 return m.msgType 1873 } 1874 1875 if m.DIDCommMsgMap != nil { 1876 return m.DIDCommMsgMap.Type() 1877 } 1878 1879 return "" 1880 }