class-action 0.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +33 -16
- data/.travis.yml +6 -0
- data/CHANGELOG.md +31 -0
- data/Gemfile.lock +62 -0
- data/README.md +42 -11
- data/class-action.gemspec +1 -0
- data/lib/class-action/rspec.rb +2 -0
- data/lib/class_action/action.rb +113 -63
- data/lib/class_action/rspec/class_action_example_group.rb +57 -0
- data/lib/class_action/rspec/have_class_action_matcher.rb +67 -0
- data/lib/class_action/rspec/respond_to_format_matcher.rb +72 -0
- data/lib/class_action/rspec/respond_with_matcher.rb +60 -0
- data/lib/class_action/rspec.rb +3 -0
- data/lib/class_action/version.rb +1 -1
- data/lib/class_action.rb +12 -8
- data/spec/class_action/action_spec.rb +202 -29
- data/spec/class_action/rspec/have_class_action_matcher_spec.rb +69 -0
- data/spec/class_action/rspec/respond_to_format_matcher_spec.rb +76 -0
- data/spec/class_action/rspec/respond_with_matcher_spec.rb +84 -0
- data/spec/class_action_spec.rb +8 -1
- data/spec/spec_helper.rb +6 -0
- metadata +32 -7
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/ClassAction.sublime-project +0 -10
- data/ClassAction.sublime-workspace +0 -1873
@@ -0,0 +1,72 @@
|
|
1
|
+
module ClassAction
|
2
|
+
module RSpec
|
3
|
+
|
4
|
+
class RespondToFormatMatcher
|
5
|
+
|
6
|
+
def initialize(format)
|
7
|
+
@format = format.to_sym
|
8
|
+
end
|
9
|
+
|
10
|
+
def on(condition)
|
11
|
+
@condition = condition
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def matches?(action, &block)
|
16
|
+
@action = action
|
17
|
+
|
18
|
+
if action.class._responders.key?([@format, @condition])
|
19
|
+
|
20
|
+
if block
|
21
|
+
# Response defined, we return true but we need to also execute the block,
|
22
|
+
# as it might contain additional checks. First run the action's response
|
23
|
+
# block, for this.
|
24
|
+
respond_block = action.class._responders[ [@format, @condition] ]
|
25
|
+
action.instance_exec &respond_block if respond_block
|
26
|
+
action.send :copy_assigns_to_controller
|
27
|
+
block.call
|
28
|
+
end
|
29
|
+
|
30
|
+
true
|
31
|
+
else
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def description
|
37
|
+
if @condition
|
38
|
+
"respond to format :#{@format} on :#{@condition}"
|
39
|
+
else
|
40
|
+
"respond to format :#{@format}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def failure_message_for_should
|
45
|
+
if @condition
|
46
|
+
"expected action of class #{@action.class} to respond to format :#{@format} on :#{@condition}"
|
47
|
+
else
|
48
|
+
"expected action of class #{@action.class} to respond to format :#{@format}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def failure_message_for_should_not
|
53
|
+
if @condition
|
54
|
+
"expected action of class #{@action.class} not to respond to format :#{@format} on :#{@condition}"
|
55
|
+
else
|
56
|
+
"expected action of class #{@action.class} not to respond to format :#{@format}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
RSpec::Matchers.module_eval do
|
66
|
+
def respond_to_format(format)
|
67
|
+
ClassAction::RSpec::RespondToFormatMatcher.new(format)
|
68
|
+
end
|
69
|
+
def respond_to_any_format
|
70
|
+
ClassAction::RSpec::RespondToFormatMatcher.new(:any)
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module ClassAction
|
2
|
+
module RSpec
|
3
|
+
|
4
|
+
class RespondWithMatcher
|
5
|
+
|
6
|
+
def initialize(expected)
|
7
|
+
@expected = expected.to_sym
|
8
|
+
end
|
9
|
+
|
10
|
+
def on(condition)
|
11
|
+
@condition = condition
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def matches?(action)
|
16
|
+
@action = action
|
17
|
+
@actual = action.class._responses[@condition].try(:to_sym)
|
18
|
+
@actual == @expected
|
19
|
+
end
|
20
|
+
|
21
|
+
def description
|
22
|
+
if @condition
|
23
|
+
"respond with method :#{@expected} on :#{@condition}"
|
24
|
+
else
|
25
|
+
"respond with method :#{@expected}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def failure_message_for_should
|
30
|
+
suffix = if @actual
|
31
|
+
", but it responds with :#{@actual}"
|
32
|
+
else
|
33
|
+
", but it has no response method"
|
34
|
+
end
|
35
|
+
|
36
|
+
if @condition
|
37
|
+
"expected action of class #{@action.class} to respond with :#{@expected} on :#{@condition}#{suffix}"
|
38
|
+
else
|
39
|
+
"expected action of class #{@action.class} to respond with :#{@expected}#{suffix}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def failure_message_for_should_not
|
44
|
+
if @condition
|
45
|
+
"expected action of class #{@action.class} not to respond with :#{@expected} on :#{@condition}"
|
46
|
+
else
|
47
|
+
"expected action of class #{@action.class} not to respond with :#{@expected}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
RSpec::Matchers.module_eval do
|
57
|
+
def respond_with(expected)
|
58
|
+
ClassAction::RSpec::RespondWithMatcher.new(expected)
|
59
|
+
end
|
60
|
+
end
|
data/lib/class_action/version.rb
CHANGED
data/lib/class_action.rb
CHANGED
@@ -28,8 +28,13 @@ module ClassAction
|
|
28
28
|
raise ArgumentError, "ClassAction does not support anonymous classes" if action_class.name.nil?
|
29
29
|
|
30
30
|
class_eval <<-RUBY, __FILE__, __LINE__+1
|
31
|
+
def _#{action}_action_class
|
32
|
+
@_class_action ||= #{action_class.name}.new self
|
33
|
+
end
|
34
|
+
private :_#{action}_action_class
|
35
|
+
|
31
36
|
def #{action}
|
32
|
-
|
37
|
+
_#{action}_action_class._execute
|
33
38
|
end
|
34
39
|
RUBY
|
35
40
|
|
@@ -43,18 +48,18 @@ module ClassAction
|
|
43
48
|
# mimes_for_respond_to hash.
|
44
49
|
def inject_class_action_mimes(action, klass)
|
45
50
|
# If no responders or a default responder is given, we don't do anything.
|
46
|
-
return if klass.
|
51
|
+
return if klass._responders.empty? || klass._responders.any? { |(mime, _condition), _block| mime == :any }
|
47
52
|
|
48
53
|
mimes = mimes_for_respond_to.dup
|
49
54
|
|
50
55
|
# Make sure no extra mimes are allowed for the action.
|
51
56
|
mimes.each do |mime, restrictions|
|
52
|
-
next if klass.
|
57
|
+
next if klass._responders.any? { |(m, _codition), _block| m == mime }
|
53
58
|
exclude_class_action_in_mime_type mime, restrictions, action
|
54
59
|
end
|
55
60
|
|
56
61
|
# Include all action mimes.
|
57
|
-
klass.
|
62
|
+
klass._responders.each do |(mime, _condition), _block|
|
58
63
|
mimes[mime] ||= { :only => [] }
|
59
64
|
include_class_action_in_mime_type mime, mimes[mime], action
|
60
65
|
end
|
@@ -64,7 +69,7 @@ module ClassAction
|
|
64
69
|
|
65
70
|
def include_class_action_in_mime_type(mime, restrictions, action)
|
66
71
|
if restrictions && restrictions[:except] && restrictions[:except].include?(action)
|
67
|
-
logger.warn "Warning: action #{action} (ClassAction) responds to `#{mime}` but it does not accept this mime type"
|
72
|
+
logger.warn "Warning: action #{action} (ClassAction) responds to `#{mime}` but it does not accept this mime type" if logger
|
68
73
|
elsif restrictions && restrictions[:only] && !restrictions[:only].include?(action)
|
69
74
|
restrictions[:only] << action
|
70
75
|
end
|
@@ -90,9 +95,8 @@ module ClassAction
|
|
90
95
|
|
91
96
|
private
|
92
97
|
|
93
|
-
def
|
94
|
-
|
95
|
-
@_class_action._execute
|
98
|
+
def _class_action
|
99
|
+
send(:"_#{action_name}_action_class")
|
96
100
|
end
|
97
101
|
|
98
102
|
end
|
@@ -5,6 +5,7 @@ describe ClassAction::Action do
|
|
5
5
|
let(:controller) { double(:controller, :view_assigns => {}, :response_body => nil) }
|
6
6
|
let(:action_class) { Class.new(ClassAction::Action) }
|
7
7
|
let(:action) { action_class.new(controller) }
|
8
|
+
before { allow(controller).to receive(:class_action).and_return(action) }
|
8
9
|
|
9
10
|
it "should by default be available" do
|
10
11
|
expect(action).to be_available
|
@@ -15,14 +16,16 @@ describe ClassAction::Action do
|
|
15
16
|
expect(action_class.helpers).to be_a(Module)
|
16
17
|
end
|
17
18
|
|
18
|
-
|
19
|
+
before do
|
19
20
|
action_class.class_eval do
|
20
21
|
def helper1
|
21
22
|
'HELPER RESULT'
|
22
23
|
end
|
23
24
|
helper_method :helper1
|
24
25
|
end
|
26
|
+
end
|
25
27
|
|
28
|
+
it "should define the helper method in the action's helpers module, which should call the method on the controller action" do
|
26
29
|
helpers = action_class.helpers
|
27
30
|
klass = Class.new do
|
28
31
|
include helpers
|
@@ -38,20 +41,45 @@ describe ClassAction::Action do
|
|
38
41
|
expect(controller).to receive(:class_action).and_return(action)
|
39
42
|
expect(obj.helper1).to eql('HELPER RESULT')
|
40
43
|
end
|
44
|
+
|
45
|
+
it "should also expose helper methods on the controller" do
|
46
|
+
action # Load the action up to include the helpers module.
|
47
|
+
expect(controller).to respond_to(:helper1)
|
48
|
+
expect(controller.helper1).to eql('HELPER RESULT')
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should also expose helper methods defined in a superclass" do
|
52
|
+
action_subclass = Class.new(action_class) do
|
53
|
+
def helper2
|
54
|
+
'HELPER2'
|
55
|
+
end
|
56
|
+
helper_method :helper2
|
57
|
+
end
|
58
|
+
|
59
|
+
obj= Class.new{ include action_subclass.helpers }.new
|
60
|
+
expect(obj).to respond_to(:helper1)
|
61
|
+
expect(obj).to respond_to(:helper2)
|
62
|
+
end
|
63
|
+
|
41
64
|
end
|
42
65
|
|
43
|
-
describe '
|
44
|
-
|
45
|
-
before {
|
66
|
+
describe 'controller methods' do
|
67
|
+
let(:result) { double(:result) }
|
68
|
+
before { allow(controller).to receive(:load_post).and_return(result) }
|
46
69
|
|
47
|
-
it "should
|
48
|
-
expect(action
|
70
|
+
it "should make the action respond to :load_post, but protectedly" do
|
71
|
+
expect(action).not_to respond_to(:load_post)
|
72
|
+
expect(action.respond_to?(:load_post, true)).to be_true # matcher doesn't work with second argument
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should pass the method :load_post on to the controller" do
|
76
|
+
expect(action.load_post).to be(result)
|
49
77
|
end
|
50
78
|
|
51
|
-
it "should create a
|
52
|
-
|
53
|
-
|
54
|
-
expect(action.
|
79
|
+
it "should create a protected method :load_post the first time it is called" do
|
80
|
+
expect(action.protected_methods).not_to include(:load_post)
|
81
|
+
action.load_post
|
82
|
+
expect(action.protected_methods).to include(:load_post)
|
55
83
|
end
|
56
84
|
|
57
85
|
it "should copy assigns to the controller before executing the controller method, and copy them back afterwards" do
|
@@ -68,7 +96,6 @@ describe ClassAction::Action do
|
|
68
96
|
end
|
69
97
|
|
70
98
|
action_class.class_eval do
|
71
|
-
controller_method :increase_var
|
72
99
|
def execute
|
73
100
|
@var = 2
|
74
101
|
increase_var
|
@@ -98,7 +125,7 @@ describe ClassAction::Action do
|
|
98
125
|
def method4; end
|
99
126
|
end
|
100
127
|
|
101
|
-
expect(action_class.
|
128
|
+
expect(action_class._action_methods).to eql([ :method1, :method2 ])
|
102
129
|
end
|
103
130
|
end
|
104
131
|
|
@@ -111,22 +138,65 @@ describe ClassAction::Action do
|
|
111
138
|
it "should execute all action methods in the action, and call #copy_assigns_to_controller finally" do
|
112
139
|
called = []
|
113
140
|
|
114
|
-
expect(action_class).to receive(:
|
115
|
-
|
116
|
-
|
141
|
+
expect(action_class).to receive(:_action_methods).and_return([:method1, :method2])
|
142
|
+
|
143
|
+
action_class.class_eval do
|
144
|
+
def method1
|
145
|
+
@called << :method1
|
146
|
+
end
|
147
|
+
def method2
|
148
|
+
@called << :method2
|
149
|
+
end
|
150
|
+
end
|
117
151
|
|
152
|
+
action.instance_variable_set '@called', called
|
118
153
|
action._execute
|
119
154
|
expect(called).to eql([:method1, :method2])
|
120
155
|
end
|
121
156
|
|
157
|
+
it "should skip methods that take arguments" do
|
158
|
+
action_class.class_eval do
|
159
|
+
def one
|
160
|
+
@called = []
|
161
|
+
@called << :one
|
162
|
+
end
|
163
|
+
def two(*args)
|
164
|
+
@called << :two
|
165
|
+
end
|
166
|
+
def three(arg)
|
167
|
+
@called << :three
|
168
|
+
end
|
169
|
+
def three(arg = nil)
|
170
|
+
@called << :four
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
action._execute
|
175
|
+
called = action.instance_variable_get('@called')
|
176
|
+
expect(called).to eql([:one])
|
177
|
+
end
|
178
|
+
|
122
179
|
it "should stop executing when a response body is set" do
|
123
180
|
called = []; response_body = nil
|
124
181
|
|
125
182
|
allow(controller).to receive(:response_body) { response_body }
|
126
|
-
|
127
|
-
|
128
|
-
|
183
|
+
allow(controller).to receive(:response).and_return(double())
|
184
|
+
allow(controller.response).to receive(:body) { response_body }
|
185
|
+
allow(controller.response).to receive(:body=) { |val| response_body = val }
|
186
|
+
|
187
|
+
expect(action_class).to receive(:_action_methods).and_return([:method1, :method2])
|
129
188
|
|
189
|
+
action_class.class_eval do
|
190
|
+
def method1
|
191
|
+
@called << :method1
|
192
|
+
response.body = '<html></html>'
|
193
|
+
end
|
194
|
+
def method2
|
195
|
+
@called << :method2
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
action.instance_variable_set '@called', called
|
130
200
|
action._execute
|
131
201
|
expect(called).to eql([:method1])
|
132
202
|
end
|
@@ -134,11 +204,20 @@ describe ClassAction::Action do
|
|
134
204
|
it "should call _respond at the end" do
|
135
205
|
called = []
|
136
206
|
|
137
|
-
expect(action_class).to receive(:
|
138
|
-
|
139
|
-
|
207
|
+
expect(action_class).to receive(:_action_methods).and_return([:method1, :method2])
|
208
|
+
|
209
|
+
action_class.class_eval do
|
210
|
+
def method1
|
211
|
+
@called << :method1
|
212
|
+
end
|
213
|
+
def method2
|
214
|
+
@called << :method2
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
140
218
|
expect(action).to receive(:_respond) { called << :_respond }
|
141
219
|
|
220
|
+
action.instance_variable_set '@called', called
|
142
221
|
action._execute
|
143
222
|
expect(called).to eql([:method1, :method2, :_respond])
|
144
223
|
end
|
@@ -168,7 +247,7 @@ describe ClassAction::Action do
|
|
168
247
|
action._execute
|
169
248
|
end
|
170
249
|
|
171
|
-
context "with no
|
250
|
+
context "with no response method or responders" do
|
172
251
|
it "should not call a respond method, but copy all instance variables into the controller at the end" do
|
173
252
|
expect(controller).not_to receive(:respond_with)
|
174
253
|
expect(controller).not_to receive(:respond_to)
|
@@ -176,16 +255,21 @@ describe ClassAction::Action do
|
|
176
255
|
end
|
177
256
|
end
|
178
257
|
|
179
|
-
context "having set a
|
258
|
+
context "having set a response method" do
|
180
259
|
let(:response) { double(:response) }
|
181
260
|
before do
|
182
261
|
action_class.class_eval do
|
183
262
|
respond_with :response
|
263
|
+
respond_with :invalid_response, on: :invalid
|
264
|
+
|
265
|
+
protected
|
266
|
+
|
267
|
+
def invalid?() false end
|
184
268
|
end
|
185
|
-
expect(action).to receive(:response).and_return(response)
|
186
269
|
end
|
187
270
|
|
188
|
-
it "should
|
271
|
+
it "should use the value of #response" do
|
272
|
+
expect(action).to receive(:response).and_return(response)
|
189
273
|
expect(controller).to receive(:respond_with).with(response) do |&blk|
|
190
274
|
expect(blk).to be_nil
|
191
275
|
end
|
@@ -193,10 +277,27 @@ describe ClassAction::Action do
|
|
193
277
|
action._execute
|
194
278
|
end
|
195
279
|
|
280
|
+
it "should use the value of #invalid_response if invalid? returns true" do
|
281
|
+
allow(action).to receive(:invalid?).and_return(true)
|
282
|
+
expect(action).to receive(:invalid_response).and_return(response)
|
283
|
+
expect(controller).to receive(:respond_with).with(response)
|
284
|
+
action._execute
|
285
|
+
end
|
286
|
+
|
287
|
+
it "should read an instance variable if this is set" do
|
288
|
+
action_class.class_eval do
|
289
|
+
respond_with :@response
|
290
|
+
end
|
291
|
+
action.instance_variable_set '@response', response
|
292
|
+
expect(controller).to receive(:respond_with).with(response)
|
293
|
+
action._execute
|
294
|
+
end
|
295
|
+
|
196
296
|
it "should use the _respond_block if it is set" do
|
197
297
|
block = proc{}
|
198
298
|
allow(action).to receive(:_respond_block).and_return(block)
|
199
299
|
|
300
|
+
expect(action).to receive(:response).and_return(response)
|
200
301
|
expect(controller).to receive(:respond_with).with(response) do |&blk|
|
201
302
|
expect(blk).to be(block)
|
202
303
|
end
|
@@ -227,18 +328,29 @@ describe ClassAction::Action do
|
|
227
328
|
|
228
329
|
# Private method, but specced individually to make spec terser.
|
229
330
|
|
230
|
-
|
331
|
+
def respond_block
|
332
|
+
action.send(:_respond_block)
|
333
|
+
end
|
231
334
|
|
232
335
|
it "should create a block using the given responders, which is executed on the action" do
|
233
336
|
called = nil; receiver = nil
|
234
337
|
json_block = proc { receiver = self; called = :json }
|
235
338
|
html_block = proc { receiver = self; called = :html }
|
236
|
-
|
339
|
+
html_invalid_block = proc { receiver = self; called = :html_invalid }
|
340
|
+
any_ok_block = proc { receiver = self; called = :any_ok }
|
237
341
|
|
238
342
|
action_class.class_eval do
|
239
343
|
respond_to :json, &json_block
|
240
344
|
respond_to :html, &html_block
|
241
|
-
|
345
|
+
respond_to :html, on: :invalid, &html_invalid_block
|
346
|
+
respond_to_any on: :ok, &any_ok_block
|
347
|
+
|
348
|
+
attr_accessor :status
|
349
|
+
|
350
|
+
protected
|
351
|
+
|
352
|
+
def ok?() status == :ok end
|
353
|
+
def invalid?() status == :invalid end
|
242
354
|
end
|
243
355
|
|
244
356
|
# Simulate ActionController's format collector.
|
@@ -247,16 +359,77 @@ describe ClassAction::Action do
|
|
247
359
|
def collector.html(&block) @html_block = block end
|
248
360
|
def collector.any(&block) @any_block = block end
|
249
361
|
|
362
|
+
action.status = :ok
|
250
363
|
respond_block.call collector
|
364
|
+
collector.json_block.call
|
365
|
+
expect(receiver).to be(action); expect(called).to be(:json)
|
251
366
|
|
367
|
+
action.status = :invalid
|
368
|
+
respond_block.call collector
|
252
369
|
collector.json_block.call
|
253
370
|
expect(receiver).to be(action); expect(called).to be(:json)
|
254
371
|
|
372
|
+
action.status = :ok
|
373
|
+
respond_block.call collector
|
255
374
|
collector.html_block.call
|
256
375
|
expect(receiver).to be(action); expect(called).to be(:html)
|
257
376
|
|
377
|
+
action.status = :invalid
|
378
|
+
respond_block.call collector
|
379
|
+
collector.html_block.call
|
380
|
+
expect(receiver).to be(action); expect(called).to be(:html_invalid)
|
381
|
+
|
382
|
+
action.status = :ok
|
383
|
+
respond_block.call collector
|
258
384
|
collector.any_block.call
|
259
|
-
expect(receiver).to be(action); expect(called).to be(:
|
385
|
+
expect(receiver).to be(action); expect(called).to be(:any_ok)
|
386
|
+
|
387
|
+
receiver = nil
|
388
|
+
called = nil
|
389
|
+
|
390
|
+
action.status = :invalid
|
391
|
+
expect(collector).not_to receive(:any)
|
392
|
+
respond_block.call collector
|
393
|
+
end
|
394
|
+
|
395
|
+
it "should copy assigns back to the controller after responding" do
|
396
|
+
action_class.class_eval do
|
397
|
+
respond_to :html do
|
398
|
+
@my_var = :value
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
collector = Class.new{ attr_reader :html_block }.new
|
403
|
+
def collector.html(&block) @html_block = block end
|
404
|
+
respond_block.call collector
|
405
|
+
|
406
|
+
collector.html_block.call
|
407
|
+
expect(controller.instance_variable_get('@my_var')).to be(:value)
|
408
|
+
end
|
409
|
+
|
410
|
+
it "should take responders to a subclass" do
|
411
|
+
action_class.class_eval do
|
412
|
+
respond_to :html
|
413
|
+
end
|
414
|
+
action_subclass = Class.new(action_class) do
|
415
|
+
respond_to :json
|
416
|
+
end
|
417
|
+
|
418
|
+
expect(action_subclass._responders).to eql(
|
419
|
+
[ :html, nil ] => nil,
|
420
|
+
[ :json, nil ] => nil
|
421
|
+
)
|
422
|
+
end
|
423
|
+
|
424
|
+
it "should copy the respond_with_method to a subclass" do
|
425
|
+
action_class.class_eval do
|
426
|
+
respond_with :post
|
427
|
+
end
|
428
|
+
|
429
|
+
action_subclass = Class.new(action_class)
|
430
|
+
expect(action_subclass).to have(1)._response
|
431
|
+
expect(action_subclass._responses.keys[0]).to be_nil
|
432
|
+
expect(action_subclass._responses.values[0]).to be(:post)
|
260
433
|
end
|
261
434
|
|
262
435
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'class_action/rspec'
|
3
|
+
|
4
|
+
describe ClassAction::RSpec::HaveClassActionMatcher do
|
5
|
+
|
6
|
+
class ClassActionTestController < ActionController::Base
|
7
|
+
class Index < ClassAction::Action
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:controller) { ClassActionTestController.new }
|
12
|
+
|
13
|
+
it "should fail if the controller does not support class actions" do
|
14
|
+
expect { expect(controller).to have_class_action(:index) }.to \
|
15
|
+
raise_error(
|
16
|
+
RSpec::Expectations::ExpectationNotMetError,
|
17
|
+
"expected controller of class ClassActionTestController to have class action :index, but it does not support class actions"
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
context "having included ClassAction" do
|
22
|
+
before { ClassActionTestController.send :include, ClassAction }
|
23
|
+
|
24
|
+
it "should fail if the controller does not have an index action" do
|
25
|
+
expect { expect(controller).to have_class_action(:index) }.to \
|
26
|
+
raise_error(
|
27
|
+
RSpec::Expectations::ExpectationNotMetError,
|
28
|
+
"expected controller of class ClassActionTestController to have class action :index"
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should fail if the controller's index action is not a class action" do
|
33
|
+
ClassActionTestController.class_eval do
|
34
|
+
def index
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
expect { expect(controller).to have_class_action(:index) }.to \
|
39
|
+
raise_error(
|
40
|
+
RSpec::Expectations::ExpectationNotMetError,
|
41
|
+
"expected action ClassActionTestController#index to be a class action"
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should pass if the index action is a class action" do
|
46
|
+
ClassActionTestController.class_eval do
|
47
|
+
class_action :index
|
48
|
+
end
|
49
|
+
|
50
|
+
expect { expect(controller).to have_class_action(:index) }.not_to raise_error
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should fail if the controller's index action uses a different class" do
|
54
|
+
ClassActionTestController.class_eval do
|
55
|
+
class Index2 < ClassAction::Action
|
56
|
+
end
|
57
|
+
|
58
|
+
class_action :index2, Index2
|
59
|
+
end
|
60
|
+
|
61
|
+
expect { expect(controller).to have_class_action(:index2).using_class(ClassActionTestController::Index) }.to \
|
62
|
+
raise_error(
|
63
|
+
RSpec::Expectations::ExpectationNotMetError,
|
64
|
+
"expected action ClassActionTestController#index2 to use class ClassActionTestController::Index, but it used Index2"
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|