rspec_api_blueprint_matchers 0.1.2 → 0.1.3

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +33 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +26 -0
  5. data/.ruby-version +1 -0
  6. data/Rakefile +2 -1
  7. data/config/rubocop/.lint_rubocop.yml +749 -0
  8. data/config/rubocop/.metrics_rubocop.yml +94 -0
  9. data/config/rubocop/.performance_rubocop.yml +323 -0
  10. data/config/rubocop/.rails_rubocop.yml +256 -0
  11. data/config/rubocop/.style_rubocop.yml +2299 -0
  12. data/docker-compose.yml +17 -0
  13. data/lib/rspec_api_blueprint_matchers.rb +1 -0
  14. data/lib/rspec_apib/config.rb +1 -0
  15. data/lib/rspec_apib/elements/annotation.rb +1 -0
  16. data/lib/rspec_apib/elements/array.rb +1 -0
  17. data/lib/rspec_apib/elements/asset.rb +1 -0
  18. data/lib/rspec_apib/elements/base.rb +11 -10
  19. data/lib/rspec_apib/elements/category.rb +2 -1
  20. data/lib/rspec_apib/elements/copy.rb +2 -1
  21. data/lib/rspec_apib/elements/data_structure.rb +2 -0
  22. data/lib/rspec_apib/elements/href_variables.rb +3 -2
  23. data/lib/rspec_apib/elements/http_headers.rb +5 -4
  24. data/lib/rspec_apib/elements/http_message_payload.rb +3 -2
  25. data/lib/rspec_apib/elements/http_request.rb +16 -10
  26. data/lib/rspec_apib/elements/http_response.rb +3 -1
  27. data/lib/rspec_apib/elements/http_transaction.rb +4 -3
  28. data/lib/rspec_apib/elements/member.rb +3 -2
  29. data/lib/rspec_apib/elements/object.rb +2 -1
  30. data/lib/rspec_apib/elements/parse_result.rb +1 -0
  31. data/lib/rspec_apib/elements/resource.rb +1 -0
  32. data/lib/rspec_apib/elements/source_map.rb +1 -0
  33. data/lib/rspec_apib/elements/string.rb +1 -0
  34. data/lib/rspec_apib/elements/templated_href.rb +1 -0
  35. data/lib/rspec_apib/elements/transition.rb +1 -0
  36. data/lib/rspec_apib/elements.rb +1 -0
  37. data/lib/rspec_apib/extractors/http_transaction.rb +1 -0
  38. data/lib/rspec_apib/extractors/resource.rb +1 -0
  39. data/lib/rspec_apib/extractors.rb +1 -0
  40. data/lib/rspec_apib/parser.rb +2 -1
  41. data/lib/rspec_apib/request.rb +7 -10
  42. data/lib/rspec_apib/response.rb +2 -2
  43. data/lib/rspec_apib/rspec.rb +4 -3
  44. data/lib/rspec_apib/transaction_coverage_report.rb +4 -3
  45. data/lib/rspec_apib/transaction_coverage_validator.rb +4 -3
  46. data/lib/rspec_apib/transaction_validator.rb +1 -0
  47. data/lib/rspec_apib/transcluder.rb +2 -2
  48. data/lib/rspec_apib/version.rb +2 -1
  49. data/lib/rspec_apib.rb +2 -1
  50. data/lib/transcluder.rb +1 -0
  51. data/rspec_api_blueprint_matchers.gemspec +6 -4
  52. metadata +25 -2
@@ -0,0 +1,17 @@
1
+ version: '2'
2
+
3
+ services:
4
+ test:
5
+ image: rspec_api_blueprint_matchers
6
+ build:
7
+ context: .
8
+ dockerfile: Dockerfile
9
+ command: bash -c "bundle install && bundle exec rspec"
10
+ volumes:
11
+ - .:/app
12
+ - rubygems_cache:/rubygems
13
+ environment:
14
+ GEM_HOME: '/rubygems'
15
+ BUNDLE_PATH: '/rubygems'
16
+ volumes:
17
+ rubygems_cache:
@@ -1 +1,2 @@
1
+ # frozen_string_literal: true
1
2
  require "rspec_apib"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  class Config
3
4
  attr_accessor :default_blueprint_file
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
3
4
  class Annotation < Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
