rspec-api_helpers 0.2.1 → 1.0.2

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: 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