Skip to content

Commit

Permalink
Minor changes in SwitchAssembly
Browse files Browse the repository at this point in the history
  • Loading branch information
ekazaev committed Sep 27, 2019
1 parent 6a69191 commit fade23f
Show file tree
Hide file tree
Showing 40 changed files with 731 additions and 802 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ProductConfiguration {
.adding(ContextSettingTask())
.using(UINavigationController.push())
.from(SwitchAssembly<UINavigationController, ProductContext>()
.addCase { (context: ProductContext) in
.addCase({ (context: ProductContext) in
// If this configuration is requested by a Universal Link (productURL != nil), then present modally.
// Try in Mobile Safari dll://productView?product=123
guard context.productURL != nil else {
Expand All @@ -35,13 +35,11 @@ class ProductConfiguration {
.from(GeneralStep.current())
.assemble()

}
})
// If UINavigationController is visible on the screen - just push
.addCase(from: ClassFinder<UINavigationController, ProductContext>(options: .currentVisibleOnly))
.assemble(default: {
// Otherwise - present in the UINavigation controller that belongs to Circle tab
return ConfigurationHolder.configuration.circleScreen.expectingContainer()
}))
// Otherwise - present in the UINavigation controller that belongs to Circle tab
.assemble(default: ConfigurationHolder.configuration.circleScreen.expectingContainer()))
.assemble()

// This path is used to test the transactions in presentations. Does not have any other purposes
Expand Down
22 changes: 11 additions & 11 deletions Example/Tests/ExtrasTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -212,16 +212,16 @@ class ExtrasTest: XCTestCase {

func testNavigationDetailsFinder() {
let emptyFinder = DetailsNavigationFinder<Any?>(options: SearchOptions.current)
XCTAssertNil(try emptyFinder.findViewController())
XCTAssertNil(emptyFinder.getViewController())

let splitViewController = UISplitViewController()
let finder = DetailsNavigationFinder<Any?>(options: SearchOptions.current, startingPoint: DefaultStackIterator.StartingPoint.custom(splitViewController))
splitViewController.viewControllers = [UINavigationController()]
XCTAssertNil(try finder.findViewController())
XCTAssertNil(finder.getViewController())

let navigationController = UINavigationController()
splitViewController.viewControllers = [UINavigationController(), navigationController]
XCTAssertEqual(try finder.findViewController(), navigationController)
XCTAssertEqual(finder.getViewController(), navigationController)

class SpecialSplitNavigationController: UINavigationController {
let nestedNavigaionController: UINavigationController
Expand All @@ -247,7 +247,7 @@ class ExtrasTest: XCTestCase {

let secondNavigationController = SpecialSplitNavigationController(nestedNavigaionController: navigationController)
splitViewController.viewControllers = [secondNavigationController]
XCTAssertEqual(try finder.findViewController(), navigationController)
XCTAssertEqual(finder.getViewController(), navigationController)
}

func testRouterNavigationToDestination() {
Expand Down Expand Up @@ -348,14 +348,14 @@ class ExtrasTest: XCTestCase {
var window: UIWindow? = UIWindow()
window?.rootViewController = UINavigationController()
let windowProvider = CustomWindowProvider(window: window!)
let action = DispatchQueue.delay(GeneralAction.replaceRoot(windowProvider: windowProvider), for: .milliseconds(3))
let action = DispatchQueue.delay(GeneralAction.replaceRoot(windowProvider: windowProvider))
let newViewController = UIViewController()
var expectation = XCTestExpectation(description: "Action to finish")
action.perform(with: newViewController, on: window!.rootViewController!, animated: true, completion: { result in
expectation.fulfill()
XCTAssertTrue(result.isSuccessful)
})
wait(for: [expectation], timeout: 0.3)
wait(for: [expectation], timeout: 0.4)
XCTAssertEqual(window?.rootViewController, newViewController)
window = nil

Expand All @@ -364,7 +364,7 @@ class ExtrasTest: XCTestCase {
expectation.fulfill()
XCTAssertFalse(result.isSuccessful)
})
wait(for: [expectation], timeout: 0.3)
wait(for: [expectation], timeout: 0.4)

var wasInCompletion = false
action.perform(with: newViewController, on: UIViewController(), animated: false, completion: { result in
Expand All @@ -387,24 +387,24 @@ class ExtrasTest: XCTestCase {
}
}

var action = DispatchQueue.delay(TestAction(result: .success), for: .milliseconds(3))
var action = DispatchQueue.delay(TestAction(result: .success))
let tabBarController = UITabBarController()
var expectation = XCTestExpectation(description: "Action to finish")
action.perform(with: UIViewController(), on: tabBarController, animated: true, completion: { result in
expectation.fulfill()
XCTAssertTrue(result.isSuccessful)
})
wait(for: [expectation], timeout: 0.3)
wait(for: [expectation], timeout: 0.4)
XCTAssertEqual(tabBarController.viewControllers?.count, 1)
tabBarController.setViewControllers([], animated: false)

action = DispatchQueue.delay(TestAction(result: .failure(RoutingError.compositionFailed(.init("test")))), for: .milliseconds(3))
action = DispatchQueue.delay(TestAction(result: .failure(RoutingError.compositionFailed(.init("test")))))
expectation = XCTestExpectation(description: "Action to finish")
action.perform(with: UIViewController(), on: tabBarController, animated: true, completion: { result in
expectation.fulfill()
XCTAssertFalse(result.isSuccessful)
})
wait(for: [expectation], timeout: 0.3)
wait(for: [expectation], timeout: 0.4)
XCTAssertEqual(tabBarController.viewControllers?.count, 0)

var wasInCompletion = false
Expand Down
23 changes: 22 additions & 1 deletion Example/Tests/FinderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@ import UIKit
import XCTest
@testable import RouteComposer

extension DefaultStackIterator.StartingPoint: Equatable {

public static func == (lhs: DefaultStackIterator.StartingPoint, rhs: DefaultStackIterator.StartingPoint) -> Bool {
switch (lhs, rhs) {
case (.root, .root):
return true
case (.topmost, .topmost):
return true
case let (.custom(lvc), .custom(rvc)):
do {
return try lvc() === rvc()
} catch {
return false
}
default:
return false
}
}

}

class FinderTest: XCTestCase {

class TestContextCheckingViewController: UIViewController, ContextChecking {
Expand Down Expand Up @@ -69,7 +90,7 @@ class FinderTest: XCTestCase {

var currentViewController: UIViewController? = UIViewController()
let iterator = DefaultStackIterator(options: .current,
startingPoint: .custom(try TestInstanceFinder<UIViewController, Any?>(instance: currentViewController).findViewController()))
startingPoint: .custom(TestInstanceFinder<UIViewController, Any?>(instance: currentViewController).getViewController()))
XCTAssertEqual(iterator.options, .current)
XCTAssertEqual(iterator.startingPoint, .custom(currentViewController))
XCTAssertEqual(try? iterator.getStartingViewController(), currentViewController)
Expand Down
2 changes: 1 addition & 1 deletion RouteComposer.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'RouteComposer'
s.version = '2.3.0'
s.version = '2.3.1'
s.summary = 'Protocol oriented library that helps to handle view controllers composition, navigation and deep linking tasks.'
s.swift_version = '5.0'

Expand Down
21 changes: 15 additions & 6 deletions RouteComposer/Classes/Assemblies/SwitchAssembly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ import UIKit
/// .addCase(from: ClassFinder<UINavigationController, ProductContext>(options: .currentVisibleOnly))
///
/// // Otherwise - create a UINavigationController and present modally
/// .assemble(default: {
/// return ChainAssembly.from(NavigationControllerStep<UINavigationController, ProductContext>())
/// .using(GeneralAction.presentModally())
/// .from(GeneralStep.current())
/// .assemble()
/// })
/// .assemble(default: ChainAssembly.from(NavigationControllerStep<UINavigationController, ProductContext>())
/// .using(GeneralAction.presentModally())
/// .from(GeneralStep.current())
/// .assemble())
/// ```
public final class SwitchAssembly<ViewController: UIViewController, Context> {

Expand Down Expand Up @@ -130,6 +128,17 @@ public final class SwitchAssembly<ViewController: UIViewController, Context> {
return DestinationStep(SwitcherStep(resolvers: resolvers))
}

/// Assembles all the cases in a `DestinationStep` instance and adds the default implementation, providing the step it is to perform
///
/// - Parameter step: an instance of `DestinationStep`
/// - Returns: a final instance of `DestinationStep`
public func assemble(default step: DestinationStep<ViewController, Context>) -> DestinationStep<ViewController, Context> {
resolvers.append(BlockResolver(resolverBlock: { _ in
return step
}))
return DestinationStep(SwitcherStep(resolvers: resolvers))
}

}

// MARK: Methods for ContainerViewController
Expand Down
4 changes: 2 additions & 2 deletions RouteComposer/Classes/Extra/DispatchQueue+Action.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public extension DispatchQueue {
/// Parameters:
/// - action: `Action` instance
/// - timeInterval: `DispatchTimeInterval` instance
static func delay<A: Action>(_ action: A, for timeInterval: DispatchTimeInterval) -> DispatchQueueWrappedAction<A> {
static func delay<A: Action>(_ action: A, for timeInterval: DispatchTimeInterval = .milliseconds(300)) -> DispatchQueueWrappedAction<A> {
return DispatchQueueWrappedAction(action, timeInterval: timeInterval)
}

Expand All @@ -24,7 +24,7 @@ public extension DispatchQueue {
/// Parameters:
/// - action: `ContainerAction` instance
/// - timeInterval: `DispatchTimeInterval` instance
static func delay<A: ContainerAction>(_ action: A, for timeInterval: DispatchTimeInterval) -> DispatchQueueWrappedContainerAction<A> {
static func delay<A: ContainerAction>(_ action: A, for timeInterval: DispatchTimeInterval = .milliseconds(300)) -> DispatchQueueWrappedContainerAction<A> {
return DispatchQueueWrappedContainerAction(action, timeInterval: timeInterval)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public struct DefaultStackIterator: StackIterator {
/// - topMost: Start from the topmost `UIViewController`
/// - root: Start from the `UIWindow`s root `UIViewController`
/// - custom: Start from the custom `UIViewController`
public enum StartingPoint: Equatable {
public enum StartingPoint {

/// Start from the topmost `UIViewController`
case topmost
Expand All @@ -26,23 +26,6 @@ public struct DefaultStackIterator: StackIterator {
/// Start from the custom `UIViewController`
case custom(@autoclosure () throws -> UIViewController?)

public static func == (lhs: StartingPoint, rhs: StartingPoint) -> Bool {
switch (lhs, rhs) {
case (.root, .root):
return true
case (.topmost, .topmost):
return true
case let (.custom(lvc), .custom(rvc)):
do {
return try lvc() === rvc()
} catch {
return false
}
default:
return false
}
}

}

// MARK: Properties
Expand Down
9 changes: 1 addition & 8 deletions RouteComposer/Classes/Router/DefaultRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ public struct DefaultRouter: InterceptableRouter, MainThreadChecking {
assertIfNotMainThread(logger: logger)
do {
let taskStack = try prepareTaskStack(with: context)

// Builds stack of factories and finds a view controller to start a navigation process from.
// Returns (rootViewController, factories) tuple
// where rootViewController is the origin of the chain of views to be built for a given destination.
let navigationStack = try prepareFactoriesStack(to: step, with: context, taskStack: taskStack)

let viewController = navigationStack.rootViewController, factoriesStack = navigationStack.factories
Expand Down Expand Up @@ -118,16 +114,13 @@ public struct DefaultRouter: InterceptableRouter, MainThreadChecking {
// Creates a class responsible to run the tasks for this particular step
let stepTaskRunner = try taskStack.taskRunner(for: step, with: context)

// Performs current step
switch try step.perform(with: context) {
case .success(let viewController):
logger?.log(.info("\(String(describing: step)) found " +
"\(String(describing: viewController)) to start the navigation process from."))
try stepTaskRunner.perform(on: viewController, with: context)
return (rootViewController: viewController, result.factories)
case .build(let originalFactory):
// If the view controller to start from is not found, but the current step has a `Factory` to build it,
// then add factory to the stack
logger?.log(.info("\(String(describing: step)) hasn't found a corresponding view " +
"controller in the stack, so it will be built using \(String(describing: originalFactory))."))

Expand All @@ -153,7 +146,7 @@ public struct DefaultRouter: InterceptableRouter, MainThreadChecking {
}
})

//Throws an exception if the router hasn't found a view controller to start the stack from.
//Throw an exception if the router hasn't found a view controller to start the stack from.
guard let rootViewController = result.rootViewController else {
throw RoutingError.initialController(.notFound, .init("Unable to start the navigation process as the view controller to start from was not found."))
}
Expand Down
6 changes: 3 additions & 3 deletions docs/tests/ActionBox.swift.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,17 @@ <h4 class="cov_filepath">RouteComposer/Classes/Router/Type Erasure/Boxes/ActionB
<tr class="covered">
<td class="num">12</td>
<td class="src"><pre><code class="objc"> init(_ action: A) {</code></pre></td>
<td class="coverage">249x</td>
<td class="coverage">255x</td>
</tr>
<tr class="covered">
<td class="num">13</td>
<td class="src"><pre><code class="objc"> self.action = action</code></pre></td>
<td class="coverage">249x</td>
<td class="coverage">255x</td>
</tr>
<tr class="covered">
<td class="num">14</td>
<td class="src"><pre><code class="objc"> }</code></pre></td>
<td class="coverage">249x</td>
<td class="coverage">255x</td>
</tr>
<tr class="never">
<td class="num">15</td>
Expand Down
22 changes: 11 additions & 11 deletions docs/tests/BaseEntitiesCollector.swift.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,57 +90,57 @@ <h4 class="cov_filepath">RouteComposer/Classes/Assemblies/Helpers/BaseEntitiesCo
<tr class="covered">
<td class="num">16</td>
<td class="src"><pre><code class="objc"> F.ViewController == FactoryBoxer.FactoryType.ViewController, F.Context == FactoryBoxer.FactoryType.Context {</code></pre></td>
<td class="coverage">239x</td>
<td class="coverage">243x</td>
</tr>
<tr class="covered">
<td class="num">17</td>
<td class="src"><pre><code class="objc"> self.finder = FinderBox(finder)</code></pre></td>
<td class="coverage">239x</td>
<td class="coverage">243x</td>
</tr>
<tr class="covered">
<td class="num">18</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">239x</td>
<td class="coverage">243x</td>
</tr>
<tr class="covered">
<td class="num">19</td>
<td class="src"><pre><code class="objc"> if let factoryBox = FactoryBoxer(factory, action: ActionBoxer(action)) {</code></pre></td>
<td class="coverage">239x</td>
<td class="coverage">243x</td>
</tr>
<tr class="covered">
<td class="num">20</td>
<td class="src"><pre><code class="objc"> self.factory = factoryBox</code></pre></td>
<td class="coverage">154x</td>
<td class="coverage">156x</td>
</tr>
<tr class="covered">
<td class="num">21</td>
<td class="src"><pre><code class="objc"> } else if let finderFactory = FinderFactory(finder: finder) {</code></pre></td>
<td class="coverage">239x</td>
<td class="coverage">243x</td>
</tr>
<tr class="covered">
<td class="num">22</td>
<td class="src"><pre><code class="objc"> self.factory = FactoryBox(finderFactory, action: ActionBox(ViewControllerActions.NilAction()))</code></pre></td>
<td class="coverage">65x</td>
<td class="coverage">67x</td>
</tr>
<tr class="covered">
<td class="num">23</td>
<td class="src"><pre><code class="objc"> } else {</code></pre></td>
<td class="coverage">239x</td>
<td class="coverage">243x</td>
</tr>
<tr class="covered">
<td class="num">24</td>
<td class="src"><pre><code class="objc"> self.factory = nil</code></pre></td>
<td class="coverage">174x</td>
<td class="coverage">176x</td>
</tr>
<tr class="covered">
<td class="num">25</td>
<td class="src"><pre><code class="objc"> }</code></pre></td>
<td class="coverage">239x</td>
<td class="coverage">243x</td>
</tr>
<tr class="covered">
<td class="num">26</td>
<td class="src"><pre><code class="objc"> }</code></pre></td>
<td class="coverage">239x</td>
<td class="coverage">243x</td>
</tr>
<tr class="never">
<td class="num">27</td>
Expand Down
Loading

0 comments on commit fade23f

Please sign in to comment.