rspec-hal 1.2.0 → 1.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 56ffc8c99f84bb144a2dc97705eb0499a2bb1cd7
4
- data.tar.gz: 8983c9abffc8c5980330c950d268914b3a01eebe
3
+ metadata.gz: 5db7232aae0766a25700b98a53d8c343c0eb8f91
4
+ data.tar.gz: 560a463c6967e2c0f060aec76c688d007cf08756
5
5
  SHA512:
6
- metadata.gz: 345a34323d5c89748d3355cba81016e3bc1c2657828073ea51a9133bb89ccd51d34062efb817f8114328f49aaf3208f80659b1fa9cfddf0fa585ad56e1bd6e15
7
- data.tar.gz: d71388e4b12afda7a66e7a5311579a6b8c47611a1a979a5bb9655423583a37806e0e6eef5f914eda53d970e40b0e119932494237aacf69c72552662bd5262dc7
6
+ metadata.gz: dfe7e6f2a41a4dce154256da82f2789d40db8509e5be62f7658a9db46ec97a3bdfdaa25e88669300158008dddb4aa1b320b0bae52aac65975646c02e11841231
7
+ data.tar.gz: f48fead8ad5405d19646fe6c01b5d07518978f475f6683089d8ce0a65e09b46ba41d4246cb4244a9aa2bcdd1a2e2d0aa6953990a64ae18a7aae61c94b78868f0
data/README.md CHANGED
@@ -35,6 +35,8 @@ Once you have the matchers included you can use it like this
35
35
  .including(a_hash_including('type' => 'sport'))
36
36
 
37
37
  expect(a_user_doc).to have_relation('tag')
