[#1029] Not enough free space UI

- The UI has been updated to the latest design
- The values of disc space are provided
- The business logic has changed to react to check every app start or app foreground
- Test has been fixed

[#1029] Not enough free space UI

- Final copy

[#1029] Not enough free space UI (#1170)

- changelog updated
This commit is contained in:
Lukas Korba 2024-04-02 15:25:16 +02:00
parent 9decc16ffa
commit 88f91380eb
19 changed files with 300 additions and 141 deletions

View File

@ -11,6 +11,9 @@ directly impact users rather than highlighting other crucial architectural updat
### Added
- Tap to Copy memo.
### Changed
- Zashi requires 1 GB of free space to operate. We have updated the user experience to display a message when this requirement is not met, indicating the actual amount of free space available. From this screen, you can access the settings to obtain the recovery phrase if needed.
### Fixed
- Tap to Copy transaction ID button animation.
- Transparent balance added up to the total balance.

View File

@ -32,6 +32,7 @@ let package = Package(
.library(name: "LogsHandler", targets: ["LogsHandler"]),
.library(name: "MnemonicClient", targets: ["MnemonicClient"]),
.library(name: "Models", targets: ["Models"]),
.library(name: "NotEnoughFreeSpace", targets: ["NotEnoughFreeSpace"]),
.library(name: "NumberFormatter", targets: ["NumberFormatter"]),
.library(name: "OnboardingFlow", targets: ["OnboardingFlow"]),
.library(name: "PartialProposalError", targets: ["PartialProposalError"]),
@ -233,8 +234,6 @@ let package = Package(
.target(
name: "Home",
dependencies: [
"AudioServices",
"DiskSpaceChecker",
"Generated",
"Models",
"RestoreWalletStorage",
@ -299,6 +298,18 @@ let package = Package(
],
path: "Sources/Models"
),
.target(
name: "NotEnoughFreeSpace",
dependencies: [
"DiskSpaceChecker",
"Generated",
"Settings",
"UIComponents",
"Utils",
.product(name: "ComposableArchitecture", package: "swift-composable-architecture")
],
path: "Sources/Features/NotEnoughFreeSpace"
),
.target(
name: "NumberFormatter",
dependencies: [
@ -393,10 +404,12 @@ let package = Package(
"DatabaseFiles",
"Deeplink",
"DerivationTool",
"DiskSpaceChecker",
"ExportLogs",
"Generated",
"MnemonicClient",
"Models",
"NotEnoughFreeSpace",
"NumberFormatter",
"OnboardingFlow",
"Pasteboard",

View File

@ -10,11 +10,11 @@ import Foundation
public struct DiskSpaceChecker {
/// Free space on disk in bytes required to do sync
public func freeSpaceRequiredForSync() -> Int64 {
return 1 * 1024 * 1024 * 1024 // 1GB converted to bytes
1 * 1024 * 1024 * 1024 // 1GB converted to bytes
}
public func hasEnoughFreeSpaceForSync() -> Bool {
return freeSpace() > freeSpaceRequiredForSync()
freeSpace() > freeSpaceRequiredForSync()
}
public func freeSpace() -> Int64 {

View File

@ -3,8 +3,6 @@ import SwiftUI
import AVFoundation
import ComposableArchitecture
import ZcashLightClientKit
import AudioServices
import DiskSpaceChecker
import Utils
import Models
import Generated
@ -22,12 +20,7 @@ public struct HomeReducer: Reducer {
private let CancelEventId = UUID()
public struct State: Equatable {
public enum Destination: Equatable {
case notEnoughFreeDiskSpace
}
@PresentationState public var alert: AlertState<Action>?
public var destination: Destination?
public var canRequestReview = false
public var isRestoringWallet = false
public var requiredTransactionConfirmations = 0
@ -61,7 +54,6 @@ public struct HomeReducer: Reducer {
}
public init(
destination: Destination? = nil,
canRequestReview: Bool = false,
isRestoringWallet: Bool = false,
requiredTransactionConfirmations: Int = 0,
@ -76,7 +68,6 @@ public struct HomeReducer: Reducer {
walletConfig: WalletConfig,
zecPrice: Decimal = Decimal(140.0)
) {
self.destination = destination
self.canRequestReview = canRequestReview
self.isRestoringWallet = isRestoringWallet
self.requiredTransactionConfirmations = requiredTransactionConfirmations
@ -109,13 +100,10 @@ public struct HomeReducer: Reducer {
case synchronizerStateChanged(RedactableSynchronizerState)
case syncFailed(ZcashError)
case syncProgress(SyncProgressReducer.Action)
case updateDestination(HomeReducer.State.Destination?)
case updateTransactionList([TransactionState])
case transactionList(TransactionListReducer.Action)
}
@Dependency(\.audioServices) var audioServices
@Dependency(\.diskSpaceChecker) var diskSpaceChecker
@Dependency(\.mainQueue) var mainQueue
@Dependency(\.restoreWalletStorage) var restoreWalletStorage
@Dependency(\.reviewRequest) var reviewRequest
@ -137,32 +125,26 @@ public struct HomeReducer: Reducer {
switch action {
case .onAppear:
state.requiredTransactionConfirmations = zcashSDKEnvironment.requiredTransactionConfirmations
if diskSpaceChecker.hasEnoughFreeSpaceForSync() {
return .merge(
Effect.send(.updateDestination(nil)),
.publisher {
sdkSynchronizer.stateStream()
.throttle(for: .seconds(0.2), scheduler: mainQueue, latest: true)
.map { $0.redacted }
.map(HomeReducer.Action.synchronizerStateChanged)
}
.cancellable(id: CancelStateId, cancelInFlight: true),
.publisher {
sdkSynchronizer.eventStream()
.throttle(for: .seconds(0.2), scheduler: mainQueue, latest: true)
.compactMap {
if case SynchronizerEvent.foundTransactions = $0 {
return HomeReducer.Action.foundTransactions
}
return nil
return .merge(
.publisher {
sdkSynchronizer.stateStream()
.throttle(for: .seconds(0.2), scheduler: mainQueue, latest: true)
.map { $0.redacted }
.map(HomeReducer.Action.synchronizerStateChanged)
}
.cancellable(id: CancelStateId, cancelInFlight: true),
.publisher {
sdkSynchronizer.eventStream()
.throttle(for: .seconds(0.2), scheduler: mainQueue, latest: true)
.compactMap {
if case SynchronizerEvent.foundTransactions = $0 {
return HomeReducer.Action.foundTransactions
}
}
.cancellable(id: CancelEventId, cancelInFlight: true)
)
} else {
return Effect.send(.updateDestination(.notEnoughFreeDiskSpace))
}
return nil
}
}
.cancellable(id: CancelEventId, cancelInFlight: true)
)
case .onDisappear:
return .concatenate(
@ -233,10 +215,6 @@ public struct HomeReducer: Reducer {
reviewRequest.foundTransactions()
}
case .updateDestination(let destination):
state.destination = destination
return .none
case .transactionList:
return .none
@ -286,19 +264,6 @@ extension HomeStore {
}
}
// MARK: - ViewStore
extension HomeViewStore {
func bindingForDestination(_ destination: HomeReducer.State.Destination) -> Binding<Bool> {
self.binding(
get: { $0.destination == destination },
send: { isActive in
return .updateDestination(isActive ? destination : nil)
}
)
}
}
// MARK: Placeholders
extension HomeReducer.State {

View File

@ -55,10 +55,6 @@ public struct HomeView: View {
state: \.$alert,
action: { .alert($0) }
))
.navigationLinkEmpty(
isActive: viewStore.bindingForDestination(.notEnoughFreeDiskSpace),
destination: { NotEnoughFreeSpaceView(viewStore: viewStore) }
)
}
.task { await store.send(.restoreWalletTask).finish() }
}

View File

@ -1,33 +0,0 @@
//
// NotEnoughFreeSpace.swift
// secant-testnet
//
// Created by Michal Fousek on 28.09.2022.
//
import Foundation
import SwiftUI
import ComposableArchitecture
import UIComponents
import Generated
public struct NotEnoughFreeSpaceView: View {
let viewStore: HomeViewStore
public init(viewStore: HomeViewStore) {
self.viewStore = viewStore
}
public var body: some View {
Text(L10n.Nefs.message)
.applyScreenBackground()
}
}
// MARK: - Previews
struct NotEnoughFreeSpaceView_Previews: PreviewProvider {
static var previews: some View {
NotEnoughFreeSpaceView(viewStore: ViewStore(HomeStore.placeholder, observe: { $0 }))
}
}

View File

@ -0,0 +1,67 @@
//
// NotEnoughFreeSpaceStore.swift
//
//
// Created by Lukáš Korba on 02.04.2024.
//
import ComposableArchitecture
import DiskSpaceChecker
import Settings
@Reducer
public struct NotEnoughFreeSpace {
@ObservableState
public struct State: Equatable {
public var freeSpaceRequiredForSync = ""
public var freeSpace = ""
public var isSettingsOpen = false
public var settingsState: SettingsReducer.State
public init(
isSettingsOpen: Bool = false,
settingsState: SettingsReducer.State
) {
self.isSettingsOpen = isSettingsOpen
self.settingsState = settingsState
}
}
public enum Action: BindableAction, Equatable {
case binding(BindingAction<NotEnoughFreeSpace.State>)
case onAppear
case settings(SettingsReducer.Action)
}
@Dependency(\.diskSpaceChecker) var diskSpaceChecker
public init() {}
public var body: some Reducer<State, Action> {
BindingReducer()
Scope(state: \.settingsState, action: /Action.settings) {
SettingsReducer()
}
Reduce { state, action in
switch action {
case .onAppear:
let fsrts = Double(diskSpaceChecker.freeSpaceRequiredForSync())
let fSpace = Double(diskSpaceChecker.freeSpace())
// We show the value in GB so any required value is divided by 1_073_741_824 bytes
state.freeSpaceRequiredForSync = String(format: "%0.0f", fsrts / Double(1_073_741_824))
// We show the value in MB so any required value is divided by 1_048_576 bytes
state.freeSpace = String(format: "%0.0f", fSpace / Double(1_048_576))
return .none
case .binding:
return .none
case .settings:
return .none
}
}
}
}

View File

@ -0,0 +1,99 @@
//
// NotEnoughFreeSpaceView.swift
// secant-testnet
//
// Created by Michal Fousek on 28.09.2022.
//
import SwiftUI
import ComposableArchitecture
import Generated
import Settings
import UIComponents
public struct NotEnoughFreeSpaceView: View {
@Perception.Bindable var store: StoreOf<NotEnoughFreeSpace>
public init(store: StoreOf<NotEnoughFreeSpace>) {
self.store = store
}
public var body: some View {
WithPerceptionTracking {
VStack {
ZashiErrorIcon()
.padding(.vertical, 20)
Text(L10n.NotEnoughFreeSpace.message(store.freeSpaceRequiredForSync, store.freeSpace))
.font(.custom(FontFamily.Inter.regular.name, size: 14))
.multilineTextAlignment(.center)
Spacer()
}
.padding(.horizontal, 60)
.padding(.vertical, 1)
.onAppear { store.send(.onAppear) }
.navigationBarTitleDisplayMode(.inline)
.navigationBarItems(trailing: settingsButton())
.applyScreenBackground()
.zashiTitle {
Text(L10n.NotEnoughFreeSpace.title.uppercased())
.font(.custom(FontFamily.Archivo.bold.name, size: 14))
}
}
}
func settingsButton() -> some View {
return Image(systemName: "line.3.horizontal")
.resizable()
.frame(width: 21, height: 15)
.padding(15)
.navigationLink(
isActive: $store.isSettingsOpen,
destination: {
SettingsView(
store:
store.scope(
state: \.settingsState,
action: \.settings
)
)
}
)
.tint(Asset.Colors.primary.color)
}
}
// MARK: - Previews
#Preview {
NavigationView {
NotEnoughFreeSpaceView(
store:
StoreOf<NotEnoughFreeSpace>(
initialState: NotEnoughFreeSpace.State(
settingsState: .initial
)
) {
NotEnoughFreeSpace()
}
)
}
}
// MARK: Placeholders
extension NotEnoughFreeSpace.State {
public static let initial = NotEnoughFreeSpace.State(
settingsState: .initial
)
}
extension NotEnoughFreeSpace {
public static let placeholder = StoreOf<NotEnoughFreeSpace>(
initialState: .initial
) {
NotEnoughFreeSpace()
}
}

View File

@ -22,16 +22,7 @@ public struct PartialProposalErrorView: View {
ScrollView {
WithPerceptionTracking {
VStack(alignment: .center) {
ZashiIcon()
.padding(.top, 20)
.scaleEffect(2)
.padding(.vertical, 30)
.overlay {
Asset.Assets.alertIcon.image
.resizable()
.frame(width: 24, height: 24)
.offset(x: 25, y: 15)
}
ZashiErrorIcon()
Group {
Text(L10n.ProposalPartial.message1)

View File

@ -16,6 +16,7 @@ import DerivationTool
extension RootReducer {
public struct DestinationState: Equatable {
public enum Destination: Equatable {
case notEnoughFreeSpace
case onboarding
case phraseDisplay
case sandbox
@ -25,6 +26,7 @@ extension RootReducer {
}
public var internalDestination: Destination = .welcome
public var preNotEnoughFreeSpaceDestination: Destination?
public var previousDestination: Destination?
public var destination: Destination {
@ -106,7 +108,8 @@ extension RootReducer {
return .none
case .tabs, .initialization, .onboarding, .sandbox, .updateStateAfterConfigUpdate, .alert, .phraseDisplay, .synchronizerStateChanged,
.welcome, .binding, .nukeWalletFailed, .nukeWalletSucceeded, .debug, .walletConfigLoaded, .exportLogs, .confirmationDialog:
.welcome, .binding, .nukeWalletFailed, .nukeWalletSucceeded, .debug, .walletConfigLoaded, .exportLogs, .confirmationDialog,
.notEnoughFreeSpace:
return .none
}

View File

@ -9,6 +9,7 @@ import ComposableArchitecture
import Foundation
import ZcashLightClientKit
import Models
import NotEnoughFreeSpace
import Utils
/// In this file is a collection of helpers that control all state and action related operations
@ -132,6 +133,13 @@ extension RootReducer {
return .none
case .initialization(.retryStart):
if !diskSpaceChecker.hasEnoughFreeSpaceForSync() {
state.destinationState.preNotEnoughFreeSpaceDestination = state.destinationState.internalDestination
return .send(.destination(.updateDestination(.notEnoughFreeSpace)))
} else if let preNotEnoughFreeSpaceDestination = state.destinationState.preNotEnoughFreeSpaceDestination {
state.destinationState.internalDestination = preNotEnoughFreeSpaceDestination
state.destinationState.preNotEnoughFreeSpaceDestination = nil
}
// Try the start only if the synchronizer has been already prepared
guard sdkSynchronizer.latestState().syncStatus.isPrepared else {
return .none
@ -182,6 +190,13 @@ extension RootReducer {
)
case .initialization(.initialSetups):
if !diskSpaceChecker.hasEnoughFreeSpaceForSync() {
state.destinationState.preNotEnoughFreeSpaceDestination = state.destinationState.internalDestination
return .send(.destination(.updateDestination(.notEnoughFreeSpace)))
} else if let preNotEnoughFreeSpaceDestination = state.destinationState.preNotEnoughFreeSpaceDestination {
state.destinationState.internalDestination = preNotEnoughFreeSpaceDestination
state.destinationState.preNotEnoughFreeSpaceDestination = nil
}
// TODO: [#524] finish all the wallet events according to definition, https://github.com/Electric-Coin-Company/zashi-ios/issues/524
LoggerProxy.event(".appDelegate(.didFinishLaunching)")
/// We need to fetch data from keychain, in order to be 100% sure the keychain can be read we delay the check a bit
@ -453,7 +468,7 @@ extension RootReducer {
case .onboarding(.securityWarning(.recoveryPhraseDisplay(.finishedPressed))):
return Effect.send(.destination(.updateDestination(.tabs)))
case .tabs, .destination, .onboarding, .sandbox, .phraseDisplay,
case .tabs, .destination, .onboarding, .sandbox, .phraseDisplay, .notEnoughFreeSpace,
.welcome, .binding, .debug, .exportLogs, .alert, .splashFinished, .splashRemovalRequested, .confirmationDialog:
return .none
}

View File

@ -2,11 +2,13 @@ import ComposableArchitecture
import ZcashLightClientKit
import DatabaseFiles
import Deeplink
import DiskSpaceChecker
import ZcashSDKEnvironment
import WalletStorage
import WalletConfigProvider
import UserPreferencesStorage
import Models
import NotEnoughFreeSpace
import Welcome
import Generated
import Foundation
@ -42,6 +44,7 @@ public struct RootReducer: Reducer {
public var exportLogsState: ExportLogsReducer.State
public var isLockedInKeychainUnavailableState = false
public var isRestoringWallet = false
public var notEnoughFreeSpaceState: NotEnoughFreeSpace.State
public var onboardingState: OnboardingFlowReducer.State
public var phraseDisplayState: RecoveryPhraseDisplay.State
public var sandboxState: SandboxReducer.State
@ -58,6 +61,7 @@ public struct RootReducer: Reducer {
exportLogsState: ExportLogsReducer.State,
isLockedInKeychainUnavailableState: Bool = false,
isRestoringWallet: Bool = false,
notEnoughFreeSpaceState: NotEnoughFreeSpace.State = .initial,
onboardingState: OnboardingFlowReducer.State,
phraseDisplayState: RecoveryPhraseDisplay.State,
sandboxState: SandboxReducer.State,
@ -73,6 +77,7 @@ public struct RootReducer: Reducer {
self.isLockedInKeychainUnavailableState = isLockedInKeychainUnavailableState
self.isRestoringWallet = isRestoringWallet
self.onboardingState = onboardingState
self.notEnoughFreeSpaceState = notEnoughFreeSpaceState
self.phraseDisplayState = phraseDisplayState
self.sandboxState = sandboxState
self.tabsState = tabsState
@ -95,6 +100,7 @@ public struct RootReducer: Reducer {
case exportLogs(ExportLogsReducer.Action)
case tabs(TabsReducer.Action)
case initialization(InitializationAction)
case notEnoughFreeSpace(NotEnoughFreeSpace.Action)
case nukeWalletFailed
case nukeWalletSucceeded
case onboarding(OnboardingFlowReducer.Action)
@ -112,6 +118,7 @@ public struct RootReducer: Reducer {
@Dependency(\.databaseFiles) var databaseFiles
@Dependency(\.deeplink) var deeplink
@Dependency(\.derivationTool) var derivationTool
@Dependency(\.diskSpaceChecker) var diskSpaceChecker
@Dependency(\.mainQueue) var mainQueue
@Dependency(\.mnemonic) var mnemonic
@Dependency(\.numberFormatter) var numberFormatter
@ -136,6 +143,10 @@ public struct RootReducer: Reducer {
ExportLogsReducer()
}
Scope(state: \.notEnoughFreeSpaceState, action: /Action.notEnoughFreeSpace) {
NotEnoughFreeSpace()
}
Scope(state: \.onboardingState, action: /Action.onboarding) {
OnboardingFlowReducer()
}

View File

@ -3,6 +3,7 @@ import StoreKit
import ComposableArchitecture
import Generated
import Models
import NotEnoughFreeSpace
import RecoveryPhraseDisplay
import Welcome
import ExportLogs
@ -47,6 +48,20 @@ private extension RootView {
WithViewStore(store, observe: { $0 }) { viewStore in
Group {
switch viewStore.destinationState.destination {
case .notEnoughFreeSpace:
NavigationView {
NotEnoughFreeSpaceView(
store: store.scope(
state: \.notEnoughFreeSpaceState,
action: RootReducer.Action.notEnoughFreeSpace
)
)
}
.navigationViewStyle(.stack)
.overlayedWithSplash(viewStore.splashAppeared) {
viewStore.send(.splashRemovalRequested)
}
case .tabs:
NavigationView {
TabsView(

View File

@ -235,6 +235,14 @@ public enum L10n {
/// Not enough space on disk to do synchronisation!
public static let message = L10n.tr("Localizable", "nefs.message", fallback: "Not enough space on disk to do synchronisation!")
}
public enum NotEnoughFreeSpace {
/// Zashi requires at least %@ GB of space to operate but there is only %@ MB available. Go to your device settings and make more space available if you wish to use the Zashi app.
public static func message(_ p1: Any, _ p2: Any) -> String {
return L10n.tr("Localizable", "notEnoughFreeSpace.message", String(describing: p1), String(describing: p2), fallback: "Zashi requires at least %@ GB of space to operate but there is only %@ MB available. Go to your device settings and make more space available if you wish to use the Zashi app.")
}
/// Not enough free space
public static let title = L10n.tr("Localizable", "notEnoughFreeSpace.title", fallback: "Not enough free space")
}
public enum Onboarding {
public enum Button {
/// Import an Existing Wallet

View File

@ -176,6 +176,10 @@
"deleteWallet.iUnderstand" = "I understand";
"deleteWallet.actionButtonTitle" = "Delete Zashi";
// MARK: - Not Enogh Free Space
"notEnoughFreeSpace.title" = "Not enough free space";
"notEnoughFreeSpace.message" = "Zashi requires at least %@ GB of space to operate but there is only %@ MB available. Go to your device settings and make more space available if you wish to use the Zashi app.";
// MARK: - Settings
"settings.feedback" = "Send us feedback";
"settings.advanced" = "Advanced";

View File

@ -21,6 +21,27 @@ public struct ZashiIcon: View {
}
}
#Preview {
ZashiIcon()
public struct ZashiErrorIcon: View {
public init() { }
public var body: some View {
ZashiIcon()
.padding(.top, 20)
.scaleEffect(2)
.padding(.vertical, 30)
.overlay {
Asset.Assets.alertIcon.image
.resizable()
.frame(width: 24, height: 24)
.offset(x: 25, y: 15)
}
}
}
#Preview {
VStack(spacing: 40) {
ZashiIcon()
ZashiErrorIcon()
}
}

View File

@ -60,7 +60,6 @@ class HomeTests: XCTestCase {
let snapshot = SyncStatusSnapshot.snapshotFor(state: syncState.syncStatus)
// expected side effects as a result of .onAppear registration
await store.receive(.updateDestination(nil))
await store.receive(.synchronizerStateChanged(SynchronizerState.zero.redacted)) { state in
state.synchronizerStatusSnapshot = snapshot
}
@ -72,32 +71,6 @@ class HomeTests: XCTestCase {
await store.finish()
}
@MainActor func testOnAppear_notEnoughSpaceOnDisk() async throws {
let store = TestStore(
initialState: .initial
) {
HomeReducer()
}
store.dependencies.diskSpaceChecker = .mockFullDisk
store.dependencies.reviewRequest = .noOp
await store.send(.onAppear) { state in
state.requiredTransactionConfirmations = 10
}
// expected side effects as a result of .onAppear registration
await store.receive(.updateDestination(.notEnoughFreeDiskSpace)) { state in
state.destination = .notEnoughFreeDiskSpace
}
// long-living (cancelable) effects need to be properly canceled.
// the .onDisappear action cancels the observer of the synchronizer status change.
await store.send(.onDisappear)
await store.finish()
}
@MainActor func testSynchronizerErrorBringsUpAlert() async {
let testError = ZcashError.synchronizerNotPrepared
let errorSnapshot = SyncStatusSnapshot.snapshotFor(

View File

@ -46,6 +46,7 @@ class AppInitializationTests: XCTestCase {
store.dependencies.databaseFiles = .noOp
store.dependencies.databaseFiles.areDbFilesPresentFor = { _ in true }
store.dependencies.derivationTool = .liveValue
store.dependencies.diskSpaceChecker = .mockEmptyDisk
store.dependencies.mainQueue = .immediate
store.dependencies.mnemonic = .mock
store.dependencies.walletStorage.exportWallet = { storedWallet }
@ -120,6 +121,7 @@ class AppInitializationTests: XCTestCase {
store.dependencies.databaseFiles = .noOp
store.dependencies.databaseFiles.areDbFilesPresentFor = { _ in true }
store.dependencies.derivationTool = .liveValue
store.dependencies.diskSpaceChecker = .mockEmptyDisk
store.dependencies.mainQueue = .immediate
store.dependencies.mnemonic = .mock
store.dependencies.walletStorage.exportWallet = { storedWallet }
@ -184,6 +186,7 @@ class AppInitializationTests: XCTestCase {
store.dependencies.databaseFiles = .noOp
store.dependencies.databaseFiles.areDbFilesPresentFor = { _ in true }
store.dependencies.diskSpaceChecker = .mockEmptyDisk
store.dependencies.walletStorage = .noOp
store.dependencies.mainQueue = .immediate
store.dependencies.walletConfigProvider = .noOp
@ -222,6 +225,7 @@ class AppInitializationTests: XCTestCase {
}
store.dependencies.databaseFiles = .noOp
store.dependencies.diskSpaceChecker = .mockEmptyDisk
store.dependencies.mainQueue = .immediate
store.dependencies.walletStorage = .noOp
store.dependencies.walletConfigProvider = .noOp

View File

@ -5,16 +5,20 @@
// Created by Michal Fousek on 28.09.2022.
//
import Foundation
import XCTest
import ComposableArchitecture
import ZcashLightClientKit
import Home
import NotEnoughFreeSpace
@testable import secant_testnet
class NotEnoughFeeSpaceSnapshots: XCTestCase {
func testNotEnoughFreeSpaceSnapshot() throws {
addAttachments(NotEnoughFreeSpaceView(viewStore: ViewStore(HomeStore.placeholder, observe: { $0 })))
let store = StoreOf<NotEnoughFreeSpace>(
initialState: .initial
) {
NotEnoughFreeSpace()
.dependency(\.diskSpaceChecker, .mockEmptyDisk)
}
addAttachments(NotEnoughFreeSpaceView(store: store))
}
}