rspec-sleeping_king_studios 2.1.1 → 2.2.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -0
  3. data/DEVELOPMENT.md +26 -17
  4. data/LICENSE +1 -1
  5. data/README.md +198 -19
  6. data/lib/rspec/sleeping_king_studios/configuration.rb +63 -2
  7. data/lib/rspec/sleeping_king_studios/examples/property_examples.rb +115 -27
  8. data/lib/rspec/sleeping_king_studios/examples/rspec_matcher_examples.rb +66 -51
  9. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors.rb +8 -269
  10. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors_matcher.rb +268 -0
  11. data/lib/rspec/sleeping_king_studios/matchers/base_matcher.rb +5 -15
  12. data/lib/rspec/sleeping_king_studios/matchers/built_in/be_kind_of.rb +3 -63
  13. data/lib/rspec/sleeping_king_studios/matchers/built_in/be_kind_of_matcher.rb +65 -0
  14. data/lib/rspec/sleeping_king_studios/matchers/built_in/include.rb +3 -108
  15. data/lib/rspec/sleeping_king_studios/matchers/built_in/include_matcher.rb +134 -0
  16. data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to.rb +3 -258
  17. data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to_matcher.rb +116 -0
  18. data/lib/rspec/sleeping_king_studios/matchers/core/alias_method.rb +11 -0
  19. data/lib/rspec/sleeping_king_studios/matchers/core/alias_method_matcher.rb +107 -0
  20. data/lib/rspec/sleeping_king_studios/matchers/core/be_boolean.rb +9 -36
  21. data/lib/rspec/sleeping_king_studios/matchers/core/be_boolean_matcher.rb +37 -0
  22. data/lib/rspec/sleeping_king_studios/matchers/core/construct.rb +3 -210
  23. data/lib/rspec/sleeping_king_studios/matchers/core/construct_matcher.rb +113 -0
  24. data/lib/rspec/sleeping_king_studios/matchers/core/delegate_method.rb +11 -0
  25. data/lib/rspec/sleeping_king_studios/matchers/core/delegate_method_matcher.rb +311 -0
  26. data/lib/rspec/sleeping_king_studios/matchers/core/have_constant.rb +16 -0
  27. data/lib/rspec/sleeping_king_studios/matchers/core/have_constant_matcher.rb +225 -0
  28. data/lib/rspec/sleeping_king_studios/matchers/core/have_predicate.rb +11 -0
  29. data/lib/rspec/sleeping_king_studios/matchers/core/have_predicate_matcher.rb +97 -0
  30. data/lib/rspec/sleeping_king_studios/matchers/core/have_property.rb +3 -104
  31. data/lib/rspec/sleeping_king_studios/matchers/core/have_property_matcher.rb +108 -0
  32. data/lib/rspec/sleeping_king_studios/matchers/core/have_reader.rb +3 -74
  33. data/lib/rspec/sleeping_king_studios/matchers/core/have_reader_matcher.rb +96 -0
  34. data/lib/rspec/sleeping_king_studios/matchers/core/have_writer.rb +4 -59
  35. data/lib/rspec/sleeping_king_studios/matchers/core/have_writer_matcher.rb +55 -0
  36. data/lib/rspec/sleeping_king_studios/matchers/description.rb +62 -0
  37. data/lib/rspec/sleeping_king_studios/matchers/macros.rb +32 -0
  38. data/lib/rspec/sleeping_king_studios/matchers/shared/match_parameters.rb +168 -66
  39. data/lib/rspec/sleeping_king_studios/matchers/shared/match_property.rb +25 -0
  40. data/lib/rspec/sleeping_king_studios/matchers.rb +0 -4
  41. data/lib/rspec/sleeping_king_studios/support/method_signature.rb +51 -0
  42. data/lib/rspec/sleeping_king_studios/support/method_signature_expectation.rb +158 -0
  43. data/lib/rspec/sleeping_king_studios/support.rb +9 -0
  44. data/lib/rspec/sleeping_king_studios/version.rb +10 -4
  45. metadata +46 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 97f6020bbdd4cef3654a94977728645b4280d887
4
- data.tar.gz: 3e131e99a70932e0bc9c37beaecb603a184545f3
3
+ metadata.gz: c81d97b3ebb552157fcc3249abff241357da9c27
4
+ data.tar.gz: c1352fafecc6381179dabec958ac2942c9feadee
5
5
  SHA512:
6
- metadata.gz: a68a14860a43074510e7174fd8cc94852c04226e30395c302acd28d86de417f4c9d34f3d85dce2824dc55cafc9e78b8fafb9ad1e637e4d473ac07588c739bdd6
7
- data.tar.gz: 1c19caf6c928f97265aff1bddbfa5f0869d2555ee77200d28cde61d37296836df7ba642d434962be1fccc19c43709b92693471a7a01f71e08991b413a764328f
6
+ metadata.gz: 51ba62b4f06c179719d702fc2b77adfea0b20dcfe7296a3e2224c4a2bc2e0d5d9d9cda5690f4fc58faa3e4900ce99ece1b9e2db51709eba8478dbfefe7446126
7
+ data.tar.gz: 85072590a4cd2c1ed1073c8b603e46b2777036b5eb3de551804af7eb89213eb09e384448cd70eaeb7069527e077fbb68c2429a39a181851e221a37e9c25e48a9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,55 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.2.0
4
+
5
+ ### Examples
6
+
7
+ #### PropertyExamples
8
+
9
+ Added examples 'should have constant' and 'should have immutable constant', which provide shortcuts for the new 'have_constant' matcher.
10
+
11
+ Added examples 'should have predicate' as a shortcut for the new 'have_predicate' matcher.
12
+
13
+ Added negated examples 'should not have reader' and 'should not have writer'.
14
+
15
+ #### RSpecMatcherExamples
16
+
17
+ Updated matcher testing examples (e.g. 'should pass with positive expectation', 'should fail with negative expectation') to support matching failure messages against strings, regular expressions, or RSpec matchers. Added configuration option for string matches to select exact match or partial/substring match.
18
+
19
+ ### Matchers
20
+
21
+ Internally refactored all matcher definitions to *\_matcher.rb, while the previous *.rb files define the macros which are added to example groups. The file names now accurately reflect what they define. In addition, the matchers can be required separately from the macros, e.g. to get around a naming conflict with another library. Also added support for aliasing matchers.
22
+
23
+ #### `alias_method` Matcher
24
+
25
+ Added the `alias_method` matcher, which checks if the object aliases the specified method with the specified other name.
26
+
27
+ ### `construct` and `respond_to` Matchers
28
+
29
+ The `construct` and `respond_to` matcher is now stricter about accepting methods with undefined argument counts. Specifically, if a method requires a minimum number of arguments, and the matcher does not have an argument count expectation but does have at least one other argument expectation (unlimited arguments, keywords, block argument, and so on), the expectation would pass on pre-2.2 versions. This is considered a bug and has been fixed. These matchers should either only check if the method is defined (if there are no argument expectations), or check that the exact argument expectations given are valid for that method.
30
+
31
+ Major internal refactoring to DRY parameter matching and ensure consistent behavior between the `construct` and `respond_to` matchers.
32
+
33
+ #### `belong_to` Matcher
34
+
35
+ Now aliases as `a_boolean`, e.g. `expect(my_object).to have_reader(:my_method).with_value(a_boolean)`.
36
+
37
+ #### `delegate_method` Matcher
38
+
39
+ Added the `delegate_method` matcher, which checks if the object forwards the specified method to the specified target.
40
+
41
+ #### `have_constant` Matcher
42
+
43
+ Added the `have_constant` matcher, which checks for the presence of a defined constant `:CONSTANT_NAME` and optionally the value of the constant. Can also check that the value is immutable.
44
+
45
+ #### `have_predicate` Matcher
46
+
47
+ Added the `have_predicate` matcher, which checks for the presence of a predicate method `#property?` and optionally the value returned by `#property?()`.
48
+
49
+ #### `have_reader` Matcher
50
+
51
+ The `have_reader` matcher is not stricter about rejecting methods with a value expectation when negated. Previously, if the matcher was negated and had a value expectation, the matcher would only fail if the object responded to the method and returned the specified value, but would pass if the object returned another value. This is considered a bug and has been fixed, bringing this matcher in line with the behavior of the `have_property` matcher. A negated `have_reader` matcher should fail if the object responds to the method, whether or not the expected value is the same.
52
+
3
53
  ## 2.1.1
