shoulda-matchers 4.4.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +22 -0
  3. data/README.md +18 -18
  4. data/lib/shoulda/matchers.rb +12 -13
  5. data/lib/shoulda/matchers/action_controller.rb +13 -13
  6. data/lib/shoulda/matchers/action_controller/callback_matcher.rb +4 -89
  7. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +3 -2
  8. data/lib/shoulda/matchers/action_controller/flash_store.rb +2 -4
  9. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +29 -27
  10. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +6 -8
  11. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +6 -8
  12. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +16 -13
  13. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +2 -1
  14. data/lib/shoulda/matchers/action_controller/route_matcher.rb +5 -6
  15. data/lib/shoulda/matchers/action_controller/route_params.rb +1 -1
  16. data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +19 -13
  17. data/lib/shoulda/matchers/active_model.rb +25 -15
  18. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +29 -36
  19. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +1 -1
  20. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +5 -5
  21. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +2 -2
  22. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +1 -1
  23. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +1 -1
  24. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +1 -1
  25. data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +51 -25
  26. data/lib/shoulda/matchers/active_model/helpers.rb +2 -2
  27. data/lib/shoulda/matchers/active_model/numericality_matchers.rb +0 -5
  28. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +32 -34
  29. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +1 -1
  30. data/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +1 -1
  31. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +10 -2
  32. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +2 -2
  33. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +8 -7
  34. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +26 -25
  35. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +6 -6
  36. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +40 -27
  37. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +4 -4
  38. data/lib/shoulda/matchers/active_model/validation_matcher.rb +6 -8
  39. data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +2 -4
  40. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +2 -4
  41. data/lib/shoulda/matchers/active_model/validator.rb +4 -9
  42. data/lib/shoulda/matchers/active_record.rb +26 -14
  43. data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +6 -3
  44. data/lib/shoulda/matchers/active_record/association_matcher.rb +101 -48
  45. data/lib/shoulda/matchers/active_record/association_matchers.rb +0 -12
  46. data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +5 -2
  47. data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +4 -4
  48. data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +1 -1
  49. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +11 -6
  50. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +2 -9
  51. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +12 -7
  52. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +23 -5
  53. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +3 -3
  54. data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +1 -1
  55. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +4 -4
  56. data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +3 -2
  57. data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +7 -5
  58. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +18 -9
  59. data/lib/shoulda/matchers/active_record/have_attached_matcher.rb +46 -8
  60. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +39 -17
  61. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +1 -1
  62. data/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +7 -7
  63. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +12 -10
  64. data/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +11 -7
  65. data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +2 -0
  66. data/lib/shoulda/matchers/active_record/serialize_matcher.rb +13 -9
  67. data/lib/shoulda/matchers/active_record/uniqueness.rb +4 -4
  68. data/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +1 -3
  69. data/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +0 -2
  70. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +78 -71
  71. data/lib/shoulda/matchers/doublespeak.rb +9 -9
  72. data/lib/shoulda/matchers/doublespeak/double.rb +1 -1
  73. data/lib/shoulda/matchers/doublespeak/double_collection.rb +3 -3
  74. data/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +8 -5
  75. data/lib/shoulda/matchers/doublespeak/object_double.rb +1 -1
  76. data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +1 -5
  77. data/lib/shoulda/matchers/doublespeak/world.rb +2 -2
  78. data/lib/shoulda/matchers/error.rb +1 -1
  79. data/lib/shoulda/matchers/independent.rb +1 -0
  80. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +14 -16
  81. data/lib/shoulda/matchers/integrations.rb +6 -6
  82. data/lib/shoulda/matchers/integrations/configuration.rb +1 -1
  83. data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +1 -1
  84. data/lib/shoulda/matchers/integrations/libraries/rails.rb +2 -2
  85. data/lib/shoulda/matchers/integrations/test_frameworks.rb +2 -4
  86. data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +1 -1
  87. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +1 -1
  88. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +1 -1
  89. data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +1 -1
  90. data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +1 -1
  91. data/lib/shoulda/matchers/rails_shim.rb +5 -42
  92. data/lib/shoulda/matchers/util.rb +9 -2
  93. data/lib/shoulda/matchers/util/word_wrap.rb +7 -7
  94. data/lib/shoulda/matchers/version.rb +1 -1
  95. data/lib/shoulda/matchers/warn.rb +3 -3
  96. data/shoulda-matchers.gemspec +12 -9
  97. metadata +14 -14
  98. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +0 -159
@@ -1,3 +1,5 @@
1
+ require 'shoulda/matchers/util/word_wrap'
2
+
1
3
  module Shoulda
2
4
  module Matchers
3
5
  # @private
@@ -5,8 +7,10 @@ module Shoulda
5
7
  MAXIMUM_LENGTH_OF_VALUE_TO_DISPLAY = 500
6
8
 
