Skip to content

Commit ab74ef0

Browse files
committed
Unit tests.
1 parent 415445c commit ab74ef0

File tree

2 files changed

+187
-2
lines changed

2 files changed

+187
-2
lines changed

Loop.xcodeproj/project.pbxproj

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
5BC88F9D246B1CDE00394C63 /* SignalProducer+Loop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC88F9B246B1CDE00394C63 /* SignalProducer+Loop.swift */; };
6969
5BC88F9E246B1CDE00394C63 /* SignalProducer+Loop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC88F9B246B1CDE00394C63 /* SignalProducer+Loop.swift */; };
7070
5BDEDA3B2473357A00A13013 /* EnvironmentLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F92132473250E00C1C90E /* EnvironmentLoop.swift */; };
71-
5BDEDA3C2473357A00A13013 /* EnvironmentLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F92132473250E00C1C90E /* EnvironmentLoop.swift */; };
7271
5BDEDA3D2473357B00A13013 /* EnvironmentLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F92132473250E00C1C90E /* EnvironmentLoop.swift */; };
7372
5BDEDA3E2473359C00A13013 /* EnvironmentValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F921B247325C300C1C90E /* EnvironmentValues.swift */; };
7473
5BDEDA3F2473359D00A13013 /* EnvironmentValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F921B247325C300C1C90E /* EnvironmentValues.swift */; };
@@ -99,6 +98,10 @@
9998
65F8C2972183725900924657 /* Loop.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 25CC87AE1F92855300A6EBFC /* Loop.framework */; };
10099
65F8C2CF218378F500924657 /* Loop.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65F8C26B218371A800924657 /* Loop.framework */; };
101100
65F8C2D0218378F500924657 /* Loop.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 65F8C26B218371A800924657 /* Loop.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
101+
9A01A42824BC78E200075A57 /* FeedbackVariantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A01A42724BC78E200075A57 /* FeedbackVariantTests.swift */; };
102+
9A01A42924BC78E200075A57 /* FeedbackVariantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A01A42724BC78E200075A57 /* FeedbackVariantTests.swift */; };
103+
9A01A42A24BC78E200075A57 /* FeedbackVariantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A01A42724BC78E200075A57 /* FeedbackVariantTests.swift */; };
104+
9A01A42B24BC7E2E00075A57 /* EnvironmentLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F92132473250E00C1C90E /* EnvironmentLoop.swift */; };
102105
9AD5D42D1F97375E00E6AE5A /* Property+System.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AD5D42C1F97375E00E6AE5A /* Property+System.swift */; };
103106
9AE181BB1F95A71B00A07551 /* Loop.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 25CC87AE1F92855300A6EBFC /* Loop.framework */; };
104107
9AE9563E2186341B005A8C69 /* ReactiveCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AE9563B21863415005A8C69 /* ReactiveCocoa.framework */; };
@@ -248,6 +251,7 @@
248251
65F8C27A218371AC00924657 /* Loop.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Loop.framework; sourceTree = BUILT_PRODUCTS_DIR; };
249252
65F8C28E2183723F00924657 /* LoopTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LoopTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
250253
65F8C2A22183725900924657 /* LoopTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LoopTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
254+
9A01A42724BC78E200075A57 /* FeedbackVariantTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbackVariantTests.swift; sourceTree = "<group>"; };
251255
9AD5D42C1F97375E00E6AE5A /* Property+System.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Property+System.swift"; sourceTree = "<group>"; };
252256
9AE181B61F95A71B00A07551 /* LoopTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LoopTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
253257
9AE181BA1F95A71B00A07551 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -520,6 +524,7 @@
520524
5898B6D01F97ADDD005EEAEC /* SystemTests.swift */,
521525
9AE181BA1F95A71B00A07551 /* Info.plist */,
522526
250B70DE23FC441300848429 /* FeedbackLoopSystemTests.swift */,
527+
9A01A42724BC78E200075A57 /* FeedbackVariantTests.swift */,
523528
);
524529
path = LoopTests;
525530
sourceTree = "<group>";
@@ -876,6 +881,7 @@
876881
5BC88F9D246B1CDE00394C63 /* SignalProducer+Loop.swift in Sources */,
877882
5BC88F93246B17B200394C63 /* Context.swift in Sources */,
878883
5BAB9751247FFBC10079B532 /* SwiftUIHotSwappableSubscription.swift in Sources */,
884+
9A01A42B24BC7E2E00075A57 /* EnvironmentLoop.swift in Sources */,
879885
585CD87C239E6A3E004BE9CC /* Reducer.swift in Sources */,
880886
65F8C262218371A800924657 /* Property+System.swift in Sources */,
881887
5BC88F89246AFC5900394C63 /* ReactiveSwift+EnqueueTo.swift in Sources */,
@@ -886,7 +892,6 @@
886892
5BC88F8F246B11DE00394C63 /* LoopBox.swift in Sources */,
887893
65761B2723CF20EF004D5506 /* Floodgate.swift in Sources */,
888894
5BC88F99246B191200394C63 /* Loop.swift in Sources */,
889-
5BDEDA3C2473357A00A13013 /* EnvironmentLoop.swift in Sources */,
890895
);
891896
runOnlyForDeploymentPostprocessing = 0;
892897
};
@@ -919,6 +924,7 @@
919924
isa = PBXSourcesBuildPhase;
920925
buildActionMask = 2147483647;
921926
files = (
927+
9A01A42924BC78E200075A57 /* FeedbackVariantTests.swift in Sources */,
922928
65F8C2802183723F00924657 /* SystemTests.swift in Sources */,
923929
250B70E023FC441300848429 /* FeedbackLoopSystemTests.swift in Sources */,
924930
);
@@ -928,6 +934,7 @@
928934
isa = PBXSourcesBuildPhase;
929935
buildActionMask = 2147483647;
930936
files = (
937+
9A01A42A24BC78E200075A57 /* FeedbackVariantTests.swift in Sources */,
931938
65F8C2942183725900924657 /* SystemTests.swift in Sources */,
932939
250B70E123FC441300848429 /* FeedbackLoopSystemTests.swift in Sources */,
933940
);
@@ -937,6 +944,7 @@
937944
isa = PBXSourcesBuildPhase;
938945
buildActionMask = 2147483647;
939946
files = (
947+
9A01A42824BC78E200075A57 /* FeedbackVariantTests.swift in Sources */,
940948
5898B6D11F97ADDD005EEAEC /* SystemTests.swift in Sources */,
941949
250B70DF23FC441300848429 /* FeedbackLoopSystemTests.swift in Sources */,
942950
);

