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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 842cf7448f6ccde919d1c6d51eccf576923fa47d7da657139b3956c09955fea3
4
- data.tar.gz: b623ad83736c487b3f0aa51f83ecedc9dc153670c15ce855b9202dcefc87f19a
3
+ metadata.gz: c9ce72856fa448b87d2a15278ceb0d9aeb93a7de02cbfe08341c872004abcffd
4
+ data.tar.gz: 7c3a71aea09013041b302aac453ddc50f1af8c41554e2c5dda0c6fe7e5c44361
5
5
  SHA512:
6
- metadata.gz: 6c65f04a0d795172d7f1100a045ff6139b3bfa391bdf4dac4c64240b0d7cf72b61136555fb80a1cb76c47645866dce982021c557c6940a0457dd812e4b61f48c
7
- data.tar.gz: d960a442315236435eb6121978468bd5670fb31d1a6f80ad72fa245294c45c1c78416a5e87003def8c2431d344415fc4368c3d6ba940ef84b3f192dd14f62190
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.1
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-01 00:00:00.000000000 Z
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/doc.rb
20
- - lib/minitest/openapi/hooks.rb
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.26
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,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'minitest/openapi/hooks'
4
-
5
- module Minitest
6
- class Config
7
- @path = 'docs/openapi.yaml'
8
-
9
- class << self
10
- attr_accessor :path
11
- end
12
- end
13
- end
@@ -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
-