7
9
  def self.deconstantize(path)
8
- if defined?(ActiveSupport::Inflector) &&
10
+ if (
11
+ defined?(ActiveSupport::Inflector) &&
9
12
  ActiveSupport::Inflector.respond_to?(:deconstantize)
13
+ )
10
14
  ActiveSupport::Inflector.deconstantize(path)
11
15
  else
12
16
  path.to_s[0...(path.to_s.rindex('::') || 0)]
@@ -14,8 +18,10 @@ module Shoulda
14
18
  end
15
19
 
16
20
  def self.safe_constantize(camel_cased_word)
17
- if defined?(ActiveSupport::Inflector) &&
21
+ if (
22
+ defined?(ActiveSupport::Inflector) &&
18
23
  ActiveSupport::Inflector.respond_to?(:safe_constantize)
24
+ )
19
25
  ActiveSupport::Inflector.safe_constantize(camel_cased_word)
20
26
  else
21
27
  begin
@@ -28,6 +34,7 @@ module Shoulda
28
34
 
29
35
  def self.indent(string, width)
30
36
  return if !string
37
+
31
38
  indentation = ' ' * width
32
39
  string.split(/[\n\r]/).map { |line| indentation + line }.join("\n")
33
40
  end
@@ -41,10 +41,10 @@ module Shoulda
41
41
 
42
42
  # @private
43
43
  class Text < ::String
44
- LIST_ITEM_REGEXP = /\A((?:[a-z0-9]+(?:\)|\.)|\*) )/
44
+ LIST_ITEM_REGEXP = /\A((?:[a-z0-9]+(?:\)|\.)|\*) )/.freeze
45
45
 
46
46
  def indented?
47
- self =~ /\A[ ]+/
47
+ self =~ /\A +/
48
48
  end
49
49
 
50
50
  def list_item?
@@ -88,11 +88,11 @@ module Shoulda
88
88
  end
89
89
 
90
90
  def combine_list_item_lines(lines)
91
- lines.reduce([]) do |combined_lines, line|
91
+ lines.inject([]) do |combined_lines, line|
92
92
  if line.list_item?
93
93
  combined_lines << line
94
94
  else
95
- combined_lines.last << (' ' + line).squeeze(' ')
95
+ combined_lines.last << (" #{line}").squeeze(' ')
96
96
  end
97
97
 
98
98
  combined_lines
@@ -114,7 +114,7 @@ module Shoulda
114
114
 
115
115
  # @private
116
116
  class Line
117
- OFFSETS = { left: -1, right: +1 }
117
+ OFFSETS = { left: -1, right: +1 }.freeze
118
118
 
119
119
  def initialize(line, indent: 0)
120
120
  @indent = indent
@@ -169,7 +169,7 @@ module Shoulda
169
169
  end
170
170
  end
171
171
 
172
- def wrap_line(line, direction: :left)
172
+ def wrap_line(line)
173
173
  index = nil
174
174
 
175
175
  if line.length > Shoulda::Matchers::WordWrap::TERMINAL_WIDTH
@@ -185,7 +185,7 @@ module Shoulda
185
185
  leftover = ''
186
186
  else
187
187
  fitted_line = line[0..index].rstrip
188
- leftover = line[index + 1 .. -1]
188
+ leftover = line[index + 1..]
189
189
  end
190
190
 
191
191
  { fitted_line: fitted_line, leftover: leftover }
@@ -1,6 +1,6 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  # @private
4
- VERSION = '4.4.0'.freeze
4
+ VERSION = '5.0.0'.freeze
5
5
  end
6
6
  end
@@ -5,13 +5,13 @@ module Shoulda
5
5
 
6
6
  # @private
7
7
  def self.warn(message)
8
- header = "Warning from shoulda-matchers:"
9
- divider = "*" * TERMINAL_MAX_WIDTH
8
+ header = 'Warning from shoulda-matchers:'
9
+ divider = '*' * TERMINAL_MAX_WIDTH
10
10
  wrapped_message = word_wrap(message)
11
11
  full_message = [
12
12
  divider,
13
13
  [header, wrapped_message.strip].join("\n\n"),
14
- divider
14
+ divider,
15
15
  ].join("\n")
16
16
 
17
17
  Kernel.warn(full_message)
@@ -18,21 +18,24 @@ Gem::Specification.new do |s|
18
18
  s.homepage = 'https://matchers.shoulda.io/'
19
19
  s.summary = 'Simple one-liner tests for common Rails functionality'
20
20
  s.license = 'MIT'