4
54
 
5
55
  ### Concerns
@@ -48,6 +98,8 @@ The old syntax (`respond_to(:my_method).with(1, :foo, :bar)`) will be supported
48
98
 
49
99
  Created suite of [Cucumber features](features) to validate and document the gem.
50
100
 
101
+ ### Matchers
102
+
51
103
  #### `construct` Matcher
52
104
 
53
105
  Aliased as `be_constructible` for more fluent specs, and the error messages have been changed from 'expected ... to construct' to 'expected ... to be constructible'.
data/DEVELOPMENT.md CHANGED
@@ -1,32 +1,38 @@
1
1
  # Development Notes
2
2
 
3
- ## Tasks
3
+ ## Version 2.2.1
4
+
5
+ ### Features
6
+
7
+ - Implement RespondToMatcher#with_at_least(N).arguments, equivalent to with(N).arguments.and_unlimited_arguments.
8
+ - Revisit failure messages for #respond_to, #be_constructible - see #received/#have_received for example?
9
+ - Enhance RSpec matcher examples to display the #failure_message on a failed "should pass/fail with" example.
10
+
11
+ ## Future Tasks
4
12
 
5
13
  - Resolve Aruba deprecation warnings.
14
+ - Run each file individually as CI step.
6
15
 
7
- ### Planned Features
16
+ ### Features
8
17
 
9
- - Add `#with_any_keywords` alias to RespondToMatcher.
10
- - Add #have_constant matcher.
11
- - Add #have_predicate matcher.
12
- - Add shared examples for 'should have constant', 'should have immutable constant'
13
- - Add shared examples for 'should have predicate'
14
- - Add shared examples for 'should not have reader/writer'
15
- - Add shared examples for #belongs_to, #has_one, #has_many, #embedded_in, #embeds_one, #embeds_many.
16
- - Add shared examples for core ActiveModel validations.
17
- - Add allow/expect(object).to alias_method(:my_method).to(:other_method)
18
- - Add allow/expect(object).to delegate(:my_method).to(other_object[, :other_method])
18
+ - Add spy+matcher for expect(my_object, :my_method).to have_changed ?
19
19
 
20
20
  ### Maintenance
21
21
 
22
- - Remove SCENARIOS from spec files.
23
- - Refactor #respond_to, #be_constructible to use RSpec 3 method reflection.
24
- - Revisit failure messages for #respond_to, #be_constructible.
22
+ - Revisit how matchers are documented, particularly in README.md
23
+ - Use matcher class name instead of macro names?
24
+ - Clarify documentation of parameters - YARD-like?
25
25
  - Pare down Cucumber features for matchers - repurpose as documentation/examples only.
26
- - Ensure behavior of `#have_reader`, `#have_writer`, `#have_property` is consistent (non-compatible; needs version 3.0).
26
+ - Break down into smaller (bite-sized?) individual examples.
27
+ - RuboCop - use RSpec rule file as starting point?
27
28
 
28
- ### Icebox
29
+ ## Icebox
29
30
 
31
+ - Extract ActiveModel/Rails functionality to sub-gem?
32
+ - Add shared examples for #belongs_to, #has_one, #has_many, #embedded_in, #embeds_one, #embeds_many.
33
+ - Add shared examples for core ActiveModel validations.
34
+ - Implement shared example group for Rails controller, 'should respond with'
35
+ - Implement shared example group for Rails routing, 'should route to'
30
36
  - Add alt doc test formatter - --format=list ? --format=documentation-list ?
31
37
  - Prints full expanded example name for each example
32
38
  - Add minimal test formatter - --format=smoke ? --format=librarian ? --format=quiet ?
@@ -36,3 +42,6 @@
36
42
  - #should(name) => include_examples "should #{name}"
37
43
  - #with(name) => wrap_context "with #{name}"
38
44
  - #when(name) => wrap_context "when #{name}"
45
+ - General project for using matchers as Ruby objects
46
+ - Inspectable - expectations, comparison results exposed via readers
47
+ - Favor readers over instance variables.
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2013-2014 Rob Smith
3
+ Copyright (c) 2013-2016 Rob Smith
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -4,13 +4,15 @@ A collection of matchers and extensions to ease TDD/BDD using RSpec. Extends bui
4
4
 
