Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* [OPR-496]: Adds FilterProcedure * [OPR-496]: Adds filter method for when Result is a sequence
- Loading branch information
Showing
6 changed files
with
143 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// | ||
// ProcedureKit | ||
// | ||
// Copyright © 2016 ProcedureKit. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
public class FilterProcedure<Element>: Procedure, ResultInjectionProtocol { | ||
|
||
public var requirement: AnySequence<Element> | ||
public var result: Array<Element> = [] | ||
public let isIncluded: (Element) throws -> Bool | ||
|
||
public init<S: Sequence>(source: S, isIncluded block: @escaping (Element) throws -> Bool) where S.Iterator.Element == Element, S.SubSequence: Sequence, S.SubSequence.Iterator.Element == Element, S.SubSequence.SubSequence == S.SubSequence { | ||
requirement = AnySequence(source) | ||
isIncluded = block | ||
super.init() | ||
} | ||
|
||
public convenience init(isIncluded block: @escaping (Element) throws -> Bool) { | ||
self.init(source: [], isIncluded: block) | ||
} | ||
|
||
public override func execute() { | ||
var finishingError: Error? = nil | ||
defer { finish(withError: finishingError) } | ||
do { | ||
result = try requirement.filter(isIncluded) | ||
} | ||
catch { finishingError = error } | ||
} | ||
} | ||
|
||
public extension ProcedureProtocol where Self: ResultInjectionProtocol, Self.Result: Sequence { | ||
|
||
func filter(includeElement: @escaping (Result.Iterator.Element) throws -> Bool) -> FilterProcedure<Result.Iterator.Element> { | ||
let filter = FilterProcedure(isIncluded: includeElement) | ||
filter.inject(dependency: self) { filter, dependency, errors in | ||
guard errors.isEmpty else { | ||
filter.cancel(withError: ProcedureKitError.dependency(finishedWithErrors: errors)); return | ||
} | ||
filter.requirement = AnySequence(Array(dependency.result)) | ||
} | ||
return filter | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// | ||
// ProcedureKit | ||
// | ||
// Copyright © 2016 ProcedureKit. All rights reserved. | ||
// | ||
|
||
import XCTest | ||
import TestingProcedureKit | ||
@testable import ProcedureKit | ||
|
||
class NumbersProcedure: Procedure, ResultInjectionProtocol { | ||
|
||
var requirement: Void = () | ||
var result: Array<Int> = [] | ||
var error: Error? = nil | ||
|
||
init(error: Error? = nil) { | ||
self.error = error | ||
super.init() | ||
} | ||
|
||
override func execute() { | ||
if let error = error { | ||
finish(withError: error) | ||
} | ||
else { | ||
result = [0, 1, 2, 3, 4, 5 , 6 , 7, 8, 9] | ||
finish() | ||
} | ||
} | ||
} | ||
|
||
class FilterProcedureTests: ProcedureKitTestCase { | ||
|
||
func test__requirement_is_filtered_to_result() { | ||
let evenOnly = FilterProcedure(source: [0,1,2,3,4,5,6,7]) { $0 % 2 == 0 } | ||
wait(for: evenOnly) | ||
XCTAssertProcedureFinishedWithoutErrors(evenOnly) | ||
XCTAssertEqual(evenOnly.result, [0,2,4,6]) | ||
} | ||
|
||
func test__finishes_with_error_if_block_throws() { | ||
let evenOnly = FilterProcedure(source: [0,1,2,3,4,5,6,7]) { _ in throw TestError() } | ||
wait(for: evenOnly) | ||
XCTAssertProcedureFinishedWithErrors(evenOnly, count: 1) | ||
} | ||
|
||
func test__filter_dependency_which_finishes_without_errors() { | ||
let numbers = NumbersProcedure() | ||
let filtered = numbers.filter { $0 % 2 == 0 } | ||
wait(for: numbers, filtered) | ||
XCTAssertProcedureFinishedWithoutErrors(numbers) | ||
XCTAssertProcedureFinishedWithoutErrors(filtered) | ||
XCTAssertEqual(filtered.result, [0,2,4,6,8]) | ||
} | ||
|
||
func test__filter_dependency_which_finishes_with_errors() { | ||
let numbers = NumbersProcedure(error: TestError()) | ||
let filtered = numbers.filter { $0 % 2 == 0 } | ||
wait(for: numbers, filtered) | ||
XCTAssertProcedureFinishedWithErrors(numbers, count: 1) | ||
XCTAssertProcedureCancelledWithErrors(filtered, count: 1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// | ||
// ProcedureKit | ||
// | ||
// Copyright © 2016 ProcedureKit. All rights reserved. | ||
// | ||
|
||
import XCTest | ||
import TestingProcedureKit | ||
@testable import ProcedureKit | ||
|
||
class MapProcedureTests: ProcedureKitTestCase { | ||
|
||
func test__requirement_is_mapped_to_result() { | ||
let timesTwo = MapProcedure<Int, Int> { return $0 * 2 } | ||
timesTwo.requirement = 2 | ||
wait(for: timesTwo) | ||
XCTAssertEqual(timesTwo.result, 4) | ||
} | ||
} |