Skip to content

Commit

Permalink
Routable inputs include finalDestination and pathNode (#13)
Browse files Browse the repository at this point in the history
Signed-off-by: Quickthyme <[email protected]>
  • Loading branch information
quickthyme authored May 5, 2020
1 parent 9012950 commit 39b5269
Show file tree
Hide file tree
Showing 18 changed files with 80 additions and 35 deletions.
1 change: 0 additions & 1 deletion Sources/QRoute/Driving/QRouteDriving.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

public protocol QRouteDriving: class {

func driveParent(from source: QRoutable,
Expand Down
26 changes: 18 additions & 8 deletions Sources/QRoute/Driving/QRouteWalkingDriver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ public final class QRouteWalkingDriver: QRouteDriving {

public func driveSub(_ targetId: QRouteId, from source: QRoutable, input: QRouteResolving.Input?, animated:Bool, completion: QRouteResolving.Completion?) {
guard let clonePath = buildClonePath(to: targetId, from: source) else { completion?(nil); return }
type(of: self).nextStep(clonePath, source, input ?? [:], animated, completion)
let finalDestination = clonePath.last?.route.id
type(of: self).nextStep(clonePath, source, finalDestination, input ?? [:], animated, completion)
}

public func driveTo(_ targetId: QRouteId, from source: QRoutable, input: QRouteResolving.Input?, animated:Bool, completion: QRouteResolving.Completion?) {
let path = source.routeResolver.route.findPath(to: targetId)
type(of: self).nextStep(path, source, input ?? [:], animated, completion)
let finalDestination = path.last?.route.id
type(of: self).nextStep(path, source, finalDestination, input ?? [:], animated, completion)
}
}

Expand All @@ -25,20 +27,28 @@ fileprivate extension QRouteWalkingDriver {
return [.DOWN( QRoute(deepClone: target).applyParent(sourceRoute) )]
}

static func nextStep(_ path: QRoutePath, _ routable: QRoutable?, _ input: QRouteResolving.Input,
static func nextStep(_ path: QRoutePath,
_ routable: QRoutable?,
_ finalDestination: QRouteId!,
_ input: QRouteResolving.Input,
_ animated:Bool,
_ finalCompletion: QRouteResolving.Completion?) {
guard let nextRoutable = routable, (path.count > 0)
guard
let nextRoutable = routable,
(!path.isEmpty)
else { finalCompletion?(routable); return }
let nextCompletion = nextStepCompletion(path, input, animated, finalCompletion)
QRouteWalkingDriverStep.perform(nextRoutable, path[0], input, animated, nextCompletion)

let nextCompletion = nextStepCompletion(path, finalDestination, input, animated, finalCompletion)
QRouteWalkingDriverStep.perform(nextRoutable, path[0], finalDestination, input, animated, nextCompletion)
}

static func nextStepCompletion(_ path: QRoutePath, _ input: QRouteResolving.Input,
static func nextStepCompletion(_ path: QRoutePath,
_ finalDestination: QRouteId,
_ input: QRouteResolving.Input,
_ animated:Bool,
_ finalCompletion: QRouteResolving.Completion?) -> QRouteResolving.Completion {
return {
QRouteWalkingDriver.nextStep(QRoutePath( path.dropFirst() ), $0, input, animated, finalCompletion)
QRouteWalkingDriver.nextStep(QRoutePath(path.dropFirst()), $0, finalDestination, input, animated, finalCompletion)
}
}
}
13 changes: 11 additions & 2 deletions Sources/QRoute/Driving/QRouteWalkingDriverStep.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@

import Dispatch

internal final class QRouteWalkingDriverStep {

static func perform(_ routable: QRoutable, _ pathNode: QRoutePathNode, _ input: QRouteResolving.Input,
static func perform(_ routable: QRoutable,
_ pathNode: QRoutePathNode,
_ finalDestination: QRouteId,
_ input: QRouteResolving.Input,
_ animated: Bool,
_ stepCompletion: @escaping QRouteResolving.Completion) {

let input = input.merging(
[
QRouteResolvingInputKey.finalDestination: finalDestination,
QRouteResolvingInputKey.pathNode: pathNode
],
uniquingKeysWith: { (_, new) in new })

switch (pathNode) {

case let .DOWN(nextRoute):
Expand Down
1 change: 0 additions & 1 deletion Sources/QRoute/QRoutable.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

public protocol QRoutable: class {
var routeResolver: QRouteResolving! { get }
}
1 change: 0 additions & 1 deletion Sources/QRoute/QRoute+ConvenienceInit.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

public extension QRoute {
convenience init(_ id:QRouteId, dependencies: [String], _ routes: QRoute...) {
self.init(id: id, dependencies: dependencies, routes: routes)
Expand Down
1 change: 0 additions & 1 deletion Sources/QRoute/QRoute.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

public typealias QRouteId = String

public class QRoute: Hashable, CustomDebugStringConvertible {
Expand Down
1 change: 0 additions & 1 deletion Sources/QRoute/QRoutePath.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

public typealias QRoutePath = Array<QRoutePathNode>

public enum QRoutePathNode: Hashable {
Expand Down
1 change: 0 additions & 1 deletion Sources/QRoute/Resolving/QRouteResolver.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

public final class QRouteResolver: QRouteResolving {

public init(_ route: QRoute,
Expand Down
1 change: 0 additions & 1 deletion Sources/QRoute/Resolving/QRouteResolverAction.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

public extension QRouteResolver {

struct ActionType {
Expand Down
9 changes: 7 additions & 2 deletions Sources/QRoute/Resolving/QRouteResolving.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

public protocol QRouteResolving: class {
typealias Input = [String:Any]
typealias Completion = (QRoutable?)->()
Expand All @@ -16,6 +15,11 @@ public protocol QRouteResolving: class {
static func mergeInputDependencies(resolver: QRouteResolving, input: Input)
}

public struct QRouteResolvingInputKey {
public static let finalDestination = "QRouteResolvingInputKey.finalDestination"
public static let pathNode = "QRouteResolvingInputKey.pathNode"
}

public extension QRouteResolving {
func resolveRouteToSelf(from: QRoutable, input: Input, animated: Bool, completion: @escaping Completion) {
mergeInputDependencies(input: input)
Expand All @@ -32,7 +36,8 @@ public extension QRouteResolving {
}

fileprivate func _mergeInputDependencies(_ resolver: QRouteResolving, _ newInput: QRouteResolving.Input) {
let dependencies = resolver.route.dependencies
let dependencies = [QRouteResolvingInputKey.finalDestination,
QRouteResolvingInputKey.pathNode] + resolver.route.dependencies
let filteredInput = newInput.filter { key, val in dependencies.contains(key) }
resolver.input = resolver.input.merging(filteredInput, uniquingKeysWith: { (_, new) in new })
}
53 changes: 44 additions & 9 deletions Tests/QRouteTests/Driving/QRouteWalkingDriverTests.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import XCTest
import QRoute

Expand Down Expand Up @@ -60,12 +59,18 @@ class QRouteWalkingDriverTests: XCTestCase {
finalResolver = $0?.routeResolver as? QRouteResolverMock
expectComplete.fulfill() })

wait(for: [expectComplete], timeout: 0.1)
wait(for: [expectComplete], timeout: 2.0)
then("it should have routed to parent one times landing on 'first'") {
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToChild()"), 0)
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToSelf()"), 0)
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToParent()"), 1)
XCTAssertEqual(finalResolver?.routeTrail, [first])

with("finalDestination and pathNode inputs make it to the end") {
let finalInput = finalResolver?.getArgument("resolveRouteToParent()", "input") as? [String: Any]
XCTAssertEqual(finalInput?[QRouteResolvingInputKey.finalDestination] as? QRouteId, "first")
XCTAssertNotNil(finalInput?[QRouteResolvingInputKey.pathNode] as? QRoutePathNode)
}
}
}
}
Expand All @@ -87,12 +92,18 @@ class QRouteWalkingDriverTests: XCTestCase {
finalResolver = $0?.routeResolver as? QRouteResolverMock
expectComplete.fulfill() })

wait(for: [expectComplete], timeout: 0.1)
wait(for: [expectComplete], timeout: 2.0)
then("it should have routed to child one times landing on third") {
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToChild()"), 1)
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToSelf()"), 0)
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToParent()"), 0)
XCTAssertEqual(finalResolver?.routeTrail, [third])

with("finalDestination and pathNode inputs make it to the end") {
let finalInput = finalResolver?.getArgument("resolveRouteToChild()", "input") as? [String: Any]
XCTAssertEqual(finalInput?[QRouteResolvingInputKey.finalDestination] as? QRouteId, "third")
XCTAssertNotNil(finalInput?[QRouteResolvingInputKey.pathNode] as? QRoutePathNode)
}
}
}
}
Expand All @@ -115,12 +126,18 @@ class QRouteWalkingDriverTests: XCTestCase {
finalResolver = $0?.routeResolver as? QRouteResolverMock
expectComplete.fulfill() })

wait(for: [expectComplete], timeout: 0.1)
wait(for: [expectComplete], timeout: 2.0)
then("it should have routed to self one times") {
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToChild()"), 0)
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToSelf()"), 1)
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToParent()"), 0)
XCTAssertEqual(finalResolver?.routeTrail, [second])

with("finalDestination and pathNode inputs make it to the end") {
let finalInput = finalResolver?.getArgument("resolveRouteToSelf()", "input") as? [String: Any]
XCTAssertEqual(finalInput?[QRouteResolvingInputKey.finalDestination] as? QRouteId, "second")
XCTAssertNotNil(finalInput?[QRouteResolvingInputKey.pathNode] as? QRoutePathNode)
}
}
}
}
Expand All @@ -142,13 +159,19 @@ class QRouteWalkingDriverTests: XCTestCase {
finalResolver = $0?.routeResolver as? QRouteResolverMock
expectComplete.fulfill() })

wait(for: [expectComplete], timeout: 0.1)
wait(for: [expectComplete], timeout: 2.0)
then("it should have routed to child two times landing on 'third'") {
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToChild()"), 2)
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToSelf()"), 0)
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToParent()"), 0)
XCTAssertEqual(finalResolver?.routeTrail, [second, third])
XCTAssertEqual(finalResolver?.route, third)

with("finalDestination and pathNode inputs make it to the end") {
let finalInput = finalResolver?.getArgument("resolveRouteToChild()", "input") as? [String: Any]
XCTAssertEqual(finalInput?[QRouteResolvingInputKey.finalDestination] as? QRouteId, "third")
XCTAssertNotNil(finalInput?[QRouteResolvingInputKey.pathNode] as? QRoutePathNode)
}
}
}
}
Expand All @@ -170,12 +193,18 @@ class QRouteWalkingDriverTests: XCTestCase {
finalResolver = $0?.routeResolver as? QRouteResolverMock
expectComplete.fulfill() })

wait(for: [expectComplete], timeout: 0.1)
wait(for: [expectComplete], timeout: 2.0)
then("it should have routed to parent two times landing on 'first'") {
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToChild()"), 0)
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToSelf()"), 0)
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToParent()"), 2)
XCTAssertEqual(finalResolver?.routeTrail, [second, first])

with("finalDestination and pathNode inputs make it to the end") {
let finalInput = finalResolver?.getArgument("resolveRouteToParent()", "input") as? [String: Any]
XCTAssertEqual(finalInput?[QRouteResolvingInputKey.finalDestination] as? QRouteId, "first")
XCTAssertNotNil(finalInput?[QRouteResolvingInputKey.pathNode] as? QRoutePathNode)
}
}
}
}
Expand All @@ -202,12 +231,18 @@ class QRouteWalkingDriverTests: XCTestCase {
finalResolver = $0?.routeResolver as? QRouteResolverMock
expectComplete.fulfill() })

wait(for: [expectComplete], timeout: 0.1)
wait(for: [expectComplete], timeout: 2.0)
then("it should have routed to parent 3 times and child 2 times landing at 'ZachTwo'") {
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToChild()"), 2)
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToSelf()"), 0)
XCTAssertEqual(finalResolver?.getTimesCalled("resolveRouteToParent()"), 3)
XCTAssertEqual(finalResolver?.routeTrail, [bravoOne, bravo, root, help, zachTwo])

with("finalDestination and pathNode inputs make it to the end") {
let finalInput = finalResolver?.getArgument("resolveRouteToChild()", "input") as? [String: Any]
XCTAssertEqual(finalInput?[QRouteResolvingInputKey.finalDestination] as? QRouteId, "ZachTwo")
XCTAssertNotNil(finalInput?[QRouteResolvingInputKey.pathNode] as? QRoutePathNode)
}
}
}
}
Expand All @@ -234,7 +269,7 @@ class QRouteWalkingDriverTests: XCTestCase {
finalResolver = $0?.routeResolver as? QRouteResolverMock
expectComplete.fulfill() })

