|
| 1 | +// |
| 2 | +// BDKSwiftExampleWalletOnboardingViewModelTests.swift |
| 3 | +// BDKSwiftExampleWalletTests |
| 4 | +// |
| 5 | +// Created by Codex on 4/9/26. |
| 6 | +// |
| 7 | + |
| 8 | +import Foundation |
| 9 | +import XCTest |
| 10 | + |
| 11 | +@testable import BDKSwiftExampleWallet |
| 12 | + |
| 13 | +final class BDKSwiftExampleWalletOnboardingViewModelTests: XCTestCase { |
| 14 | + private enum TestOnboardingError: Error { |
| 15 | + case noBackup |
| 16 | + } |
| 17 | + |
| 18 | + private func makeBDKClient( |
| 19 | + createWalletFromSeed: @escaping (String?) throws -> Void, |
| 20 | + getBackupInfo: @escaping () throws -> BackupInfo = { throw TestOnboardingError.noBackup } |
| 21 | + ) -> BDKClient { |
| 22 | + BDKClient( |
| 23 | + loadWallet: BDKClient.mock.loadWallet, |
| 24 | + deleteWallet: BDKClient.mock.deleteWallet, |
| 25 | + createWalletFromSeed: createWalletFromSeed, |
| 26 | + createWalletFromDescriptor: BDKClient.mock.createWalletFromDescriptor, |
| 27 | + createWalletFromXPub: BDKClient.mock.createWalletFromXPub, |
| 28 | + getBalance: BDKClient.mock.getBalance, |
| 29 | + transactions: BDKClient.mock.transactions, |
| 30 | + listUnspent: BDKClient.mock.listUnspent, |
| 31 | + syncWithInspector: BDKClient.mock.syncWithInspector, |
| 32 | + fullScanWithInspector: BDKClient.mock.fullScanWithInspector, |
| 33 | + getAddress: BDKClient.mock.getAddress, |
| 34 | + send: BDKClient.mock.send, |
| 35 | + sweepWif: BDKClient.mock.sweepWif, |
| 36 | + calculateFee: BDKClient.mock.calculateFee, |
| 37 | + calculateFeeRate: BDKClient.mock.calculateFeeRate, |
| 38 | + sentAndReceived: BDKClient.mock.sentAndReceived, |
| 39 | + txDetails: BDKClient.mock.txDetails, |
| 40 | + buildTransaction: BDKClient.mock.buildTransaction, |
| 41 | + getBackupInfo: getBackupInfo, |
| 42 | + needsFullScan: BDKClient.mock.needsFullScan, |
| 43 | + setNeedsFullScan: BDKClient.mock.setNeedsFullScan, |
| 44 | + getNetwork: BDKClient.mock.getNetwork, |
| 45 | + getEsploraURL: BDKClient.mock.getEsploraURL, |
| 46 | + updateNetwork: BDKClient.mock.updateNetwork, |
| 47 | + updateEsploraURL: BDKClient.mock.updateEsploraURL, |
| 48 | + getAddressType: BDKClient.mock.getAddressType, |
| 49 | + updateAddressType: BDKClient.mock.updateAddressType, |
| 50 | + getClientType: BDKClient.mock.getClientType, |
| 51 | + updateClientType: BDKClient.mock.updateClientType |
| 52 | + ) |
| 53 | + } |
| 54 | + |
| 55 | + @MainActor |
| 56 | + func testCreateWalletIgnoresRepeatedCallsWhileCreationInProgress() async { |
| 57 | + let started = expectation(description: "wallet creation started") |
| 58 | + let created = XCTNSNotificationExpectation(name: .walletCreated) |
| 59 | + let unblockCreation = DispatchSemaphore(value: 0) |
| 60 | + var createCallCount = 0 |
| 61 | + |
| 62 | + let viewModel = OnboardingViewModel( |
| 63 | + bdkClient: makeBDKClient(createWalletFromSeed: { _ in |
| 64 | + createCallCount += 1 |
| 65 | + started.fulfill() |
| 66 | + unblockCreation.wait() |
| 67 | + }) |
| 68 | + ) |
| 69 | + viewModel.words = |
| 70 | + "abandon ability able about above absent absorb abstract absurd abuse access accident" |
| 71 | + |
| 72 | + viewModel.createWallet() |
| 73 | + await fulfillment(of: [started], timeout: 1.0) |
| 74 | + viewModel.createWallet() |
| 75 | + |
| 76 | + XCTAssertTrue(viewModel.isCreatingWallet) |
| 77 | + XCTAssertEqual(createCallCount, 1) |
| 78 | + |
| 79 | + unblockCreation.signal() |
| 80 | + await fulfillment(of: [created], timeout: 1.0) |
| 81 | + XCTAssertFalse(viewModel.isCreatingWallet) |
| 82 | + } |
| 83 | +} |
0 commit comments