5
5
  ## Support
6
6
 
7
- RSpec::SleepingKingStudios is tested against RSpec 3.0, 3.1, 3.2, and 3.3.
7
+ RSpec::SleepingKingStudios is tested against RSpec 3.0 through 3.4.
8
8
 
9
9
  Currently, the following versions of Ruby are officially supported:
10
10
 
11
- * 2.0
12
11
  * 2.1
13
12
  * 2.2
13
+ * 2.3
14
+
15
+ For Ruby 2.0 support, use version 2.1 or earlier: `gem "rspec-sleeping_king_studios", "~> 2.1.1"`.
14
16
 
15
17
  If you require a previous version of Ruby or RSpec, the 1.0 branch supports Ruby 1.9.3 and RSpec 2: `gem "rspec-sleeping_king_studios", "~> 1.0.1"`. However, changes from 2.0 and higher will not be backported.
16
18
 
@@ -28,6 +30,18 @@ Hi, I'm Rob Smith, a Ruby Engineer and the developer of this library. I use thes
28
30
 
29
31
  RSpec::SleepingKingStudios now has configuration options available through `RSpec.configuration`. For example, to set the behavior of the matcher examples when a failure message expectation is undefined (see RSpec Matcher Examples, below), put the following in your `spec_helper` or other configuration file:
30
32
 
33
+ RSpec.configure do |config|
34
+ config.sleeping_king_studios do |config|
35
+ # RSpec::SleepingKingStudios configuration can be set here.
36
+ end # config
37
+ end # config
38
+
39
+ ### Configuration Options
40
+
41
+ #### Examples
42
+
43
+ ##### Handle Missing Failure Message With
44
+
31
45
  RSpec.configure do |config|
32
46
  config.sleeping_king_studios do |config|
33
47
  config.examples do |config|
@@ -36,11 +50,33 @@ RSpec::SleepingKingStudios now has configuration options available through `RSpe
36
50
  end # config
37
51
  end # config
38
52
 
39
- ### Configuration Options
53
+ This option is used with the RSpec matcher examples (see Examples, below), and determines the behavior when a matcher is expected to fail, but the corresponding failure message is not defined (via `let(:failure_message)` or `let(:failure_message_when_negated)`). The default option is `:pending`, which marks the generated example as skipped (and will show up as pending in the formatter). Other options include `:ignore`, which marks the generated example as passing, and `:exception`, which marks the generated example as failing.
40
54
 
41
- #### Handle Missing Failure Message With
55
+ ##### Match String Failure Message As
42
56
 
43
- This option is used with the RSpec matcher examples (see Examples, below), and determines the behavior when a matcher is expected to fail, but the corresponding failure message is not defined (via `let(:failure_message)` or `let(:failure_message_when_negated)`). The default option is `:pending`, which marks the generated example as skipped (and will show up as pending in the formatter). Other options include `:ignore`, which marks the generated example as passing, and `:exception`, which marks the generated example as failing.
57
+ RSpec.configure do |config|
58
+ config.sleeping_king_studios do |config|
59
+ config.examples do |config|
60
+ config.match_string_failure_message_as = :exact
61
+ end # config
62
+ end # config
63
+ end # config
64
+
65
+ This option is used with the RSpec matcher examples (see Examples, below), and determines whether an expected failure message is matched against the actual failure message as an exact match or as a substring. The default option is `:substring`, which means that any failure message that contains the expected message as a substring will match. Alternatively, setting the option to `:exact` will mean that only a failure message that is an exact match for the expected message will match.
66
+
67
+ #### Matchers
68
+
69
+ ##### Strict Predicate Matching
70
+
71
+ RSpec.configure do |config|
72
+ config.sleeping_king_studios do |config|
73
+ config.matchers do |config|
74
+ config.strict_predicate_matching = true
75
+ end # config
76
+ end # config
77
+ end # config
78
+
79
+ This option is used with the HavePredicateMatcher (see `#have_predicate`, below). If set to true, ensures that any method that is expected to be a predicate will return either true or false. The matcher will fail if the method returns any other value. The default value is false, which allows for loose matching of predicate methods.
44
80
 
45
81
  ## Concerns
46
82
 
@@ -164,6 +200,12 @@ To enable a custom matcher, simply require the associated file. Matchers can be
164
200
  require 'rspec/sleeping_king_studios/matchers/core/construct'
