diff --git a/lib/reynard/specification.rb b/lib/reynard/specification.rb index b589c36..04b6481 100644 --- a/lib/reynard/specification.rb +++ b/lib/reynard/specification.rb @@ -60,7 +60,8 @@ def build_body(operation_node, data) end def operation(operation_name) - dig('paths').each do |path, operations| + dig('paths').each_key do |path| + operations = dig('paths', path) operations.slice(*VERBS).each do |verb, operation| return Operation.new(node: ['paths', path, verb]) if operation_name == operation['operationId'] end diff --git a/test/files/openapi/external.yml b/test/files/openapi/external.yml index fe45b3f..eb82c5f 100644 --- a/test/files/openapi/external.yml +++ b/test/files/openapi/external.yml @@ -47,3 +47,5 @@ paths: application/json: schema: $ref: "schemas/author.yml" + /authors: + $ref: "./paths/authors.yml#/paths/index" diff --git a/test/files/openapi/paths/authors.yml b/test/files/openapi/paths/authors.yml new file mode 100644 index 0000000..15d0071 --- /dev/null +++ b/test/files/openapi/paths/authors.yml @@ -0,0 +1,21 @@ +paths: + index: + get: + summary: Fetch authors + description: Fetch a list of all authors + operationId: listAuthors + tags: + - authors + responses: + "200": + description: A list of authors + content: + application/json: + schema: + $ref: "../schemas/authors.yml" + default: + description: An error. + content: + application/json: + schema: + $ref: "../simple.yml#/components/schemas/Error" diff --git a/test/files/openapi/schemas/authors.yml b/test/files/openapi/schemas/authors.yml new file mode 100644 index 0000000..807cf70 --- /dev/null +++ b/test/files/openapi/schemas/authors.yml @@ -0,0 +1,6 @@ +type: array +title: Authors +description: >- + A list of authors of a book. +items: + $ref: "author.yml" diff --git a/test/reynard/object_builder_test.rb b/test/reynard/object_builder_test.rb index 57ee43d..3626d94 100644 --- a/test/reynard/object_builder_test.rb +++ b/test/reynard/object_builder_test.rb @@ -72,6 +72,31 @@ def setup end end + class ExternalRequestPathAndDeepRefsBuilderTest < Reynard::Test + def setup + @specification = Specification.new(filename: fixture_file('openapi/external.yml')) + @inflector = Inflector.new + end + + test 'builds a singular record' do + operation = @specification.operation('listAuthors') + media_type = @specification.media_type(operation.node, '200', 'application/json') + schema = @specification.schema(media_type.node) + authors = Reynard::ObjectBuilder.new( + schema:, + inflector: @inflector, + parsed_body: [ + { id: 42, name: 'Jerry Writer', bio: { age: 42 } } + ] + ).call + assert_model_name('AuthorsCollection', authors) + authors.each do |author| + assert_model_name('Author', author) + assert_equal 42, author.id + end + end + end + class TitledObjectBuilderTest < Reynard::Test def setup @specification = Specification.new(filename: fixture_file('openapi/titled.yml')) diff --git a/test/reynard/schema/model_naming_test.rb b/test/reynard/schema/model_naming_test.rb index 2e0e18a..44119c8 100644 --- a/test/reynard/schema/model_naming_test.rb +++ b/test/reynard/schema/model_naming_test.rb @@ -49,7 +49,7 @@ class ModelNamingTest < Reynard::Test class RegressionModelNamingTest < Reynard::Test EXPECTED = { 'bare' => [], - 'external' => %w[Author Bio Error Author Bio], + 'external' => %w[Author Bio Error Author Bio Author Bio Error AuthorsCollection], 'minimal' => %w[Spaceship SpaceshipCollection], 'naming' => %w[ Sector Subsector IndustryGroup Industry NationalIndustry Art NationalIndustry diff --git a/test/reynard/specification_test.rb b/test/reynard/specification_test.rb index d14ce0c..04e5452 100644 --- a/test/reynard/specification_test.rb +++ b/test/reynard/specification_test.rb @@ -241,6 +241,15 @@ def setup @specification = Specification.new(filename: fixture_file('openapi/external.yml')) end + test 'finds an operation, loads media type, and returns schema defined externally in a file' do + operation = @specification.operation('listAuthors') + media_type = @specification.media_type(operation.node, '200', 'application/json') + assert_equal( + 'array', + @specification.dig(*media_type.node, 'schema', 'type') + ) + end + test 'digs into an external file' do data = @specification.dig( 'paths', '/authors/{id}', 'get', 'responses', '200',