38
+ expect(a_user_doc).to have_templated_relation("search")
39
+ expect(a_user_doc).to have_templated_relation("search", matching("{?q}"))
38
40
  ```
39
41
 
40
42
  ## Installation
@@ -60,4 +62,4 @@ Or install it yourself as:
60
62
  5. Push to the branch (`git push origin my-new-feature`)
61
63
  6. Create new Pull Request
62
64
 
63
- [semver]: http://semver.org
65
+ [semver]: http://semver.org
@@ -4,7 +4,10 @@ require 'hal-client'
4
4
  module RSpec
5
5
  module Hal
6
6
  module Matchers
7
+ autoload :HalMatcherHelpers, "rspec/hal/matchers/hal_matcher_helpers"
8
+ require "rspec/hal/matchers/relation_matcher"
7
9
  require "rspec/hal/matchers/templated_relation_matcher"
10
+ require "rspec/hal/matchers/have_property_matcher"
8
11
 
9
12
  # Examples
10
13
  #
@@ -15,6 +18,35 @@ module RSpec
15
18
  TemplatedRelationMatcher.new(*args)
16
19
  end
17
20
 
21
+ # Signature
22
+ #
23
+ # expect(doc).to have_relation(link_rel)
24
+ # expect(doc).to have_relation(link_rel, href_matcher)
25
+ # expect(doc).to have_relation(link_rel, template_variables)
26
+ # expect(doc).to have_relation(link_rel, template_variables, href_matcher)
27
+ #
28
+ # Examples
29
+ #
30
+ # expect(authors_doc).to have_relation("search",
31
+ # {q: "Alice"},
32
+ # match(%r|users/42|))
33
+ def have_relation(*args)
34
+ RelationMatcher.new(*args)
35
+ end
36
+
37
+ # Signature
38
+ #
39
+ # expect(a_doc).to have_property "name"
40
+ # expect(a_doc).to have_property "name, matching(/alice/i)
41
+ #
42
+ # expect(a_doc).to have_property("name").matching(/alice/i)
43
+ # expect(a_doc).to have_property("hobbies").including(matching("golf"))
44
+ # expect(a_doc).to have_property("name").that_is("Bob")
45
+ # expect(a_doc).to have_property("age").that_is kind_of Numeric
46
+ def have_property(*args)
47
+ HavePropertyMatcher.new(*args)
48
+ end
49
+
18
50
  module Document
19
51
  extend RSpec::Matchers::DSL
20
52
 
@@ -74,91 +106,7 @@ module RSpec
74
106
  "Expected `$._embedded.item` to exist in:\n" + a_doc
75
107
  end
76
108
  end
77
-
78
- # Check that the document has the specified property.
79
- #
80
- # Signature
81
- #
82
- # expect(a_user_doc).to have_property "name"
83
- # expect(a_user_doc).to have_property("name").that_is("Bob")
84
- # expect(a_user_doc).to have_property("age").that_is kind_of Numeric
85
- # expect(a_user_doc).to have_property("name").matching(/bob/i)
86
- # expect(a_user_doc).to have_property("hobbies").including(matching("golf"))
87
- matcher :have_property do |prop_name|
88
- match do |a_doc|
89
- a_doc = JSON.load(a_doc) rescue a_doc
90
-
91
-
92
- next false unless a_doc.key? prop_name
93
-
94
- __value_matcher === a_doc.fetch(prop_name)
95
- end
96
-
97
- chain :that_is do |expected_val|
98
- @value_matcher = expected_val
99
- end
100
-
101
- chain :matching do |val_pat|
102
- @value_matcher = if Regexp === val_pat
103
- RSpec::Matchers::BuiltIn::Match.new val_pat
104
- else
105
- val_pat
106
- end
107
- end
108
-
109
- chain :including do |val_pat|
110
- @value_matcher = RSpec::Matchers::BuiltIn::Include.new val_pat
111
- end
112
-
113
- failure_message do
114
- msg = super()
115
- if @value_matcher
116
- msg + " " + @value_matcher.description.gsub(/^match /, "matching ")
117
- end
118
- end
119
-
120
- define_method(:__value_matcher) do
121
- @value_matcher || ->(*_){ true }
122
- end
123
- end
124
-
125
- # Check that the document has the specified relation (in
126
- # either the _links or _embedded sections.
127
- #
128
- # Signature
129
- #
130
- # expect(a_user_doc).to have_relation "tag"
131
- matcher :have_relation do |link_rel|
132
- match do |a_doc|
133
- a_doc = JSON.load(a_doc) rescue a_doc
134
- repr = HalClient::Representation.new(parsed_json: a_doc)
135
-
136
- begin
137
- repr.related_hrefs(link_rel) .any?{|an_href|
138
- next true if !defined? @href_matcher
139
- @href_matcher === an_href
140
- }
141
- rescue KeyError
142
- false
143
- end
144
- end
145
-
146
- chain :with_href do |expected_href|
147
- (fail ArgumentError, "#{expected_href.inspect} must be a matcher") unless expected_href.respond_to? :matches?
148
-
149
- @href_matcher = expected_href
150
- end
151
-
152
- failure_message do
153
- msg = super()
154
- if @href_matcher
155
- msg + " with href " + @href_matcher.description.gsub(/^match /, "matching ")
156
- end
157
- end
158
-
159
- end
160
109
  end
161
-
162
110
  include Document
163
111
  end
164
112
  end
@@ -0,0 +1,65 @@
1
+ module RSpec
2
+ module Hal
3
+ module Matchers
4
+ module HalMatcherHelpers
5
+ NullMatcher = Class.new do
6
+ def matches(*args)
7
+ true
8
+ end
9
+ def ===(*args)
10
+ true
11
+ end
12
+ def description
13
+ ""
14
+ end
15
+ end.new
16
+
17
+ # Returns string composed of the specified clauses with proper
18
+ # spacing between them. Empty and nil clauses are ignored.
19
+ def sentencize(*clauses)
20
+ clauses
21
+ .flatten
22
+ .compact
23
+ .reject(&:empty?)
24
+ .map(&:strip)
25
+ .join(" ")
26
+ end
27
+
28
+ # Returns HalClient::Representation of the provided jsonish
29
+ # thing.
30
+ #
31
+ # jsonish - A HAL document (as a string or pre-parsed hash) or
32
+ # an object that can be converted into one via its `#to_hal`
33
+ # or `#to_json` methods.
34
+ def parse(jsonish)
35
+ json = if jsonish.kind_of? String
36
+ jsonish
37
+
38
+ elsif jsonish.respond_to? :to_hal
39
+ jsonish.to_hal
40
+
41
+ else jsonish.respond_to? :to_json
42
+ jsonish.to_json
43
+ end
44
+
45
+ HalClient::Representation.new(parsed_json: MultiJson.load(json))
46
+ end
47
+
48
+ def matcherize(expected)
49
+ if matcher? expected
50
+ expected
51
+ elsif expected.kind_of? Regexp
52
+ RSpec::Matchers::BuiltIn::Match.new(expected)
53
+ else
54
+ RSpec::Matchers::BuiltIn::Eq.new(expected)
55
+ end
56
+ end
57
+
58
+ def matcher?(obj)
59
+ obj.respond_to?(:matches?) and (obj.respond_to?(:failure_message) or
60
+ obj.respond_to?(:failure_message_for_should))
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,69 @@
1
+ module RSpec
2
+ module Hal
3
+ module Matchers
4
+
5
+ # Example
6
+ #
7
+ # expect(doc).to have_property("name")
8
+ # expect(doc).to have_property("search", matching("Alice"))
9
+ #
10
+ class HavePropertyMatcher
11
+ include HalMatcherHelpers
12
+
13
+ def initialize(property_name, expected=NullMatcher)
14
+ @prop_name = property_name
15
+ @expected = expected
16
+ end
17
+
18
+ def matches?(jsonish)
19
+ repr = parse(jsonish)
20
+
21
+ repr.property?(prop_name) &&
22
+ expected === repr.property(prop_name){ nil }
23
+ end
24
+
25
+ def failure_message
26
+ but_clause = if outcome == :no_templates
27
+ "found only non-templated links"
28
+ else
29
+ "found none"
30
+ end
31
+ expected_clause = if expected != NullMatcher && expected.respond_to?(:description)
32
+ expected.description
33
+ elsif expected != NullMatcher
34
+ "matching #{expected}"
35
+ else
36
+ "to exist"
37
+ end
38
+
39
+ "Expected templated `#{link_rel}` link #{expected_clause} but #{but_clause}"
40
+ end
41
+ alias_method :failure_message_for_should, :failure_message
42
+
43
+ def failure_message_when_negated
44
+ "Expected `#{link_rel}` link to be absent or not templated"
45
+ end
46
+ alias_method :failure_message_for_should_not, :failure_message_when_negated
47
+
48
+ def description
49
+ "have property `#{prop_name}` #{@expected.description}"
50
+ end
51
+
52
+
53
+ def matching(expected)
54
+ self.class.new(prop_name, matcherize(expected))
55
+ end
56
+ alias_method :that_is, :matching
57
+
58
+ def including(expected)
59
+ self.class.new(prop_name, RSpec::Matchers::BuiltIn::Include.new(expected))
60
+ end
61
+
62
+ protected
63
+
64
+ attr_reader :prop_name, :outcome, :expected
65
+
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,69 @@
1
+ module RSpec
2
+ module Hal
3
+ module Matchers
4
+
5
+ # Example
6
+ #
7
+ # expect(doc).to have_relation("search")
8
+ # expect(doc).to have_relation("search", matching("{?q}"))
9
+ #
10
+ class RelationMatcher
11
+ include HalMatcherHelpers
12
+
13
+ # Signature
14
+ #
15
+ # expect(doc).to have_relation link_rel
16
+ # expect(doc).to have_relation link_rel, href_matcher
17
+ # expect(doc).to have_relation link_rel, template_variables
18
+ # expect(doc).to have_relation link_rel, template_variables, href_matcher
19
+ def initialize(link_rel, *args)
20
+ @link_rel = link_rel
21
+
22
+ @tmpl_vars, @expected = *if args.empty?
23
+ [{},NullMatcher]
24
+ elsif args.size > 1
25
+ args
26
+ elsif hashish? args.first
27
+ [args.first, NullMatcher]
28
+ else
29
+ [{}, args.first]
30
+ end
31
+ end
32
+
33
+ def matches?(jsonish)
34
+ repr = parse(jsonish)
35
+
36
+ repr.related_hrefs(link_rel, tmpl_vars){[]}
37
+ .select{|it| expected === it }
38
+ .any?
39
+ end
40
+
41
+ def failure_message
42
+ sentencize "Expected `#{link_rel}` link or embedded", expected.description, "but found none"
43
+ end
44
+ alias_method :failure_message_for_should, :failure_message
45
+
46
+ def failure_message_when_negated
47
+ "Expected `#{link_rel}` link to be absent"
48
+ end
49
+ alias_method :failure_message_for_should_not, :failure_message_when_negated
50
+
51
+ def description
52
+ "have #{link_rel} link or embedded"
53
+ end
54
+
55
+ def with_href(expected)
56
+ self.class.new(link_rel, tmpl_vars, matcherize(expected))
57
+ end
58
+
59
+ protected
60
+
61
+ attr_reader :link_rel, :expected, :tmpl_vars
62
+
63
+ def hashish?(obj)
64
+ obj.respond_to?(:key?) && obj.respond_to?(:[])
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -8,7 +8,9 @@ module RSpec
8
8
  # expect(doc).to have_templated_relation("search", matching("{?q}"))