21
- s.description = 'Shoulda Matchers provides RSpec- and Minitest-compatible one-liners to test common Rails functionality that, if written by hand, would be much longer, more complex, and error-prone.'
22
- s.metadata = {
21
+ s.description = <<~DESC.tr("\n", ' ').squeeze(' ')
22
+ Shoulda Matchers provides RSpec- and Minitest-compatible one-liners to test
23
+ common Rails functionality that, if written by hand, would be much
24
+ longer, more complex, and error-prone.
25
+ DESC
26
+
27
+ s.metadata = {
23
28
  'bug_tracker_uri' => 'https://github.com/thoughtbot/shoulda-matchers/issues',
24
- 'changelog_uri' => 'https://github.com/thoughtbot/shoulda-matchers/blob/master/NEWS.md',
29
+ 'changelog_uri' => 'https://github.com/thoughtbot/shoulda-matchers/blob/master/CHANGELOG.md',
25
30
  'documentation_uri' => 'https://matchers.shoulda.io/docs',
26
31
  'homepage_uri' => 'https://matchers.shoulda.io',
27
32
  'source_code_uri' => 'https://github.com/thoughtbot/shoulda-matchers',
28
33
  }
29
34
 
30
- s.files = Dir.chdir(File.expand_path(__dir__)) do
31
- `git ls-files -z -- {docs,lib,README.md,MIT-LICENSE,shoulda-matchers.gemspec}`.
32
- split("\x0")
33
- end
35
+ s.files = Dir['{docs,lib}/**/*', 'README.md', 'LICENSE',
36
+ 'shoulda-matchers.gemspec']
34
37
  s.require_paths = ['lib']
35
38
 
36
- s.required_ruby_version = '>= 2.4.0'
37
- s.add_dependency('activesupport', '>= 4.2.0')
39
+ s.required_ruby_version = '>= 2.6.0'
40
+ s.add_dependency('activesupport', '>= 5.2.0')
38
41
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shoulda-matchers
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tammer Saleh
@@ -11,10 +11,10 @@ authors:
11
11
  - Matt Jankowski
12
12
  - Stafford Brunk
13
13
  - Elliot Winkler
14
- autorequire:
14
+ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2020-08-25 00:00:00.000000000 Z
17
+ date: 2021-07-10 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: activesupport
@@ -22,22 +22,23 @@ dependencies:
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 4.2.0
25
+ version: 5.2.0
26
26
  type: :runtime
27
27
  prerelease: false
28
28
  version_requirements: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 4.2.0
33
- description: Shoulda Matchers provides RSpec- and Minitest-compatible one-liners to
34
- test common Rails functionality that, if written by hand, would be much longer,
35
- more complex, and error-prone.
32
+ version: 5.2.0
33
+ description: 'Shoulda Matchers provides RSpec- and Minitest-compatible one-liners
34
+ to test common Rails functionality that, if written by hand, would be much longer,
35
+ more complex, and error-prone. '
36
36
  email: support@thoughtbot.com
37
37
  executables: []
38
38
  extensions: []
39
39
  extra_rdoc_files: []
40
40
  files:
41
+ - LICENSE
41
42
  - README.md
42
43
  - docs/errors/NonCaseSwappableValueError.md
43
44
  - lib/shoulda-matchers.rb
@@ -59,7 +60,6 @@ files:
59
60
  - lib/shoulda/matchers/action_controller/set_session_matcher.rb
60
61
  - lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb
61
62
  - lib/shoulda/matchers/active_model.rb
62
- - lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb
63
63
  - lib/shoulda/matchers/active_model/allow_value_matcher.rb
64
64
  - lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb
65
65
  - lib/shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error.rb
@@ -173,11 +173,11 @@ licenses:
173
173
  - MIT
174
174
  metadata:
175
175
  bug_tracker_uri: https://github.com/thoughtbot/shoulda-matchers/issues
176
- changelog_uri: https://github.com/thoughtbot/shoulda-matchers/blob/master/NEWS.md
176
+ changelog_uri: https://github.com/thoughtbot/shoulda-matchers/blob/master/CHANGELOG.md
177
177
  documentation_uri: https://matchers.shoulda.io/docs
178
178
  homepage_uri: https://matchers.shoulda.io
179
179
  source_code_uri: https://github.com/thoughtbot/shoulda-matchers
180
- post_install_message:
180
+ post_install_message:
181
181
  rdoc_options: []
182
182
  require_paths:
183
183
  - lib
@@ -185,15 +185,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
185
185
  requirements:
186
186
  - - ">="
187
187
  - !ruby/object:Gem::Version
188
- version: 2.4.0
188
+ version: 2.6.0
189
189
  required_rubygems_version: !ruby/object:Gem::Requirement
190
190
  requirements:
191
191
  - - ">="
192
192
  - !ruby/object:Gem::Version
193
193
  version: '0'
194
194
  requirements: []
195
- rubygems_version: 3.1.2
196
- signing_key:
195
+ rubygems_version: 3.2.15
196
+ signing_key:
197
197
  specification_version: 4
198
198
  summary: Simple one-liner tests for common Rails functionality
199
199
  test_files: []
@@ -1,159 +0,0 @@
1
- module Shoulda
2
- module Matchers
3
- module ActiveModel
4
- # The `allow_mass_assignment_of` matcher tests usage of Rails 3's
5
- # `attr_accessible` and `attr_protected` macros, asserting that an
6
- # attribute in your model is contained in either the whitelist or
7
- # blacklist and thus can or cannot be set via mass assignment.
8
- #
9
- # class Post
10
- # include ActiveModel::Model
11
- # include ActiveModel::MassAssignmentSecurity
12
- # attr_accessor :title
13
- #
14
- # attr_accessible :title
15
- # end
16
- #
17
- # class User
18
- # include ActiveModel::Model
19
- # include ActiveModel::MassAssignmentSecurity
20
- # attr_accessor :encrypted_password
21
- #
22
- # attr_protected :encrypted_password
23
- # end
24
- #
25
- # # RSpec
26
- # RSpec.describe Post, type: :model do
27
- # it { should allow_mass_assignment_of(:title) }
28
- # end
29
- #
30
- # RSpec.describe User, type: :model do
31
- # it { should_not allow_mass_assignment_of(:encrypted_password) }
32
- # end
33
- #
34
- # # Minitest (Shoulda)
35
- # class PostTest < ActiveSupport::TestCase
36
- # should allow_mass_assignment_of(:title)
37
- # end
38
- #
39
- # class UserTest < ActiveSupport::TestCase
40
- # should_not allow_mass_assignment_of(:encrypted_password)
41
- # end
42
- #
43
- # #### Optional qualifiers
44
- #
45
- # ##### as
46
- #
47
- # Use `as` if your mass-assignment rules apply only under a certain role
48
- # *(Rails >= 3.1 only)*.
49
- #
50
- # class Post
51
- # include ActiveModel::Model
52
- # include ActiveModel::MassAssignmentSecurity
53
- # attr_accessor :title
54
- #
55
- # attr_accessible :title, as: :admin
56
- # end
57
- #
58
- # # RSpec
59
- # RSpec.describe Post, type: :model do
60
- # it { should allow_mass_assignment_of(:title).as(:admin) }
61
- # end
62
- #
63
- # # Minitest (Shoulda)
64
- # class PostTest < ActiveSupport::TestCase
65
- # should allow_mass_assignment_of(:title).as(:admin)
66
- # end
67
- #
68
- # @return [AllowMassAssignmentOfMatcher]
69
- #
70
- def allow_mass_assignment_of(value)
71
- AllowMassAssignmentOfMatcher.new(value)
72
- end
73
-
74
- # @private
75
- class AllowMassAssignmentOfMatcher
76
- attr_reader :failure_message, :failure_message_when_negated
77
-
78
- def initialize(attribute)
79
- @attribute = attribute.to_s
80
- @options = {}
81
- end
82
-
83
- def as(role)
84
- @options[:role] = role
85
- self
86
- end
87
-
88
- def matches?(subject)
89
- @subject = subject
90
- if attr_mass_assignable?
91
- if whitelisting?
92
- @failure_message_when_negated = "#{@attribute} was made accessible"
93
- else
94
- if protected_attributes.empty?
95
- @failure_message_when_negated = 'no attributes were protected'
96
- else
97
- @failure_message_when_negated = "#{class_name} is protecting " <<
98
- "#{protected_attributes.to_a.to_sentence}, " <<
99
- "but not #{@attribute}."
100
- end
101
- end
102
- true
103
- else
104
- if whitelisting?
105
- @failure_message = "Expected #{@attribute} to be accessible"
106
- else
107
- @failure_message = "Did not expect #{@attribute} to be protected"
108
- end
109
- false
110
- end
111
- end
112
-
113
- def description
114
- [base_description, role_description].compact.join(' ')
115
- end
116
-
117
- private
118
-
119
- def base_description
120
- "allow mass assignment of #{@attribute}"
121
- end
122
-
123
- def role_description
124
- if role != :default
125
- "as #{role}"
126
- end
127
- end
128
-
129
- def role
130
- @options[:role] || :default
131
- end
132
-
133
- def protected_attributes
134
- @protected_attributes ||= (@subject.class.protected_attributes || [])
135
- end
136
-
137
- def accessible_attributes
138
- @accessible_attributes ||= (@subject.class.accessible_attributes || [])
139
- end
140
-
141
- def whitelisting?
142
- authorizer.kind_of?(::ActiveModel::MassAssignmentSecurity::WhiteList)
143
- end
144
-
145
- def attr_mass_assignable?
146
- !authorizer.deny?(@attribute)
147
- end
148
-
149
- def authorizer
150
- @subject.class.active_authorizer[role]
151
- end
152
-
153
- def class_name
154
- @subject.class.name
155
- end
156
- end
157
- end
158
- end
159
- end