[#427] Add not enough disk space screen (#429)

Closes #427

- This is scaffold work for #427. Logic is done and some basic UI.
- Logic that works with free disk space is in `DiskSpaceChecker`. Use
  `WrappedDiskSpaceChecker` to get live or mocked instances of `DiskSpaceChecker`.
- You can either use `mockEmptyDisk` which mocks situation when there
  is enough space on disk.
- Or you can use `mockFullDisk` to mock situation when there isn't enough space on disk.
This commit is contained in:
Michal Fousek 2022-09-30 15:49:07 +02:00 committed by GitHub
parent d807f86d49
commit ad575b8173
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 249 additions and 37 deletions

3
.gitignore vendored
View File

@ -51,9 +51,6 @@ playground.xcworkspace
Carthage/Checkouts
Carthage/Build
Example/**/Carthage
# Accio dependency management
Dependencies/
.accio/
# fastlane
fastlane/report.xml

View File

@ -68,11 +68,15 @@
2EDA07A027EDE18C00D6F09B /* TCATextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EDA079F27EDE18C00D6F09B /* TCATextField.swift */; };
2EDA07A227EDE1AE00D6F09B /* TextFieldFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EDA07A127EDE1AE00D6F09B /* TextFieldFooter.swift */; };
2EDA07A427EDE2A900D6F09B /* DebugFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EDA07A327EDE2A900D6F09B /* DebugFrame.swift */; };
3448CB3228E47666006ADEDB /* NotEnoughFreeSpaceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448CB3128E47666006ADEDB /* NotEnoughFreeSpaceView.swift */; };
3448CB3428E47787006ADEDB /* WrappedDiskSpaceChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448CB3328E47787006ADEDB /* WrappedDiskSpaceChecker.swift */; };
3448CB3728E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448CB3628E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift */; };
346715A528E2027D0035F7C4 /* CheckCircleStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346715A428E2027D0035F7C4 /* CheckCircleStore.swift */; };
346715A828E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346715A728E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift */; };
346D41E428DF0B8600963F36 /* CheckCircle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346D41E328DF0B8600963F36 /* CheckCircle.swift */; };
34E0AF0F28DEE4C70034CF37 /* HoldToSendButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */; };
34E0AF1128DEE5220034CF37 /* Wedge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E0AF1028DEE5220034CF37 /* Wedge.swift */; };
34E5F2F328E46DB700C17E5F /* DiskSpaceChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E5F2F228E46DB700C17E5F /* DiskSpaceChecker.swift */; };
660558E9270C7A54009D6954 /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 660558E8270C7A54009D6954 /* Colors.xcassets */; };
660558F7270C862F009D6954 /* Fonts+Generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 660558F5270C862F009D6954 /* Fonts+Generated.swift */; };
660558F8270C862F009D6954 /* XCAssets+Generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 660558F6270C862F009D6954 /* XCAssets+Generated.swift */; };
@ -307,11 +311,15 @@
2EDA079F27EDE18C00D6F09B /* TCATextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TCATextField.swift; sourceTree = "<group>"; };
2EDA07A127EDE1AE00D6F09B /* TextFieldFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldFooter.swift; sourceTree = "<group>"; };
2EDA07A327EDE2A900D6F09B /* DebugFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugFrame.swift; sourceTree = "<group>"; };
3448CB3128E47666006ADEDB /* NotEnoughFreeSpaceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotEnoughFreeSpaceView.swift; sourceTree = "<group>"; };
3448CB3328E47787006ADEDB /* WrappedDiskSpaceChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedDiskSpaceChecker.swift; sourceTree = "<group>"; };
3448CB3628E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotEnoughFeeSpaceSnapshots.swift; sourceTree = "<group>"; };
346715A428E2027D0035F7C4 /* CheckCircleStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckCircleStore.swift; sourceTree = "<group>"; };
346715A728E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionConfirmationSnapshotTests.swift; sourceTree = "<group>"; };
346D41E328DF0B8600963F36 /* CheckCircle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckCircle.swift; sourceTree = "<group>"; };
34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoldToSendButton.swift; sourceTree = "<group>"; };
34E0AF1028DEE5220034CF37 /* Wedge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wedge.swift; sourceTree = "<group>"; };
34E5F2F228E46DB700C17E5F /* DiskSpaceChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiskSpaceChecker.swift; sourceTree = "<group>"; };
660558E8270C7A54009D6954 /* Colors.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Colors.xcassets; sourceTree = "<group>"; };
660558F5270C862F009D6954 /* Fonts+Generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Fonts+Generated.swift"; sourceTree = "<group>"; };
660558F6270C862F009D6954 /* XCAssets+Generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCAssets+Generated.swift"; sourceTree = "<group>"; };
@ -718,6 +726,14 @@
path = Components;
sourceTree = "<group>";
};
3448CB3028E4764E006ADEDB /* NotEnoughFreeSpace */ = {
isa = PBXGroup;
children = (
3448CB3128E47666006ADEDB /* NotEnoughFreeSpaceView.swift */,
);
path = NotEnoughFreeSpace;
sourceTree = "<group>";
};
346715A628E20FB30035F7C4 /* SendSnapshotTests */ = {
isa = PBXGroup;
children = (
@ -751,23 +767,24 @@
6654C73B2715A3F000901167 /* Features */ = {
isa = PBXGroup;
children = (
9EAFEB8B2808174900199FC9 /* Sandbox */,
0D0781C2278750C00083ACD7 /* Welcome */,
F9971A4927680DC400A2DB75 /* App */,
F93874EC273C4DE200F0E875 /* Home */,
9E6713F2289BC51200A6796F /* BalanceBreakdown */,
F9971A4F27680DD000A2DB75 /* Profile */,
9E7CB61B2874140900A02233 /* AddressDetails */,
F9971A4927680DC400A2DB75 /* App */,
9E6713F2289BC51200A6796F /* BalanceBreakdown */,
F93874EC273C4DE200F0E875 /* Home */,
9E2DF99727CF704D00649636 /* ImportWallet */,
3448CB3028E4764E006ADEDB /* NotEnoughFreeSpace */,
6654C73C2715A3FA00901167 /* OnboardingFlow */,
F9971A4F27680DD000A2DB75 /* Profile */,
9E7FE0E4282E753700C374E8 /* RecoveryPhraseDisplay */,
9E7FE0E3282E751A00C374E8 /* RecoveryPhraseValidationFlow */,
F9971A5527680DDE00A2DB75 /* Request */,
9EAFEB8B2808174900199FC9 /* Sandbox */,
F9971A5B27680DF600A2DB75 /* Scan */,
F9C165B62740403600592F76 /* SendFlow */,
F9971A6127680DFE00A2DB75 /* Settings */,
F96B41E2273B501F0021B49A /* WalletEventsFlow */,
9E7FE0E4282E753700C374E8 /* RecoveryPhraseDisplay */,
9E7FE0E3282E751A00C374E8 /* RecoveryPhraseValidationFlow */,
6654C73C2715A3FA00901167 /* OnboardingFlow */,
F9971A6727680E1000A2DB75 /* WalletInfo */,
9E2DF99727CF704D00649636 /* ImportWallet */,
0D0781C2278750C00083ACD7 /* Welcome */,
);
path = Features;
sourceTree = "<group>";
@ -837,23 +854,24 @@
9E02B56827FED42D005B809B /* Wrappers */ = {
isa = PBXGroup;
children = (
9E02B56927FED43E005B809B /* WrappedFileManager.swift */,
9EAFEB83280597B700199FC9 /* WrappedSecItem.swift */,
9E02B5C2280458D2005B809B /* WrappedDerivationTool.swift */,
9EAFEB872806E5AE00199FC9 /* WrappedSDKSynchronizer.swift */,
9E5BF6452821028C00BA3F17 /* WrappedUserDefaults.swift */,
9E5BF647282277BE00BA3F17 /* WrappedNotificationCenter.swift */,
9E2AC10027D8EF0B0042AA47 /* WrappedMnemonic.swift */,
9EF8139027F191BF0075AF48 /* WrappedWalletStorage.swift */,
9E7FE0D8282D289B00C374E8 /* WrappedFeedbackGenerator.swift */,
9E7FE0DA282D28F100C374E8 /* WrappedPasteboard.swift */,
9E7FE0E7282E7B7C00C374E8 /* WrappedDatabaseFiles.swift */,
9E01F81F2833861A000EFC57 /* WrappedCaptureDevice.swift */,
9E01F8232833C0D8000EFC57 /* WrappedURIParser.swift */,
9E87ADF028363DE400122FCC /* WrappedAudioServices.swift */,
9E39113A2848D5180073DD9A /* WrappedNumberFormatter.swift */,
9E39113E2848EC350073DD9A /* WrappedRecoveryPhraseRandomizer.swift */,
9E01F81F2833861A000EFC57 /* WrappedCaptureDevice.swift */,
9E7FE0E7282E7B7C00C374E8 /* WrappedDatabaseFiles.swift */,
9EAB46692859F42E002904A0 /* WrappedDeeplinkHandler.swift */,
9E02B5C2280458D2005B809B /* WrappedDerivationTool.swift */,
3448CB3328E47787006ADEDB /* WrappedDiskSpaceChecker.swift */,
9E7FE0D8282D289B00C374E8 /* WrappedFeedbackGenerator.swift */,
9E02B56927FED43E005B809B /* WrappedFileManager.swift */,
9E2AC10027D8EF0B0042AA47 /* WrappedMnemonic.swift */,
9E5BF647282277BE00BA3F17 /* WrappedNotificationCenter.swift */,
9E39113A2848D5180073DD9A /* WrappedNumberFormatter.swift */,
9E7FE0DA282D28F100C374E8 /* WrappedPasteboard.swift */,
9E39113E2848EC350073DD9A /* WrappedRecoveryPhraseRandomizer.swift */,
9EAFEB872806E5AE00199FC9 /* WrappedSDKSynchronizer.swift */,
9EAFEB83280597B700199FC9 /* WrappedSecItem.swift */,
9E01F8232833C0D8000EFC57 /* WrappedURIParser.swift */,
9E5BF6452821028C00BA3F17 /* WrappedUserDefaults.swift */,
9EF8139027F191BF0075AF48 /* WrappedWalletStorage.swift */,
);
path = Wrappers;
sourceTree = "<group>";
@ -894,7 +912,6 @@
9E391162284E3ECF0073DD9A /* SnapshotTests */ = {
isa = PBXGroup;
children = (
9E92AF0728530EBF007367AD /* View+UIImage.swift */,
9E94C62128AA7ECD008256E9 /* BalanceBreakdownSnapshotTests */,
9E9ECC8B28589E150099D5A2 /* HomeSnapshotTests */,
9E9ECC9328589E150099D5A2 /* ImportWalletSnapshotTests */,
@ -904,6 +921,7 @@
9E9ECC9128589E150099D5A2 /* RecoveryPhraseValidationFlowSnapshotTests */,
346715A628E20FB30035F7C4 /* SendSnapshotTests */,
9E7225EF2889537E00DF7F17 /* SettingsSnapshotTests */,
9E92AF0728530EBF007367AD /* View+UIImage.swift */,
9E7CB6102869881300A02233 /* WalletEventsSnapshotTests */,
9E9ECC8D28589E150099D5A2 /* WelcomeSnapshotTests */,
);
@ -1086,15 +1104,16 @@
9E7FE0BD282D1DE100C374E8 /* Dependencies */ = {
isa = PBXGroup;
children = (
9E7CB6282875AC2D00A02233 /* AppVersionHandler.swift */,
9E3911462848EEB90073DD9A /* DatabaseFiles.swift */,
9EAB4670285A1C77002904A0 /* DeeplinkHandler.swift */,
34E5F2F228E46DB700C17E5F /* DiskSpaceChecker.swift */,
9E66129A28884BFB00C75B70 /* LocalAuthenticationHandler.swift */,
9E3911422848EEB90073DD9A /* RecoveryPhraseRandomizer.swift */,
9E3911432848EEB90073DD9A /* URIParser.swift */,
9E3911442848EEB90073DD9A /* UserPreferencesStorage.swift */,
9E3911472848EEB90073DD9A /* WalletStorage.swift */,
9E3911452848EEB90073DD9A /* ZCashSDKEnvironment.swift */,
9EAB4670285A1C77002904A0 /* DeeplinkHandler.swift */,
9E7CB6282875AC2D00A02233 /* AppVersionHandler.swift */,
9E66129A28884BFB00C75B70 /* LocalAuthenticationHandler.swift */,
);
path = Dependencies;
sourceTree = "<group>";
@ -1202,8 +1221,9 @@
9E9ECC8B28589E150099D5A2 /* HomeSnapshotTests */ = {
isa = PBXGroup;
children = (
9E9ECC8C28589E150099D5A2 /* HomeSnapshotTests.swift */,
9E661229287717A900C75B70 /* HomeCircularProgressSnapshotTests.swift */,
9E9ECC8C28589E150099D5A2 /* HomeSnapshotTests.swift */,
3448CB3628E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift */,
);
path = HomeSnapshotTests;
sourceTree = "<group>";
@ -1663,6 +1683,7 @@
9E3911482848EEB90073DD9A /* RecoveryPhraseRandomizer.swift in Sources */,
0DF482BA2787ADA800EB37D6 /* ConditionalModifier.swift in Sources */,
9E7225F3288AB6DD00DF7F17 /* MultipleLineTextField.swift in Sources */,
3448CB3228E47666006ADEDB /* NotEnoughFreeSpaceView.swift in Sources */,
9E7FE0EC282E7D9400C374E8 /* TransactionState.swift in Sources */,
9E2F1C8F280EDE09004E65FE /* Drawer.swift in Sources */,
665C963F272C26E600BC04FB /* CircularFrameBackground.swift in Sources */,
@ -1707,6 +1728,7 @@
34E0AF0F28DEE4C70034CF37 /* HoldToSendButton.swift in Sources */,
F9C165C02740403600592F76 /* TransactionConfirmationView.swift in Sources */,
0DF2DC5427235E3E00FA31E2 /* View+InnerShadow.swift in Sources */,
3448CB3428E47787006ADEDB /* WrappedDiskSpaceChecker.swift in Sources */,
9E39113F2848EC360073DD9A /* WrappedRecoveryPhraseRandomizer.swift in Sources */,
9EAFEB84280597B700199FC9 /* WrappedSecItem.swift in Sources */,
9E5BF6462821028C00BA3F17 /* WrappedUserDefaults.swift in Sources */,
@ -1748,6 +1770,7 @@
2E8719CB27FB09990082C926 /* TransactionAmountTextField.swift in Sources */,
9E7CB6212874143800A02233 /* AddressDetailsView.swift in Sources */,
9E6713FA289BE0E100A6796F /* ClearBackgroundView.swift in Sources */,
34E5F2F328E46DB700C17E5F /* DiskSpaceChecker.swift in Sources */,
F9C165C42740403600592F76 /* TransactionSentView.swift in Sources */,
F9971A5927680DDE00A2DB75 /* RequestStore.swift in Sources */,
);
@ -1773,6 +1796,7 @@
9EDDEAA32829610D00B4100C /* TransactionAmountInputTests.swift in Sources */,
9E7CB6242874246800A02233 /* ProfileTests.swift in Sources */,
9EAFEB862805A23100199FC9 /* WrappedSecItemTests.swift in Sources */,
3448CB3728E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift in Sources */,
9E9ECC9828589E150099D5A2 /* WelcomeSnapshotTests.swift in Sources */,
9E7CB6122869882D00A02233 /* WalletEventsSnapshotTests.swift in Sources */,
9E5BF644281FEC9900BA3F17 /* SendTests.swift in Sources */,

View File

@ -0,0 +1,30 @@
//
// FreeDiskSpaceChecker.swift
// secant-testnet
//
// Created by Michal Fousek on 28.09.2022.
//
import Foundation
struct DiskSpaceChecker {
/// Free space on disk in bytes required to do sync
func freeSpaceRequiredForSync() -> Int64 {
return 1 * 1024 * 1024 * 1024 // 1GB converted to bytes
}
func hasEnoughFreeSpaceForSync() -> Bool {
return freeSpace() > freeSpaceRequiredForSync()
}
func freeSpace() -> Int64 {
do {
let fileURL = URL(fileURLWithPath: NSHomeDirectory())
let values = try fileURL.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey])
return values.volumeAvailableCapacityForImportantUsage ?? 0
} catch {
// If there is error getting information about free space from filesystem let's assume something is seriously wrong.
return 0
}
}
}

View File

@ -68,6 +68,7 @@ struct AppEnvironment {
let databaseFiles: WrappedDatabaseFiles
let deeplinkHandler: WrappedDeeplinkHandler
let derivationTool: WrappedDerivationTool
let diskSpaceChecker: WrappedDiskSpaceChecker
let feedbackGenerator: WrappedFeedbackGenerator
let mnemonic: WrappedMnemonic
let recoveryPhraseRandomizer: WrappedRecoveryPhraseRandomizer
@ -83,6 +84,7 @@ extension AppEnvironment {
databaseFiles: .live(),
deeplinkHandler: .live,
derivationTool: .live(derivationTool: DerivationTool(networkType: .testnet)),
diskSpaceChecker: .live,
feedbackGenerator: .haptic,
mnemonic: .live,
recoveryPhraseRandomizer: .live,
@ -97,6 +99,7 @@ extension AppEnvironment {
databaseFiles: .live(),
deeplinkHandler: .live,
derivationTool: .live(derivationTool: DerivationTool(networkType: .testnet)),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
recoveryPhraseRandomizer: .live,
@ -365,6 +368,7 @@ extension AppReducer {
HomeEnvironment(
audioServices: environment.audioServices,
derivationTool: environment.derivationTool,
diskSpaceChecker: environment.diskSpaceChecker,
feedbackGenerator: environment.feedbackGenerator,
mnemonic: environment.mnemonic,
scheduler: environment.scheduler,

View File

@ -13,6 +13,7 @@ typealias HomeViewStore = ViewStore<HomeState, HomeAction>
struct HomeState: Equatable {
enum Route: Equatable {
case notEnoughFreeDiskSpace
case profile
case request
case send
@ -78,6 +79,7 @@ enum HomeAction: Equatable {
struct HomeEnvironment {
let audioServices: WrappedAudioServices
let derivationTool: WrappedDerivationTool
let diskSpaceChecker: WrappedDiskSpaceChecker
let feedbackGenerator: WrappedFeedbackGenerator
let mnemonic: WrappedMnemonic
let scheduler: AnySchedulerOf<DispatchQueue>
@ -90,6 +92,7 @@ extension HomeEnvironment {
static let demo = HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
@ -119,10 +122,17 @@ extension HomeReducer {
switch action {
case .onAppear:
state.requiredTransactionConfirmations = environment.zcashSDKEnvironment.requiredTransactionConfirmations
return environment.SDKSynchronizer.stateChanged
.map(HomeAction.synchronizerStateChanged)
.eraseToEffect()
.cancellable(id: CancelId(), cancelInFlight: true)
if environment.diskSpaceChecker.hasEnoughFreeSpaceForSync() {
let syncEffect = environment.SDKSynchronizer.stateChanged
.map(HomeAction.synchronizerStateChanged)
.eraseToEffect()
.cancellable(id: CancelId(), cancelInFlight: true)
return .concatenate(Effect(value: .updateRoute(nil)), syncEffect)
} else {
return Effect(value: .updateRoute(.notEnoughFreeDiskSpace))
}
case .onDisappear:
return Effect.cancel(id: CancelId())
@ -380,6 +390,7 @@ extension HomeStore {
environment: HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .live,
scheduler: DispatchQueue.main.eraseToAnyScheduler(),

View File

@ -31,6 +31,10 @@ struct HomeView: View {
BalanceBreakdown(store: store.balanceBreakdownStore())
}
}
.navigationLinkEmpty(
isActive: viewStore.bindingForRoute(.notEnoughFreeDiskSpace),
destination: { NotEnoughFreeSpaceView(viewStore: viewStore) }
)
}
}
}

View File

@ -0,0 +1,27 @@
//
// NotEnoughFreeSpace.swift
// secant-testnet
//
// Created by Michal Fousek on 28.09.2022.
//
import Foundation
import SwiftUI
import ComposableArchitecture
struct NotEnoughFreeSpaceView: View {
let viewStore: HomeViewStore
var body: some View {
Text("Not enough space on disk to do synchronisation!")
.applyScreenBackground()
}
}
// MARK: - Previews
struct NotEnoughFreeSpaceView_Previews: PreviewProvider {
static var previews: some View {
NotEnoughFreeSpaceView(viewStore: ViewStore(HomeStore.placeholder))
}
}

View File

@ -0,0 +1,37 @@
//
// WrappedDiskSpaceChecker.swift
// secant-testnet
//
// Created by Michal Fousek on 28.09.2022.
//
import Foundation
struct WrappedDiskSpaceChecker {
let freeSpaceRequiredForSync: () -> Int64
let hasEnoughFreeSpaceForSync: () -> Bool
let freeSpace: () -> Int64
}
extension WrappedDiskSpaceChecker {
static let live: WrappedDiskSpaceChecker = {
let diskSpaceChecker = DiskSpaceChecker()
return WrappedDiskSpaceChecker(
freeSpaceRequiredForSync: { diskSpaceChecker.freeSpaceRequiredForSync() },
hasEnoughFreeSpaceForSync: { diskSpaceChecker.hasEnoughFreeSpaceForSync() },
freeSpace: { diskSpaceChecker.freeSpace() }
)
}()
static let mockEmptyDisk = WrappedDiskSpaceChecker(
freeSpaceRequiredForSync: { 1024 },
hasEnoughFreeSpaceForSync: { true },
freeSpace: { 2048 }
)
static let mockFullDisk = WrappedDiskSpaceChecker(
freeSpaceRequiredForSync: { 1024 },
hasEnoughFreeSpaceForSync: { false },
freeSpace: { 0 }
)
}

View File

@ -111,6 +111,7 @@ class AppInitializationTests: XCTestCase {
databaseFiles: dbFiles,
deeplinkHandler: .live,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
recoveryPhraseRandomizer: recoveryPhraseRandomizer,
@ -186,6 +187,7 @@ class AppInitializationTests: XCTestCase {
databaseFiles: dbFiles,
deeplinkHandler: .live,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
recoveryPhraseRandomizer: .live,
@ -229,6 +231,7 @@ class AppInitializationTests: XCTestCase {
databaseFiles: .throwing,
deeplinkHandler: .live,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
recoveryPhraseRandomizer: .live,

View File

@ -17,6 +17,7 @@ class AppTests: XCTestCase {
databaseFiles: .throwing,
deeplinkHandler: .live,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
recoveryPhraseRandomizer: .live,
@ -32,6 +33,7 @@ class AppTests: XCTestCase {
databaseFiles: .throwing,
deeplinkHandler: .live,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
recoveryPhraseRandomizer: .live,
@ -58,6 +60,7 @@ class AppTests: XCTestCase {
databaseFiles: .live(databaseFiles: DatabaseFiles(fileManager: wfmMock)),
deeplinkHandler: .live,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
recoveryPhraseRandomizer: .live,
@ -84,6 +87,7 @@ class AppTests: XCTestCase {
databaseFiles: .live(databaseFiles: DatabaseFiles(fileManager: wfmMock)),
deeplinkHandler: .live,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
recoveryPhraseRandomizer: .live,

View File

@ -84,6 +84,7 @@ class DeeplinkTests: XCTestCase {
databaseFiles: .live(),
deeplinkHandler: .live,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
recoveryPhraseRandomizer: .live,
@ -127,6 +128,7 @@ class DeeplinkTests: XCTestCase {
databaseFiles: .live(),
deeplinkHandler: .live,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
recoveryPhraseRandomizer: .live,
@ -178,6 +180,7 @@ class DeeplinkTests: XCTestCase {
databaseFiles: .live(),
deeplinkHandler: .live,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
recoveryPhraseRandomizer: .live,

View File

@ -18,6 +18,7 @@ class HomeTests: XCTestCase {
let testEnvironment = HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
scheduler: testScheduler.eraseToAnyScheduler(),
@ -49,6 +50,7 @@ class HomeTests: XCTestCase {
let testEnvironment = HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
scheduler: testScheduler.eraseToAnyScheduler(),
@ -100,6 +102,7 @@ class HomeTests: XCTestCase {
let testEnvironment = HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
scheduler: testScheduler.eraseToAnyScheduler(),
@ -143,6 +146,7 @@ class HomeTests: XCTestCase {
let testEnvironment = HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
scheduler: testScheduler.eraseToAnyScheduler(),
@ -188,6 +192,7 @@ class HomeTests: XCTestCase {
let testEnvironment = HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
scheduler: testScheduler.eraseToAnyScheduler(),
@ -209,6 +214,7 @@ class HomeTests: XCTestCase {
testScheduler.advance(by: 0.01)
// expected side effects as a result of .onAppear registration
store.receive(.updateRoute(nil))
store.receive(.synchronizerStateChanged(.unknown))
store.receive(.updateSynchronizerStatus)
@ -216,6 +222,44 @@ class HomeTests: XCTestCase {
// the .onDisappear action cancles the observer of the synchronizer status change.
store.send(.onDisappear)
}
func testOnAppear_notEnoughSpaceOnDisk() throws {
// setup the store and environment to be fully mocked
let testScheduler = DispatchQueue.test
let testEnvironment = HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockFullDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
scheduler: testScheduler.eraseToAnyScheduler(),
SDKSynchronizer: MockWrappedSDKSynchronizer(),
walletStorage: .throwing,
zcashSDKEnvironment: .testnet
)
let store = TestStore(
initialState: .placeholder,
reducer: HomeReducer.default,
environment: testEnvironment
)
store.send(.onAppear) { state in
state.requiredTransactionConfirmations = 10
}
testScheduler.advance(by: 0.01)
// expected side effects as a result of .onAppear registration
store.receive(.updateRoute(.notEnoughFreeDiskSpace)) { state in
state.route = .notEnoughFreeDiskSpace
}
// long-living (cancelable) effects need to be properly canceled.
// the .onDisappear action cancles the observer of the synchronizer status change.
store.send(.onDisappear)
}
func testQuickRescan_ResetToHomeScreen() throws {
// setup the store and environment to be fully mocked
@ -224,6 +268,7 @@ class HomeTests: XCTestCase {
let testEnvironment = HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
scheduler: testScheduler.eraseToAnyScheduler(),
@ -263,6 +308,7 @@ class HomeTests: XCTestCase {
let testEnvironment = HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
scheduler: testScheduler.eraseToAnyScheduler(),

View File

@ -32,6 +32,7 @@ class HomeCircularProgressSnapshotTests: XCTestCase {
let testEnvironment = HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
scheduler: testScheduler.eraseToAnyScheduler(),
@ -80,6 +81,7 @@ class HomeCircularProgressSnapshotTests: XCTestCase {
let testEnvironment = HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
scheduler: testScheduler.eraseToAnyScheduler(),
@ -121,6 +123,7 @@ class HomeCircularProgressSnapshotTests: XCTestCase {
let testEnvironment = HomeEnvironment(
audioServices: .silent,
derivationTool: .live(),
diskSpaceChecker: .mockEmptyDisk,
feedbackGenerator: .silent,
mnemonic: .mock,
scheduler: testScheduler.eraseToAnyScheduler(),

View File

@ -0,0 +1,19 @@
//
// NotEnoughFeeSpaceViewSnapshots.swift
// secantTests
//
// Created by Michal Fousek on 28.09.2022.
//
import Foundation
import XCTest
@testable import secant_testnet
import ComposableArchitecture
import ZcashLightClientKit
class NotEnoughFeeSpaceSnapshots: XCTestCase {
func testNotEnoughFreeSpaceSnapshot() throws {
addAttachments(NotEnoughFreeSpaceView(viewStore: ViewStore(HomeStore.placeholder)))
}
}