From 2b4de5e2c296cbe2fc38a6688f21c68420bbe436 Mon Sep 17 00:00:00 2001 From: tokijh Date: Wed, 8 May 2019 10:41:49 +0900 Subject: [PATCH 1/6] Support Swift 5.0 and RxSwift 5.0 --- Package.resolved | 4 +- Package.swift | 4 +- Sources/RxExpect/AnyTestTime.swift | 2 +- Sources/RxExpect/Assertion.swift | 8 +-- Sources/RxExpect/Deprecated.swift | 17 ++++++ Sources/RxExpect/RxExpect.swift | 15 +----- Sources/RxExpect/Utility.swift | 8 +-- Tests/RxExpectTests/RxExpectTests.swift | 52 +++++++++--------- Tests/RxExpectTests/UtilityTests.swift | 72 ++++++++++++------------- 9 files changed, 96 insertions(+), 86 deletions(-) create mode 100644 Sources/RxExpect/Deprecated.swift diff --git a/Package.resolved b/Package.resolved index fbc3172..e3afef8 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/ReactiveX/RxSwift.git", "state": { "branch": null, - "revision": "0df62b4d562f8620d4b795b18e4adf0b631527a1", - "version": "4.3.1" + "revision": "b3e888b4972d9bc76495dd74d30a8c7fad4b9395", + "version": "5.0.1" } } ] diff --git a/Package.swift b/Package.swift index 421e07e..c71f5cc 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:4.2 +// swift-tools-version:5.0 import PackageDescription @@ -8,7 +8,7 @@ let package = Package( .library(name: "RxExpect", targets: ["RxExpect"]), ], dependencies: [ - .package(url: "https://github.com/ReactiveX/RxSwift.git", .upToNextMajor(from: "4.0.0")), + .package(url: "https://github.com/ReactiveX/RxSwift.git", .upToNextMajor(from: "5.0.0")), ], targets: [ .target(name: "RxExpect", dependencies: ["RxSwift", "RxTest"]), diff --git a/Sources/RxExpect/AnyTestTime.swift b/Sources/RxExpect/AnyTestTime.swift index d071a0a..06503b4 100644 --- a/Sources/RxExpect/AnyTestTime.swift +++ b/Sources/RxExpect/AnyTestTime.swift @@ -4,5 +4,5 @@ import RxTest let AnyTestTime = TestTime.min public func next(_ element: T) -> Recorded> { - return next(AnyTestTime, element) + return Recorded.next(AnyTestTime, element) } diff --git a/Sources/RxExpect/Assertion.swift b/Sources/RxExpect/Assertion.swift index 50d951c..9fb83de 100644 --- a/Sources/RxExpect/Assertion.swift +++ b/Sources/RxExpect/Assertion.swift @@ -13,17 +13,17 @@ public typealias AssertionClosure = ([Recorded>]) -> Void open class Assertion: AnyAssertion { let source: O let disposeAt: TestTime? - let closure: AssertionClosure - var recorder: TestableObserver? + let closure: AssertionClosure + var recorder: TestableObserver? - init(source: O, disposeAt: TestTime?, closure: @escaping AssertionClosure) { + init(source: O, disposeAt: TestTime?, closure: @escaping AssertionClosure) { self.source = source self.disposeAt = disposeAt self.closure = closure } func prepareRecorder(scheduler: TestScheduler, disposeAt: TestTime?) { - let recorder = scheduler.createObserver(O.E.self) + let recorder = scheduler.createObserver(O.Element.self) self.recorder = recorder let subscription = self.source.asObservable().subscribe(recorder) diff --git a/Sources/RxExpect/Deprecated.swift b/Sources/RxExpect/Deprecated.swift new file mode 100644 index 0000000..20f26d4 --- /dev/null +++ b/Sources/RxExpect/Deprecated.swift @@ -0,0 +1,17 @@ +import RxSwift +import RxTest + +extension RxExpect { + + @available(*, deprecated, message: "Variable is deprecated.") + public func input(_ variable: Variable, _ events: [Recorded>], file: StaticString = #file, line: UInt = #line) { + Swift.assert(!events.contains { $0.time == AnyTestTime }, "Input events should have specific time.", file: file, line: line) + self.maximumInputTime = ([self.maximumInputTime] + events.map { $0.time }).max() ?? self.maximumInputTime + self.deferredInputs.append { `self` in + self.scheduler + .createHotObservable(events) + .subscribe(onNext: { variable.value = $0 }) + .disposed(by: self.disposeBag) + } + } +} diff --git a/Sources/RxExpect/RxExpect.swift b/Sources/RxExpect/RxExpect.swift index 2614e4c..214eade 100644 --- a/Sources/RxExpect/RxExpect.swift +++ b/Sources/RxExpect/RxExpect.swift @@ -29,7 +29,7 @@ open class RxExpect { return object } - public func input(_ observer: O, _ events: [Recorded>], file: StaticString = #file, line: UInt = #line) { + public func input(_ observer: O, _ events: [Recorded>], file: StaticString = #file, line: UInt = #line) { Swift.assert(!events.contains { $0.time == AnyTestTime }, "Input events should have specific time.", file: file, line: line) self.maximumInputTime = ([self.maximumInputTime] + events.map { $0.time }).max() ?? self.maximumInputTime self.deferredInputs.append { `self` in @@ -40,18 +40,7 @@ open class RxExpect { } } - public func input(_ variable: Variable, _ events: [Recorded>], file: StaticString = #file, line: UInt = #line) { - Swift.assert(!events.contains { $0.time == AnyTestTime }, "Input events should have specific time.", file: file, line: line) - self.maximumInputTime = ([self.maximumInputTime] + events.map { $0.time }).max() ?? self.maximumInputTime - self.deferredInputs.append { `self` in - self.scheduler - .createHotObservable(events) - .subscribe(onNext: { variable.value = $0 }) - .disposed(by: self.disposeBag) - } - } - - open func assert(_ source: O, disposed: TestTime? = nil, closure: @escaping AssertionClosure) { + open func assert(_ source: O, disposed: TestTime? = nil, closure: @escaping AssertionClosure) { let assertion = Assertion(source: source, disposeAt: disposed, closure: closure) self.assertions.append(assertion) } diff --git a/Sources/RxExpect/Utility.swift b/Sources/RxExpect/Utility.swift index a0a2b32..d54cec7 100644 --- a/Sources/RxExpect/Utility.swift +++ b/Sources/RxExpect/Utility.swift @@ -40,19 +40,19 @@ public enum EventFilter { } public extension Array where Element: RecordedType, Element.ValueType: EventType { - public var elements: [Element.ValueType.ElementType] { + var elements: [Element.ValueType.ElementType] { return self.compactMap { $0.value.element } } - public var error: Error? { + var error: Error? { return self.lazy.compactMap { $0.value.error }.first } - public func filter(_ event: EventFilter) -> Array { + func filter(_ event: EventFilter) -> Array { return self.filter { $0.value.is(event) } } - public func `in`(_ timeRange: R) -> Array where R: RangeExpression, R.Bound == TestTime { + func `in`(_ timeRange: R) -> Array where R: RangeExpression, R.Bound == TestTime { return self.filter { timeRange.contains($0.time) } } } diff --git a/Tests/RxExpectTests/RxExpectTests.swift b/Tests/RxExpectTests/RxExpectTests.swift index cb2b08c..1574cca 100644 --- a/Tests/RxExpectTests/RxExpectTests.swift +++ b/Tests/RxExpectTests/RxExpectTests.swift @@ -9,7 +9,7 @@ final class RxExpectTests: XCTestCase { _ = { let test = RxExpect() let source = PublishSubject() - test.input(source, [next(100, "A"), next(200, "B")]) + test.input(source, [.next(100, "A"), .next(200, "B")]) test.assert(source) { _ in executions.append("1") } test.assert(source) { _ in executions.append("2") } test.assert(source) { _ in executions.append("3") } @@ -21,47 +21,51 @@ final class RxExpectTests: XCTestCase { let test = RxExpect() let subject = PublishSubject() test.input(subject, [ - next(100, "A"), - next(200, "B"), - completed(300), + .next(100, "A"), + .next(200, "B"), + .completed(300), ]) test.assert(subject) { events in XCTAssertEqual(events, [ - next(100, "A"), - next(200, "B"), - completed(300), + .next(100, "A"), + .next(200, "B"), + .completed(300), ]) } + } + @available(*, deprecated) + func testAssertEventsWithVariable() { + let test = RxExpect() let variable = Variable(0) test.input(variable, [ - next(300, 1), - next(400, 2), - next(500, 3), - ]) + .next(300, 1), + .next(400, 2), + .next(500, 3), + ]) test.assert(variable.asObservable()) { events in XCTAssertEqual(events, [ - next(0, 0), - next(300, 1), - next(400, 2), - next(500, 3), + .next(0, 0), + .next(300, 1), + .next(400, 2), + .next(500, 3), ]) } } func testAssertInfiniteObservable() { let test = RxExpect() - let timer = Observable.interval(100, scheduler: test.scheduler) + let timer = Observable.interval(.seconds(100), scheduler: test.scheduler) test.assert(timer, disposed: 400) { events in XCTAssertEqual(events, [ - next(100, 0), - next(200, 1), - next(300, 2), + .next(100, 0), + .next(200, 1), + .next(300, 2), ]) } test.assert(timer, disposed: 200) { events in XCTAssertEqual(events, [ - next(100, 0), + .next(100, 0), ]) } } @@ -71,14 +75,14 @@ final class RxExpectTests: XCTestCase { let subjects: [PublishSubject] = [.init(), .init(), .init()] let observable = Observable.merge(subjects).observeOn(MainScheduler.instance) test.input(subjects[0], [ - next(500, "A"), + .next(500, "A"), ]) test.input(subjects[1], [ - next(300, "B"), + .next(300, "B"), ]) test.input(subjects[2], [ - next(100, "C"), - next(600, "D"), + .next(100, "C"), + .next(600, "D"), ]) test.assert(observable) { events in XCTAssertEqual(events.elements, ["C", "B", "A", "D"]) diff --git a/Tests/RxExpectTests/UtilityTests.swift b/Tests/RxExpectTests/UtilityTests.swift index a018536..59d7e5d 100644 --- a/Tests/RxExpectTests/UtilityTests.swift +++ b/Tests/RxExpectTests/UtilityTests.swift @@ -8,81 +8,81 @@ private struct TestError: Error {} final class UtilityTests: XCTestCase { func testElements() { let events: [Recorded>] = [ - next(100, "A"), - next(200, "B"), - next(300, "C"), - completed(400), + .next(100, "A"), + .next(200, "B"), + .next(300, "C"), + .completed(400), ] XCTAssertEqual(events.elements, ["A", "B", "C"]) } func testError() { let events: [Recorded>] = [ - next(100, "A"), - next(200, "B"), - next(300, "C"), - error(400, TestError()), + .next(100, "A"), + .next(200, "B"), + .next(300, "C"), + .error(400, TestError()), ] XCTAssertTrue(events.error is TestError) } func testFilterNext() { let events: [Recorded>] = [ - next(100, "A"), - next(200, "B"), - next(300, "C"), - completed(400), + .next(100, "A"), + .next(200, "B"), + .next(300, "C"), + .completed(400), ] XCTAssertEqual(events.filter(.next), [ - next(100, "A"), - next(200, "B"), - next(300, "C"), + .next(100, "A"), + .next(200, "B"), + .next(300, "C"), ]) } func testFilterError() { let events: [Recorded>] = [ - next(100, "A"), - next(200, "B"), - next(300, "C"), - error(400, TestError()), + .next(100, "A"), + .next(200, "B"), + .next(300, "C"), + .error(400, TestError()), ] XCTAssertEqual(events.filter(.error), [ - error(400, TestError()), + .error(400, TestError()), ]) } func testFilterCompleted() { let events: [Recorded>] = [ - next(100, "A"), - next(200, "B"), - next(300, "C"), - completed(400), + .next(100, "A"), + .next(200, "B"), + .next(300, "C"), + .completed(400), ] XCTAssertEqual(events.filter(.completed), [ - completed(400), + .completed(400), ]) } func testFilterByTime() { let events: [Recorded>] = [ - next(100, "A"), - next(200, "B"), - next(300, "C"), - completed(400), + .next(100, "A"), + .next(200, "B"), + .next(300, "C"), + .completed(400), ] XCTAssertEqual(events.in(200..<400), [ - next(200, "B"), - next(300, "C"), + .next(200, "B"), + .next(300, "C"), ]) XCTAssertEqual(events.in(300...), [ - next(300, "C"), - completed(400), + .next(300, "C"), + .completed(400), ]) XCTAssertEqual(events.in(...300), [ - next(100, "A"), - next(200, "B"), - next(300, "C"), + .next(100, "A"), + .next(200, "B"), + .next(300, "C"), ]) } } From 52b5ebb66eabdf2bb03f430e37ee97b474c8b877 Mon Sep 17 00:00:00 2001 From: tokijh Date: Wed, 8 May 2019 11:06:18 +0900 Subject: [PATCH 2/6] Replace `AnyTestTime.next` from `next` --- Sources/RxExpect/AnyTestTime.swift | 8 +++++--- Sources/RxExpect/Deprecated.swift | 11 ++++++++++- Sources/RxExpect/RxExpect.swift | 2 +- Tests/RxExpectTests/AnyTestTimeTests.swift | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Sources/RxExpect/AnyTestTime.swift b/Sources/RxExpect/AnyTestTime.swift index 06503b4..f1f5ab1 100644 --- a/Sources/RxExpect/AnyTestTime.swift +++ b/Sources/RxExpect/AnyTestTime.swift @@ -1,8 +1,10 @@ import RxSwift import RxTest -let AnyTestTime = TestTime.min +public struct AnyTestTime { + static let time = TestTime.min -public func next(_ element: T) -> Recorded> { - return Recorded.next(AnyTestTime, element) + public static func next(_ element: T) -> Recorded> { + return Recorded.next(time, element) + } } diff --git a/Sources/RxExpect/Deprecated.swift b/Sources/RxExpect/Deprecated.swift index 20f26d4..e193983 100644 --- a/Sources/RxExpect/Deprecated.swift +++ b/Sources/RxExpect/Deprecated.swift @@ -1,11 +1,20 @@ import RxSwift import RxTest +// MARK: - AnyTestTime + +@available(*, deprecated, message: "next is deprecated. Please use `AnyTestTime.next` as a replacement.") +public func next(_ element: T) -> Recorded> { + return Recorded.next(AnyTestTime.time, element) +} + +// MARK: - RxExpect + extension RxExpect { @available(*, deprecated, message: "Variable is deprecated.") public func input(_ variable: Variable, _ events: [Recorded>], file: StaticString = #file, line: UInt = #line) { - Swift.assert(!events.contains { $0.time == AnyTestTime }, "Input events should have specific time.", file: file, line: line) + Swift.assert(!events.contains { $0.time == AnyTestTime.time }, "Input events should have specific time.", file: file, line: line) self.maximumInputTime = ([self.maximumInputTime] + events.map { $0.time }).max() ?? self.maximumInputTime self.deferredInputs.append { `self` in self.scheduler diff --git a/Sources/RxExpect/RxExpect.swift b/Sources/RxExpect/RxExpect.swift index 214eade..391a1cd 100644 --- a/Sources/RxExpect/RxExpect.swift +++ b/Sources/RxExpect/RxExpect.swift @@ -30,7 +30,7 @@ open class RxExpect { } public func input(_ observer: O, _ events: [Recorded>], file: StaticString = #file, line: UInt = #line) { - Swift.assert(!events.contains { $0.time == AnyTestTime }, "Input events should have specific time.", file: file, line: line) + Swift.assert(!events.contains { $0.time == AnyTestTime.time }, "Input events should have specific time.", file: file, line: line) self.maximumInputTime = ([self.maximumInputTime] + events.map { $0.time }).max() ?? self.maximumInputTime self.deferredInputs.append { `self` in self.scheduler diff --git a/Tests/RxExpectTests/AnyTestTimeTests.swift b/Tests/RxExpectTests/AnyTestTimeTests.swift index 68f22a6..db67bdd 100644 --- a/Tests/RxExpectTests/AnyTestTimeTests.swift +++ b/Tests/RxExpectTests/AnyTestTimeTests.swift @@ -3,7 +3,7 @@ import RxExpect final class AnyTestTimeTests: XCTestCase { func testAnyTestTime() { - let event = next("Hey") + let event = AnyTestTime.next("Hey") XCTAssertEqual(event.value.element, "Hey") XCTAssertLessThan(event.time, 0) } From 8a9ec390f2c046328086306ffeebcb41e132001f Mon Sep 17 00:00:00 2001 From: tokijh Date: Wed, 8 May 2019 11:12:24 +0900 Subject: [PATCH 3/6] Update README --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 91edb8c..5a47176 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ RxExpect ======== -![Swift](https://img.shields.io/badge/Swift-4.2-orange.svg) +![Swift](https://img.shields.io/badge/Swift-5.0-orange.svg) [![CocoaPods](http://img.shields.io/cocoapods/v/RxExpect.svg)](https://cocoapods.org/pods/RxExpect) [![Build Status](https://travis-ci.org/devxoul/RxExpect.svg?branch=master)](https://travis-ci.org/devxoul/RxExpect) [![Codecov](https://img.shields.io/codecov/c/github/devxoul/RxExpect.svg)](https://codecov.io/gh/devxoul/RxExpect/) @@ -20,19 +20,19 @@ func testMultiply() { // provide inputs test.input(value, [ - next(100, 1), - next(200, 2), - next(300, 3), - completed(400) + .next(100, 1), + .next(200, 2), + .next(300, 3), + .completed(400) ]) - + // test output test.assert(result) { events in XCTAssertEqual(events, [ - next(100, 2), - next(200, 4), - next(300, 6), - completed(400) + .next(100, 2), + .next(200, 4), + .next(300, 6), + .completed(400) ]) } } @@ -57,7 +57,7 @@ final class ArticleDetailViewModelTests: XCTestCase { // providing an user input: user tapped like button test.input(viewModel.likeButtonDidTap, [ - next(100, Void()), + .next(100, Void()), ]) // test output: like button become selected @@ -73,7 +73,7 @@ final class ArticleDetailViewModelTests: XCTestCase { // providing an user input: user tapped like button test.input(viewModel.likeButtonDidTap, [ - next(100, Void()), + .next(100, Void()), ]) // test output: like button become selected From 48d6005c4df0bff8212725ea051d93e88b102796 Mon Sep 17 00:00:00 2001 From: tokijh Date: Wed, 8 May 2019 11:14:09 +0900 Subject: [PATCH 4/6] Update dependency versions --- .swift-version | 2 +- Cartfile | 2 +- RxExpect.podspec | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.swift-version b/.swift-version index bf77d54..819e07a 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.2 +5.0 diff --git a/Cartfile b/Cartfile index c5bf2f9..c6cc795 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1 @@ -github "ReactiveX/RxSwift" >= 3.4 +github "ReactiveX/RxSwift" >= 5.0 diff --git a/RxExpect.podspec b/RxExpect.podspec index 7641c3e..3993aa6 100644 --- a/RxExpect.podspec +++ b/RxExpect.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "RxExpect" - s.version = "1.2.0" + s.version = "1.3.0" s.summary = "The RxSwift testing framework" s.homepage = "https://github.com/devxoul/RxExpect" s.license = { :type => "MIT", :file => "LICENSE" } @@ -14,8 +14,8 @@ Pod::Spec.new do |s| s.ios.deployment_target = "8.0" s.osx.deployment_target = "10.10" s.tvos.deployment_target = "9.0" - - s.dependency "RxSwift", ">= 4.0.0" - s.dependency "RxCocoa", ">= 4.0.0" - s.dependency "RxTest", ">= 4.0.0" + + s.dependency "RxSwift", ">= 5.0.0" + s.dependency "RxCocoa", ">= 5.0.0" + s.dependency "RxTest", ">= 5.0.0" end From 0512889980221449cfd3908901462e8e2c51d62d Mon Sep 17 00:00:00 2001 From: tokijh Date: Wed, 8 May 2019 11:39:34 +0900 Subject: [PATCH 5/6] Update xcode version on travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 210a8fa..ca386b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -osx_image: xcode10 +osx_image: xcode10.2 language: objective-c sudo: required env: From cb0da8a16912c9971fbd0279b47dee2131079047 Mon Sep 17 00:00:00 2001 From: tokijh Date: Wed, 8 May 2019 11:54:00 +0900 Subject: [PATCH 6/6] Update travis --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index ca386b1..17e0e4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,13 +5,13 @@ env: global: - PROJECT="RxExpect.xcodeproj" - SCHEME="RxExpect-Package" - - IOS_SDK="iphonesimulator12.0" + - IOS_SDK="iphonesimulator" - MACOS_SDK="macosx10.14" - - TVOS_SDK="appletvsimulator12.0" + - TVOS_SDK="appletvsimulator" matrix: - - SDK="$IOS_SDK" DESTINATION="platform=iOS Simulator,name=iPhone 8,OS=12.0" + - SDK="$IOS_SDK" DESTINATION="platform=iOS Simulator,name=iPhone 8,OS=12.2" - SDK="$MACOS_SDK" DESTINATION="arch=x86_64" - - SDK="$TVOS_SDK" DESTINATION="OS=12.0,name=Apple TV 4K" + - SDK="$TVOS_SDK" DESTINATION="OS=12.2,name=Apple TV 4K" install: - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)"