Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hanami support #202

Merged
merged 18 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ AllCops:
SuggestExtensions: false
TargetRubyVersion: 2.7
Exclude:
- 'spec/rails/**/*'
- 'spec/apps/**/*'
- 'vendor/**/*'

Style/TrailingCommaInHashLiteral:
Expand Down
9 changes: 9 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@ source 'https://rubygems.org'
gemspec

gem 'rails', ENV['RAILS_VERSION'] || '6.0.3.7'

if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0')
gem 'hanami', ENV['HANAMI_VERSION'] || '2.1.0'
gem 'hanami-controller', ENV['HANAMI_VERSION'] || '2.1.0'
gem 'hanami-router', ENV['HANAMI_VERSION'] || '2.1.0'
end

gem 'roda'

gem 'rails-dom-testing', '~> 2.2'
gem 'rspec-rails'

group :test do
Expand Down
5 changes: 4 additions & 1 deletion lib/rspec/openapi/record_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ def safe_parse_body(response, media_type)
def extract_headers(request, response)
request_headers = RSpec::OpenAPI.request_headers.each_with_object([]) do |header, headers_arr|
header_key = header.gsub('-', '_').upcase.to_sym
header_value = request.get_header(['HTTP', header_key].join('_')) || request.get_header(header_key)

header_value = request.get_header(['HTTP', header_key].join('_')) ||
request.get_header(header_key) ||
request.get_header(header_key.to_s)
Copy link
Contributor Author

@AlexeyMatskevich AlexeyMatskevich Mar 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found one problem with the new edits - https://github.com/exoego/rspec-openapi/pull/198/files#diff-a79ceb062f9ec26b6203f0b7541bd0a9b1cc2ebf3370cac3da9039f4f11dc1a7R56 - Rack test seems to send strings instead of characters in headers, so because of this edit, headers can no longer be detected.

headers_arr << [header, header_value] if header_value
end
response_headers = RSpec::OpenAPI.response_headers.each_with_object([]) do |header, headers_arr|
Expand Down
9 changes: 8 additions & 1 deletion lib/rspec/openapi/schema_merger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ def merge_arrays(base, key, value)
def merge_parameters(base, key, value)
all_parameters = value | base[key]

unique_base_parameters = base[key].index_by { |parameter| [parameter[:name], parameter[:in]] }
unique_base_parameters = build_unique_params(base, key)

all_parameters = all_parameters.map do |parameter|
base_parameter = unique_base_parameters[[parameter[:name], parameter[:in]]] || {}
base_parameter ? base_parameter.merge(parameter) : parameter
Expand All @@ -63,6 +64,12 @@ def merge_parameters(base, key, value)
base[key] = all_parameters
end

def build_unique_params(base, key)
base[key].each_with_object({}) do |parameter, hash|
hash[[parameter[:name], parameter[:in]]] = parameter
end
end

SIMILARITY_THRESHOLD = 0.5

def merge_closest_match!(options, spec)
Expand Down
1 change: 1 addition & 0 deletions rspec-openapi.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
spec.require_paths = ['lib']

