swagger-diff 1.0.5 → 1.1.0

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: 4b908f910198d381cab6749fceb46dc189fcb824
4
- data.tar.gz: f78caffe05399b68b448a021e7dd4b8c19ef1fba
3
+ metadata.gz: 7025ab8a26aa9eb452cbb399bf2fbde273f46299
4
+ data.tar.gz: 2a57c963078b714a2e1fa042ce12b2c3fbfa37a3
5
5
  SHA512:
6
- metadata.gz: 7e534c39a09234677cf591f360d1f329a6f511cc16a052bd2ec49a474bcc87413cd78b4ce40b8e0b8a5408e6b78e7655b6f575c55d16047c3910ed382ab3dad0
7
- data.tar.gz: d714909471d1c5d605d67c88f44fd07985d70abe94e1ba434b3a57522ab577f01e056fd91de566ff22e2c1c474cf44319576a02ef6b78b7e4ff4c871d1fc89a3
6
+ metadata.gz: 5963d3d5faf6c84097ffa29ab5cbe45a91b9b7dfa945571aa418ea6a1cb48c9c907a125f47df06c31f5f8b6bb4bdb0c0043a339d15fdb0ccebb6c4545e79b575
7
+ data.tar.gz: 5f3579dd89962e0ebb2e88440f8b195886a00002fc147b94e0369f81be4ec2a686dc008918e4a5b129374e089691ebbc3ecfdb57c60bc8359857d00b6da76127
@@ -2,7 +2,7 @@ Metrics/AbcSize:
2
2
  Max: 30
3
3
 
4
4
  Metrics/ClassLength:
5
- Max: 200
5
+ Max: 240
6
6
 
7
7
  Metrics/LineLength:
8
8
  Max: 120
@@ -1 +1 @@
1
- 2.2.3
1
+ 2.3.1
@@ -1,5 +1,13 @@
1
1
  language: ruby
2
2
  cache: bundler
3
+ rvm:
4
+ - 2.0
5
+ - 2.1.9
6
+ - 2.2.5
7
+ - 2.3.1
8
+ before_install:
9
+ - gem update --system
10
+ - rvm @global do gem install bundler
3
11
  branches:
4
12
  only:
5
13
  - master
@@ -1,49 +1,88 @@
1
1
  # Change Log
2
2
 
