minitest-openapi 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/lib/minitest/openapi/endpoint_metadata.rb +45 -0
- data/lib/minitest/openapi/minitest_hook.rb +64 -0
- data/lib/minitest/openapi/parse_request.rb +13 -0
- data/lib/minitest/openapi/path.rb +38 -0
- data/lib/minitest/openapi/schema.rb +52 -0
- data/lib/minitest/openapi/webhook.rb +34 -0
- data/lib/minitest/openapi.rb +28 -0
- metadata +11 -5
- data/lib/minitest/doc.rb +0 -13
- data/lib/minitest/openapi/hooks.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9ce72856fa448b87d2a15278ceb0d9aeb93a7de02cbfe08341c872004abcffd
|
4
|
+
data.tar.gz: 7c3a71aea09013041b302aac453ddc50f1af8c41554e2c5dda0c6fe7e5c44361
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c4b050a134c378ea354408056e6dcc5e3060a929b3ce0b7f2979bf3eded390dd20b2392619a77dc007956d1a42a010a2634e3819b57d220bcfde7c47d84d860
|
7
|
+
data.tar.gz: 1326a492f68652eceb81017c9676f0401a8d0361dadca7b6b82ad7c92136938661a120f0fb6ca0cfba962b7a25fd2b9e4dbc770a53c7eefff4316d48a571bc24
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_dispatch"
|
4
|
+
require "active_support/inflector"
|
5
|
+
|
6
|
+
module Minitest
|
7
|
+
module OpenAPI
|
8
|
+
module EndpointMetadata
|
9
|
+
class << self
|
10
|
+
def call(context, _test)
|
11
|
+
@request, @response = Minitest::OpenAPI::ParseRequest.call(context)
|
12
|
+
return if @request.nil?
|
13
|
+
|
14
|
+
@endpoint = @request.filtered_path || "unknown"
|
15
|
+
metadata
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def metadata
|
21
|
+
{
|
22
|
+
endpoint: format_endpoint,
|
23
|
+
method: @request.method.downcase,
|
24
|
+
summary: "",
|
25
|
+
parameters: [],
|
26
|
+
status: @response.status
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
# Convert "owners/1234/pets/5678" to "owners/{ownerId}/pets/{petId}"
|
31
|
+
def format_endpoint
|
32
|
+
ep = @endpoint.split("/")[1..-1] || []
|
33
|
+
resource = ""
|
34
|
+
|
35
|
+
ep.each_with_index do |e, i|
|
36
|
+
i.odd? ?
|
37
|
+
ep[i] = "{#{resource}Id}" :
|
38
|
+
resource = ActiveSupport::Inflector.singularize(e)
|
39
|
+
end
|
40
|
+
"/#{ep.join("/")}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "minitest"
|
4
|
+
|
5
|
+
module Minitest
|
6
|
+
module OpenAPI
|
7
|
+
TestCase = Struct.new(:path)
|
8
|
+
|
9
|
+
module RunPatch
|
10
|
+
def run(*args)
|
11
|
+
return super unless ENV["DOC"]
|
12
|
+
result = super
|
13
|
+
|
14
|
+
if self.class.document?
|
15
|
+
test_file_path = result.source_location.first
|
16
|
+
test_case = TestCase.new(test_file_path)
|
17
|
+
metadata = Minitest::OpenAPI::EndpointMetadata.call(self, test_case) || {}
|
18
|
+
|
19
|
+
self.webhook? ?
|
20
|
+
Minitest::OpenAPI::Webhook.build(metadata, test_case) :
|
21
|
+
Minitest::OpenAPI::Path.build(metadata, test_case)
|
22
|
+
end
|
23
|
+
|
24
|
+
result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module MinitestOpenAPIMethods
|
31
|
+
def self.prepended(base)
|
32
|
+
base.extend(Document)
|
33
|
+
|
34
|
+
base.class_eval do
|
35
|
+
def webhook?
|
36
|
+
@webhook
|
37
|
+
end
|
38
|
+
|
39
|
+
def webhook!
|
40
|
+
@webhook = true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module Document
|
46
|
+
def document?
|
47
|
+
@document
|
48
|
+
end
|
49
|
+
|
50
|
+
def document!
|
51
|
+
@document = true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
Minitest::Test.prepend MinitestOpenAPIMethods
|
57
|
+
|
58
|
+
if ENV["DOC"]
|
59
|
+
Minitest::Test.prepend Minitest::OpenAPI::RunPatch
|
60
|
+
|
61
|
+
Minitest.after_run do
|
62
|
+
Minitest::OpenAPI::Schema.build
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minitest
|
4
|
+
module OpenAPI
|
5
|
+
module ParseRequest
|
6
|
+
# TODO: Add support for Rack::Test for middleware/etc.
|
7
|
+
def self.call(context)
|
8
|
+
@context = context
|
9
|
+
[ @context.request, @context.response ]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Minitest
|
2
|
+
module OpenAPI
|
3
|
+
module Path
|
4
|
+
TestCase = Struct.new(:path)
|
5
|
+
|
6
|
+
def self.build(metadata, test_case)
|
7
|
+
export_file_path = Minitest::OpenAPI.path.yield_self { |p| p.is_a?(Proc) ? p.call(test_case) : p }
|
8
|
+
file_path_data = Minitest::OpenAPI.paths[export_file_path]
|
9
|
+
|
10
|
+
if file_path_data[metadata[:endpoint]]
|
11
|
+
if file_path_data[metadata[:endpoint]][metadata[:method]]
|
12
|
+
file_path_data[metadata[:endpoint]][metadata[:method]][:responses].merge!({ metadata[:status] => {} })
|
13
|
+
else
|
14
|
+
file_path_data[metadata[:endpoint]].merge! self.format_endpoint(metadata)
|
15
|
+
end
|
16
|
+
else
|
17
|
+
file_path_data.merge!(metadata[:endpoint] => self.format_endpoint(metadata))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.format_endpoint(metadata)
|
22
|
+
{
|
23
|
+
metadata[:method] => {
|
24
|
+
parameters: [],
|
25
|
+
responses: {
|
26
|
+
metadata[:status] => {
|
27
|
+
description: "",
|
28
|
+
headers: {},
|
29
|
+
content: {}
|
30
|
+
},
|
31
|
+
default: {}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minitest
|
4
|
+
module OpenAPI
|
5
|
+
class InvalidFileFormat < StandardError; end
|
6
|
+
|
7
|
+
module Schema
|
8
|
+
ALLOWED_EXTENSIONS = %w[.json .yaml .yml].freeze
|
9
|
+
|
10
|
+
def self.build
|
11
|
+
file_paths = self.parse_files
|
12
|
+
|
13
|
+
Dir.mkdir("docs") unless File.exist?("docs")
|
14
|
+
file_paths.each do |file|
|
15
|
+
raise InvalidFileFormat unless valid_file_ext?(file)
|
16
|
+
|
17
|
+
File.open(file, "w") do |f|
|
18
|
+
f.write(JSON.pretty_generate(json_schema(file), indent: " "))
|
19
|
+
puts "File generated!"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# IDK
|
25
|
+
def self.json_schema(file)
|
26
|
+
JSON.parse({
|
27
|
+
openapi: "3.1.0",
|
28
|
+
info: {
|
29
|
+
title: Minitest::OpenAPI.title,
|
30
|
+
version: Minitest::OpenAPI.version
|
31
|
+
},
|
32
|
+
servers: Minitest::OpenAPI.servers,
|
33
|
+
paths: Minitest::OpenAPI.paths[file],
|
34
|
+
webhooks: Minitest::OpenAPI.webhooks[file]
|
35
|
+
}.to_json)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.parse_files
|
39
|
+
file_paths = []
|
40
|
+
file_paths.concat(
|
41
|
+
Minitest::OpenAPI.paths.keys,
|
42
|
+
Minitest::OpenAPI.webhooks.keys
|
43
|
+
)
|
44
|
+
file_paths.uniq
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.valid_file_ext?(file)
|
48
|
+
ALLOWED_EXTENSIONS.include?(File.extname(file))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Minitest
|
2
|
+
module OpenAPI
|
3
|
+
module Webhook
|
4
|
+
TestCase = Struct.new(:path)
|
5
|
+
|
6
|
+
def self.build(metadata, test_case)
|
7
|
+
export_file_path = Minitest::OpenAPI.path.yield_self { |p| p.is_a?(Proc) ? p.call(test_case) : p }
|
8
|
+
file_path_data = Minitest::OpenAPI.webhooks[export_file_path]
|
9
|
+
|
10
|
+
if file_path_data[metadata[:endpoint]]
|
11
|
+
if file_path_data[metadata[:endpoint]][metadata[:method]]
|
12
|
+
file_path_data[metadata[:endpoint]][metadata[:method]][:responses].merge!({ metadata[:status] => {} })
|
13
|
+
else
|
14
|
+
file_path_data[metadata[:endpoint]].merge! self.format_endpoint(metadata)
|
15
|
+
end
|
16
|
+
else
|
17
|
+
file_path_data.merge!(metadata[:endpoint] => self.format_endpoint(metadata))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.format_endpoint(metadata)
|
22
|
+
{
|
23
|
+
metadata[:method] => {
|
24
|
+
parameters: [],
|
25
|
+
responses: {
|
26
|
+
metadata[:status] => {},
|
27
|
+
default: {}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "minitest/openapi/minitest_hook"
|
4
|
+
require "minitest/openapi/parse_request"
|
5
|
+
require "minitest/openapi/endpoint_metadata"
|
6
|
+
require "minitest/openapi/path"
|
7
|
+
require "minitest/openapi/schema"
|
8
|
+
require "minitest/openapi/webhook"
|
9
|
+
|
10
|
+
module Minitest
|
11
|
+
module OpenAPI
|
12
|
+
@path = "docs/openapi.json"
|
13
|
+
@paths = Hash.new { |h, k| h[k] = {} }
|
14
|
+
@servers = []
|
15
|
+
@title = ""
|
16
|
+
@version = ""
|
17
|
+
@webhooks = Hash.new { |h, k| h[k] = {} }
|
18
|
+
|
19
|
+
class << self
|
20
|
+
attr_accessor :path,
|
21
|
+
:paths,
|
22
|
+
:servers,
|
23
|
+
:title,
|
24
|
+
:version,
|
25
|
+
:webhooks
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minitest-openapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Austin Wasson
|
8
|
+
- Bijan Rahnema
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2024-01-
|
12
|
+
date: 2024-01-15 00:00:00.000000000 Z
|
12
13
|
dependencies: []
|
13
14
|
description: API documentation generator based on the OpenAPI spec.
|
14
15
|
email: austinpwasson@gmail.com
|
@@ -16,8 +17,13 @@ executables: []
|
|
16
17
|
extensions: []
|
17
18
|
extra_rdoc_files: []
|
18
19
|
files:
|
19
|
-
- lib/minitest/
|
20
|
-
- lib/minitest/openapi/
|
20
|
+
- lib/minitest/openapi.rb
|
21
|
+
- lib/minitest/openapi/endpoint_metadata.rb
|
22
|
+
- lib/minitest/openapi/minitest_hook.rb
|
23
|
+
- lib/minitest/openapi/parse_request.rb
|
24
|
+
- lib/minitest/openapi/path.rb
|
25
|
+
- lib/minitest/openapi/schema.rb
|
26
|
+
- lib/minitest/openapi/webhook.rb
|
21
27
|
homepage:
|
22
28
|
licenses:
|
23
29
|
- MIT
|
@@ -37,7 +43,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
37
43
|
- !ruby/object:Gem::Version
|
38
44
|
version: '0'
|
39
45
|
requirements: []
|
40
|
-
rubygems_version: 3.3
|
46
|
+
rubygems_version: 3.5.3
|
41
47
|
signing_key:
|
42
48
|
specification_version: 4
|
43
49
|
summary: API documentation generator based on the OpenAPI spec.
|
data/lib/minitest/doc.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'minitest'
|
4
|
-
|
5
|
-
module Minitest
|
6
|
-
module OpenAPI
|
7
|
-
module RunPatch
|
8
|
-
def run(*args)
|
9
|
-
result = super
|
10
|
-
if ENV['OPENAPI'] && self.class.openapi?
|
11
|
-
# This will run before specs
|
12
|
-
end
|
13
|
-
result
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
module ActivateOpenApiClassMethods
|
18
|
-
def self.prepended(base)
|
19
|
-
base.extend(ClassMethods)
|
20
|
-
end
|
21
|
-
|
22
|
-
module ClassMethods
|
23
|
-
def openapi?
|
24
|
-
@openapi
|
25
|
-
end
|
26
|
-
|
27
|
-
def openapi!
|
28
|
-
@openapi = true
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
Minitest::Test.prepend Minitest::OpenAPI::ActivateOpenApiClassMethods
|
36
|
-
|
37
|
-
if ENV['OPENAPI']
|
38
|
-
Minitest::Test.prepend Minitest::OpenAPI::RunPatch
|
39
|
-
Minitest.after_run do
|
40
|
-
puts "============================="
|
41
|
-
puts "Building Docs 🎉"
|
42
|
-
puts "============================="
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|