9
9
  #
10
10
  class TemplatedRelationMatcher
11
- def initialize(link_rel, expected=nil)
11
+ include HalMatcherHelpers
12
+
13
+ def initialize(link_rel, expected=NullMatcher)
12
14
  @link_rel = link_rel
13
15
  @expected = expected
14
16
  end
@@ -37,15 +39,8 @@ module RSpec
37
39
  else
38
40
  "found none"
39
41
  end
40
- expected_clause = if expected != NullMatcher && expected.respond_to?(:description)
41
- expected.description
42
- elsif expected != NullMatcher
43
- "matching #{expected}"
44
- else
45
- "to exist"
46
- end
47
42
 
48
- "Expected templated `#{link_rel}` link #{expected_clause} but #{but_clause}"
43
+ sentencize "Expected templated `#{link_rel}` link", expected.description, "but #{but_clause}"
49
44
  end
50
45
  alias_method :failure_message_for_should, :failure_message
51
46
 
@@ -60,27 +55,7 @@ module RSpec
60
55
 
61
56
  protected
62
57
 
63
- attr_reader :link_rel, :outcome
64
-
65
- NullMatcher = ->(_url_template){ true }
66
-
67
- def expected
68
- @expected ||= NullMatcher
69
- end
70
-
71
- def parse(jsonish)
72
- json = if jsonish.kind_of? String
73
- jsonish
74
-
75
- elsif jsonish.respond_to? :to_hal
76
- jsonish.to_hal
77
-
78
- else jsonish.respond_to? :to_json
79
- jsonish.to_json
80
- end
81
-
82
- HalClient::Representation.new(parsed_json: MultiJson.load(json))
83
- end
58
+ attr_reader :link_rel, :outcome, :expected
84
59
  end
