Skip to content

Commit 7ef3e4e

Browse files
authored
Merge pull request #884 from Quick/9.x-tuple-equal
[9.x] Add support for tuples of up to 6 elements to `equal` matcher, as with the standard library
2 parents 01e3b79 + 4a36072 commit 7ef3e4e

File tree

4 files changed

+157
-7
lines changed

4 files changed

+157
-7
lines changed

Nimble.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,9 @@
398398
CDD80B831F2030790002CD65 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; };
399399
CDD80B841F20307A0002CD65 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; };
400400
CDD80B851F20307B0002CD65 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; };
401+
CDF5C57B2647B89B0036532C /* Equal+Tuple.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF5C57A2647B89B0036532C /* Equal+Tuple.swift */; };
402+
CDF5C57C2647B89B0036532C /* Equal+Tuple.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF5C57A2647B89B0036532C /* Equal+Tuple.swift */; };
403+
CDF5C57D2647B89B0036532C /* Equal+Tuple.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF5C57A2647B89B0036532C /* Equal+Tuple.swift */; };
401404
CDFB6A231F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */; };
402405
CDFB6A241F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */; };
403406
CDFB6A251F7E07C700AD8CC7 /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */; };
@@ -637,6 +640,7 @@
637640
CD4C8F082464365300A7BDE0 /* SynchronousDeprecatedTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousDeprecatedTest.swift; sourceTree = "<group>"; };
638641
CDBC39B82462EA7D00069677 /* PredicateTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PredicateTest.swift; sourceTree = "<group>"; };
639642
CDC157902511957100EAA480 /* DSLTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DSLTest.swift; sourceTree = "<group>"; };
643+
CDF5C57A2647B89B0036532C /* Equal+Tuple.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Equal+Tuple.swift"; sourceTree = "<group>"; };
640644
CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchException.swift; sourceTree = "<group>"; };
641645
CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlCatchException.m; sourceTree = "<group>"; };
642646
CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlCatchException.h; sourceTree = "<group>"; };
@@ -890,6 +894,7 @@
890894
B20058C020E92C7500C1264D /* ElementsEqual.swift */,
891895
1FD8CD1B1968AB07008ED995 /* EndWith.swift */,
892896
1FD8CD1C1968AB07008ED995 /* Equal.swift */,
897+
CDF5C57A2647B89B0036532C /* Equal+Tuple.swift */,
893898
472FD1341B9E085700C7B8DA /* HaveCount.swift */,
894899
DDB4D5EC19FE43C200E9D9FE /* Match.swift */,
895900
1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */,
@@ -1365,6 +1370,7 @@
13651370
29EA59661B551EE6002D767E /* ThrowError.swift in Sources */,
13661371
62FB326323B78BF90047BED9 /* BeginWithPrefix.swift in Sources */,
13671372
1FD8CD5A1968AB07008ED995 /* Equal.swift in Sources */,
1373+
CDF5C57C2647B89B0036532C /* Equal+Tuple.swift in Sources */,
13681374
1FD8CD4C1968AB07008ED995 /* BeLessThan.swift in Sources */,
13691375
1F1871CC1CA89EDB00A34BF2 /* NMBObjCMatcher.swift in Sources */,
13701376
1FD8CD461968AB07008ED995 /* BeGreaterThan.swift in Sources */,
@@ -1486,6 +1492,7 @@
14861492
buildActionMask = 2147483647;
14871493
files = (
14881494
1F5DF1791BDCA0F500C3A531 /* BeCloseTo.swift in Sources */,
1495+
CDF5C57D2647B89B0036532C /* Equal+Tuple.swift in Sources */,
14891496
1F5DF16C1BDCA0F500C3A531 /* AssertionRecorder.swift in Sources */,
14901497
1F1871D71CA89EEF00A34BF2 /* NMBExceptionCapture.m in Sources */,
14911498
1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */,
@@ -1654,6 +1661,7 @@
16541661
29EA59671B551EE6002D767E /* ThrowError.swift in Sources */,
16551662
62FB326223B78BF90047BED9 /* BeginWithPrefix.swift in Sources */,
16561663
1FD8CD5B1968AB07008ED995 /* Equal.swift in Sources */,
1664+
CDF5C57B2647B89B0036532C /* Equal+Tuple.swift in Sources */,
16571665
1FD8CD4D1968AB07008ED995 /* BeLessThan.swift in Sources */,
16581666
1FD8CD471968AB07008ED995 /* BeGreaterThan.swift in Sources */,
16591667
F8A1BE301CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */,
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// swiftlint:disable large_tuple vertical_whitespace
2+
3+
// MARK: Tuple2
4+
5+
/// A Nimble matcher that succeeds when the actual tuple is equal to the expected tuple.
6+
/// Values can support equal by supporting the Equatable protocol.
7+
public func equal<T1: Equatable, T2: Equatable>(
8+
_ expectedValue: (T1, T2)?
9+
) -> Predicate<(T1, T2)> {
10+
equal(expectedValue, by: ==)
11+
}
12+
13+
public func ==<T1: Equatable, T2: Equatable>(
14+
lhs: Expectation<(T1, T2)>,
15+
rhs: (T1, T2)?
16+
) {
17+
lhs.to(equal(rhs))
18+
}
19+
20+
public func !=<T1: Equatable, T2: Equatable>(
21+
lhs: Expectation<(T1, T2)>,
22+
rhs: (T1, T2)?
23+
) {
24+
lhs.toNot(equal(rhs))
25+
}
26+
27+
28+
// MARK: Tuple3
29+
30+
/// A Nimble matcher that succeeds when the actual tuple is equal to the expected tuple.
31+
/// Values can support equal by supporting the Equatable protocol.
32+
public func equal<T1: Equatable, T2: Equatable, T3: Equatable>(
33+
_ expectedValue: (T1, T2, T3)?
34+
) -> Predicate<(T1, T2, T3)> {
35+
equal(expectedValue, by: ==)
36+
}
37+
38+
public func ==<T1: Equatable, T2: Equatable, T3: Equatable>(
39+
lhs: Expectation<(T1, T2, T3)>,
40+
rhs: (T1, T2, T3)?
41+
) {
42+
lhs.to(equal(rhs))
43+
}
44+
45+
public func !=<T1: Equatable, T2: Equatable, T3: Equatable>(
46+
lhs: Expectation<(T1, T2, T3)>,
47+
rhs: (T1, T2, T3)?
48+
) {
49+
lhs.toNot(equal(rhs))
50+
}
51+
52+
53+
// MARK: Tuple4
54+
55+
/// A Nimble matcher that succeeds when the actual tuple is equal to the expected tuple.
56+
/// Values can support equal by supporting the Equatable protocol.
57+
public func equal<T1: Equatable, T2: Equatable, T3: Equatable, T4: Equatable>(
58+
_ expectedValue: (T1, T2, T3, T4)?
59+
) -> Predicate<(T1, T2, T3, T4)> {
60+
equal(expectedValue, by: ==)
61+
}
62+
63+
public func ==<T1: Equatable, T2: Equatable, T3: Equatable, T4: Equatable>(
64+
lhs: Expectation<(T1, T2, T3, T4)>,
65+
rhs: (T1, T2, T3, T4)?
66+
) {
67+
lhs.to(equal(rhs))
68+
}
69+
70+
public func !=<T1: Equatable, T2: Equatable, T3: Equatable, T4: Equatable>(
71+
lhs: Expectation<(T1, T2, T3, T4)>,
72+
rhs: (T1, T2, T3, T4)?
73+
) {
74+
lhs.toNot(equal(rhs))
75+
}
76+
77+
78+
// MARK: Tuple5
79+
80+
/// A Nimble matcher that succeeds when the actual tuple is equal to the expected tuple.
81+
/// Values can support equal by supporting the Equatable protocol.
82+
public func equal<T1: Equatable, T2: Equatable, T3: Equatable, T4: Equatable, T5: Equatable>(
83+
_ expectedValue: (T1, T2, T3, T4, T5)?
84+
) -> Predicate<(T1, T2, T3, T4, T5)> {
85+
equal(expectedValue, by: ==)
86+
}
87+
88+
public func ==<T1: Equatable, T2: Equatable, T3: Equatable, T4: Equatable, T5: Equatable>(
89+
lhs: Expectation<(T1, T2, T3, T4, T5)>,
90+
rhs: (T1, T2, T3, T4, T5)?
91+
) {
92+
lhs.to(equal(rhs))
93+
}
94+
95+
public func !=<T1: Equatable, T2: Equatable, T3: Equatable, T4: Equatable, T5: Equatable>(
96+
lhs: Expectation<(T1, T2, T3, T4, T5)>,
97+
rhs: (T1, T2, T3, T4, T5)?
98+
) {
99+
lhs.toNot(equal(rhs))
100+
}
101+
102+
103+
// MARK: Tuple6
104+
105+
/// A Nimble matcher that succeeds when the actual tuple is equal to the expected tuple.
106+
/// Values can support equal by supporting the Equatable protocol.
107+
public func equal<T1: Equatable, T2: Equatable, T3: Equatable, T4: Equatable, T5: Equatable, T6: Equatable>(
108+
_ expectedValue: (T1, T2, T3, T4, T5, T6)?
109+
) -> Predicate<(T1, T2, T3, T4, T5, T6)> {
110+
equal(expectedValue, by: ==)
111+
}
112+
113+
public func ==<T1: Equatable, T2: Equatable, T3: Equatable, T4: Equatable, T5: Equatable, T6: Equatable>(
114+
lhs: Expectation<(T1, T2, T3, T4, T5, T6)>,
115+
rhs: (T1, T2, T3, T4, T5, T6)?
116+
) {
117+
lhs.to(equal(rhs))
118+
}
119+
120+
public func !=<T1: Equatable, T2: Equatable, T3: Equatable, T4: Equatable, T5: Equatable, T6: Equatable>(
121+
lhs: Expectation<(T1, T2, T3, T4, T5, T6)>,
122+
rhs: (T1, T2, T3, T4, T5, T6)?
123+
) {
124+
lhs.toNot(equal(rhs))
125+
}
126+
127+
// swiftlint:enable large_tuple vertical_whitespace

Sources/Nimble/Matchers/Equal.swift

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
1-
/// A Nimble matcher that succeeds when the actual value is equal to the expected value.
2-
/// Values can support equal by supporting the Equatable protocol.
3-
///
4-
/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles).
5-
public func equal<T: Equatable>(_ expectedValue: T?) -> Predicate<T> {
1+
internal func equal<T>(
2+
_ expectedValue: T?,
3+
by areEquivalent: @escaping (T, T) -> Bool
4+
) -> Predicate<T> {
65
return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in
76
let actualValue = try actualExpression.evaluate()
87
switch (expectedValue, actualValue) {
98
case (nil, _?):
109
return PredicateResult(status: .fail, message: msg.appendedBeNilHint())
11-
case (nil, nil), (_, nil):
10+
case (_, nil):
1211
return PredicateResult(status: .fail, message: msg)
1312
case (let expected?, let actual?):
14-
let matches = expected == actual
13+
let matches = areEquivalent(expected, actual)
1514
return PredicateResult(bool: matches, message: msg)
1615
}
1716
}
1817
}
1918

