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 15 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
7 changes: 7 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
gemspec

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

gem 'hanami', ENV['HANAMI_VERSION'] || '2.1.0'
gem 'hanami-router', ENV['HANAMI_VERSION'] || '2.1.0'
gem 'hanami-controller', ENV['HANAMI_VERSION'] || '2.1.0'

Check notice

Code scanning / Rubocop

Gems within groups in the Gemfile should be alphabetically sorted. Note

Bundler/OrderedGems: Gems should be sorted in an alphabetical order within their section of the Gemfile. Gem hanami-controller should appear before hanami-router.

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"

Check notice

Code scanning / Rubocop

Checks if uses of quotes match the configured preference. Note test

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
10 changes: 10 additions & 0 deletions spec/apps/hanami/app/action.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# auto_register: false
# frozen_string_literal: true

require "hanami/action"

Check notice

Code scanning / Rubocop

Checks if uses of quotes match the configured preference. Note test

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

module HanamiTest

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
class Action < Hanami::Action
class RecordNotFound < StandardError; end
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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
module Actions
module Extensions
class Create < HanamiTest::Action
def handle(request, response)

Check warning

Code scanning / Rubocop

Checks for unused method arguments. Warning test

Lint/UnusedMethodArgument: Unused method argument - request. If it's necessary, use \_ or \_request as an argument name to indicate that it won't be used. If it's unnecessary, remove it.
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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
module Actions
module Extensions
class Index < HanamiTest::Action
def handle(request, response)

Check warning

Code scanning / Rubocop

Checks for unused method arguments. Warning test

Lint/UnusedMethodArgument: Unused method argument - request. If it's necessary, use \_ or \_request as an argument name to indicate that it won't be used. If it's unnecessary, remove it.
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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
module Actions
module Images
class Index < HanamiTest::Action
format :json

def handle(_request, response)
list = [
{
'name': 'file.png',

Check warning

Code scanning / Rubocop

Checks for unnecessary symbol conversions. Warning test

Lint/SymbolConversion: Unnecessary symbol conversion; use name: instead.
'tags': [], # Keep this empty to check empty array is accepted

Check warning

Code scanning / Rubocop

Checks for unnecessary symbol conversions. Warning test

Lint/SymbolConversion: Unnecessary symbol conversion; use tags: instead.
},
]

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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
module Actions
module Images
class Show < HanamiTest::Action
def handle(_request, response)
png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='.

Check notice

Code scanning / Rubocop

Checks the position of the dot in multi-line method calls. Note test

Layout/DotPosition: Place the . on the next line, together with the method name.
unpack('m').first

Check notice

Code scanning / Rubocop

Checks indentation of method calls with the dot operator that span more than one line. Note test

Layout/MultilineMethodCallIndentation: Align unpack with 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='. on line 8.

Check notice

Code scanning / Rubocop

Checks for accessing the first element of `String#unpack` instead of using `unpack1`. Note test

Style/UnpackFirst: Use unpack1('m') instead of unpack('m').first.

response.format = :png
response.body = png
response.headers.merge!(
{
'Content-Type' => 'image/png',
'Content-Disposition' => 'inline'

Check notice

Code scanning / Rubocop

Checks for trailing comma in hash literals. Note test

Style/TrailingCommaInHashLiteral: Put a comma after the last item of a multiline hash.
}

Check notice

Code scanning / Rubocop

Checks for trailing comma in argument lists. Note test

Style/TrailingCommaInArguments: Put a comma after the last parameter of a multiline method call.
)
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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
module Actions
module Images
class Upload < HanamiTest::Action
# format :form

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

Check notice

Code scanning / Rubocop

Checks the position of the dot in multi-line method calls. Note test

Layout/DotPosition: Place the . on the next line, together with the method name.
unpack('m').first

Check notice

Code scanning / Rubocop

Checks indentation of method calls with the dot operator that span more than one line. Note test

Layout/MultilineMethodCallIndentation: Align unpack with 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='. on line 10.

Check notice

Code scanning / Rubocop

Checks for accessing the first element of `String#unpack` instead of using `unpack1`. Note test

Style/UnpackFirst: Use unpack1('m') instead of unpack('m').first.

response.format = :png
response.body = png
response.headers.merge!(
{
'Content-Type' => 'image/png',
'Content-Disposition' => 'inline'

Check notice

Code scanning / Rubocop

Checks for trailing comma in hash literals. Note test

Style/TrailingCommaInHashLiteral: Put a comma after the last item of a multiline hash.
}

Check notice

Code scanning / Rubocop

Checks for trailing comma in argument lists. Note test

Style/TrailingCommaInArguments: Put a comma after the last parameter of a multiline method call.
)
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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
module Actions
module Images
class UploadMultiple < HanamiTest::Action
# format :multipart

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

Check notice

Code scanning / Rubocop

Checks the position of the dot in multi-line method calls. Note test

Layout/DotPosition: Place the . on the next line, together with the method name.
unpack('m').first

Check notice

Code scanning / Rubocop

Checks indentation of method calls with the dot operator that span more than one line. Note test

Layout/MultilineMethodCallIndentation: Align unpack with 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='. on line 10.

Check notice