85
60
  end
86
61
  end
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module Hal
3
- VERSION = "1.2.0"
3
+ VERSION = "1.2.1"
4
4
  end
5
5
  end
@@ -0,0 +1,126 @@
1
+ require_relative "../../../spec_helper"
2
+ require "rspec/version"
3
+
4
+ describe RSpec::Hal::Matchers::HavePropertyMatcher do
5
+ describe "creation" do
6
+ specify { expect{ described_class.new(a_prop_name) }.not_to raise_error }
7
+ specify { expect{ described_class.new(a_prop_name, any_matcher) }.not_to raise_error }
8
+ end
9
+
10
+ subject(:matcher) { described_class.new(a_prop_name) }
11
+
12
+ specify { expect(matcher.matches?(json_str_w_property)).to be_truthy}
13
+ specify { expect(matcher.matches?(json_str_wo_property)).to be_falsey}
14
+
15
+ specify { expect(matcher.matches?(parsed_json_w_property)).to be_truthy}
16
+ specify { expect(matcher.matches?(parsed_json_wo_property)).to be_falsey}
17
+
18
+ specify { expect(matcher.matches?(to_halable_w_property)).to be_truthy}
19
+ specify { expect(matcher.matches?(to_halable_wo_property)).to be_falsey}
20
+
21
+
22
+ describe "value expectation set via #matching(regexp)" do
23
+ subject(:matcher) { described_class.new(a_prop_name).matching(/ice$/) }
24
+
25
+ specify { expect(matcher.description).to match /have property `name`/ }
26
+ specify { expect(matcher.description).to match /match.*ice/ }
27
+
28
+ specify { expect(matcher.matches?(json_str_w_property)).to be_truthy}
29
+ specify { expect(matcher.matches?(json_str_wo_property)).to be_falsey}
30
+ specify { expect(matcher.matches?(json_str_w_nonmatching_property)).to be_falsey}
31
+ end
32
+
33
+ describe "value expectation set via #matching(another_matcher)" do
34
+ subject(:matcher) { described_class.new(a_prop_name)
35
+ .matching(RSpec::Matchers::BuiltIn::EndWith.new("ice")) }
36
+
37
+ specify { expect(matcher.description).to match /have property `name`/ }
38
+ specify { expect(matcher.description).to match /end with.*/ }
39
+
40
+ specify { expect(matcher.matches?(json_str_w_property)).to be_truthy}
41
+ specify { expect(matcher.matches?(json_str_wo_property)).to be_falsey}
42
+ specify { expect(matcher.matches?(json_str_w_nonmatching_property)).to be_falsey}
43
+ end
44
+
45
+ describe "value expectation set via #including(another_matcher)" do
46
+ subject(:matcher) { described_class.new('hobbies')
47
+ .including(RSpec::Matchers::BuiltIn::Include.new('type' => 'sport')) }
48
+
49
+ specify { expect(matcher.description).to match /have property `hobbies`/ }
50
+ specify { expect(matcher.description).to match /include.*sport/ }
51
+
52
+ specify { expect(matcher.matches?(json_str_w_property)).to be_truthy}
53
+ specify { expect(matcher.matches?(json_str_wo_property)).to be_falsey}
54
+ specify { expect(matcher.matches?(json_str_w_nonmatching_property)).to be_falsey}
55
+ end
56
+
57
+ describe "value expectation set via #that_is(another_matcher)" do
58
+ subject(:matcher) { described_class.new(a_prop_name)
59
+ .that_is(RSpec::Matchers::BuiltIn::EndWith.new("ice")) }
60
+
61
+ specify { expect(matcher.description).to match /have property `name`/ }
62
+ specify { expect(matcher.description).to match /end with.*/ }
63
+
64
+ specify { expect(matcher.matches?(json_str_w_property)).to be_truthy}
65
+ specify { expect(matcher.matches?(json_str_wo_property)).to be_falsey}
66
+ specify { expect(matcher.matches?(json_str_w_nonmatching_property)).to be_falsey}
67
+ end
68
+
69
+ describe "value expectation set via #that_is(exact_value)" do
70
+ subject(:matcher) { described_class.new(a_prop_name)
71
+ .that_is("Alice") }
72
+
73
+ specify { expect(matcher.description).to match /have property `name`/ }
74
+ specify { expect(matcher.description).to match /Alice/ }
75
+
76
+ specify { expect(matcher.matches?(json_str_w_property)).to be_truthy}
77
+ specify { expect(matcher.matches?(json_str_wo_property)).to be_falsey}
78
+ specify { expect(matcher.matches?(json_str_w_nonmatching_property)).to be_falsey}
79
+ end
80
+
81
+
82
+ specify { expect(matcher.description).to match "have property `#{a_prop_name}`" }
83
+
84
+
85
+
86
+ # Background
87
+ # ---
88
+
89
+ let(:json_str_w_property) { <<-HAL }
90
+ { "name": "Alice"
91
+ ,"hobbies": [{"name": "soccer", "type": "sport"}]
92
+ }
93
+ HAL
94
+
95
+ let(:json_str_wo_property) { <<-HAL }
96
+ { }
97
+ HAL
98
+
99
+ let(:json_str_w_nonmatching_property) { <<-HAL }
100
+ { "name": "Bob"
101
+ ,"hobbies": [{"name": "trumpet", "type": "music"}] }
102
+ HAL
103
+
104
+
105
+ let(:parsed_json_w_property) { MultiJson.load json_str_w_property }
106
+ let(:parsed_json_wo_property) { MultiJson.load json_str_wo_property }
107
+
108
+ let(:to_halable_w_property) { halable.new json_str_w_property}
109
+ let(:to_halable_wo_property) { halable.new json_str_wo_property }
110
+
111
+ let(:halable) { Class.new do
112
+ def initialize(json)
113
+ @json = json
114
+ end
115
+
116
+ def to_hal
117
+ return @json
118
+ end
119
+ end }
120
+
121
+ let(:a_prop_name) { "name" }
122
+
123
+ let(:any_matcher) { matching_prop_value_matcher }
124
+ let(:matching_prop_value_matcher) { match "Alice" }
125
+ # let(:nonmatching_template_str_matcher) { match "hello" }
126
+ end
@@ -0,0 +1,173 @@
1
+ require_relative "../../../spec_helper"
2
+
3
+ describe RSpec::Hal::Matchers::RelationMatcher do
4
+ describe "creation" do
5
+ specify { expect{ described_class.new(a_link_rel) }.not_to raise_error }
6
+ specify { expect{ described_class.new(a_link_rel, any_href_matcher) }.not_to raise_error }
7
+ specify { expect{ described_class.new(a_link_rel, template_variables, any_href_matcher) }
8
+ .not_to raise_error }
9
+ end
10
+
11
+ subject(:matcher) { described_class.new(a_link_rel) }
12
+
13
+ specify{ expect(matcher.matches?(json_str_w_link)).to be_truthy }
14
+ specify{ expect(matcher.matches?(json_str_wo_link)).to be_falsey }
15
+
16
+ context "curries" do
17
+ let(:a_link_rel) { "http://example.com/rels/foo" }
18
+ specify{ expect(matcher.matches?(json_str_w_curied_link)).to be_truthy }
19
+
20
+ context "trying to match unexpanded rel" do
21
+ let(:a_link_rel) { "ex:foo" }
22
+ specify{ expect(matcher.matches? json_str_w_curied_link).to be_falsey }
23
+ end
24
+ end
25
+
26
+ context "templated links" do
27
+ subject(:matcher) { described_class.new(a_link_rel, which: "mother") }
28
+
29
+ specify{ expect(matcher.matches? json_str_w_templated_link).to be_truthy }
30
+ specify{ expect(matcher.matches? json_str_w_link).to be_truthy }
31
+ specify{ expect(matcher.matches? json_str_wo_link).to be_falsey }
32
+ end
33
+
34
+ context "templated links with href matcher" do
35
+ subject(:matcher) { described_class.new(a_link_rel, {which: "mother"}, match(/parent/)) }
36
+
37
+ specify{ expect(matcher.matches? json_str_w_templated_link).to be_truthy }
38
+ specify{ expect(matcher.matches? json_str_w_link).to be_truthy }
39
+ specify{ expect(matcher.matches? json_str_wo_link).to be_falsey }
40
+ end
41
+
42
+ specify{ expect(matcher.matches?(parsed_json_w_link)).to be_truthy }
43
+ specify{ expect(matcher.matches?(parsed_json_wo_link)).to be_falsey }
44
+
45
+ specify{ expect(matcher.matches?(to_halable_w_link)).to be_truthy }
46
+ specify{ expect(matcher.matches?(to_halable_wo_link)).to be_falsey }
47
+
48
+ specify { expect(matcher.description).to match "have #{a_link_rel} link" }
49
+
50
+ context "exact expected href specified via #with_href" do
51
+ subject(:matcher) { described_class.new(a_link_rel)
52
+ .with_href("http://example.com/parent") }
53
+
54
+ specify{ expect(matcher.matches? json_str_w_link).to be_truthy }
55
+ specify{ expect(matcher.matches? json_str_wo_link).to be_falsey }
56
+ end
57
+
58
+ context "regexp expected href specified via #with_href" do
59
+ subject(:matcher) { described_class.new(a_link_rel)
60
+ .with_href(%r(/parent)) }
61
+
62
+ specify{ expect(matcher.matches? json_str_w_link).to be_truthy }
63
+ specify{ expect(matcher.matches? json_str_wo_link).to be_falsey }
64
+ end
65
+
66
+ context "matcher for expected href specified via #with_href" do
67
+ subject(:matcher) { described_class.new(a_link_rel)
68
+ .with_href(end_with("parent")) }
69
+
70
+ specify{ expect(matcher.matches? json_str_w_link).to be_truthy }
71
+ specify{ expect(matcher.matches? json_str_wo_link).to be_falsey }
72
+ end
73
+
74
+ context "non-matching expected href specified via #with_href" do
75
+ subject(:matcher) { described_class.new(a_link_rel)
76
+ .with_href("Malory") }
77
+
78
+ specify{ expect(matcher.matches? json_str_w_link).to be_falsy }
79
+ end
80
+
81
+
82
+ context "failed due to missing relation matcher" do
83
+ before do
84
+ matcher.matches? json_str_wo_link
85
+ end
86
+
87
+ specify { expect(matcher.failure_message)
88
+ .to match "Expected `#{a_link_rel}` link or embedded but found none" }
89
+ specify { expect(matcher.failure_message_for_should)
90
+ .to match matcher.failure_message }
91
+ end
92
+
93
+ context "failed due to unexpected existing relation" do
94
+ before do
95
+ matcher.matches? json_str_w_link
96
+ end
97
+
98
+ specify { expect(matcher.failure_message_when_negated)
99
+ .to match "Expected `#{a_link_rel}` link to be absent" }
100
+ specify { expect(matcher.failure_message_for_should_not)
101
+ .to match matcher.failure_message_when_negated }
102
+ end
103
+
104
+ context "failed due to sub-matcher failure matcher" do
105
+ subject(:matcher) { described_class.new(a_link_rel, match("absent")) }
106
+ before do
107
+ matcher.matches? json_str_wo_link
108
+ end
109
+
110
+ specify { expect(matcher.failure_message)
111
+ .to match %r(Expected `#{a_link_rel}` link or embedded match(?:ing)? "absent" but found none) }
112
+ end
113
+
114
+
115
+ # Background
116
+ # ---
117
+
118
+ let(:json_str_w_link) { <<-HAL }
119
+ { "_links": {
120
+ "up": {"href": "http://example.com/parent"}
121
+ }}
122
+ HAL
123
+
124
+ let(:json_str_wo_link) { <<-HAL }
125
+ { "_links": {
126
+ }}
127
+ HAL
128
+
129
+ let(:json_str_w_curied_link) { <<-HAL }
130
+ { "_links": {
131
+ "ex:foo": {"href": "http://example.com/parent"},
132
+ "curies": [
133
+ {"name": "ex", "href": "http://example.com/rels/{rel}", "templated": true }
134
+ ]
135
+ }}
136
+ HAL
137
+
138
+ let(:json_str_w_templated_link) { <<-HAL }
139
+ { "_links": {
140
+ "up": {"href": "http://example.com/parent{?which}", "templated": true}
141
+ }}
142
+ HAL
143
+
144
+
145
+ # let(:json_str_w_nontemplate_link) { <<-HAL }
146
+ # { "_links": {
147
+ # "up": {"href": "http://example.com/parent"}
148
+ # }}
149
+ # HAL
150
+
151
+
152
+ let(:parsed_json_w_link) { MultiJson.load json_str_w_link }
153
+ let(:parsed_json_wo_link) { MultiJson.load json_str_wo_link }
154
+
155
+ let(:to_halable_w_link) { halable.new json_str_w_link}
156
+ let(:to_halable_wo_link) { halable.new json_str_wo_link }
157
+
158
+ let(:halable) { Class.new do
159
+ def initialize(json)
160
+ @json = json
161
+ end
162
+
163
+ def to_hal
164
+ return @json
165
+ end
166
+ end }
167
+
168
+ let(:a_link_rel) { "up" }
169
+ let(:any_href_matcher) { matching_href_matcher }
170
+ let(:matching_href_matcher) { match /example.com/ }
171
+ let(:nonmatching_href_matcher) { match "hello" }
172
+ let(:template_variables) { {q: "search terms"} }
173
+ end
@@ -28,7 +28,7 @@ describe RSpec::Hal::Matchers::TemplatedRelationMatcher do
28
28
  end