165
201
  #=> requires only the :construct matcher
166
202
 
203
+ As of version 2.2, you can also load only the matcher, without adding the associated macro to your example groups. This can be useful in case of naming conflicts with other libraries, or if you need only the matcher in isolation.
204
+
205
+ require 'rspec/sleeping_king_studios/matchers/core/be_boolean_matcher'
206
+ #=> requires the matcher itself as RSpec::SleepingKingStudios::Matchers::Core::BeBooleanMatcher,
207
+ # but does not add a #be_boolean macro to example groups.
208
+
167
209
  ### ActiveModel
168
210
 
169
211
  require 'rspec/sleeping_king_studios/matchers/active_model/all'
@@ -254,16 +296,38 @@ Now has additional chaining functionality to validate the number of arguments ac
254
296
 
255
297
  These matchers check core functionality, such as object boolean-ness, the existence of properties, and so on.
256
298
 
299
+ #### `#alias_method` Matcher
300
+
301
+ require 'rspec/sleeping_king_studios/matchers/core/alias_method'
302
+
303
+ Checks if the object aliases the specified method with the specified other name. Matches if and only if the object responds to both the old and new method names, and if the old method and the new method are the same method.
304
+
305
+ **How To Use**:
306
+
307
+ expect(object).to alias_method(:old_method).as(:new_method)
308
+
309
+ **Parameters:** Old method name. Expects the name of the method which has been aliased as a String or Symbol.
310
+
311
+ **Chaining:**
312
+
313
+ * **`#as`:** Required. Expects one String or Symbol, which is the name of the generated method.
314
+
257
315
  #### `#be_boolean` Matcher
258
316
 
259
317
  require 'rspec/sleeping_king_studios/matchers/core/be_boolean'
260
318
 
261
319
  Checks if the provided object is true or false.
262
320
 
321
+ **Aliases:** `#a_boolean`.
322
+
263
323
  **How To Use:**
264
324
 
325
+ # With an object comparison.
265
326
  expect(object).to be_boolean
266
327
 
328
+ # Inside a composable matcher.
329
+ expect(array).to include(a_boolean)
330
+
267
331
  **Parameters:** None.
268
332
 
269
333
  #### `#construct` Matcher
@@ -289,6 +353,73 @@ Verifies that the actual object can be constructed using `::new`. Can take an op
289
353
  * **`#with_keywords`:** (also `and_keywords`) Expects one or more String or Symbol arguments. Verifies that the class's constructor accepts each provided keyword or has a variadic keyword of the form `**params`. As of 2.1.0 and required keywords, verifies that all required keywords are provided.
290
354
  * **`#with_arbitrary_keywords`:** (also `and_arbitrary_keywords`) No parameters. Verifies that the class's constructor accepts any keyword arguments via a variadic keyword of the form `**params`.
291
355
 
