Module: Minitest::OpenAPI::Spec

Defined in:
lib/minitest/openapi/spec.rb

Overview

Nested block DSL for minitest/spec users. Extend an integration test class with it; api_path / api_operation / api_response build nested describe blocks and run_api_test! defines the test:

class MediaEntriesApiTest < ActionDispatch::IntegrationTest
  extend Minitest::OpenAPI::Spec

  api_path "/api/v1/media_entries" do
    api_operation :get, summary: "List media entries" do
      api_response 200, schema: {"$ref" => "#/components/schemas/MediaEntry"} do
        run_api_test!
      end
    end
  end
end

Metadata accumulates down the nesting; run_api_test! merges the whole chain. Its optional block runs in the test instance and returns request overrides ({ path:, params:, headers:, body: }) — use it to build a concrete URL from records created in the test.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object



28
29
30
# File 'lib/minitest/openapi/spec.rb', line 28

def self.extended(base)
  base.extend(Minitest::Spec::DSL) unless base.is_a?(Minitest::Spec::DSL)
end

Instance Method Details

#api_operation(verb, **meta, &block) ⇒ Object



45
46
47
48
49
50
# File 'lib/minitest/openapi/spec.rb', line 45

def api_operation(verb, **meta, &block)
  describe(verb.to_s) do
    @openapi_metadata = {verb: verb}.merge(meta)
    class_eval(&block)
  end
end

#api_path(path, &block) ⇒ Object



38
39
40
41
42
43
# File 'lib/minitest/openapi/spec.rb', line 38

def api_path(path, &block)
  describe("path #{path}") do
    @openapi_metadata = {path: path}
    class_eval(&block)
  end
end

#api_response(status, **meta, &block) ⇒ Object



52
53
54
55
56
57
# File 'lib/minitest/openapi/spec.rb', line 52

def api_response(status, **meta, &block)
  describe("#{status} response") do
    @openapi_metadata = {response_status: status}.merge(meta)
    class_eval(&block)
  end
end

#openapi_metadataObject

Metadata declared on this describe merged onto its parent’s.



33
34
35
36
# File 'lib/minitest/openapi/spec.rb', line 33

def 
  inherited = superclass.respond_to?(:openapi_metadata) ? superclass. : {}
  inherited.merge(@openapi_metadata || {})
end

#run_api_test!(description = nil, &request_block) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/minitest/openapi/spec.rb', line 59

def run_api_test!(description = nil, &request_block)
  meta = 
  verb = meta.fetch(:verb) { raise Error, "run_api_test! must be nested in api_operation" }
  status = meta.fetch(:response_status) { raise Error, "run_api_test! must be nested in api_response" }
  doc_path = meta.fetch(:path) { raise Error, "run_api_test! must be nested in api_path" }

  it(description || "conforms to the #{status} response") do
    overrides = request_block ? instance_exec(&request_block) : {}
    overrides ||= {}
    Recorder.run(
      test: self,
      verb: verb,
      request_path: overrides[:path] || doc_path,
      doc_path: doc_path,
      response: {status: status, schema: meta[:schema], description: meta[:description]},
      summary: meta[:summary],
      operation_id: meta[:operation_id],
      description: meta[:operation_description],
      tags: meta[:tags],
      parameters: meta[:parameters],
      request_body: meta[:request_body],
      params: overrides[:params],
      headers: overrides[:headers],
      body: overrides[:body],
      assert_status: true
    )
  end
end