19+
/// A Nimble matcher that succeeds when the actual value is equal to the expected value.
20+
/// Values can support equal by supporting the Equatable protocol.
21+
///
22+
/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles).
23+
public func equal<T: Equatable>(_ expectedValue: T?) -> Predicate<T> {
24+
equal(expectedValue, by: ==)
25+
}
26+
2027
/// A Nimble matcher allowing comparison of collection with optional type
2128
public func equal<T: Equatable>(_ expectedValue: [T?]) -> Predicate<[T?]> {
2229
return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in

Tests/NimbleTests/Matchers/EqualTest.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,4 +246,12 @@ final class EqualTest: XCTestCase {
246246

247247
expect(result).to(equal(storyCount))
248248
}
249+
250+
func testTuple() {
251+
expect((1, "2")).to(equal((1, "2")))
252+
expect((1, "2", 3)).to(equal((1, "2", 3)))
253+
expect((1, "2", 3, four: "4")).to(equal((1, "2", 3, "4")))
254+
expect((1, "2", 3, four: "4", 5)).to(equal((1, "2", 3, "4", five: 5)))
255+
expect((1, "2", 3, four: "4", 5, "6")).to(equal((1, "2", 3, "4", five: 5, "6")))
256+
}
249257
}

0 commit comments

Comments
 (0)