 }
 
 
-// MARK: - AssertEqual
-
-extension RxExpectation {
-
-    private func _assertEqual<O: ObservableConvertibleType, E where E == O.E>(
-                              source: O,
-                              _ expectedEvents: [Recorded<Event<E>>],
-                              _ recordedEventFilter: Recorded<Event<E>> -> Bool,
-                              _ predicate: ((Recorded<Event<E>>, Recorded<Event<E>>) -> Bool),
-                              file: StaticString = #file,
-                              line: UInt = #line) {
+// MARK: - Assert
+
+extension RxExpectation {
+
+    private func _assert<O: ObservableConvertibleType, E where E == O.E>(
+                         source: O,
+                         expectedEvents: [Recorded<Event<E>>],
+                         recordedEventFilter: Recorded<Event<E>> -> Bool,
+                         condition: ((Recorded<Event<E>>, Recorded<Event<E>>) -> Bool),
+                         file: StaticString = #file,
+                         line: UInt = #line) {
         guard let testCase = self._testCase else { return }
         let recorder = self.scheduler.createObserver(E)
         let disposeBag = DisposeBag()

        }
    }

    public func assertEqual<O: ObservableConvertibleType, E where E == O.E>(
                            source: O,
                            _ expectedEvents: [Recorded<Event<E>>],
                            _ predicate: ((Recorded<Event<E>>, Recorded<Event<E>>) -> Bool),
                            file: StaticString = #file,
                            line: UInt = #line) {
        let recordedEventFilter: Recorded<Event<E>> -> Bool = { _ in true }
        self._assertEqual(source, expectedEvents, recordedEventFilter, predicate, file: file, line: line)
    }

    public func assertEqualNext<O: ObservableConvertibleType, E where E == O.E>(
                                source: O,
                                _ expectedEvents: [Recorded<Event<E>>],
                                _ predicate: ((Recorded<Event<E>>, Recorded<Event<E>>) -> Bool),
                                file: StaticString = #file,
                                line: UInt = #line) {
        let recordedEventFilter: Recorded<Event<E>> -> Bool = { event in
            if case .Next = event.value {
                return true
            }
            return false
        }
        self._assertEqual(source, expectedEvents, recordedEventFilter, predicate, file: file, line: line)
    }

}


// MARK: - AssertEqual (Equatable)

extension RxExpectation {

    public func assertEqual<O: ObservableConvertibleType, E: Equatable where E == O.E>(
                            source: O,
                            _ expectedEvents: [Recorded<Event<E>>],
                            file: StaticString = #file,
                            line: UInt = #line) {
        let predicate: (Recorded<Event<E>>, Recorded<Event<E>>) -> Bool = { lhs, rhs in
            return lhs.time == AnyTestTime || rhs.time == AnyTestTime || lhs == rhs
        }
        self.assertEqual(source, expectedEvents, predicate, file: file, line: line)
    }

    public func assertEqualNext<O: ObservableConvertibleType, E: Equatable where E == O.E>(
                                source: O,
                                _ expectedEvents: [Recorded<Event<E>>],
                                file: StaticString = #file,
                                line: UInt = #line) {
        let predicate: (Recorded<Event<E>>, Recorded<Event<E>>) -> Bool = { lhs, rhs in
            return lhs.time == AnyTestTime || rhs.time == AnyTestTime || lhs == rhs
        }
        self.assertEqualNext(source, expectedEvents, predicate, file: file, line: line)
    }

}


// MARK: - AssertEqual (Void)

extension RxExpectation {

    public func assertEqual<O: ObservableConvertibleType where O.E == Void>(
                            source: O,
                            _ expectedEvents: [Recorded<Event<Void>>],
                            file: StaticString = #file,
                            line: UInt = #line) {
        let predicate: (Recorded<Event<Void>>, Recorded<Event<Void>>) -> Bool = { lhs, rhs in
            return lhs.time == AnyTestTime || rhs.time == AnyTestTime || lhs.time == rhs.time
        }
        self.assertEqual(source, expectedEvents, predicate, file: file, line: line)
    }

    public func assertEqualNext<O: ObservableConvertibleType where O.E == Void>(
                                source: O,
                                _ expectedEvents: [Recorded<Event<Void>>],
                                file: StaticString = #file,
                                line: UInt = #line) {
        let predicate: (Recorded<Event<Void>>, Recorded<Event<Void>>) -> Bool = { lhs, rhs in
            return lhs.time == AnyTestTime || rhs.time == AnyTestTime || lhs.time == rhs.time
        }
        self.assertEqualNext(source, expectedEvents, predicate, file: file, line: line)
    }

}


// MARK: - AssertEqual with Element

extension RxExpectation {

    public func assertEqual<O: ObservableConvertibleType, E where E == O.E>(
                            source: O,
                            _ expectedElements: [E],
                            _ predicate: ((E, E) -> Bool),
                            file: StaticString = #file,
                            line: UInt = #line) {
        let events = expectedElements.map { Recorded(time: 0, event: Event.Next($0)) }
        let eventPredicate: (Recorded<Event<E>>, Recorded<Event<E>>) -> Bool = { lhs, rhs in
            guard let leftElement = lhs.value.element, rightElement = rhs.value.element else { return false }
            return predicate(leftElement, rightElement)
        }
        self.assertEqual(source, events, eventPredicate, file: file, line: line)
    }

    public func assertEqualNext<O: ObservableConvertibleType, E where E == O.E>(
                                source: O,
                                _ expectedElements: [E],
                                _ predicate: ((E, E) -> Bool),
                                file: StaticString = #file,
                                line: UInt = #line) {
        let events = expectedElements.map { Recorded(time: 0, event: Event.Next($0)) }
        let eventPredicate: (Recorded<Event<E>>, Recorded<Event<E>>) -> Bool = { lhs, rhs in
            guard let leftElement = lhs.value.element, rightElement = rhs.value.element else { return false }
            return predicate(leftElement, rightElement)
        }
        self.assertEqualNext(source, events, eventPredicate, file: file, line: line)
    }

}


// MARK: - AssertEqual with Element (Equtable)

extension RxExpectation {

    public func assertEqual<O: ObservableConvertibleType, E: Equatable where E == O.E>(
                            source: O,
                            _ expectedElements: [E],
                            file: StaticString = #file,
                            line: UInt = #line) {
        let events = expectedElements.map { Recorded(time: 0, event: Event.Next($0)) }
        self.assertEqual(source, events, file: file, line: line)
    }

    public func assertEqualNext<O: ObservableConvertibleType, E: Equatable where E == O.E>(
                                source: O,
                                _ expectedElements: [E],
                                file: StaticString = #file,
                                line: UInt = #line) {
        let events = expectedElements.map { Recorded(time: 0, event: Event.Next($0)) }
        self.assertEqualNext(source, events, file: file, line: line)
    }

}


let AnyTestTime = TestTime.min

public func next<T>(element: T) -> Recorded<Event<T>> {
    return next(AnyTestTime, element)
}

            XCTAssertEqual(error, nil, file: file, line: line)
            let recordedEvents = recorder.events.filter(recordedEventFilter)
            let isCountEqual = expectedEvents.count == recordedEvents.count
            let isValueEqual = !zip(expectedEvents, recordedEvents).lazy.contains { !condition($0, $1) }
            let isSucceeded = isCountEqual && isValueEqual

            let expectedEventsDescription = String(expectedEvents)
                .stringByReplacingOccurrencesOfString(String(AnyTestTime), withString: "any")
            let message = "\(self._description ?? "")\n" +