3
4
  class Array < ::Array
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
3
4
  class Asset < Base
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
3
- class Base < Struct.new(:element, :meta, :attributes, :content, :parent)
4
+ BaseStruct = Struct.new(:element, :meta, :attributes, :content, :parent)
4
5
 
5
- def inspect(*args)
6
+ # A base class for all objects in api-elements (http://api-elements.readthedocs.io/en/latest/)
7
+ class Base < BaseStruct
8
+ def inspect
6
9
  "##{self.class} (element: #{element}, meta: #{meta}, attributes: #{attributes.inspect}, content: #{content.inspect}, parent: ##{parent.class})"
7
10
  end
8
11
 
@@ -14,11 +17,11 @@ module RSpecApib
14
17
 
15
18
  def self.parse(node_or_nodes, index:, parent:, klass: nil)
16
19
  return node_or_nodes.map { |node| parse(node, index: index, parent: parent) } if node_or_nodes.is_a?(::Array)
17
- return transformed_basic_hash(node_or_nodes, index: index, parent: parent) if is_basic_hash?(node_or_nodes)
18
- return node_or_nodes unless !klass.nil? || is_base_element?(node_or_nodes)
20
+ return transformed_basic_hash(node_or_nodes, index: index, parent: parent) if basic_hash?(node_or_nodes)
21
+ return node_or_nodes unless !klass.nil? || base_element?(node_or_nodes)
19
22
  hash = node_or_nodes
20
23
  klass_name = klass
21
- klass_name ||= hash["element"].slice(0,1).capitalize + hash["element"].slice(1..-1).gsub(" ", "")
24
+ klass_name ||= hash["element"].slice(0, 1).capitalize + hash["element"].slice(1..-1).delete(" ")
22
25
  return node_or_nodes unless RSpecApib::Element.const_defined?(klass_name)
23
26
  klass = RSpecApib::Element.const_get(klass_name)
24
27
  index[klass] ||= []
@@ -61,12 +64,10 @@ module RSpecApib
61
64
  {}
62
65
  end
63
66
 
64
- def self.is_base_element?(node)
67
+ def self.base_element?(node)
65
68
  node.is_a?(::Hash) && node.keys.include?("element")
66
69
  end
67
70
 
68
- private
69
-
70
71
  def self.attributes_schema
71
72
  {}
72
73
  end
@@ -81,8 +82,8 @@ module RSpecApib
81
82
  node
82
83
  end
83
84
 
84
- def self.is_basic_hash?(node)
85
- node.is_a?(::Hash) && !is_base_element?(node)
85
+ def self.basic_hash?(node)
86
+ node.is_a?(::Hash) && !base_element?(node)
86
87
  end
87
88
 
88
89
  def self.transformed_basic_hash(node, index:, parent:)
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
4
+ # Represents a category in api-elements (http://api-elements.readthedocs.io/en/latest/)
3
5
  class Category < Base
4
-
5
6
  end
6
7
  end
7
8
  end
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
4
+ # Represents copy text in api-elements (http://api-elements.readthedocs.io/en/latest/)
3
5
  class Copy < Base
4
-
5
6
  end
6
7
  end
7
8
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
4
+ # Represents a data structure in api-elements (http://api-elements.readthedocs.io/en/latest/)
3
5
  class DataStructure < Base
4
6
 
5
7
  end
@@ -1,13 +1,14 @@
1
+ # frozen_string_literal: true
1
2
  require "addressable"
2
3
  module RSpecApib
3
4
  module Element
5
+ # Represents a collection of href variables in api-elements (http://api-elements.readthedocs.io/en/latest/)
4
6
  class HrefVariables < Base
5
7
  def [](key)
6
- member = content.find {|h| h.is_a?(Member) && h.content.key?(key) }
8
+ member = content.find { |h| h.is_a?(Member) && h.content.key?(key) }
7
9
  return nil if member.nil?
8
10
  member.content[key]
9
11
  end
10
-
11
12
  end
12
13
  end
13
14
  end
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
4
+ # Represents a collection of http headers in api-elements (http://api-elements.readthedocs.io/en/latest/)
3
5
  class HttpHeaders < Base
4
6
  def [](key)
5
- member = content.find {|h| h.is_a?(Member) && h.content.key?(key) }
7
+ member = content.find { |h| h.is_a?(Member) && h.content.key?(key) }
6
8
  return nil if member.nil?
