-
Notifications
You must be signed in to change notification settings - Fork 25
Navigator
Facade type erasing the type of the underlying datasource
public struct Navigator Testing helper
typealias DismissSuccessorInvocation = DismissInvocation var invocations = [Navigator.DismissInvocation]()
let expectectedInvocations = [
Navigator.DismissInvocation(id: .id(expectedID))
]
let sut = Navigator.mock(
path: { self.path },
dismissSuccessor: { id in
invocations.append(.init(id: id))
}
)
sut.dismissSuccessor(of: expectedID) // invoke code that invokes dismissSuccessor(of:)
XCTAssertEqual(expectectedInvocations, invocations)init(path:go:goToOnScreen:goToPath:goToPathOnScreen:goBack:goBackToID:replace:dismiss:dismissScreen:dismissSuccessor:dismissSuccessorOfScreen:replaceContent:replaceScreen:didAppear:)
public init(
path: @escaping () -> PathUpdate,
go: @escaping (AnyScreen, ScreenID) -> Void,
goToOnScreen: @escaping (AnyScreen, AnyScreen) -> Void,
goToPath: @escaping ([AnyScreen], ScreenID) -> Void,
goToPathOnScreen: @escaping ([AnyScreen], AnyScreen) -> Void,
goBack: @escaping (AnyScreen) -> Void,
goBackToID: @escaping (ScreenID) -> Void,
replace: @escaping ([AnyScreen]) -> Void,
dismiss: @escaping (ScreenID) -> Void,
dismissScreen: @escaping (AnyScreen) -> Void,
dismissSuccessor: @escaping (ScreenID) -> Void,
dismissSuccessorOfScreen: @escaping (AnyScreen) -> Void,
replaceContent: @escaping (ScreenID, AnyScreen) -> Void,
replaceScreen: @escaping (AnyScreen, AnyScreen) -> Void,
didAppear: @escaping (ScreenID) -> Void
) Initialises a Navigator wrapping a Datasource object
init(dataSource: Navigator.Datasource) - dataSource: The wrapped data source
static let stub Enable logging received function calls and path changes.
func debug(
log: @escaping (String) -> Void = { print($0) },
dumpPath: @escaping (PathUpdate) -> Void = { dump($0) }
) -> Navigator mock(path:go:goToOnScreen:goToPath:goToPathOnScreen:goBack:goBackToID:replace:dismiss:dismissScreen:dismissSuccessor:dismissSuccessorOfScreen:replaceContent:replaceScreen:didAppear:)
static func mock(
path: @escaping () -> PathUpdate = {
fatalError("path() unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
go: @escaping (AnyScreen, ScreenID) -> Void = { _, _ in
fatalError("go(to:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
goToOnScreen: @escaping (AnyScreen, AnyScreen) -> Void = { _, _ in
fatalError("go(to:, on screen:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
goToPath: @escaping ([AnyScreen], ScreenID) -> Void = { _, _ in
fatalError("goTo(path:, to:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
goToPathOnScreen: @escaping ([AnyScreen], AnyScreen) -> Void = { _, _ in
fatalError("goTo(path:, to:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
goBack: @escaping (AnyScreen) -> Void = { _ in
fatalError("goBack(to:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
goBackToID: @escaping (ScreenID) -> Void = { _ in
fatalError("goBack(to:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
replace: @escaping ([AnyScreen]) -> Void = { _ in
fatalError("replace(path:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
dismiss: @escaping (ScreenID) -> Void = { _ in
fatalError("dismiss(id:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
dismissScreen: @escaping (AnyScreen) -> Void = { _ in
fatalError("dismiss(screen:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
dismissSuccessor: @escaping (ScreenID) -> Void = { _ in
fatalError("dismissSuccessor(of:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
dismissSuccessorOfScreen: @escaping (AnyScreen) -> Void = { _ in
fatalError("dismissSuccessor(of:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
replaceContent: @escaping (ScreenID, AnyScreen) -> Void = { _, _ in
fatalError("replaceContent(of id:, with:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
replaceScreen: @escaping (AnyScreen, AnyScreen) -> Void = { _, _ in
fatalError("replace(screen:, with:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
didAppear: @escaping (ScreenID) -> Void = { _ in
fatalError("didAppear(id:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
}
) -> Navigator mock(path:goToInvoked:goToPathInvoked:goBackToInvoked:replacePathInvoked:dismissInvoked:dismissSuccessorInvoked:replaceContentInvoked:replaceScreenInvoked:didAppearInvoked:)
static func mock(
path: @escaping () -> PathUpdate = {
fatalError("path() unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
goToInvoked: @escaping (Navigator.GoToInvocation) -> Void = { _ in
fatalError("go(to screen:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
goToPathInvoked: @escaping (Navigator.GoToPathInvocation) -> Void = { _ in
fatalError("go(to path:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
goBackToInvoked: @escaping (Navigator.GoBackToInvocation) -> Void = { _ in
fatalError("goBack(to:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
replacePathInvoked: @escaping (Navigator.ReplacePathInvocation) -> Void = { _ in
fatalError("replace(path:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
dismissInvoked: @escaping (Navigator.DismissInvocation) -> Void = { _ in
fatalError("dismiss(id:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
dismissSuccessorInvoked: @escaping (Navigator.DismissSuccessorInvocation) -> Void = { _ in
fatalError("dismissSuccessor(of:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
replaceContentInvoked: @escaping (Navigator.ReplaceContentInvocation) -> Void = { _ in
fatalError("replaceContent(of id:, with:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
replaceScreenInvoked: @escaping (Navigator.ReplaceScreenInvocation) -> Void = { _ in
fatalError("replace(screen:, with:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
},
didAppearInvoked: @escaping (Navigator.DidAppearInvocation) -> Void = { _ in
fatalError("didAppear(id:) unimplemented in stub. Make sure to wrap your application in a Root view or inject Navigator via .environment(\\.navigator, navigator) for testing purposes.")
}
) -> Navigator Append a screen after a given ScreenID.
public func go<S: Screen>(to screen: S, on id: ScreenID) go(to:, on:) appends the given screen after the screen associated with the passed ScreenID. If you call go(to:, on:) for a ScreenID that is not associated with the last screen in the current navigation path, the navigation path after the ScreenID is replaced with [screen] and therefore cut off.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1)]
navigator.go(to: C(), on: 1)
// New path
// [(A, 0), (B, 1)], (C, 2)]- screen: Destination
- id:
ScreenIDused to identify where the destination should be appended
Append a screen after a given Screen.
public func go<S: Screen, Parent: Screen>(to screen: S, on parent: Parent) go(to:, on:) appends the given screen after the last occurrence of the passed Parent screen object.
If you call go(to:, on:) for a Screen that is not associated with the last screen in the current navigation path, the navigation path after the Parent is replaced with [screen] and therefore cut off.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1)]
navigator.go(to: C(), on: B())
// New path
// [(A, 0), (B, 1)], (C, 2)]- screen: Destination
- parent:
Parentscreen object used to identify where the destination should be appended
Replace the path after a given ScreenID with the passed path.
public func go(to path: [AnyScreen], on id: ScreenID) go(to:, on:) appends the given path after the screen associated with the passed ScreenID. If you call go(to:, on:) for a ScreenID that is not associated with the last screen in the current navigation path, the navigation path after the ScreenID is replaced with path and potentially cut off.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1)]
navigator.go(
to: [C().eraseToAnyScreen(), D().eraseToAnyScreen()],
on: 0
)
// New path
// [(A, 0), (C, 2), (D, 3)]- path: New path after
id - id:
ScreenIDused to identify where the path should be appended
Replace the path after the last occurrence of a given Parent with the passed path.
public func go<Parent: Screen>(to path: [AnyScreen], on parent: Parent) go(to:, on:) appends the given path after the last occurrence of the passed Parent Screen object. If you call go(to:, on:) for a Parent screen that is not associated with the last screen in the current navigation path, the navigation path after the ScreenID is replaced with path and potentially cut off.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1)]
navigator.go(
to: [C().eraseToAnyScreen(), D().eraseToAnyScreen()],
on: A()
)
// New path
// [(A, 0), (C, 2), (D, 3)]- path: New path after
Parent - parent:
Screenused to identify where the path should be appended
Go back to the last occurrence of the screen instance in the navigation path.
public func goBack<S: Screen>(to screen: S) goBack(to:) trims the navigation path to up to the last occurrence of the passed screen.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1), (C, 2)]
navigator.goBack(to: A())
// New path
// [(A, 0)]- screen: Destination
Go back to the specified ScreenID in the navigation path.
public func goBack(to id: ScreenID) goBack(to:) trims the navigation path to up to the last occurrence of the passed screen.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1), (C, 2)]
navigator.goBack(to: 0)
// New path
// [(A, 0)]- id: Destination ID
Replace the current navigation path with a new navigation path.
public func replace(path: AnyScreen...) Example
// Curent path [(Content, ID)]
// [(A, 0), (B, 1)]
navigator.replace(
path: C().eraseToAnyScreen(), D().eraseToAnyScreen()
)
// New path
// [(C, 0), (D, 1)]- path: The new navigation path
Replace the current navigation path with a new navigation path.
public func replace(path: [AnyScreen]) replace(path:) checks if a prefix of the new path was already part of the replaced navigation path and makes sure to keep the IDs and hasAppeared state intact.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1)]
navigator.replace(
path: [
C().eraseToAnyScreen(),
D().eraseToAnyScreen()
]
)
// New path
// [(C, 0), (D, 1)]- path: The new navigation path
Removes the screen associated with the passed screenID from the navigation path.
public func dismiss(id: ScreenID) dismiss(id:) does not care take the screen's presentation style into account and cuts the navigation path up to the passed id.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1), (C, 2), (D,3)]
navigator.dismiss(id: 2)
// New path
// [(A, 0), (B, 1)]- id: The id identifying the screen that needs to be dismissed
Removes the last occurrence screen from the navigation path.
public func dismiss<S: Screen>(screen: S) dismiss(screen:) does not care take the screen's presentation style into account and cuts the navigation path up to the passed id.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1), (C, 2), (D,3)]
navigator.dismiss(screen: C())
// New path
// [(A, 0), (B, 1)]- screen: The screen that needs to be dismissed
Removes the screen successors from the navigation path.
public func dismissSuccessor(of id: ScreenID) dismissSuccessor(of id:) does not care take the screen's presentation style into account and cuts the navigation path after the passed id.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1), (C, 2), (D,3)]
navigator.dismissSuccessor(of id: 2)
// New path
// [(A, 0), (B, 1), (C, 2)]- id: The id identifying the screen that needs to be dismissed
Removes successors of the last occurrence of the passed screen from the navigation path.
public func dismissSuccessor<S: Screen>(of screen: S) dismissSuccessor(of screen:) does not care take the screen's presentation style into account and cuts the navigation path after the passed id.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1), (C, 2), (D,3)]
navigator.dismissSuccessor(of: C())
// New path
// [(A, 0), (B, 1), (C, 2)]- screen: The screen that needs to be dismissed
Replace the Screen associated with an id with a new Screen
public func replaceContent<NewContent: Screen>(of id: ScreenID, with newContent: NewContent) replaceContent(of id:, with:) replaces the content associated with the passed ScreenID and will not assign a new ScreenID to the changed path element.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1), (C, 2), (D,3)]
navigator.replaceContent(of: 0, with: E())
// New path
// [(E, 0), (B, 1), (C, 2), (D,3)]- id:
ScreenIDused to identify the screen that needs to be replaced - newContent: The new screen that will replace the screen associated with the passed
ScreenID
Replace the last occurence of a Screen with a new Screen
public func replace<OldContent: Screen, NewContent: Screen>(
screen: OldContent,
with newContent: NewContent
) replace(screen:, with:) replaces the last occurence of the passed Screen with the passed newContent Screen and will not assign a new ScreenID to the changed path element.
// Curent path [(Content, ID)]
// [(A, 0), (B, 1), (C, 2), (D,3)]
navigator.replace(screen: A(), with: E())
// New path
// [(E, 0), (B, 1), (C, 2), (D,3)]- screen:
Screengetting replaced - newContent: The new screen that will replace the screen associated with the passed
ScreenID
Generated at 2021-04-29T07:59:04+0000 using swift-doc 1.0.0-beta.6.
Types
- AnyPathBuilder
- AnyScreen
- Deeplink
- DeeplinkComponent
- DeeplinkComponent.Argument
- DeeplinkHandler
- DeeplinkParser
- EitherAB
- EitherABC
- EitherABCD
- EitherABCDE
- EitherABCDEF
- EitherABCDEFG
- EitherABCDEFGH
- EitherABCDEFGHI
- EitherABCDEFGHIJ
- IdentifiedScreen
- NavigationNode
- NavigationTreeBuilder
- Navigator
- Navigator.Datasource
- Navigator.DidAppearInvocation
- Navigator.DismissInvocation
- Navigator.GoBackToInvocation
- Navigator.GoToInvocation
- Navigator.GoToPathInvocation
- Navigator.NavigationIdentifier
- Navigator.ReplaceContentInvocation
- Navigator.ReplacePathInvocation
- Navigator.ReplaceScreenInvocation
- NavigatorKey
- OnDismissView
- PathBuilders
- PathBuilders.EmptyBuilder
- PathBuilders.WildcardView
- PathComponentUpdate
- PathUpdate
- Root
- ScreenPresentationStyle
- TreatSheetDismissAsAppearInPresenterKey
- _PathBuilder