wait(for: [expectComplete], timeout: 0.1)
wait(for: [expectComplete], timeout: 2.0)
then("it should have routed to child 1 times landing at 'ZachTwo' clone") {
let zachTwoClone = finalResolver!.route
XCTAssertEqual(finalResolver?.routeTrail, [zachTwoClone])
Expand Down Expand Up @@ -270,7 +305,7 @@ class QRouteWalkingDriverTests: XCTestCase {
backResult = $0; expectComplete.fulfill(); }
)

wait(for: [expectComplete], timeout: 0.1)
wait(for: [expectComplete], timeout: 2.0)
then("it should arrive back at 'BravoOne'") {
XCTAssertEqual(backResult?.routeResolver.route, bravoOne)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import XCTest
import QRoute

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import XCTest
import QRoute

Expand Down
1 change: 0 additions & 1 deletion Tests/QRouteTests/Resolving/QRouteResolverTests.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import XCTest
import QRoute

Expand Down
1 change: 0 additions & 1 deletion Tests/QRouteTests/helpers/BDDTestHelpers.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import XCTest

extension XCTestCase {
Expand Down
1 change: 0 additions & 1 deletion Tests/QRouteTests/helpers/QRouteResolverTestHelpers.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import XCTest
import QRoute

Expand Down
1 change: 0 additions & 1 deletion Tests/QRouteTests/mocks/MockQRoutePlan.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import QRoute

public func MockQRoutePlan() -> QRoute {
Expand Down
1 change: 0 additions & 1 deletion Tests/QRouteTests/mocks/StubQResolverActions.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import QRoute

public class StubQResolverActions {
Expand Down

0 comments on commit 39b5269

Please sign in to comment.