remarkable 3.1.6 → 3.1.7

Sign up to get free protection for your applications and to get access to all the features.
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