shoulda-matchers 2.8.0 → 3.0.0.rc1

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 (171) hide show
  1. checksums.yaml +4 -4
  2. data/.hound_config/ruby.yml +7 -0
  3. data/.travis.yml +11 -54
  4. data/Appraisals +45 -100
  5. data/CONTRIBUTING.md +51 -7
  6. data/Gemfile +7 -19
  7. data/Gemfile.lock +60 -134
  8. data/Guardfile +5 -0
  9. data/NEWS.md +203 -0
  10. data/README.md +95 -50
  11. data/Rakefile +1 -0
  12. data/doc_config/yard/templates/default/layout/html/setup.rb +1 -1
  13. data/gemfiles/4.0.0.gemfile +10 -7
  14. data/gemfiles/4.0.0.gemfile.lock +103 -79
  15. data/gemfiles/4.0.1.gemfile +10 -7
  16. data/gemfiles/4.0.1.gemfile.lock +109 -83
  17. data/gemfiles/4.1.gemfile +10 -7
  18. data/gemfiles/4.1.gemfile.lock +109 -85
  19. data/gemfiles/4.2.gemfile +10 -9
  20. data/gemfiles/4.2.gemfile.lock +86 -78
  21. data/lib/shoulda/matchers.rb +13 -18
  22. data/lib/shoulda/matchers/action_controller.rb +4 -1
  23. data/lib/shoulda/matchers/action_controller/flash_store.rb +95 -0
  24. data/lib/shoulda/matchers/action_controller/{strong_parameters_matcher.rb → permit_matcher.rb} +147 -30
  25. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +1 -1
  26. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +1 -1
  27. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +1 -1
  28. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +1 -1
  29. data/lib/shoulda/matchers/action_controller/route_matcher.rb +5 -1
  30. data/lib/shoulda/matchers/action_controller/route_params.rb +15 -6
  31. data/lib/shoulda/matchers/action_controller/session_store.rb +34 -0
  32. data/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +30 -136
  33. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +28 -109
  34. data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +103 -0
  35. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +1 -12
  36. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +79 -10
  37. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +10 -0
  38. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +21 -0
  39. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +24 -0
  40. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +22 -5
  41. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +29 -10
  42. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +27 -10
  43. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +27 -12
  44. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +56 -20
  45. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +3 -11
  46. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +65 -0
  47. data/lib/shoulda/matchers/active_record/association_matcher.rb +40 -6
  48. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +21 -7
  49. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +11 -40
  50. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +1 -1
  51. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +2 -6
  52. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +137 -22
  53. data/lib/shoulda/matchers/configuration.rb +20 -0
  54. data/lib/shoulda/matchers/doublespeak.rb +11 -1
  55. data/lib/shoulda/matchers/doublespeak/double.rb +29 -11
  56. data/lib/shoulda/matchers/doublespeak/double_collection.rb +4 -3
  57. data/lib/shoulda/matchers/doublespeak/method_call.rb +35 -0
  58. data/lib/shoulda/matchers/doublespeak/object_double.rb +7 -2
  59. data/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +4 -3
  60. data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +3 -3
  61. data/lib/shoulda/matchers/doublespeak/world.rb +21 -1
  62. data/lib/shoulda/matchers/integrations.rb +43 -0
  63. data/lib/shoulda/matchers/integrations/configuration.rb +68 -0
  64. data/lib/shoulda/matchers/integrations/configuration_error.rb +9 -0
  65. data/lib/shoulda/matchers/integrations/inclusion.rb +20 -0
  66. data/lib/shoulda/matchers/integrations/libraries.rb +15 -0
  67. data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +31 -0
  68. data/lib/shoulda/matchers/integrations/libraries/active_model.rb +26 -0
  69. data/lib/shoulda/matchers/integrations/libraries/active_record.rb +26 -0
  70. data/lib/shoulda/matchers/integrations/libraries/missing_library.rb +19 -0
  71. data/lib/shoulda/matchers/integrations/libraries/rails.rb +30 -0
  72. data/lib/shoulda/matchers/integrations/rails.rb +12 -0
  73. data/lib/shoulda/matchers/integrations/registry.rb +28 -0
  74. data/lib/shoulda/matchers/integrations/test_frameworks.rb +16 -0
  75. data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +37 -0
  76. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +36 -0
  77. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +37 -0
  78. data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +40 -0
  79. data/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +29 -0
  80. data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +36 -0
  81. data/lib/shoulda/matchers/rails_shim.rb +0 -40
  82. data/lib/shoulda/matchers/version.rb +1 -1
  83. data/script/SUPPORTED_VERSIONS +1 -1
  84. data/script/update_gems_in_all_appraisals +14 -0
  85. data/shoulda-matchers.gemspec +2 -2
  86. data/spec/acceptance/active_model_integration_spec.rb +4 -1
  87. data/spec/acceptance/independent_matchers_spec.rb +6 -6
  88. data/spec/acceptance/multiple_libraries_integration_spec.rb +52 -0
  89. data/spec/acceptance/rails_integration_spec.rb +15 -5
  90. data/spec/acceptance_spec_helper.rb +8 -0
  91. data/spec/doublespeak_spec_helper.rb +14 -0
  92. data/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +110 -0
  93. data/spec/support/acceptance/helpers.rb +2 -0
  94. data/spec/support/acceptance/helpers/base_helpers.rb +6 -1
  95. data/spec/support/acceptance/helpers/command_helpers.rb +6 -2
  96. data/spec/support/acceptance/helpers/minitest_helpers.rb +0 -8
  97. data/spec/support/acceptance/helpers/n_unit_helpers.rb +25 -0
  98. data/spec/support/acceptance/helpers/rspec_helpers.rb +2 -0
  99. data/spec/support/acceptance/helpers/step_helpers.rb +13 -19
  100. data/spec/support/acceptance/matchers/have_output.rb +1 -1
  101. data/spec/support/tests/bundle.rb +1 -1
  102. data/spec/support/tests/command_runner.rb +25 -13
  103. data/spec/support/tests/current_bundle.rb +47 -0
  104. data/spec/support/tests/database.rb +28 -0
  105. data/spec/support/tests/database_adapters/postgresql.rb +25 -0
  106. data/spec/support/tests/database_adapters/sqlite3.rb +26 -0
  107. data/spec/support/tests/database_configuration.rb +33 -0
  108. data/spec/support/tests/database_configuration_registry.rb +28 -0
  109. data/spec/support/tests/filesystem.rb +25 -2
  110. data/spec/support/unit/helpers/active_record_versions.rb +12 -0
  111. data/spec/support/unit/helpers/class_builder.rb +6 -2
  112. data/spec/support/unit/helpers/column_type_helpers.rb +26 -0
  113. data/spec/support/unit/helpers/controller_builder.rb +0 -28
  114. data/spec/support/unit/helpers/database_helpers.rb +18 -0
  115. data/spec/support/unit/helpers/model_builder.rb +38 -6
  116. data/spec/support/unit/helpers/rails_versions.rb +2 -2
  117. data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +9 -8
  118. data/spec/support/unit/matchers/fail_with_message_matcher.rb +1 -1
  119. data/spec/support/unit/rails_application.rb +29 -13
  120. data/spec/support/unit/record_validating_confirmation_builder.rb +1 -2
  121. data/spec/support/unit/shared_examples/set_session_or_flash.rb +355 -0
  122. data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +433 -0
  123. data/spec/unit/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +1 -5
  124. data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +37 -0
  125. data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +23 -147
  126. data/spec/unit/shoulda/matchers/action_controller/set_session_matcher_spec.rb +8 -285
  127. data/spec/unit/shoulda/matchers/action_controller/set_session_or_flash_matcher_spec.rb +562 -0
  128. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +81 -14
  129. data/spec/unit/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +16 -8
  130. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +101 -9
  131. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +39 -1
  132. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +39 -1
  133. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +39 -0
  134. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +0 -17
  135. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +0 -17
  136. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +0 -17
  137. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +838 -271
  138. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +0 -19
  139. data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +93 -0
  140. data/spec/unit/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +3 -3
  141. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +25 -0
  142. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +905 -0
  143. data/spec/unit/shoulda/matchers/doublespeak/double_collection_spec.rb +17 -11
  144. data/spec/unit/shoulda/matchers/doublespeak/double_implementation_registry_spec.rb +1 -1
  145. data/spec/unit/shoulda/matchers/doublespeak/double_spec.rb +144 -43
  146. data/spec/unit/shoulda/matchers/doublespeak/object_double_spec.rb +1 -1
  147. data/spec/unit/shoulda/matchers/doublespeak/proxy_implementation_spec.rb +36 -11
  148. data/spec/unit/shoulda/matchers/doublespeak/stub_implementation_spec.rb +29 -16
  149. data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +8 -5
  150. data/spec/unit/shoulda/matchers/doublespeak_spec.rb +1 -1
  151. data/spec/unit_spec_helper.rb +15 -14
  152. data/spec/warnings_spy.rb +1 -1
  153. metadata +68 -29
  154. data/docs.watchr +0 -5
  155. data/gemfiles/3.0.gemfile +0 -26
  156. data/gemfiles/3.0.gemfile.lock +0 -173
  157. data/gemfiles/3.1.gemfile +0 -32
  158. data/gemfiles/3.1.gemfile.lock +0 -212
  159. data/gemfiles/3.1_1.9.2.gemfile +0 -32
  160. data/gemfiles/3.1_1.9.2.gemfile.lock +0 -212
  161. data/gemfiles/3.2.gemfile +0 -33
  162. data/gemfiles/3.2.gemfile.lock +0 -212
  163. data/gemfiles/3.2_1.9.2.gemfile +0 -31
  164. data/gemfiles/3.2_1.9.2.gemfile.lock +0 -207
  165. data/lib/shoulda/matchers/assertion_error.rb +0 -27
  166. data/lib/shoulda/matchers/doublespeak/structs.rb +0 -10
  167. data/lib/shoulda/matchers/integrations/nunit_test_case_detection.rb +0 -39
  168. data/lib/shoulda/matchers/integrations/rspec.rb +0 -19
  169. data/lib/shoulda/matchers/integrations/test_unit.rb +0 -34
  170. data/spec/unit/shoulda/matchers/action_controller/strong_parameters_matcher_spec.rb +0 -331
  171. data/spec/unit/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +0 -564
@@ -0,0 +1,47 @@
1
+ require 'bundler'
2
+ require 'appraisal'
3
+
4
+ module Tests
5
+ class CurrentBundle
6
+ AppraisalNotSpecified = Class.new(ArgumentError)
7
+
8
+ include Singleton
9
+
10
+ def assert_appraisal!
11
+ unless appraisal?
12
+ message = <<EOT
13
+
14
+
15
+ Please run tests starting with `appraisal <appraisal_name>`.
16
+ Possible appraisals are: #{possible_appraisals}
17
+
18
+ EOT
19
+ raise AppraisalNotSpecified, message
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def possible_appraisals
26
+ appraisals = []
27
+
28
+ Appraisal::File.each do |appraisal|
29
+ appraisals << appraisal.name
30
+ end
31
+
32
+ appraisals
33
+ end
34
+
35
+ def path
36
+ Bundler.default_gemfile
37
+ end
38
+
39
+ def appraisal?
40
+ path.dirname == root.join('gemfiles')
41
+ end
42
+
43
+ def root
44
+ Pathname.new('../../../..').expand_path(__FILE__)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,28 @@
1
+ require_relative 'database_configuration'
2
+
3
+ module Tests
4
+ class Database
5
+ NAME = 'shoulda-matchers-test'
6
+ ADAPTER_NAME = ENV.fetch('DATABASE_ADAPTER', 'sqlite3').to_sym
7
+
8
+ include Singleton
9
+
10
+ attr_reader :config
11
+
12
+ def initialize
13
+ @config = Tests::DatabaseConfiguration.for(NAME, ADAPTER_NAME)
14
+ end
15
+
16
+ def name
17
+ config.database
18
+ end
19
+
20
+ def adapter_name
21
+ config.adapter
22
+ end
23
+
24
+ def adapter_class
25
+ config.adapter_class
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ module Tests
2
+ module DatabaseAdapters
3
+ class PostgreSQL
4
+ def self.name
5
+ :postgresql
6
+ end
7
+
8
+ attr_reader :database
9
+
10
+ def initialize(database)
11
+ @database = database
12
+ end
13
+
14
+ def adapter
15
+ self.class.name
16
+ end
17
+
18
+ def require_dependencies
19
+ require 'pg'
20
+ end
21
+ end
22
+
23
+ DatabaseConfigurationRegistry.instance.register(PostgreSQL)
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ module Tests
2
+ module DatabaseAdapters
3
+ class SQLite3
4
+ def self.name
5
+ :sqlite3
6
+ end
7
+
8
+ def initialize(_database)
9
+ end
10
+
11
+ def adapter
12
+ self.class.name
13
+ end
14
+
15
+ def database
16
+ 'db/db.sqlite3'
17
+ end
18
+
19
+ def require_dependencies
20
+ require 'sqlite3'
21
+ end
22
+ end
23
+
24
+ DatabaseConfigurationRegistry.instance.register(SQLite3)
25
+ end
26
+ end
@@ -0,0 +1,33 @@
1
+ require_relative 'database_configuration_registry'
2
+ require 'delegate'
3
+
4
+ module Tests
5
+ class DatabaseConfiguration < SimpleDelegator
6
+ ENVIRONMENTS = %w(development test production)
7
+
8
+ attr_reader :adapter_class
9
+
10
+ def self.for(database_name, adapter_name)
11
+ config_class = DatabaseConfigurationRegistry.instance.get(adapter_name)
12
+ config = config_class.new(database_name)
13
+ new(config)
14
+ end
15
+
16
+ def initialize(config)
17
+ @adapter_class = config.class.to_s.split('::').last
18
+ super(config)
19
+ end
20
+
21
+ def to_hash
22
+ ENVIRONMENTS.each_with_object({}) do |env, config_as_hash|
23
+ config_as_hash[env] = inner_config_as_hash
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def inner_config_as_hash
30
+ { 'adapter' => adapter.to_s, 'database' => database.to_s }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ require 'singleton'
2
+
3
+ module Tests
4
+ class DatabaseConfigurationRegistry
5
+ include Singleton
6
+
7
+ def initialize
8
+ @registry = {}
9
+ end
10
+
11
+ def register(config_class)
12
+ registry[config_class.name] = config_class
13
+ end
14
+
15
+ def get(name)
16
+ registry.fetch(name) do
17
+ raise KeyError, "No such adapter registered: #{name}"
18
+ end
19
+ end
20
+
21
+ protected
22
+
23
+ attr_reader :registry
24
+ end
25
+ end
26
+
27
+ require_relative 'database_adapters/postgresql'
28
+ require_relative 'database_adapters/sqlite3'
@@ -69,9 +69,32 @@ module Tests
69
69
  end