7
9
  member.content[key]
8
10
  end
9
11
 
10
12
  def each_pair
11
- content.select {|h| h.is_a?(Member)}.each do |header|
13
+ content.select { |h| h.is_a?(Member) }.each do |header|
12
14
  yield header.key, header.value
13
15
  end
14
16
  end
@@ -16,12 +18,11 @@ module RSpecApib
16
18
  def keep_if
17
19
  results = dup
18
20
  results.content = []
19
- content.select {|h| h.is_a?(Member)}.each do |header|
21
+ content.select { |h| h.is_a?(Member) }.each do |header|
20
22
  results.content << header if yield header.key, header.value
21
23
  end
22
24
  results
23
25
  end
24
-
25
26
  end
26
27
  end
27
28
  end
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  require "json-schema"
2
3
  require "rspec_apib/elements/http_message_payload"
3
4
  module RSpecApib
4
5
  module Element
6
+ # Represents a http message payload in api-elements (http://api-elements.readthedocs.io/en/latest/)
5
7
  class HttpMessagePayload < Base
6
-
7
8
  # The content type if defined else nil
8
9
  # @return [String | NilClass] The content type header or nil
9
10
  def content_type
@@ -31,7 +32,7 @@ module RSpecApib
31
32
  reason: "Schema validation failure",
32
33
  details: errors
33
34
  }
34
- return [failure_reason]
35
+ [failure_reason]
35
36
  end
36
37
 
37
38
  private
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  require "json-schema"
2
3
  require "rspec_apib/elements/http_message_payload"
3
4
  module RSpecApib
4
5
  module Element
6
+ # Represents a http request in api-elements (http://api-elements.readthedocs.io/en/latest/)
5
7
  class HttpRequest < HttpMessagePayload
6
8
 
7
9
  # Indicates if the incoming request matches the method, path and path vars
@@ -9,8 +11,8 @@ module RSpecApib
9
11
  # @return [Boolean] true if matches else false
10
12
  def matches?(request, options: {})
11
13
  matches_method?(request) &&
12
- matches_path?(request) &&
13
- matches_headers?(request, options)
14
+ matches_path?(request) &&
15
+ matches_headers?(request, options)
14
16
  end
15
17
 
16
18
  # Inherit href and hrefVariables from any ancestor
@@ -30,10 +32,16 @@ module RSpecApib
30
32
  attributes && attributes["href"].to_s
31
33
  end
32
34
 
35
+ def self.attributes_schema
36
+ {
37
+ href: "TemplatedHref"
38
+ }
39
+ end
40
+
33
41
  private
34
42
 
35
- def matches_headers?(request_or_response, options)
36
- headers = attributes && attributes["headers"] && attributes["headers"].keep_if {|k, v| k == "Content-Type" || k == "Accept"}
43
+ def matches_headers?(request_or_response, _options)
44
+ headers = compared_headers
37
45
  return true if headers.nil?
38
46
  headers.each_pair do |header_key, header_value|
39
47
  return false unless request_or_response.headers.key?(header_key) &&
@@ -41,6 +49,10 @@ module RSpecApib
41
49
  end
42
50
  end
43
51
 
52
+ def compared_headers
53
+ attributes && attributes["headers"] && attributes["headers"].keep_if {|k, _v| k == "Content-Type" || k == "Accept"}
54
+ end
55
+
44
56
  def matches_method?(request)
45
57
  attributes && attributes["method"] && attributes["method"].downcase.to_sym == request.request_method
46
58
  end
@@ -48,12 +60,6 @@ module RSpecApib
48
60
  def matches_path?(request)
49
61
  attributes && attributes["href"] && attributes["href"].matches_path?(request)
50
62
  end
51
-
52
- def self.attributes_schema
53
- {
54
- href: "TemplatedHref"
55
- }
56
- end
57
63
  end
58
64
  end
59
65
  end
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
1
2
  require "rspec_apib/elements/http_message_payload"
2
3
  module RSpecApib
3
4
  module Element
5
+ # Represents a http response in api-elements (http://api-elements.readthedocs.io/en/latest/)
4
6
  class HttpResponse < HttpMessagePayload
5
7
  # Indicates if the incoming request matches the method, path and path vars