Code scanning / Rubocop

Checks for accessing the first element of `String#unpack` instead of using `unpack1`. Note test

Style/UnpackFirst: Use unpack1('m') instead of unpack('m').first.

response.format = :png
response.body = png
response.headers.merge!(
{
'Content-Type' => 'image/png',
'Content-Disposition' => 'inline'

Check notice

Code scanning / Rubocop

Checks for trailing comma in hash literals. Note test

Style/TrailingCommaInHashLiteral: Put a comma after the last item of a multiline hash.
}

Check notice

Code scanning / Rubocop

Checks for trailing comma in argument lists. Note test

Style/TrailingCommaInArguments: Put a comma after the last parameter of a multiline method call.
)
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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
module Actions
module Images
class UploadMultipleNested < HanamiTest::Action
def handle(_request, response)
png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='.

Check notice

Code scanning / Rubocop

Checks the position of the dot in multi-line method calls. Note test

Layout/DotPosition: Place the . on the next line, together with the method name.
unpack('m').first

Check notice

Code scanning / Rubocop

Checks indentation of method calls with the dot operator that span more than one line. Note test

Layout/MultilineMethodCallIndentation: Align unpack with 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='. on line 8.

Check notice

Code scanning / Rubocop

Checks for accessing the first element of `String#unpack` instead of using `unpack1`. Note test

Style/UnpackFirst: Use unpack1('m') instead of unpack('m').first.

response.format = :png
response.body = png
response.headers.merge!(
{
'Content-Type' => 'image/png',
'Content-Disposition' => 'inline'

Check notice

Code scanning / Rubocop

Checks for trailing comma in hash literals. Note test

Style/TrailingCommaInHashLiteral: Put a comma after the last item of a multiline hash.
}

Check notice

Code scanning / Rubocop

Checks for trailing comma in argument lists. Note test

Style/TrailingCommaInArguments: Put a comma after the last parameter of a multiline method call.
)
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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
module Actions
module Images
class UploadNested < HanamiTest::Action
def handle(_request, response)
png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='.

Check notice

Code scanning / Rubocop

Checks the position of the dot in multi-line method calls. Note test

Layout/DotPosition: Place the . on the next line, together with the method name.
unpack('m').first

Check notice

Code scanning / Rubocop

Checks indentation of method calls with the dot operator that span more than one line. Note test

Layout/MultilineMethodCallIndentation: Align unpack with 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='. on line 8.

Check notice

Code scanning / Rubocop

Checks for accessing the first element of `String#unpack` instead of using `unpack1`. Note test

Style/UnpackFirst: Use unpack1('m') instead of unpack('m').first.

response.format = :png
response.body = png
response.headers.merge!(
{
'Content-Type' => 'image/png',
'Content-Disposition' => 'inline'

Check notice

Code scanning / Rubocop

Checks for trailing comma in hash literals. Note test

Style/TrailingCommaInHashLiteral: Put a comma after the last item of a multiline hash.
}

Check notice

Code scanning / Rubocop

Checks for trailing comma in argument lists. Note test

Style/TrailingCommaInArguments: Put a comma after the last parameter of a multiline method call.
)
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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
module Actions
module Tables
class Index < TableAction
def handle(request, response)
response.headers['X-Cursor'] = 100

if request.params[:show_columns]
response.format = :json

Check notice

Code scanning / Rubocop

Checks that conditional statements do not have an identical line at the end of each branch, which can validly be moved out of the conditional. Note test

Style/IdenticalConditionalBranches: Move response.format = :json out of the conditional.
response.body = [find_table('42')].to_json
else
response.format = :json

Check notice

Code scanning / Rubocop

Checks that conditional statements do not have an identical line at the end of each branch, which can validly be moved out of the conditional. Note test

Style/IdenticalConditionalBranches: Move response.format = :json out of the conditional.
response.body = [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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
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

Check notice

Code scanning / Rubocop

Checks style of children classes and modules. Note test

Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
module Actions
module Tables
class TableAction < HanamiTest::Action
APIKEY = 'k0kubun'.freeze

Check notice

Code scanning / Rubocop

Checks usages of Object#freeze on immutable objects. Note test

Style/RedundantFreeze: Do not freeze immutable objects, as freezing them has no effect.

include TableRepository

handle_exception RecordNotFound => :handle_not_fount_error

before :authenticate

private

def handle_not_fount_error(_request, response, _exception)

Check warning

Code scanning / Rubocop

Checks for unused method arguments. Warning test

Lint/UnusedMethodArgument: Unused method argument - response. If it's necessary, use \_ or \_response as an argument name to indicate that it won't be used. If it's unnecessary, remove it. You can also write as handle\_not\_fount\_error(\*) if you want the method to accept any arguments but don't care about them.
halt 404, { message: 'not found' }.to_json
end

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

Check notice

Code scanning / Rubocop

Check for conditionals that can be replaced with guard clauses. Note test

Style/GuardClause: Use a guard clause (return unless request.get\_header('AUTHORIZATION') != APIKEY) instead of wrapping the code inside a conditional expression.
response.format = :json
halt 401, { message: 'Unauthorized' }.to_json
end
end
end
end
end
end
Loading
Loading