356
+ #### `#delegate_method` Matcher
357
+
358
+ require 'rspec/sleeping_king_studios/matchers/core/delegate_method'
359
+
360
+ Checks if the actual object forwards the specified method to the specified target. Can also specify that arguments, keywords, and/or a block are passed to the target, and that the object returns the specified values.
361
+
362
+ **How To Use:**
363
+
364
+ expect(object).to delegate_method(:my_method).to(target)
365
+
366
+ # Specify that arguments must be passed to the target.
367
+ expect(object).to delegate_method(:my_method).to(target).with_arguments(:ichi, :ni, :san)
368
+ expect(object).to delegate_method(:my_method).to(target).with_keywords(:foo => 'foo', :bar => 'bar')
369
+ expect(object).to delegate_method(:my_method).to(target).with_a_block
370
+
371
+ # Specify that the method must return the specified value.
372
+ expect(object).to delegate_method(:my_method).to(target).and_return(true) # Called 1 time.
373
+ expect(object).to delegate_method(:my_method).to(target).and_return(0, 1, 2) # Called 3 times.
374
+
375
+ **Parameters:** Method name. Expects a string or symbol that is a valid identifier.
376
+
377
+ **Chaining:**
378
+
379
+ * **`#to`:** Required. Expects an object, which is the target the method should be forwarded to.
380
+ * **`#with_arguments`:** (also `and_arguments`) Expects one or more arguments. Specifies that when the method is called on the actual object with the given arguments, those arguments are then passed on to the target object when the method is called on the target.
381
+ * **`#with_keywords:`** (also `and_keywords`) Expects a hash of keywords and values. Specifies that when the method is called on the actual object with the given keywords, those keywords are then passed on to the target object when the method is called on the target.
382
+ * **`#with_a_block:`** (also `and_a_block`) Specifies that when the method is called on the actual object a block argument, thhe block is then passed on to the target object when the method is called on the target.
383
+ * **`#and_return`:** Expects one or more arguments. The method is called on the actual object one time for each value passed into `#and_return`. Specifies that the return value of calling the method on the actual object is the corresponding value passed into `#and_return`.
384
+
385
+ #### `#have_constant` Matcher
386
+
387
+ require 'rspec/sleeping_king_studios/matchers/core/have_constant'
388
+
389
+ Checks for the presence of a defined constant `:CONSTANT_NAME` and optionally the value of the constant. Can also check that the value is immutable, e.g. for an additional layer of protection over important constants.
390
+
391
+ **How To Use:**
392
+
393
+ expect(instance).to have_constant(:FOO)
394
+
395
+ expect(instance).to have_constant(:BAR).with_value('Bar')
396
+
397
+ expect(instance).to have_immutable_constant(:BAZ).with_value('Baz')
398
+
399
+ **Parameters:** Constant name. Expects a string or symbol that is a valid identifier.
400
+
401
+ **Chaining:**
402
+
403
+ * **`#immutable`:** Sets a mutability expectation, which passes if the value of the constant is immutable. Values of `nil`, `false`, `true` are always immutable, as are `Numeric` and `Symbol` primitives. `Array` values must be frozen and all array items must be immutable. `Hash` values must be frozen and all hash keys and values must be immutable. All other objects must be frozen.
404
+
405
+ * **`#with`:** (also `#with_value`) Expects `true` or `false`, which is checked against the current value of `actual.property?()` if actual responds to `#property?`.
406
+
407
+ #### `#have_predicate` Matcher
408
+
409
+ require 'rspec/sleeping_king_studios/matchers/core/have_predicate'
410
+
411
+ Checks if the actual object responds to `#property?`, and optionally if the current value of `actual.property?()` is equal to a specified value. If `config.sleeping_king_studios.matchers.strict_predicate_matching` is set to true, will also validate that the `#property?` returns either `true` or `false`.
412
+
413
+ **How To Use:**
414
+
415
+ expect(instance).to have_predicate(:foo?).with(true)
416
+
417
+ **Parameters:** Property. Expects a string or symbol that is a valid identifier.
418
+
419
+ **Chaining:**
420
+
421
+ * **`#with`:** (also `#with_value`) Expects `true` or `false`, which is checked against the current value of `actual.property?()` if actual responds to `#property?`.
422
+
292
423
  #### `#have_property` Matcher
293
424
 
294
425
  require 'rspec/sleeping_king_studios/matchers/core/have_property'
@@ -355,33 +486,81 @@ Unless otherwise noted, these shared examples expect the example group to define
355
486
 
356
487
  ### Property Examples
357
488
 