spec.add_dependency 'actionpack', '>= 5.2.0'
spec.add_dependency 'rails-dom-testing'
spec.add_dependency 'rspec-core'
spec.metadata['rubygems_mfa_required'] = 'true'
end
2 changes: 2 additions & 0 deletions spec/apps/hanami/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.env
log/*
1 change: 1 addition & 0 deletions spec/apps/hanami/Procfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: bundle exec hanami server
3 changes: 3 additions & 0 deletions spec/apps/hanami/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

require "hanami/rake_tasks"
8 changes: 8 additions & 0 deletions spec/apps/hanami/app/action.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# auto_register: false
# frozen_string_literal: true

require 'hanami/action'

class HanamiTest::Action < Hanami::Action
class RecordNotFound < StandardError; end
end
File renamed without changes.
13 changes: 13 additions & 0 deletions spec/apps/hanami/app/actions/extensions/create.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Extensions
class Create < HanamiTest::Action
def handle(_request, response)
response.body = [{ name: 'my-ext-1' }].to_json
end
end
end
end
end
13 changes: 13 additions & 0 deletions spec/apps/hanami/app/actions/extensions/index.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Extensions
class Index < HanamiTest::Action
def handle(_request, response)
response.body = { message: 'created' }.to_json
end
end
end
end
end
22 changes: 22 additions & 0 deletions spec/apps/hanami/app/actions/images/index.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Images
class Index < HanamiTest::Action
format :json

def handle(_request, response)
list = [
{
name: 'file.png',
tags: [], # Keep this empty to check empty array is accepted
},
]

response.body = list.to_json
end
end
end
end
end
23 changes: 23 additions & 0 deletions spec/apps/hanami/app/actions/images/show.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Images
class Show < HanamiTest::Action
def handle(_request, response)
png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='
.unpack('m').first

response.format = :png
response.body = png
response.headers.merge!(
{
'Content-Type' => 'image/png',
'Content-Disposition' => 'inline',
}
)
end
end
end
end
end
25 changes: 25 additions & 0 deletions spec/apps/hanami/app/actions/images/upload.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Images
class Upload < HanamiTest::Action
# format :form

def handle(_request, response)
png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='
.unpack('m').first

response.format = :png
response.body = png
response.headers.merge!(
{
'Content-Type' => 'image/png',
'Content-Disposition' => 'inline',
}
)
end
end
end
end
end
25 changes: 25 additions & 0 deletions spec/apps/hanami/app/actions/images/upload_multiple.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Images
class UploadMultiple < HanamiTest::Action
# format :multipart

def handle(_request, response)
png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='
.unpack('m').first

response.format = :png
response.body = png
response.headers.merge!(
{
'Content-Type' => 'image/png',
'Content-Disposition' => 'inline',
}
)
end
end
end
end
end
23 changes: 23 additions & 0 deletions spec/apps/hanami/app/actions/images/upload_multiple_nested.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Images
class UploadMultipleNested < HanamiTest::Action
def handle(_request, response)
png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='
.unpack('m').first

response.format = :png
response.body = png
response.headers.merge!(
{
'Content-Type' => 'image/png',
'Content-Disposition' => 'inline',
}
)
end
end
end
end
end
23 changes: 23 additions & 0 deletions spec/apps/hanami/app/actions/images/upload_nested.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Images
class UploadNested < HanamiTest::Action
def handle(_request, response)
png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='
.unpack('m').first

response.format = :png
response.body = png
response.headers.merge!(
{
'Content-Type' => 'image/png',
'Content-Disposition' => 'inline',
}
)
end
end
end
end
end
15 changes: 15 additions & 0 deletions spec/apps/hanami/app/actions/secret_items/index.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module SecretItems
class Index < HanamiTest::Action
format :json

def handle(_request, response)
response.body = { items: ['secrets'] }.to_json
end
end
end
end
end
21 changes: 21 additions & 0 deletions spec/apps/hanami/app/actions/tables/create.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Tables
class Create < TableAction
format :json

def handle(request, response)
if request.params[:name].blank? || request.params[:name] == 'some_invalid_name'
response.status = 422
response.body = { error: 'invalid name parameter' }.to_json
else
response.status = 201
response.body = find_table.to_json
end
end
end
end
end
end
18 changes: 18 additions & 0 deletions spec/apps/hanami/app/actions/tables/destroy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Tables
class Destroy < TableAction
def handle(request, response)
response.format = :json
if request.params[:no_content]
response.status = 202
else
response.body = find_table(request.params[:id]).to_json
end
end
end
end
end
end
21 changes: 21 additions & 0 deletions spec/apps/hanami/app/actions/tables/index.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Tables
class Index < TableAction
def handle(request, response)
response.headers['X-Cursor'] = 100

response.format = :json

response.body = if request.params[:show_columns]
[find_table('42')].to_json
else
[find_table].to_json
end
end
end
end
end
end
15 changes: 15 additions & 0 deletions spec/apps/hanami/app/actions/tables/show.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Tables
class Show < TableAction
format :json

def handle(request, response)
response.body = find_table(request.params[:id]).to_json
end
end
end
end
end
30 changes: 30 additions & 0 deletions spec/apps/hanami/app/actions/tables/table_action.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module HanamiTest
module Actions
module Tables
class TableAction < HanamiTest::Action
APIKEY = 'k0kubun'.freeze

include TableRepository

handle_exception RecordNotFound => :handle_not_fount_error

before :authenticate

private

def handle_not_fount_error(_request, _response, _exception)
halt 404, { message: 'not found' }.to_json
end

def authenticate(request, response)
return unless request.get_header('AUTHORIZATION') != APIKEY

response.format = :json
halt 401, { message: 'Unauthorized' }.to_json
end
end
end
end
end
Loading