29
29
 
30
30
  specify { expect(matcher.failure_message)
31
- .to match "Expected templated `#{a_link_rel}` link to exist but found none" }
31
+ .to match "Expected templated `#{a_link_rel}` link but found none" }
32
32
  specify { expect(matcher.failure_message_for_should)
33
33
  .to match matcher.failure_message }
34
34
  end
@@ -50,17 +50,17 @@ describe RSpec::Hal::Matchers::TemplatedRelationMatcher do
50
50
  end
51
51
 
52
52
  specify { expect(matcher.failure_message)
53
- .to match "Expected templated `#{a_link_rel}` link to exist but found only non-templated links" }
53
+ .to match "Expected templated `#{a_link_rel}` link but found only non-templated links" }
54
54
  end
55
55
 
56
56
  context "failed due to sub-matcher failure matcher" do
57
- subject(:matcher) { described_class.new(a_link_rel, matching("absent")) }
57
+ subject(:matcher) { described_class.new(a_link_rel, match("absent")) }
58
58
  before do
59
59
  matcher.matches? json_str_wo_link
60
60
  end
61
61
 
62
62
  specify { expect(matcher.failure_message)
63
- .to match %(Expected templated `#{a_link_rel}` link matching "absent" but found none) }
63
+ .to match %r(Expected templated `#{a_link_rel}` link match(?:ing)? "absent" but found none) }
64
64
  end
