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.
Files changed (81) hide show
  1. data/.gitignore +8 -0
  2. data/README.md +7 -0
  3. data/Rakefile +18 -0
  4. data/lib/rspec_candy/helpers/disposable_copy.rb +16 -0
  5. data/lib/rspec_candy/helpers/it_should_act_like.rb +39 -0
  6. data/lib/rspec_candy/helpers/new_with_stubs.rb +16 -0
  7. data/lib/rspec_candy/helpers/rails/create_without_callbacks.rb +25 -0
  8. data/lib/rspec_candy/helpers/rails/it_should_run_callbacks.rb +111 -0
  9. data/lib/rspec_candy/helpers/rails/prevent_storage.rb +20 -0
  10. data/lib/rspec_candy/helpers/should_receive_and_execute.rb +38 -0
  11. data/lib/rspec_candy/helpers/should_receive_and_return.rb +17 -0
  12. data/lib/rspec_candy/helpers/should_receive_chain.rb +43 -0
  13. data/lib/rspec_candy/helpers/stub_any_instance.rb +25 -0
  14. data/lib/rspec_candy/helpers/stub_existing.rb +20 -0
  15. data/lib/rspec_candy/switcher.rb +44 -0
  16. data/lib/rspec_candy/version.rb +3 -0
  17. data/lib/rspec_candy.rb +16 -0
  18. data/rspec_candy.gemspec +19 -0
  19. data/spec/rspec1/Gemfile +13 -0
  20. data/spec/rspec1/Rakefile +11 -0
  21. data/spec/rspec1/app_root/config/boot.rb +114 -0
  22. data/spec/rspec1/app_root/config/database.yml +21 -0
  23. data/spec/rspec1/app_root/config/environment.rb +14 -0
  24. data/spec/rspec1/app_root/config/environments/in_memory.rb +0 -0
  25. data/spec/rspec1/app_root/config/environments/mysql.rb +0 -0
  26. data/spec/rspec1/app_root/config/environments/postgresql.rb +0 -0
  27. data/spec/rspec1/app_root/config/environments/sqlite.rb +0 -0
  28. data/spec/rspec1/app_root/config/environments/sqlite3.rb +0 -0
  29. data/spec/rspec1/app_root/config/initializers/state_machine.rb +1 -0
  30. data/spec/rspec1/app_root/config/routes.rb +4 -0
  31. data/spec/rspec1/app_root/log/.gitignore +1 -0
  32. data/spec/rspec1/rcov.opts +2 -0
  33. data/spec/rspec1/spec.opts +4 -0
  34. data/spec/rspec1/spec_helper.rb +24 -0
  35. data/spec/rspec2/.rspec +2 -0
  36. data/spec/rspec2/Gemfile +13 -0
  37. data/spec/rspec2/Rakefile +11 -0
  38. data/spec/rspec2/app_root/.gitignore +4 -0
  39. data/spec/rspec2/app_root/config/application.rb +32 -0
  40. data/spec/rspec2/app_root/config/boot.rb +13 -0
  41. data/spec/rspec2/app_root/config/database.yml +21 -0
  42. data/spec/rspec2/app_root/config/environment.rb +5 -0
  43. data/spec/rspec2/app_root/config/environments/in_memory.rb +0 -0
  44. data/spec/rspec2/app_root/config/environments/mysql.rb +0 -0
  45. data/spec/rspec2/app_root/config/environments/postgresql.rb +0 -0
  46. data/spec/rspec2/app_root/config/environments/sqlite.rb +0 -0
  47. data/spec/rspec2/app_root/config/environments/sqlite3.rb +0 -0
  48. data/spec/rspec2/app_root/config/environments/test.rb +35 -0
  49. data/spec/rspec2/app_root/config/initializers/backtrace_silencers.rb +7 -0
  50. data/spec/rspec2/app_root/config/initializers/inflections.rb +10 -0
  51. data/spec/rspec2/app_root/config/initializers/mime_types.rb +5 -0
  52. data/spec/rspec2/app_root/config/initializers/secret_token.rb +7 -0
  53. data/spec/rspec2/app_root/config/initializers/session_store.rb +8 -0
  54. data/spec/rspec2/app_root/config/initializers/state_machine.rb +1 -0
  55. data/spec/rspec2/app_root/config/locales/en.yml +5 -0
  56. data/spec/rspec2/app_root/config/routes.rb +58 -0
  57. data/spec/rspec2/app_root/log/.gitkeep +0 -0
  58. data/spec/rspec2/rcov.opts +2 -0
  59. data/spec/rspec2/spec_helper.rb +25 -0
  60. data/spec/shared/app_root/app/controllers/application_controller.rb +2 -0
  61. data/spec/shared/app_root/app/models/model.rb +19 -0
  62. data/spec/shared/app_root/app/models/state_machine_model.rb +30 -0
  63. data/spec/shared/app_root/config/initializers/state_machine.rb +1 -0
  64. data/spec/shared/app_root/db/migrate/001_create_model.rb +13 -0
  65. data/spec/shared/app_root/db/migrate/002_create_state_machine_model.rb +13 -0
  66. data/spec/shared/rspec_candy/helpers/disposable_copy_spec.rb +45 -0
  67. data/spec/shared/rspec_candy/helpers/it_should_act_like_spec.rb +139 -0
  68. data/spec/shared/rspec_candy/helpers/new_with_stubs_spec.rb +41 -0
  69. data/spec/shared/rspec_candy/helpers/rails/create_without_callbacks_spec.rb +41 -0
  70. data/spec/shared/rspec_candy/helpers/rails/it_should_run_callbacks_spec.rb +142 -0
  71. data/spec/shared/rspec_candy/helpers/rails/prevent_storage_spec.rb +85 -0
  72. data/spec/shared/rspec_candy/helpers/should_receive_and_execute_spec.rb +32 -0
  73. data/spec/shared/rspec_candy/helpers/should_receive_and_return_spec.rb +30 -0
  74. data/spec/shared/rspec_candy/helpers/should_receive_chain_spec.rb +99 -0
  75. data/spec/shared/rspec_candy/helpers/stub_any_instance_spec.rb +32 -0
  76. data/spec/shared/rspec_candy/helpers/stub_existing_spec.rb +27 -0
  77. data/spec/shared/support/matchers/pass_as_describe_block.rb +32 -0
  78. data/spec/shared/support/matchers/pass_as_example.rb +30 -0
  79. data/template/spec_candy.rails2.rb +171 -0
  80. data/template/spec_candy.rails3.rb +175 -0
  81. metadata +159 -0
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ doc
2
+ pkg
3
+ *.gem
4
+ .idea
5
+ spec/**/app_root/log/*
6
+ Gemfile.lock
7
+
8
+
data/README.md ADDED
@@ -0,0 +1,7 @@
1
+ Changes from previous versions:
2
+
3
+ - `new_and_store` has been renamed `create_without_callbacks`
4
+ - `keep_invalid!` has been renamed to `prevent_storage`
5
+ - `Object#should_not_receive_and_execute` has been removed (same as `Object#should_not_receive`)
6
+ - `should_receive_all_with` (over-generic method name for a helper that is rarely useful)
7
+
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ require "bundler/gem_tasks"
5
+
6
+
7
+ desc 'Default: Run all specs.'
8
+ task :default => :all_specs
9
+
10
+ desc "Run all specs"
11
+ task :all_specs do
12
+ Dir['spec/**/Rakefile'].sort.each do |rakefile|
13
+ directory = File.dirname(rakefile)
14
+ puts '', "\033[44m#{directory}\033[0m", ''
15
+ env = "SPEC=../../#{ENV['SPEC']} " if ENV['SPEC']
16
+ system("cd #{directory} && #{env} bundle exec rake")
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ module RSpecCandy
2
+ module Helpers
3
+ module DisposableCopy
4
+
5
+ def disposable_copy(&body)
6
+ this = self
7
+ copy = Class.new(self, &body)
8
+ copy.singleton_class.send(:define_method, :name) { this.name }
9
+ copy
10
+ end
11
+
12
+ Class.send(:include, self)
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module RSpecCandy
2
+ module Helpers
3
+ module ItShouldActLike
4
+
5
+ def self.included(by)
6
+ by.class_eval do
7
+
8
+ # Improves it_should_behave_like in some ways:
9
+ # - It scopes the reused examples so #let und #subject does not bleed into the reusing example groups
10
+ # - It allows to parametrize the reused example group by appending a hash argument.
11
+ # Every key/value pair in the hash will become a #let variable for the reused example group
12
+ # - You can call it with a block. It will be available to the reused example group as let(:block)
13
+ def it_should_act_like(shared_example_group, environment = {}, &block)
14
+ if Switcher.rspec_version == :rspec2
15
+ warn('"it_should_act_like" is deprecated. Consider using "it_should_behave_like".')
16
+ end
17
+
18
+ description = "as #{shared_example_group}"
19
+ description << " (#{environment.inspect})" if environment.present?
20
+ describe description do
21
+ environment.each do |name, value|
22
+ let(name) { value }
23
+ end
24
+ let(:block) { block } if block
25
+ it_should_behave_like(shared_example_group)
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ case Switcher.rspec_version
32
+ when :rspec1
33
+ Spec::Example::ExampleGroupMethods.send(:include, self)
34
+ when :rspec2
35
+ RSpec::Core::ExampleGroup.singleton_class.send(:include, self)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,16 @@
1
+ module RSpecCandy
2
+ module Helpers
3
+ module NewWithStubs
4
+
5
+ def new_with_stubs(stubs)
6
+ obj = new
7
+ obj.stub_existing stubs
8
+ obj
9
+ end
10
+
11
+ Class.send(:include, self)
12
+
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,25 @@
1
+ module RSpecCandy
2
+ module Helpers
3
+ module Rails
4
+ module CreateWithoutCallbacks
5
+
6
+ def create_without_callbacks(*args)
7
+ table_name = self.table_name
8
+ plain_model = Class.new(ActiveRecord::Base) do
9
+ self.table_name = table_name
10
+ end
11
+ plain_record = plain_model.create!(*args)
12
+ find plain_record.id
13
+ end
14
+
15
+ def new_and_store(*args)
16
+ warn 'new_and_store is deprecated. Use create_without_callbacks instead.'
17
+ create_without_callbacks(*args)
18
+ end
19
+
20
+ ActiveRecord::Base.send(:extend, self)
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,111 @@
1
+ module RSpecCandy
2
+ module Helpers
3
+ module Rails
4
+ module ItShouldRunCallbacks
5
+
6
+ module ExampleGroupMethods
7
+ def self.included(by)
8
+ by.class_eval do
9
+
10
+ def it_should_run_callbacks_in_order(*callbacks)
11
+ callbacks.push(:ordered => true)
12
+ it_should_run_callbacks(*callbacks)
13
+ end
14
+
15
+ def it_should_run_callbacks(*callbacks)
16
+ options = callbacks.last.is_a?(Hash) ? callbacks.pop : {}
17
+ reason = callbacks.pop if callbacks.last.is_a?(String)
18
+ should = ['should run callbacks', callbacks.inspect, ('in order' if options[:ordered]), reason].compact.join ' '
19
+
20
+ prose = case Switcher.rspec_version
21
+ when :rspec1
22
+ description_parts.last
23
+ when :rspec2
24
+ description.split(/(?=#)/).last
25
+ end
26
+
27
+ send(:it, should) do
28
+ extend ExampleMethods
29
+ if subject.class.respond_to?(:state_machine) and defined?(StateMachine)
30
+ extend StateMachineExampleMethods
31
+ end
32
+ callbacks.each do |callback|
33
+ expectation = subject.should_receive(callback).once
34
+ expectation.ordered if options[:ordered]
35
+ end
36
+ run_all_callbacks(prose)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ module ExampleMethods
44
+ private
45
+
46
+ def run_all_callbacks(prose)
47
+ run_active_record_callbacks_from_prose(prose)
48
+ end
49
+
50
+ case Switcher.rspec_version
51
+ when :rspec1
52
+
53
+ def run_active_record_callbacks_from_prose(prose)
54
+ subject.run_callbacks(prose.sub(/^#/, ''))
55
+ end
56
+
57
+ when :rspec2
58
+
59
+ def run_active_record_callbacks_from_prose(prose)
60
+ hook = prose.split.last.sub(/^#/, '')
61
+ if hook.sub!(/_on_(create|update)$/, '')
62
+ condition = "validation_context == :#{$1}"
63
+ else
64
+ condition = nil
65
+ end
66
+ if hook == 'validate'
67
+ kind = 'before'
68
+ action = 'validate'
69
+ else
70
+ hook =~ /^(before|after|around)_(.*)$/
71
+ kind = $1
72
+ action = $2
73
+ end
74
+ # Run all matching callbacks
75
+ subject.send("_#{action}_callbacks").send(kind == 'after' ? :reverse_each : :each) do |callback|
76
+ if callback.kind.to_s == kind && (condition.nil? || callback.options[:if].include?(condition))
77
+ subject.send(callback.filter.to_s.gsub(/[\(,\)]/, '').to_sym) {}
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+ end
84
+
85
+ module StateMachineExampleMethods
86
+ def run_all_callbacks(prose)
87
+ run_state_machine_callbacks_from_prose(prose) or super
88
+ end
89
+
90
+ def run_state_machine_callbacks_from_prose(prose)
91
+ if parts = prose.match(/^(#\w+) from ([\:\w]+) to ([\:\w]+)$/)
92
+ name = parts[1].sub(/^#/, '').to_sym
93
+ from = parts[2].sub(/^:/, '').to_sym
94
+ to = parts[3].sub(/^:/, '').to_sym
95
+ transition = StateMachine::Transition.new(subject, subject.class.state_machine, name, from, to)
96
+ transition.run_callbacks
97
+ end
98
+ end
99
+ end
100
+
101
+ case Switcher.rspec_version
102
+ when :rspec1
103
+ Spec::Example::ExampleGroupMethods.send(:include, self::ExampleGroupMethods)
104
+ when :rspec2
105
+ RSpec::Core::ExampleGroup.singleton_class.send(:include, self::ExampleGroupMethods)
106
+ end
107
+
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,20 @@
1
+ module RSpecCandy
2
+ module Helpers
3
+ module Rails
4
+ module PreventStorage
5
+
6
+ def prevent_storage
7
+ errors.stub :empty? => false
8
+ end
9
+
10
+ def keep_invalid!
11
+ warn 'keep_invalid! is deprecated. Use prevent_storage instead.'
12
+ prevent_storage
13
+ end
14
+
15
+ ActiveRecord::Base.send(:include, self)
16
+
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,38 @@
1
+ module RSpecCandy
2
+ module Helpers
3
+ module ShouldReceiveAndExecute
4
+
5
+ def should_receive_and_execute(method)
6
+ method_base = method.to_s.gsub(/([\?\!\=\[\]]+)$/, '')
7
+ method_suffix = $1
8
+
9
+ method_called = "_#{method_base}_called#{method_suffix}"
10
+ method_with_spy = "#{method_base}_with_spy#{method_suffix}"
11
+ method_without_spy = "#{method_base}_without_spy#{method_suffix}"
12
+
13
+ prototype = respond_to?(:singleton_class) ? singleton_class : metaclass
14
+ prototype.class_eval do
15
+
16
+ unless method_defined?(method_with_spy)
17
+
18
+ define_method method_called do
19
+ end
20
+
21
+ define_method method_with_spy do |*args, &block|
22
+ send(method_called, *args)
23
+ send(method_without_spy, *args, &block)
24
+ end
25
+ alias_method_chain method, :spy
26
+ end
27
+
28
+ end
29
+
30
+ should_receive(method_called)
31
+ end
32
+
33
+ Object.send(:include, self)
34
+
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,17 @@
1
+ module RSpecCandy
2
+ module Helpers
3
+ module ShouldReceiveAndReturn
4
+
5
+ def should_receive_and_return(methods_and_values)
6
+ methods_and_values.each do |method, value|
7
+ should_receive(method).and_return(value)
8
+ end
9
+ self
10
+ end
11
+
12
+ Object.send(:include, self)
13
+
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,43 @@
1
+ module RSpecCandy
2
+ module Helpers
3
+ module ShouldReceiveChain
4
+
5
+ def should_receive_chain(*parts)
6
+ setup_expectation_chain(parts)
7
+ end
8
+
9
+ def should_not_receive_chain(*parts)
10
+ setup_expectation_chain(parts, :negate => true)
11
+ end
12
+
13
+ private
14
+
15
+ def setup_expectation_chain(parts, options = {})
16
+ obj = self
17
+ for part in parts
18
+ if part == parts.last
19
+ expectation = options[:negate] ? :should_not_receive : :should_receive
20
+ obj = add_expectation_chain_link(obj, expectation, part)
21
+ else
22
+ next_obj = Switcher.new_mock('chain link')
23
+ add_expectation_chain_link(obj, :stub, part).and_return(next_obj)
24
+ obj = next_obj
25
+ end
26
+ end
27
+ obj
28
+ end
29
+
30
+ def add_expectation_chain_link(obj, expectation, part)
31
+ if part.is_a?(Array)
32
+ obj.send(expectation, part.first).with(*part[1..-1])
33
+ else
34
+ obj.send(expectation, part)
35
+ end
36
+ end
37
+
38
+ Object.send(:include, self)
39
+
40
+ end
41
+ end
42
+ end
43
+
@@ -0,0 +1,25 @@
1
+ module RSpecCandy
2
+ module Helpers
3
+ module StubAnyInstance
4
+
5
+ def stub_any_instance(stubs)
6
+ case Switcher.rspec_version
7
+ when :rspec1
8
+ unstubbed_new = method(:new)
9
+ stub(:new).and_return do |*args|
10
+ unstubbed_new.call(*args).tap do |obj|
11
+ obj.stub stubs
12
+ end
13
+ end
14
+ stubs
15
+ when :rspec2
16
+ any_instance.stub(stubs)
17
+ end
18
+ end
19
+
20
+ Class.send(:include, self)
21
+
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,20 @@
1
+ module RSpecCandy
2
+ module Helpers
3
+ module StubExisting
4
+
5
+ def stub_existing(attrs)
6
+ attrs.each do |method, value|
7
+ if respond_to?(method, true)
8
+ stub(method => value)
9
+ else
10
+ raise "Attempted to stub non-existing method ##{method} on #{inspect}"
11
+ end
12
+ end
13
+ end
14
+
15
+ Object.send(:include, self)
16
+
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,44 @@
1
+ module RSpecCandy
2
+ module Switcher
3
+ extend self
4
+
5
+ def rspec_version
6
+ if defined?(RSpec)
7
+ :rspec2
8
+ elsif defined?(Spec)
9
+ :rspec1
10
+ else
11
+ raise 'Cannot determine RSpec version'
12
+ end
13
+ end
14
+
15
+ def rails_version
16
+ if Rails.version.to_i < 3
17
+ :rails2
18
+ else
19
+ :rails3
20
+ end
21
+ end
22
+
23
+ def rails_loaded?
24
+ defined?(Rails)
25
+ end
26
+
27
+ def new_mock(*args)
28
+ rspec_root.const_get(:Mocks).const_get(:Mock).new(*args)
29
+ end
30
+
31
+ def rspec_root
32
+ (defined?(RSpec) ? RSpec : Spec)
33
+ end
34
+
35
+ def rspec_matcher_registry
36
+ rspec_root.const_get(:Matchers)
37
+ end
38
+
39
+ def define_matcher(*args, &block)
40
+ rspec_matcher_registry.define(*args, &block)
41
+ end
42
+
43
+ end
44
+ end