LoopTests/FeedbackVariantTests.swift

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import XCTest
2+
import Nimble
3+
import ReactiveSwift
4+
@testable import Loop
5+
6+
class FeedbackVariantTests: XCTestCase {
7+
func test_whenBecomesTrue_positive_edge() {
8+
var receivedValues: [String] = []
9+
10+
let loop = Loop<String, String>(
11+
initial: "",
12+
reducer: { content, string in
13+
content.append(contentsOf: string)
14+
},
15+
feedbacks: [
16+
.whenBecomesTrue(
17+
{ $0.hasSuffix("_") },
18+
effects: { state -> SignalProducer<String, Never> in
19+
receivedValues.append(state)
20+
21+
return SignalProducer(value: "feedback_")
22+
}
23+
)
24+
]
25+
)
26+
27+
expect(loop.box._current) == ""
28+
29+
loop.send("hello")
30+
expect(loop.box._current) == "hello"
31+
expect(receivedValues.last).to(beNil())
32+
33+
// This should trigger a positive edge in `whenBecomesTrue`.
34+
loop.send("_")
35+
expect(loop.box._current) == "hello_feedback_"
36+
expect(receivedValues.last) == "hello_"
37+
38+
// The predicate stays `true`, so no transition should occur.
39+
loop.send("_")
40+
expect(loop.box._current) == "hello_feedback__"
41+
expect(receivedValues.last) == "hello_"
42+
43+
// This should lead to a negative edge.
44+
loop.send("world")
45+
expect(loop.box._current) == "hello_feedback__world"
46+
expect(receivedValues.last) == "hello_"
47+
48+
// This should trigger a positive edge again in `whenBecomesTrue`.
49+
loop.send("_")
50+
expect(loop.box._current) == "hello_feedback__world_feedback_"
51+
expect(receivedValues.last) == "hello_feedback__world_"
52+
}
53+
54+
func test_whenBecomesTrue_negative_edge() {
55+
var hasStarted = false
56+
var hasCancelled = false
57+
58+
let loop = Loop<String, String>(
59+
initial: "",
60+
reducer: { content, string in
61+
content.append(contentsOf: string)
62+
},
63+
feedbacks: [
64+
.whenBecomesTrue(
65+
{ $0.hasSuffix("_") },
66+
effects: { _ in
67+
SignalProducer.never
68+
.on(started: { hasStarted = true })
69+
.on(disposed: { hasCancelled = true })
70+
}
71+
)
72+
]
73+
)
74+
75+
expect(loop.box._current) == ""
76+
expect(hasStarted) == false
77+
78+
// This should trigger a positive edge in `whenBecomesTrue`.
79+
loop.send("_")
80+
expect(hasStarted) == true
81+
expect(hasCancelled) == false
82+
83+
loop.send("_")
84+
expect(hasCancelled) == false
85+
86+
loop.send("_")
87+
expect(hasCancelled) == false
88+
89+
// This should lead to a negative edge, which in turn should cancel the effect.
90+
loop.send("word")
91+
expect(hasCancelled) == true
92+
}
93+
94+
func test_firstValueAfterNil_positive_edge() {
95+
var receivedValues: [String] = []
96+
97+
let loop = Loop<String, String>(
98+
initial: "",
99+
reducer: { content, string in
100+
content = string
101+
},
102+
feedbacks: [
103+
.firstValueAfterNil(
104+
{ $0.hasPrefix("hello") ? $0 : nil },
105+
effects: { state -> SignalProducer<String, Never> in
106+
receivedValues.append(state)
107+
108+
return SignalProducer(value: "\(String(repeating: state, count: 2))")
109+
}
110+
)
111+
]
112+
)
113+
114+
expect(loop.box._current) == ""
115+
expect(receivedValues.last).to(beNil())
116+
117+
// This should trigger a positive edge in `firstValueAfterNil`.
118+
loop.send("hello#")
119+
expect(loop.box._current) == "hello#hello#"
120+
expect(receivedValues.last) == "hello#"
121+
122+
// The transform output stays non-nil, so no transition should occur.
123+
loop.send("hello_world")
124+
expect(loop.box._current) == "hello_world"
125+
expect(receivedValues.last) == "hello#"
126+
127+
// This should lead to a negative edge.
128+
loop.send("goodbye")
129+
expect(loop.box._current) == "goodbye"
130+
expect(receivedValues.last) == "hello#"
131+
132+
// This should trigger a positive edge again in `firstValueAfterNil`.
133+
loop.send("hello_it_is_me#")
134+
expect(loop.box._current) == "hello_it_is_me#hello_it_is_me#"
135+
expect(receivedValues.last) == "hello_it_is_me#"
136+
}
137+
138+
func test_firstValueAfterNil_negative_edge() {
139+
var hasStarted = false
140+
var hasCancelled = false
141+
142+
let loop = Loop<String, String>(
143+
initial: "",
144+
reducer: { content, string in
145+
content = string
146+
},
147+
feedbacks: [
148+
.firstValueAfterNil(
149+
{ $0.hasPrefix("hello") ? $0 : nil },
150+
effects: { _ in
151+
SignalProducer.never
152+
.on(started: { hasStarted = true })
153+
.on(disposed: { hasCancelled = true })
154+
}
155+
)
156+
]
157+
)
158+
159+
expect(loop.box._current) == ""
160+
expect(hasStarted) == false
161+
162+
// This should trigger a positive edge in `whenBecomesTrue`.
163+
loop.send("hello1")
164+
expect(hasStarted) == true
165+
expect(hasCancelled) == false
166+
167+
loop.send("hello2")
168+
expect(hasCancelled) == false
169+
170+
loop.send("hello3")
171+
expect(hasCancelled) == false
172+
173+
// This should lead to a negative edge, which in turn should cancel the effect.
174+
loop.send("world")
175+
expect(hasCancelled) == true
176+
}
177+
}

0 commit comments

Comments
 (0)