65
65
 
66
66
 
@@ -17,7 +17,7 @@ describe RSpec::Hal::Matchers do
17
17
 
18
18
  matcher :be_a_matcher do
19
19
  match do |actual|
20
- respond_to?(:matches?) && respond_to?(:failure_message)
20
+ actual.respond_to?(:matches?) && actual.respond_to?(:failure_message)
21
21
  end
22
22
  end
23
23
  end
@@ -38,50 +38,6 @@ describe RSpec::Hal::Matchers::Document do
38
38
  specify { expect(matcher.matches?(hal_doc)).to be_falsey }
39
39
  end
40
40
 
41
- describe "have_property('name')" do
42
- subject(:matcher) { have_property('name') }
43
-
44
- specify { expect(matcher.matches?(hal_doc)).to be_truthy}
45
- specify { expect(matcher.matches?("{}")).to be_falsey}
46
- end
47
-
48
- describe "have_property('name').matching(/ice$/)" do
49
- subject(:matcher) { have_property('name').matching(/ice$/) }
50
-
51
- specify { expect(matcher.matches?(hal_doc)).to be_truthy}
52
- specify { expect(matcher.matches?("{}")).to be_falsey}
53
- specify { expect(matcher.matches?(bob)).to be_falsey}
54
- end
55
-
56
- describe "have_property('name').matching(end_with('ice'))" do
57
- before do skip("RSpec 3 feature") unless /3\./ === RSpec::Version::STRING end
58
- subject(:matcher) { have_property('name')
59
- .matching(RSpec::Matchers::BuiltIn::EndWith.new("ice")) }
60
-
61
- specify { expect(matcher.matches?(hal_doc)).to be_truthy}
62
- specify { expect(matcher.matches?("{}")).to be_falsey}
63
- specify { expect(matcher.matches?(bob)).to be_falsey}
64
- end
65
-
66
- describe "have_property('hobbies').including(a_hash_including('type' => 'sport'))" do
67
- subject(:matcher) { have_property('hobbies')
68
- .including(RSpec::Matchers::BuiltIn::Include.new('type' => 'sport')) }
69
- before do extend described_class end
70
-
71
- specify { expect(matcher.matches?(hal_doc)).to be_truthy}
72
- specify { expect(matcher.matches?("{}")).to be_falsey}
73
- specify { expect(matcher.matches?(bob)).to be_falsey}
74
- end
75
-
76
- describe "have_relation('tag')" do
77
- subject(:matcher) { have_relation('tag') }
78
-
79
- specify { expect(matcher.matches?(hal_doc)).to be_truthy}
80
- specify { expect(matcher.matches?("{}")).to be_falsey}
81
- specify { expect(matcher.matches?(bob)).to be_falsey}
82
- end
83
-
84
-
85
41
  before do