3
- ## 1.0.5 (2015-11-16)
3
+ All notable changes to this project will be documented in this file.
4
+ This project adheres to [Semantic Versioning](http://semver.org/).
4
5
 
5
- ### Bugs Fixed
6
+ ## [Unreleased]
7
+
8
+ ## [1.1.0] - 2016-05-20
9
+
10
+ ### Added
11
+
12
+ * Added a [Code of Conduct](CODE_OF_CONDUCT.md)
13
+ * Added a matrix build of 2.0, 2.1, 2.2, and 2.3 to Travis
14
+ * [#33](https://github.com/civisanalytics/swagger-diff/pull/33)
15
+ added a changelog feature
16
+ * [#35](https://github.com/civisanalytics/swagger-diff/pull/35)
17
+ print a warning if an OAI specification is invalid
18
+
19
+ ### Changed
20
+
21
+ * Bumped the Ruby version for development to 2.3.1
22
+ * Bumped the RuboCop version for development to 0.40
23
+ * Bumped the WebMock version for development to 2.0
24
+ * Bumped the Rake version for development to 11.1
25
+
26
+ ### Fixed
27
+
28
+ * [#27](https://github.com/civisanalytics/swagger-diff/pull/27)
29
+ made the Ruby 2.0+ dependency explicit
30
+ * [#32](https://github.com/civisanalytics/swagger-diff/pull/32)
31
+ replaced the Swagger parser
32
+
33
+ ## [1.0.5] - 2015-11-16
34
+
35
+ ### Fixed
6
36
 
7
37
  * [#18](https://github.com/civisanalytics/swagger-diff/pull/18)
8
38
  parse non-ref parameter schemas (`allOf`, `properties`, and `items`)
9
39
 
10
- ## 1.0.4 (2015-11-11)
40
+ ## [1.0.4] - 2015-11-11
11
41
 
12
- ### Bugs Fixed
42
+ ### Fixed
13
43
 
14
44
  * [#14](https://github.com/civisanalytics/swagger-diff/pull/14)
15
45
  allow schema definitions without properties
16
46
  * [#15](https://github.com/civisanalytics/swagger-diff/pull/15)
17
47
  parse non-ref response schemas (`allOf`, `properties`, and `items`)
18
48
 
19
- ## 1.0.3 (2015-11-04)
49
+ ## [1.0.3] - 2015-11-04
20
50
 
21
- ### Changes
51
+ ### Added
22
52
 
23
53
  * Added a default Rake task to run Rubocop and RSpec
24
54
  * Added [CONTRIBUTING.md](CONTRIBUTING.md)
25
55
 
26
- ### Bugs Fixed
56
+ ### Fixed
27
57
 
28
58
  * [#8](https://github.com/civisanalytics/swagger-diff/pull/8)
29
59
  fixed parsing of header and formData parameters
30
60
  * [#10](https://github.com/civisanalytics/swagger-diff/pull/10)
31
61
  detect if a parameter's location (*i.e.*, `in` value) changes
32
62
 
33
- ## 1.0.2 (2015-10-08)
63
+ ## [1.0.2] - 2015-10-08
34
64
 
35
- ### Bugs Fixed
65
+ ### Fixed
36
66
 
37
67
  * [#3](https://github.com/civisanalytics/swagger-diff/pull/3)
38
68
  treat required elements in new child parameters as backwards-compatible
39
69
 
40
- ## 1.0.1 (2015-10-01)
70
+ ## [1.0.1] - 2015-10-01
41
71
 
42
- ### Bugs Fixed
72
+ ### Fixed
43
73
 
44
74
  * [#1](https://github.com/civisanalytics/swagger-diff/pull/1)
45
75
  added missing rspec-expectations dependency
46
76
 
47
- ## 1.0.0 (2015-10-01)
77
+ ## [1.0.0] - 2015-10-01 - [YANKED]
48
78
 
49
79
  * Initial Release
80
+
81
+ [Unreleased]: https://github.com/civisanalytics/swagger-diff/compare/v1.1.0...HEAD
82
+ [1.1.0]: https://github.com/civisanalytics/swagger-diff/compare/v1.0.5...v1.1.0
83
+ [1.0.5]: https://github.com/civisanalytics/swagger-diff/compare/v1.0.4...v1.0.5
84
+ [1.0.4]: https://github.com/civisanalytics/swagger-diff/compare/v1.0.3...v1.0.4
85
+ [1.0.3]: https://github.com/civisanalytics/swagger-diff/compare/v1.0.2...v1.0.3
86
+ [1.0.2]: https://github.com/civisanalytics/swagger-diff/compare/v1.0.1...v1.0.2
87
+ [1.0.1]: https://github.com/civisanalytics/swagger-diff/compare/v1.0.0...v1.0.1
88
+ [1.0.0]: https://github.com/civisanalytics/swagger-diff/commit/0f6390eedef2428e78bbd816cbb14f724543f59b
@@ -0,0 +1,50 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This Code of Conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at opensource@civisanalytics.com.
39
+ All complaints will be reviewed and investigated and will result in a response
40
+ that is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+
45
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
46
+ version 1.3.0, available at
47
+ [http://contributor-covenant.org/version/1/3/0/][version]
48
+
49
+ [homepage]: http://contributor-covenant.org
50
+ [version]: http://contributor-covenant.org/version/1/3/0/
@@ -1,6 +1,8 @@
1
1
  # Contributing to Swagger::Diff
2
2
 
3
- We welcome pull requests from everyone!
3
+ We welcome bug reports and pull requests from everyone!
4
+ This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
5
+
4
6
 
5
7
  ## Getting Started
6
8
 
File without changes
data/README.md CHANGED
@@ -9,7 +9,8 @@
9
9
  > You can tell me by the way I walk - Genesis
10
10
 
11
11
  Swagger::Diff is a utility for comparing two different
12
- [Swagger](http://swagger.io/) specifications.
12
+ [Open API Initiative (OAI)](https://openapis.org/) specifications (fka
13
+ [Swagger](http://swagger.io/) specifications).
13
14
  Its intended use is to determine whether a newer API specification is
14
15
  backwards-compatible with an older API specification.
15
16
  It provides both an [RSpec](http://rspec.info/) matcher and helper functions
@@ -27,6 +28,9 @@ Specifications are considered backwards compatible if:
27
28
  - all response attributes in the old specification have the same type in the new
28
29
  one
29
30
 
31
+ It can also be used to enumerate all changes between two specifications (*i.e.*,
32
+ to generate a changelog).
33
+
30
34
  Read more on the [Civis Analytics blog](https://civisanalytics.com/blog/engineering/2015/10/02/using-swagger-to-detect-breaking-api-changes/).
31
35
 
32
36
  ## Installation
@@ -47,18 +51,15 @@ Or install it yourself as:
47
51
 
48
52
  ## Usage
49
53
 
50
- Swagger::Diff uses the [Swagger](https://github.com/swagger-rb/swagger-rb) gem
51
- to parse Swagger specifications.
52
- Specifications can be any
53
- [supported format](https://github.com/swagger-rb/swagger-rb/tree/v0.2.3#parsing):
54
+ Swagger specifications can be any valid Swagger file format, raw or parsed:
54
55
 
55
- - the path to a file containing a Swagger specification.
56
+ - the path to a file containing an OAI specification.
56
57
  This may be local (*e.g.*, `/path/to/swagger.json`) or remote (*e.g.*,
57
58
  `http://host.domain/swagger.yml`)
58
- - a Hash containing a parsed Swagger specification (*e.g.*, the output of
59
+ - a Hash containing a parsed OAI specification (*e.g.*, the output of
59
60
  `JSON.parse`)
60
- - a string of JSON containing a Swagger specification
61
- - a string of YAML containing a Swagger specification
61
+ - a string of JSON containing an OAI specification
62
+ - a string of YAML containing an OAI specification
62
63
 
63
64
  ### RSpec
64
65
 
@@ -97,17 +98,53 @@ request parameters, and response attributes; *e.g.*,
97
98
  }
98
99
  ```
99
100
 
101
+ You can also directly invoke the changes function:
102
+
103
+ ```ruby
104
+ diff = Swagger::Diff::Diff.new(<old>, <new>)
105
+ diff.changes
106
+ ```
107
+
108
+ `#changes` will return a hash containing the changed endpoints, request
109
+ parameters, and response attributes; *e.g.*,
110
+
111
+ ```ruby
112
+ { new_endpoints: ['delete /pets/{}', 'get /pets/{}', 'post /pets'],
113
+ new_request_params: {
114
+ 'get /pets' => ['new request param: tags (in: query, type: array)',
115
+ 'new request param: limit (in: query, type: integer)'] },
116
+ new_response_attributes: {},
117
+ removed_endpoints: [],
118
+ removed_request_params: {},
119
+ removed_response_attributes: {}
120
+ }
121
+ ```
122
+
100
123
  ### Command-Line
101
124
 
102
125
  It also includes a command-line version:
103
126
 
104
127
  ```bash
105
- $ swagger-diff <old> <new>
128
+ $ swagger-diff -i <old> <new>
106
129
  ```
107
130
 
108
131
  `swagger-diff` will print a list of any backwards-incompatibilities `new` has
109
132
  when compared to `old`.
110
133
 
134
+ For backwards-compatibility with previous versions of `swagger-diff`, the `-i`
135
+ argument is optional:
136
+
137
+ ```bash
138
+ $ swagger-diff <old> <new>
139
+ ```
140
+
141
+ The command-line version can also be used to generate a list of all changes
142
+ (*i.e.*, a changelog):
143
+
144
+ ```bash
145
+ $ swagger-diff -c <old> <new>
146
+ ```
147
+
111
148
  ## Gem Development
112
149
 
113
150
  After checking out the repo, run `bin/setup` to install dependencies.
@@ -122,4 +159,18 @@ See [CONTRIBUTING](CONTRIBUTING.md).
122
159
 
123
160
  ## License
124
161
 
125
- Swagger::Diff is released under the [BSD 3-Clause License](LICENSE.txt).
162
+ Swagger::Diff is released under the [BSD 3-Clause License](LICENSE.md).
163
+
164
+ ## OpenAPI (fka Swagger) Specification License
165
+
166
+ Swagger::Diff includes an
167
+ [unmodified copy of the OpenAPI Specification](schema/oai/schema.json).
168
+ The OpenAPI Specification is licensed under the
169
+ [Apache License, Version 2.0](schema/oai/LICENSE.md).
170
+
171
+ ## JSON Schema Specification License
172
+
173
+ Swagger::Diff includes an
174
+ [unmodified copy of the JSON Schema Specification, draft v4](schema/json/schema.json).
175
+ The JSON Schema Specification is licensed under the
176
+ [Simplified BSD License](schema/json/LICENSE.md).
@@ -1,17 +1,49 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'optparse'
3
4
  require 'swagger/diff'
4
5
 
6
+ options = {}
7
+ OptionParser.new do |opts|
8
+ opts.banner = 'Usage: swagger-diff [options] <old> <new>'
9
+
10
+ opts.on('-c', '--changes',
11
+ 'Generate a list of changes between <new>',
12
+ 'and <old>') do |c|
13
+ options[:changes] = c
14
+ end
15
+
16
+ opts.on('-i', '--incompatibilities',
17
+ 'Checks <new> for backwards-compatibility',
18
+ 'with <old>. If <new> is incompatible, a',
19
+ 'list of incompatibilities will be printed.') do |i|
20
+ options[:incompatibilities] = i
21
+ end
22
+
23
+ opts.on_tail('-h', '--help', 'This message') do
24
+ puts opts
25
+ exit
26
+ end
27
+
28
+ opts.on_tail('-v', '--version', 'Display the version') do
29
+ puts Swagger::Diff::VERSION
30
+ exit
31
+ end
32
+
33
+ options[:help] = opts
34
+ end.parse!
35
+
5
36
  if ARGV.length == 2
6
37
  diff = Swagger::Diff::Diff.new(ARGV[0], ARGV[1])
7
38
 
8
- unless diff.compatible?
9
- puts diff.incompatibilities_message
10
- exit 1
39
+ if options[:changes]
40
+ puts diff.changes_message
41
+ else
42
+ unless diff.compatible?
43
+ puts diff.incompatibilities_message
44
+ exit 1
45
+ end
11
46
  end
12
47
  else
13
- puts 'Usage: swagger-diff <old> <new>
14
-
15
- Checks <new> for backwards-compatibility with <old>. If <new> is incompatible,
16
- a list of incompatibilities will be printed.'
48
+ puts options[:help]
17
49
  end
@@ -1,8 +1,10 @@
1
- require 'forwardable' # Needed to require swagger-core.
2
- require 'swagger'
1
+ require 'json'
2
+ require 'open-uri'
3
+ require 'set'
4
+ require 'yaml'
5
+ require 'json-schema'
3
6
  require 'rspec/expectations'
4
7
  require 'swagger/diff/diff'
5
- require 'swagger/diff/patch'
6
8
  require 'swagger/diff/rspec_matchers'
7
9
  require 'swagger/diff/specification'
8
10
  require 'swagger/diff/version'
@@ -6,37 +6,69 @@ module Swagger
6
6
  @old_specification = Swagger::Diff::Specification.new(old)
7
7
  end
8
8
 
9
+ def changes
10
+ @changes ||= {
11
+ new_endpoints: new_endpoints.to_a.sort,
12
+ removed_endpoints: missing_endpoints.to_a.sort,
13
+ new_request_params: new_or_changed_request_params,
14
+ removed_request_params: incompatible_request_params,
15
+ new_response_attributes: new_or_changed_response_attributes,
16
+ removed_response_attributes: incompatible_response_attributes
17
+ }
18
+ end
19
+
20
+ def changes_message
21
+ changed_endpoints_message + changed_params_message + changed_attrs_message
22
+ end
23
+
9
24
  def compatible?
10
25
  endpoints_compatible? && requests_compatible? && responses_compatible?
11
26
  end
12
27
 
13
28
  def incompatibilities
14
- { endpoints: missing_endpoints.to_a.sort,
29
+ @incompatibilities ||= {
30
+ endpoints: missing_endpoints.to_a.sort,
15
31
  request_params: incompatible_request_params,
16
- response_attributes: incompatible_response_attributes }
32
+ response_attributes: incompatible_response_attributes
33
+ }
17
34
  end
18
35
 
19
36
  def incompatibilities_message
20
37
  msg = ''
21
- if incompatibilities[:endpoints]
22
- msg += incompatibilities_message_endpoints(incompatibilities[:endpoints])
23
- end
24
- if incompatibilities[:request_params]
25
- msg += incompatibilities_message_params(incompatibilities[:request_params])
26
- end
27
- if incompatibilities[:response_attributes]
28
- msg += incompatibilities_message_attributes(incompatibilities[:response_attributes])
29
- end
38
+ msg += endpoints_message('missing', incompatibilities[:endpoints])
39
+ msg += params_message('incompatible', incompatibilities[:request_params])
40
+ msg += attributes_message('incompatible', incompatibilities[:response_attributes])
30
41
  msg
31
42
  end
32
43
 
33
44
  private
34
45
 
35
- def incompatibilities_message_endpoints(endpoints)
46
+ def changed_endpoints_message
47
+ msg = ''
48
+ msg += endpoints_message('new', changes[:new_endpoints])
49
+ msg += endpoints_message('removed', changes[:removed_endpoints])
50
+ msg
51
+ end
52
+
53
+ def changed_params_message
54
+ msg = ''
55
+ msg += params_message('new', changes[:new_request_params])
56
+ msg += params_message('removed', changes[:removed_request_params])
57
+ msg
58
+ end
59
+
60
+ def changed_attrs_message
61
+ msg = ''
62
+ msg += attributes_message('new', changes[:new_response_attributes])
63
+ msg += attributes_message('removed', changes[:removed_response_attributes])
64
+ msg
65
+ end
66
+
67
+ def endpoints_message(type, endpoints)
36
68
  if endpoints.empty?
37
69
  ''
38
70
  else
39
- msg = "- missing endpoints\n"
71
+ msg = "- #{type} endpoints\n"
40
72
  endpoints.each do |endpoint|
41
73
  msg += " - #{endpoint}\n"
42
74
  end
@@ -44,11 +76,11 @@ module Swagger
44
76
  end
45
77
  end
46
78
 
47
- def incompatibilities_message_inner(typestr, collection)
79
+ def inner_message(nature, type, collection)
48
80
  if collection.nil? || collection.empty?
49
81
  ''
50
82
  else
51
- msg = "- incompatible #{typestr}\n"
83
+ msg = "- #{nature} #{type}\n"
52
84
  collection.sort.each do |endpoint, attributes|
53
85
  msg += " - #{endpoint}\n"
54
86
  attributes.each do |attribute|
@@ -59,27 +91,45 @@ module Swagger
59
91
  end
60
92
  end
61
93
 
62
- def incompatibilities_message_params(params)
63
- incompatibilities_message_inner('request params', params)
94
+ def params_message(type, params)
95
+ inner_message(type, 'request params', params)
64
96
  end
65
97
 
66
- def incompatibilities_message_attributes(attributes)
67
- incompatibilities_message_inner('response attributes', attributes)
98
+ def attributes_message(type, attributes)
99
+ inner_message(type, 'response attributes', attributes)
68
100
  end
69
101
 
70
102
  def missing_endpoints
71
103
  @old_specification.endpoints - @new_specification.endpoints
72
104
  end
73
105
 
74
- def incompatible_request_params
106
+ def new_endpoints
107
+ @new_specification.endpoints - @old_specification.endpoints
108
+ end
109
+
110
+ def change_hash(enumerator)
75
111
  ret = {}
76
- incompatible_request_params_enumerator.each do |key, val|
112
+ enumerator.each do |key, val|
77
113
  ret[key] ||= []
78
114
  ret[key] << val
79
115
  end
80
116
  ret
81
117
  end
82
118
 
119
+ def incompatible_request_params
120
+ change_hash(incompatible_request_params_enumerator)
121
+ end
122
+
123
+ def new_or_changed_request_params
124
+ enumerator = changed_request_params_enumerator(
125
+ @new_specification,
126
+ @old_specification,
127
+ '%{req} is no longer required',
128
+ 'new request param: %{req}'
129
+ )
130
+ change_hash(enumerator)
131
+ end
132
+
83
133
  def new_child?(req, old)
84
134
  idx = req.rindex('/')
85
135
  return false unless idx
@@ -87,49 +137,72 @@ module Swagger
87
137
  !old.any? { |param| param.start_with?(key) }
88
138
  end
89
139
 
90
- def incompatible_request_params_enumerator
140
+ def changed_request_params_enumerator(from, to, req_msg, missing_msg)
91
141
  Enumerator.new do |yielder|
92
- @old_specification.request_params.each do |key, old_params|
93
- new_params = @new_specification.request_params[key]
142
+ from.request_params.each do |key, old_params|
143
+ new_params = to.request_params[key]
94
144
  next if new_params.nil?
95
145
  (new_params[:required] - old_params[:required]).each do |req|
96
146
  next if new_child?(req, old_params[:all])
97
- yielder << [key, "new required request param: #{req}"]
147
+ yielder << [key, req_msg % { req: req }]
98
148
  end
99
149
  (old_params[:all] - new_params[:all]).each do |req|
100
- yielder << [key, "missing request param: #{req}"]
150
+ yielder << [key, missing_msg % { req: req }]
101
151
  end
102
152
  end
103
153
  end.lazy
104
154
  end
105
155
 
156
+ def incompatible_request_params_enumerator
157
+ changed_request_params_enumerator(
158
+ @old_specification,
159
+ @new_specification,
160
+ 'new required request param: %{req}',
161
+ 'missing request param: %{req}'
162
+ )
163
+ end
164
+
106
165
  def incompatible_response_attributes
107
- ret = {}
108
- incompatible_response_attributes_enumerator.each do |key, val|
109
- ret[key] ||= []
110
- ret[key] << val
111
- end
112
- ret
166
+ change_hash(incompatible_response_attributes_enumerator)
113
167
  end
114
168
 
115
- def incompatible_response_attributes_enumerator
169
+ def new_or_changed_response_attributes
170
+ enumerator = changed_response_attributes_enumerator(
171
+ @new_specification,
172
+ @old_specification,
173
+ 'new attribute for %{code} response: %{resp}',
174
+ 'new %{code} response'
175
+ )
176
+ change_hash(enumerator)
177
+ end
178
+
179
+ def changed_response_attributes_enumerator(from, to, attr_msg, code_msg)
116
180
  Enumerator.new do |yielder|
117
- @old_specification.response_attributes.each do |key, old_attributes|
118
- new_attributes = @new_specification.response_attributes[key]
181
+ from.response_attributes.each do |key, old_attributes|
182
+ new_attributes = to.response_attributes[key]
119
183
  next if new_attributes.nil?
120
184
  old_attributes.keys.each do |code|
121
185
  if new_attributes.key?(code)
122
186
  (old_attributes[code] - new_attributes[code]).each do |resp|
123
- yielder << [key, "missing attribute from #{code} response: #{resp}"]
187
+ yielder << [key, attr_msg % { code: code, resp: resp }]
124
188
  end
125
189
  else
126
- yielder << [key, "missing #{code} response"]
190
+ yielder << [key, code_msg % { code: code }]
127
191
  end
128
192
  end
129
193
  end
130
194
  end.lazy
131
195
  end
132
196
 
197
+ def incompatible_response_attributes_enumerator
198
+ changed_response_attributes_enumerator(
199
+ @old_specification,
200
+ @new_specification,
201
+ 'missing attribute from %{code} response: %{resp}',
202
+ 'missing %{code} response'
203
+ )
204
+ end
205
+
133
206
  def endpoints_compatible?
134
207
  missing_endpoints.empty?
135
208
  end