rspec-api_helpers 0.2.1 → 1.0.2

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: b793c8e8f7f6b2ac576475bbd5a388770374a396
4
- data.tar.gz: e9b24e1f7035dc2c255d807aa21b7d71f86ffb55
3
+ metadata.gz: fc01855aa47f3e617fdfca911ccbf4aede2e50a3
4
+ data.tar.gz: 5db89416125336490daa28757862b0a74887dc86
5
5
  SHA512:
6
- metadata.gz: dbb94217c3cd0dd3d6218aa3a5905f2581ff6b6d1b53c1957660d3d1e872234a7ac9c0dbd75ddbfa8cd45d4789e3e6e5ac7947d21e0c06d3feed2f198eb576e2
7
- data.tar.gz: 5b7de73e53c6bddacff741325324824ab2a2ea2254af2ad964006f0809f8e74e93b33799a6635fe14ca0a4eaacd335432155a9580703db51e166751358135ee8
6
+ metadata.gz: 8b53bd402dd540f09d4b63e471f8bffa5e985a2b56e94ea4ed506c4c9eddbdb5dcd771a9bc378d23dfb7659239b6e5d408365a0509fd317e7701e9bdd097323a
7
+ data.tar.gz: dfb3344d4d964e568a399157e3587b15893b48d2ce29f3d8ad8ca274c2821b1df850683e52ba6468f5b0ba1c445f56ed44ec4e5e8c679a584864340a067e6ee4
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Rspec::ApiHelpers
2
2
 
3
- Usefull Rspec helpers for APIs (currently only ActiveModel Serializers are supported)
3
+ Usefull Rspec helpers for APIs (currently JSONAPI and AM-JSON adapters are supported)
4
4
 
5
5
  ## Installation
6
6
 
@@ -29,43 +29,122 @@ In your `rails_helper.rb` add in the top:
29
29
  require 'rspec/api_helpers'
30
30
  ```
31
31
 
32
- and then you only need to include the helpers in your rspec examples. You can include them on all api (:type => :api) helpers by adding the following line in your rspec config:
32
+ Then you need to specify the adapter you want.
33
33
 
34
34
  ```ruby
35
- config.include Rspec::ApiHelpers, type: :api
35
+ RSpec.configure do |config|
36
+ config.include Rspec::ApiHelpers.with(adapter: :json_api)
37
+ end
36
38
  ```
39
+ Other possible options for the adapter is `active_model`.
37
40
 
41
+ You can also inject your custom made class by providing the class:
42
+ ```ruby
43
+ RSpec.configure do |config|
44
+ config.include Rspec::ApiHelpers.with(adapter: Adapter::Hal)
45
+ end
46
+ ```
38
47
 
39
48
  ### Examples
49
+ The library heavily uses dynamic scopes through procs (an alternative to eval).
50
+
51
+
52
+ #### General
40
53
 
41
54
  ```ruby
42
55
  it_returns_status(200)
43
56
  ```
44
- It checks if the HTTP response status is 200.
57
+ It expects the HTTP response status to be 200.
45
58
 
46
59
  ```ruby