86
42
  extend RSpec::Hal::Matchers::Document
87
43
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-hal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-02 00:00:00.000000000 Z
11
+ date: 2014-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -88,9 +88,14 @@ files:
88
88
  - lib/rspec-hal.rb
89
89
  - lib/rspec/hal.rb
90
90
  - lib/rspec/hal/matchers.rb
91
+ - lib/rspec/hal/matchers/hal_matcher_helpers.rb
92
+ - lib/rspec/hal/matchers/have_property_matcher.rb
93
+ - lib/rspec/hal/matchers/relation_matcher.rb
91
94
  - lib/rspec/hal/matchers/templated_relation_matcher.rb
92
95
  - lib/rspec/hal/version.rb
93
96
  - rspec-hal.gemspec
97
+ - spec/rspec/hal/matchers/have_property_matcher_spec.rb
98
+ - spec/rspec/hal/matchers/relation_matcher_spec.rb
94
99
  - spec/rspec/hal/matchers/templated_relation_matcher_spec.rb
95
100
  - spec/rspec/hal/matchers_spec.rb
96
101
  - spec/spec_helper.rb
@@ -119,6 +124,8 @@ signing_key:
119
124
  specification_version: 4
120
125
  summary: Matchers and helpers for specing HAL documents.
121
126
  test_files:
127
+ - spec/rspec/hal/matchers/have_property_matcher_spec.rb
128
+ - spec/rspec/hal/matchers/relation_matcher_spec.rb
122
129
  - spec/rspec/hal/matchers/templated_relation_matcher_spec.rb
123
130
  - spec/rspec/hal/matchers_spec.rb
124
131
  - spec/spec_helper.rb