rspec-hal 1.2.0 → 1.2.1

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