70
70
 
71
71
  def remove_from_file(path, pattern)
72
+ unless pattern.is_a?(Regexp)
73
+ pattern = Regexp.new('^' + Regexp.escape(pattern) + '$')
74
+ end
75
+
76
+ transform(path) do |lines|
77
+ lines.reject { |line| line =~ pattern }
78
+ end
79
+ end
80
+
81
+ def comment_lines_matching(path, pattern)
82
+ transform(path) do |lines|
83
+ lines.map do |line|
84
+ if line =~ pattern
85
+ "###{line}"
86
+ else
87
+ line
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ def transform(path)
72
94
  content = read(path)
73
- content.sub!(/#{pattern}\n/, '')
74
- write(path, content)
95
+ lines = content.split(/\n/)
96
+ transformed_lines = yield lines
97
+ write(path, transformed_lines.join("\n") + "\n")
75
98
  end
76
99
  end
77
100
  end
@@ -12,5 +12,17 @@ module UnitTests
12
12
  def active_record_can_raise_range_error?
13
13
  active_record_version >= 4.2
14
14
  end
15
+
16
+ def active_record_supports_enum?
17
+ defined?(::ActiveRecord::Enum)
18
+ end
19
+
20
+ def active_record_supports_has_secure_password?
21
+ active_record_version >= 3.1
22
+ end
23
+
24
+ def active_record_supports_array_columns?
25
+ active_record_version > 4.2
26
+ end
15
27
  end
16
28
  end
@@ -57,8 +57,12 @@ module UnitTests
57
57
  namespace.const_get(name_without_namespace).tap do |constant|
58
58
  constant.unloadable
59
59
 
60
- if block_given?
61
- constant.class_eval(&block)
60
+ if block
61
+ if block.arity == 0
62
+ constant.class_eval(&block)
63
+ else
64
+ block.call(constant)
65
+ end
62
66
  end
63
67
  end
64
68
  end
@@ -0,0 +1,26 @@
1
+ module UnitTests
2
+ module ColumnTypeHelpers
3
+ def self.configure_example_group(example_group)
4
+ example_group.include(self)
5
+ end
6
+
7
+ def column_type_class_namespace
8
+ if database_adapter == :postgresql
9
+ ActiveRecord::ConnectionAdapters::PostgreSQL
10
+ else
11
+ ActiveRecord::Type
12
+ end
13
+ end
14
+
15
+ def column_type_class_for(type)
16
+ namespace =
17
+ if type == :integer && database_adapter == :postgresql
18
+ column_type_class_namespace::OID
19
+ else
20
+ column_type_class_namespace
21
+ end
22
+
23
+ namespace.const_get(type.to_s.camelize)
24
+ end
25
+ end
26
+ end
@@ -52,34 +52,6 @@ module UnitTests
52
52
  $test_app.create_temp_view(path, contents)
53
53
  end
54
54
 
55
- def controller_for_resource_with_strong_parameters(options = {}, &action_body)
56
- model_name = options.fetch(:model_name, 'User')
57
- controller_name = options.fetch(:controller_name, 'UsersController')
58
- collection_name = controller_name.
59
- to_s.sub(/Controller$/, '').underscore.
60
- to_sym
61
- action_name = options.fetch(:action, :some_action)
62
- routes ||= options.fetch(:routes, -> { resources collection_name })
63
-
64
- define_model(model_name)
65
-
66
- controller_class = define_controller(controller_name) do
67
- define_method action_name do
68
- if action_body
69
- instance_eval(&action_body)
70
- end
71
-
72
- render nothing: true
73
- end
74
- end
75
-
76
- setup_rails_controller_test(controller_class)
77
-
78
- define_routes(&routes)
79
-
80
- controller_class
81
- end
82
-
83
55
  def delete_temporary_views
84
56
  $test_app.delete_temp_views
85
57
  end
@@ -0,0 +1,18 @@
1
+ module UnitTests
2
+ module DatabaseHelpers
3
+ def self.configure_example_group(example_group)
4
+ example_group.include(self)
5
+ example_group.extend(self)
6
+ end
7
+
8
+ def database_adapter
9
+ Tests::Database.instance.adapter_name
10
+ end
11
+
12
+ def database_supports_uuid_columns?
13
+ database_adapter == :postgresql
14
+ end
15
+ alias_method :database_supports_array_columns?,
16
+ :database_supports_uuid_columns?
17
+ end
18
+ end
@@ -32,10 +32,18 @@ module UnitTests
32
32
  end
33
33
 
34
34
  def define_active_model_class(class_name, options = {}, &block)
35
+ accessors = options.fetch(:accessors, [])
36
+
35
37
  define_class(class_name) do
36
38
  include ActiveModel::Validations
37
39
 
38
- options[:accessors].each do |column|
40
+ def initialize(attributes = {})
41
+ attributes.each do |name, value|
42
+ __send__("#{name}=", value)
43
+ end
44
+ end
45
+
46
+ accessors.each do |column|
39
47
  attr_accessor column.to_sym
40
48
  end
41
49
 
@@ -52,9 +60,17 @@ module UnitTests
52
60
  table_block = lambda do |table|
53
61
  columns.each do |column_name, specification|
54
62
  if specification.is_a?(Hash)
55
- table.column column_name, specification[:type], specification[:options]
63
+ column_type = specification[:type]
64
+ column_options = specification.fetch(:options, {})
56
65
  else
57
- table.column column_name, specification
66
+ column_type = specification
67
+ column_options = {}
68
+ end
69
+
70
+ begin
71
+ table.__send__(column_type, column_name, column_options)
72
+ rescue NoMethodError
73
+ raise NoMethodError, "#{Tests::Database.instance.adapter_class} does not support :#{column_type} columns"
58
74
  end
59
75
  end
60
76
  end
@@ -66,13 +82,21 @@ module UnitTests
66
82
  create_table(table_name, &table_block)
67
83
  end
68
84
 
69
- define_model_class(class_name).tap do |model|
85
+ model = define_model_class(class_name).tap do |m|
70
86
  if block
71
- model.class_eval(&block)
87
+ if block.arity == 0
88
+ m.class_eval(&block)
89
+ else
90
+ block.call(m)
91
+ end
72
92
  end
73
93
 
74
- model.table_name = table_name
94
+ m.table_name = table_name
75
95
  end
96
+
97
+ defined_models << model
98
+
99
+ model
76
100
  end
77
101
 
78
102
  private
@@ -85,6 +109,10 @@ module UnitTests
85
109
  elsif ActiveRecord::Base.connection_pool.respond_to?(:clear_cache!)
86
110
  ActiveRecord::Base.connection_pool.clear_cache!
87
111
  end
112
+
113
+ defined_models.each do |model|
114
+ model.reset_column_information
115
+ end
88
116
  end
89
117
 
90
118
  def drop_created_tables
@@ -98,5 +126,9 @@ module UnitTests
98
126
  def created_tables
99
127
  @_created_tables ||= []
100
128
  end
129
+
130
+ def defined_models
131
+ @_defined_models ||= []
132
+ end
101
133
  end
102
134
  end
@@ -21,8 +21,8 @@ module UnitTests
21
21
  rails_version >= 4.1
22
22
  end
23
23
 
24
- def active_record_supports_enum?
25
- defined?(::ActiveRecord::Enum)
24
+ def rails_gte_4_2?
25
+ rails_version >= 4.2
26
26
  end
27
27
  end
28
28
  end
@@ -20,15 +20,17 @@ module UnitTests
20
20
  end
21
21
 
22
22
  def failure_message
23
- msg = "Expectation should have failed with message including '#{expected}'"
23
+ lines = ['Expectation should have failed with message including:']
24
+ lines << Shoulda::Matchers::Util.indent(expected, 2)
24
25
 
25
26
  if @actual
26
- msg << ",\nactually failed with '#{@actual}'"
27
+ lines << 'Actually failed with:'
28
+ lines << Shoulda::Matchers::Util.indent(@actual, 2)
27
29
  else
28
- msg << ", but did not fail."
30
+ lines << 'However, the expectation did not fail.'
29
31
  end
30
32
 
31
- msg
33
+ lines.join("\n")
32
34
  end
33
35
 
34
36
  def failure_message_for_should
@@ -36,10 +38,9 @@ module UnitTests
36
38
  end
37
39
 
38
40
  def failure_message_when_negated
39
- msg = "Expectation should not have failed with message including '#{expected}'"
40
- msg << ", but did."
41
-
42
- msg
41
+ lines = ['Expectation should not have failed with message including:']
42
+ lines << Shoulda::Matchers::Util.indent(expected, 2)
43
+ lines.join("\n")
43
44
  end
44
45
 
45
46
  def failure_message_for_should_not