358
- These examples are shorthand for defining a reader and/or writer expectation.
489
+ These examples are shorthand for defining a property expectation.
490
+
491
+ require 'rspec/sleeping_king_studios/examples/property_examples'
492
+
493
+ RSpec.describe MyClass do
494
+ include RSpec::SleepingKingStudios::Examples::PropertyExamples
495
+
496
+ # You can use the custom shared examples here.
497
+ end # describe
498
+
499
+ #### Should Have Constant
500
+
501
+ include_examples 'should have constant', :FOO, 42
502
+
503
+ Delegates to the `#have_constant` matcher (see Core/#have_constant, above) and passes if the described class defines the specified constant. If a value is specified, the class or module must define the constant with the specified value. Alternatively, you can set a proc as the expected value, which can contain a comparison, an RSpec expectation, or a more complex expression:
504
+
505
+ include_examples 'should have property', :BAR, ->() { an_instance_of(String) }
506
+
507
+ include_examples 'should have property', :BAZ, ->(value) { value.count = 3 }
508
+
509
+ #### Should Have Immutable Constant
510
+
511
+ include_examples 'should have immutable constant', :FOO, 42
512
+
513
+ As the 'should have constant' example, but sets a mutability expectation on the constant. See Core/#have_constant for specifics on which objects are considered mutable.
514
+
515
+ #### Should Have Predicate
516
+
517
+ include_examples 'should have predicate', :foo, true
518
+
519
+ include_examples 'should have predicate', :foo?, true
520
+
521
+ Delegates to the `#have_predicate` matcher (see Core/#have_predicate, above) and passes if the actual object responds to the specified predicate. If a value is specified, the object must respond to the predicate and return the specified value, which must be true or false. Alternatively, you can set a proc as the expected value, which can contain a comparison, an RSpec expectation, or a more complex expression:
522
+
523
+ include_examples 'should have predicate', :bar, ->() { a_boolean }
524
+
525
+ include_examples 'should have predicate', :baz, ->(value) { value == true }
526
+
527
+ #### Should Have Property
528
+
529
+ include_examples 'should have property', :foo, 42
530
+
531
+ Delegates to the `#have_property` matcher (see Core/#have\_property, above) and passes if the actual object responds to the specified reader and writer methods. If a value is specified, the object must respond to the property and return the specified value. Alternatively, you can set a proc as the expected value, which can contain a comparison, an RSpec expectation, or a more complex expression:
532
+
533
+ include_examples 'should have property', :bar, ->() { an_instance_of(String) }
534
+
535
+ include_examples 'should have property', :baz, ->(value) { value.count = 3 }
536
+
537
+ #### Should Have Reader
359
538
 
360
- #### Has Property
539
+ include_examples 'should have reader', :foo, 42
361
540
 
362
- include_examples 'has property', :foo, 42
541
+ Delegates to the `#have_reader` matcher (see Core/#have_reader, above) and passes if the actual object responds to the specified property reader. If a value is specified, the object must respond to the property and return the specified value. Alternatively, you can set a proc as the expected value, which can contain a comparison, an RSpec expectation, or a more complex expression:
363
542
 
364
- Delegates to the `#has_reader` and `#has_writer` matchers (see Core/#has\_reader and Core/#has\_writer, above) and passes if the actual object responds to the specified property and property writer methods. If a value is specified, the object must respond to the property and return the specified value. Alternatively, you can set a proc as the expected value, which can contain a comparison, an RSpec expectation, or a more complex expression:
543
+ include_examples 'should have reader', :bar, ->() { an_instance_of(String) }
365
544
 
366
- include_examples 'has property', :bar, ->() { an_instance_of(String) }
545
+ include_examples 'should have reader', :baz, ->(value) { value.count = 3 }
367
546
 
368
- include_examples 'has property', :baz, ->(value) { value.count = 3 }
547
+ #### Should Not Have Reader
369
548
 
370
- #### Has Reader
549
+ include_examples 'should not have reader', :foo
371
550
 
372
- include_examples 'has reader', :foo, 42
551
+ Delegates to the `#have_reader` matcher (see Core/#have_reader, above) and passes if the actual object does not respond to to the specified property reader.
373
552
 
374
- Delegates to the `#has_reader` matcher (see Core/#has_reader, above) and passes if the actual object responds to the specified property. If a value is specified, the object must respond to the property and return the specified value. Alternatively, you can set a proc as the expected value, which can contain a comparison, an RSpec expectation, or a more complex expression:
553
+ #### Should Have Writer
375
554
 
376
- include_examples 'has reader', :bar, ->() { an_instance_of(String) }
555
+ include_examples 'should have writer', :foo=
377
556
 
378
- include_examples 'has reader', :baz, ->(value) { value.count = 3 }
557
+ Delegates to the `#have_writer` matcher (see Core/#have_writer, above) and passes if the actual object responds to the specified property writer.
379
558
 
380
- #### Has Writer
559
+ #### Should Not Have Writer
381
560
 
382
- include_examples 'has writer', :foo=
561
+ include_examples 'should not have writer', :foo=
383
562
 
384
- Delegates to the `#has_writer` matcher (see Core/#has_writer, above) and passes if the actual object responds to the specified property writer.
563
+ Delegates to the `#have_writer` matcher (see Core/#have_writer, above) and passes if the actual object does not respond to to the specified property writer.
385
564
 
386
565
  ### RSpec Matcher Examples
387
566
 
@@ -10,13 +10,16 @@ module RSpec::SleepingKingStudios
10
10
  # Permitted options for :handle_missing_failure_message_with.
11
11
  MISSING_FAILURE_MESSAGE_HANDLERS = %w(ignore pending exception).map(&:intern)
12
12
 
13
+ # Options for matching failure messages to strings.
14
+ STRING_FAILURE_MESSAGE_MATCH_OPTIONS = %w(exact substring).map(&:intern)
15
+
13
16
  # Gets the handler for missing failure messages when using the matcher
14
17
  # examples, and sets to :pending if unset.
15
18
  #
16
19
  # @return [Symbol] The current missing message handler.
17
20
  def handle_missing_failure_message_with
18
21
  @handle_missing_failure_message_with ||= :pending
19
- end # method missing_failure_message
22
+ end # method handle_missing_failure_message_with
20
23
 
21
24
  # Sets the handler for missing failure messages when using the matcher
22
25
  # examples.
@@ -29,11 +32,59 @@ module RSpec::SleepingKingStudios
29
32
  def handle_missing_failure_message_with= value
30
33
  unless MISSING_FAILURE_MESSAGE_HANDLERS.include?(value)
31
34
  message = "unrecognized handler value -- must be in #{MISSING_FAILURE_MESSAGE_HANDLERS.join ', '}"
35
+
32
36
  raise ArgumentError.new message
33
37
  end # unless
34
38
 
35
39
  @handle_missing_failure_message_with = value
36
- end # message missing_failure_message=
40
+ end # method handle_missing_failure_message_with=
41
+
42
+ # Gets the option for matching failure messages to strings, and sets to
43
+ # :substring if unset.
44
+ #
45
+ # @return [Symbol] The current failure message string matching option.
46
+ def match_string_failure_message_as
47
+ @match_string_failure_message_as ||= :substring
48
+ end # method match_string_failure_message_as
49
+
50
+ # Sets the option for matching failure messages to strings.
51
+ #
52
+ # @param [Symbol] value The desired option. Must be :exact, :substring, or
53
+ # :partial (alias of :substring).
54
+ #
55
+ # @raise ArgumentError If the handler is not one of the recognized
56
+ # values.
57
+ def match_string_failure_message_as= value
58
+ value = :substring if value == :partial
59
+
60
+ unless STRING_FAILURE_MESSAGE_MATCH_OPTIONS.include?(value)
61
+ message = "unrecognized value -- must be in #{STRING_FAILURE_MESSAGE_MATCH_OPTIONS.join ', '}"
62
+
63
+ raise ArgumentError.new message
64
+ end # unless
65
+
66
+ @match_string_failure_message_as = value
67
+ end # method match_string_failure_message_as=
68
+ end # class
69
+
70
+ # Configuration options for RSpec::SleepingKingStudios::Matchers.
71
+ class Matchers
72
+ # Checks whether predicates are matched "strictly", meaning that they must
73
+ # return either true or false.
74
+ #
75
+ # @return [Boolean] True if predicates are strictly matched, otherwise
76
+ # false.
77
+ def strict_predicate_matching
78
+ @strict_predicate_matching ||= false
79
+ end # method strict_predicate_matching
80
+
81
+ # Sets whether predicates are matched "strictly", meaning that they must
82
+ # return either true or false.
83
+ #
84
+ # @param [Boolean] value The desired value. Is coerced to true or false.
85
+ def strict_predicate_matching= value
86
+ @strict_predicate_matching = !!value
87
+ end # method strict_predicate_matching
37
88
  end # class
38
89
 
39
90
  # Get or set the configuration options for
@@ -45,6 +96,16 @@ module RSpec::SleepingKingStudios
45
96
  end # if
46
97
  end # tap
47
98
  end # method examples
99
+
100
+ # Get or set the configuration options for
101
+ # RSpec::SleepingKingStudios::Matchers.
102
+ def matchers &block
103
+ (@matchers ||= RSpec::SleepingKingStudios::Configuration::Matchers.new).tap do |config|
104
+ if block_given?
105
+ config.instance_eval &block
106
+ end # if
107
+ end # tap
108
+ end # method matchers
48
109
  end # class
49
110
  end # module
50
111