6
8
  # @param [::RSpecApib::Request] The incoming request - normalized
7
9
  # @return [Boolean] true if matches else false
8
10
  def matches?(response, options: {})
9
11
  matches_status?(response) &&
10
- matches_content_type?(response)
12
+ matches_content_type?(response)
11
13
  end
12
14
 
13
15
  def status
@@ -1,15 +1,16 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
4
+ # Represents a http transaction in api-elements (http://api-elements.readthedocs.io/en/latest/)
3
5
  class HttpTransaction < Base
4
-
5
6
  def matches?(request_in, response_in, options: {})
6
7
  request.matches?(request_in, options: options) && response.matches?(response_in, options: options)
7
8
  end
8
9
 
9
10
  def potential_match?(path:, request_method:, content_type:)
10
11
  potential_match_content_type?(content_type) &&
11
- (request_method == :any || request_method == request.request_method) &&
12
- (path == :any || request.path == path)
12
+ (request_method == :any || request_method == request.request_method) &&
13
+ (path == :any || request.path == path)
13
14
  end
14
15
 
15
16
  def validate_schema(request_in, response_in, validate_request_schema: :always, validate_response_schema: :always)
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
4
+ # Represents a member in api-elements (http://api-elements.readthedocs.io/en/latest/)
3
5
  class Member < Base
4
-
5
6
  def self.from_hash(hash, index:, parent:)
6
7
  child = super
7
8
  content = child.content
8
- child.content = {content["key"] => content["value"]}
9
+ child.content = { content["key"] => content["value"] }
9
10
  child
10
11
  end
11
12
 
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
4
+ # Represents an object request in api-elements (http://api-elements.readthedocs.io/en/latest/)
3
5
  class Object < Base
4
-
5
6
  end
6
7
  end
7
8
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
3
4
  class ParseResult < Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
3
4
  # (byebug) parent.parent["attributes"]
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
3
4
  class SourceMap < Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
3
4
  class String < ::String
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "addressable"
2
3
  module RSpecApib
3
4
  module Element
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Element
3
4
  class Transition < Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "rspec_apib/elements/base"
2
3
  require "rspec_apib/elements/parse_result"
3
4
  require "rspec_apib/elements/category"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Extractor
3
4
  class HttpTransaction
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module RSpecApib
2
3
  module Extractor
3
4
  class Resource
@@ -1,2 +1,3 @@
1
+ # frozen_string_literal: true
1
2
  require "rspec_apib/extractors/resource"
2
3
  require "rspec_apib/extractors/http_transaction"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "rspec_apib/transcluder"
2
3
  require "rspec_apib/extractors"
3
4
  require "rspec_apib/elements"
@@ -65,7 +66,7 @@ module RSpecApib
65
66
 
66
67
  def call_parser(file)
67
68
  op = nil
68
- Open3.popen3("#{bin_path} -f json") do |stdin, stdout, stderr, wait_thr|
69
+ Open3.popen3("#{bin_path} -f json") do |stdin, stdout, _stderr, wait_thr|
69
70
  transcluder.each_line(file) do |line|
70
71
  stdin.write line
71
72
  end
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require "forwardable"
1
3
  module RSpecApib
2
4
  class Request
5
+ extend Forwardable
3
6
  def initialize(request)
4
7
  self.raw_request = request
5
8
  end
@@ -8,19 +11,15 @@ module RSpecApib
8
11
  raw_request.method
9
12
  end
10
13
 
11
- def url
12
- raw_request.url
13
- end
14
+ delegate url: :raw_request
14
15
 
15
16
  def validate_body_with_json_schema?
16
- request_method != :get && is_json?
17
+ request_method != :get && json?
17
18
  end
18
19
 
19
20
  # The request body
20
21
  # @return [String] The request body - always as a string
21
- def body
22
- raw_request.body
23
- end
22
+ delegate body: :raw_request
24
23
 
25
24
  def content_type
26
25
  headers["Content-Type"]
@@ -30,15 +29,13 @@ module RSpecApib
30
29
  raw_request.request_headers
31
30
  end
32
31
 
33
-
34
32
  private
35
33
 
36
34
  attr_accessor :raw_request
37
35
 
38
- def is_json?
36
+ def json?
39
37
  content_type =~ /json/
40
38
  end
41
39
 
42
-
43
40
  end
44
41
  end