mcmire-shoulda-matchers 2.5.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 (164) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +32 -0
  4. data/.yardopts +7 -0
  5. data/Appraisals +45 -0
  6. data/CONTRIBUTING.md +41 -0
  7. data/Gemfile +31 -0
  8. data/Gemfile.lock +166 -0
  9. data/MIT-LICENSE +22 -0
  10. data/NEWS.md +299 -0
  11. data/README.md +163 -0
  12. data/Rakefile +116 -0
  13. data/doc_config/gh-pages/index.html.erb +9 -0
  14. data/doc_config/yard/setup.rb +22 -0
  15. data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +5967 -0
  16. data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +12 -0
  17. data/doc_config/yard/templates/default/fulldoc/html/css/global.css +45 -0
  18. data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +69 -0
  19. data/doc_config/yard/templates/default/fulldoc/html/css/style.css +283 -0
  20. data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +32 -0
  21. data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +1 -0
  22. data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +8 -0
  23. data/doc_config/yard/templates/default/fulldoc/html/js/app.js +300 -0
  24. data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +1 -0
  25. data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +289 -0
  26. data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +6 -0
  27. data/doc_config/yard/templates/default/fulldoc/html/setup.rb +8 -0
  28. data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +14 -0
  29. data/doc_config/yard/templates/default/layout/html/fonts.erb +1 -0
  30. data/doc_config/yard/templates/default/layout/html/layout.erb +23 -0
  31. data/doc_config/yard/templates/default/layout/html/search.erb +13 -0
  32. data/doc_config/yard/templates/default/layout/html/setup.rb +8 -0
  33. data/doc_config/yard/templates/default/method_details/html/source.erb +10 -0
  34. data/doc_config/yard/templates/default/module/html/box_info.erb +31 -0
  35. data/features/rails_integration.feature +113 -0
  36. data/features/step_definitions/rails_steps.rb +162 -0
  37. data/features/support/env.rb +5 -0
  38. data/gemfiles/3.0.gemfile +24 -0
  39. data/gemfiles/3.0.gemfile.lock +150 -0
  40. data/gemfiles/3.1.gemfile +27 -0
  41. data/gemfiles/3.1.gemfile.lock +173 -0
  42. data/gemfiles/3.2.gemfile +27 -0
  43. data/gemfiles/3.2.gemfile.lock +171 -0
  44. data/gemfiles/4.0.0.gemfile +28 -0
  45. data/gemfiles/4.0.0.gemfile.lock +172 -0
  46. data/gemfiles/4.0.1.gemfile +28 -0
  47. data/gemfiles/4.0.1.gemfile.lock +172 -0
  48. data/lib/shoulda-matchers.rb +1 -0
  49. data/lib/shoulda/matchers.rb +11 -0
  50. data/lib/shoulda/matchers/action_controller.rb +17 -0
  51. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +64 -0
  52. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +97 -0
  53. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +81 -0
  54. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +117 -0
  55. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +114 -0
  56. data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +154 -0
  57. data/lib/shoulda/matchers/action_controller/route_matcher.rb +116 -0
  58. data/lib/shoulda/matchers/action_controller/route_params.rb +48 -0
  59. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +164 -0
  60. data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +296 -0
  61. data/lib/shoulda/matchers/active_model.rb +30 -0
  62. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +167 -0
  63. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +314 -0
  64. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +46 -0
  65. data/lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb +160 -0
  66. data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +417 -0
  67. data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +337 -0
  68. data/lib/shoulda/matchers/active_model/errors.rb +10 -0
  69. data/lib/shoulda/matchers/active_model/exception_message_finder.rb +58 -0
  70. data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +92 -0
  71. data/lib/shoulda/matchers/active_model/helpers.rb +46 -0
  72. data/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
  73. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +75 -0
  74. data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +27 -0
  75. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +41 -0
  76. data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +27 -0
  77. data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +26 -0
  78. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +112 -0
  79. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +77 -0
  80. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +121 -0
  81. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +380 -0
  82. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +89 -0
  83. data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +372 -0
  84. data/lib/shoulda/matchers/active_model/validation_matcher.rb +97 -0
  85. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +69 -0
  86. data/lib/shoulda/matchers/active_record.rb +22 -0
  87. data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +204 -0
  88. data/lib/shoulda/matchers/active_record/association_matcher.rb +901 -0
  89. data/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
  90. data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +41 -0
  91. data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +41 -0
  92. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +81 -0
  93. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +65 -0
  94. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +94 -0
  95. data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
  96. data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +41 -0
  97. data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +63 -0
  98. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +261 -0
  99. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +149 -0
  100. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +72 -0
  101. data/lib/shoulda/matchers/active_record/serialize_matcher.rb +181 -0
  102. data/lib/shoulda/matchers/assertion_error.rb +19 -0
  103. data/lib/shoulda/matchers/error.rb +6 -0
  104. data/lib/shoulda/matchers/integrations/rspec.rb +20 -0
  105. data/lib/shoulda/matchers/integrations/test_unit.rb +30 -0
  106. data/lib/shoulda/matchers/rails_shim.rb +50 -0
  107. data/lib/shoulda/matchers/version.rb +6 -0
  108. data/lib/shoulda/matchers/warn.rb +8 -0
  109. data/shoulda-matchers.gemspec +23 -0
  110. data/spec/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +22 -0
  111. data/spec/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +42 -0
  112. data/spec/shoulda/matchers/action_controller/render_template_matcher_spec.rb +78 -0
  113. data/spec/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +63 -0
  114. data/spec/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +63 -0
  115. data/spec/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +31 -0
  116. data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +70 -0
  117. data/spec/shoulda/matchers/action_controller/route_params_spec.rb +30 -0
  118. data/spec/shoulda/matchers/action_controller/set_session_matcher_spec.rb +51 -0
  119. data/spec/shoulda/matchers/action_controller/set_the_flash_matcher_spec.rb +153 -0
  120. data/spec/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +111 -0
  121. data/spec/shoulda/matchers/active_model/allow_value_matcher_spec.rb +170 -0
  122. data/spec/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +81 -0
  123. data/spec/shoulda/matchers/active_model/ensure_exclusion_of_matcher_spec.rb +95 -0
  124. data/spec/shoulda/matchers/active_model/ensure_inclusion_of_matcher_spec.rb +320 -0
  125. data/spec/shoulda/matchers/active_model/ensure_length_of_matcher_spec.rb +166 -0
  126. data/spec/shoulda/matchers/active_model/exception_message_finder_spec.rb +111 -0
  127. data/spec/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +20 -0
  128. data/spec/shoulda/matchers/active_model/helpers_spec.rb +158 -0
  129. data/spec/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +169 -0
  130. data/spec/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +59 -0
  131. data/spec/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +59 -0
  132. data/spec/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +57 -0
  133. data/spec/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +139 -0
  134. data/spec/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +41 -0
  135. data/spec/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +47 -0
  136. data/spec/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +331 -0
  137. data/spec/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +180 -0
  138. data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +398 -0
  139. data/spec/shoulda/matchers/active_model/validation_message_finder_spec.rb +127 -0
  140. data/spec/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +107 -0
  141. data/spec/shoulda/matchers/active_record/association_matcher_spec.rb +860 -0
  142. data/spec/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +247 -0
  143. data/spec/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +111 -0
  144. data/spec/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +78 -0
  145. data/spec/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +41 -0
  146. data/spec/shoulda/matchers/active_record/serialize_matcher_spec.rb +86 -0
  147. data/spec/spec_helper.rb +26 -0
  148. data/spec/support/active_model_versions.rb +13 -0
  149. data/spec/support/active_resource_builder.rb +29 -0
  150. data/spec/support/activemodel_helpers.rb +19 -0
  151. data/spec/support/capture_helpers.rb +19 -0
  152. data/spec/support/class_builder.rb +42 -0
  153. data/spec/support/controller_builder.rb +74 -0
  154. data/spec/support/fail_with_message_including_matcher.rb +33 -0
  155. data/spec/support/fail_with_message_matcher.rb +32 -0
  156. data/spec/support/i18n_faker.rb +10 -0
  157. data/spec/support/mailer_builder.rb +10 -0
  158. data/spec/support/model_builder.rb +81 -0
  159. data/spec/support/rails_versions.rb +18 -0
  160. data/spec/support/shared_examples/numerical_submatcher.rb +19 -0
  161. data/spec/support/shared_examples/numerical_type_submatcher.rb +17 -0
  162. data/spec/support/test_application.rb +120 -0
  163. data/yard.watchr +5 -0
  164. metadata +281 -0
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shoulda::Matchers::ActiveRecord::SerializeMatcher do
4
+ it 'accepts when the attribute is serialized' do
5
+ expect(with_serialized_attr).to serialize(:attr)
6
+ end
7
+
8
+ context 'when attribute is not serialized' do
9
+ it 'rejects' do
10
+ expect(unserialized_model).not_to serialize(:attr)
11
+ end
12
+
13
+ it 'assigns a helpful failure message' do
14
+ matcher = serialize(:attr)
15
+
16
+ matcher.matches?(unserialized_model)
17
+
18
+ expect(matcher.failure_message).to match(/to serialize the attribute called :attr/)
19
+ end
20
+
21
+ it 'assigns a helpful failure message when using #as' do
22
+ matcher = serialize(:attr).as(Hash)
23
+
24
+ matcher.matches?(unserialized_model)
25
+
26
+ expect(matcher.failure_message).to match(/with a type of Hash/)
27
+ end
28
+
29
+ it 'assigns a helpful failure message when using #as_instance_of' do
30
+ matcher = serialize(:attr).as_instance_of(Hash)
31
+
32
+ matcher.matches?(unserialized_model)
33
+
34
+ expect(matcher.failure_message).to match(/with an instance of Hash/)
35
+ end
36
+
37
+ def unserialized_model
38
+ @model ||= define_model(:example, attr: :string).new
39
+ end
40
+ end
41
+
42
+ context 'an attribute that is serialized as a specific type' do
43
+ it 'accepts when the types match' do
44
+ expect(with_serialized_attr(Hash)).to serialize(:attr).as(Hash)
45
+ end
46
+
47
+ it 'rejects when the types do not match' do
48
+ expect(with_serialized_attr(Hash)).not_to serialize(:attr).as(String)
49
+ end
50
+
51
+ it 'rejects when using as_instance_of' do
52
+ expect(with_serialized_attr(Hash)).not_to serialize(:attr).as_instance_of(Hash)
53
+ end
54
+ end
55
+
56
+ context 'a serializer that is an instance of a class' do
57
+ it 'accepts when using #as_instance_of' do
58
+ define_serializer(:ExampleSerializer)
59
+ expect(with_serialized_attr(ExampleSerializer.new)).
60
+ to serialize(:attr).as_instance_of(ExampleSerializer)
61
+ end
62
+
63
+ it 'rejects when using #as' do
64
+ define_serializer(:ExampleSerializer)
65
+ expect(with_serialized_attr(ExampleSerializer.new)).
66
+ not_to serialize(:attr).as(ExampleSerializer)
67
+ end
68
+ end
69
+
70
+ def with_serialized_attr(type = nil)
71
+ define_model(:example, attr: :string) do
72
+ if type
73
+ serialize :attr, type
74
+ else
75
+ serialize :attr
76
+ end
77
+ end.new
78
+ end
79
+
80
+ def define_serializer(name)
81
+ define_class(name) do
82
+ def load(*); end
83
+ def dump(*); end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path('../support/test_application', __FILE__)
2
+
3
+ $test_app = TestApplication.new
4
+ $test_app.create
5
+ $test_app.load
6
+
7
+ ENV['BUNDLE_GEMFILE'] ||= app.gemfile_path
8
+ ENV['RAILS_ENV'] = 'test'
9
+
10
+ require 'bourne'
11
+ require 'shoulda-matchers'
12
+ require 'rspec/rails'
13
+
14
+ PROJECT_ROOT = File.expand_path('../..', __FILE__)
15
+ $LOAD_PATH << File.join(PROJECT_ROOT, 'lib')
16
+ Dir[ File.join(PROJECT_ROOT, 'spec/support/**/*.rb') ].each { |file| require file }
17
+
18
+ RSpec.configure do |config|
19
+ config.expect_with :rspec do |c|
20
+ c.syntax = :expect
21
+ end
22
+
23
+ config.mock_with :mocha
24
+ config.include Shoulda::Matchers::ActionController,
25
+ example_group: { file_path: /action_controller/ }
26
+ end
@@ -0,0 +1,13 @@
1
+ RSpec.configure do |c|
2
+ def active_model_3_1?
3
+ (::ActiveModel::VERSION::MAJOR == 3 && ::ActiveModel::VERSION::MINOR >= 1) || active_model_4_0?
4
+ end
5
+
6
+ def active_model_3_2?
7
+ (::ActiveModel::VERSION::MAJOR == 3 && ::ActiveModel::VERSION::MINOR >= 2) || active_model_4_0?
8
+ end
9
+
10
+ def active_model_4_0?
11
+ ::ActiveModel::VERSION::MAJOR == 4
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ require 'active_resource'
2
+
3
+ module ActiveResourceBuilder
4
+ def self.included(example_group)
5
+ example_group.class_eval do
6
+ after do
7
+ ActiveSupport::Dependencies.clear
8
+ end
9
+ end
10
+ end
11
+
12
+ def define_active_resource_class(class_name, attributes = {}, &block)
13
+ define_class(class_name, ActiveResource::Base) do
14
+ schema do
15
+ attributes.each do |attr, type|
16
+ attribute attr, type
17
+ end
18
+ end
19
+
20
+ if block_given?
21
+ class_eval(&block)
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ RSpec.configure do |config|
28
+ config.include ActiveResourceBuilder
29
+ end
@@ -0,0 +1,19 @@
1
+ module ActiveModelHelpers
2
+ def custom_validation(&block)
3
+ define_model(:example, attr: :integer) do
4
+ validate :custom_validation
5
+
6
+ define_method(:custom_validation, &block)
7
+ end.new
8
+ end
9
+
10
+ def validating_format(options)
11
+ define_model :example, attr: :string do
12
+ validates_format_of :attr, options
13
+ end.new
14
+ end
15
+ end
16
+
17
+ RSpec.configure do |c|
18
+ c.include ActiveModelHelpers
19
+ end
@@ -0,0 +1,19 @@
1
+ module Kernel
2
+ unless method_defined?(:capture)
3
+ def capture(stream)
4
+ stream = stream.to_s
5
+ captured_stream = Tempfile.new(stream)
6
+ stream_io = eval("$#{stream}")
7
+ origin_stream = stream_io.dup
8
+ stream_io.reopen(captured_stream)
9
+
10
+ yield
11
+
12
+ stream_io.rewind
13
+ return captured_stream.read
14
+ ensure
15
+ captured_stream.unlink
16
+ stream_io.reopen(origin_stream)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,42 @@
1
+ module ClassBuilder
2
+ def self.included(example_group)
3
+ example_group.class_eval do
4
+ after do
5
+ teardown_defined_constants
6
+ end
7
+ end
8
+ end
9
+
10
+ def define_class(class_name, base = Object, &block)
11
+ class_name = class_name.to_s.camelize
12
+
13
+ # FIXME: ActionMailer 3.2 calls `name.underscore` immediately upon
14
+ # subclassing. Class.new.name == nil. So, Class.new(ActionMailer::Base)
15
+ # errors out since it's trying to do `nil.underscore`. This is very ugly but
16
+ # allows us to test against ActionMailer 3.2.x.
17
+ eval <<-A_REAL_CLASS_FOR_ACTION_MAILER_3_2
18
+ class ::#{class_name} < #{base}
19
+ end
20
+ A_REAL_CLASS_FOR_ACTION_MAILER_3_2
21
+
22
+ Object.const_get(class_name).tap do |constant_class|
23
+ constant_class.unloadable
24
+
25
+ if block_given?
26
+ constant_class.class_eval(&block)
27
+ end
28
+
29
+ if constant_class.respond_to?(:reset_column_information)
30
+ constant_class.reset_column_information
31
+ end
32
+ end
33
+ end
34
+
35
+ def teardown_defined_constants
36
+ ActiveSupport::Dependencies.clear
37
+ end
38
+ end
39
+
40
+ RSpec.configure do |config|
41
+ config.include ClassBuilder
42
+ end
@@ -0,0 +1,74 @@
1
+ module ControllerBuilder
2
+ def self.included(example_group)
3
+ example_group.class_eval do
4
+ after do
5
+ delete_temporary_views
6
+ restore_original_routes
7
+ end
8
+ end
9
+ end
10
+
11
+ def define_controller(class_name, &block)
12
+ class_name = class_name.to_s
13
+ class_name << 'Controller' unless class_name =~ /Controller$/
14
+ define_class(class_name, ActionController::Base, &block)
15
+ end
16
+
17
+ def define_routes(&block)
18
+ @routes = $test_app.draw_routes(&block)
19
+ class << self
20
+ include ActionDispatch::Assertions
21
+ end
22
+ end
23
+
24
+ def build_response(opts = {}, &block)
25
+ action = opts[:action] || 'example'
26
+ partial = opts[:partial] || '_partial'
27
+ block ||= lambda { render nothing: true }
28
+ controller_class = define_controller('Examples') do
29
+ layout false
30
+ define_method(action, &block)
31
+ end
32
+ controller_class.view_paths = [ $test_app.temp_views_dir_path ]
33
+
34
+ define_routes do
35
+ get 'examples', to: "examples##{action}"
36
+ end
37
+
38
+ create_view("examples/#{action}.html.erb", 'action')
39
+ create_view("examples/#{partial}.html.erb", 'partial')
40
+
41
+ setup_rails_controller_test(controller_class)
42
+ get action
43
+
44
+ @controller
45
+ end
46
+
47
+ def setup_rails_controller_test(controller_class)
48
+ @controller = controller_class.new
49
+ @request = ::ActionController::TestRequest.new
50
+ @response = ::ActionController::TestResponse.new
51
+
52
+ class << self
53
+ include ActionController::TestCase::Behavior
54
+ end
55
+ end
56
+
57
+ def create_view(path, contents)
58
+ $test_app.create_temp_view(path, contents)
59
+ end
60
+
61
+ private
62
+
63
+ def delete_temporary_views
64
+ $test_app.delete_temp_views
65
+ end
66
+
67
+ def restore_original_routes
68
+ Rails.application.reload_routes!
69
+ end
70
+ end
71
+
72
+ RSpec.configure do |config|
73
+ config.include ControllerBuilder
74
+ end
@@ -0,0 +1,33 @@
1
+ RSpec::Matchers.define :fail_with_message_including do |expected|
2
+ match do |block|
3
+ @actual = nil
4
+
5
+ begin
6
+ block.call
7
+ rescue RSpec::Expectations::ExpectationNotMetError => ex
8
+ @actual = ex.message
9
+ end
10
+
11
+ @actual && @actual.include?(expected)
12
+ end
13
+
14
+ failure_message_for_should do
15
+ msg = "Expectation should have failed with message including '#{expected}'"
16
+
17
+ if @actual
18
+ msg << ", actually failed with '#{@actual}'"
19
+ else
20
+ msg << ", but did not fail."
21
+ end
22
+
23
+ msg
24
+ end
25
+
26
+ failure_message_for_should_not do
27
+ msg = "Expectation should not have failed with message including '#{expected}'"
28
+ msg << ", but did."
29
+
30
+ msg
31
+ end
32
+
33
+ end
@@ -0,0 +1,32 @@
1
+ RSpec::Matchers.define :fail_with_message do |expected|
2
+ match do |block|
3
+ @actual = nil
4
+
5
+ begin
6
+ block.call
7
+ rescue RSpec::Expectations::ExpectationNotMetError => ex
8
+ @actual = ex.message
9
+ end
10
+
11
+ @actual && @actual == expected
12
+ end
13
+
14
+ failure_message_for_should do
15
+ msg = "Expectation should have failed with message '#{expected}'"
16
+
17
+ if @actual
18
+ msg << ", actually failed with '#{@actual}'"
19
+ else
20
+ msg << ", but did not fail."
21
+ end
22
+
23
+ msg
24
+ end
25
+
26
+ failure_message_for_should_not do
27
+ msg = "Expectation should not have failed with message '#{expected}'"
28
+ msg << ", but did."
29
+
30
+ msg
31
+ end
32
+ end
@@ -0,0 +1,10 @@
1
+ module I18nFaker
2
+ def stub_translation(key, message)
3
+ yml = key.split('.').reverse.inject(message) { |a, n| { n => a } }
4
+ I18n.backend.store_translations(:en, yml)
5
+ end
6
+ end
7
+
8
+ RSpec.configure do |config|
9
+ config.include I18nFaker
10
+ end
@@ -0,0 +1,10 @@
1
+ module MailerBuilder
2
+ def define_mailer(name, paths, &block)
3
+ class_name = name.to_s.pluralize.classify
4
+ define_class(class_name, ActionMailer::Base, &block)
5
+ end
6
+ end
7
+
8
+ RSpec.configure do |config|
9
+ config.include MailerBuilder
10
+ end
@@ -0,0 +1,81 @@
1
+ module ModelBuilder
2
+ def self.included(example_group)
3
+ example_group.class_eval do
4
+ before do
5
+ @created_tables ||= []
6
+ end
7
+
8
+ after do
9
+ drop_created_tables
10
+ ActiveSupport::Dependencies.clear
11
+ end
12
+ end
13
+ end
14
+
15
+ def create_table(table_name, options = {}, &block)
16
+ connection = ActiveRecord::Base.connection
17
+
18
+ begin
19
+ connection.execute("DROP TABLE IF EXISTS #{table_name}")
20
+ connection.create_table(table_name, options, &block)
21
+ @created_tables << table_name
22
+ connection
23
+ rescue Exception => e
24
+ connection.execute("DROP TABLE IF EXISTS #{table_name}")
25
+ raise e
26
+ end
27
+ end
28
+
29
+ def define_model_class(class_name, &block)
30
+ define_class(class_name, ActiveRecord::Base, &block)
31
+ end
32
+
33
+ def define_active_model_class(class_name, options = {}, &block)
34
+ define_class(class_name) do
35
+ include ActiveModel::Validations
36
+
37
+ options[:accessors].each do |column|
38
+ attr_accessor column.to_sym
39
+ end
40
+
41
+ if block_given?
42
+ class_eval(&block)
43
+ end
44
+ end
45
+ end
46
+
47
+ def define_model(name, columns = {}, &block)
48
+ class_name = name.to_s.pluralize.classify
49
+ table_name = class_name.tableize
50
+ table_block = lambda do |table|
51
+ columns.each do |name, specification|
52
+ if specification.is_a?(Hash)
53
+ table.column name, specification[:type], specification[:options]
54
+ else
55
+ table.column name, specification
56
+ end
57
+ end
58
+ end
59
+
60
+ if columns.key?(:id) && columns[:id] == false
61
+ columns.delete(:id)
62
+ create_table(table_name, id: false, &table_block)
63
+ else
64
+ create_table(table_name, &table_block)
65
+ end
66
+
67
+ define_model_class(class_name, &block)
68
+ end
69
+
70
+ def drop_created_tables
71
+ connection = ActiveRecord::Base.connection
72
+
73
+ @created_tables.each do |table_name|
74
+ connection.execute("DROP TABLE IF EXISTS #{table_name}")
75
+ end
76
+ end
77
+ end
78
+
79
+ RSpec.configure do |config|
80
+ config.include ModelBuilder
81
+ end