api_matchers 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. data/.gitignore +17 -0
  2. data/.rspec +1 -0
  3. data/.rvmrc +1 -0
  4. data/Gemfile +4 -0
  5. data/History.markdown +5 -0
  6. data/LICENSE +22 -0
  7. data/README.markdown +129 -0
  8. data/Rakefile +2 -0
  9. data/api_matchers.gemspec +21 -0
  10. data/lib/api_matchers/core/find_in_json.rb +25 -0
  11. data/lib/api_matchers/core/rspec_matchers.rb +49 -0
  12. data/lib/api_matchers/core/setup.rb +58 -0
  13. data/lib/api_matchers/headers/base.rb +14 -0
  14. data/lib/api_matchers/headers/be_json.rb +17 -0
  15. data/lib/api_matchers/headers/be_xml.rb +17 -0
  16. data/lib/api_matchers/http_status_code/base.rb +32 -0
  17. data/lib/api_matchers/http_status_code/be_bad_request.rb +17 -0
  18. data/lib/api_matchers/http_status_code/be_internal_server_error.rb +17 -0
  19. data/lib/api_matchers/http_status_code/be_unauthorized.rb +17 -0
  20. data/lib/api_matchers/http_status_code/create_resource.rb +17 -0
  21. data/lib/api_matchers/response_body/base.rb +46 -0
  22. data/lib/api_matchers/response_body/have_json_node.rb +25 -0
  23. data/lib/api_matchers/response_body/have_node.rb +6 -0
  24. data/lib/api_matchers/response_body/have_xml_node.rb +19 -0
  25. data/lib/api_matchers/version.rb +3 -0
  26. data/lib/api_matchers.rb +45 -0
  27. data/spec/api_matchers/core/find_in_json_spec.rb +27 -0
  28. data/spec/api_matchers/core/setup_spec.rb +4 -0
  29. data/spec/api_matchers/headers/base_spec.rb +12 -0
  30. data/spec/api_matchers/headers/be_json_spec.rb +23 -0
  31. data/spec/api_matchers/headers/be_xml_spec.rb +27 -0
  32. data/spec/api_matchers/http_status_code/base_spec.rb +12 -0
  33. data/spec/api_matchers/http_status_code/be_bad_request_spec.rb +43 -0
  34. data/spec/api_matchers/http_status_code/be_internal_server_error_spec.rb +43 -0
  35. data/spec/api_matchers/http_status_code/be_unauthorized_spec.rb +43 -0
  36. data/spec/api_matchers/http_status_code/create_resource_spec.rb +43 -0
  37. data/spec/api_matchers/response_body/base_spec.rb +47 -0
  38. data/spec/api_matchers/response_body/have_json_node_spec.rb +101 -0
  39. data/spec/api_matchers/response_body/have_node_spec.rb +27 -0
  40. data/spec/api_matchers/response_body/have_xml_node_spec.rb +102 -0
  41. data/spec/spec_helper.rb +10 -0
  42. metadata +134 -0
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 @@
1
+ --color -f d
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2@api_matchers --create
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in api_matchers.gemspec
4
+ gemspec
data/History.markdown ADDED
@@ -0,0 +1,5 @@
1
+ ## development
2
+
3
+ 1) Headers Matchers: be_xml, be_json (**OBS:** Need to think about the setup!)
4
+ 2) HTTP Status Matchers: be_a_bad_request, be_internal_server_error, be_unauthorized, create_resource
5
+ 3) Response body Matchers: have_node, have_json_node, have_xml_node
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Tomas D'Stefano
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.markdown ADDED
@@ -0,0 +1,129 @@
1
+ # API Matchers
2
+
3
+ Collection of RSpec matchers for create your API.
4
+
5
+ ## Matchers
6
+
7
+ * be_in_xml
8
+ * be_a_json
9
+ * create_resource
10
+ * be_a_bad_request
11
+ * be_unauthorized
12
+ * be_internal_server_error
13
+ * have_node
14
+ * have_json_node
15
+ * have_xml_node
16
+ * be_json_eql
17
+ * be_xml_eql
18
+
19
+ ## Install
20
+
21
+ gem install api_matchers
22
+
23
+ ## Usage
24
+
25
+ ### Have Node Matcher
26
+
27
+ "{ 'transaction': { 'id': '54', 'status': 'paid' } }".should have_node(:transaction)
28
+
29
+ "{ 'transaction': { 'id': '54', 'status': 'paid' } }".should have_node(:id).with(54)
30
+
31
+ "{ 'error': '', 'transaction': { 'id': '55', 'status': 'waiting_payment' } }".should have_node(:error).with('not_authorized')
32
+
33
+ If you want to configure to make all **searches inside a root element**, you can do this:
34
+
35
+ APIMatchers.setup do |config|
36
+ config.root_element = :transaction
37
+ end
38
+
39
+ "{ 'transaction': { 'id': '54', 'status': 'paid' } }".should have_node(:id).with(54) # WILL PASS
40
+
41
+ "{ 'error': '', 'transaction': { 'id': '55', 'status': 'waiting_payment' } }".should have_node(:error).with('not_authorized') # WILL NOT PASS BECAUSE THE ERROR NODE ISN'T INSIDE THE TRANSACTION NODE
42
+
43
+ ### HAVE NODE Matcher Configuration
44
+
45
+ You can configure if you want xml or json(**JSON is the default**):
46
+
47
+ APIMatchers.setup do |config|
48
+ config.content_type = :xml
49
+ end
50
+
51
+ '<transaction><id>200</id><status>paid</status></transaction>'.should have_node(:status).with('paid')
52
+
53
+ **Observation: You can use the *have_xml_node* or *have_json_node* if you don't want to configure everytime.**
54
+
55
+ You can configure the name of the method for example:
56
+
57
+ ## Instead of this
58
+ response.body.should have_node(:foo)
59
+
60
+ ## YOU can do this
61
+ APIMatchers.setup do |config|
62
+ config.body_method = :body
63
+ end
64
+
65
+ Then you can use without call the **#body** method:
66
+
67
+ response.should have_node(:foo).with('bar')
68
+
69
+ ### Create Resource Matcher
70
+
71
+ This matchers see the HTTP STATUS CODE is equal to 201.
72
+
73
+ response.status.should create_resource
74
+
75
+ ### BAD REQUEST Matcher
76
+
77
+ This BAD REQUEST is a matcher that see if the HTTP STATUS code is equal to 400.
78
+
79
+ response.status.should be_a_bad_request
80
+ response.status.should be_bad_request
81
+
82
+ ### UNAUTHORIZED Matcher
83
+
84
+ This UNAUTHORIZED is a matcher that see if the HTTP STATUS code is equal to 401.
85
+
86
+ response.status.should be_unauthorized
87
+ response.body.should have_node(:message).with('Invalid Credentials')
88
+
89
+ ### INTERNAL SERVER ERROR Matcher
90
+
91
+ This INTERNAL SERVER Error is a matcher that see if the HTTP STATUS code is equal to 500.
92
+
93
+ response.status.should be_internal_server_error
94
+ response.body.should have_node(:message).with('An Internal Error Occurs in our precious app. :S')
95
+
96
+ ### HTTP STATUS CODE Configuration
97
+
98
+ You can configure the name method to call the http status code:
99
+
100
+ APIMatchers.setup do |config|
101
+ config.http_status_method = :status
102
+ end
103
+
104
+ Then you can use without call the **#status** method:
105
+
106
+ response.should create_resource
107
+
108
+ This configurations affects this matchers:
109
+
110
+ * create_resource
111
+ * be_a_bad_request
112
+ * be_internal_server_error
113
+ * be_unauthorized
114
+
115
+ ### Be in XML Matcher
116
+
117
+ This is a matcher that see if the content type is xml:
118
+
119
+ response.content_type.should be_in_xml
120
+
121
+ ### Be in JSON Matcher
122
+
123
+ This is a matcher that see if the content type is in JSON:
124
+
125
+ response.content_type.should be_in_json
126
+
127
+ ### Acknowlegments
128
+
129
+ * Special thanks to Daniel Konishi to contribute in the product that I extracted the matchers to this gem.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/api_matchers/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Tomas D'Stefano"]
6
+ gem.email = ["tomas_stefano@successoft.com"]
7
+ gem.description = %q{Collection of RSpec matchers for create your API.}
8
+ gem.summary = %q{Collection of RSpec matchers for create your API.}
9
+ gem.homepage = "https://github.com/tomas-stefano/api_matchers"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "api_matchers"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = APIMatchers::VERSION
17
+
18
+ gem.add_dependency 'rspec', '>= 2.11.0'
19
+ gem.add_dependency 'activesupport', '>= 3.2.6'
20
+ gem.add_dependency 'nokogiri', '>= 1.5.5'
21
+ end
@@ -0,0 +1,25 @@
1
+ module APIMatchers
2
+ module Core
3
+ class FindInJSON
4
+ attr_reader :json
5
+
6
+ def initialize(json)
7
+ @json = json
8
+ end
9
+
10
+ def find(options={})
11
+ expected_key = options.fetch(:node).to_s
12
+
13
+ @json.each do |key, value|
14
+ if key == expected_key
15
+ return value
16
+ end
17
+ if value.is_a? Hash
18
+ return FindInJSON.new(value).find(node: expected_key)
19
+ end
20
+ end
21
+ nil # Don't find anything!
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,49 @@
1
+ module APIMatchers
2
+ module RSpecMatchers
3
+ def be_bad_request
4
+ ::APIMatchers::HTTPStatusCode::BeBadRequest.new(::APIMatchers::Core::Setup)
5
+ end
6
+ alias :be_a_bad_request :be_bad_request
7
+
8
+ def be_internal_server_error
9
+ ::APIMatchers::HTTPStatusCode::BeInternalServerError.new(::APIMatchers::Core::Setup)
10
+ end
11
+ alias :be_an_internal_server_error :be_internal_server_error
12
+
13
+ def be_unauthorized
14
+ ::APIMatchers::HTTPStatusCode::BeUnauthorized.new(::APIMatchers::Core::Setup)
15
+ end
16
+
17
+ def create_resource
18
+ ::APIMatchers::HTTPStatusCode::CreateResource.new(::APIMatchers::Core::Setup)
19
+ end
20
+ alias :created_resource :create_resource
21
+
22
+ def be_xml
23
+ ::APIMatchers::Headers::BeXML.new(::APIMatchers::Core::Setup)
24
+ end
25
+ alias :be_in_xml :be_xml
26
+
27
+ def be_json
28
+ ::APIMatchers::Headers::BeJSON.new(::APIMatchers::Core::Setup)
29
+ end
30
+ alias :be_in_json :be_json
31
+ alias :be_a_json :be_json
32
+
33
+ def have_json_node(expected_node)
34
+ ::APIMatchers::ResponseBody::HaveJsonNode.new(expected_node: expected_node, setup: ::APIMatchers::Core::Setup)
35
+ end
36
+
37
+ def have_xml_node(expected_node)
38
+ ::APIMatchers::ResponseBody::HaveXmlNode.new(expected_node: expected_node, setup: ::APIMatchers::Core::Setup)
39
+ end
40
+
41
+ def have_node(expected_node)
42
+ if ::APIMatchers::Core::Setup.have_node_matcher.equal?(:json)
43
+ have_json_node(expected_node)
44
+ else
45
+ have_xml_node(expected_node)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,58 @@
1
+ module APIMatchers
2
+ module Core
3
+ class Setup
4
+ # The http status method that will be called when you call http status matchers
5
+ #
6
+ # ==== Examples
7
+ #
8
+ # response.status.should create_resource
9
+ # response.status.should be_bad_request
10
+ # response.status.should be_unauthorized
11
+ #
12
+ # # Instead calling #status everytime, you can configure:
13
+ #
14
+ # APIMatchers.setup do |config|
15
+ # config.http_status_method = :status
16
+ # end
17
+ #
18
+ # Then:
19
+ #
20
+ # response.should create_resource
21
+ # response.should be_bad_request
22
+ # response.should be_unauthorized
23
+ #
24
+ cattr_accessor :http_status_method
25
+
26
+ # The response body method that will be called when you call the have_node matchers
27
+ #
28
+ # ==== Examples
29
+ #
30
+ # response.body.should have_node(:foo)
31
+ # response.body.should have_node(:bar)
32
+ # response.body.should have_node(:baz)
33
+ #
34
+ # # Instead calling #body everytime, you can configure:
35
+ #
36
+ # APIMatchers.setup do |config|
37
+ # config.http_status_method = :body
38
+ # end
39
+ #
40
+ # Then:
41
+ #
42
+ # response.should have_node(:foo)
43
+ # response.should have_node(:bar)
44
+ # response.should have_node(:baz)
45
+ #
46
+ cattr_accessor :response_body_method
47
+
48
+ # The default have node matcher that will be used.
49
+ # This have_node matcher is useful when you just work with one content type in your API.
50
+ # Change to :xml if you want that have_node works ONLY with XML.
51
+ # If you work with xml and json in the same API, I recommend that you check the
52
+ # have_json_node and have_xml_node matchers.
53
+ #
54
+ cattr_accessor :have_node_matcher
55
+ self.have_node_matcher = :json
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,14 @@
1
+ module APIMatchers
2
+ module Headers
3
+ class Base
4
+ def matches?(actual)
5
+ @actual = actual
6
+ actual.eql?(expected_content_type)
7
+ end
8
+
9
+ def expected_content_type
10
+ raise NotImplementedError, "not implemented on #{self}"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ module APIMatchers
2
+ module Headers
3
+ class BeJSON < Base
4
+ def expected_content_type
5
+ 'application/json; charset=utf-8'
6
+ end
7
+
8
+ def failure_message_for_should
9
+ %Q{expected a JSON response with '#{expected_content_type}'. Got: '#{@actual}'.}
10
+ end
11
+
12
+ def failure_message_for_should_not
13
+ %Q{expected to not be a JSON response. Got: '#{expected_content_type}'.}
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module APIMatchers
2
+ module Headers
3
+ class BeXML < Base
4
+ def expected_content_type
5
+ 'application/xml; charset=utf-8'
6
+ end
7
+
8
+ def failure_message_for_should
9
+ %Q{expected a XML response with '#{expected_content_type}'. Got: '#{@actual}'.}
10
+ end
11
+
12
+ def failure_message_for_should_not
13
+ %Q{expected to not be a XML response. Got: '#{expected_content_type}'.}
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,32 @@
1
+ module APIMatchers
2
+ module HTTPStatusCode
3
+ class Base
4
+ attr_reader :setup
5
+
6
+ def initialize(setup)
7
+ @setup = setup
8
+ end
9
+
10
+ # Matches the actual with the expected http status code
11
+ #
12
+ def matches?(actual)
13
+ @http_status_code = find_http_status_code(actual)
14
+ @http_status_code.equal?(expected_status_code)
15
+ end
16
+
17
+ def expected_status_code
18
+ raise NotImplementedError, "not implemented on #{self}"
19
+ end
20
+
21
+ # If have some configuration about the method to call on actual that method will be called.
22
+ #
23
+ def find_http_status_code(actual)
24
+ if @setup.http_status_method.present?
25
+ actual.send(@setup.http_status_method)
26
+ else
27
+ actual
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ module APIMatchers
2
+ module HTTPStatusCode
3
+ class BeBadRequest < Base
4
+ def expected_status_code
5
+ 400
6
+ end
7
+
8
+ def failure_message_for_should
9
+ %Q{expected that '#{@http_status_code}' to be a Bad Request with the status '400'.}
10
+ end
11
+
12
+ def failure_message_for_should_not
13
+ %Q{expected that '#{@http_status_code}' to NOT be a Bad Request with the status '400'.}
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module APIMatchers
2
+ module HTTPStatusCode
3
+ class BeInternalServerError < Base
4
+ def expected_status_code
5
+ 500
6
+ end
7
+
8
+ def failure_message_for_should
9
+ %Q{expected that '#{@http_status_code}' to be Internal Server Error with the status '500'.}
10
+ end
11
+
12
+ def failure_message_for_should_not
13
+ %Q{expected that '#{@http_status_code}' to NOT be Internal Server Error.}
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module APIMatchers
2
+ module HTTPStatusCode
3
+ class BeUnauthorized < Base
4
+ def expected_status_code
5
+ 401
6
+ end
7
+
8
+ def failure_message_for_should
9
+ %Q{expected that '#{@http_status_code}' to be Unauthorized with the status '401'.}
10
+ end
11
+
12
+ def failure_message_for_should_not
13
+ %Q{expected that '#{@http_status_code}' to NOT be Unauthorized.}
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module APIMatchers
2
+ module HTTPStatusCode
3
+ class CreateResource < Base
4
+ def expected_status_code
5
+ 201
6
+ end
7
+
8
+ def failure_message_for_should
9
+ %Q{expected that '#{@http_status_code}' to be Created Resource with the status '201'.}
10
+ end
11
+
12
+ def failure_message_for_should_not
13
+ %Q{expected that '#{@http_status_code}' to NOT be Created Resource.}
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,46 @@
1
+ module APIMatchers
2
+ module ResponseBody
3
+ class Base
4
+ attr_reader :setup, :expected_node, :actual
5
+ attr_writer :actual
6
+
7
+ def initialize(options={})
8
+ @expected_node = options.fetch(:expected_node)
9
+ @setup = options.fetch(:setup)
10
+ end
11
+
12
+ def matches?(actual)
13
+ raise NotImplementedError, "not implemented on #{self}"
14
+ end
15
+
16
+ def with(expected_value)
17
+ @with_value = expected_value
18
+ self
19
+ end
20
+
21
+ def response_body
22
+ if @setup.response_body_method.present?
23
+ @actual.send(@setup.response_body_method)
24
+ else
25
+ @actual
26
+ end
27
+ end
28
+
29
+ def failure_message_for_should
30
+ "expected to have node called: '#{@expected_node}'" << added_message << ". Got: '#{response_body}'"
31
+ end
32
+
33
+ def failure_message_for_should_not
34
+ "expected to NOT have node called: '#{@expected_node}'" << added_message << ". Got: '#{response_body}'"
35
+ end
36
+
37
+ def added_message
38
+ if @with_value
39
+ " with value: '#{@with_value}'"
40
+ else
41
+ ""
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,25 @@
1
+ require 'json'
2
+ require 'active_support/core_ext/hash'
3
+
4
+ module APIMatchers
5
+ module ResponseBody
6
+ class HaveJsonNode < Base
7
+ def matches?(actual)
8
+ @actual = actual
9
+ json = begin
10
+ JSON.parse(response_body)
11
+ rescue
12
+ {}
13
+ end
14
+
15
+ node = Core::FindInJSON.new(json).find(node: @expected_node.to_s)
16
+
17
+ if @with_value
18
+ node.to_s == @with_value.to_s
19
+ else
20
+ node.present?
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,6 @@
1
+ module APIMatchers
2
+ module ResponseBody
3
+ class HaveNode
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,19 @@
1
+ require 'nokogiri'
2
+
3
+ module APIMatchers
4
+ module ResponseBody
5
+ class HaveXmlNode < Base
6
+ def matches?(actual)
7
+ @actual = actual
8
+ xml = Nokogiri::XML(response_body)
9
+ node = xml.xpath("//#{@expected_node}").text
10
+
11
+ if @with_value
12
+ node == @with_value.to_s
13
+ else
14
+ node.present?
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module APIMatchers
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,45 @@
1
+ require "api_matchers/version"
2
+ require "active_support/core_ext/object"
3
+ require "active_support/core_ext/class"
4
+
5
+ module APIMatchers
6
+ autoload :RSpecMatchers, 'api_matchers/core/rspec_matchers'
7
+
8
+ # HTTP Status Code Matchers
9
+ #
10
+ module HTTPStatusCode
11
+ autoload :Base, 'api_matchers/http_status_code/base'
12
+ autoload :BeBadRequest, 'api_matchers/http_status_code/be_bad_request'
13
+ autoload :BeInternalServerError, 'api_matchers/http_status_code/be_internal_server_error'
14
+ autoload :BeUnauthorized, 'api_matchers/http_status_code/be_unauthorized'
15
+ autoload :CreateResource, 'api_matchers/http_status_code/create_resource'
16
+ end
17
+
18
+ # Content Type Matchers
19
+ #
20
+ module Headers
21
+ autoload :Base, 'api_matchers/headers/base'
22
+ autoload :BeXML, 'api_matchers/headers/be_xml'
23
+ autoload :BeJSON, 'api_matchers/headers/be_json'
24
+ end
25
+
26
+ # Response Body Matchers
27
+ #
28
+ module ResponseBody
29
+ autoload :Base, 'api_matchers/response_body/base'
30
+ autoload :HaveJsonNode, 'api_matchers/response_body/have_json_node'
31
+ autoload :HaveXmlNode, 'api_matchers/response_body/have_xml_node'
32
+ autoload :HaveNode, 'api_matchers/response_body/have_node'
33
+ end
34
+
35
+ # Core
36
+ #
37
+ module Core
38
+ autoload :FindInJSON, 'api_matchers/core/find_in_json'
39
+ autoload :Setup, 'api_matchers/core/setup'
40
+ end
41
+
42
+ def self.setup
43
+ yield(::APIMatchers::Core::Setup)
44
+ end
45
+ end