Skip to content

Commit dcf7d9a

Browse files
authored
Merge pull request #880 from Quick/tuple-equal
Add support for tuples of up to 6 elements to `equal` matcher, as with the standard library
2 parents 2d4c1ef + 562493f commit dcf7d9a

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
@@ -389,6 +389,9 @@
389389
CDD80B831F2030790002CD65 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; };
390390
CDD80B841F20307A0002CD65 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; };
391391
CDD80B851F20307B0002CD65 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; };
392+
CDF5C57B2647B89B0036532C /* Equal+Tuple.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF5C57A2647B89B0036532C /* Equal+Tuple.swift */; };
393+
CDF5C57C2647B89B0036532C /* Equal+Tuple.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF5C57A2647B89B0036532C /* Equal+Tuple.swift */; };
394+
CDF5C57D2647B89B0036532C /* Equal+Tuple.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF5C57A2647B89B0036532C /* Equal+Tuple.swift */; };
392395
CDFB6A231F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */; };
393396
CDFB6A241F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */; };
394397
CDFB6A251F7E07C700AD8CC7 /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */; };
@@ -625,6 +628,7 @@
625628
CD3D9A78232647BC00802581 /* CwlCatchBadInstructionPosix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstructionPosix.swift; sourceTree = "<group>"; };
626629
CDBC39B82462EA7D00069677 /* PredicateTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PredicateTest.swift; sourceTree = "<group>"; };
627630
CDC157902511957100EAA480 /* DSLTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DSLTest.swift; sourceTree = "<group>"; };
631+
CDF5C57A2647B89B0036532C /* Equal+Tuple.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Equal+Tuple.swift"; sourceTree = "<group>"; };
628632
CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchException.swift; sourceTree = "<group>"; };
629633
CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlCatchException.m; sourceTree = "<group>"; };
630634
CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlCatchException.h; sourceTree = "<group>"; };
@@ -876,6 +880,7 @@
876880
B20058C020E92C7500C1264D /* ElementsEqual.swift */,
877881
1FD8CD1B1968AB07008ED995 /* EndWith.swift */,
878882
1FD8CD1C1968AB07008ED995 /* Equal.swift */,
883+
CDF5C57A2647B89B0036532C /* Equal+Tuple.swift */,
879884
472FD1341B9E085700C7B8DA /* HaveCount.swift */,
880885
DDB4D5EC19FE43C200E9D9FE /* Match.swift */,
881886
1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */,
@@ -1350,6 +1355,7 @@
13501355
29EA59661B551EE6002D767E /* ThrowError.swift in Sources */,
13511356
62FB326323B78BF90047BED9 /* BeginWithPrefix.swift in Sources */,
13521357
1FD8CD5A1968AB07008ED995 /* Equal.swift in Sources */,
1358+
CDF5C57C2647B89B0036532C /* Equal+Tuple.swift in Sources */,
13531359
1FD8CD4C1968AB07008ED995 /* BeLessThan.swift in Sources */,
13541360
1FD8CD461968AB07008ED995 /* BeGreaterThan.swift in Sources */,
13551361
F8A1BE2F1CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */,
@@ -1468,6 +1474,7 @@
14681474
buildActionMask = 2147483647;
14691475
files = (
14701476
1F5DF1791BDCA0F500C3A531 /* BeCloseTo.swift in Sources */,
1477+
CDF5C57D2647B89B0036532C /* Equal+Tuple.swift in Sources */,
14711478
1F5DF16C1BDCA0F500C3A531 /* AssertionRecorder.swift in Sources */,
14721479
1F1871D71CA89EEF00A34BF2 /* NMBExceptionCapture.m in Sources */,
14731480
1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */,
@@ -1633,6 +1640,7 @@
16331640
29EA59671B551EE6002D767E /* ThrowError.swift in Sources */,
16341641
62FB326223B78BF90047BED9 /* BeginWithPrefix.swift in Sources */,
16351642
1FD8CD5B1968AB07008ED995 /* Equal.swift in Sources */,
1643+
CDF5C57B2647B89B0036532C /* Equal+Tuple.swift in Sources */,
16361644
1FD8CD4D1968AB07008ED995 /* BeLessThan.swift in Sources */,
16371645
1FD8CD471968AB07008ED995 /* BeGreaterThan.swift in Sources */,
16381646
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)