diff --git a/Sources/Nimble/Matchers/ElementsEqual.swift b/Sources/Nimble/Matchers/ElementsEqual.swift index 94b772882..d098eb057 100644 --- a/Sources/Nimble/Matchers/ElementsEqual.swift +++ b/Sources/Nimble/Matchers/ElementsEqual.swift @@ -1,8 +1,10 @@ -/// A Nimble matcher that succeeds when the actual sequence contain the same elements in the same order to the exepected sequence. +/// A Nimble matcher that succeeds when the actual sequence and the exepected sequence contain the same elements in +/// the same order. +/// +/// This is a matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2854213-elementsequal public func elementsEqual(_ expectedValue: Seq2?) -> Predicate where Seq1.Element: Equatable, Seq1.Element == Seq2.Element { //swiftlint:disable:this opening_brace - // A matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2949668-elementsequal return Predicate.define("elementsEqual <\(stringify(expectedValue))>") { (actualExpression, msg) in let actualValue = try actualExpression.evaluate() switch (expectedValue, actualValue) { @@ -16,3 +18,25 @@ public func elementsEqual(_ expectedValue: Seq2? } } } + +/// A Nimble matcher that succeeds when the actual sequence and the exepected sequence contain equivalent elements in +/// the same order, using the given predicate as the equivalence test. +/// +/// This is a matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2949668-elementsequal +public func elementsEqual( + _ expectedValue: Seq2?, + by areEquivalent: @escaping (Seq1.Element, Seq2.Element) -> Bool +) -> Predicate { + return Predicate.define("elementsEqual <\(stringify(expectedValue))>") { (actualExpression, msg) in + let actualValue = try actualExpression.evaluate() + switch (expectedValue, actualValue) { + case (nil, _?): + return PredicateResult(status: .fail, message: msg.appendedBeNilHint()) + case (nil, nil), (_, nil): + return PredicateResult(status: .fail, message: msg) + case (let expected?, let actual?): + let matches = actual.elementsEqual(expected, by: areEquivalent) + return PredicateResult(bool: matches, message: msg) + } + } +} diff --git a/Tests/NimbleTests/Matchers/ElementsEqualTest.swift b/Tests/NimbleTests/Matchers/ElementsEqualTest.swift index 15b02d469..39dd1f467 100644 --- a/Tests/NimbleTests/Matchers/ElementsEqualTest.swift +++ b/Tests/NimbleTests/Matchers/ElementsEqualTest.swift @@ -24,9 +24,33 @@ final class ElementsEqualTest: XCTestCase { expect(sequence1).to(elementsEqual([1, 2, 3])) } + func testSequenceElementsEqualityUsingPredicateClosure() { + failsWithErrorMessageForNil("expected to elementsEqual , got ") { + expect(nil as [Int]?).to(elementsEqual(nil as [Int]?, by: { $0 == $1 })) + } + let sequence = [1, 2] + failsWithErrorMessageForNil("expected to elementsEqual <[1, 2]>, got ") { + expect(nil as [Int]?).to(elementsEqual(sequence, by: { $0 == $1 })) + } + + failsWithErrorMessageForNil("expected to elementsEqual , got <[1, 2]>") { + expect(sequence).to(elementsEqual(nil as [Int]?, by: { $0 == $1 })) + } + + let sequence1 = [1, 2, 3] + let sequence2 = [1, 2, 3, 4, 5] + expect(sequence1).toNot(elementsEqual(sequence2, by: { $0 == $1 })) + expect(sequence1).toNot(elementsEqual([3, 2, 1], by: { $0 == $1 })) + expect(sequence1).to(elementsEqual([1, 2, 3], by: { $0 == $1 })) + } + func testElementsEqualDifferentSequenceTypes() { expect(1...3).to(elementsEqual([1, 2, 3])) expect(1...3).toNot(elementsEqual([1, 2, 3, 4, 5])) expect(1...3).toNot(elementsEqual([3, 2, 1])) + + expect(1...3).to(elementsEqual([1, 2, 3], by: { $0 == $1 })) + expect(1...3).toNot(elementsEqual([1, 2, 3, 4, 5], by: { $0 == $1 })) + expect(1...3).toNot(elementsEqual([3, 2, 1], by: { $0 == $1 })) } } diff --git a/Tests/NimbleTests/XCTestManifests.swift b/Tests/NimbleTests/XCTestManifests.swift index 3d1b066c5..dc4a74aaf 100644 --- a/Tests/NimbleTests/XCTestManifests.swift +++ b/Tests/NimbleTests/XCTestManifests.swift @@ -283,6 +283,7 @@ extension ElementsEqualTest { static let __allTests__ElementsEqualTest = [ ("testElementsEqualDifferentSequenceTypes", testElementsEqualDifferentSequenceTypes), ("testSequenceElementsEquality", testSequenceElementsEquality), + ("testSequenceElementsEqualityUsingPredicateClosure", testSequenceElementsEqualityUsingPredicateClosure), ] }