47
- it_returns_attributes(resource: 'user', model: '@user', only: [
60
+ it_includes_in_headers('SESSION_TOKEN' => proc{@user.token})
61
+ ```
62
+ It expects the HTTP response to include this header (and value).
63
+
64
+ #### Resource
65
+
66
+ ```ruby
67
+ it_returns_attributes(resource: 'user', model: '@user', attrs: [
48
68
  :email, :name
49
69
  ])
50
70
  ```
51
- It checks if the HTTP body contains an AMS json that has :email and :name attributes and
52
- compares them with '@user' variable's attributes.
71
+
72
+ It expects the JSON resource to contain :email and :name attributes and
73
+ be equal with with `@user` methods.
74
+
75
+
76
+ ```ruby
77
+ it_returns_attribute_values(
78
+ resource: 'user', model: proc{@user}, attrs: [
79
+ :id, :name, :email, :admin, :activated, :created_at, :updated_at
80
+ ], modifiers: {
81
+ [:created_at, :updated_at] => proc{|i| i.iso8601},
82
+ :id => proc{|i| i.to_s}
83
+ }
84
+ )
85
+ ```
86
+ It expects the JSON resource to contain specific attribute values as above but for
87
+ `:updated_at`, `:created_at` and `id` it applies specific methods first, defined in the
88
+ `modifier` hash (note that the methods are applied in the JSON resource, not in the variable)
89
+
90
+ ```ruby
91
+ it_returns_no_attributes(
92
+ resource: 'user', attrs: [:foo1, :foo2, :foo3]
93
+ )
94
+ ```
95
+ It expects the JSON resource to NOT contain any of those attributes.
96
+
97
+ #### Collection
98
+ ```ruby
99
+ it_returns_collection_size(resource: 'users', size: 6)
100
+ ```
101
+
102
+ It expects the JSON collection to have `6` resources.
53
103
 
54
104
  ```ruby
55
- it_returns_more_attributes(
56
- resource: 'user',
57
- model: 'User.last!',
58
- only: [:updated_at, :created_at],
59
- modifier: 'iso8601'
105
+ it_returns_collection_attributes(
106
+ resource: 'users', attrs: [
107
+ :id, :name, :email, :admin, :activated, :created_at, :updated_at
108
+ ]
60
109
  )
61
110
  ```
62
- It checks if the HTTP body contains an AMS json that has :updated_at and :created_at
63
- attributes and compares them with '@user' variable's attributes after it applies modifier.
111
+
112
+ It expects the JSON collection to have those attributes (no value checking).
113
+
64
114
 
65
115
  ```ruby
66
- it_returns_resources(root: 'users', number: 5)
116
+ it_returns_no_collection_attributes(
117
+ resource: 'users', attrs: [
118
+ :foo
119
+ ]
120
+ )
67
121
  ```
68
- It checks if the HTTP body contains an AMS json with an array of 'users'.
122
+
123
+ It expects the JSON collection NOT to have those attributes (no value checking).
124
+
125
+
126
+ ```ruby
127
+ it_returns_collection_attribute_values(
128
+ resource: 'users', model: proc{User.first!}, attrs: [
129
+ :id, :name, :email, :admin, :activated, :created_at, :updated_at
130
+ ], modifiers: {
131
+ [:created_at, :updated_at] => proc{|i| i.iso8601},
132
+ :id => proc{|i| i.to_s}
133
+ }
134
+ )
135
+ ```
136
+
137
+ It expects the JSON collection to contain specific attribute values as above but for
138
+ `:updated_at`, `:created_at` and `id` it applies specific methods first, defined in the
139
+ `modifier` hash (note that the methods are applied in the JSON resource, not in the variable)
140
+
141
+
142
+ ## To Do
143
+ * Enhance documentation
144
+ * Better dir structure (break example group methods to modules)
145
+ * Support for nested resources
146
+ * Add tests
147
+ * Support for HAL/Siren adapter
69
148
 
70
149
  ## Contributing
71
150
 
@@ -1,12 +1,33 @@
1
1
  require 'rspec/api_helpers/version'
2
+ require 'rspec/api_helpers/dispatcher'
2
3
  require 'rspec/api_helpers/example_methods'
3
4
  require 'rspec/api_helpers/example_group_methods'
4
5
 
5
6
  module Rspec
7
+
6
8
  module ApiHelpers
9
+ class << self;
10
+ attr_accessor :adapter
11
+ end
12
+
7
13
  def self.included(receiver)
8
14
  receiver.extend ExampleGroupMethods
9
15
  receiver.send :include, ExampleMethods
10
16
  end
17
+
18
+ def self.with(adapter:)
19
+ if adapter.is_a?(Class)
20
+ self.adapter = adapter
21
+ else
22
+ case adapter.to_s.to_sym
23
+ when :active_model
24
+ self.adapter = Adapter::ActiveModel
25
+ when :json_api
26
+ self.adapter = Adapter::JsonApi
27
+ end
28
+ end
29
+
30
+ return self
31
+ end
11
32
  end
12
33
  end
@@ -0,0 +1,19 @@
1
+ class Adapter
2
+ class ActiveModel
3
+ include RSpec::Matchers
4
+
5
+ class << self
6
+ def resource(options, response, _binding)
7
+ hashed_response = HashWithIndifferentAccess.new(JSON.parse(response.body))
8
+
9
+ return Resource.new(options, hashed_response, _binding)
10
+ end
11
+
12
+ def collection(options, response, _binding)
13
+ hashed_response = HashWithIndifferentAccess.new(JSON.parse(response.body))
14
+
15
+ return Collection.new(options, hashed_response, _binding)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,46 @@
1
+ class Adapter::ActiveModel::Collection
2
+ include Adapter::ActiveModel::CommonHelpers
3
+ include RSpec::Matchers
4
+
5
+ def initialize(options, response, _binding)
6
+ @options = HashWithIndifferentAccess.new(options)
7
+ @response = response
8
+ @_binding = _binding
9
+ end
10
+
11
+ def has_size(size)
12
+ expect(collection.size).to(eq size)
13
+ end
14
+
15
+ def sample(new_options = {})
16
+ Adapter::ActiveModel::Resource.new(
17
+ options.merge(new_options), collection.sample.hash, @_binding
18
+ )
19
+ end
20
+
21
+ def find_by(id, new_options = {})
22
+ resource = collection.find{|i| i.send(id).to_s == model.send(id).to_s}
23
+ if resource.nil?
24
+ raise "Resource was not found for id: #{id} (model value: #{model.send(id)})"
25
+ end
26
+
27
+ return Adapter::ActiveModel::Resource.new(
28
+ options.merge(new_options), resource.hash, @_binding
29
+ )
30
+ end
31
+
32
+ private
33
+ attr_reader :options
34
+
35
+ def model
36
+ @model ||= parse_model(
37
+ @_binding.instance_exec(&options[:model])
38
+ )
39
+ end
40
+
41
+ def collection
42
+ @collection ||= objectize_collection(
43
+ @response, root: options[:resource]
44
+ )
45
+ end
46
+ end
@@ -0,0 +1,74 @@
1
+ module Adapter::ActiveModel::CommonHelpers
2
+ def objectize_collection(collection, root: nil, existing: true)
3
+ if root
4
+ collection = collection[root]
5
+ end
6
+
7
+ return collection.map{|resource|
8
+ object_hash(resource, existing: existing)
9
+ }
10
+ end
11
+
12
+ def objectize_resource(resource, root: nil, existing: true)
13
+ if root
14
+ obj = object_hash(resource[root], existing: existing)
15
+ else
16
+ obj = object_hash(resource, existing: existing)
17
+ end
18
+
19
+ return obj
20
+ end
21
+
22
+ def object_hash(hash, existing: true)
23
+ ObjectHash.new(hash, existing: existing)
24
+ end
25
+
26
+ class ObjectHash
27
+ #existing denotes whether we search for attributes that exist on the
28
+ #resource or attributes that shouldn't exist
29
+ attr_accessor :hash, :existing
30
+ def initialize(hash, existing: true)
31
+ @hash = HashWithIndifferentAccess.new(hash)
32
+ @existing = existing
33
+ end
34
+
35
+ def method_missing(name)
36
+ if existing
37
+ if hash.key?(name)
38
+ return hash[name]
39
+ else
40
+ return raise KeyError.new("Attribute not found in resource: #{name}")
41
+ end
42
+ else
43
+ if hash.key?(name)
44
+ return raise(
45
+ KeyError.new(
46
+ "Attribute found in resource when it shouldn't: #{name}"
47
+ )
48
+ )
49
+ else
50
+ return :attribute_not_found
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ def superset_mismatch_error(superset, subset)
57
+ "Expected \n #{subset.to_a.to_s} \n to be included in \n #{superset.to_a.to_s}"
58
+ end
59
+
60
+ def parse_model(model)
61
+ return model unless model.is_a? Hash
62
+
63
+ return object_hash(model)
64
+ end
65
+
66
+ def modifier_for(key)
67
+ if modifiers_hash[key]
68
+ return modifiers_hash[key]
69
+ else
70
+ return proc{|i| i}
71
+ end
72
+ end
73
+
74
+ end
@@ -0,0 +1,77 @@
1
+ class Adapter::ActiveModel::Resource
2
+ include Adapter::ActiveModel::CommonHelpers
3
+ include RSpec::Matchers
4
+
5
+ def initialize(options, response, _binding)
6
+ @options = HashWithIndifferentAccess.new(options)
7
+ @response = response
8
+ @_binding = _binding
9
+ end
10
+
11
+ def resource
12
+ @resource ||= objectize_resource(
13
+ @response, root: options[:resource], existing: options[:existing]
14
+ )
15
+ end
16
+
17
+ def compare_attribute(attribute)
18
+ expect(resource.send(attribute)).to(
19
+ eql(
20
+ modifier_for(attribute).call(
21
+ model.send(attribute)
22
+ )
23
+ )
24
+ )
25
+ end
26
+
27
+ def embedded_collection(new_options = {})
28
+ raise 'embeds option missing' unless (options[:embeds] || new_options[:embeds])
29
+
30
+ Adapter::ActiveModel::Collection.new(
31
+ options.merge(new_options), resource.send(options[:embeds]), @_binding
32
+ )
33
+ end
34
+
35
+ def has_no_attribute(attribute)
36
+ expect(resource.send(attribute)).to(eql(:attribute_not_found))
37
+ end
38
+
39
+ def has_attribute(attribute)
40
+ expect(resource.send(attribute)).to_not(eql(:attribute_not_found))
41
+ end
42
+
43
+ private
44
+ attr_reader :options
45
+
46
+ def model
47
+ raise 'model is missing' if options[:model].blank?
48
+
49
+ @model ||= parse_model(
50
+ @_binding.instance_exec(&options[:model])
51
+ )
52
+ end
53
+
54
+ def attrs
55
+ options[:attrs].map{|i| i.to_s}
56
+ end
57
+
58
+ def attrs?
59
+ attrs.any?
60
+ end
61
+
62
+ def modifiers_hash
63
+ return {} if options[:modifiers].blank?
64
+
65
+ @modifiers_hash = {}
66
+ options[:modifiers].each do |key, value|
67
+ [key].flatten.each do |attr|
68
+ if attrs?
69
+ raise "#{attr} missing from :attrs param" unless attrs.include?(attr.to_s)
70
+ @modifiers_hash[attr] = value
71
+ end
72
+ end
73
+ end
74
+
75
+ return @modifiers_hash
76
+ end
77
+ end
@@ -0,0 +1,52 @@
1
+ class Adapter
2
+ class JsonApi
3
+ include RSpec::Matchers
4
+
5
+ class << self
6
+ def resource(options, response, _binding)
7
+ jsonapi_resource = HashWithIndifferentAccess.new(JSON.parse(response.body))
8
+
9
+ jsonapi_resource = transform_resource(jsonapi_resource.dig('data') || {})
10
+
11
+ return Adapter::ActiveModel::Resource.new(options, jsonapi_resource, _binding)
12
+ end
13
+
14
+ def collection(options, response, _binding)
15
+ jsonapi_collection = HashWithIndifferentAccess.new(JSON.parse(response.body))
16
+
17
+ jsonapi_collection = transform_collection(jsonapi_collection.dig('data') || {})
18
+
19
+ return Adapter::ActiveModel::Collection.new(options, jsonapi_collection, _binding)
20
+ end
21
+
22
+
23
+ private
24
+ def transform_resource(jsonapi_hash, root: true)
25
+ type = jsonapi_hash.dig('type').singularize
26
+ json_hash = jsonapi_hash.dig('attributes').transform_keys{|key|
27
+ key.underscore
28
+ }.merge(id: jsonapi_hash.dig('id').to_s)
29
+
30
+ if root
31
+ return HashWithIndifferentAccess.new({type => json_hash})
32
+ else
33
+ return HashWithIndifferentAccess.new(json_hash)
34
+ end
35
+ end
36
+
37
+ def transform_collection(jsonapi_hash, root: true)
38
+ type = jsonapi_hash.first.dig('type').pluralize
39
+
40
+ json_hash = jsonapi_hash.map{|data|
41
+ transform_resource(data, root: false)
42
+ }
43
+
44
+ if root
45
+ return HashWithIndifferentAccess.new({type => json_hash})
46
+ else
47
+ return json_hash
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,16 @@
1
+ require 'rspec/api_helpers/adapter/jsonapi/adapter'
2
+ require 'rspec/api_helpers/adapter/active_model/adapter'
3
+ require 'rspec/api_helpers/adapter/active_model/common_helpers'
4
+ require 'rspec/api_helpers/adapter/active_model/resource'
5
+ require 'rspec/api_helpers/adapter/active_model/collection'
6
+
7
+
8
+ module Rspec
9
+ module ApiHelpers
10
+ class Dispatcher
11
+ def adapter
12
+ Rspec::ApiHelpers.adapter
13
+ end
14
+ end
15
+ end
16
+ end
@@ -7,56 +7,23 @@ module Rspec
7
7
  end
8
8
  end
9
9
 
10
- def it_returns_attribute_values(resource:, model:, only: [], modifier: {})
11
- it "expects returned resource (#{resource}) to have model attribute values" do
12
- api_resource = objectize_resource(last_response.body, root: resource)
13
-
14
- modifier = HashWithIndifferentAccess.new(modifier)
15
-
16
- model = eval(model)
17
- if model.is_a? Hash
18
- model = object_hash(model)
19
- end
20
-
21
- if only
22
- only.each do |attribute|
23
- begin
24
- if modifier.has_key?(attribute)
25
- modifier[attribute] = [modifier[attribute]].flatten
26
-
27
- expect(api_resource.send(attribute)).to(
28
- eql(
29
- modifier[attribute].inject(
30
- model.send(attribute), :send
31
- )
32
- )
33
- )
34
- else
35
- expect(api_resource.send(attribute)).to(
36
- eql(model.send(attribute))
37
- )
38
- end
39
- rescue RSpec::Expectations::ExpectationNotMetError => e
40
- e.message << "failed at model attribute: #{attribute}"
41
- raise e
42
- end
43
- end
10
+ #make rehashable
11
+ def it_includes_in_headers(headers = {})
12
+ headers.each do |header, value|
13
+ it "returns headers #{header} wih value: #{value}" do
14
+ expect(last_response.headers[header.to_s]).to eq(eval(value))
44
15
  end
45
16
  end
46
-
47
17
  end
48
- alias_method :it_returns_more_attribute_values, :it_returns_attribute_values
49
-
50
18
 
51
- def it_returns_no_attributes(resource:, attributes: [])
52
- it "expects returned resource (#{resource}) to NOT have the following attributes" do
53
- api_resource = objectize_resource(
54
- last_response.body, root: resource, existing: false
55
- )
19
+ def it_returns_attribute_values(options = {})
20
+ it "expects returned resource (#{options[:resource]}) to have model attribute values" do
21
+ resource = dispatcher.adapter.resource(options.merge(existing: true), last_response, self)
56
22
 
57
- attributes.each do |attribute|
23
+ #support proc on attrs
24
+ options[:attrs].each do |attribute|
58
25
  begin
59
- expect(api_resource.send(attribute)).to eql(:attribute_not_found)
26
+ resource.compare_attribute(attribute)
60
27
  rescue RSpec::Expectations::ExpectationNotMetError => e
61
28
  e.message << "failed at model attribute: #{attribute}"
62
29
  raise e
@@ -64,61 +31,45 @@ module Rspec
64
31
  end
65
32
  end
66
33
  end
34
+ alias_method :it_returns_more_attribute_values, :it_returns_attribute_values
67
35
 
68
- def it_includes_in_headers(headers = {})
69
- headers.each do |header, value|
70
- it "returns headers #{header} wih value: #{value}" do
71
- expect(last_response.headers[header.to_s]).to eq(eval(value))
72
- end
73
- end
74
- end
36
+ def it_returns_no_attributes(options = {})
37
+ it "expects returned resource (#{options[:root]}) to NOT have the following attributes" do
38
+ resource = dispatcher.adapter.resource(options.merge(existing: false), last_response, self)
75
39
 
76
- def it_returns_collection_size(resource:, size:)
77
- it "returns the correct number of resources in the #{resource} collection" do
78
- resources = objectize_resources(last_response.body, root: resource)
79
- expect(resources.length).to eql(size)
40
+ options[:attrs].each do |attribute|
41
+ begin
42
+ resource.has_no_attribute(attribute)
43
+ rescue RSpec::Expectations::ExpectationNotMetError => e
44
+ e.message << "failed at model attribute: #{attribute}"
45
+ raise e
46
+ end
47
+ end
80
48
  end
81
49
  end
82
50
 
83
- def it_returns_collection_embedded_size(resource:, embeds:, size:)
84
- it "returns the correct number of embedded resource #{embeds} in the #{resource} collection" do
85
- resources = objectize_resources(last_response.body, root: resource)
86
- expect(resources.sample[embeds].length).to eql(size)
87
- end
88
- end
51
+ def it_returns_collection_size(options = {})
52
+ it "returns the correct number of resources in the #{options[:resource]} collection" do
53
+ collection = dispatcher.adapter.collection(options.merge(existing: true), last_response, self)
89
54
 
90
- def it_returns_embedded_size(resource:, embeds:, size:)
91
- it "returns the correct number of embedded resource #{embeds} in the #{resource} resource" do
92
- resource = objectize_resource(last_response.body, root: resource)
93
- expect(resource.send(embeds).length).to eql(size)
55
+ collection.has_size(options[:size])
94
56
  end
95
57
  end
96
58
 
97
- def it_returns_collection_attributes(resource:, attributes: [], subset: true)
98
- it "returns the correct attributes (no value checking) for each resource in the #{resource} collection" do
99
- resources = objectize_resources(last_response.body, root: resource.pluralize)
59
+ def it_returns_collection_attributes(options = {})
60
+ it "returns the correct attributes (no value checking) for resources in the #{options[:resource]} collection" do
61
+ sample_resource = dispatcher.adapter.collection(
62
+ options, last_response, self
63
+ ).sample(existing: true, resource: nil)
100
64
 
101
- resource_attributes_set = SortedSet.new(
102
- resources.sample.hash.keys.map(&:to_s)
103
- )
104
- checking_attributes_set = SortedSet.new(attributes.map(&:to_s).to_set)
105
-
106
- if subset
65
+ #support proc on attrs
66
+ options[:attrs].each do |attribute|
107
67
  begin
108
- expect(resource_attributes_set.superset?(checking_attributes_set)).to(
109
- eq(true)
110
- )
111
- rescue RSpec::Expectations::ExpectationNotMetError => _
112
- raise(
113
- $!,
114
- superset_mismatch_error(
115
- resource_attributes_set, checking_attributes_set
116
- ),
117
- $!.backtrace
118
- )
68
+ sample_resource.has_attribute(attribute)
69
+ rescue RSpec::Expectations::ExpectationNotMetError => e
70
+ e.message << "failed at model attribute: #{attribute}"
71
+ raise e
119
72
  end
120
- else
121
- expect(resource_attributes_set).to eq(checking_attributes_set)
122
73
  end
123
74
  end
124
75
  end
@@ -127,52 +78,35 @@ module Rspec
127
78
  :it_returns_collection_attributes
128
79
  )
129
80
 
130
- def it_returns_collection_embedded_resource_attributes(
131
- resource:, embeds:, attributes: [], subset: true
132
- )
133
- it "returns the correct attributes (no value checking) of #{embeds} resource inside #{resource} collection" do
134
- resource = objectize_resources(last_response.body, root: resource)
135
- embedded_resource = object_hash(resource.sample.send(embeds.to_sym))
136
-
137
- embedded_resource_attributes_set = SortedSet.new(
138
- embedded_resource.hash.keys.map(&:to_s)
139
- )
140
- checking_attributes_set = SortedSet.new(attributes.map(&:to_s).to_set)
81
+ def it_returns_no_collection_attributes(options = {})
82
+ it "expects returned collection (#{options[:resource]}) to NOT have the following attributes" do
83
+ sample_resource = dispatcher.adapter.collection(
84
+ options, last_response, self
85
+ ).sample(existing: false, resource: nil)
141
86
 
142
- if subset
87
+ #support proc on attrs
88
+ options[:attrs].each do |attribute|
143
89
  begin
144
- expect(
145
- embedded_resource_attributes_set.superset?(
146
- checking_attributes_set
147
- )
148
- ).to(
149
- eq(true)
150
- )
151
- rescue RSpec::Expectations::ExpectationNotMetError => _
152
- raise(
153
- $!,
154
- superset_mismatch_error(
155
- embedded_resource_attributes_set, checking_attributes_set
156
- ),
157
- $!.backtrace
158
- )
90
+ sample_resource.has_no_attribute(attribute)
91
+ rescue RSpec::Expectations::ExpectationNotMetError => e
92
+ e.message << "failed at model attribute: #{attribute}"
93
+ raise e
159
94
  end
160
- else
161
- expect(resource_attributes_set).to eq(checking_attributes_set)
162
95
  end
163
96
  end
164
-
165
97
  end
166
98
 
167
- def it_returns_no_collection_attributes(resource:, attributes: [])
168
- it "expects returned collection (#{resource}) to NOT have the following attributes" do
169
- resources = objectize_resources(
170
- last_response.body, root: resource.pluralize, existing: false
171
- )
99
+ #finds_by id
100
+ def it_returns_collection_attribute_values(options = {})
101
+ it "expects returned collection (#{options[:resource]}) to have model attribute values" do
102
+ resource = dispatcher.adapter.collection(
103
+ options, last_response, self
104
+ ).find_by(:id, existing: true, resource: nil)
172
105
 
173
- attributes.each do |attribute|
106
+ #support proc on attrs
107
+ options[:attrs].each do |attribute|
174
108
  begin
175
- expect(resources.sample.send(attribute)).to eql(:attribute_not_found)
109
+ resource.compare_attribute(attribute)
176
110
  rescue RSpec::Expectations::ExpectationNotMetError => e
177
111
  e.message << "failed at model attribute: #{attribute}"
178
112
  raise e
@@ -181,29 +115,36 @@ module Rspec
181
115
  end
182
116
  end
183
117
 
184
- def it_returns_no_collection_embedded_resource_attributes(
185
- resource:, embeds:, attributes: []
186
- )
187
- it "expects the embedded resource #{embeds} inside the returned collection (#{resource}) to NOT have the following attributes" do
188
- resources = objectize_resources(
189
- last_response.body, root: resource.pluralize
190
- )
118
+ =begin
119
+ #not tested
120
+ def it_returns_embedded_collection_size(options = {})
121
+ it "returns the correct number of embedded resource #{embeds} in the #{resource} resource" do
122
+ collection = dispatcher.adapter.resource(
123
+ options.merge(existing: true), last_response, self
124
+ ).embedded_collection
191
125
 
192
- embedded_resource = object_hash(
193
- resources.sample.send(embeds.to_sym), existing: false
194
- )
126
+ collection.has_size(options[:size])
127
+ end
128
+ end
129
+
130
+ def it_returns_collection_embedded_collection_size(options = {})
131
+ it "returns the correct number of embedded resource #{embeds} in the #{resource} collection" do
195
132
 
196
- attributes.each do |attribute|
197
- begin
198
- expect(embedded_resource.send(attribute)).to eql(:attribute_not_found)
199
- rescue RSpec::Expectations::ExpectationNotMetError => e
200
- e.message << "failed at model attribute: #{attribute}"
201
- raise e
202
- end
203
- end
204
133
  end
205
134
  end
206
135
 
136
+ def it_returns_collection_embedded_resource_attributes(options = {})
137
+ it "returns the correct attributes (no value checking) of #{embeds} resource inside #{resource} collection" do
138
+
139
+ end
140
+ end
141
+
142
+ def it_returns_no_collection_embedded_resource_attributes(options = {})
143
+ it "expects the embedded resource #{embeds} inside the returned collection (#{resource}) to NOT have the following attributes" do
144
+
145
+ end
146
+ end
147
+ =end
207
148
  end
208
149
  end
209
150
  end
@@ -3,67 +3,8 @@ require "rspec/api_helpers/version"
3
3
  module Rspec
4
4
  module ApiHelpers
5
5
  module ExampleMethods
6
- def objectize_resources(json, root:, existing: true)
7
- array = []
8
- array_hash = HashWithIndifferentAccess.new(JSON.parse(json))
9
-
10
- if root
11
- array_hash = array_hash[root]
12
- end
13
-
14
- array_hash.each do |resource|
15
- array << object_hash(resource, existing: existing)
16
- end
17
-
18
- return array
19
- end
20
-
21
- def objectize_resource(json, root:, existing: true)
22
- hash = HashWithIndifferentAccess.new(JSON.parse(json))
23
- if root
24
- obj = object_hash(hash[root], existing: existing)
25
- else
26
- obj = object_hash(hash, existing: existing)
27
- end
28
-
29
- return obj
30
- end
31
-
32
- def object_hash(hash, existing: true)
33
- ObjectHash.new(hash, existing: existing)
34
- end
35
-
36
- class ObjectHash
37
- #existing denotes whether we search for attributes that exist on the
38
- #resource or attributes that shouldn't exist
39
- attr_accessor :hash, :existing
40
- def initialize(hash, existing: true)
41
- @hash = HashWithIndifferentAccess.new(hash)
42
- @existing = existing
43
- end
44
- def method_missing(name)
45
- if existing
46
- if hash.key?(name)
47
- return hash[name]
48
- else
49
- return raise KeyError.new("Attribute not found in resource: #{name}")
50
- end
51
- else
52
- if hash.key?(name)
53
- return raise(
54
- KeyError.new(
55
- "Attribute found in resource when it shouldn't: #{name}"
56
- )
57
- )
58
- else
59
- return :attribute_not_found
60
- end
61
- end
62
- end
63
- end
64
-
65
- def superset_mismatch_error(superset, subset)
66
- "Expected \n #{subset.to_a.to_s} \n to be included in \n #{superset.to_a.to_s}"
6
+ def dispatcher
7
+ @dispatcher ||= Rspec::ApiHelpers::Dispatcher.new
67
8
  end
68
9
  end
69
10
  end
@@ -1,5 +1,5 @@
1
1
  module Rspec
2
2
  module Api
3
- VERSION = "0.2.1"
3
+ VERSION = "1.0.2"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-api_helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Filippos Vasilakis
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-10-13 00:00:00.000000000 Z
12
+ date: 2016-12-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -53,6 +53,12 @@ files:
53
53
  - README.md
54
54
  - Rakefile
55
55
  - lib/rspec/api_helpers.rb
56
+ - lib/rspec/api_helpers/adapter/active_model/adapter.rb
57
+ - lib/rspec/api_helpers/adapter/active_model/collection.rb
58
+ - lib/rspec/api_helpers/adapter/active_model/common_helpers.rb
59
+ - lib/rspec/api_helpers/adapter/active_model/resource.rb
60
+ - lib/rspec/api_helpers/adapter/jsonapi/adapter.rb
61
+ - lib/rspec/api_helpers/dispatcher.rb
56
62
  - lib/rspec/api_helpers/example_group_methods.rb
57
63
  - lib/rspec/api_helpers/example_methods.rb
58
64
  - lib/rspec/api_helpers/version.rb
@@ -77,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
83
  version: '0'
78
84
  requirements: []
79
85
  rubyforge_project:
80
- rubygems_version: 2.4.5
86
+ rubygems_version: 2.5.1
81
87
  signing_key:
82
88
  specification_version: 4
83
89
  summary: Rspec matchers for APIs