remarkable 3.1.6 → 3.1.7

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/CHANGELOG CHANGED
@@ -1,45 +1,45 @@
1
- # v3.1
2
-
3
- * Remarkable.include_matchers! require just one argument [#80]
4
-
5
- * Pending groups show proper backtrace and run by default in execute mode [#49]
6
-
7
- * Added support to blocks configuration. All Remarkable matcher and macros can
8
- now be configured using a block:
9
-
10
- should_accept_nested_attributes_for :tasks do |m|
11
- m.allow_destroy
12
- m.accept(:name => 'cool')
13
- m.reject(:name => '')
14
- end
15
-
16
- * Added support to {{sentence}} as interpolation option in optionals.
17
- Previously we had:
18
-
19
- validate_uniqueness_of :id, :scope => [:project_id, :company_id]
20
- # Description: "should require unique attributes for id scoped to [:project_id, :company_id]"
21
-
22
- Now with the new sentence option, we can have:
23
-
24
- validate_uniqueness_of :id, :scope => [:project_id, :company_id]
25
- # Description: "should require unique attributes for id scoped to project_id and company_id"
26
-
27
- * Added support to splat and block to optionals
28
-
29
- * Added namespace lookup to optionals and expectations. For example, in ActiveRecord
30
- several matchers have :allow_nil and :allow_blank as options. So you can store
31
- the translation at:
32
-
33
- remarkable:
34
- activerecord:
35
- optionals:
36
- allow_nil:
37
- # ...
38
- allow_blank:
39
- # ...
40
-
41
- * Added a repository to hold I18n files
42
-
1
+ # v3.1
2
+
3
+ * Remarkable.include_matchers! require just one argument [#80]
4
+
5
+ * Pending groups show proper backtrace and run by default in execute mode [#49]
6
+
7
+ * Added support to blocks configuration. All Remarkable matcher and macros can
8
+ now be configured using a block:
9
+
10
+ should_accept_nested_attributes_for :tasks do |m|
11
+ m.allow_destroy
12
+ m.accept(:name => 'cool')
13
+ m.reject(:name => '')
14
+ end
15
+
16
+ * Added support to {{sentence}} as interpolation option in optionals.
17
+ Previously we had:
18
+
19
+ validate_uniqueness_of :id, :scope => [:project_id, :company_id]
20
+ # Description: "should require unique attributes for id scoped to [:project_id, :company_id]"
21
+
22
+ Now with the new sentence option, we can have:
23
+
24
+ validate_uniqueness_of :id, :scope => [:project_id, :company_id]
25
+ # Description: "should require unique attributes for id scoped to project_id and company_id"
26
+
27
+ * Added support to splat and block to optionals
28
+
29
+ * Added namespace lookup to optionals and expectations. For example, in ActiveRecord
30
+ several matchers have :allow_nil and :allow_blank as options. So you can store
31
+ the translation at:
32
+
33
+ remarkable:
34
+ activerecord:
35
+ optionals:
36
+ allow_nil:
37
+ # ...
38
+ allow_blank:
39
+ # ...
40
+
41
+ * Added a repository to hold I18n files
42
+
43
43
  # v3.0
44
44
 
45
45
  * Added Remarkable::Matchers. Now you can include your Remarkable matchers and
@@ -1,6 +1,6 @@
1
- module Remarkable
2
- # This class holds the basic structure for Remarkable matchers. All matchers
3
- # must inherit from it.
1
+ module Remarkable
2
+ # This class holds the basic structure for Remarkable matchers. All matchers
3
+ # must inherit from it.
4
4
  class Base
5
5
  include Remarkable::Messages
6
6
  extend Remarkable::DSL
@@ -1,119 +1,119 @@
1
1
  module Remarkable
2
- module DSL
3
- # This module is responsable to create a basic matcher structure using a DSL.
4
- #
5
- # A matcher that checks if an element is included in an array can be done
6
- # just with:
7
- #
8
- # class IncludedMatcher < Remarkable::Base
9
- # arguments :value
10
- # assertion :is_included?
11
- #
12
- # protected
13
- # def is_included?
14
- # @subject.include?(@value)
15
- # end
16
- # end
17
- #
18
- # As you have noticed, the DSL also allows you to remove the messages from
19
- # matcher. Since it will look for it on I18n yml file.
20
- #
21
- # If you want to create a matcher that accepts multile values to be tested,
22
- # you just need to do:
23
- #
24
- # class IncludedMatcher < Remarkable::Base
25
- # arguments :collection => :values, :as => :value
26
- # collection_assertion :is_included?
27
- #
28
- # protected
29
- # def is_included?
30
- # @subject.include?(@value)
31
- # end
32
- # end
33
- #
34
- # Notice that the :is_included? logic didn't have to change, because Remarkable
35
- # handle this automatically for you.
2
+ module DSL
3
+ # This module is responsable to create a basic matcher structure using a DSL.
36
4
  #
37
- module Assertions
38
-
39
- def self.included(base) # :nodoc:
40
- base.extend ClassMethods
5
+ # A matcher that checks if an element is included in an array can be done
6
+ # just with:
7
+ #
8
+ # class IncludedMatcher < Remarkable::Base
9
+ # arguments :value
10
+ # assertion :is_included?
11
+ #
12
+ # protected
13
+ # def is_included?
14
+ # @subject.include?(@value)
15
+ # end
16
+ # end
17
+ #
18
+ # As you have noticed, the DSL also allows you to remove the messages from
19
+ # matcher. Since it will look for it on I18n yml file.
20
+ #
21
+ # If you want to create a matcher that accepts multile values to be tested,
22
+ # you just need to do:
23
+ #
24
+ # class IncludedMatcher < Remarkable::Base
25
+ # arguments :collection => :values, :as => :value
26
+ # collection_assertion :is_included?
27
+ #
28
+ # protected
29
+ # def is_included?
30
+ # @subject.include?(@value)
31
+ # end
32
+ # end
33
+ #
34
+ # Notice that the :is_included? logic didn't have to change, because Remarkable
35
+ # handle this automatically for you.
36
+ #
37
+ module Assertions
38
+
39
+ def self.included(base) # :nodoc:
40
+ base.extend ClassMethods
41
41
  end
42
-
43
- module ClassMethods
42
+
43
+ module ClassMethods
44
44
 
45
45
  protected
46
46
 
47
- # It sets the arguments your matcher receives on initialization.
48
- #
47
+ # It sets the arguments your matcher receives on initialization.
48
+ #
49
49
  # == Options
50
- #
51
- # * <tt>:collection</tt> - if a collection is expected.
52
- # * <tt>:as</tt> - how each item of the collection will be available.
53
- # * <tt>:block</tt> - tell the matcher can receive blocks as argument and store
54
- # them under the variable given.
55
- #
56
- # Note: the expected block cannot have arity 1. This is already reserved
57
- # for macro configuration.
58
- #
59
- # == Examples
60
- #
61
- # Let's see for each example how the arguments declarion reflects on
62
- # the matcher API:
63
- #
64
- # arguments :assign
65
- # # Can be called as:
66
- # #=> should_assign :task
67
- # #=> should_assign :task, :with => Task.new
68
- #
69
- # This is roughly the same as:
70
- #
50
+ #
51
+ # * <tt>:collection</tt> - if a collection is expected.
52
+ # * <tt>:as</tt> - how each item of the collection will be available.
53
+ # * <tt>:block</tt> - tell the matcher can receive blocks as argument and store
54
+ # them under the variable given.
55
+ #
56
+ # Note: the expected block cannot have arity 1. This is already reserved
57
+ # for macro configuration.
58
+ #
59
+ # == Examples
60
+ #
61
+ # Let's see for each example how the arguments declarion reflects on
62
+ # the matcher API:
63
+ #
64
+ # arguments :assign
65
+ # # Can be called as:
66
+ # #=> should_assign :task
67
+ # #=> should_assign :task, :with => Task.new
68
+ #
69
+ # This is roughly the same as:
70
+ #
71
71
  # def initialize(assign, options = {})
72
72
  # @assign = name
73
73
  # @options = options
74
- # end
75
- #
76
- # As you noticed, a matcher can always receive options on initialization.
77
- # If you have a matcher that accepts only options, for example,
78
- # have_default_scope you just need to call <tt>arguments</tt>:
79
- #
80
- # arguments
81
- # # Can be called as:
82
- # #=> should_have_default_scope :limit => 10
83
- #
84
- # arguments :collection => :assigns, :as => :assign
85
- # # Can be called as:
86
- # #=> should_assign :task1, :task2
87
- # #=> should_assign :task1, :task2, :with => Task.new
88
- #
89
- # arguments :collection => :assigns, :as => :assign, :block => :buildeer
90
- # # Can be called as:
91
- # #=> should_assign :task1, :task2
92
- # #=> should_assign(:task1, :task2){ Task.new }
93
- #
94
- # The block will be available under the instance variable @builder.
95
- #
96
- # == I18n
97
- #
98
- # All the parameters given to arguments are available for interpolation
99
- # in I18n. So if you have the following declarion:
100
- #
101
- # class InRange < Remarkable::Base
102
- # arguments :range, :collection => :names, :as => :name
103
- #
104
- # You will have {{range}}, {{names}} and {{name}} available for I18n
105
- # messages:
106
- #
107
- # in_range:
108
- # description: "have {{names}} to be on range {{range}}"
109
- #
110
- # Before a collection is sent to I18n, it's transformed to a sentence.
111
- # So if the following matcher:
112
- #
113
- # in_range(2..20, :username, :password)
114
- #
115
- # Has the following description:
116
- #
74
+ # end
75
+ #
76
+ # As you noticed, a matcher can always receive options on initialization.
77
+ # If you have a matcher that accepts only options, for example,
78
+ # have_default_scope you just need to call <tt>arguments</tt>:
79
+ #
80
+ # arguments
81
+ # # Can be called as:
82
+ # #=> should_have_default_scope :limit => 10
83
+ #
84
+ # arguments :collection => :assigns, :as => :assign
85
+ # # Can be called as:
86
+ # #=> should_assign :task1, :task2
87
+ # #=> should_assign :task1, :task2, :with => Task.new
88
+ #
89
+ # arguments :collection => :assigns, :as => :assign, :block => :buildeer
90
+ # # Can be called as:
91
+ # #=> should_assign :task1, :task2
92
+ # #=> should_assign(:task1, :task2){ Task.new }
93
+ #
94
+ # The block will be available under the instance variable @builder.
95
+ #
96
+ # == I18n
97
+ #
98
+ # All the parameters given to arguments are available for interpolation
99
+ # in I18n. So if you have the following declarion:
100
+ #
101
+ # class InRange < Remarkable::Base
102
+ # arguments :range, :collection => :names, :as => :name
103
+ #
104
+ # You will have {{range}}, {{names}} and {{name}} available for I18n
105
+ # messages:
106
+ #
107
+ # in_range:
108
+ # description: "have {{names}} to be on range {{range}}"
109
+ #
110
+ # Before a collection is sent to I18n, it's transformed to a sentence.
111
+ # So if the following matcher:
112
+ #
113
+ # in_range(2..20, :username, :password)
114
+ #
115
+ # Has the following description:
116
+ #
117
117
  # "should have username and password in range 2..20"
118
118
  #
119
119
  def arguments(*names)
@@ -140,14 +140,14 @@ module Remarkable
140
140
  set_collection = ''
141
141
  end
142
142
 
143
- if block = options.delete(:block)
144
- block = :block unless block.is_a?(Symbol)
143
+ if block = options.delete(:block)
144
+ block = :block unless block.is_a?(Symbol)
145
145
  @matcher_arguments[:block] = block
146
- end
147
-
148
- # Blocks are always appended. If they have arity 1, they are used for
149
- # macro configuration, otherwise, they are stored in the :block variable.
150
- #
146
+ end
147
+
148
+ # Blocks are always appended. If they have arity 1, they are used for
149
+ # macro configuration, otherwise, they are stored in the :block variable.
150
+ #
151
151
  args << "&block"
152
152
 
153
153
  assignments = names.map do |name|
@@ -155,111 +155,111 @@ module Remarkable
155
155
  end.join("\n ")
156
156
 
157
157
  class_eval <<-END, __FILE__, __LINE__
158
- def initialize(#{args.join(',')})
159
- _builder, block = block, nil if block && block.arity == 1
160
- #{assignments}
158
+ def initialize(#{args.join(',')})
159
+ _builder, block = block, nil if block && block.arity == 1
160
+ #{assignments}
161
161
  #{"@#{block} = block" if block}
162
162
  @options = default_options.merge(#{get_options})
163
- #{set_collection}
164
- run_after_initialize_callbacks
163
+ #{set_collection}
164
+ run_after_initialize_callbacks
165
165
  _builder.call(self) if _builder
166
166
  end
167
167
  END
168
168
  end
169
169
 
170
- # Declare the assertions that are runned for each element in the collection.
171
- # It must be used with <tt>arguments</tt> methods in order to work properly.
172
- #
173
- # == Examples
174
- #
175
- # The example given in <tt>assertions</tt> can be transformed to
176
- # accept a collection just doing:
177
- #
178
- # class IncludedMatcher < Remarkable::Base
179
- # arguments :collection => :values, :as => :value
180
- # collection_assertion :is_included?
181
- #
182
- # protected
183
- # def is_included?
184
- # @subject.include?(@value)
185
- # end
186
- # end
187
- #
188
- # All further consideration done in <tt>assertions</tt> are also valid here.
189
- #
170
+ # Declare the assertions that are runned for each element in the collection.
171
+ # It must be used with <tt>arguments</tt> methods in order to work properly.
172
+ #
173
+ # == Examples
174
+ #
175
+ # The example given in <tt>assertions</tt> can be transformed to
176
+ # accept a collection just doing:
177
+ #
178
+ # class IncludedMatcher < Remarkable::Base
179
+ # arguments :collection => :values, :as => :value
180
+ # collection_assertion :is_included?
181
+ #
182
+ # protected
183
+ # def is_included?
184
+ # @subject.include?(@value)
185
+ # end
186
+ # end
187
+ #
188
+ # All further consideration done in <tt>assertions</tt> are also valid here.
189
+ #
190
190
  def collection_assertions(*methods, &block)
191
191
  define_method methods.last, &block if block_given?
192
192
  @matcher_collection_assertions += methods
193
193
  end
194
194
  alias :collection_assertion :collection_assertions
195
195
 
196
- # Declares the assertions that are run once per matcher.
197
- #
198
- # == Examples
199
- #
200
- # A matcher that checks if an element is included in an array can be done
201
- # just with:
202
- #
203
- # class IncludedMatcher < Remarkable::Base
204
- # arguments :value
205
- # assertion :is_included?
206
- #
207
- # protected
208
- # def is_included?
209
- # @subject.include?(@value)
210
- # end
211
- # end
212
- #
213
- # Whenever the matcher is called, the :is_included? action is automatically
214
- # triggered. Each assertion must return true or false. In case it's false
215
- # it will seach for an expectation message on the I18n file. In this
216
- # case, the error message would be on:
217
- #
218
- # included:
219
- # description: "check {{value}} is included in the array"
220
- # expectations:
221
- # is_included: "{{value}} is included in the array"
222
- #
223
- # In case of failure, it will output:
224
- #
225
- # "Expected {{value}} is included in the array"
226
- #
227
- # Notice that on the yml file the question mark is removed for readability.
228
- #
229
- # == Shortcut declaration
230
- #
231
- # You can shortcut declaration by giving a name and block to assertion
232
- # method:
233
- #
234
- # class IncludedMatcher < Remarkable::Base
235
- # arguments :value
236
- #
237
- # assertion :is_included? do
238
- # @subject.include?(@value)
239
- # end
240
- # end
241
- #
242
- def assertions(*methods, &block)
196
+ # Declares the assertions that are run once per matcher.
197
+ #
198
+ # == Examples
199
+ #
200
+ # A matcher that checks if an element is included in an array can be done
201
+ # just with:
202
+ #
203
+ # class IncludedMatcher < Remarkable::Base
204
+ # arguments :value
205
+ # assertion :is_included?
206
+ #
207
+ # protected
208
+ # def is_included?
209
+ # @subject.include?(@value)
210
+ # end
211
+ # end
212
+ #
213
+ # Whenever the matcher is called, the :is_included? action is automatically
214
+ # triggered. Each assertion must return true or false. In case it's false
215
+ # it will seach for an expectation message on the I18n file. In this
216
+ # case, the error message would be on:
217
+ #
218
+ # included:
219
+ # description: "check {{value}} is included in the array"
220
+ # expectations:
221
+ # is_included: "{{value}} is included in the array"
222
+ #
223
+ # In case of failure, it will output:
224
+ #
225
+ # "Expected {{value}} is included in the array"
226
+ #
227
+ # Notice that on the yml file the question mark is removed for readability.
228
+ #
229
+ # == Shortcut declaration
230
+ #
231
+ # You can shortcut declaration by giving a name and block to assertion
232
+ # method:
233
+ #
234
+ # class IncludedMatcher < Remarkable::Base
235
+ # arguments :value
236
+ #
237
+ # assertion :is_included? do
238
+ # @subject.include?(@value)
239
+ # end
240
+ # end
241
+ #
242
+ def assertions(*methods, &block)
243
243
  if block_given?
244
- define_method methods.last, &block
245
- protected methods.last
246
- end
244
+ define_method methods.last, &block
245
+ protected methods.last
246
+ end
247
247
 
248
248
  @matcher_single_assertions += methods
249
249
  end
250
250
  alias :assertion :assertions
251
251
 
252
- # Class method that accepts a block or a hash to set matcher's default
253
- # options. It's called on matcher initialization and stores the default
254
- # value in the @options instance variable.
255
- #
256
- # == Examples
257
- #
258
- # default_options do
259
- # { :name => @subject.name }
260
- # end
261
- #
262
- # default_options :message => :invalid
252
+ # Class method that accepts a block or a hash to set matcher's default
253
+ # options. It's called on matcher initialization and stores the default
254
+ # value in the @options instance variable.
255
+ #
256
+ # == Examples
257
+ #
258
+ # default_options do
259
+ # { :name => @subject.name }
260
+ # end
261
+ #
262
+ # default_options :message => :invalid
263
263
  #
264
264
  def default_options(hash = {}, &block)
265
265
  if block_given?
@@ -267,15 +267,15 @@ module Remarkable
267
267
  else
268
268
  class_eval "def default_options; #{hash.inspect}; end"
269
269
  end
270
- end
270
+ end
271
271
  end
272
-
272
+
273
273
  # This method is responsable for connecting <tt>arguments</tt>, <tt>assertions</tt>
274
- # and <tt>collection_assertions</tt>.
275
- #
276
- # It's the one that executes the assertions once, executes the collection
277
- # assertions for each element in the collection and also responsable to set
278
- # the I18n messages.
274
+ # and <tt>collection_assertions</tt>.
275
+ #
276
+ # It's the one that executes the assertions once, executes the collection
277
+ # assertions for each element in the collection and also responsable to set
278
+ # the I18n messages.
279
279
  #
280
280
  def matches?(subject)
281
281
  @subject = subject
@@ -291,7 +291,7 @@ module Remarkable
291
291
 
292
292
  protected
293
293
 
294
- # You can overwrite this instance method to provide default options on
294
+ # You can overwrite this instance method to provide default options on
295
295
  # initialization.
296
296
  #
297
297
  def default_options
@@ -368,21 +368,21 @@ module Remarkable
368
368
  methods.each do |method|
369
369
  bool, hash = send(method)
370
370
 
371
- unless bool
372
- parent_scope = matcher_i18n_scope.split('.')
373
- matcher_name = parent_scope.pop
374
- lookup = :"expectations.#{method.to_s.gsub(/(\?|\!)$/, '')}"
375
-
376
- hash = { :scope => parent_scope, :default => lookup }.merge(hash || {})
377
- @expectation ||= Remarkable.t "#{matcher_name}.#{lookup}", default_i18n_options.merge(hash)
371
+ unless bool
372
+ parent_scope = matcher_i18n_scope.split('.')
373
+ matcher_name = parent_scope.pop
374
+ lookup = :"expectations.#{method.to_s.gsub(/(\?|\!)$/, '')}"
375
+
376
+ hash = { :scope => parent_scope, :default => lookup }.merge(hash || {})
377
+ @expectation ||= Remarkable.t "#{matcher_name}.#{lookup}", default_i18n_options.merge(hash)
378
378
 
379
379
  return false
380
380
  end
381
381
  end
382
382
 
383
383
  return true
384
- end
385
-
384
+ end
385
+
386
386
 
387
387
  end
388
388
  end
@@ -1,6 +1,6 @@
1
- module Remarkable
2
- # Holds the methods required by rspec for each matcher plus a collection of
3
- # helpers to deal with I18n.
1
+ module Remarkable
2
+ # Holds the methods required by rspec for each matcher plus a collection of
3
+ # helpers to deal with I18n.
4
4
  #
5
5
  module Messages
6
6
 
@@ -84,8 +84,8 @@ module Remarkable
84
84
  words_connector = Remarkable.t 'remarkable.core.helpers.words_connector'
85
85
  two_words_connector = Remarkable.t 'remarkable.core.helpers.two_words_connector'
86
86
  last_word_connector = Remarkable.t 'remarkable.core.helpers.last_word_connector'
87
-
88
- array.map!{|i| i.inspect} if inspect
87
+
88
+ array = array.map { |i| i.inspect } if inspect
89
89
 
90
90
  case array.length
91
91
  when 0
@@ -97,7 +97,7 @@ module Remarkable
97
97
  else
98
98
  "#{array[0...-1].join(words_connector)}#{last_word_connector}#{array[-1]}"
99
99
  end
100
- end
100
+ end
101
101
 
102
102
  end
103
103
  end
@@ -1,3 +1,3 @@
1
1
  module Remarkable
2
- VERSION = '3.1.6' unless self.const_defined?(:VERSION)
2
+ VERSION = '3.1.7' unless self.const_defined?(:VERSION)
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remarkable
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.6
4
+ version: 3.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carlos Brando
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-06-06 00:00:00 +02:00
13
+ date: 2009-07-05 00:00:00 +02:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency