rspec_candy 0.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.
- data/.gitignore +8 -0
- data/README.md +7 -0
- data/Rakefile +18 -0
- data/lib/rspec_candy/helpers/disposable_copy.rb +16 -0
- data/lib/rspec_candy/helpers/it_should_act_like.rb +39 -0
- data/lib/rspec_candy/helpers/new_with_stubs.rb +16 -0
- data/lib/rspec_candy/helpers/rails/create_without_callbacks.rb +25 -0
- data/lib/rspec_candy/helpers/rails/it_should_run_callbacks.rb +111 -0
- data/lib/rspec_candy/helpers/rails/prevent_storage.rb +20 -0
- data/lib/rspec_candy/helpers/should_receive_and_execute.rb +38 -0
- data/lib/rspec_candy/helpers/should_receive_and_return.rb +17 -0
- data/lib/rspec_candy/helpers/should_receive_chain.rb +43 -0
- data/lib/rspec_candy/helpers/stub_any_instance.rb +25 -0
- data/lib/rspec_candy/helpers/stub_existing.rb +20 -0
- data/lib/rspec_candy/switcher.rb +44 -0
- data/lib/rspec_candy/version.rb +3 -0
- data/lib/rspec_candy.rb +16 -0
- data/rspec_candy.gemspec +19 -0
- data/spec/rspec1/Gemfile +13 -0
- data/spec/rspec1/Rakefile +11 -0
- data/spec/rspec1/app_root/config/boot.rb +114 -0
- data/spec/rspec1/app_root/config/database.yml +21 -0
- data/spec/rspec1/app_root/config/environment.rb +14 -0
- data/spec/rspec1/app_root/config/environments/in_memory.rb +0 -0
- data/spec/rspec1/app_root/config/environments/mysql.rb +0 -0
- data/spec/rspec1/app_root/config/environments/postgresql.rb +0 -0
- data/spec/rspec1/app_root/config/environments/sqlite.rb +0 -0
- data/spec/rspec1/app_root/config/environments/sqlite3.rb +0 -0
- data/spec/rspec1/app_root/config/initializers/state_machine.rb +1 -0
- data/spec/rspec1/app_root/config/routes.rb +4 -0
- data/spec/rspec1/app_root/log/.gitignore +1 -0
- data/spec/rspec1/rcov.opts +2 -0
- data/spec/rspec1/spec.opts +4 -0
- data/spec/rspec1/spec_helper.rb +24 -0
- data/spec/rspec2/.rspec +2 -0
- data/spec/rspec2/Gemfile +13 -0
- data/spec/rspec2/Rakefile +11 -0
- data/spec/rspec2/app_root/.gitignore +4 -0
- data/spec/rspec2/app_root/config/application.rb +32 -0
- data/spec/rspec2/app_root/config/boot.rb +13 -0
- data/spec/rspec2/app_root/config/database.yml +21 -0
- data/spec/rspec2/app_root/config/environment.rb +5 -0
- data/spec/rspec2/app_root/config/environments/in_memory.rb +0 -0
- data/spec/rspec2/app_root/config/environments/mysql.rb +0 -0
- data/spec/rspec2/app_root/config/environments/postgresql.rb +0 -0
- data/spec/rspec2/app_root/config/environments/sqlite.rb +0 -0
- data/spec/rspec2/app_root/config/environments/sqlite3.rb +0 -0
- data/spec/rspec2/app_root/config/environments/test.rb +35 -0
- data/spec/rspec2/app_root/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rspec2/app_root/config/initializers/inflections.rb +10 -0
- data/spec/rspec2/app_root/config/initializers/mime_types.rb +5 -0
- data/spec/rspec2/app_root/config/initializers/secret_token.rb +7 -0
- data/spec/rspec2/app_root/config/initializers/session_store.rb +8 -0
- data/spec/rspec2/app_root/config/initializers/state_machine.rb +1 -0
- data/spec/rspec2/app_root/config/locales/en.yml +5 -0
- data/spec/rspec2/app_root/config/routes.rb +58 -0
- data/spec/rspec2/app_root/log/.gitkeep +0 -0
- data/spec/rspec2/rcov.opts +2 -0
- data/spec/rspec2/spec_helper.rb +25 -0
- data/spec/shared/app_root/app/controllers/application_controller.rb +2 -0
- data/spec/shared/app_root/app/models/model.rb +19 -0
- data/spec/shared/app_root/app/models/state_machine_model.rb +30 -0
- data/spec/shared/app_root/config/initializers/state_machine.rb +1 -0
- data/spec/shared/app_root/db/migrate/001_create_model.rb +13 -0
- data/spec/shared/app_root/db/migrate/002_create_state_machine_model.rb +13 -0
- data/spec/shared/rspec_candy/helpers/disposable_copy_spec.rb +45 -0
- data/spec/shared/rspec_candy/helpers/it_should_act_like_spec.rb +139 -0
- data/spec/shared/rspec_candy/helpers/new_with_stubs_spec.rb +41 -0
- data/spec/shared/rspec_candy/helpers/rails/create_without_callbacks_spec.rb +41 -0
- data/spec/shared/rspec_candy/helpers/rails/it_should_run_callbacks_spec.rb +142 -0
- data/spec/shared/rspec_candy/helpers/rails/prevent_storage_spec.rb +85 -0
- data/spec/shared/rspec_candy/helpers/should_receive_and_execute_spec.rb +32 -0
- data/spec/shared/rspec_candy/helpers/should_receive_and_return_spec.rb +30 -0
- data/spec/shared/rspec_candy/helpers/should_receive_chain_spec.rb +99 -0
- data/spec/shared/rspec_candy/helpers/stub_any_instance_spec.rb +32 -0
- data/spec/shared/rspec_candy/helpers/stub_existing_spec.rb +27 -0
- data/spec/shared/support/matchers/pass_as_describe_block.rb +32 -0
- data/spec/shared/support/matchers/pass_as_example.rb +30 -0
- data/template/spec_candy.rails2.rb +171 -0
- data/template/spec_candy.rails3.rb +175 -0
- metadata +159 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RSpecCandy::Helpers::StubExisting do
|
|
4
|
+
|
|
5
|
+
describe Object do
|
|
6
|
+
|
|
7
|
+
describe '#stub_existing' do
|
|
8
|
+
|
|
9
|
+
it 'should stub an existing method' do
|
|
10
|
+
string = 'foo'
|
|
11
|
+
string.stub_existing(:upcase => 'BAR', :downcase => 'bar')
|
|
12
|
+
string.upcase.should == 'BAR'
|
|
13
|
+
string.downcase.should == 'bar'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'should raise an error when attempting to stub a non-existing method' do
|
|
17
|
+
string = 'foo'
|
|
18
|
+
expect do
|
|
19
|
+
string.stub_existing(:unknown => 'value')
|
|
20
|
+
end.to raise_error('Attempted to stub non-existing method #unknown on "foo"')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
class RSpecRemote
|
|
2
|
+
def self.run_describe_block(describe_block)
|
|
3
|
+
temp_path = nil
|
|
4
|
+
Tempfile.open(['example', '_spec.rb']) do |io|
|
|
5
|
+
io.write(<<-spec)
|
|
6
|
+
require 'spec_helper';
|
|
7
|
+
#{describe_block}
|
|
8
|
+
spec
|
|
9
|
+
temp_path = io.path
|
|
10
|
+
end
|
|
11
|
+
`rake SPEC=#{temp_path} 2>&1`
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
RSpecCandy::Switcher.define_matcher :pass_as_describe_block do
|
|
17
|
+
|
|
18
|
+
match do |describe_block|
|
|
19
|
+
rspec_out = RSpecRemote.run_describe_block(describe_block)
|
|
20
|
+
rspec_out.include?('0 failures')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
RSpecCandy::Switcher.define_matcher :fail_as_describe_block do
|
|
26
|
+
|
|
27
|
+
match do |describe_block|
|
|
28
|
+
rspec_out = RSpecRemote.run_describe_block(describe_block)
|
|
29
|
+
rspec_out.include?('1 failure')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
class RSpecRemote
|
|
2
|
+
def self.run_example(example)
|
|
3
|
+
run_describe_block(<<-describe_block)
|
|
4
|
+
describe 'context' do
|
|
5
|
+
it 'should pass' do
|
|
6
|
+
#{example}
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
describe_block
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
RSpecCandy::Switcher.define_matcher :pass_as_example do
|
|
15
|
+
|
|
16
|
+
match do |example|
|
|
17
|
+
rspec_out = RSpecRemote.run_example(example)
|
|
18
|
+
rspec_out.include?('0 failures')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
RSpecCandy::Switcher.define_matcher :fail_as_example do
|
|
24
|
+
|
|
25
|
+
match do |example|
|
|
26
|
+
rspec_out = RSpecRemote.run_example(example)
|
|
27
|
+
rspec_out.include?('1 failure')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Object.class_eval do
|
|
2
|
+
|
|
3
|
+
def should_receive_chain(*parts)
|
|
4
|
+
setup_expectation_chain(parts)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.new_with_stubs(attrs)
|
|
8
|
+
new.tap do |obj|
|
|
9
|
+
obj.stub_existing attrs
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def stub_existing(attrs)
|
|
14
|
+
attrs.each do |method, value|
|
|
15
|
+
if respond_to?(method, true)
|
|
16
|
+
stub(method => value)
|
|
17
|
+
else
|
|
18
|
+
raise "Attempted to stub non-existing method ##{method} on a #{self.class.name}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def should_receive_and_return(methods_and_values)
|
|
24
|
+
methods_and_values.each do |method, value|
|
|
25
|
+
should_receive(method).and_return(value)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def should_receive_all_with(methods_and_values)
|
|
30
|
+
methods_and_values.each do |method, value|
|
|
31
|
+
should_receive(method).with(value)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def should_not_receive_and_execute(method)
|
|
36
|
+
should_receive_and_execute(method, true)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def should_receive_and_execute(method, negate = false)
|
|
40
|
+
method_base = method.to_s.gsub(/([\?\!\=\[\]]+)$/, '')
|
|
41
|
+
method_suffix = $1
|
|
42
|
+
|
|
43
|
+
method_called = "_#{method_base}_called#{method_suffix}"
|
|
44
|
+
method_with_spy = "#{method_base}_with_spy#{method_suffix}"
|
|
45
|
+
method_without_spy = "#{method_base}_without_spy#{method_suffix}"
|
|
46
|
+
|
|
47
|
+
prototype = respond_to?(:singleton_class) ? singleton_class : metaclass
|
|
48
|
+
prototype.class_eval do
|
|
49
|
+
|
|
50
|
+
unless method_defined?(method_with_spy)
|
|
51
|
+
|
|
52
|
+
define_method method_called do
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
define_method method_with_spy do |*args, &block|
|
|
56
|
+
send(method_called, *args)
|
|
57
|
+
send(method_without_spy, *args, &block)
|
|
58
|
+
end
|
|
59
|
+
alias_method_chain method, :spy
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
expectation = negate ? :should_not_receive : :should_receive
|
|
65
|
+
send(expectation, method_called)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def setup_expectation_chain(parts)
|
|
71
|
+
obj = self
|
|
72
|
+
for part in parts
|
|
73
|
+
if part == parts.last
|
|
74
|
+
obj = add_expectation_chain_link(obj, part)
|
|
75
|
+
else
|
|
76
|
+
next_obj = Spec::Mocks::Mock.new('chain link')
|
|
77
|
+
add_expectation_chain_link(obj, part).at_least(:once).and_return(next_obj)
|
|
78
|
+
obj = next_obj
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
obj
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def add_expectation_chain_link(obj, part)
|
|
85
|
+
if part.is_a?(Array)
|
|
86
|
+
obj.should_receive(part.first).with(*part[1..-1])
|
|
87
|
+
else
|
|
88
|
+
obj.should_receive(part)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
Spec::Example::ExampleGroupMethods.class_eval do
|
|
95
|
+
|
|
96
|
+
# Improves it_should_behave_like in some ways:
|
|
97
|
+
# - It scopes the reused examples so #let und #subject does not bleed into the reusing example groups
|
|
98
|
+
# - It allows to parametrize the reused example group by appending a hash argument.
|
|
99
|
+
# Every key/value pair in the hash will become a #let variable for the reused example group
|
|
100
|
+
# - You can call it with a block. It will be available to the reused example group as let(:block)
|
|
101
|
+
def it_should_act_like(shared_example_group, environment = {}, &block)
|
|
102
|
+
description = "as #{shared_example_group}"
|
|
103
|
+
description << " (#{environment.inspect})" if environment.present?
|
|
104
|
+
describe description do
|
|
105
|
+
environment.each do |name, value|
|
|
106
|
+
let(name) { value }
|
|
107
|
+
end
|
|
108
|
+
let(:block) { block } if block
|
|
109
|
+
it_should_behave_like(shared_example_group)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
Spec::Rails::Example::ModelExampleGroup.class_eval do
|
|
116
|
+
|
|
117
|
+
def self.it_should_run_callbacks_in_order(*callbacks)
|
|
118
|
+
callbacks.push(:ordered => true)
|
|
119
|
+
it_should_run_callbacks(*callbacks)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def self.it_should_run_callbacks(*callbacks)
|
|
123
|
+
options = callbacks.last.is_a?(Hash) ? callbacks.pop : {}
|
|
124
|
+
reason = callbacks.pop if callbacks.last.is_a?(String)
|
|
125
|
+
hook = description_parts.last.sub(/^#/, '')
|
|
126
|
+
should = ['should run callbacks', callbacks.inspect, ('in order' if options[:ordered]), reason].compact.join ' '
|
|
127
|
+
send(:it, should) do
|
|
128
|
+
callbacks.each do |callback|
|
|
129
|
+
expectation = subject.should_receive(callback).once
|
|
130
|
+
expectation.ordered if options[:ordered]
|
|
131
|
+
end
|
|
132
|
+
run_state_machine_callbacks_from_prose(hook) || subject.run_callbacks(hook)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
private
|
|
137
|
+
|
|
138
|
+
def run_state_machine_callbacks_from_prose(prose)
|
|
139
|
+
if parts = prose.match(/^(\w+) from ([\:\w]+) to ([\:\w]+)$/)
|
|
140
|
+
name = parts[1].to_sym
|
|
141
|
+
from = parts[2].sub(/^:/, '').to_sym
|
|
142
|
+
to = parts[3].sub(/^:/, '').to_sym
|
|
143
|
+
transition = StateMachine::Transition.new(subject, subject.class.state_machine, name, from, to)
|
|
144
|
+
transition.run_callbacks
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
ActiveRecord::Base.class_eval do
|
|
151
|
+
|
|
152
|
+
# Prevents the databse from being touched, but still runs all validations.
|
|
153
|
+
def keep_invalid!
|
|
154
|
+
errors.stub :empty? => false
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
Class.class_eval do
|
|
160
|
+
|
|
161
|
+
define_method :stub_any_instance do |stubs|
|
|
162
|
+
unstubbed_new = method(:new)
|
|
163
|
+
stub(:new).and_return do |*args|
|
|
164
|
+
unstubbed_new.call(*args).tap do |obj|
|
|
165
|
+
obj.stub stubs
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
stubs
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
end
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
Object.class_eval do
|
|
2
|
+
|
|
3
|
+
# def should_receive_chain(*parts)
|
|
4
|
+
# setup_expectation_chain(parts)
|
|
5
|
+
# end
|
|
6
|
+
#
|
|
7
|
+
# def should_not_receive_chain(*parts)
|
|
8
|
+
# setup_expectation_chain(parts, :negate => true)
|
|
9
|
+
# end
|
|
10
|
+
#
|
|
11
|
+
# def self.new_with_stubs(attrs)
|
|
12
|
+
# new.tap { |obj| obj.stub(attrs) }
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# def should_receive_and_return(methods_and_values)
|
|
16
|
+
# methods_and_values.each do |method, value|
|
|
17
|
+
# should_receive(method).and_return(value)
|
|
18
|
+
# end
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# def self.new_and_store(options = {})
|
|
22
|
+
# new.tap do |record|
|
|
23
|
+
# record.send(:attributes=, options, false)
|
|
24
|
+
# record.save!(:validate => false)
|
|
25
|
+
# end
|
|
26
|
+
# end
|
|
27
|
+
#
|
|
28
|
+
# def stub_existing(attrs)
|
|
29
|
+
# attrs.each do |method, value|
|
|
30
|
+
# if respond_to?(method, true)
|
|
31
|
+
# stub(method => value)
|
|
32
|
+
# else
|
|
33
|
+
# raise "Attempted to stub non-existing method ##{method} on a #{self.class.name}"
|
|
34
|
+
# end
|
|
35
|
+
# end
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# def should_receive_and_execute(method, negate = false)
|
|
39
|
+
# method_base = method.to_s.gsub(/([\?\!\=\[\]]+)$/, '')
|
|
40
|
+
# method_suffix = $1
|
|
41
|
+
#
|
|
42
|
+
# method_called = "_#{method_base}_called#{method_suffix}"
|
|
43
|
+
# method_with_spy = "#{method_base}_with_spy#{method_suffix}"
|
|
44
|
+
# method_without_spy = "#{method_base}_without_spy#{method_suffix}"
|
|
45
|
+
#
|
|
46
|
+
# prototype = respond_to?(:singleton_class) ? singleton_class : metaclass
|
|
47
|
+
# prototype.class_eval do
|
|
48
|
+
#
|
|
49
|
+
# unless method_defined?(method_with_spy)
|
|
50
|
+
#
|
|
51
|
+
# define_method method_called do
|
|
52
|
+
# end
|
|
53
|
+
#
|
|
54
|
+
# define_method method_with_spy do |*args, &block|
|
|
55
|
+
# send(method_called, *args)
|
|
56
|
+
# send(method_without_spy, *args, &block)
|
|
57
|
+
# end
|
|
58
|
+
# alias_method_chain method, :spy
|
|
59
|
+
# end
|
|
60
|
+
#
|
|
61
|
+
# end
|
|
62
|
+
#
|
|
63
|
+
# expectation = negate ? :should_not_receive : :should_receive
|
|
64
|
+
# send(expectation, method_called)
|
|
65
|
+
# end
|
|
66
|
+
#
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def setup_expectation_chain(parts, options = {})
|
|
70
|
+
obj = self
|
|
71
|
+
for part in parts
|
|
72
|
+
if part == parts.last
|
|
73
|
+
expectation = options[:negate] ? :should_not_receive : :should_receive
|
|
74
|
+
obj = add_expectation_chain_link(obj, expectation, part)
|
|
75
|
+
else
|
|
76
|
+
next_obj = RSpec::Mocks::Mock.new('chain link')
|
|
77
|
+
add_expectation_chain_link(obj, :stub, part).and_return(next_obj)
|
|
78
|
+
obj = next_obj
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
obj
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def add_expectation_chain_link(obj, expectation, part)
|
|
85
|
+
if part.is_a?(Array)
|
|
86
|
+
obj.send(expectation, part.first).with(*part[1..-1])
|
|
87
|
+
else
|
|
88
|
+
obj.send(expectation, part)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
RSpec::Core::ExampleGroup.class_eval do
|
|
95
|
+
|
|
96
|
+
def self.it_should_run_callbacks_in_order(*callbacks)
|
|
97
|
+
callbacks.push(:ordered => true)
|
|
98
|
+
it_should_run_callbacks(*callbacks)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# Improves it_should_behave_like in some ways:
|
|
103
|
+
# - It scopes the reused examples so #let und #subject does not bleed into the reusing example groups
|
|
104
|
+
# - It allows to parametrize the reused example group by appending a hash argument.
|
|
105
|
+
# Every key/value pair in the hash will become a #let variable for the reused example group
|
|
106
|
+
# - You can call it with a block. It will be available to the reused example group as let(:block)
|
|
107
|
+
def self.it_should_act_like(shared_example_group, environment = {}, &block)
|
|
108
|
+
description = "as #{shared_example_group}"
|
|
109
|
+
description << " (#{environment.inspect})" if environment.present?
|
|
110
|
+
describe description do
|
|
111
|
+
environment.each do |name, value|
|
|
112
|
+
let(name) { value }
|
|
113
|
+
end
|
|
114
|
+
let(:block) { block } if block
|
|
115
|
+
it_should_behave_like(shared_example_group)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def self.it_should_run_callbacks(*callbacks)
|
|
120
|
+
options = callbacks.last.is_a?(Hash) ? callbacks.pop : {}
|
|
121
|
+
reason = callbacks.pop if callbacks.last.is_a?(String)
|
|
122
|
+
example_description = description
|
|
123
|
+
send(:it, ["should run callbacks", callbacks.inspect, ('in order' if options[:ordered]), reason].compact.join(' ')) do
|
|
124
|
+
# Set expectations
|
|
125
|
+
callbacks.each do |callback|
|
|
126
|
+
expectation = subject.should_receive(callback).once
|
|
127
|
+
expectation.ordered if options[:ordered]
|
|
128
|
+
end
|
|
129
|
+
run_state_machine_callbacks_from_prose(example_description) || run_active_record_callbacks_from_prose(example_description)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def run_active_record_callbacks_from_prose(prose)
|
|
134
|
+
hook = prose.split.last.sub(/^#/, '')
|
|
135
|
+
if hook.sub!(/_on_(create|update)$/, '')
|
|
136
|
+
condition = "validation_context == :#{$1}"
|
|
137
|
+
else
|
|
138
|
+
condition = nil
|
|
139
|
+
end
|
|
140
|
+
if hook == 'validate'
|
|
141
|
+
kind = 'before'
|
|
142
|
+
action = 'validate'
|
|
143
|
+
else
|
|
144
|
+
hook =~ /^(before|after|around)_(.*)$/
|
|
145
|
+
kind = $1
|
|
146
|
+
action = $2
|
|
147
|
+
end
|
|
148
|
+
# Run all matching callbacks
|
|
149
|
+
subject.send("_#{action}_callbacks").each do |callback|
|
|
150
|
+
if callback.kind.to_s == kind && (condition.nil? || callback.options[:if].include?(condition))
|
|
151
|
+
subject.send callback.filter.to_s.gsub(/[\(,\)]/, '').to_sym
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def run_state_machine_callbacks_from_prose(prose)
|
|
157
|
+
if parts = prose.match(/^(\#\w+) from ([\:\w]+) to ([\:\w]+)$/)
|
|
158
|
+
name = parts[1].sub(/^#/, '').to_sym
|
|
159
|
+
from = parts[2].sub(/^:/, '').to_sym
|
|
160
|
+
to = parts[3].sub(/^:/, '').to_sym
|
|
161
|
+
transition = StateMachine::Transition.new(subject, subject.class.state_machine, name, from, to)
|
|
162
|
+
transition.run_callbacks
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
ActiveRecord::Base.class_eval do
|
|
169
|
+
|
|
170
|
+
# Prevents the database from being touched, but still runs all validations.
|
|
171
|
+
def keep_invalid!
|
|
172
|
+
errors.stub :empty? => false
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rspec_candy
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: 27
|
|
5
|
+
prerelease:
|
|
6
|
+
segments:
|
|
7
|
+
- 0
|
|
8
|
+
- 1
|
|
9
|
+
- 0
|
|
10
|
+
version: 0.1.0
|
|
11
|
+
platform: ruby
|
|
12
|
+
authors:
|
|
13
|
+
- Henning Koch
|
|
14
|
+
- Tobias Kraze
|
|
15
|
+
autorequire:
|
|
16
|
+
bindir: bin
|
|
17
|
+
cert_chain: []
|
|
18
|
+
|
|
19
|
+
date: 2012-05-11 00:00:00 Z
|
|
20
|
+
dependencies:
|
|
21
|
+
- !ruby/object:Gem::Dependency
|
|
22
|
+
name: rspec
|
|
23
|
+
prerelease: false
|
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ">="
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
hash: 3
|
|
30
|
+
segments:
|
|
31
|
+
- 0
|
|
32
|
+
version: "0"
|
|
33
|
+
type: :runtime
|
|
34
|
+
version_requirements: *id001
|
|
35
|
+
description: RSpec helpers and matchers we use in our daily work at makandra.
|
|
36
|
+
email: henning.koch@makandra.de
|
|
37
|
+
executables: []
|
|
38
|
+
|
|
39
|
+
extensions: []
|
|
40
|
+
|
|
41
|
+
extra_rdoc_files: []
|
|
42
|
+
|
|
43
|
+
files:
|
|
44
|
+
- .gitignore
|
|
45
|
+
- README.md
|
|
46
|
+
- Rakefile
|
|
47
|
+
- lib/rspec_candy.rb
|
|
48
|
+
- lib/rspec_candy/helpers/disposable_copy.rb
|
|
49
|
+
- lib/rspec_candy/helpers/it_should_act_like.rb
|
|
50
|
+
- lib/rspec_candy/helpers/new_with_stubs.rb
|
|
51
|
+
- lib/rspec_candy/helpers/rails/create_without_callbacks.rb
|
|
52
|
+
- lib/rspec_candy/helpers/rails/it_should_run_callbacks.rb
|
|
53
|
+
- lib/rspec_candy/helpers/rails/prevent_storage.rb
|
|
54
|
+
- lib/rspec_candy/helpers/should_receive_and_execute.rb
|
|
55
|
+
- lib/rspec_candy/helpers/should_receive_and_return.rb
|
|
56
|
+
- lib/rspec_candy/helpers/should_receive_chain.rb
|
|
57
|
+
- lib/rspec_candy/helpers/stub_any_instance.rb
|
|
58
|
+
- lib/rspec_candy/helpers/stub_existing.rb
|
|
59
|
+
- lib/rspec_candy/switcher.rb
|
|
60
|
+
- lib/rspec_candy/version.rb
|
|
61
|
+
- rspec_candy.gemspec
|
|
62
|
+
- spec/rspec1/Gemfile
|
|
63
|
+
- spec/rspec1/Rakefile
|
|
64
|
+
- spec/rspec1/app_root/config/boot.rb
|
|
65
|
+
- spec/rspec1/app_root/config/database.yml
|
|
66
|
+
- spec/rspec1/app_root/config/environment.rb
|
|
67
|
+
- spec/rspec1/app_root/config/environments/in_memory.rb
|
|
68
|
+
- spec/rspec1/app_root/config/environments/mysql.rb
|
|
69
|
+
- spec/rspec1/app_root/config/environments/postgresql.rb
|
|
70
|
+
- spec/rspec1/app_root/config/environments/sqlite.rb
|
|
71
|
+
- spec/rspec1/app_root/config/environments/sqlite3.rb
|
|
72
|
+
- spec/rspec1/app_root/config/initializers/state_machine.rb
|
|
73
|
+
- spec/rspec1/app_root/config/routes.rb
|
|
74
|
+
- spec/rspec1/app_root/log/.gitignore
|
|
75
|
+
- spec/rspec1/rcov.opts
|
|
76
|
+
- spec/rspec1/spec.opts
|
|
77
|
+
- spec/rspec1/spec_helper.rb
|
|
78
|
+
- spec/rspec2/.rspec
|
|
79
|
+
- spec/rspec2/Gemfile
|
|
80
|
+
- spec/rspec2/Rakefile
|
|
81
|
+
- spec/rspec2/app_root/.gitignore
|
|
82
|
+
- spec/rspec2/app_root/config/application.rb
|
|
83
|
+
- spec/rspec2/app_root/config/boot.rb
|
|
84
|
+
- spec/rspec2/app_root/config/database.yml
|
|
85
|
+
- spec/rspec2/app_root/config/environment.rb
|
|
86
|
+
- spec/rspec2/app_root/config/environments/in_memory.rb
|
|
87
|
+
- spec/rspec2/app_root/config/environments/mysql.rb
|
|
88
|
+
- spec/rspec2/app_root/config/environments/postgresql.rb
|
|
89
|
+
- spec/rspec2/app_root/config/environments/sqlite.rb
|
|
90
|
+
- spec/rspec2/app_root/config/environments/sqlite3.rb
|
|
91
|
+
- spec/rspec2/app_root/config/environments/test.rb
|
|
92
|
+
- spec/rspec2/app_root/config/initializers/backtrace_silencers.rb
|
|
93
|
+
- spec/rspec2/app_root/config/initializers/inflections.rb
|
|
94
|
+
- spec/rspec2/app_root/config/initializers/mime_types.rb
|
|
95
|
+
- spec/rspec2/app_root/config/initializers/secret_token.rb
|
|
96
|
+
- spec/rspec2/app_root/config/initializers/session_store.rb
|
|
97
|
+
- spec/rspec2/app_root/config/initializers/state_machine.rb
|
|
98
|
+
- spec/rspec2/app_root/config/locales/en.yml
|
|
99
|
+
- spec/rspec2/app_root/config/routes.rb
|
|
100
|
+
- spec/rspec2/app_root/log/.gitkeep
|
|
101
|
+
- spec/rspec2/rcov.opts
|
|
102
|
+
- spec/rspec2/spec_helper.rb
|
|
103
|
+
- spec/shared/app_root/app/controllers/application_controller.rb
|
|
104
|
+
- spec/shared/app_root/app/models/model.rb
|
|
105
|
+
- spec/shared/app_root/app/models/state_machine_model.rb
|
|
106
|
+
- spec/shared/app_root/config/initializers/state_machine.rb
|
|
107
|
+
- spec/shared/app_root/db/migrate/001_create_model.rb
|
|
108
|
+
- spec/shared/app_root/db/migrate/002_create_state_machine_model.rb
|
|
109
|
+
- spec/shared/rspec_candy/helpers/disposable_copy_spec.rb
|
|
110
|
+
- spec/shared/rspec_candy/helpers/it_should_act_like_spec.rb
|
|
111
|
+
- spec/shared/rspec_candy/helpers/new_with_stubs_spec.rb
|
|
112
|
+
- spec/shared/rspec_candy/helpers/rails/create_without_callbacks_spec.rb
|
|
113
|
+
- spec/shared/rspec_candy/helpers/rails/it_should_run_callbacks_spec.rb
|
|
114
|
+
- spec/shared/rspec_candy/helpers/rails/prevent_storage_spec.rb
|
|
115
|
+
- spec/shared/rspec_candy/helpers/should_receive_and_execute_spec.rb
|
|
116
|
+
- spec/shared/rspec_candy/helpers/should_receive_and_return_spec.rb
|
|
117
|
+
- spec/shared/rspec_candy/helpers/should_receive_chain_spec.rb
|
|
118
|
+
- spec/shared/rspec_candy/helpers/stub_any_instance_spec.rb
|
|
119
|
+
- spec/shared/rspec_candy/helpers/stub_existing_spec.rb
|
|
120
|
+
- spec/shared/support/matchers/pass_as_describe_block.rb
|
|
121
|
+
- spec/shared/support/matchers/pass_as_example.rb
|
|
122
|
+
- template/spec_candy.rails2.rb
|
|
123
|
+
- template/spec_candy.rails3.rb
|
|
124
|
+
homepage: https://github.com/makandra/rspec_candy
|
|
125
|
+
licenses: []
|
|
126
|
+
|
|
127
|
+
post_install_message:
|
|
128
|
+
rdoc_options: []
|
|
129
|
+
|
|
130
|
+
require_paths:
|
|
131
|
+
- lib
|
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
133
|
+
none: false
|
|
134
|
+
requirements:
|
|
135
|
+
- - ">="
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
hash: 3
|
|
138
|
+
segments:
|
|
139
|
+
- 0
|
|
140
|
+
version: "0"
|
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
|
+
none: false
|
|
143
|
+
requirements:
|
|
144
|
+
- - ">="
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
hash: 3
|
|
147
|
+
segments:
|
|
148
|
+
- 0
|
|
149
|
+
version: "0"
|
|
150
|
+
requirements: []
|
|
151
|
+
|
|
152
|
+
rubyforge_project:
|
|
153
|
+
rubygems_version: 1.8.10
|
|
154
|
+
signing_key:
|
|
155
|
+
specification_version: 3
|
|
156
|
+
summary: RSpec helpers and matchers we use in our daily work at makandra.
|
|
157
|
+
test_files: []
|
|
158
|
+
|
|
159
|
+
has_rdoc:
|