rspec-siren 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem "pry"
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Neer Friedman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # Rspec::Siren
2
+
3
+ Helpers for testing [siren](https://github.com/kevinswiber/siren) objects with
4
+ RSpec
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'rspec-siren'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ In your `spec_helper.rb` add: `require 'rspec-siren'`
17
+
18
+ ## Usage
19
+
20
+ ```ruby
21
+ require 'spec_helper'
22
+
23
+ RSpec.describe MyCustomSirenSerializer do
24
+ let(:siren) { MyCustomSirenSerializer.new.to_siren }
25
+
26
+ it { should have_class("MyCustomSiren") }
27
+
28
+ it { should have_entities.with_class("MySubEntity").exactly(2) }
29
+
30
+ it { should have_link_with_rel("my-rel") }
31
+
32
+ it { should have_property("myProperty").with_value("myValue") }
33
+ end
34
+ ```
35
+
36
+
37
+ ## Contributing
38
+
39
+ 1. Fork it
40
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
41
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
42
+ 4. Push to the branch (`git push origin my-new-feature`)
43
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,28 @@
1
+ module RSpec
2
+ module Siren
3
+ module Matchers
4
+ class HasClass
5
+ def initialize(expected)
6
+ @expected = expected
7
+ end
8
+
9
+ def matches?(target)
10
+ @target = target
11
+ @target[:class] && safe_classes.include?(@expected)
12
+ end
13
+
14
+ def safe_classes
15
+ Array(@target[:class])
16
+ end
17
+
18
+ def description
19
+ "have siren class '#{@expected}'"
20
+ end
21
+
22
+ def failure_message
23
+ "expected siren object to have class '#{@expected}' found classes: #{safe_classes.inspect}"
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,47 @@
1
+ module RSpec
2
+ module Siren
3
+ module Matchers
4
+ class HasEntities
5
+ def matches?(target)
6
+ @target = target
7
+
8
+ @entities = safe_entities.select do |e|
9
+ !@klass || e[:class].include?(@klass)
10
+ end
11
+
12
+ !@entities.empty? && (!@count || @entities.count == @count)
13
+ end
14
+
15
+ def with_class(klass)
16
+ @klass = klass
17
+ self
18
+ end
19
+
20
+ def exactly(count)
21
+ @count = count
22
+ self
23
+ end
24
+
25
+ def description
26
+ message = "have"
27
+ message << " #{@count}" if @count
28
+ message << " entities with klass '#{@klass}'"
29
+ end
30
+
31
+ def failure_message
32
+ message = "expected"
33
+ message << " #{@count}"
34
+ message << " entities with class '#{@klass}'."
35
+ message << " Found #{@entities.count}."
36
+ end
37
+
38
+ private
39
+
40
+ def safe_entities
41
+ Array(@target[:entities])
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,32 @@
1
+ module RSpec
2
+ module Siren
3
+ module Matchers
4
+ class HasLink
5
+ def initialize(expected_rel)
6
+ @expected_rel = expected_rel
7
+ end
8
+
9
+ def matches?(target)
10
+ @target = target
11
+ link = safe_links.detect { |l| l[:rel].include?(@expected_rel) }
12
+
13
+ !!link
14
+ end
15
+
16
+ def description
17
+ "have a link with rel '#{@expected_rel}'"
18
+ end
19
+
20
+ def failure_message
21
+ "has no link with rel '#{@expected_rel}'"
22
+ end
23
+
24
+ private
25
+
26
+ def safe_links
27
+ Array(@target[:links])
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,61 @@
1
+ module RSpec
2
+ module Siren
3
+ module Matchers
4
+ class HasProperty
5
+ def initialize(expected_name)
6
+ @expected_name = expected_name
7
+ end
8
+
9
+ def matches?(target)
10
+ @target = target
11
+
12
+ @value = safe_properties[@expected_name]
13
+
14
+ property_exists? && (!has_expected_value? || expected_value_matches?)
15
+ end
16
+
17
+ def with_value(expected_value)
18
+ @expected_value = expected_value
19
+ self
20
+ end
21
+
22
+ def has_expected_value?
23
+ !!@expected_value
24
+ end
25
+
26
+ def expected_value_matches?
27
+ @value == @expected_value
28
+ end
29
+
30
+ def property_exists?
31
+ safe_properties.has_key?(@expected_name)
32
+ end
33
+
34
+ def description
35
+ message = "have"
36
+ message << " property '#{@expected_name}'"
37
+ message << " with value '#{@expected_value}'"
38
+ end
39
+
40
+ def failure_message
41
+ message = "expected"
42
+ message << " property '#{@expected_name}'"
43
+ message << " with value '#{@expected_value}'" if @expected_value
44
+ message << ". Found"
45
+ if !property_exists?
46
+ message << " no such property."
47
+ else
48
+ message << " with value '#{@value}'"
49
+ end
50
+ message
51
+ end
52
+
53
+ private
54
+
55
+ def safe_properties
56
+ @target[:properties] || @target["properties"] || {}
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,27 @@
1
+ module RSpec
2
+ module Siren
3
+ module Matchers
4
+ autoload :HasClass, "rspec/siren/matchers/has_class"
5
+ autoload :HasEntities, "rspec/siren/matchers/has_entities"
6
+ autoload :HasLink, "rspec/siren/matchers/has_link"
7
+ autoload :HasProperty, "rspec/siren/matchers/has_property"
8
+
9
+ def have_class(expected_class)
10
+ HasClass.new(expected_class)
11
+ end
12
+
13
+ def have_entities
14
+ HasEntities.new
15
+ end
16
+
17
+ def have_link_with_rel(expected_rel)
18
+ HasLink.new(expected_rel)
19
+ end
20
+
21
+ def have_property(expected_name)
22
+ HasProperty.new(expected_name)
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,5 @@
1
+ module RSpec
2
+ module Siren
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ require "rspec/siren/version"
2
+ require "rspec/siren/matchers"
3
+
4
+ module RSpec
5
+ module Siren
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ require "rspec/siren"
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rspec/siren/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rspec-siren"
8
+ spec.version = RSpec::Siren::VERSION
9
+ spec.authors = ["Neer Friedman"]
10
+ spec.email = ["neerfri@gmail.com"]
11
+ spec.description = %q{RSpec for siren hypermedia}
12
+ spec.summary = %q{A collection of matchers and helpers for easy testing of siren objects via RSpec}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ end
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe RSpec::Siren::Matchers::HasClass do
4
+ include RSpec::Siren::Matchers
5
+ include RSpec::Siren::MatchersSpecHelper
6
+
7
+ let(:expected_class) { "my-class" }
8
+ let(:matcher) { have_class(expected_class) }
9
+ subject { matcher }
10
+
11
+ context "with correct class" do
12
+ it { should match_siren }
13
+ end
14
+
15
+ context "with incorrect class" do
16
+ let(:expected_class) { "wrong-class" }
17
+
18
+ it { should_not match_siren }
19
+ end
20
+
21
+ context "when siren object has no class attribute" do
22
+ it { should_not match_siren }
23
+
24
+ def siren_hash
25
+ super.merge(class: nil)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,60 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe RSpec::Siren::Matchers::HasEntities do
4
+ include RSpec::Siren::Matchers
5
+ include RSpec::Siren::MatchersSpecHelper
6
+
7
+ let(:expected_rel) { "some-rel" }
8
+ let(:matcher) { have_entities }
9
+ subject { matcher }
10
+
11
+ context "with any entity" do
12
+ it { should match_siren }
13
+
14
+ context "and correct count" do
15
+ let(:matcher) { super().exactly(2) }
16
+
17
+ it { should match_siren }
18
+ end
19
+
20
+ context "and wrong count" do
21
+ let(:matcher) { super().exactly(3) }
22
+
23
+ it { should_not match_siren }
24
+ end
25
+ end
26
+
27
+ context "with existing entity class" do
28
+ let(:matcher) { super().with_class("my-entity") }
29
+
30
+ it { should match_siren }
31
+
32
+ context "and correct count" do
33
+ let(:matcher) { super().exactly(2) }
34
+
35
+ it { should match_siren }
36
+ end
37
+
38
+ context "and wrong count" do
39
+ let(:matcher) { super().exactly(3) }
40
+
41
+ it { should_not match_siren }
42
+ end
43
+ end
44
+
45
+ context "with no entities" do
46
+ it { should_not match_siren }
47
+
48
+ def siren_hash
49
+ super.merge(entities: [])
50
+ end
51
+ end
52
+
53
+ context "when siren has no entities attribute" do
54
+ it { should_not match_siren }
55
+
56
+ def siren_hash
57
+ super.merge(entities: nil)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,46 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe RSpec::Siren::Matchers::HasLink do
4
+ include RSpec::Siren::Matchers
5
+ include RSpec::Siren::MatchersSpecHelper
6
+
7
+ let(:expected_rel) { "some-rel" }
8
+ let(:matcher) { have_link_with_rel(expected_rel) }
9
+ subject { matcher }
10
+
11
+ context "with correct rel" do
12
+ let(:expected_rel) { "my-link" }
13
+
14
+ it { should match_siren }
15
+
16
+ it "describes link presence" do
17
+ match!
18
+
19
+ expect(matcher.description).to eq("have a link with rel 'my-link'")
20
+ end
21
+ end
22
+
23
+ context "when siren object has no class attribute" do
24
+ it { should_not match_siren }
25
+
26
+ it "does not raise" do
27
+ matcher = have_a_link("some-rel")
28
+ expect { match! }.to_not raise_error
29
+ end
30
+
31
+ def siren_hash
32
+ super.merge(links: nil)
33
+ end
34
+ end
35
+
36
+ context "with incorrect rel" do
37
+ let(:expected_rel) { "some-rel" }
38
+
39
+ it { should_not match_siren }
40
+
41
+ it "notifies about missing link" do
42
+ match!
43
+ expect(matcher.failure_message).to eq("has no link with rel 'some-rel'")
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe RSpec::Siren::Matchers::HasProperty do
4
+ include RSpec::Siren::Matchers
5
+ include RSpec::Siren::MatchersSpecHelper
6
+
7
+ let(:expected_property) { :someProperty }
8
+ let(:matcher) { have_property(expected_property) }
9
+ subject { matcher }
10
+
11
+ context "with existing property" do
12
+ it { should match_siren }
13
+
14
+ context "and correct value" do
15
+ let(:matcher) { super().with_value("someValue") }
16
+
17
+ it { should match_siren }
18
+ end
19
+
20
+ context "and wrong value" do
21
+ let(:matcher) { super().with_value("wrongValue") }
22
+
23
+ it { should_not match_siren }
24
+ end
25
+ end
26
+
27
+ context "with non-existing property" do
28
+ let(:expected_property) { :nonExistingProperty }
29
+
30
+ it { should_not match_siren }
31
+ end
32
+
33
+ context "when siren has no properties attribute" do
34
+ it { should_not match_siren }
35
+
36
+ def siren_hash
37
+ super.merge(properties: nil)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,32 @@
1
+ require "rspec-siren"
2
+
3
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
4
+ RSpec.configure do |config|
5
+ config.expect_with :rspec do |expectations|
6
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
7
+ end
8
+
9
+ config.mock_with :rspec do |mocks|
10
+ mocks.verify_partial_doubles = true
11
+ end
12
+
13
+ config.disable_monkey_patching!
14
+
15
+ config.filter_run :focus
16
+ config.run_all_when_everything_filtered = true
17
+
18
+ if config.files_to_run.one?
19
+ # Use the documentation formatter for detailed output,
20
+ # unless a formatter has already been configured
21
+ # (e.g. via a command-line flag).
22
+ config.default_formatter = 'doc'
23
+ end
24
+
25
+ config.order = :random
26
+ Kernel.srand config.seed
27
+
28
+ # load files in support dir
29
+ Dir[File.expand_path("../support/**/*.rb", __FILE__)]
30
+ .sort
31
+ .each { |f| require f }
32
+ end
@@ -0,0 +1,66 @@
1
+ module RSpec
2
+ module Siren
3
+ module MatchersSpecHelper
4
+ def match!
5
+ matcher.matches?(siren_hash)
6
+ end
7
+
8
+ def siren_hash
9
+ {
10
+ class: siren_classes,
11
+ links: siren_links,
12
+ entities: siren_entities,
13
+ properties: siren_properties,
14
+ }
15
+ end
16
+
17
+ def siren_classes
18
+ [ "my-class" ]
19
+ end
20
+
21
+ def siren_links
22
+ [
23
+ { rel: ["my-link"], href: "http://example.com" },
24
+ ]
25
+ end
26
+
27
+ def siren_entities
28
+ [
29
+ { class: ["my-entity"], href: "http://example.com" },
30
+ { class: ["my-entity"], href: "http://example.com" },
31
+ ]
32
+ end
33
+
34
+ def siren_properties
35
+ {
36
+ someProperty: "someValue"
37
+ }
38
+ end
39
+
40
+ class MatchSirenMatcher < Struct.new(:siren_hash)
41
+ def matches?(matcher)
42
+ @matcher = matcher
43
+ matcher.matches?(siren_hash) == true
44
+ end
45
+
46
+ def description
47
+ "match"
48
+ end
49
+
50
+ def failure_message
51
+ "expected to match but did not match." \
52
+ " original failure message is: " \
53
+ "#{@matcher.failure_message.inspect}"
54
+ end
55
+
56
+ def failure_message_when_negated
57
+ "expected to not match but matched"
58
+ end
59
+ end
60
+
61
+ def match_siren
62
+ MatchSirenMatcher.new(siren_hash)
63
+ end
64
+ end
65
+ end
66
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-siren
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Neer Friedman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-09-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.7'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.7'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: RSpec for siren hypermedia
63
+ email:
64
+ - neerfri@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .rspec
71
+ - Gemfile
72
+ - LICENSE.txt
73
+ - README.md
74
+ - Rakefile
75
+ - lib/rspec-siren.rb
76
+ - lib/rspec/siren.rb
77
+ - lib/rspec/siren/matchers.rb
78
+ - lib/rspec/siren/matchers/has_class.rb
79
+ - lib/rspec/siren/matchers/has_entities.rb
80
+ - lib/rspec/siren/matchers/has_link.rb
81
+ - lib/rspec/siren/matchers/has_property.rb
82
+ - lib/rspec/siren/version.rb
83
+ - rspec-siren.gemspec
84
+ - spec/rspec/siren/matchers/has_class_spec.rb
85
+ - spec/rspec/siren/matchers/has_entities_spec.rb
86
+ - spec/rspec/siren/matchers/has_link_spec.rb
87
+ - spec/rspec/siren/matchers/has_property_spec.rb
88
+ - spec/spec_helper.rb
89
+ - spec/support/matchers_spec_helper.rb
90
+ homepage: ''
91
+ licenses:
92
+ - MIT
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ segments:
104
+ - 0
105
+ hash: -4380809523059336186
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ segments:
113
+ - 0
114
+ hash: -4380809523059336186
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 1.8.23
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: A collection of matchers and helpers for easy testing of siren objects via
121
+ RSpec
122
+ test_files:
123
+ - spec/rspec/siren/matchers/has_class_spec.rb
124
+ - spec/rspec/siren/matchers/has_entities_spec.rb
125
+ - spec/rspec/siren/matchers/has_link_spec.rb
126
+ - spec/rspec/siren/matchers/has_property_spec.rb
127
+ - spec/spec_helper.rb
128
+ - spec/support/matchers_spec_helper.rb