open_api-loader 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +15 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.rubocop.yml +28 -0
- data/.travis.yml +24 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +99 -0
- data/Rakefile +10 -0
- data/bin/console +6 -0
- data/bin/setup +6 -0
- data/lib/open_api-loader.rb +1 -0
- data/lib/open_api/loader.rb +44 -0
- data/lib/open_api/loader/collector.rb +61 -0
- data/lib/open_api/loader/denormalizer.rb +27 -0
- data/lib/open_api/loader/denormalizer/parameters.rb +46 -0
- data/lib/open_api/loader/denormalizer/security.rb +35 -0
- data/lib/open_api/loader/denormalizer/servers.rb +36 -0
- data/lib/open_api/loader/denormalizer/variables.rb +54 -0
- data/lib/open_api/loader/reader.rb +47 -0
- data/lib/open_api/loader/ref.rb +85 -0
- data/lib/open_api/loader/translator.rb +50 -0
- data/lib/open_api/loader/translator/clean_definitions.rb +16 -0
- data/lib/open_api/loader/translator/convert_bodies.rb +77 -0
- data/lib/open_api/loader/translator/convert_forms.rb +71 -0
- data/lib/open_api/loader/translator/convert_parameters.rb +135 -0
- data/lib/open_api/loader/translator/convert_responses.rb +63 -0
- data/lib/open_api/loader/translator/convert_security_schemes.rb +49 -0
- data/lib/open_api/loader/translator/convert_servers.rb +46 -0
- data/lib/open_api/loader/translator/convert_version.rb +12 -0
- data/lib/open_api/loader/translator/denormalize_consumes.rb +44 -0
- data/lib/open_api/loader/translator/denormalize_parameters.rb +55 -0
- data/lib/open_api/loader/translator/denormalize_produces.rb +53 -0
- data/open_api-loader.gemspec +25 -0
- data/spec/fixtures/oas2/collected.yaml +1012 -0
- data/spec/fixtures/oas2/denormalized.yaml +1462 -0
- data/spec/fixtures/oas2/loaded.yaml +564 -0
- data/spec/fixtures/oas2/models.yaml +118 -0
- data/spec/fixtures/oas2/source.json +1 -0
- data/spec/fixtures/oas2/source.yaml +569 -0
- data/spec/fixtures/oas2/translated.yaml +1396 -0
- data/spec/fixtures/oas3/collected.yaml +233 -0
- data/spec/fixtures/oas3/denormalized.yaml +233 -0
- data/spec/fixtures/oas3/source.json +1 -0
- data/spec/fixtures/oas3/source.yaml +217 -0
- data/spec/loader_spec.rb +53 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/fixture_helpers.rb +18 -0
- data/spec/support/path_helpers.rb +27 -0
- data/spec/unit/collector_spec.rb +31 -0
- data/spec/unit/denormalizer_spec.rb +17 -0
- data/spec/unit/reader_spec.rb +53 -0
- data/spec/unit/ref_spec.rb +107 -0
- data/spec/unit/translator_spec.rb +15 -0
- metadata +232 -0
@@ -0,0 +1 @@
|
|
1
|
+
{"openapi":"3.0.0","servers":[{"url":"{scheme}://developer.uspto.gov/ds-api","variables":{"scheme":{"description":"The Data Set API is accessible via https and http","enum":["https","http"],"default":"https"}}}],"info":{"description":"The Data Set API (DSAPI) allows the public users to discover and search USPTO exported data sets. This is a generic API that allows USPTO users to make any CSV based data files searchable through API. With the help of GET call, it returns the list of data fields that are searchable. With the help of POST call, data can be fetched based on the filters on the field names. Please note that POST call is used to search the actual data. The reason for the POST call is that it allows users to specify any complex search criteria without worry about the GET size limitations as well as encoding of the input parameters.","version":"1.0.0","title":"USPTO Data Set API","contact":{"name":"Open Data Portal","url":"https://developer.uspto.gov","email":"developer@uspto.gov"}},"tags":[{"name":"metadata","description":"Find out about the data sets"},{"name":"search","description":"Search a data set"}],"paths":{"/":{"get":{"tags":["metadata"],"operationId":"list-data-sets","summary":"List available data sets","responses":{"200":{"description":"Returns a list of data sets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/dataSetList"},"example":{"total":2,"apis":[{"apiKey":"oa_citations","apiVersionNumber":"v1","apiUrl":"https://developer.uspto.gov/ds-api/oa_citations/v1/fields","apiDocumentationUrl":"https://developer.uspto.gov/ds-api-docs/index.html?url=https://developer.uspto.gov/ds-api/swagger/docs/oa_citations.json"},{"apiKey":"cancer_moonshot","apiVersionNumber":"v1","apiUrl":"https://developer.uspto.gov/ds-api/cancer_moonshot/v1/fields","apiDocumentationUrl":"https://developer.uspto.gov/ds-api-docs/index.html?url=https://developer.uspto.gov/ds-api/swagger/docs/cancer_moonshot.json"}]}}}}}}},"/{dataset}/{version}/fields":{"parameters":[{"name":"dataset","in":"path","description":"Name of the dataset. In this case, the default value is oa_citations","required":true,"schema":{"type":"string","default":"oa_citations"}},{"name":"version","in":"path","description":"Version of the dataset.","required":true,"schema":{"type":"string","default":"v1"}}],"get":{"tags":["metadata"],"summary":"Provides the general information about the API and the list of fields that can be used to query the dataset.","description":"This GET API returns the list of all the searchable field names that are in the oa_citations. Please see the 'fields' attribute which returns an array of field names. Each field or a combination of fields can be searched using the syntax options shown below.","operationId":"list-searchable-fields","responses":{"200":{"description":"The dataset api for the given version is found and it is accessible to consume.","content":{"application/json":{"schema":{"type":"string"}}}},"404":{"description":"The combination of dataset name and version is not found in the system or it is not published yet to be consumed by public.","content":{"application/json":{"schema":{"type":"string"}}}}}}},"/{dataset}/{version}/records":{"parameters":[{"name":"version","in":"path","description":"Version of the dataset.","required":true,"schema":{"type":"string","default":"v1"}},{"name":"dataset","in":"path","description":"Name of the dataset. In this case, the default value is oa_citations","required":true,"schema":{"type":"string","default":"oa_citations"}}],"post":{"tags":["search"],"summary":"Provides search capability for the data set with the given search criteria.","description":"This API is based on Solr/Lucense Search. The data is indexed using SOLR. This GET API returns the list of all the searchable field names that are in the Solr Index. Please see the 'fields' attribute which returns an array of field names. Each field or a combination of fields can be searched using the Solr/Lucene Syntax. Please refer https://lucene.apache.org/core/3_6_2/queryparsersyntax.html#Overview for the query syntax. List of field names that are searchable can be determined using above GET api.","operationId":"perform-search","responses":{"200":{"description":"successful operation","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":{"type":"object"}}}}}},"404":{"description":"No matching record found for the given criteria."}},"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"criteria":{"description":"Uses Lucene Query Syntax in the format of propertyName:value, propertyName:[num1 TO num2] and date range format: propertyName:[yyyyMMdd TO yyyyMMdd]. In the response please see the 'docs' element which has the list of record objects. Each record structure would consist of all the fields and their corresponding values.","type":"string","default":"*:*"},"start":{"description":"Starting record number. Default value is 0.","type":"integer","default":0},"rows":{"description":"Specify number of rows to be returned. If you run the search with default values, in the response you will see 'numFound' attribute which will tell the number of records available in the dataset.","type":"integer","default":100}},"required":["criteria"]}}}}}}},"components":{"schemas":{"dataSetList":{"type":"object","properties":{"total":{"type":"integer"},"apis":{"type":"array","items":{"type":"object","properties":{"apiKey":{"type":"string","description":"To be used as a dataset parameter value"},"apiVersionNumber":{"type":"string","description":"To be used as a version parameter value"},"apiUrl":{"type":"string","format":"uriref","description":"The URL describing the dataset's fields"},"apiDocumentationUrl":{"type":"string","format":"uriref","description":"A URL to the API console for each API"}}}}}}}}}
|
@@ -0,0 +1,217 @@
|
|
1
|
+
#
|
2
|
+
# The OAS3 specification downloaded from
|
3
|
+
# https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/uspto.yaml
|
4
|
+
#
|
5
|
+
# The source.json contain exactly the same data in JSON format
|
6
|
+
#
|
7
|
+
---
|
8
|
+
openapi: 3.0.0
|
9
|
+
servers:
|
10
|
+
- url: '{scheme}://developer.uspto.gov/ds-api'
|
11
|
+
variables:
|
12
|
+
scheme:
|
13
|
+
description: 'The Data Set API is accessible via https and http'
|
14
|
+
enum:
|
15
|
+
- 'https'
|
16
|
+
- 'http'
|
17
|
+
default: 'https'
|
18
|
+
info:
|
19
|
+
description: >-
|
20
|
+
The Data Set API (DSAPI) allows the public users to discover and search
|
21
|
+
USPTO exported data sets. This is a generic API that allows USPTO users to
|
22
|
+
make any CSV based data files searchable through API. With the help of GET
|
23
|
+
call, it returns the list of data fields that are searchable. With the help
|
24
|
+
of POST call, data can be fetched based on the filters on the field names.
|
25
|
+
Please note that POST call is used to search the actual data. The reason for
|
26
|
+
the POST call is that it allows users to specify any complex search criteria
|
27
|
+
without worry about the GET size limitations as well as encoding of the
|
28
|
+
input parameters.
|
29
|
+
version: 1.0.0
|
30
|
+
title: USPTO Data Set API
|
31
|
+
contact:
|
32
|
+
name: Open Data Portal
|
33
|
+
url: 'https://developer.uspto.gov'
|
34
|
+
email: developer@uspto.gov
|
35
|
+
tags:
|
36
|
+
- name: metadata
|
37
|
+
description: Find out about the data sets
|
38
|
+
- name: search
|
39
|
+
description: Search a data set
|
40
|
+
paths:
|
41
|
+
/:
|
42
|
+
get:
|
43
|
+
tags:
|
44
|
+
- metadata
|
45
|
+
operationId: list-data-sets
|
46
|
+
summary: List available data sets
|
47
|
+
responses:
|
48
|
+
200:
|
49
|
+
description: Returns a list of data sets
|
50
|
+
content:
|
51
|
+
application/json:
|
52
|
+
schema:
|
53
|
+
$ref: '#/components/schemas/dataSetList'
|
54
|
+
example:
|
55
|
+
{
|
56
|
+
"total": 2,
|
57
|
+
"apis": [
|
58
|
+
{
|
59
|
+
"apiKey": "oa_citations",
|
60
|
+
"apiVersionNumber": "v1",
|
61
|
+
"apiUrl": "https://developer.uspto.gov/ds-api/oa_citations/v1/fields",
|
62
|
+
"apiDocumentationUrl": "https://developer.uspto.gov/ds-api-docs/index.html?url=https://developer.uspto.gov/ds-api/swagger/docs/oa_citations.json"
|
63
|
+
},
|
64
|
+
{
|
65
|
+
"apiKey": "cancer_moonshot",
|
66
|
+
"apiVersionNumber": "v1",
|
67
|
+
"apiUrl": "https://developer.uspto.gov/ds-api/cancer_moonshot/v1/fields",
|
68
|
+
"apiDocumentationUrl": "https://developer.uspto.gov/ds-api-docs/index.html?url=https://developer.uspto.gov/ds-api/swagger/docs/cancer_moonshot.json"
|
69
|
+
}
|
70
|
+
]
|
71
|
+
}
|
72
|
+
/{dataset}/{version}/fields:
|
73
|
+
parameters:
|
74
|
+
- name: dataset
|
75
|
+
in: path
|
76
|
+
description: 'Name of the dataset. In this case, the default value is oa_citations'
|
77
|
+
required: true
|
78
|
+
schema:
|
79
|
+
type: string
|
80
|
+
default: oa_citations
|
81
|
+
- name: version
|
82
|
+
in: path
|
83
|
+
description: Version of the dataset.
|
84
|
+
required: true
|
85
|
+
schema:
|
86
|
+
type: string
|
87
|
+
default: v1
|
88
|
+
get:
|
89
|
+
tags:
|
90
|
+
- metadata
|
91
|
+
summary: >-
|
92
|
+
Provides the general information about the API and the list of fields
|
93
|
+
that can be used to query the dataset.
|
94
|
+
description: >-
|
95
|
+
This GET API returns the list of all the searchable field names that are
|
96
|
+
in the oa_citations. Please see the 'fields' attribute which returns an
|
97
|
+
array of field names. Each field or a combination of fields can be
|
98
|
+
searched using the syntax options shown below.
|
99
|
+
operationId: list-searchable-fields
|
100
|
+
responses:
|
101
|
+
200:
|
102
|
+
description: >-
|
103
|
+
The dataset api for the given version is found and it is accessible
|
104
|
+
to consume.
|
105
|
+
content:
|
106
|
+
application/json:
|
107
|
+
schema:
|
108
|
+
type: string
|
109
|
+
404:
|
110
|
+
description: >-
|
111
|
+
The combination of dataset name and version is not found in the
|
112
|
+
system or it is not published yet to be consumed by public.
|
113
|
+
content:
|
114
|
+
application/json:
|
115
|
+
schema:
|
116
|
+
type: string
|
117
|
+
/{dataset}/{version}/records:
|
118
|
+
parameters:
|
119
|
+
- name: version
|
120
|
+
in: path
|
121
|
+
description: Version of the dataset.
|
122
|
+
required: true
|
123
|
+
schema:
|
124
|
+
type: string
|
125
|
+
default: v1
|
126
|
+
- name: dataset
|
127
|
+
in: path
|
128
|
+
description: 'Name of the dataset. In this case, the default value is oa_citations'
|
129
|
+
required: true
|
130
|
+
schema:
|
131
|
+
type: string
|
132
|
+
default: oa_citations
|
133
|
+
post:
|
134
|
+
tags:
|
135
|
+
- search
|
136
|
+
summary: >-
|
137
|
+
Provides search capability for the data set with the given search
|
138
|
+
criteria.
|
139
|
+
description: >-
|
140
|
+
This API is based on Solr/Lucense Search. The data is indexed using
|
141
|
+
SOLR. This GET API returns the list of all the searchable field names
|
142
|
+
that are in the Solr Index. Please see the 'fields' attribute which
|
143
|
+
returns an array of field names. Each field or a combination of fields
|
144
|
+
can be searched using the Solr/Lucene Syntax. Please refer
|
145
|
+
https://lucene.apache.org/core/3_6_2/queryparsersyntax.html#Overview for
|
146
|
+
the query syntax. List of field names that are searchable can be
|
147
|
+
determined using above GET api.
|
148
|
+
operationId: perform-search
|
149
|
+
responses:
|
150
|
+
200:
|
151
|
+
description: successful operation
|
152
|
+
content:
|
153
|
+
application/json:
|
154
|
+
schema:
|
155
|
+
type: array
|
156
|
+
items:
|
157
|
+
type: object
|
158
|
+
additionalProperties:
|
159
|
+
type: object
|
160
|
+
404:
|
161
|
+
description: No matching record found for the given criteria.
|
162
|
+
requestBody:
|
163
|
+
content:
|
164
|
+
application/x-www-form-urlencoded:
|
165
|
+
schema:
|
166
|
+
type: object
|
167
|
+
properties:
|
168
|
+
criteria:
|
169
|
+
description: >-
|
170
|
+
Uses Lucene Query Syntax in the format of
|
171
|
+
propertyName:value, propertyName:[num1 TO num2] and date
|
172
|
+
range format: propertyName:[yyyyMMdd TO yyyyMMdd]. In the
|
173
|
+
response please see the 'docs' element which has the list of
|
174
|
+
record objects. Each record structure would consist of all
|
175
|
+
the fields and their corresponding values.
|
176
|
+
type: string
|
177
|
+
default: '*:*'
|
178
|
+
start:
|
179
|
+
description: Starting record number. Default value is 0.
|
180
|
+
type: integer
|
181
|
+
default: 0
|
182
|
+
rows:
|
183
|
+
description: >-
|
184
|
+
Specify number of rows to be returned. If you run the search
|
185
|
+
with default values, in the response you will see 'numFound'
|
186
|
+
attribute which will tell the number of records available in
|
187
|
+
the dataset.
|
188
|
+
type: integer
|
189
|
+
default: 100
|
190
|
+
required:
|
191
|
+
- criteria
|
192
|
+
components:
|
193
|
+
schemas:
|
194
|
+
dataSetList:
|
195
|
+
type: object
|
196
|
+
properties:
|
197
|
+
total:
|
198
|
+
type: integer
|
199
|
+
apis:
|
200
|
+
type: array
|
201
|
+
items:
|
202
|
+
type: object
|
203
|
+
properties:
|
204
|
+
apiKey:
|
205
|
+
type: string
|
206
|
+
description: To be used as a dataset parameter value
|
207
|
+
apiVersionNumber:
|
208
|
+
type: string
|
209
|
+
description: To be used as a version parameter value
|
210
|
+
apiUrl:
|
211
|
+
type: string
|
212
|
+
format: uriref
|
213
|
+
description: "The URL describing the dataset's fields"
|
214
|
+
apiDocumentationUrl:
|
215
|
+
type: string
|
216
|
+
format: uriref
|
217
|
+
description: A URL to the API console for each API
|
data/spec/loader_spec.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
RSpec.describe OpenAPI::Loader do
|
2
|
+
subject { described_class.call(source, **options) }
|
3
|
+
|
4
|
+
let(:options) { {} }
|
5
|
+
|
6
|
+
context "with OAS 2" do
|
7
|
+
context "in YAML" do
|
8
|
+
let(:source) { "spec/fixtures/oas2/source.yaml" }
|
9
|
+
let(:target) { yaml_fixture_file "oas2/denormalized.yaml" }
|
10
|
+
|
11
|
+
it { is_expected.to eq target }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "in JSON" do
|
15
|
+
let(:source) { "spec/fixtures/oas2/source.json" }
|
16
|
+
let(:target) { yaml_fixture_file "oas2/denormalized.yaml" }
|
17
|
+
|
18
|
+
it { is_expected.to eq target }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "with option denormalize: false" do
|
22
|
+
let(:source) { "spec/fixtures/oas2/source.yaml" }
|
23
|
+
let(:target) { yaml_fixture_file "oas2/translated.yaml" }
|
24
|
+
let(:options) { { denormalize: false } }
|
25
|
+
|
26
|
+
it { is_expected.to eq target }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with OAS 3" do
|
31
|
+
context "in YAML" do
|
32
|
+
let(:source) { "spec/fixtures/oas3/source.yaml" }
|
33
|
+
let(:target) { yaml_fixture_file "oas3/denormalized.yaml" }
|
34
|
+
|
35
|
+
it { is_expected.to eq target }
|
36
|
+
end
|
37
|
+
|
38
|
+
context "in JSON" do
|
39
|
+
let(:source) { "spec/fixtures/oas3/source.json" }
|
40
|
+
let(:target) { yaml_fixture_file "oas3/denormalized.yaml" }
|
41
|
+
|
42
|
+
it { is_expected.to eq target }
|
43
|
+
end
|
44
|
+
|
45
|
+
context "with option denormalize: false" do
|
46
|
+
let(:source) { "spec/fixtures/oas3/source.yaml" }
|
47
|
+
let(:target) { yaml_fixture_file "oas3/collected.yaml" }
|
48
|
+
let(:options) { { denormalize: false } }
|
49
|
+
|
50
|
+
it { is_expected.to eq target }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require "pry"
|
3
|
+
require "webmock/rspec"
|
4
|
+
require "open_api/loader"
|
5
|
+
require "rspec/its"
|
6
|
+
|
7
|
+
require_relative "support/fixture_helpers"
|
8
|
+
require_relative "support/path_helpers"
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
12
|
+
config.expect_with(:rspec) { |c| c.syntax = :expect }
|
13
|
+
|
14
|
+
config.order = :random
|
15
|
+
config.filter_run focus: true
|
16
|
+
config.run_all_when_everything_filtered = true
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
def fixture_file_path(filename)
|
5
|
+
File.expand_path "spec/fixtures/#{filename}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def read_fixture_file(filename)
|
9
|
+
File.read fixture_file_path(filename)
|
10
|
+
end
|
11
|
+
|
12
|
+
def yaml_fixture_file(filename, **_params)
|
13
|
+
YAML.load read_fixture_file(filename)
|
14
|
+
end
|
15
|
+
|
16
|
+
def json_fixture_file(filename)
|
17
|
+
JSON.parse read_fixture_file(filename)
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
def local_path(content)
|
2
|
+
file = Tempfile.create ""
|
3
|
+
File.write file, content
|
4
|
+
file.path
|
5
|
+
end
|
6
|
+
|
7
|
+
def remote_path(content)
|
8
|
+
path = "https://www.example.com/source"
|
9
|
+
stub_request(:get, path).to_return(body: content)
|
10
|
+
path
|
11
|
+
end
|
12
|
+
|
13
|
+
def yaml_local_path(data)
|
14
|
+
local_path YAML.dump(data)
|
15
|
+
end
|
16
|
+
|
17
|
+
def yaml_remote_path(data)
|
18
|
+
remote_path YAML.dump(data)
|
19
|
+
end
|
20
|
+
|
21
|
+
def json_local_path(data)
|
22
|
+
local_path JSON.dump(data)
|
23
|
+
end
|
24
|
+
|
25
|
+
def json_remote_path(data)
|
26
|
+
remote_path JSON.dump(data)
|
27
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
RSpec.describe OpenAPI::Loader::Collector, ".call" do
|
2
|
+
subject { described_class.call(source) }
|
3
|
+
|
4
|
+
context "OAS 2" do
|
5
|
+
let(:target) { yaml_fixture_file "oas2/collected.yaml" }
|
6
|
+
|
7
|
+
context "from local yaml" do
|
8
|
+
let(:source) { "spec/fixtures/oas2/source.yaml" }
|
9
|
+
it { is_expected.to eq target }
|
10
|
+
end
|
11
|
+
|
12
|
+
context "from local json" do
|
13
|
+
let(:source) { "spec/fixtures/oas2/source.json" }
|
14
|
+
it { is_expected.to eq target }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "OAS 3" do
|
19
|
+
let(:target) { yaml_fixture_file "oas3/collected.yaml" }
|
20
|
+
|
21
|
+
context "from local yaml" do
|
22
|
+
let(:source) { "spec/fixtures/oas3/source.yaml" }
|
23
|
+
it { is_expected.to eq target }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "from local json" do
|
27
|
+
let(:source) { "spec/fixtures/oas3/source.json" }
|
28
|
+
it { is_expected.to eq target }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
RSpec.describe OpenAPI::Loader::Denormalizer, ".call" do
|
2
|
+
subject { described_class.call(source) }
|
3
|
+
|
4
|
+
context "OAS 2" do
|
5
|
+
let(:source) { yaml_fixture_file "oas2/translated.yaml" }
|
6
|
+
let(:target) { yaml_fixture_file "oas2/denormalized.yaml" }
|
7
|
+
|
8
|
+
it { is_expected.to eq target }
|
9
|
+
end
|
10
|
+
|
11
|
+
context "OAS 3" do
|
12
|
+
let(:source) { yaml_fixture_file "oas3/collected.yaml" }
|
13
|
+
let(:target) { yaml_fixture_file "oas3/denormalized.yaml" }
|
14
|
+
|
15
|
+
it { is_expected.to eq target }
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
RSpec.describe OpenAPI::Loader::Reader, ".call" do
|
2
|
+
subject { described_class.call(source) }
|
3
|
+
|
4
|
+
context "from local yaml" do
|
5
|
+
let(:source) { "spec/fixtures/oas2/source.yaml" }
|
6
|
+
let(:target) { yaml_fixture_file "oas2/loaded.yaml" }
|
7
|
+
|
8
|
+
it { is_expected.to eq target }
|
9
|
+
end
|
10
|
+
|
11
|
+
context "from local json" do
|
12
|
+
let(:source) { "spec/fixtures/oas2/source.json" }
|
13
|
+
let(:target) { yaml_fixture_file "oas2/loaded.yaml" }
|
14
|
+
|
15
|
+
it { is_expected.to eq target }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "from another existing local" do
|
19
|
+
let(:source) { local_path target }
|
20
|
+
let(:target) { "foo" }
|
21
|
+
|
22
|
+
it { is_expected.to eq target }
|
23
|
+
end
|
24
|
+
|
25
|
+
context "from absent local" do
|
26
|
+
let(:source) { "foo" }
|
27
|
+
|
28
|
+
it "raises StandardError" do
|
29
|
+
expect { subject }.to raise_error(StandardError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "from remote yaml" do
|
34
|
+
let(:source) { yaml_remote_path(target) }
|
35
|
+
let(:target) { { "foo" => "bar" } }
|
36
|
+
|
37
|
+
it { is_expected.to eq target }
|
38
|
+
end
|
39
|
+
|
40
|
+
context "from remote json" do
|
41
|
+
let(:source) { json_remote_path(target) }
|
42
|
+
let(:target) { { "foo" => "bar" } }
|
43
|
+
|
44
|
+
it { is_expected.to eq target }
|
45
|
+
end
|
46
|
+
|
47
|
+
context "from another remote" do
|
48
|
+
let(:source) { remote_path(target) }
|
49
|
+
let(:target) { "foo" }
|
50
|
+
|
51
|
+
it { is_expected.to eq target }
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
RSpec.describe OpenAPI::Loader::Ref do
|
2
|
+
describe ".new" do
|
3
|
+
subject { described_class.new(source) }
|
4
|
+
|
5
|
+
context "with a pointer to the external subpath" do
|
6
|
+
let(:source) { "https://example.com#/foo/ /e%5Ef/a~10b/m~01n" }
|
7
|
+
|
8
|
+
it { is_expected.to eq source }
|
9
|
+
its(:uri) { is_expected.to eq URI("https://example.com") }
|
10
|
+
its(:path) { is_expected.to eq ["foo", " ", "e^f", "a/0b", "m~1n"] }
|
11
|
+
end
|
12
|
+
|
13
|
+
context "with an explicit pointer to the current root" do
|
14
|
+
let(:source) { "#" }
|
15
|
+
|
16
|
+
it { is_expected.to eq source }
|
17
|
+
its(:uri) { is_expected.to be_nil }
|
18
|
+
its(:path) { is_expected.to eq [] }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "with an implicit pointer to the current root" do
|
22
|
+
let(:source) { "" }
|
23
|
+
|
24
|
+
it { is_expected.to eq "#" }
|
25
|
+
its(:uri) { is_expected.to be_nil }
|
26
|
+
its(:path) { is_expected.to eq [] }
|
27
|
+
end
|
28
|
+
|
29
|
+
context "with a local pointer" do
|
30
|
+
let(:source) { "#/foo/ /e%5Ef/a~10b/m~01n" }
|
31
|
+
|
32
|
+
it { is_expected.to eq source }
|
33
|
+
its(:uri) { is_expected.to be_nil }
|
34
|
+
its(:path) { is_expected.to eq ["foo", " ", "e^f", "a/0b", "m~1n"] }
|
35
|
+
end
|
36
|
+
|
37
|
+
context "with an explicit pointer to the external root" do
|
38
|
+
let(:source) { "https://example.com/#" }
|
39
|
+
|
40
|
+
it { is_expected.to eq source }
|
41
|
+
its(:uri) { is_expected.to eq URI("https://example.com/") }
|
42
|
+
its(:path) { is_expected.to eq [] }
|
43
|
+
end
|
44
|
+
|
45
|
+
context "without an implicit pointer to the external root" do
|
46
|
+
let(:source) { "https://example.com/foo" }
|
47
|
+
|
48
|
+
it { is_expected.to eq "https://example.com/foo#" }
|
49
|
+
its(:uri) { is_expected.to eq URI("https://example.com/foo") }
|
50
|
+
its(:path) { is_expected.to eq [] }
|
51
|
+
end
|
52
|
+
|
53
|
+
context "with an external pointer" do
|
54
|
+
let(:source) { "https://example.com/foo#/foo/ /e%5Ef/a~10b/m~01n" }
|
55
|
+
|
56
|
+
it { is_expected.to eq source }
|
57
|
+
its(:uri) { is_expected.to eq URI("https://example.com/foo") }
|
58
|
+
its(:path) { is_expected.to eq ["foo", " ", "e^f", "a/0b", "m~1n"] }
|
59
|
+
end
|
60
|
+
|
61
|
+
context "with several #" do
|
62
|
+
let(:source) { "#/foo#/ /e%5Ef/a~10b/m~01n" }
|
63
|
+
|
64
|
+
it "raises ArgumentError" do
|
65
|
+
expect { subject }.to raise_error(ArgumentError)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "with a # succeeded not by a slash" do
|
70
|
+
let(:source) { "# /foo/ /e%5Ef/a~10b/m~01n" }
|
71
|
+
|
72
|
+
it "raises ArgumentError" do
|
73
|
+
expect { subject }.to raise_error(ArgumentError)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe ".[]" do
|
79
|
+
subject { described_class[*path] }
|
80
|
+
|
81
|
+
let(:path) { %w[foo~/bar 0 baz/~qux] }
|
82
|
+
|
83
|
+
it { is_expected.to eq "#/foo~0~1bar/0/baz~1~0qux" }
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#fetch_from" do
|
87
|
+
subject { ref.fetch_from(data) }
|
88
|
+
|
89
|
+
let(:ref) { described_class.new "#/foo/0/bar" }
|
90
|
+
|
91
|
+
context "when value is present" do
|
92
|
+
let(:data) { { "foo" => [{ "bar" => :BAZ }] } }
|
93
|
+
|
94
|
+
it "finds the value" do
|
95
|
+
expect(subject).to eq :BAZ
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when value is absent" do
|
100
|
+
let(:data) { { "foo" => { "bar" => :BAZ } } }
|
101
|
+
|
102
|
+
it "raises key error" do
|
103
|
+
expect { subject }.to raise_error(KeyError, %r{'#/foo/0'})
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|