interaktor 0.2.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,249 @@
1
+ RSpec.describe Interaktor::Organizer do
2
+ it_behaves_like "lint", described_class
3
+
4
+ describe ".organize" do
5
+ let(:interaktor2) { instance_double(Interaktor) }
6
+ let(:interaktor3) { instance_double(Interaktor) }
7
+
8
+ it "sets interaktors given class arguments" do
9
+ organizer = FakeInteraktor.build_interaktor(type: described_class)
10
+
11
+ expect {
12
+ organizer.organize(interaktor2, interaktor3)
13
+ }.to change(organizer, :organized)
14
+ .from([])
15
+ .to([interaktor2, interaktor3])
16
+ end
17
+
18
+ it "sets interaktors given an array of classes" do
19
+ organizer = FakeInteraktor.build_interaktor(type: described_class)
20
+
21
+ expect {
22
+ organizer.organize([interaktor2, interaktor3])
23
+ }.to change(organizer, :organized)
24
+ .from([])
25
+ .to([interaktor2, interaktor3])
26
+ end
27
+
28
+ it "allows multiple organize calls" do
29
+ organizer = FakeInteraktor.build_interaktor(type: described_class)
30
+ interaktor4 = instance_double(Interaktor)
31
+
32
+ expect {
33
+ organizer.organize(interaktor2, interaktor3)
34
+ organizer.organize(interaktor4)
35
+ }.to change(organizer, :organized)
36
+ .from([])
37
+ .to([interaktor2, interaktor3, interaktor4])
38
+ end
39
+ end
40
+
41
+ describe ".organized" do
42
+ it "is empty by default" do
43
+ organizer = FakeInteraktor.build_interaktor(type: described_class)
44
+
45
+ expect(organizer.organized).to eq([])
46
+ end
47
+ end
48
+
49
+ describe "#call" do
50
+ it "calls each interaktor in order" do
51
+ organizer = FakeInteraktor.build_interaktor(type: described_class) do
52
+ input { required(:foo) }
53
+ success { required(:foo) }
54
+ end
55
+
56
+ interaktor1 = FakeInteraktor.build_interaktor("Interaktor1") do
57
+ input { required(:foo) }
58
+ success { required(:foo) }
59
+
60
+ def call
61
+ success!(foo: "bar")
62
+ end
63
+ end
64
+
65
+ interaktor2 = FakeInteraktor.build_interaktor("Interaktor2") do
66
+ input { required(:foo) }
67
+ success { required(:foo) }
68
+
69
+ def call
70
+ success!(foo: "baz")
71
+ end
72
+ end
73
+
74
+ interaktor3 = FakeInteraktor.build_interaktor("Interaktor3") do
75
+ input { required(:foo) }
76
+ success { required(:foo) }
77
+
78
+ def call
79
+ success!(foo: "wadus")
80
+ end
81
+ end
82
+
83
+ allow(organizer).to receive(:organized) {
84
+ [interaktor1, interaktor2, interaktor3]
85
+ }
86
+
87
+ expect(interaktor1).to receive(:call!).once.ordered.and_call_original
88
+ expect(interaktor2).to receive(:call!).once.ordered.and_call_original
89
+ expect(interaktor3).to receive(:call!).once.ordered.and_call_original
90
+
91
+ result = organizer.call(foo: "asdf")
92
+
93
+ expect(result.foo).to eq "wadus"
94
+ end
95
+
96
+ it "calls each interaktor in order and passes success attributes" do
97
+ organizer = FakeInteraktor.build_interaktor(type: described_class) { input { required(:foo) } }
98
+
99
+ interaktor1 = FakeInteraktor.build_interaktor("Interaktor1") do
100
+ input { required(:foo) }
101
+ success { required(:bar) }
102
+
103
+ def call
104
+ success!(bar: "baz")
105
+ end
106
+ end
107
+
108
+ interaktor2 = FakeInteraktor.build_interaktor("Interaktor1") do
109
+ input { required(:bar) }
110
+
111
+ def call
112
+ self.bar = "wadus"
113
+ end
114
+ end
115
+
116
+ allow(organizer).to receive(:organized) {
117
+ [interaktor1, interaktor2]
118
+ }
119
+
120
+ expect(interaktor1).to receive(:call!).once.ordered.and_call_original
121
+ expect(interaktor2).to receive(:call!).once.ordered.and_call_original
122
+
123
+ result = organizer.call(foo: "asdf")
124
+
125
+ expect(result.bar).to eq "wadus"
126
+ end
127
+
128
+ it "allows an interaktor to accept required attributes from previous success attributes" do
129
+ organizer = FakeInteraktor.build_interaktor(type: described_class)
130
+ interaktor1 = FakeInteraktor.build_interaktor("Interaktor1") do
131
+ success { required(:foo) }
132
+
133
+ def call
134
+ success!(foo: "whatever")
135
+ end
136
+ end
137
+ interaktor2 = FakeInteraktor.build_interaktor("Interaktor2") do
138
+ success { required(:bar) }
139
+
140
+ def call
141
+ success!(bar: "whatever")
142
+ end
143
+ end
144
+ interaktor3 = FakeInteraktor.build_interaktor("Interaktor3") do
145
+ input do
146
+ required(:foo)
147
+ required(:bar)
148
+ end
149
+ end
150
+
151
+ allow(organizer).to receive(:organized).and_return([interaktor1, interaktor2, interaktor3])
152
+
153
+ expect(interaktor1).to receive(:call!).once.ordered.and_call_original
154
+ expect(interaktor2).to receive(:call!).once.ordered.and_call_original
155
+ expect(interaktor3).to receive(:call!).once.ordered.and_call_original
156
+
157
+ organizer.call
158
+ end
159
+
160
+ it "allows an interaktor to accept required attributes from the original organizer" do
161
+ organizer = FakeInteraktor.build_interaktor(type: described_class) do
162
+ input do
163
+ required(:foo)
164
+ required(:bar)
165
+ end
166
+ end
167
+ interaktor1 = FakeInteraktor.build_interaktor("Interaktor1")
168
+ interaktor2 = FakeInteraktor.build_interaktor("Interaktor2") { input { required(:foo) } }
169
+ interaktor3 = FakeInteraktor.build_interaktor("Interaktor3") { input { required(:bar) } }
170
+
171
+ allow(organizer).to receive(:organized).and_return([interaktor1, interaktor2, interaktor3])
172
+
173
+ expect(interaktor1).to receive(:call!).once.ordered.and_call_original
174
+ expect(interaktor2).to receive(:call!).once.ordered.and_call_original
175
+ expect(interaktor3).to receive(:call!).once.ordered.and_call_original
176
+
177
+ organizer.call(foo: "whatever", bar: "baz")
178
+ end
179
+
180
+ it "allows an interaktor to accept required attributes from the original organizer AND previous success attributes" do
181
+ organizer = FakeInteraktor.build_interaktor(type: described_class) { input { required(:foo) } }
182
+ interaktor1 = FakeInteraktor.build_interaktor("Interaktor1") do
183
+ success { required(:bar) }
184
+
185
+ def call
186
+ success!(bar: "whatever")
187
+ end
188
+ end
189
+ interaktor2 = FakeInteraktor.build_interaktor("Interaktor2") do
190
+ success { required(:baz) }
191
+
192
+ def call
193
+ success!(baz: "whatever")
194
+ end
195
+ end
196
+ interaktor3 = FakeInteraktor.build_interaktor("Interaktor3") do
197
+ input do
198
+ required(:foo)
199
+ required(:bar)
200
+ required(:baz)
201
+ end
202
+ end
203
+
204
+ allow(organizer).to receive(:organized).and_return([interaktor1, interaktor2, interaktor3])
205
+
206
+ expect(interaktor1).to receive(:call!).once.ordered.and_call_original
207
+ expect(interaktor2).to receive(:call!).once.ordered.and_call_original
208
+ expect(interaktor3).to receive(:call!).once.ordered.and_call_original
209
+
210
+ organizer.call(foo: "whatever")
211
+ end
212
+
213
+ it "raises an exception if an interaktor requires an input attribute not provided by any previous interaktor" do
214
+ organizer = FakeInteraktor.build_interaktor(type: described_class)
215
+ interaktor1 = FakeInteraktor.build_interaktor("Interaktor1")
216
+ interaktor2 = FakeInteraktor.build_interaktor("Interaktor2") { input { required(:foo) } }
217
+
218
+ allow(organizer).to receive(:organized).and_return([interaktor1, interaktor2])
219
+
220
+ expect(interaktor1).not_to receive(:call!)
221
+
222
+ expect {
223
+ organizer.call
224
+ }.to raise_error(
225
+ an_instance_of(Interaktor::Error::OrganizerMissingPassedAttributeError)
226
+ .and(having_attributes(
227
+ attribute: :foo,
228
+ interaktor: interaktor2,
229
+ ))
230
+ )
231
+ end
232
+
233
+ it "raises an exception if the organizer's last interaktor does not include the organizer's success attributes" do
234
+ organizer = FakeInteraktor.build_interaktor(type: described_class) { success { required(:final) } }
235
+ interaktor1 = FakeInteraktor.build_interaktor("Interaktor1")
236
+
237
+ allow(organizer).to receive(:organized).and_return([interaktor1])
238
+
239
+ expect(interaktor1).not_to receive(:call!)
240
+
241
+ expect {
242
+ organizer.call
243
+ }.to raise_error(
244
+ an_instance_of(Interaktor::Error::OrganizerSuccessAttributeMissingError)
245
+ .and(having_attributes(attribute: :final, interaktor: interaktor1))
246
+ )
247
+ end
248
+ end
249
+ end
@@ -1,3 +1,3 @@
1
- describe Interaktor do
2
- include_examples "lint"
1
+ RSpec.describe Interaktor do
2
+ it_behaves_like "lint", described_class
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,23 @@
1
+ RSpec.configure do |config|
2
+ config.expect_with :rspec do |expectations|
3
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
4
+ end
5
+
6
+ config.mock_with :rspec do |mocks|
7
+ mocks.verify_partial_doubles = true
8
+ end
9
+
10
+ config.shared_context_metadata_behavior = :apply_to_host_groups
11
+ config.filter_run_when_matching :focus
12
+ config.example_status_persistence_file_path = "spec/examples.txt"
13
+ config.disable_monkey_patching!
14
+ config.order = :random
15
+
16
+ config.default_formatter = "doc" if config.files_to_run.one?
17
+
18
+ Kernel.srand config.seed
19
+ end
20
+
1
21
  require "simplecov"
2
22
  SimpleCov.start do
3
23
  enable_coverage :branch
@@ -0,0 +1,14 @@
1
+ class FakeInteraktor
2
+ # @param name [String]
3
+ def self.build_interaktor(name = nil, type: Interaktor, &block)
4
+ name ||= "MyTest#{type}"
5
+
6
+ result = Class.new.include(type)
7
+
8
+ result.class_eval(&block) if block
9
+ result.define_singleton_method(:inspect) { name.to_s }
10
+ result.define_singleton_method(:to_s) { inspect }
11
+
12
+ result
13
+ end
14
+ end