From e1cf5a01f348dd2e7e3fefe34b366c68297a215f Mon Sep 17 00:00:00 2001 From: Alexey Matskevich <45947106+AlexeyMatskevich@users.noreply.github.com> Date: Thu, 29 Feb 2024 14:12:26 +0600 Subject: [PATCH 01/17] Add rails-dom-testing to dependency --- rspec-openapi.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/rspec-openapi.gemspec b/rspec-openapi.gemspec index fb8f427b..dc4ec2b1 100644 --- a/rspec-openapi.gemspec +++ b/rspec-openapi.gemspec @@ -27,5 +27,6 @@ Gem::Specification.new do |spec| spec.add_dependency 'actionpack', '>= 5.2.0' spec.add_dependency 'rspec-core' + spec.add_dependency 'rails-dom-testing' spec.metadata['rubygems_mfa_required'] = 'true' end From da4bcb7968b409e7f2423205cfcf19f8ef3db575 Mon Sep 17 00:00:00 2001 From: Alexey Matskevich <45947106+AlexeyMatskevich@users.noreply.github.com> Date: Thu, 29 Feb 2024 14:15:24 +0600 Subject: [PATCH 02/17] Apply linter offences --- rspec-openapi.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rspec-openapi.gemspec b/rspec-openapi.gemspec index dc4ec2b1..662c8bd1 100644 --- a/rspec-openapi.gemspec +++ b/rspec-openapi.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |spec| spec.require_paths = ['lib'] spec.add_dependency 'actionpack', '>= 5.2.0' - spec.add_dependency 'rspec-core' spec.add_dependency 'rails-dom-testing' + spec.add_dependency 'rspec-core' spec.metadata['rubygems_mfa_required'] = 'true' end From 9d12c4657ce5b5b8d414007e7e30f0317d6dc160 Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Thu, 29 Feb 2024 15:00:11 +0600 Subject: [PATCH 03/17] Add rails-dom-testing to gemfile --- Gemfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Gemfile b/Gemfile index edcdb401..754b331a 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,7 @@ source 'https://rubygems.org' gemspec gem 'rails', ENV['RAILS_VERSION'] || '6.0.3.7' +gem 'rails-dom-testing', '~> 2.2' gem 'roda' gem 'rspec-rails' From 5b7266a233bf44861989a9671b15ed8f3e413c3f Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Tue, 26 Mar 2024 17:58:42 +0500 Subject: [PATCH 04/17] Move test applications to \specs\apps --- spec/{ => apps}/rails/.gitignore | 2 +- spec/{ => apps}/rails/Rakefile | 0 .../rails/app/assets/config/manifest.js | 0 spec/{ => apps}/rails/app/assets/images/.keep | 0 .../rails/app/assets/stylesheets/application.css | 0 .../app/channels/application_cable/channel.rb | 0 .../app/channels/application_cable/connection.rb | 0 .../app/controllers/application_controller.rb | 0 .../rails/app/controllers/concerns/.keep | 0 .../rails/app/controllers/images_controller.rb | 0 .../app/controllers/secret_items_controller.rb | 0 .../rails/app/controllers/tables_controller.rb | 0 .../rails/app/controllers/users_controller.rb | 0 .../rails/app/helpers/application_helper.rb | 0 .../rails/app/javascript/channels/consumer.js | 0 .../rails/app/javascript/channels/index.js | 0 .../rails/app/javascript/packs/application.js | 0 spec/{ => apps}/rails/app/jobs/application_job.rb | 0 .../rails/app/mailers/application_mailer.rb | 0 .../rails/app/models/application_record.rb | 0 spec/{ => apps}/rails/app/models/concerns/.keep | 0 .../rails/app/views/layouts/application.html.erb | 0 .../rails/app/views/layouts/mailer.html.erb | 0 .../rails/app/views/layouts/mailer.text.erb | 0 spec/{ => apps}/rails/bin/rails | 0 spec/{ => apps}/rails/bin/rake | 0 spec/{ => apps}/rails/bin/setup | 0 spec/{ => apps}/rails/bin/yarn | 0 spec/{ => apps}/rails/config.ru | 0 spec/{ => apps}/rails/config/application.rb | 0 spec/{ => apps}/rails/config/boot.rb | 0 spec/{ => apps}/rails/config/cable.yml | 0 spec/{ => apps}/rails/config/credentials.yml.enc | 0 spec/{ => apps}/rails/config/database.yml | 0 spec/{ => apps}/rails/config/environment.rb | 0 .../rails/config/environments/development.rb | 0 .../rails/config/environments/production.rb | 0 spec/{ => apps}/rails/config/environments/test.rb | 0 .../application_controller_renderer.rb | 0 .../config/initializers/backtrace_silencers.rb | 0 .../initializers/content_security_policy.rb | 0 .../config/initializers/cookies_serializer.rb | 0 .../initializers/filter_parameter_logging.rb | 0 .../rails/config/initializers/inflections.rb | 0 .../rails/config/initializers/mime_types.rb | 0 .../rails/config/initializers/wrap_parameters.rb | 0 spec/{ => apps}/rails/config/locales/en.yml | 0 spec/{ => apps}/rails/config/puma.rb | 0 spec/{ => apps}/rails/config/routes.rb | 0 spec/{ => apps}/rails/config/spring.rb | 0 spec/{ => apps}/rails/config/storage.yml | 0 spec/{ => apps}/rails/db/seeds.rb | 0 spec/{ => apps}/rails/doc/openapi.json | 0 spec/{ => apps}/rails/doc/openapi.yaml | 10 +++++----- spec/{ => apps}/rails/doc/screenshot.png | Bin spec/{ => apps}/rails/doc/smart/expected.yaml | 0 spec/{ => apps}/rails/doc/smart/openapi.yaml | 0 spec/{ => apps}/rails/lib/assets/.keep | 0 spec/{ => apps}/rails/lib/tasks/.keep | 0 spec/{ => apps}/rails/log/.keep | 0 spec/{ => apps}/rails/package.json | 0 spec/{ => apps}/rails/public/404.html | 0 spec/{ => apps}/rails/public/422.html | 0 spec/{ => apps}/rails/public/500.html | 0 .../rails/public/apple-touch-icon-precomposed.png | 0 spec/{ => apps}/rails/public/apple-touch-icon.png | 0 spec/{ => apps}/rails/public/favicon.ico | 0 spec/{ => apps}/rails/public/robots.txt | 0 spec/{ => apps}/rails/storage/.keep | 0 spec/{ => apps}/rails/tmp/.keep | 0 spec/{ => apps}/rails/tmp/pids/.keep | 0 spec/{ => apps}/rails/vendor/.keep | 0 .../rails/vendor/my_engine/config/routes.rb | 0 .../vendor/my_engine/lib/my_engine/engine.rb | 0 spec/{ => apps}/roda/doc/openapi.json | 0 spec/{ => apps}/roda/doc/openapi.yaml | 0 spec/{ => apps}/roda/doc/rspec_openapi.rb | 0 spec/{ => apps}/roda/roda_app.rb | 0 spec/integration_tests/rails_test.rb | 4 ++-- spec/integration_tests/roda_test.rb | 4 ++-- spec/minitest/rack_test_spec.rb | 8 ++++---- spec/minitest/rails_spec.rb | 8 ++++---- spec/requests/rails_smart_merge_spec.rb | 4 ++-- spec/requests/rails_spec.rb | 4 ++-- spec/requests/roda_spec.rb | 4 ++-- spec/rspec/rack_test_spec.rb | 8 ++++---- spec/rspec/rails_spec.rb | 14 +++++++------- 87 files changed, 35 insertions(+), 35 deletions(-) rename spec/{ => apps}/rails/.gitignore (98%) rename spec/{ => apps}/rails/Rakefile (100%) rename spec/{ => apps}/rails/app/assets/config/manifest.js (100%) rename spec/{ => apps}/rails/app/assets/images/.keep (100%) rename spec/{ => apps}/rails/app/assets/stylesheets/application.css (100%) rename spec/{ => apps}/rails/app/channels/application_cable/channel.rb (100%) rename spec/{ => apps}/rails/app/channels/application_cable/connection.rb (100%) rename spec/{ => apps}/rails/app/controllers/application_controller.rb (100%) rename spec/{ => apps}/rails/app/controllers/concerns/.keep (100%) rename spec/{ => apps}/rails/app/controllers/images_controller.rb (100%) rename spec/{ => apps}/rails/app/controllers/secret_items_controller.rb (100%) rename spec/{ => apps}/rails/app/controllers/tables_controller.rb (100%) rename spec/{ => apps}/rails/app/controllers/users_controller.rb (100%) rename spec/{ => apps}/rails/app/helpers/application_helper.rb (100%) rename spec/{ => apps}/rails/app/javascript/channels/consumer.js (100%) rename spec/{ => apps}/rails/app/javascript/channels/index.js (100%) rename spec/{ => apps}/rails/app/javascript/packs/application.js (100%) rename spec/{ => apps}/rails/app/jobs/application_job.rb (100%) rename spec/{ => apps}/rails/app/mailers/application_mailer.rb (100%) rename spec/{ => apps}/rails/app/models/application_record.rb (100%) rename spec/{ => apps}/rails/app/models/concerns/.keep (100%) rename spec/{ => apps}/rails/app/views/layouts/application.html.erb (100%) rename spec/{ => apps}/rails/app/views/layouts/mailer.html.erb (100%) rename spec/{ => apps}/rails/app/views/layouts/mailer.text.erb (100%) rename spec/{ => apps}/rails/bin/rails (100%) rename spec/{ => apps}/rails/bin/rake (100%) rename spec/{ => apps}/rails/bin/setup (100%) rename spec/{ => apps}/rails/bin/yarn (100%) rename spec/{ => apps}/rails/config.ru (100%) rename spec/{ => apps}/rails/config/application.rb (100%) rename spec/{ => apps}/rails/config/boot.rb (100%) rename spec/{ => apps}/rails/config/cable.yml (100%) rename spec/{ => apps}/rails/config/credentials.yml.enc (100%) rename spec/{ => apps}/rails/config/database.yml (100%) rename spec/{ => apps}/rails/config/environment.rb (100%) rename spec/{ => apps}/rails/config/environments/development.rb (100%) rename spec/{ => apps}/rails/config/environments/production.rb (100%) rename spec/{ => apps}/rails/config/environments/test.rb (100%) rename spec/{ => apps}/rails/config/initializers/application_controller_renderer.rb (100%) rename spec/{ => apps}/rails/config/initializers/backtrace_silencers.rb (100%) rename spec/{ => apps}/rails/config/initializers/content_security_policy.rb (100%) rename spec/{ => apps}/rails/config/initializers/cookies_serializer.rb (100%) rename spec/{ => apps}/rails/config/initializers/filter_parameter_logging.rb (100%) rename spec/{ => apps}/rails/config/initializers/inflections.rb (100%) rename spec/{ => apps}/rails/config/initializers/mime_types.rb (100%) rename spec/{ => apps}/rails/config/initializers/wrap_parameters.rb (100%) rename spec/{ => apps}/rails/config/locales/en.yml (100%) rename spec/{ => apps}/rails/config/puma.rb (100%) rename spec/{ => apps}/rails/config/routes.rb (100%) rename spec/{ => apps}/rails/config/spring.rb (100%) rename spec/{ => apps}/rails/config/storage.yml (100%) rename spec/{ => apps}/rails/db/seeds.rb (100%) rename spec/{ => apps}/rails/doc/openapi.json (100%) rename spec/{ => apps}/rails/doc/openapi.yaml (99%) rename spec/{ => apps}/rails/doc/screenshot.png (100%) rename spec/{ => apps}/rails/doc/smart/expected.yaml (100%) rename spec/{ => apps}/rails/doc/smart/openapi.yaml (100%) rename spec/{ => apps}/rails/lib/assets/.keep (100%) rename spec/{ => apps}/rails/lib/tasks/.keep (100%) rename spec/{ => apps}/rails/log/.keep (100%) rename spec/{ => apps}/rails/package.json (100%) rename spec/{ => apps}/rails/public/404.html (100%) rename spec/{ => apps}/rails/public/422.html (100%) rename spec/{ => apps}/rails/public/500.html (100%) rename spec/{ => apps}/rails/public/apple-touch-icon-precomposed.png (100%) rename spec/{ => apps}/rails/public/apple-touch-icon.png (100%) rename spec/{ => apps}/rails/public/favicon.ico (100%) rename spec/{ => apps}/rails/public/robots.txt (100%) rename spec/{ => apps}/rails/storage/.keep (100%) rename spec/{ => apps}/rails/tmp/.keep (100%) rename spec/{ => apps}/rails/tmp/pids/.keep (100%) rename spec/{ => apps}/rails/vendor/.keep (100%) rename spec/{ => apps}/rails/vendor/my_engine/config/routes.rb (100%) rename spec/{ => apps}/rails/vendor/my_engine/lib/my_engine/engine.rb (100%) rename spec/{ => apps}/roda/doc/openapi.json (100%) rename spec/{ => apps}/roda/doc/openapi.yaml (100%) rename spec/{ => apps}/roda/doc/rspec_openapi.rb (100%) rename spec/{ => apps}/roda/roda_app.rb (100%) diff --git a/spec/rails/.gitignore b/spec/apps/rails/.gitignore similarity index 98% rename from spec/rails/.gitignore rename to spec/apps/rails/.gitignore index a7c1e90f..9e94df15 100644 --- a/spec/rails/.gitignore +++ b/spec/apps/rails/.gitignore @@ -13,7 +13,7 @@ /db/*.sqlite3-* # Ignore all logfiles and tempfiles. -/log/* +/log/.keep /tmp/* !/log/.keep !/tmp/.keep diff --git a/spec/rails/Rakefile b/spec/apps/rails/Rakefile similarity index 100% rename from spec/rails/Rakefile rename to spec/apps/rails/Rakefile diff --git a/spec/rails/app/assets/config/manifest.js b/spec/apps/rails/app/assets/config/manifest.js similarity index 100% rename from spec/rails/app/assets/config/manifest.js rename to spec/apps/rails/app/assets/config/manifest.js diff --git a/spec/rails/app/assets/images/.keep b/spec/apps/rails/app/assets/images/.keep similarity index 100% rename from spec/rails/app/assets/images/.keep rename to spec/apps/rails/app/assets/images/.keep diff --git a/spec/rails/app/assets/stylesheets/application.css b/spec/apps/rails/app/assets/stylesheets/application.css similarity index 100% rename from spec/rails/app/assets/stylesheets/application.css rename to spec/apps/rails/app/assets/stylesheets/application.css diff --git a/spec/rails/app/channels/application_cable/channel.rb b/spec/apps/rails/app/channels/application_cable/channel.rb similarity index 100% rename from spec/rails/app/channels/application_cable/channel.rb rename to spec/apps/rails/app/channels/application_cable/channel.rb diff --git a/spec/rails/app/channels/application_cable/connection.rb b/spec/apps/rails/app/channels/application_cable/connection.rb similarity index 100% rename from spec/rails/app/channels/application_cable/connection.rb rename to spec/apps/rails/app/channels/application_cable/connection.rb diff --git a/spec/rails/app/controllers/application_controller.rb b/spec/apps/rails/app/controllers/application_controller.rb similarity index 100% rename from spec/rails/app/controllers/application_controller.rb rename to spec/apps/rails/app/controllers/application_controller.rb diff --git a/spec/rails/app/controllers/concerns/.keep b/spec/apps/rails/app/controllers/concerns/.keep similarity index 100% rename from spec/rails/app/controllers/concerns/.keep rename to spec/apps/rails/app/controllers/concerns/.keep diff --git a/spec/rails/app/controllers/images_controller.rb b/spec/apps/rails/app/controllers/images_controller.rb similarity index 100% rename from spec/rails/app/controllers/images_controller.rb rename to spec/apps/rails/app/controllers/images_controller.rb diff --git a/spec/rails/app/controllers/secret_items_controller.rb b/spec/apps/rails/app/controllers/secret_items_controller.rb similarity index 100% rename from spec/rails/app/controllers/secret_items_controller.rb rename to spec/apps/rails/app/controllers/secret_items_controller.rb diff --git a/spec/rails/app/controllers/tables_controller.rb b/spec/apps/rails/app/controllers/tables_controller.rb similarity index 100% rename from spec/rails/app/controllers/tables_controller.rb rename to spec/apps/rails/app/controllers/tables_controller.rb diff --git a/spec/rails/app/controllers/users_controller.rb b/spec/apps/rails/app/controllers/users_controller.rb similarity index 100% rename from spec/rails/app/controllers/users_controller.rb rename to spec/apps/rails/app/controllers/users_controller.rb diff --git a/spec/rails/app/helpers/application_helper.rb b/spec/apps/rails/app/helpers/application_helper.rb similarity index 100% rename from spec/rails/app/helpers/application_helper.rb rename to spec/apps/rails/app/helpers/application_helper.rb diff --git a/spec/rails/app/javascript/channels/consumer.js b/spec/apps/rails/app/javascript/channels/consumer.js similarity index 100% rename from spec/rails/app/javascript/channels/consumer.js rename to spec/apps/rails/app/javascript/channels/consumer.js diff --git a/spec/rails/app/javascript/channels/index.js b/spec/apps/rails/app/javascript/channels/index.js similarity index 100% rename from spec/rails/app/javascript/channels/index.js rename to spec/apps/rails/app/javascript/channels/index.js diff --git a/spec/rails/app/javascript/packs/application.js b/spec/apps/rails/app/javascript/packs/application.js similarity index 100% rename from spec/rails/app/javascript/packs/application.js rename to spec/apps/rails/app/javascript/packs/application.js diff --git a/spec/rails/app/jobs/application_job.rb b/spec/apps/rails/app/jobs/application_job.rb similarity index 100% rename from spec/rails/app/jobs/application_job.rb rename to spec/apps/rails/app/jobs/application_job.rb diff --git a/spec/rails/app/mailers/application_mailer.rb b/spec/apps/rails/app/mailers/application_mailer.rb similarity index 100% rename from spec/rails/app/mailers/application_mailer.rb rename to spec/apps/rails/app/mailers/application_mailer.rb diff --git a/spec/rails/app/models/application_record.rb b/spec/apps/rails/app/models/application_record.rb similarity index 100% rename from spec/rails/app/models/application_record.rb rename to spec/apps/rails/app/models/application_record.rb diff --git a/spec/rails/app/models/concerns/.keep b/spec/apps/rails/app/models/concerns/.keep similarity index 100% rename from spec/rails/app/models/concerns/.keep rename to spec/apps/rails/app/models/concerns/.keep diff --git a/spec/rails/app/views/layouts/application.html.erb b/spec/apps/rails/app/views/layouts/application.html.erb similarity index 100% rename from spec/rails/app/views/layouts/application.html.erb rename to spec/apps/rails/app/views/layouts/application.html.erb diff --git a/spec/rails/app/views/layouts/mailer.html.erb b/spec/apps/rails/app/views/layouts/mailer.html.erb similarity index 100% rename from spec/rails/app/views/layouts/mailer.html.erb rename to spec/apps/rails/app/views/layouts/mailer.html.erb diff --git a/spec/rails/app/views/layouts/mailer.text.erb b/spec/apps/rails/app/views/layouts/mailer.text.erb similarity index 100% rename from spec/rails/app/views/layouts/mailer.text.erb rename to spec/apps/rails/app/views/layouts/mailer.text.erb diff --git a/spec/rails/bin/rails b/spec/apps/rails/bin/rails similarity index 100% rename from spec/rails/bin/rails rename to spec/apps/rails/bin/rails diff --git a/spec/rails/bin/rake b/spec/apps/rails/bin/rake similarity index 100% rename from spec/rails/bin/rake rename to spec/apps/rails/bin/rake diff --git a/spec/rails/bin/setup b/spec/apps/rails/bin/setup similarity index 100% rename from spec/rails/bin/setup rename to spec/apps/rails/bin/setup diff --git a/spec/rails/bin/yarn b/spec/apps/rails/bin/yarn similarity index 100% rename from spec/rails/bin/yarn rename to spec/apps/rails/bin/yarn diff --git a/spec/rails/config.ru b/spec/apps/rails/config.ru similarity index 100% rename from spec/rails/config.ru rename to spec/apps/rails/config.ru diff --git a/spec/rails/config/application.rb b/spec/apps/rails/config/application.rb similarity index 100% rename from spec/rails/config/application.rb rename to spec/apps/rails/config/application.rb diff --git a/spec/rails/config/boot.rb b/spec/apps/rails/config/boot.rb similarity index 100% rename from spec/rails/config/boot.rb rename to spec/apps/rails/config/boot.rb diff --git a/spec/rails/config/cable.yml b/spec/apps/rails/config/cable.yml similarity index 100% rename from spec/rails/config/cable.yml rename to spec/apps/rails/config/cable.yml diff --git a/spec/rails/config/credentials.yml.enc b/spec/apps/rails/config/credentials.yml.enc similarity index 100% rename from spec/rails/config/credentials.yml.enc rename to spec/apps/rails/config/credentials.yml.enc diff --git a/spec/rails/config/database.yml b/spec/apps/rails/config/database.yml similarity index 100% rename from spec/rails/config/database.yml rename to spec/apps/rails/config/database.yml diff --git a/spec/rails/config/environment.rb b/spec/apps/rails/config/environment.rb similarity index 100% rename from spec/rails/config/environment.rb rename to spec/apps/rails/config/environment.rb diff --git a/spec/rails/config/environments/development.rb b/spec/apps/rails/config/environments/development.rb similarity index 100% rename from spec/rails/config/environments/development.rb rename to spec/apps/rails/config/environments/development.rb diff --git a/spec/rails/config/environments/production.rb b/spec/apps/rails/config/environments/production.rb similarity index 100% rename from spec/rails/config/environments/production.rb rename to spec/apps/rails/config/environments/production.rb diff --git a/spec/rails/config/environments/test.rb b/spec/apps/rails/config/environments/test.rb similarity index 100% rename from spec/rails/config/environments/test.rb rename to spec/apps/rails/config/environments/test.rb diff --git a/spec/rails/config/initializers/application_controller_renderer.rb b/spec/apps/rails/config/initializers/application_controller_renderer.rb similarity index 100% rename from spec/rails/config/initializers/application_controller_renderer.rb rename to spec/apps/rails/config/initializers/application_controller_renderer.rb diff --git a/spec/rails/config/initializers/backtrace_silencers.rb b/spec/apps/rails/config/initializers/backtrace_silencers.rb similarity index 100% rename from spec/rails/config/initializers/backtrace_silencers.rb rename to spec/apps/rails/config/initializers/backtrace_silencers.rb diff --git a/spec/rails/config/initializers/content_security_policy.rb b/spec/apps/rails/config/initializers/content_security_policy.rb similarity index 100% rename from spec/rails/config/initializers/content_security_policy.rb rename to spec/apps/rails/config/initializers/content_security_policy.rb diff --git a/spec/rails/config/initializers/cookies_serializer.rb b/spec/apps/rails/config/initializers/cookies_serializer.rb similarity index 100% rename from spec/rails/config/initializers/cookies_serializer.rb rename to spec/apps/rails/config/initializers/cookies_serializer.rb diff --git a/spec/rails/config/initializers/filter_parameter_logging.rb b/spec/apps/rails/config/initializers/filter_parameter_logging.rb similarity index 100% rename from spec/rails/config/initializers/filter_parameter_logging.rb rename to spec/apps/rails/config/initializers/filter_parameter_logging.rb diff --git a/spec/rails/config/initializers/inflections.rb b/spec/apps/rails/config/initializers/inflections.rb similarity index 100% rename from spec/rails/config/initializers/inflections.rb rename to spec/apps/rails/config/initializers/inflections.rb diff --git a/spec/rails/config/initializers/mime_types.rb b/spec/apps/rails/config/initializers/mime_types.rb similarity index 100% rename from spec/rails/config/initializers/mime_types.rb rename to spec/apps/rails/config/initializers/mime_types.rb diff --git a/spec/rails/config/initializers/wrap_parameters.rb b/spec/apps/rails/config/initializers/wrap_parameters.rb similarity index 100% rename from spec/rails/config/initializers/wrap_parameters.rb rename to spec/apps/rails/config/initializers/wrap_parameters.rb diff --git a/spec/rails/config/locales/en.yml b/spec/apps/rails/config/locales/en.yml similarity index 100% rename from spec/rails/config/locales/en.yml rename to spec/apps/rails/config/locales/en.yml diff --git a/spec/rails/config/puma.rb b/spec/apps/rails/config/puma.rb similarity index 100% rename from spec/rails/config/puma.rb rename to spec/apps/rails/config/puma.rb diff --git a/spec/rails/config/routes.rb b/spec/apps/rails/config/routes.rb similarity index 100% rename from spec/rails/config/routes.rb rename to spec/apps/rails/config/routes.rb diff --git a/spec/rails/config/spring.rb b/spec/apps/rails/config/spring.rb similarity index 100% rename from spec/rails/config/spring.rb rename to spec/apps/rails/config/spring.rb diff --git a/spec/rails/config/storage.yml b/spec/apps/rails/config/storage.yml similarity index 100% rename from spec/rails/config/storage.yml rename to spec/apps/rails/config/storage.yml diff --git a/spec/rails/db/seeds.rb b/spec/apps/rails/db/seeds.rb similarity index 100% rename from spec/rails/db/seeds.rb rename to spec/apps/rails/db/seeds.rb diff --git a/spec/rails/doc/openapi.json b/spec/apps/rails/doc/openapi.json similarity index 100% rename from spec/rails/doc/openapi.json rename to spec/apps/rails/doc/openapi.json diff --git a/spec/rails/doc/openapi.yaml b/spec/apps/rails/doc/openapi.yaml similarity index 99% rename from spec/rails/doc/openapi.yaml rename to spec/apps/rails/doc/openapi.yaml index c1be9e5a..e73ce612 100644 --- a/spec/rails/doc/openapi.yaml +++ b/spec/apps/rails/doc/openapi.yaml @@ -345,7 +345,7 @@ paths: database: id: 2 name: production - null_sample: + null_sample: storage_size: 12.3 created_at: '2020-07-17T00:00:00+00:00' updated_at: '2020-07-17T00:00:00+00:00' @@ -415,7 +415,7 @@ paths: database: id: 2 name: production - null_sample: + null_sample: storage_size: 12.3 created_at: '2020-07-17T00:00:00+00:00' updated_at: '2020-07-17T00:00:00+00:00' @@ -513,7 +513,7 @@ paths: database: id: 2 name: production - null_sample: + null_sample: storage_size: 12.3 created_at: '2020-07-17T00:00:00+00:00' updated_at: '2020-07-17T00:00:00+00:00' @@ -591,7 +591,7 @@ paths: database: id: 2 name: production - null_sample: + null_sample: storage_size: 12.3 created_at: '2020-07-17T00:00:00+00:00' updated_at: '2020-07-17T00:00:00+00:00' @@ -693,7 +693,7 @@ paths: database: id: 2 name: production - null_sample: + null_sample: storage_size: 12.3 created_at: '2020-07-17T00:00:00+00:00' updated_at: '2020-07-17T00:00:00+00:00' diff --git a/spec/rails/doc/screenshot.png b/spec/apps/rails/doc/screenshot.png similarity index 100% rename from spec/rails/doc/screenshot.png rename to spec/apps/rails/doc/screenshot.png diff --git a/spec/rails/doc/smart/expected.yaml b/spec/apps/rails/doc/smart/expected.yaml similarity index 100% rename from spec/rails/doc/smart/expected.yaml rename to spec/apps/rails/doc/smart/expected.yaml diff --git a/spec/rails/doc/smart/openapi.yaml b/spec/apps/rails/doc/smart/openapi.yaml similarity index 100% rename from spec/rails/doc/smart/openapi.yaml rename to spec/apps/rails/doc/smart/openapi.yaml diff --git a/spec/rails/lib/assets/.keep b/spec/apps/rails/lib/assets/.keep similarity index 100% rename from spec/rails/lib/assets/.keep rename to spec/apps/rails/lib/assets/.keep diff --git a/spec/rails/lib/tasks/.keep b/spec/apps/rails/lib/tasks/.keep similarity index 100% rename from spec/rails/lib/tasks/.keep rename to spec/apps/rails/lib/tasks/.keep diff --git a/spec/rails/log/.keep b/spec/apps/rails/log/.keep similarity index 100% rename from spec/rails/log/.keep rename to spec/apps/rails/log/.keep diff --git a/spec/rails/package.json b/spec/apps/rails/package.json similarity index 100% rename from spec/rails/package.json rename to spec/apps/rails/package.json diff --git a/spec/rails/public/404.html b/spec/apps/rails/public/404.html similarity index 100% rename from spec/rails/public/404.html rename to spec/apps/rails/public/404.html diff --git a/spec/rails/public/422.html b/spec/apps/rails/public/422.html similarity index 100% rename from spec/rails/public/422.html rename to spec/apps/rails/public/422.html diff --git a/spec/rails/public/500.html b/spec/apps/rails/public/500.html similarity index 100% rename from spec/rails/public/500.html rename to spec/apps/rails/public/500.html diff --git a/spec/rails/public/apple-touch-icon-precomposed.png b/spec/apps/rails/public/apple-touch-icon-precomposed.png similarity index 100% rename from spec/rails/public/apple-touch-icon-precomposed.png rename to spec/apps/rails/public/apple-touch-icon-precomposed.png diff --git a/spec/rails/public/apple-touch-icon.png b/spec/apps/rails/public/apple-touch-icon.png similarity index 100% rename from spec/rails/public/apple-touch-icon.png rename to spec/apps/rails/public/apple-touch-icon.png diff --git a/spec/rails/public/favicon.ico b/spec/apps/rails/public/favicon.ico similarity index 100% rename from spec/rails/public/favicon.ico rename to spec/apps/rails/public/favicon.ico diff --git a/spec/rails/public/robots.txt b/spec/apps/rails/public/robots.txt similarity index 100% rename from spec/rails/public/robots.txt rename to spec/apps/rails/public/robots.txt diff --git a/spec/rails/storage/.keep b/spec/apps/rails/storage/.keep similarity index 100% rename from spec/rails/storage/.keep rename to spec/apps/rails/storage/.keep diff --git a/spec/rails/tmp/.keep b/spec/apps/rails/tmp/.keep similarity index 100% rename from spec/rails/tmp/.keep rename to spec/apps/rails/tmp/.keep diff --git a/spec/rails/tmp/pids/.keep b/spec/apps/rails/tmp/pids/.keep similarity index 100% rename from spec/rails/tmp/pids/.keep rename to spec/apps/rails/tmp/pids/.keep diff --git a/spec/rails/vendor/.keep b/spec/apps/rails/vendor/.keep similarity index 100% rename from spec/rails/vendor/.keep rename to spec/apps/rails/vendor/.keep diff --git a/spec/rails/vendor/my_engine/config/routes.rb b/spec/apps/rails/vendor/my_engine/config/routes.rb similarity index 100% rename from spec/rails/vendor/my_engine/config/routes.rb rename to spec/apps/rails/vendor/my_engine/config/routes.rb diff --git a/spec/rails/vendor/my_engine/lib/my_engine/engine.rb b/spec/apps/rails/vendor/my_engine/lib/my_engine/engine.rb similarity index 100% rename from spec/rails/vendor/my_engine/lib/my_engine/engine.rb rename to spec/apps/rails/vendor/my_engine/lib/my_engine/engine.rb diff --git a/spec/roda/doc/openapi.json b/spec/apps/roda/doc/openapi.json similarity index 100% rename from spec/roda/doc/openapi.json rename to spec/apps/roda/doc/openapi.json diff --git a/spec/roda/doc/openapi.yaml b/spec/apps/roda/doc/openapi.yaml similarity index 100% rename from spec/roda/doc/openapi.yaml rename to spec/apps/roda/doc/openapi.yaml diff --git a/spec/roda/doc/rspec_openapi.rb b/spec/apps/roda/doc/rspec_openapi.rb similarity index 100% rename from spec/roda/doc/rspec_openapi.rb rename to spec/apps/roda/doc/rspec_openapi.rb diff --git a/spec/roda/roda_app.rb b/spec/apps/roda/roda_app.rb similarity index 100% rename from spec/roda/roda_app.rb rename to spec/apps/roda/roda_app.rb diff --git a/spec/integration_tests/rails_test.rb b/spec/integration_tests/rails_test.rb index 8cce8dc3..28afa884 100644 --- a/spec/integration_tests/rails_test.rb +++ b/spec/integration_tests/rails_test.rb @@ -5,12 +5,12 @@ ENV['OPENAPI_OUTPUT'] ||= 'yaml' require 'minitest/autorun' -require File.expand_path('../rails/config/environment', __dir__) +require File.expand_path('../apps/rails/config/environment', __dir__) RSpec::OpenAPI.title = 'OpenAPI Documentation' RSpec::OpenAPI.request_headers = %w[X-Authorization-Token] RSpec::OpenAPI.response_headers = %w[X-Cursor] -RSpec::OpenAPI.path = File.expand_path("../rails/doc/openapi.#{ENV.fetch('OPENAPI_OUTPUT', nil)}", __dir__) +RSpec::OpenAPI.path = File.expand_path("../apps/rails/doc/openapi.#{ENV.fetch('OPENAPI_OUTPUT', nil)}", __dir__) RSpec::OpenAPI.comment = <<~COMMENT This file is auto-generated by rspec-openapi https://github.com/k0kubun/rspec-openapi diff --git a/spec/integration_tests/roda_test.rb b/spec/integration_tests/roda_test.rb index 8151d2c3..f83b9661 100644 --- a/spec/integration_tests/roda_test.rb +++ b/spec/integration_tests/roda_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative '../roda/roda_app' +require_relative '../apps/roda/roda_app' require 'json' require 'rack/test' require 'minitest/autorun' @@ -9,7 +9,7 @@ ENV['OPENAPI_OUTPUT'] ||= 'yaml' RSpec::OpenAPI.title = 'OpenAPI Documentation' -RSpec::OpenAPI.path = File.expand_path("../roda/doc/openapi.#{ENV.fetch('OPENAPI_OUTPUT', nil)}", __dir__) +RSpec::OpenAPI.path = File.expand_path("../apps/roda/doc/openapi.#{ENV.fetch('OPENAPI_OUTPUT', nil)}", __dir__) class RodaTest < Minitest::Test include Rack::Test::Methods diff --git a/spec/minitest/rack_test_spec.rb b/spec/minitest/rack_test_spec.rb index 20c8d424..3ea15c3f 100644 --- a/spec/minitest/rack_test_spec.rb +++ b/spec/minitest/rack_test_spec.rb @@ -9,10 +9,10 @@ describe 'yaml output' do let(:openapi_path) do - File.expand_path('spec/roda/doc/openapi.yaml', repo_root) + File.expand_path('spec/apps/roda/doc/openapi.yaml', repo_root) end - it 'generates the same spec/roda/doc/openapi.yaml' do + it 'generates the same spec/apps/roda/doc/openapi.yaml' do org_yaml = YAML.safe_load(File.read(openapi_path)) minitest 'spec/integration_tests/roda_test.rb', openapi: true new_yaml = YAML.safe_load(File.read(openapi_path)) @@ -22,10 +22,10 @@ describe 'json output' do let(:openapi_path) do - File.expand_path('spec/roda/doc/openapi.json', repo_root) + File.expand_path('spec/apps/roda/doc/openapi.json', repo_root) end - it 'generates the same spec/roda/doc/openapi.json' do + it 'generates the same spec/apps/roda/doc/openapi.json' do org_yaml = YAML.safe_load(File.read(openapi_path)) minitest 'spec/integration_tests/roda_test.rb', openapi: true, output: :json new_yaml = YAML.safe_load(File.read(openapi_path)) diff --git a/spec/minitest/rails_spec.rb b/spec/minitest/rails_spec.rb index d67a3cab..eee10628 100644 --- a/spec/minitest/rails_spec.rb +++ b/spec/minitest/rails_spec.rb @@ -10,10 +10,10 @@ describe 'yaml output' do let(:openapi_path) do - File.expand_path('spec/rails/doc/openapi.yaml', repo_root) + File.expand_path('spec/apps/rails/doc/openapi.yaml', repo_root) end - it 'generates the same spec/rails/doc/openapi.yaml' do + it 'generates the same spec/apps/rails/doc/openapi.yaml' do org_yaml = YAML.safe_load(File.read(openapi_path)) minitest 'spec/integration_tests/rails_test.rb', openapi: true, output: :yaml new_yaml = YAML.safe_load(File.read(openapi_path)) @@ -23,10 +23,10 @@ describe 'json' do let(:openapi_path) do - File.expand_path('spec/rails/doc/openapi.json', repo_root) + File.expand_path('spec/apps/rails/doc/openapi.json', repo_root) end - it 'generates the same spec/rails/doc/openapi.json' do + it 'generates the same spec/apps/rails/doc/openapi.json' do org_yaml = JSON.parse(File.read(openapi_path)) minitest 'spec/integration_tests/rails_test.rb', openapi: true, output: :json new_yaml = JSON.parse(File.read(openapi_path)) diff --git a/spec/requests/rails_smart_merge_spec.rb b/spec/requests/rails_smart_merge_spec.rb index 3a98aba5..79499090 100644 --- a/spec/requests/rails_smart_merge_spec.rb +++ b/spec/requests/rails_smart_merge_spec.rb @@ -4,12 +4,12 @@ ENV['RAILS_ENV'] ||= 'test' ENV['OPENAPI_OUTPUT'] ||= 'json' -require File.expand_path('../rails/config/environment', __dir__) +require File.expand_path('../apps/rails/config/environment', __dir__) require 'rspec/rails' RSpec::OpenAPI.request_headers = %w[X-Authorization-Token] RSpec::OpenAPI.response_headers = %w[X-Cursor] -RSpec::OpenAPI.path = File.expand_path("../rails/doc/smart/openapi.#{ENV.fetch('OPENAPI_OUTPUT', nil)}", __dir__) +RSpec::OpenAPI.path = File.expand_path("../apps/rails/doc/smart/openapi.#{ENV.fetch('OPENAPI_OUTPUT', nil)}", __dir__) RSpec::OpenAPI.comment = <<~COMMENT This file is auto-generated by rspec-openapi https://github.com/k0kubun/rspec-openapi diff --git a/spec/requests/rails_spec.rb b/spec/requests/rails_spec.rb index 9b45971d..a6184cd7 100644 --- a/spec/requests/rails_spec.rb +++ b/spec/requests/rails_spec.rb @@ -4,13 +4,13 @@ ENV['RAILS_ENV'] ||= 'test' ENV['OPENAPI_OUTPUT'] ||= 'yaml' -require File.expand_path('../rails/config/environment', __dir__) +require File.expand_path('../apps/rails/config/environment', __dir__) require 'rspec/rails' RSpec::OpenAPI.title = 'OpenAPI Documentation' RSpec::OpenAPI.request_headers = %w[X-Authorization-Token Secret-Key] RSpec::OpenAPI.response_headers = %w[X-Cursor] -RSpec::OpenAPI.path = File.expand_path("../rails/doc/openapi.#{ENV.fetch('OPENAPI_OUTPUT', nil)}", __dir__) +RSpec::OpenAPI.path = File.expand_path("../apps/rails/doc/openapi.#{ENV.fetch('OPENAPI_OUTPUT', nil)}", __dir__) RSpec::OpenAPI.comment = <<~COMMENT This file is auto-generated by rspec-openapi https://github.com/k0kubun/rspec-openapi diff --git a/spec/requests/roda_spec.rb b/spec/requests/roda_spec.rb index b54645f6..34a007f4 100644 --- a/spec/requests/roda_spec.rb +++ b/spec/requests/roda_spec.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true -require_relative '../roda/roda_app' +require_relative '../apps/roda/roda_app' require 'json' require 'rack/test' ENV['OPENAPI_OUTPUT'] ||= 'yaml' RSpec::OpenAPI.title = 'OpenAPI Documentation' -RSpec::OpenAPI.path = File.expand_path("../roda/doc/openapi.#{ENV.fetch('OPENAPI_OUTPUT', nil)}", __dir__) +RSpec::OpenAPI.path = File.expand_path("../apps/roda/doc/openapi.#{ENV.fetch('OPENAPI_OUTPUT', nil)}", __dir__) RSpec::OpenAPI.description_builder = lambda do |example| contexts = example.example_group.parent_groups.map(&:description).grep(/\Awhen /) diff --git a/spec/rspec/rack_test_spec.rb b/spec/rspec/rack_test_spec.rb index 40866ec2..c8735398 100644 --- a/spec/rspec/rack_test_spec.rb +++ b/spec/rspec/rack_test_spec.rb @@ -9,10 +9,10 @@ describe 'yaml output' do let(:openapi_path) do - File.expand_path('spec/roda/doc/openapi.yaml', repo_root) + File.expand_path('spec/apps/roda/doc/openapi.yaml', repo_root) end - it 'generates the same spec/roda/doc/openapi.yaml' do + it 'generates the same spec/apps/roda/doc/openapi.yaml' do org_yaml = YAML.safe_load(File.read(openapi_path)) rspec 'spec/requests/roda_spec.rb', openapi: true new_yaml = YAML.safe_load(File.read(openapi_path)) @@ -22,10 +22,10 @@ describe 'json output' do let(:openapi_path) do - File.expand_path('spec/roda/doc/openapi.json', repo_root) + File.expand_path('spec/apps/roda/doc/openapi.json', repo_root) end - it 'generates the same spec/roda/doc/openapi.json' do + it 'generates the same spec/apps/roda/doc/openapi.json' do org_yaml = YAML.safe_load(File.read(openapi_path)) rspec 'spec/requests/roda_spec.rb', openapi: true, output: :json new_yaml = YAML.safe_load(File.read(openapi_path)) diff --git a/spec/rspec/rails_spec.rb b/spec/rspec/rails_spec.rb index 7e310b64..aa15a33e 100644 --- a/spec/rspec/rails_spec.rb +++ b/spec/rspec/rails_spec.rb @@ -10,10 +10,10 @@ describe 'yaml output' do let(:openapi_path) do - File.expand_path('spec/rails/doc/openapi.yaml', repo_root) + File.expand_path('spec/apps/rails/doc/openapi.yaml', repo_root) end - it 'generates the same spec/rails/doc/openapi.yaml' do + it 'generates the same spec/apps/rails/doc/openapi.yaml' do org_yaml = YAML.safe_load(File.read(openapi_path)) rspec 'spec/requests/rails_spec.rb', openapi: true, output: :yaml new_yaml = YAML.safe_load(File.read(openapi_path)) @@ -23,10 +23,10 @@ describe 'json' do let(:openapi_path) do - File.expand_path('spec/rails/doc/openapi.json', repo_root) + File.expand_path('spec/apps/rails/doc/openapi.json', repo_root) end - it 'generates the same spec/rails/doc/openapi.json' do + it 'generates the same spec/apps/rails/doc/openapi.json' do org_json = JSON.parse(File.read(openapi_path)) rspec 'spec/requests/rails_spec.rb', openapi: true, output: :json new_json = JSON.parse(File.read(openapi_path)) @@ -36,14 +36,14 @@ describe 'smart merge' do let(:openapi_path) do - File.expand_path('spec/rails/doc/smart/openapi.yaml', repo_root) + File.expand_path('spec/apps/rails/doc/smart/openapi.yaml', repo_root) end let(:expected_path) do - File.expand_path('spec/rails/doc/smart/expected.yaml', repo_root) + File.expand_path('spec/apps/rails/doc/smart/expected.yaml', repo_root) end - it 'updates the spec/rails/doc/smart/openapi.yaml as same as in expected.yaml' do + it 'updates the spec/apps/rails/doc/smart/openapi.yaml as same as in expected.yaml' do original_source = File.read(openapi_path) begin rspec 'spec/requests/rails_smart_merge_spec.rb', openapi: true, output: :yaml From 0629d976fe347ac28bff593e753a17a83e22f272 Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Tue, 26 Mar 2024 18:14:14 +0500 Subject: [PATCH 05/17] Add hanami to test apps --- Gemfile | 7 +- spec/apps/hanami/.gitignore | 2 + spec/apps/hanami/Gemfile | 29 +++++++ spec/apps/hanami/Procfile.dev | 1 + spec/apps/hanami/Rakefile | 3 + spec/apps/hanami/app/action.rb | 9 ++ spec/apps/hanami/app/actions/.keep | 0 .../hanami/app/templates/layouts/app.html.erb | 11 +++ spec/apps/hanami/app/view.rb | 9 ++ spec/apps/hanami/app/views/helpers.rb | 10 +++ spec/apps/hanami/bin/dev | 8 ++ spec/apps/hanami/config.ru | 5 ++ spec/apps/hanami/config/app.rb | 8 ++ spec/apps/hanami/config/puma.rb | 47 +++++++++++ spec/apps/hanami/config/routes.rb | 7 ++ spec/apps/hanami/config/settings.rb | 9 ++ spec/apps/hanami/lib/hanami/types.rb | 11 +++ spec/apps/hanami/lib/tasks/.keep | 0 spec/apps/hanami/public/404.html | 82 +++++++++++++++++++ spec/apps/hanami/public/500.html | 82 +++++++++++++++++++ 20 files changed, 339 insertions(+), 1 deletion(-) create mode 100644 spec/apps/hanami/.gitignore create mode 100644 spec/apps/hanami/Gemfile create mode 100644 spec/apps/hanami/Procfile.dev create mode 100644 spec/apps/hanami/Rakefile create mode 100644 spec/apps/hanami/app/action.rb create mode 100644 spec/apps/hanami/app/actions/.keep create mode 100644 spec/apps/hanami/app/templates/layouts/app.html.erb create mode 100644 spec/apps/hanami/app/view.rb create mode 100644 spec/apps/hanami/app/views/helpers.rb create mode 100755 spec/apps/hanami/bin/dev create mode 100644 spec/apps/hanami/config.ru create mode 100644 spec/apps/hanami/config/app.rb create mode 100644 spec/apps/hanami/config/puma.rb create mode 100644 spec/apps/hanami/config/routes.rb create mode 100644 spec/apps/hanami/config/settings.rb create mode 100644 spec/apps/hanami/lib/hanami/types.rb create mode 100644 spec/apps/hanami/lib/tasks/.keep create mode 100644 spec/apps/hanami/public/404.html create mode 100644 spec/apps/hanami/public/500.html diff --git a/Gemfile b/Gemfile index 754b331a..bfc1ac1f 100644 --- a/Gemfile +++ b/Gemfile @@ -6,8 +6,13 @@ source 'https://rubygems.org' gemspec gem 'rails', ENV['RAILS_VERSION'] || '6.0.3.7' -gem 'rails-dom-testing', '~> 2.2' + +gem 'hanami', ENV['HANAMI_VERSION'] || '2.1.0' +gem 'hanami-router', ENV['HANAMI_VERSION'] || '2.1.0' + gem 'roda' + +gem 'rails-dom-testing', '~> 2.2' gem 'rspec-rails' group :test do diff --git a/spec/apps/hanami/.gitignore b/spec/apps/hanami/.gitignore new file mode 100644 index 00000000..f1112aba --- /dev/null +++ b/spec/apps/hanami/.gitignore @@ -0,0 +1,2 @@ +.env +log/* diff --git a/spec/apps/hanami/Gemfile b/spec/apps/hanami/Gemfile new file mode 100644 index 00000000..fe10f27f --- /dev/null +++ b/spec/apps/hanami/Gemfile @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +# gem "hanami", "~> 2.1" +gem "hanami-controller", "~> 2.1" +gem "hanami-router", "~> 2.1" +# ? gem "hanami-validations", "~> 2.1" +# ? gem "hanami-view", "~> 2.1" + +gem "dry-types", "~> 1.0", ">= 1.6.1" +# gem "puma" +# gem "rake" + +# group :development do +# gem "hanami-webconsole", "~> 2.1" +# end +# +# group :development, :test do +# gem "dotenv" +# end +# +# group :cli, :development do +# gem "hanami-reloader", "~> 2.1" +# end +# +# group :cli, :development, :test do +# gem "hanami-rspec", "~> 2.1" +# end diff --git a/spec/apps/hanami/Procfile.dev b/spec/apps/hanami/Procfile.dev new file mode 100644 index 00000000..9c043624 --- /dev/null +++ b/spec/apps/hanami/Procfile.dev @@ -0,0 +1 @@ +web: bundle exec hanami server diff --git a/spec/apps/hanami/Rakefile b/spec/apps/hanami/Rakefile new file mode 100644 index 00000000..c526f383 --- /dev/null +++ b/spec/apps/hanami/Rakefile @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require "hanami/rake_tasks" diff --git a/spec/apps/hanami/app/action.rb b/spec/apps/hanami/app/action.rb new file mode 100644 index 00000000..6e2fad60 --- /dev/null +++ b/spec/apps/hanami/app/action.rb @@ -0,0 +1,9 @@ +# auto_register: false +# frozen_string_literal: true + +require "hanami/action" + +module Hanami + class Action < Hanami::Action + end +end diff --git a/spec/apps/hanami/app/actions/.keep b/spec/apps/hanami/app/actions/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/apps/hanami/app/templates/layouts/app.html.erb b/spec/apps/hanami/app/templates/layouts/app.html.erb new file mode 100644 index 00000000..6ef771f3 --- /dev/null +++ b/spec/apps/hanami/app/templates/layouts/app.html.erb @@ -0,0 +1,11 @@ + + + + + + Hanami + + + <%= yield %> + + diff --git a/spec/apps/hanami/app/view.rb b/spec/apps/hanami/app/view.rb new file mode 100644 index 00000000..59d79df6 --- /dev/null +++ b/spec/apps/hanami/app/view.rb @@ -0,0 +1,9 @@ +# auto_register: false +# frozen_string_literal: true + +require "hanami/view" + +module Hanami + class View < Hanami::View + end +end diff --git a/spec/apps/hanami/app/views/helpers.rb b/spec/apps/hanami/app/views/helpers.rb new file mode 100644 index 00000000..b93d1efe --- /dev/null +++ b/spec/apps/hanami/app/views/helpers.rb @@ -0,0 +1,10 @@ +# auto_register: false +# frozen_string_literal: true + +module Hanami + module Views + module Helpers + # Add your view helpers here + end + end +end diff --git a/spec/apps/hanami/bin/dev b/spec/apps/hanami/bin/dev new file mode 100755 index 00000000..74ade166 --- /dev/null +++ b/spec/apps/hanami/bin/dev @@ -0,0 +1,8 @@ +#!/usr/bin/env sh + +if ! gem list foreman -i --silent; then + echo "Installing foreman..." + gem install foreman +fi + +exec foreman start -f Procfile.dev "$@" diff --git a/spec/apps/hanami/config.ru b/spec/apps/hanami/config.ru new file mode 100644 index 00000000..879c0858 --- /dev/null +++ b/spec/apps/hanami/config.ru @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +require "hanami/boot" + +run Hanami.app diff --git a/spec/apps/hanami/config/app.rb b/spec/apps/hanami/config/app.rb new file mode 100644 index 00000000..0da32152 --- /dev/null +++ b/spec/apps/hanami/config/app.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require "hanami" + +module Hanami + class App < Hanami::App + end +end diff --git a/spec/apps/hanami/config/puma.rb b/spec/apps/hanami/config/puma.rb new file mode 100644 index 00000000..1866af83 --- /dev/null +++ b/spec/apps/hanami/config/puma.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +# +# Environment and port +# +port ENV.fetch("HANAMI_PORT", 2300) +environment ENV.fetch("HANAMI_ENV", "development") + +# +# Threads within each Puma/Ruby process (aka worker) +# + +# Configure the minimum and maximum number of threads to use to answer requests. +max_threads_count = ENV.fetch("HANAMI_MAX_THREADS", 5) +min_threads_count = ENV.fetch("HANAMI_MIN_THREADS") { max_threads_count } + +threads min_threads_count, max_threads_count + +# +# Workers (aka Puma/Ruby processes) +# + +puma_concurrency = Integer(ENV.fetch("HANAMI_WEB_CONCURRENCY", 0)) +puma_cluster_mode = puma_concurrency > 1 + +# How many worker (Puma/Ruby) processes to run. +# Typically this is set to the number of available cores. +workers puma_concurrency + +# +# Cluster mode (aka multiple workers) +# + +if puma_cluster_mode + # Preload the application before starting the workers. Only in cluster mode. + preload_app! + + # Code to run immediately before master process forks workers (once on boot). + # + # These hooks can block if necessary to wait for background operations unknown + # to puma to finish before the process terminates. This can be used to close + # any connections to remote servers (database, redis, …) that were opened when + # preloading the code. + before_fork do + Hanami.shutdown + end +end diff --git a/spec/apps/hanami/config/routes.rb b/spec/apps/hanami/config/routes.rb new file mode 100644 index 00000000..9caa1430 --- /dev/null +++ b/spec/apps/hanami/config/routes.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Hanami + class Routes < Hanami::Routes + # Add your routes here. See https://guides.hanamirb.org/routing/overview/ for details. + end +end diff --git a/spec/apps/hanami/config/settings.rb b/spec/apps/hanami/config/settings.rb new file mode 100644 index 00000000..59e3e6d7 --- /dev/null +++ b/spec/apps/hanami/config/settings.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Hanami + class Settings < Hanami::Settings + # Define your app settings here, for example: + # + # setting :my_flag, default: false, constructor: Types::Params::Bool + end +end diff --git a/spec/apps/hanami/lib/hanami/types.rb b/spec/apps/hanami/lib/hanami/types.rb new file mode 100644 index 00000000..3961bb6b --- /dev/null +++ b/spec/apps/hanami/lib/hanami/types.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require "dry/types" + +module Hanami + Types = Dry.Types + + module Types + # Define your custom types here + end +end diff --git a/spec/apps/hanami/lib/tasks/.keep b/spec/apps/hanami/lib/tasks/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/apps/hanami/public/404.html b/spec/apps/hanami/public/404.html new file mode 100644 index 00000000..51242009 --- /dev/null +++ b/spec/apps/hanami/public/404.html @@ -0,0 +1,82 @@ + + + + + + The page you were looking for doesn’t exist (404) + + + + +
+
+

404

+

The page you were looking for doesn’t exist.

+
+
+ + diff --git a/spec/apps/hanami/public/500.html b/spec/apps/hanami/public/500.html new file mode 100644 index 00000000..1f8ff3cc --- /dev/null +++ b/spec/apps/hanami/public/500.html @@ -0,0 +1,82 @@ + + + + + + We’re sorry, but something went wrong (500) + + + + +
+
+

500

+

We’re sorry, but something went wrong.

+
+
+ + From cd84b7daa1a8c49a8a9105f902319e19e1a784fe Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Tue, 26 Mar 2024 21:55:53 +0500 Subject: [PATCH 06/17] Make Hanami load in the tests --- spec/apps/hanami/Gemfile | 29 ---- spec/apps/hanami/config/app.rb | 2 +- spec/requests/hanami_spec.rb | 263 +++++++++++++++++++++++++++++++++ 3 files changed, 264 insertions(+), 30 deletions(-) delete mode 100644 spec/apps/hanami/Gemfile create mode 100644 spec/requests/hanami_spec.rb diff --git a/spec/apps/hanami/Gemfile b/spec/apps/hanami/Gemfile deleted file mode 100644 index fe10f27f..00000000 --- a/spec/apps/hanami/Gemfile +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -source "https://rubygems.org" - -# gem "hanami", "~> 2.1" -gem "hanami-controller", "~> 2.1" -gem "hanami-router", "~> 2.1" -# ? gem "hanami-validations", "~> 2.1" -# ? gem "hanami-view", "~> 2.1" - -gem "dry-types", "~> 1.0", ">= 1.6.1" -# gem "puma" -# gem "rake" - -# group :development do -# gem "hanami-webconsole", "~> 2.1" -# end -# -# group :development, :test do -# gem "dotenv" -# end -# -# group :cli, :development do -# gem "hanami-reloader", "~> 2.1" -# end -# -# group :cli, :development, :test do -# gem "hanami-rspec", "~> 2.1" -# end diff --git a/spec/apps/hanami/config/app.rb b/spec/apps/hanami/config/app.rb index 0da32152..7036eef3 100644 --- a/spec/apps/hanami/config/app.rb +++ b/spec/apps/hanami/config/app.rb @@ -3,6 +3,6 @@ require "hanami" module Hanami - class App < Hanami::App + class AppTest < Hanami::App end end diff --git a/spec/requests/hanami_spec.rb b/spec/requests/hanami_spec.rb new file mode 100644 index 00000000..8599f838 --- /dev/null +++ b/spec/requests/hanami_spec.rb @@ -0,0 +1,263 @@ +# frozen_string_literal: true + +ENV['TZ'] ||= 'UTC' +ENV['HANAMI_ENV'] ||= 'test' +ENV['OPENAPI_OUTPUT'] ||= 'yaml' + +require "hanami" + +module Hanami + def self.app_path(dir = Hanami.app_path(File.expand_path('../apps/hanami/', __dir__))) + dir = Pathname(dir).expand_path + path = dir.join(APP_PATH) + + if path.file? + path + elsif !dir.root? + app_path(dir.parent) + end + end +end +# SPEC_ROOT = File.expand_path('../apps/hanami', __dir__).freeze + +require "hanami/prepare" + +RSpec::OpenAPI.title = 'OpenAPI Documentation' +RSpec::OpenAPI.request_headers = %w[X-Authorization-Token Secret-Key] +RSpec::OpenAPI.response_headers = %w[X-Cursor] +RSpec::OpenAPI.path = File.expand_path("../apps/rails/doc/openapi.#{ENV.fetch('OPENAPI_OUTPUT', nil)}", __dir__) +RSpec::OpenAPI.comment = <<~COMMENT + This file is auto-generated by rspec-openapi https://github.com/k0kubun/rspec-openapi + + When you write a spec in spec/requests, running the spec with `OPENAPI=1 rspec` will + update this file automatically. You can also manually edit this file. +COMMENT +RSpec::OpenAPI.servers = [{ url: 'http://localhost:3000' }] +RSpec::OpenAPI.info = { + description: 'My beautiful API', + license: { + name: 'Apache 2.0', + url: 'https://www.apache.org/licenses/LICENSE-2.0.html', + }, +} + +RSpec::OpenAPI.security_schemes = { + SecretApiKeyAuth: { + type: 'apiKey', + in: 'header', + name: 'Secret-Key', + }, +} + +RSpec.xdescribe 'Tables', type: :request do + describe '#index' do + context it 'returns a list of tables' do + it 'with flat query parameters' do + get '/tables', params: { page: '1', per: '10' }, + headers: { authorization: 'k0kubun', 'X-Authorization-Token': 'token' } + expect(response.status).to eq(200) + end + + it 'with deep query parameters' do + get '/tables', params: { filter: { 'name' => 'Example Table' } }, headers: { authorization: 'k0kubun' } + expect(response.status).to eq(200) + end + + it 'with different deep query parameters' do + get '/tables', params: { filter: { 'price' => 0 } }, headers: { authorization: 'k0kubun' } + expect(response.status).to eq(200) + end + end + + it 'has a request spec which does not make any request' do + expect(request).to eq(nil) + end + + it 'does not return tables if unauthorized' do + get '/tables' + expect(response.status).to eq(401) + end + end + + describe '#show' do + it 'returns a table' do + get '/tables/1', headers: { authorization: 'k0kubun' } + expect(response.status).to eq(200) + end + + it 'does not return a table if unauthorized' do + get '/tables/1' + expect(response.status).to eq(401) + end + + it 'does not return a table if not found' do + get '/tables/2', headers: { authorization: 'k0kubun' } + expect(response.status).to eq(404) + end + + it 'does not return a table if not found (openapi: false)', openapi: false do + get '/tables/3', headers: { authorization: 'k0kubun' } + expect(response.status).to eq(404) + end + end + + describe '#create' do + it 'returns a table' do + post '/tables', headers: { authorization: 'k0kubun', 'Content-Type': 'application/json' }, params: { + name: 'k0kubun', + description: 'description', + database_id: 2, + }.to_json + expect(response.status).to eq(201) + end + + it 'fails to create a table' do + post '/tables', headers: { authorization: 'k0kubun', 'Content-Type': 'application/json' }, params: { + description: 'description', + database_id: 2, + }.to_json + expect(response.status).to eq(422) + end + + it 'fails to create a table (2)' do + post '/tables', headers: { authorization: 'k0kubun', 'Content-Type': 'application/json' }, params: { + name: 'some_invalid_name', + description: 'description', + database_id: 2, + }.to_json + expect(response.status).to eq(422) + end + end + + describe '#update' do + it 'returns a table' do + patch '/tables/1', headers: { authorization: 'k0kubun' }, params: { name: 'test' } + expect(response.status).to eq(200) + end + end + + describe '#destroy' do + it 'returns a table' do + delete '/tables/1', headers: { authorization: 'k0kubun' } + expect(response.status).to eq(200) + end + + it 'returns no content if specified' do + delete '/tables/1', headers: { authorization: 'k0kubun' }, params: { no_content: true } + expect(response.status).to eq(202) + end + end +end + +RSpec.xdescribe 'Images', type: :request do + describe '#payload' do + it 'returns a image payload' do + get '/images/1' + expect(response.status).to eq(200) + end + end + + describe '#index' do + it 'can return an object with an attribute of empty array' do + get '/images' + expect(response.status).to eq(200) + end + end + + describe '#upload' do + before do + png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjP + QBoAAAAASUVORK5CYII='.unpack1('m') + File.binwrite('test.png', png) + end + let(:image) { Rack::Test::UploadedFile.new('test.png', 'image/png') } + + it 'returns a image payload with upload' do + post '/images/upload', params: { image: image } + expect(response.status).to eq(200) + end + end + + describe '#upload_nested' do + before do + png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjP + QBoAAAAASUVORK5CYII='.unpack1('m') + File.binwrite('test.png', png) + end + let(:image) { Rack::Test::UploadedFile.new('test.png', 'image/png') } + + it 'returns a image payload with upload nested' do + post '/images/upload_nested', params: { nested_image: { image: image, caption: 'Some caption' } } + expect(response.status).to eq(200) + end + end + + describe '#upload_multiple' do + before do + png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjP + QBoAAAAASUVORK5CYII='.unpack1('m') + File.binwrite('test.png', png) + end + let(:image) { Rack::Test::UploadedFile.new('test.png', 'image/png') } + + it 'returns a image payload with upload multiple' do + post '/images/upload_multiple', params: { images: [image, image] } + expect(response.status).to eq(200) + end + end + + describe '#upload_multiple_nested' do + before do + png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjP + QBoAAAAASUVORK5CYII='.unpack1('m') + File.binwrite('test.png', png) + end + let(:image) { Rack::Test::UploadedFile.new('test.png', 'image/png') } + + it 'returns a image payload with upload multiple nested' do + post '/images/upload_multiple_nested', params: { images: [{ image: image }, { image: image }] } + expect(response.status).to eq(200) + end + end +end + +RSpec.xdescribe 'SecretKey securityScheme', + type: :request, + openapi: { security: [{ 'SecretApiKeyAuth' => [] }] } do + describe '#secret_items' do + it 'authorizes with secret key' do + get '/secret_items', + headers: { + 'Secret-Key' => '42', + } + expect(response.status).to eq(200) + end + end +end + +RSpec.xdescribe 'Extra routes', type: :request do + describe '#test_block' do + it 'returns the block content' do + get '/test_block' + expect(response.status).to eq(200) + end + end +end + +RSpec.xdescribe 'Engine test', type: :request do + describe 'engine routes' do + it 'returns some content from the engine' do + get '/my_engine/eng_route' + expect(response.status).to eq(200) + end + end +end + +RSpec.xdescribe 'Engine extra routes', type: :request do + describe '#test' do + it 'returns the block content' do + get '/my_engine/test' + expect(response.status).to eq(200) + end + end +end From d58641a09c08c04ce0eab69e2a52a5966a3a1eca Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Thu, 28 Mar 2024 18:47:16 +0500 Subject: [PATCH 07/17] Re-implement rails app in hanami version --- Gemfile | 1 + spec/apps/hanami/app/action.rb | 3 +- spec/apps/hanami/app/actions/images/index.rb | 22 +++ spec/apps/hanami/app/actions/images/show.rb | 23 +++ spec/apps/hanami/app/actions/images/upload.rb | 25 +++ .../app/actions/images/upload_multiple.rb | 25 +++ .../actions/images/upload_multiple_nested.rb | 23 +++ .../app/actions/images/upload_nested.rb | 23 +++ .../hanami/app/actions/secret_items/index.rb | 15 ++ spec/apps/hanami/app/actions/tables/create.rb | 21 +++ .../apps/hanami/app/actions/tables/destroy.rb | 17 ++ spec/apps/hanami/app/actions/tables/index.rb | 19 +++ spec/apps/hanami/app/actions/tables/show.rb | 15 ++ .../hanami/app/actions/tables/table_action.rb | 30 ++++ .../app/actions/tables/table_repository.rb | 51 ++++++ spec/apps/hanami/app/actions/tables/update.rb | 13 ++ spec/apps/hanami/app/actions/users/active.rb | 15 ++ spec/apps/hanami/app/actions/users/create.rb | 26 +++ spec/apps/hanami/app/actions/users/show.rb | 15 ++ .../hanami/app/actions/users/user_action.rb | 22 +++ .../app/actions/users/user_repository.rb | 32 ++++ .../hanami/app/templates/layouts/app.html.erb | 11 -- spec/apps/hanami/app/view.rb | 9 - spec/apps/hanami/app/views/helpers.rb | 10 -- spec/apps/hanami/config/app.rb | 6 +- spec/apps/hanami/config/routes.rb | 27 ++- spec/apps/hanami/config/settings.rb | 2 +- .../lib/{hanami => hanami_test}/types.rb | 2 +- spec/apps/hanami/slices/my_engine/action.rb | 7 + .../hanami/slices/my_engine/actions/.keep | 0 .../slices/my_engine/actions/eng/example.rb | 14 ++ spec/apps/hanami/test.png | Bin 0 -> 71 bytes spec/requests/hanami_spec.rb | 155 +++++++++--------- 33 files changed, 568 insertions(+), 111 deletions(-) create mode 100644 spec/apps/hanami/app/actions/images/index.rb create mode 100644 spec/apps/hanami/app/actions/images/show.rb create mode 100644 spec/apps/hanami/app/actions/images/upload.rb create mode 100644 spec/apps/hanami/app/actions/images/upload_multiple.rb create mode 100644 spec/apps/hanami/app/actions/images/upload_multiple_nested.rb create mode 100644 spec/apps/hanami/app/actions/images/upload_nested.rb create mode 100644 spec/apps/hanami/app/actions/secret_items/index.rb create mode 100644 spec/apps/hanami/app/actions/tables/create.rb create mode 100644 spec/apps/hanami/app/actions/tables/destroy.rb create mode 100644 spec/apps/hanami/app/actions/tables/index.rb create mode 100644 spec/apps/hanami/app/actions/tables/show.rb create mode 100644 spec/apps/hanami/app/actions/tables/table_action.rb create mode 100644 spec/apps/hanami/app/actions/tables/table_repository.rb create mode 100644 spec/apps/hanami/app/actions/tables/update.rb create mode 100644 spec/apps/hanami/app/actions/users/active.rb create mode 100644 spec/apps/hanami/app/actions/users/create.rb create mode 100644 spec/apps/hanami/app/actions/users/show.rb create mode 100644 spec/apps/hanami/app/actions/users/user_action.rb create mode 100644 spec/apps/hanami/app/actions/users/user_repository.rb delete mode 100644 spec/apps/hanami/app/templates/layouts/app.html.erb delete mode 100644 spec/apps/hanami/app/view.rb delete mode 100644 spec/apps/hanami/app/views/helpers.rb rename spec/apps/hanami/lib/{hanami => hanami_test}/types.rb (88%) create mode 100644 spec/apps/hanami/slices/my_engine/action.rb create mode 100644 spec/apps/hanami/slices/my_engine/actions/.keep create mode 100644 spec/apps/hanami/slices/my_engine/actions/eng/example.rb create mode 100644 spec/apps/hanami/test.png diff --git a/Gemfile b/Gemfile index bfc1ac1f..7ae28e59 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,7 @@ 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' gem 'roda' diff --git a/spec/apps/hanami/app/action.rb b/spec/apps/hanami/app/action.rb index 6e2fad60..99a6649e 100644 --- a/spec/apps/hanami/app/action.rb +++ b/spec/apps/hanami/app/action.rb @@ -3,7 +3,8 @@ require "hanami/action" -module Hanami +module HanamiTest class Action < Hanami::Action + class RecordNotFound < StandardError; end end end diff --git a/spec/apps/hanami/app/actions/images/index.rb b/spec/apps/hanami/app/actions/images/index.rb new file mode 100644 index 00000000..c4277966 --- /dev/null +++ b/spec/apps/hanami/app/actions/images/index.rb @@ -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 diff --git a/spec/apps/hanami/app/actions/images/show.rb b/spec/apps/hanami/app/actions/images/show.rb new file mode 100644 index 00000000..1817efa1 --- /dev/null +++ b/spec/apps/hanami/app/actions/images/show.rb @@ -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 diff --git a/spec/apps/hanami/app/actions/images/upload.rb b/spec/apps/hanami/app/actions/images/upload.rb new file mode 100644 index 00000000..106b8dfe --- /dev/null +++ b/spec/apps/hanami/app/actions/images/upload.rb @@ -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 diff --git a/spec/apps/hanami/app/actions/images/upload_multiple.rb b/spec/apps/hanami/app/actions/images/upload_multiple.rb new file mode 100644 index 00000000..41cc2c38 --- /dev/null +++ b/spec/apps/hanami/app/actions/images/upload_multiple.rb @@ -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 diff --git a/spec/apps/hanami/app/actions/images/upload_multiple_nested.rb b/spec/apps/hanami/app/actions/images/upload_multiple_nested.rb new file mode 100644 index 00000000..075cd3aa --- /dev/null +++ b/spec/apps/hanami/app/actions/images/upload_multiple_nested.rb @@ -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 diff --git a/spec/apps/hanami/app/actions/images/upload_nested.rb b/spec/apps/hanami/app/actions/images/upload_nested.rb new file mode 100644 index 00000000..43d66529 --- /dev/null +++ b/spec/apps/hanami/app/actions/images/upload_nested.rb @@ -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 diff --git a/spec/apps/hanami/app/actions/secret_items/index.rb b/spec/apps/hanami/app/actions/secret_items/index.rb new file mode 100644 index 00000000..b2166e35 --- /dev/null +++ b/spec/apps/hanami/app/actions/secret_items/index.rb @@ -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 diff --git a/spec/apps/hanami/app/actions/tables/create.rb b/spec/apps/hanami/app/actions/tables/create.rb new file mode 100644 index 00000000..a20939aa --- /dev/null +++ b/spec/apps/hanami/app/actions/tables/create.rb @@ -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 diff --git a/spec/apps/hanami/app/actions/tables/destroy.rb b/spec/apps/hanami/app/actions/tables/destroy.rb new file mode 100644 index 00000000..638d15ac --- /dev/null +++ b/spec/apps/hanami/app/actions/tables/destroy.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module HanamiTest + module Actions + module Tables + class Destroy < TableAction + def handle(request, response) + if request.params[:no_content] + response.status = 202 + else + response.body = find_table(request.params[:id]).to_json + end + end + end + end + end +end diff --git a/spec/apps/hanami/app/actions/tables/index.rb b/spec/apps/hanami/app/actions/tables/index.rb new file mode 100644 index 00000000..45a05e8c --- /dev/null +++ b/spec/apps/hanami/app/actions/tables/index.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module HanamiTest + module Actions + module Tables + class Index < TableAction + def handle(request, response) + response.headers['X-Cursor'] = 100 + + if request.params[:show_columns] + response.body = [find_table('42')].to_json + else + response.body = [find_table].to_json + end + end + end + end + end +end diff --git a/spec/apps/hanami/app/actions/tables/show.rb b/spec/apps/hanami/app/actions/tables/show.rb new file mode 100644 index 00000000..88bdb211 --- /dev/null +++ b/spec/apps/hanami/app/actions/tables/show.rb @@ -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 diff --git a/spec/apps/hanami/app/actions/tables/table_action.rb b/spec/apps/hanami/app/actions/tables/table_action.rb new file mode 100644 index 00000000..02824da9 --- /dev/null +++ b/spec/apps/hanami/app/actions/tables/table_action.rb @@ -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) + response.status = 404 + response.body = { message: 'not found' }.to_json + end + + def authenticate(request, _response) + if request.get_header('authorization') != APIKEY + halt 401, { message: 'Unauthorized' }.to_json + end + end + end + end + end +end diff --git a/spec/apps/hanami/app/actions/tables/table_repository.rb b/spec/apps/hanami/app/actions/tables/table_repository.rb new file mode 100644 index 00000000..e4bf7f54 --- /dev/null +++ b/spec/apps/hanami/app/actions/tables/table_repository.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +module HanamiTest + module Actions + module Tables + module TableRepository + class RecordNotFound < StandardError; end + + def find_table(id = nil) + time = Time.parse('2020-07-17 00:00:00') + case id + when '1', nil + { + id: 1, + name: 'access', + description: 'logs', + database: { + id: 2, + name: 'production', + }, + null_sample: nil, + storage_size: 12.3, + created_at: time.iso8601, + updated_at: time.iso8601, + } + when '42' + { + id: 42, + name: 'access', + description: 'logs', + database: { + id: 4242, + name: 'production', + }, + columns: [ + { name: 'id', column_type: 'integer' }, + { name: 'description', column_type: 'varchar' }, + ], + null_sample: nil, + storage_size: 12.3, + created_at: time.iso8601, + updated_at: time.iso8601, + } + else + raise RecordNotFound + end + end + end + end + end +end diff --git a/spec/apps/hanami/app/actions/tables/update.rb b/spec/apps/hanami/app/actions/tables/update.rb new file mode 100644 index 00000000..82c02083 --- /dev/null +++ b/spec/apps/hanami/app/actions/tables/update.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module HanamiTest + module Actions + module Tables + class Update < TableAction + def handle(request, response) + response.body = find_table(request.params[:id]).to_json + end + end + end + end +end diff --git a/spec/apps/hanami/app/actions/users/active.rb b/spec/apps/hanami/app/actions/users/active.rb new file mode 100644 index 00000000..70c8789f --- /dev/null +++ b/spec/apps/hanami/app/actions/users/active.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module HanamiTest + module Actions + module Users + class Active < UserAction + format :json + + def handle(request, response) + response.body = find_user(request.params[:id]).present?.to_json # present not exist in hanami + end + end + end + end +end diff --git a/spec/apps/hanami/app/actions/users/create.rb b/spec/apps/hanami/app/actions/users/create.rb new file mode 100644 index 00000000..189ce0ea --- /dev/null +++ b/spec/apps/hanami/app/actions/users/create.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module HanamiTest + module Actions + module Users + class Create < UserAction + format :json + + def handle(_request, response) + res = { + name: params[:name], + relations: { + avatar: { + url: params[:avatar_url] || 'https://example.com/avatar.png', + }, + pets: params[:pets] || [], + }, + } + + response.status = 201 + response.body = res.to_json + end + end + end + end +end diff --git a/spec/apps/hanami/app/actions/users/show.rb b/spec/apps/hanami/app/actions/users/show.rb new file mode 100644 index 00000000..bc136ecd --- /dev/null +++ b/spec/apps/hanami/app/actions/users/show.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module HanamiTest + module Actions + module Users + class Show < UserAction + format :json + + def handle(request, response) + response.body = find_user(request.params[:id]).to_json + end + end + end + end +end diff --git a/spec/apps/hanami/app/actions/users/user_action.rb b/spec/apps/hanami/app/actions/users/user_action.rb new file mode 100644 index 00000000..b757e707 --- /dev/null +++ b/spec/apps/hanami/app/actions/users/user_action.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module HanamiTest + module Actions + module Tables + class UserAction < HanamiTest::Action + include UserRepository + + handle_exception RecordNotFound => :handle_not_fount_error + + before :authenticate + + private + + def handle_not_fount_error(_request, response, _exception) + response.status = 404 + response.body = { message: 'not found' }.to_json + end + end + end + end +end diff --git a/spec/apps/hanami/app/actions/users/user_repository.rb b/spec/apps/hanami/app/actions/users/user_repository.rb new file mode 100644 index 00000000..24115a0d --- /dev/null +++ b/spec/apps/hanami/app/actions/users/user_repository.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true +module HanamiTest + module Actions + module Users + module UserRepository + class RecordNotFound < StandardError; end + + def find_user(id = nil) + case id + when '1', nil + { + name: 'John Doe', + relations: { + avatar: { + url: 'https://example.com/avatar.jpg', + }, + pets: [ + { name: 'doge', age: 8 }, + ], + }, + } + when '2' + { + } + else + raise RecordNotFound + end + end + end + end + end +end diff --git a/spec/apps/hanami/app/templates/layouts/app.html.erb b/spec/apps/hanami/app/templates/layouts/app.html.erb deleted file mode 100644 index 6ef771f3..00000000 --- a/spec/apps/hanami/app/templates/layouts/app.html.erb +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - Hanami - - - <%= yield %> - - diff --git a/spec/apps/hanami/app/view.rb b/spec/apps/hanami/app/view.rb deleted file mode 100644 index 59d79df6..00000000 --- a/spec/apps/hanami/app/view.rb +++ /dev/null @@ -1,9 +0,0 @@ -# auto_register: false -# frozen_string_literal: true - -require "hanami/view" - -module Hanami - class View < Hanami::View - end -end diff --git a/spec/apps/hanami/app/views/helpers.rb b/spec/apps/hanami/app/views/helpers.rb deleted file mode 100644 index b93d1efe..00000000 --- a/spec/apps/hanami/app/views/helpers.rb +++ /dev/null @@ -1,10 +0,0 @@ -# auto_register: false -# frozen_string_literal: true - -module Hanami - module Views - module Helpers - # Add your view helpers here - end - end -end diff --git a/spec/apps/hanami/config/app.rb b/spec/apps/hanami/config/app.rb index 7036eef3..590a267b 100644 --- a/spec/apps/hanami/config/app.rb +++ b/spec/apps/hanami/config/app.rb @@ -2,7 +2,9 @@ require "hanami" -module Hanami - class AppTest < Hanami::App +module HanamiTest + + class App < Hanami::App + config.middleware.use :body_parser, :json end end diff --git a/spec/apps/hanami/config/routes.rb b/spec/apps/hanami/config/routes.rb index 9caa1430..c55e9bf5 100644 --- a/spec/apps/hanami/config/routes.rb +++ b/spec/apps/hanami/config/routes.rb @@ -1,7 +1,32 @@ # frozen_string_literal: true -module Hanami +module HanamiTest class Routes < Hanami::Routes # Add your routes here. See https://guides.hanamirb.org/routing/overview/ for details. + get "/secret_items", to: "secret_items.index" + + get "/tables", to: "tables.index" + get "/tables/:id", to: "tables.show" + post "/tables", to: "tables.create" + patch "/tables/:id", to: "tables.update" + delete "/tables/:id", to: "tables.destroy" + + get "/images", to: "images.index" + get "/images/:id", to: "images.show" + post "/images/upload", to: "images.upload" + post "/images/upload_nested", to: "images.upload_nested" + post "/images/upload_multiple", to: "images.upload_multiple" + post "/images/upload_multiple_nested", to: "images.upload_multiple_nested" + + post "/users", to: "users.create" + get "/users/:id", to: "users.show" + get "/users/active", to: "users.active" + + get '/test_block', to: ->(_env) { [200, { 'Content-Type' => 'text/plain' }, ['A TEST']] } + + slice :my_engine, at: "/my_engine" do + get '/test', to: ->(_env) { [200, { 'Content-Type' => 'text/plain' }, ['ANOTHER TEST']] } + get "/eng/example", to: "eng.example" + end end end diff --git a/spec/apps/hanami/config/settings.rb b/spec/apps/hanami/config/settings.rb index 59e3e6d7..126f822f 100644 --- a/spec/apps/hanami/config/settings.rb +++ b/spec/apps/hanami/config/settings.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module Hanami +module HanamiTest class Settings < Hanami::Settings # Define your app settings here, for example: # diff --git a/spec/apps/hanami/lib/hanami/types.rb b/spec/apps/hanami/lib/hanami_test/types.rb similarity index 88% rename from spec/apps/hanami/lib/hanami/types.rb rename to spec/apps/hanami/lib/hanami_test/types.rb index 3961bb6b..a5c02023 100644 --- a/spec/apps/hanami/lib/hanami/types.rb +++ b/spec/apps/hanami/lib/hanami_test/types.rb @@ -2,7 +2,7 @@ require "dry/types" -module Hanami +module HanamiTest Types = Dry.Types module Types diff --git a/spec/apps/hanami/slices/my_engine/action.rb b/spec/apps/hanami/slices/my_engine/action.rb new file mode 100644 index 00000000..8b8a350a --- /dev/null +++ b/spec/apps/hanami/slices/my_engine/action.rb @@ -0,0 +1,7 @@ +# auto_register: false +# frozen_string_literal: true + +module MyEngine + class Action < HanamiTest::Action + end +end diff --git a/spec/apps/hanami/slices/my_engine/actions/.keep b/spec/apps/hanami/slices/my_engine/actions/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/apps/hanami/slices/my_engine/actions/eng/example.rb b/spec/apps/hanami/slices/my_engine/actions/eng/example.rb new file mode 100644 index 00000000..2ad29ef0 --- /dev/null +++ b/spec/apps/hanami/slices/my_engine/actions/eng/example.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module MyEngine + module Actions + module Eng + class Example < MyEngine::Action + def handle(_request, response) + response.headers['Content-Type'] = 'text/plain' + response.body = 'AN ENGINE TEST' + end + end + end + end +end diff --git a/spec/apps/hanami/test.png b/spec/apps/hanami/test.png new file mode 100644 index 0000000000000000000000000000000000000000..4579a0069bef1f610b761ce291af341f6cf87319 GIT binary patch literal 71 zcmeAS@N?(olHy`uVBq!ia0vp^93TuL7#^lP3 'k0kubun', 'X-Authorization-Token' => 'token' } + expect(last_response.status).to eq(200) end it 'with deep query parameters' do - get '/tables', params: { filter: { 'name' => 'Example Table' } }, headers: { authorization: 'k0kubun' } - expect(response.status).to eq(200) + get '/tables', { filter: { 'name' => 'Example Table' } }.to_json, { 'authorization' => 'k0kubun' } + expect(last_response.status).to eq(200) end it 'with different deep query parameters' do - get '/tables', params: { filter: { 'price' => 0 } }, headers: { authorization: 'k0kubun' } - expect(response.status).to eq(200) + get '/tables', { filter: { 'price' => 0 } }.to_json, { 'authorization' => 'k0kubun' } + expect(last_response.status).to eq(200) end end - it 'has a request spec which does not make any request' do - expect(request).to eq(nil) - end + # it 'has a request spec which does not make any request' do + # expect(last_request).to eq(nil) + # end + # Rack::Test::Error: + # No request yet. Request a page first. it 'does not return tables if unauthorized' do get '/tables' - expect(response.status).to eq(401) + expect(last_response.status).to eq(401) end end describe '#show' do it 'returns a table' do - get '/tables/1', headers: { authorization: 'k0kubun' } - expect(response.status).to eq(200) + get '/tables/1', nil, { 'authorization' => 'k0kubun' } + expect(last_response.status).to eq(200) end it 'does not return a table if unauthorized' do get '/tables/1' - expect(response.status).to eq(401) + expect(last_response.status).to eq(401) end it 'does not return a table if not found' do - get '/tables/2', headers: { authorization: 'k0kubun' } - expect(response.status).to eq(404) + get '/tables/2', nil, { 'authorization' => 'k0kubun' } + expect(last_response.status).to eq(404) end it 'does not return a table if not found (openapi: false)', openapi: false do - get '/tables/3', headers: { authorization: 'k0kubun' } - expect(response.status).to eq(404) + get '/tables/3', nil, { 'authorization' => 'k0kubun' } + expect(last_response.status).to eq(404) end end describe '#create' do it 'returns a table' do - post '/tables', headers: { authorization: 'k0kubun', 'Content-Type': 'application/json' }, params: { + post '/tables', { name: 'k0kubun', description: 'description', database_id: 2, - }.to_json - expect(response.status).to eq(201) + }.to_json, + { 'authorization' => 'k0kubun', 'CONTENT_TYPE' => 'application/json' } + expect(last_response.status).to eq(201) end it 'fails to create a table' do - post '/tables', headers: { authorization: 'k0kubun', 'Content-Type': 'application/json' }, params: { + post '/tables', { description: 'description', database_id: 2, - }.to_json - expect(response.status).to eq(422) + }.to_json, + { 'authorization' => 'k0kubun', 'CONTENT_TYPE' => 'application/json' } + expect(last_response.status).to eq(422) end it 'fails to create a table (2)' do - post '/tables', headers: { authorization: 'k0kubun', 'Content-Type': 'application/json' }, params: { + post '/tables', { name: 'some_invalid_name', description: 'description', database_id: 2, - }.to_json - expect(response.status).to eq(422) + }.to_json, + { 'authorization' => 'k0kubun', 'CONTENT_TYPE' => 'application/json' } + expect(last_response.status).to eq(422) end end describe '#update' do it 'returns a table' do - patch '/tables/1', headers: { authorization: 'k0kubun' }, params: { name: 'test' } - expect(response.status).to eq(200) + patch '/tables/1', { name: 'test' }, + { 'authorization' => 'k0kubun', 'CONTENT_TYPE' => 'application/x-www-form-urlencoded' } + expect(last_response.status).to eq(200) end end describe '#destroy' do it 'returns a table' do - delete '/tables/1', headers: { authorization: 'k0kubun' } - expect(response.status).to eq(200) + delete '/tables/1', nil, { 'authorization' => 'k0kubun' } + expect(last_response.status).to eq(200) end it 'returns no content if specified' do - delete '/tables/1', headers: { authorization: 'k0kubun' }, params: { no_content: true } - expect(response.status).to eq(202) + delete '/tables/1', { no_content: true }, + { 'authorization' => 'k0kubun', 'CONTENT_TYPE' => 'application/x-www-form-urlencoded' } + expect(last_response.status).to eq(202) end end end -RSpec.xdescribe 'Images', type: :request do +RSpec.describe 'Images', type: :request do describe '#payload' do it 'returns a image payload' do get '/images/1' - expect(response.status).to eq(200) + expect(last_response.status).to eq(200) end end describe '#index' do it 'can return an object with an attribute of empty array' do get '/images' - expect(response.status).to eq(200) + expect(last_response.status).to eq(200) end end @@ -173,8 +177,9 @@ def self.app_path(dir = Hanami.app_path(File.expand_path('../apps/hanami/', __di let(:image) { Rack::Test::UploadedFile.new('test.png', 'image/png') } it 'returns a image payload with upload' do - post '/images/upload', params: { image: image } - expect(response.status).to eq(200) + post '/images/upload', { 'image' => image } + # binding.irb + expect(last_response.status).to eq(200) end end @@ -187,8 +192,8 @@ def self.app_path(dir = Hanami.app_path(File.expand_path('../apps/hanami/', __di let(:image) { Rack::Test::UploadedFile.new('test.png', 'image/png') } it 'returns a image payload with upload nested' do - post '/images/upload_nested', params: { nested_image: { image: image, caption: 'Some caption' } } - expect(response.status).to eq(200) + post '/images/upload_nested', { nested_image: { image: image, caption: 'Some caption' } } + expect(last_response.status).to eq(200) end end @@ -201,8 +206,8 @@ def self.app_path(dir = Hanami.app_path(File.expand_path('../apps/hanami/', __di let(:image) { Rack::Test::UploadedFile.new('test.png', 'image/png') } it 'returns a image payload with upload multiple' do - post '/images/upload_multiple', params: { images: [image, image] } - expect(response.status).to eq(200) + post '/images/upload_multiple', { images: [image, image] } + expect(last_response.status).to eq(200) end end @@ -215,49 +220,49 @@ def self.app_path(dir = Hanami.app_path(File.expand_path('../apps/hanami/', __di let(:image) { Rack::Test::UploadedFile.new('test.png', 'image/png') } it 'returns a image payload with upload multiple nested' do - post '/images/upload_multiple_nested', params: { images: [{ image: image }, { image: image }] } - expect(response.status).to eq(200) + post '/images/upload_multiple_nested', { images: [{ image: image }, { image: image }] } + expect(last_response.status).to eq(200) end end end -RSpec.xdescribe 'SecretKey securityScheme', +RSpec.describe 'SecretKey securityScheme', type: :request, openapi: { security: [{ 'SecretApiKeyAuth' => [] }] } do describe '#secret_items' do it 'authorizes with secret key' do get '/secret_items', - headers: { + { 'Secret-Key' => '42', } - expect(response.status).to eq(200) + expect(last_response.status).to eq(200) end end end -RSpec.xdescribe 'Extra routes', type: :request do +RSpec.describe 'Extra routes', type: :request do describe '#test_block' do it 'returns the block content' do get '/test_block' - expect(response.status).to eq(200) + expect(last_response.status).to eq(200) end end end -RSpec.xdescribe 'Engine test', type: :request do +RSpec.describe 'Engine test', type: :request do describe 'engine routes' do it 'returns some content from the engine' do - get '/my_engine/eng_route' - expect(response.status).to eq(200) + get '/my_engine/test' + expect(last_response.status).to eq(200) end end end -RSpec.xdescribe 'Engine extra routes', type: :request do +RSpec.describe 'Engine extra routes', type: :request do describe '#test' do it 'returns the block content' do - get '/my_engine/test' - expect(response.status).to eq(200) + get '/my_engine/eng/example' + expect(last_response.status).to eq(200) end end end From 1e7dc00153871755b43b397c92637acfdce29b7b Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Thu, 28 Mar 2024 23:34:32 +0500 Subject: [PATCH 08/17] Don't use rails methods in schema_merger --- lib/rspec/openapi/schema_merger.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/rspec/openapi/schema_merger.rb b/lib/rspec/openapi/schema_merger.rb index 7861ada6..ecbc57ee 100644 --- a/lib/rspec/openapi/schema_merger.rb +++ b/lib/rspec/openapi/schema_merger.rb @@ -64,7 +64,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 @@ -74,6 +75,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) From ba09e53451ca4fca6efa46b7ab030a511bc23b10 Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Thu, 28 Mar 2024 23:35:30 +0500 Subject: [PATCH 09/17] Returns the correct content type in hanami --- spec/apps/hanami/app/actions/tables/destroy.rb | 1 + spec/apps/hanami/app/actions/tables/index.rb | 2 ++ spec/apps/hanami/app/actions/tables/table_action.rb | 8 ++++---- spec/apps/hanami/app/actions/tables/update.rb | 1 + 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/spec/apps/hanami/app/actions/tables/destroy.rb b/spec/apps/hanami/app/actions/tables/destroy.rb index 638d15ac..2d4d04bf 100644 --- a/spec/apps/hanami/app/actions/tables/destroy.rb +++ b/spec/apps/hanami/app/actions/tables/destroy.rb @@ -5,6 +5,7 @@ module Actions module Tables class Destroy < TableAction def handle(request, response) + response.format = :json if request.params[:no_content] response.status = 202 else diff --git a/spec/apps/hanami/app/actions/tables/index.rb b/spec/apps/hanami/app/actions/tables/index.rb index 45a05e8c..27e98cd6 100644 --- a/spec/apps/hanami/app/actions/tables/index.rb +++ b/spec/apps/hanami/app/actions/tables/index.rb @@ -8,8 +8,10 @@ def handle(request, response) response.headers['X-Cursor'] = 100 if request.params[:show_columns] + response.format = :json response.body = [find_table('42')].to_json else + response.format = :json response.body = [find_table].to_json end end diff --git a/spec/apps/hanami/app/actions/tables/table_action.rb b/spec/apps/hanami/app/actions/tables/table_action.rb index 02824da9..79e2b3cc 100644 --- a/spec/apps/hanami/app/actions/tables/table_action.rb +++ b/spec/apps/hanami/app/actions/tables/table_action.rb @@ -15,12 +15,12 @@ class TableAction < HanamiTest::Action private def handle_not_fount_error(_request, response, _exception) - response.status = 404 - response.body = { message: 'not found' }.to_json + halt 404, { message: 'not found' }.to_json end - def authenticate(request, _response) - if request.get_header('authorization') != APIKEY + def authenticate(request, response) + if request.get_header('AUTHORIZATION') != APIKEY + response.format = :json halt 401, { message: 'Unauthorized' }.to_json end end diff --git a/spec/apps/hanami/app/actions/tables/update.rb b/spec/apps/hanami/app/actions/tables/update.rb index 82c02083..2638b9a3 100644 --- a/spec/apps/hanami/app/actions/tables/update.rb +++ b/spec/apps/hanami/app/actions/tables/update.rb @@ -5,6 +5,7 @@ module Actions module Tables class Update < TableAction def handle(request, response) + response.format = :json response.body = find_table(request.params[:id]).to_json end end From 2c25ed3e15b2648bfa0f7588892672881682b89d Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Thu, 28 Mar 2024 23:36:00 +0500 Subject: [PATCH 10/17] Rack test doesn't do upcase for headers --- spec/requests/hanami_spec.rb | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/spec/requests/hanami_spec.rb b/spec/requests/hanami_spec.rb index ec06e3c5..c3ed4d60 100644 --- a/spec/requests/hanami_spec.rb +++ b/spec/requests/hanami_spec.rb @@ -50,18 +50,17 @@ describe '#index' do context 'returns a list of tables' do it 'with flat query parameters' do - get '/tables', { page: '1', per: '10' }.to_json, - { 'authorization' => 'k0kubun', 'X-Authorization-Token' => 'token' } + get '/tables', { page: '1', per: '10' }, { 'AUTHORIZATION' => 'k0kubun', 'X_AUTHORIZATION_TOKEN' => 'token' } expect(last_response.status).to eq(200) end it 'with deep query parameters' do - get '/tables', { filter: { 'name' => 'Example Table' } }.to_json, { 'authorization' => 'k0kubun' } + get '/tables', { filter: { 'name' => 'Example Table' } }, { 'AUTHORIZATION' => 'k0kubun' } expect(last_response.status).to eq(200) end it 'with different deep query parameters' do - get '/tables', { filter: { 'price' => 0 } }.to_json, { 'authorization' => 'k0kubun' } + get '/tables', { filter: { 'price' => 0 } }, { 'AUTHORIZATION' => 'k0kubun' } expect(last_response.status).to eq(200) end end @@ -80,7 +79,7 @@ describe '#show' do it 'returns a table' do - get '/tables/1', nil, { 'authorization' => 'k0kubun' } + get '/tables/1', nil, { 'AUTHORIZATION' => 'k0kubun' } expect(last_response.status).to eq(200) end @@ -90,12 +89,12 @@ end it 'does not return a table if not found' do - get '/tables/2', nil, { 'authorization' => 'k0kubun' } + get '/tables/2', nil, { 'AUTHORIZATION' => 'k0kubun' } expect(last_response.status).to eq(404) end it 'does not return a table if not found (openapi: false)', openapi: false do - get '/tables/3', nil, { 'authorization' => 'k0kubun' } + get '/tables/3', nil, { 'AUTHORIZATION' => 'k0kubun' } expect(last_response.status).to eq(404) end end @@ -107,7 +106,7 @@ description: 'description', database_id: 2, }.to_json, - { 'authorization' => 'k0kubun', 'CONTENT_TYPE' => 'application/json' } + { 'AUTHORIZATION' => 'k0kubun', 'CONTENT_TYPE' => 'application/json' } expect(last_response.status).to eq(201) end @@ -116,7 +115,7 @@ description: 'description', database_id: 2, }.to_json, - { 'authorization' => 'k0kubun', 'CONTENT_TYPE' => 'application/json' } + { 'AUTHORIZATION' => 'k0kubun', 'CONTENT_TYPE' => 'application/json' } expect(last_response.status).to eq(422) end @@ -126,7 +125,7 @@ description: 'description', database_id: 2, }.to_json, - { 'authorization' => 'k0kubun', 'CONTENT_TYPE' => 'application/json' } + { 'AUTHORIZATION' => 'k0kubun', 'CONTENT_TYPE' => 'application/json' } expect(last_response.status).to eq(422) end end @@ -134,20 +133,20 @@ describe '#update' do it 'returns a table' do patch '/tables/1', { name: 'test' }, - { 'authorization' => 'k0kubun', 'CONTENT_TYPE' => 'application/x-www-form-urlencoded' } + { 'AUTHORIZATION' => 'k0kubun', 'CONTENT_TYPE' => 'application/x-www-form-urlencoded' } expect(last_response.status).to eq(200) end end describe '#destroy' do it 'returns a table' do - delete '/tables/1', nil, { 'authorization' => 'k0kubun' } + delete '/tables/1', nil, { 'AUTHORIZATION' => 'k0kubun' } expect(last_response.status).to eq(200) end it 'returns no content if specified' do delete '/tables/1', { no_content: true }, - { 'authorization' => 'k0kubun', 'CONTENT_TYPE' => 'application/x-www-form-urlencoded' } + { 'AUTHORIZATION' => 'k0kubun', 'CONTENT_TYPE' => 'application/x-www-form-urlencoded' } expect(last_response.status).to eq(202) end end @@ -231,7 +230,7 @@ openapi: { security: [{ 'SecretApiKeyAuth' => [] }] } do describe '#secret_items' do it 'authorizes with secret key' do - get '/secret_items', + get '/secret_items', nil, { 'Secret-Key' => '42', } From bd2dbfbab73e00163273300cb808eb8101ef12af Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Thu, 28 Mar 2024 23:36:21 +0500 Subject: [PATCH 11/17] Initial openapi docs for hanami --- spec/apps/hanami/doc/openapi.json | 1009 +++++++++++++++++++++++++++++ spec/apps/hanami/doc/openapi.yaml | 666 +++++++++++++++++++ spec/rspec/hanami_spec.rb | 36 + 3 files changed, 1711 insertions(+) create mode 100644 spec/apps/hanami/doc/openapi.json create mode 100644 spec/apps/hanami/doc/openapi.yaml create mode 100644 spec/rspec/hanami_spec.rb diff --git a/spec/apps/hanami/doc/openapi.json b/spec/apps/hanami/doc/openapi.json new file mode 100644 index 00000000..f84c8506 --- /dev/null +++ b/spec/apps/hanami/doc/openapi.json @@ -0,0 +1,1009 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "OpenAPI Documentation", + "version": "1.0.0", + "description": "My beautiful hanami API", + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "servers": [ + { + "url": "http://localhost:3000" + } + ], + "paths": { + "/images": { + "get": { + "summary": "GET /images", + "responses": { + "200": { + "description": "can return an object with an attribute of empty array", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + } + } + }, + "required": [ + "name", + "tags" + ] + } + }, + "example": [ + { + "name": "file.png", + "tags": [ + + ] + } + ] + } + } + } + } + } + }, + "/images/1": { + "get": { + "summary": "GET /images/1", + "responses": { + "200": { + "description": "returns a image payload", + "content": { + "image/png": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + }, + "/images/upload": { + "post": { + "summary": "POST /images/upload", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "image": { + "type": "string", + "format": "binary" + } + }, + "required": [ + "image" + ] + }, + "example": { + "image": "test.png" + } + } + } + }, + "responses": { + "200": { + "description": "returns a image payload with upload", + "content": { + "image/png": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + }, + "/images/upload_multiple": { + "post": { + "summary": "POST /images/upload_multiple", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "images": { + "type": "array", + "items": { + "type": "string", + "format": "binary" + } + } + }, + "required": [ + "images" + ] + }, + "example": { + "images": [ + "test.png", + "test.png" + ] + } + } + } + }, + "responses": { + "200": { + "description": "returns a image payload with upload multiple", + "content": { + "image/png": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + }, + "/images/upload_multiple_nested": { + "post": { + "summary": "POST /images/upload_multiple_nested", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "images": { + "type": "array", + "items": { + "type": "object", + "properties": { + "image": { + "type": "string", + "format": "binary" + } + }, + "required": [ + "image" + ] + } + } + }, + "required": [ + "images" + ] + }, + "example": { + "images": [ + { + "image": "test.png" + }, + { + "image": "test.png" + } + ] + } + } + } + }, + "responses": { + "200": { + "description": "returns a image payload with upload multiple nested", + "content": { + "image/png": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + }, + "/images/upload_nested": { + "post": { + "summary": "POST /images/upload_nested", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "nested_image": { + "type": "object", + "properties": { + "image": { + "type": "string", + "format": "binary" + }, + "caption": { + "type": "string" + } + }, + "required": [ + "image", + "caption" + ] + } + }, + "required": [ + "nested_image" + ] + }, + "example": { + "nested_image": { + "image": "test.png", + "caption": "Some caption" + } + } + } + } + }, + "responses": { + "200": { + "description": "returns a image payload with upload nested", + "content": { + "image/png": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + }, + "/my_engine/eng/example": { + "get": { + "summary": "GET /my_engine/eng/example", + "responses": { + "200": { + "description": "returns the block content", + "content": { + "text/plain": { + "schema": { + "type": "string" + }, + "example": "AN ENGINE TEST" + } + } + } + } + } + }, + "/my_engine/test": { + "get": { + "summary": "GET /my_engine/test", + "responses": { + "200": { + "description": "returns some content from the engine", + "content": { + "text/plain": { + "schema": { + "type": "string" + }, + "example": "ANOTHER TEST" + } + } + } + } + } + }, + "/secret_items": { + "get": { + "summary": "GET /secret_items", + "security": [ + { + "SecretApiKeyAuth": [ + + ] + } + ], + "responses": { + "200": { + "description": "authorizes with secret key", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "items" + ] + }, + "example": { + "items": [ + "secrets" + ] + } + } + } + } + } + } + }, + "/tables": { + "get": { + "summary": "GET /tables", + "responses": { + "200": { + "description": "with different deep query parameters", + "headers": { + "X-Cursor": { + "schema": { + "type": "integer" + } + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "database": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "null_sample": { + "nullable": true + }, + "storage_size": { + "type": "number", + "format": "float" + }, + "created_at": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "description", + "database", + "null_sample", + "storage_size", + "created_at", + "updated_at" + ] + } + }, + "example": [ + { + "id": 1, + "name": "access", + "description": "logs", + "database": { + "id": 2, + "name": "production" + }, + "null_sample": null, + "storage_size": 12.3, + "created_at": "2020-07-17T00:00:00+00:00", + "updated_at": "2020-07-17T00:00:00+00:00" + } + ] + } + } + }, + "401": { + "description": "does not return tables if unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + }, + "required": [ + "message" + ] + }, + "example": { + "message": "Unauthorized" + } + } + } + } + }, + "parameters": [ + { + "name": "X-Authorization-Token", + "in": "header", + "required": true, + "schema": { + "type": "string" + }, + "example": "token" + }, + { + "name": "filter[name]", + "in": "query", + "required": false, + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "example": { + "name": "Example Table" + } + }, + { + "name": "filter[price]", + "in": "query", + "required": false, + "schema": { + "type": "object", + "properties": { + "price": { + "type": "string" + } + }, + "required": [ + "price" + ] + }, + "example": { + "price": "0" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer" + }, + "example": 1 + }, + { + "name": "per", + "in": "query", + "required": false, + "schema": { + "type": "integer" + }, + "example": 10 + } + ] + }, + "post": { + "summary": "POST /tables", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "database_id": { + "type": "integer" + } + }, + "required": [ + "name", + "description", + "database_id" + ] + }, + "example": { + "name": "k0kubun", + "description": "description", + "database_id": 2 + } + } + } + }, + "responses": { + "201": { + "description": "returns a table", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "database": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "null_sample": { + "nullable": true + }, + "storage_size": { + "type": "number", + "format": "float" + }, + "created_at": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "description", + "database", + "null_sample", + "storage_size", + "created_at", + "updated_at" + ] + }, + "example": { + "id": 1, + "name": "access", + "description": "logs", + "database": { + "id": 2, + "name": "production" + }, + "null_sample": null, + "storage_size": 12.3, + "created_at": "2020-07-17T00:00:00+00:00", + "updated_at": "2020-07-17T00:00:00+00:00" + } + } + } + }, + "422": { + "description": "fails to create a table (2)", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "error": { + "type": "string" + } + }, + "required": [ + "error" + ] + }, + "example": { + "error": "invalid name parameter" + } + } + } + } + } + } + }, + "/tables/1": { + "delete": { + "summary": "DELETE /tables/1", + "responses": { + "200": { + "description": "returns a table", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "database": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "null_sample": { + "nullable": true + }, + "storage_size": { + "type": "number", + "format": "float" + }, + "created_at": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "description", + "database", + "null_sample", + "storage_size", + "created_at", + "updated_at" + ] + }, + "example": { + "id": 1, + "name": "access", + "description": "logs", + "database": { + "id": 2, + "name": "production" + }, + "null_sample": null, + "storage_size": 12.3, + "created_at": "2020-07-17T00:00:00+00:00", + "updated_at": "2020-07-17T00:00:00+00:00" + } + } + } + }, + "202": { + "description": "returns no content if specified" + } + }, + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "type": "object", + "properties": { + "no_content": { + "type": "string" + } + }, + "required": [ + "no_content" + ] + }, + "example": { + "no_content": "true" + } + } + } + } + }, + "get": { + "summary": "GET /tables/1", + "responses": { + "200": { + "description": "returns a table", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "database": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "null_sample": { + "nullable": true + }, + "storage_size": { + "type": "number", + "format": "float" + }, + "created_at": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "description", + "database", + "null_sample", + "storage_size", + "created_at", + "updated_at" + ] + }, + "example": { + "id": 1, + "name": "access", + "description": "logs", + "database": { + "id": 2, + "name": "production" + }, + "null_sample": null, + "storage_size": 12.3, + "created_at": "2020-07-17T00:00:00+00:00", + "updated_at": "2020-07-17T00:00:00+00:00" + } + } + } + }, + "401": { + "description": "does not return a table if unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + }, + "required": [ + "message" + ] + }, + "example": { + "message": "Unauthorized" + } + } + } + } + } + }, + "patch": { + "summary": "PATCH /tables/1", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "example": { + "name": "test" + } + } + } + }, + "responses": { + "200": { + "description": "returns a table", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "database": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "null_sample": { + "nullable": true + }, + "storage_size": { + "type": "number", + "format": "float" + }, + "created_at": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "description", + "database", + "null_sample", + "storage_size", + "created_at", + "updated_at" + ] + }, + "example": { + "id": 1, + "name": "access", + "description": "logs", + "database": { + "id": 2, + "name": "production" + }, + "null_sample": null, + "storage_size": 12.3, + "created_at": "2020-07-17T00:00:00+00:00", + "updated_at": "2020-07-17T00:00:00+00:00" + } + } + } + } + } + } + }, + "/tables/2": { + "get": { + "summary": "GET /tables/2", + "responses": { + "404": { + "description": "does not return a table if not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + }, + "required": [ + "message" + ] + }, + "example": { + "message": "not found" + } + } + } + } + } + } + }, + "/test_block": { + "get": { + "summary": "GET /test_block", + "responses": { + "200": { + "description": "returns the block content", + "content": { + "text/plain": { + "schema": { + "type": "string" + }, + "example": "A TEST" + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "SecretApiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "Secret-Key" + } + } + } +} \ No newline at end of file diff --git a/spec/apps/hanami/doc/openapi.yaml b/spec/apps/hanami/doc/openapi.yaml new file mode 100644 index 00000000..29e03cac --- /dev/null +++ b/spec/apps/hanami/doc/openapi.yaml @@ -0,0 +1,666 @@ +# This file is auto-generated by rspec-openapi https://github.com/k0kubun/rspec-openapi +# +# When you write a spec in spec/requests, running the spec with `OPENAPI=1 rspec` will +# update this file automatically. You can also manually edit this file. +--- +openapi: 3.0.3 +info: + title: OpenAPI Documentation + version: 1.0.0 + description: My beautiful hanami API + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: +- url: http://localhost:3000 +paths: + "/images": + get: + summary: GET /images + responses: + '200': + description: can return an object with an attribute of empty array + content: + application/json: + schema: + type: array + items: + type: object + properties: + name: + type: string + tags: + type: array + items: {} + required: + - name + - tags + example: + - name: file.png + tags: [] + "/images/1": + get: + summary: GET /images/1 + responses: + '200': + description: returns a image payload + content: + image/png: + schema: + type: string + format: binary + "/images/upload": + post: + summary: POST /images/upload + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + image: + type: string + format: binary + required: + - image + example: + image: test.png + responses: + '200': + description: returns a image payload with upload + content: + image/png: + schema: + type: string + format: binary + "/images/upload_multiple": + post: + summary: POST /images/upload_multiple + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + images: + type: array + items: + type: string + format: binary + required: + - images + example: + images: + - test.png + - test.png + responses: + '200': + description: returns a image payload with upload multiple + content: + image/png: + schema: + type: string + format: binary + "/images/upload_multiple_nested": + post: + summary: POST /images/upload_multiple_nested + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + images: + type: array + items: + type: object + properties: + image: + type: string + format: binary + required: + - image + required: + - images + example: + images: + - image: test.png + - image: test.png + responses: + '200': + description: returns a image payload with upload multiple nested + content: + image/png: + schema: + type: string + format: binary + "/images/upload_nested": + post: + summary: POST /images/upload_nested + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + nested_image: + type: object + properties: + image: + type: string + format: binary + caption: + type: string + required: + - image + - caption + required: + - nested_image + example: + nested_image: + image: test.png + caption: Some caption + responses: + '200': + description: returns a image payload with upload nested + content: + image/png: + schema: + type: string + format: binary + "/my_engine/eng/example": + get: + summary: GET /my_engine/eng/example + responses: + '200': + description: returns the block content + content: + text/plain: + schema: + type: string + example: AN ENGINE TEST + "/my_engine/test": + get: + summary: GET /my_engine/test + responses: + '200': + description: returns some content from the engine + content: + text/plain: + schema: + type: string + example: ANOTHER TEST + "/secret_items": + get: + summary: GET /secret_items + security: + - SecretApiKeyAuth: [] + responses: + '200': + description: authorizes with secret key + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + type: string + required: + - items + example: + items: + - secrets + '401': + description: authorizes with secret key + content: + text/html: + schema: + type: string + example: '' + "/tables": + get: + summary: GET /tables + parameters: + - name: X-Authorization-Token + in: header + required: true + schema: + type: string + example: token + - name: filter[name] + in: query + required: false + schema: + type: object + properties: + name: + type: string + required: + - name + example: + name: Example Table + - name: filter[price] + in: query + required: false + schema: + type: object + properties: + price: + type: string + required: + - price + example: + price: '0' + - name: page + in: query + required: false + schema: + type: integer + example: 1 + - name: per + in: query + required: false + schema: + type: integer + example: 10 + responses: + '200': + description: with different deep query parameters + headers: + X-Cursor: + schema: + type: integer + content: + application/json: + schema: + type: array + items: + type: object + properties: + id: + type: integer + name: + type: string + description: + type: string + database: + type: object + properties: + id: + type: integer + name: + type: string + required: + - id + - name + null_sample: + nullable: true + storage_size: + type: number + format: float + created_at: + type: string + updated_at: + type: string + required: + - id + - name + - description + - database + - null_sample + - storage_size + - created_at + - updated_at + example: + - id: 1 + name: access + description: logs + database: + id: 2 + name: production + null_sample: + storage_size: 12.3 + created_at: '2020-07-17T00:00:00+00:00' + updated_at: '2020-07-17T00:00:00+00:00' + '401': + description: does not return tables if unauthorized + content: + application/json: + schema: + type: object + properties: + message: + type: string + required: + - message + example: + message: Unauthorized + post: + summary: POST /tables + responses: + '201': + description: returns a table + content: + application/json: + schema: + type: object + properties: + id: + type: integer + name: + type: string + description: + type: string + database: + type: object + properties: + id: + type: integer + name: + type: string + required: + - id + - name + null_sample: + nullable: true + storage_size: + type: number + format: float + created_at: + type: string + updated_at: + type: string + required: + - id + - name + - description + - database + - null_sample + - storage_size + - created_at + - updated_at + example: + id: 1 + name: access + description: logs + database: + id: 2 + name: production + null_sample: + storage_size: 12.3 + created_at: '2020-07-17T00:00:00+00:00' + updated_at: '2020-07-17T00:00:00+00:00' + '422': + description: fails to create a table (2) + content: + application/json: + schema: + type: object + properties: + error: + type: string + required: + - error + example: + error: invalid name parameter + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: + type: string + database_id: + type: integer + required: + - name + - description + - database_id + example: + name: k0kubun + description: description + database_id: 2 + "/tables/1": + delete: + summary: DELETE /tables/1 + responses: + '200': + description: returns a table + content: + application/json: + schema: + type: object + properties: + id: + type: integer + name: + type: string + description: + type: string + database: + type: object + properties: + id: + type: integer + name: + type: string + required: + - id + - name + null_sample: + nullable: true + storage_size: + type: number + format: float + created_at: + type: string + updated_at: + type: string + required: + - id + - name + - description + - database + - null_sample + - storage_size + - created_at + - updated_at + example: + id: 1 + name: access + description: logs + database: + id: 2 + name: production + null_sample: + storage_size: 12.3 + created_at: '2020-07-17T00:00:00+00:00' + updated_at: '2020-07-17T00:00:00+00:00' + '202': + description: returns no content if specified + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + no_content: + type: string + required: + - no_content + example: + no_content: 'true' + get: + summary: GET /tables/1 + responses: + '200': + description: returns a table + content: + application/json: + schema: + type: object + properties: + id: + type: integer + name: + type: string + description: + type: string + database: + type: object + properties: + id: + type: integer + name: + type: string + required: + - id + - name + null_sample: + nullable: true + storage_size: + type: number + format: float + created_at: + type: string + updated_at: + type: string + required: + - id + - name + - description + - database + - null_sample + - storage_size + - created_at + - updated_at + example: + id: 1 + name: access + description: logs + database: + id: 2 + name: production + null_sample: + storage_size: 12.3 + created_at: '2020-07-17T00:00:00+00:00' + updated_at: '2020-07-17T00:00:00+00:00' + '401': + description: does not return a table if unauthorized + content: + application/json: + schema: + type: object + properties: + message: + type: string + required: + - message + example: + message: Unauthorized + patch: + summary: PATCH /tables/1 + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + name: + type: string + required: + - name + example: + name: test + responses: + '200': + description: returns a table + content: + application/json: + schema: + type: object + properties: + id: + type: integer + name: + type: string + description: + type: string + database: + type: object + properties: + id: + type: integer + name: + type: string + required: + - id + - name + null_sample: + nullable: true + storage_size: + type: number + format: float + created_at: + type: string + updated_at: + type: string + required: + - id + - name + - description + - database + - null_sample + - storage_size + - created_at + - updated_at + example: + id: 1 + name: access + description: logs + database: + id: 2 + name: production + null_sample: + storage_size: 12.3 + created_at: '2020-07-17T00:00:00+00:00' + updated_at: '2020-07-17T00:00:00+00:00' + "/tables/2": + get: + summary: GET /tables/2 + responses: + '404': + description: does not return a table if not found + content: + application/json: + schema: + type: object + properties: + message: + type: string + required: + - message + example: + message: not found + "/test_block": + get: + summary: GET /test_block + responses: + '200': + description: returns the block content + content: + text/plain: + schema: + type: string + example: A TEST +components: + securitySchemes: + SecretApiKeyAuth: + type: apiKey + in: header + name: Secret-Key diff --git a/spec/rspec/hanami_spec.rb b/spec/rspec/hanami_spec.rb new file mode 100644 index 00000000..f1f3599f --- /dev/null +++ b/spec/rspec/hanami_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'yaml' +require 'json' +require 'pry' + +RSpec.describe 'hanami request spec' do + include SpecHelper + + describe 'yaml output' do + let(:openapi_path) do + File.expand_path('spec/apps/hanami/doc/openapi.yaml', repo_root) + end + + it 'generates the same spec/apps/hanami/doc/openapi.yaml' do + org_yaml = YAML.safe_load(File.read(openapi_path)) + rspec 'spec/requests/hanami_spec.rb', openapi: true, output: :yaml + new_yaml = YAML.safe_load(File.read(openapi_path)) + expect(new_yaml).to eq org_yaml + end + end + + describe 'json' do + let(:openapi_path) do + File.expand_path('spec/apps/hanami/doc/openapi.json', repo_root) + end + + it 'generates the same spec/apps/hanami/doc/openapi.json' do + org_json = JSON.parse(File.read(openapi_path)) + rspec 'spec/requests/hanami_spec.rb', openapi: true, output: :json + new_json = JSON.parse(File.read(openapi_path)) + expect(new_json).to eq org_json + end + end +end From 3edc089fc1ed400372ffad97c27a8bbb3ff4f55f Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Fri, 29 Mar 2024 00:06:24 +0500 Subject: [PATCH 12/17] Remove binding --- spec/requests/hanami_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/requests/hanami_spec.rb b/spec/requests/hanami_spec.rb index c3ed4d60..fc1a419a 100644 --- a/spec/requests/hanami_spec.rb +++ b/spec/requests/hanami_spec.rb @@ -177,7 +177,6 @@ it 'returns a image payload with upload' do post '/images/upload', { 'image' => image } - # binding.irb expect(last_response.status).to eq(200) end end From 90c1dffbb0a33312bd637b3479d16bf0126f6197 Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Fri, 29 Mar 2024 00:10:17 +0500 Subject: [PATCH 13/17] Remove empty space in rails openapi --- spec/apps/rails/doc/openapi.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/apps/rails/doc/openapi.yaml b/spec/apps/rails/doc/openapi.yaml index e73ce612..c1be9e5a 100644 --- a/spec/apps/rails/doc/openapi.yaml +++ b/spec/apps/rails/doc/openapi.yaml @@ -345,7 +345,7 @@ paths: database: id: 2 name: production - null_sample: + null_sample: storage_size: 12.3 created_at: '2020-07-17T00:00:00+00:00' updated_at: '2020-07-17T00:00:00+00:00' @@ -415,7 +415,7 @@ paths: database: id: 2 name: production - null_sample: + null_sample: storage_size: 12.3 created_at: '2020-07-17T00:00:00+00:00' updated_at: '2020-07-17T00:00:00+00:00' @@ -513,7 +513,7 @@ paths: database: id: 2 name: production - null_sample: + null_sample: storage_size: 12.3 created_at: '2020-07-17T00:00:00+00:00' updated_at: '2020-07-17T00:00:00+00:00' @@ -591,7 +591,7 @@ paths: database: id: 2 name: production - null_sample: + null_sample: storage_size: 12.3 created_at: '2020-07-17T00:00:00+00:00' updated_at: '2020-07-17T00:00:00+00:00' @@ -693,7 +693,7 @@ paths: database: id: 2 name: production - null_sample: + null_sample: storage_size: 12.3 created_at: '2020-07-17T00:00:00+00:00' updated_at: '2020-07-17T00:00:00+00:00' From 4007dd17c424e8cf6a9683bafd3b17d651741289 Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Sun, 31 Mar 2024 17:46:25 +0500 Subject: [PATCH 14/17] Adopt openapi deprecated function to hanami version --- lib/rspec/openapi/record_builder.rb | 5 ++++- .../hanami/app/actions/extensions/create.rb | 13 +++++++++++++ .../hanami/app/actions/extensions/index.rb | 13 +++++++++++++ spec/apps/hanami/config/routes.rb | 7 +++++++ spec/apps/hanami/doc/openapi.json | 8 +++----- spec/apps/hanami/doc/openapi.yaml | 3 +-- spec/requests/hanami_spec.rb | 18 +++++++++++++++++- 7 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 spec/apps/hanami/app/actions/extensions/create.rb create mode 100644 spec/apps/hanami/app/actions/extensions/index.rb diff --git a/lib/rspec/openapi/record_builder.rb b/lib/rspec/openapi/record_builder.rb index 81e11ef1..31e7adff 100644 --- a/lib/rspec/openapi/record_builder.rb +++ b/lib/rspec/openapi/record_builder.rb @@ -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) headers_arr << [header, header_value] if header_value end response_headers = RSpec::OpenAPI.response_headers.each_with_object([]) do |header, headers_arr| diff --git a/spec/apps/hanami/app/actions/extensions/create.rb b/spec/apps/hanami/app/actions/extensions/create.rb new file mode 100644 index 00000000..72f1ebcb --- /dev/null +++ b/spec/apps/hanami/app/actions/extensions/create.rb @@ -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 diff --git a/spec/apps/hanami/app/actions/extensions/index.rb b/spec/apps/hanami/app/actions/extensions/index.rb new file mode 100644 index 00000000..b1d6c533 --- /dev/null +++ b/spec/apps/hanami/app/actions/extensions/index.rb @@ -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 diff --git a/spec/apps/hanami/config/routes.rb b/spec/apps/hanami/config/routes.rb index c55e9bf5..a3caec99 100644 --- a/spec/apps/hanami/config/routes.rb +++ b/spec/apps/hanami/config/routes.rb @@ -28,5 +28,12 @@ class Routes < Hanami::Routes get '/test', to: ->(_env) { [200, { 'Content-Type' => 'text/plain' }, ['ANOTHER TEST']] } get "/eng/example", to: "eng.example" end + + scope "admin" do + scope "masters" do + get "/extensions", to: "extensions.index" + post "/extensions", to: "extensions.create" + end + end end end diff --git a/spec/apps/hanami/doc/openapi.json b/spec/apps/hanami/doc/openapi.json index f84c8506..9d628946 100644 --- a/spec/apps/hanami/doc/openapi.json +++ b/spec/apps/hanami/doc/openapi.json @@ -742,10 +742,7 @@ "no_content": { "type": "string" } - }, - "required": [ - "no_content" - ] + } }, "example": { "no_content": "true" @@ -993,7 +990,8 @@ } } } - } + }, + "deprecated": true } } }, diff --git a/spec/apps/hanami/doc/openapi.yaml b/spec/apps/hanami/doc/openapi.yaml index 29e03cac..f26243ac 100644 --- a/spec/apps/hanami/doc/openapi.yaml +++ b/spec/apps/hanami/doc/openapi.yaml @@ -491,8 +491,6 @@ paths: properties: no_content: type: string - required: - - no_content example: no_content: 'true' get: @@ -658,6 +656,7 @@ paths: schema: type: string example: A TEST + deprecated: true components: securitySchemes: SecretApiKeyAuth: diff --git a/spec/requests/hanami_spec.rb b/spec/requests/hanami_spec.rb index fc1a419a..34c999ab 100644 --- a/spec/requests/hanami_spec.rb +++ b/spec/requests/hanami_spec.rb @@ -14,6 +14,7 @@ RSpec::OpenAPI.request_headers = %w[X-Authorization-Token Secret-Key] RSpec::OpenAPI.response_headers = %w[X-Cursor] RSpec::OpenAPI.path = File.expand_path("../apps/hanami/doc/openapi.#{ENV.fetch('OPENAPI_OUTPUT', nil)}", __dir__) +RSpec::OpenAPI.ignored_paths = ['/admin/masters/extensions'] RSpec::OpenAPI.comment = <<~COMMENT This file is auto-generated by rspec-openapi https://github.com/k0kubun/rspec-openapi @@ -51,6 +52,7 @@ context 'returns a list of tables' do it 'with flat query parameters' do get '/tables', { page: '1', per: '10' }, { 'AUTHORIZATION' => 'k0kubun', 'X_AUTHORIZATION_TOKEN' => 'token' } + # binding.irb expect(last_response.status).to eq(200) end @@ -239,7 +241,7 @@ end RSpec.describe 'Extra routes', type: :request do - describe '#test_block' do + describe '#test_block', openapi: { deprecated: true } do it 'returns the block content' do get '/test_block' expect(last_response.status).to eq(200) @@ -264,3 +266,17 @@ end end end + +RSpec.describe 'Namespace test', type: :request do + describe '/admin/masters/extensions' do + it 'returns some content' do + get '/admin/masters/extensions' + expect(last_response.status).to eq(200) + end + + it 'creates a content' do + post '/admin/masters/extensions' + expect(last_response.status).to eq(200) + end + end +end \ No newline at end of file From d220ef828521fb731d1ab84cdf0ca3fbb9344077 Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Sun, 31 Mar 2024 18:24:24 +0500 Subject: [PATCH 15/17] Run rubocop --- spec/apps/hanami/app/actions/images/show.rb | 4 ++-- spec/apps/hanami/app/actions/images/upload.rb | 4 ++-- spec/apps/hanami/app/actions/images/upload_multiple.rb | 4 ++-- spec/apps/hanami/app/actions/images/upload_multiple_nested.rb | 4 ++-- spec/apps/hanami/app/actions/images/upload_nested.rb | 4 ++-- spec/apps/hanami/app/actions/users/user_repository.rb | 4 ++-- spec/apps/hanami/config/app.rb | 1 - spec/apps/rails/app/controllers/users_controller.rb | 3 +-- spec/apps/rails/config/environments/production.rb | 2 +- spec/apps/rails/config/routes.rb | 2 +- spec/requests/hanami_spec.rb | 2 +- 11 files changed, 16 insertions(+), 18 deletions(-) diff --git a/spec/apps/hanami/app/actions/images/show.rb b/spec/apps/hanami/app/actions/images/show.rb index 1817efa1..cf84c633 100644 --- a/spec/apps/hanami/app/actions/images/show.rb +++ b/spec/apps/hanami/app/actions/images/show.rb @@ -5,8 +5,8 @@ module Actions module Images class Show < HanamiTest::Action def handle(_request, response) - png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='. - unpack('m').first + png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII=' + .unpack('m').first response.format = :png response.body = png diff --git a/spec/apps/hanami/app/actions/images/upload.rb b/spec/apps/hanami/app/actions/images/upload.rb index 106b8dfe..c2d44273 100644 --- a/spec/apps/hanami/app/actions/images/upload.rb +++ b/spec/apps/hanami/app/actions/images/upload.rb @@ -7,8 +7,8 @@ class Upload < HanamiTest::Action # format :form def handle(_request, response) - png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='. - unpack('m').first + png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII=' + .unpack('m').first response.format = :png response.body = png diff --git a/spec/apps/hanami/app/actions/images/upload_multiple.rb b/spec/apps/hanami/app/actions/images/upload_multiple.rb index 41cc2c38..f90128f5 100644 --- a/spec/apps/hanami/app/actions/images/upload_multiple.rb +++ b/spec/apps/hanami/app/actions/images/upload_multiple.rb @@ -7,8 +7,8 @@ class UploadMultiple < HanamiTest::Action # format :multipart def handle(_request, response) - png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='. - unpack('m').first + png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII=' + .unpack('m').first response.format = :png response.body = png diff --git a/spec/apps/hanami/app/actions/images/upload_multiple_nested.rb b/spec/apps/hanami/app/actions/images/upload_multiple_nested.rb index 075cd3aa..84a41e55 100644 --- a/spec/apps/hanami/app/actions/images/upload_multiple_nested.rb +++ b/spec/apps/hanami/app/actions/images/upload_multiple_nested.rb @@ -5,8 +5,8 @@ module Actions module Images class UploadMultipleNested < HanamiTest::Action def handle(_request, response) - png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='. - unpack('m').first + png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII=' + .unpack('m').first response.format = :png response.body = png diff --git a/spec/apps/hanami/app/actions/images/upload_nested.rb b/spec/apps/hanami/app/actions/images/upload_nested.rb index 43d66529..7acac820 100644 --- a/spec/apps/hanami/app/actions/images/upload_nested.rb +++ b/spec/apps/hanami/app/actions/images/upload_nested.rb @@ -5,8 +5,8 @@ module Actions module Images class UploadNested < HanamiTest::Action def handle(_request, response) - png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII='. - unpack('m').first + png = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAADklEQVQIW2P4DwUMlDEA98A/wTjPQBoAAAAASUVORK5CYII=' + .unpack('m').first response.format = :png response.body = png diff --git a/spec/apps/hanami/app/actions/users/user_repository.rb b/spec/apps/hanami/app/actions/users/user_repository.rb index 24115a0d..f2228a5b 100644 --- a/spec/apps/hanami/app/actions/users/user_repository.rb +++ b/spec/apps/hanami/app/actions/users/user_repository.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module HanamiTest module Actions module Users @@ -20,8 +21,7 @@ def find_user(id = nil) }, } when '2' - { - } + {} else raise RecordNotFound end diff --git a/spec/apps/hanami/config/app.rb b/spec/apps/hanami/config/app.rb index 590a267b..d8bbb296 100644 --- a/spec/apps/hanami/config/app.rb +++ b/spec/apps/hanami/config/app.rb @@ -3,7 +3,6 @@ require "hanami" module HanamiTest - class App < Hanami::App config.middleware.use :body_parser, :json end diff --git a/spec/apps/rails/app/controllers/users_controller.rb b/spec/apps/rails/app/controllers/users_controller.rb index 2a66a2a2..e25e4e1d 100644 --- a/spec/apps/rails/app/controllers/users_controller.rb +++ b/spec/apps/rails/app/controllers/users_controller.rb @@ -37,8 +37,7 @@ def find_user(id = nil) }, } when '2' - { - } + {} else raise NotFoundError end diff --git a/spec/apps/rails/config/environments/production.rb b/spec/apps/rails/config/environments/production.rb index 37a5e950..0a9905f5 100644 --- a/spec/apps/rails/config/environments/production.rb +++ b/spec/apps/rails/config/environments/production.rb @@ -51,7 +51,7 @@ config.log_level = :debug # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] + config.log_tags = [:request_id] # Use a different cache store in production. # config.cache_store = :mem_cache_store diff --git a/spec/apps/rails/config/routes.rb b/spec/apps/rails/config/routes.rb index 224d5ddb..889043dd 100644 --- a/spec/apps/rails/config/routes.rb +++ b/spec/apps/rails/config/routes.rb @@ -15,7 +15,7 @@ post 'upload_multiple_nested' end end - resources :users, only: [:show, :create] do + resources :users, only: [:show, :create] do get 'active' end diff --git a/spec/requests/hanami_spec.rb b/spec/requests/hanami_spec.rb index 34c999ab..d84d5d51 100644 --- a/spec/requests/hanami_spec.rb +++ b/spec/requests/hanami_spec.rb @@ -279,4 +279,4 @@ expect(last_response.status).to eq(200) end end -end \ No newline at end of file +end From 6ccdbad7603fd2f2ed3a3159a5ec463ed75ef38d Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Sun, 31 Mar 2024 18:32:44 +0500 Subject: [PATCH 16/17] Apply github rubocop bot offences --- Gemfile | 2 +- spec/apps/hanami/app/action.rb | 8 ++-- .../hanami/app/actions/extensions/create.rb | 2 +- .../hanami/app/actions/extensions/index.rb | 2 +- spec/apps/hanami/app/actions/images/index.rb | 4 +- spec/apps/hanami/app/actions/images/show.rb | 2 +- spec/apps/hanami/app/actions/images/upload.rb | 2 +- .../app/actions/images/upload_multiple.rb | 2 +- .../actions/images/upload_multiple_nested.rb | 2 +- .../app/actions/images/upload_nested.rb | 2 +- spec/apps/hanami/app/actions/tables/index.rb | 14 +++---- .../hanami/app/actions/tables/table_action.rb | 10 ++--- spec/apps/hanami/config.ru | 2 +- spec/apps/hanami/config/app.rb | 2 +- spec/apps/hanami/config/puma.rb | 10 ++--- spec/apps/hanami/config/routes.rb | 42 +++++++++---------- 16 files changed, 53 insertions(+), 55 deletions(-) diff --git a/Gemfile b/Gemfile index 7ae28e59..ae751823 100644 --- a/Gemfile +++ b/Gemfile @@ -8,8 +8,8 @@ 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' +gem 'hanami-router', ENV['HANAMI_VERSION'] || '2.1.0' gem 'roda' diff --git a/spec/apps/hanami/app/action.rb b/spec/apps/hanami/app/action.rb index 99a6649e..ec957c67 100644 --- a/spec/apps/hanami/app/action.rb +++ b/spec/apps/hanami/app/action.rb @@ -1,10 +1,8 @@ # auto_register: false # frozen_string_literal: true -require "hanami/action" +require 'hanami/action' -module HanamiTest - class Action < Hanami::Action - class RecordNotFound < StandardError; end - end +class HanamiTest::Action < Hanami::Action + class RecordNotFound < StandardError; end end diff --git a/spec/apps/hanami/app/actions/extensions/create.rb b/spec/apps/hanami/app/actions/extensions/create.rb index 72f1ebcb..d74aed17 100644 --- a/spec/apps/hanami/app/actions/extensions/create.rb +++ b/spec/apps/hanami/app/actions/extensions/create.rb @@ -4,7 +4,7 @@ module HanamiTest module Actions module Extensions class Create < HanamiTest::Action - def handle(request, response) + def handle(_request, response) response.body = [{ name: 'my-ext-1' }].to_json end end diff --git a/spec/apps/hanami/app/actions/extensions/index.rb b/spec/apps/hanami/app/actions/extensions/index.rb index b1d6c533..be1a4a0b 100644 --- a/spec/apps/hanami/app/actions/extensions/index.rb +++ b/spec/apps/hanami/app/actions/extensions/index.rb @@ -4,7 +4,7 @@ module HanamiTest module Actions module Extensions class Index < HanamiTest::Action - def handle(request, response) + def handle(_request, response) response.body = { message: 'created' }.to_json end end diff --git a/spec/apps/hanami/app/actions/images/index.rb b/spec/apps/hanami/app/actions/images/index.rb index c4277966..0e498e1d 100644 --- a/spec/apps/hanami/app/actions/images/index.rb +++ b/spec/apps/hanami/app/actions/images/index.rb @@ -9,8 +9,8 @@ class Index < HanamiTest::Action def handle(_request, response) list = [ { - 'name': 'file.png', - 'tags': [], # Keep this empty to check empty array is accepted + name: 'file.png', + tags: [], # Keep this empty to check empty array is accepted }, ] diff --git a/spec/apps/hanami/app/actions/images/show.rb b/spec/apps/hanami/app/actions/images/show.rb index cf84c633..3e1f13eb 100644 --- a/spec/apps/hanami/app/actions/images/show.rb +++ b/spec/apps/hanami/app/actions/images/show.rb @@ -13,7 +13,7 @@ def handle(_request, response) response.headers.merge!( { 'Content-Type' => 'image/png', - 'Content-Disposition' => 'inline' + 'Content-Disposition' => 'inline', } ) end diff --git a/spec/apps/hanami/app/actions/images/upload.rb b/spec/apps/hanami/app/actions/images/upload.rb index c2d44273..9b04f68f 100644 --- a/spec/apps/hanami/app/actions/images/upload.rb +++ b/spec/apps/hanami/app/actions/images/upload.rb @@ -15,7 +15,7 @@ def handle(_request, response) response.headers.merge!( { 'Content-Type' => 'image/png', - 'Content-Disposition' => 'inline' + 'Content-Disposition' => 'inline', } ) end diff --git a/spec/apps/hanami/app/actions/images/upload_multiple.rb b/spec/apps/hanami/app/actions/images/upload_multiple.rb index f90128f5..f468a843 100644 --- a/spec/apps/hanami/app/actions/images/upload_multiple.rb +++ b/spec/apps/hanami/app/actions/images/upload_multiple.rb @@ -15,7 +15,7 @@ def handle(_request, response) response.headers.merge!( { 'Content-Type' => 'image/png', - 'Content-Disposition' => 'inline' + 'Content-Disposition' => 'inline', } ) end diff --git a/spec/apps/hanami/app/actions/images/upload_multiple_nested.rb b/spec/apps/hanami/app/actions/images/upload_multiple_nested.rb index 84a41e55..365f7709 100644 --- a/spec/apps/hanami/app/actions/images/upload_multiple_nested.rb +++ b/spec/apps/hanami/app/actions/images/upload_multiple_nested.rb @@ -13,7 +13,7 @@ def handle(_request, response) response.headers.merge!( { 'Content-Type' => 'image/png', - 'Content-Disposition' => 'inline' + 'Content-Disposition' => 'inline', } ) end diff --git a/spec/apps/hanami/app/actions/images/upload_nested.rb b/spec/apps/hanami/app/actions/images/upload_nested.rb index 7acac820..480f0bbf 100644 --- a/spec/apps/hanami/app/actions/images/upload_nested.rb +++ b/spec/apps/hanami/app/actions/images/upload_nested.rb @@ -13,7 +13,7 @@ def handle(_request, response) response.headers.merge!( { 'Content-Type' => 'image/png', - 'Content-Disposition' => 'inline' + 'Content-Disposition' => 'inline', } ) end diff --git a/spec/apps/hanami/app/actions/tables/index.rb b/spec/apps/hanami/app/actions/tables/index.rb index 27e98cd6..65fe6f70 100644 --- a/spec/apps/hanami/app/actions/tables/index.rb +++ b/spec/apps/hanami/app/actions/tables/index.rb @@ -7,13 +7,13 @@ class Index < TableAction def handle(request, response) response.headers['X-Cursor'] = 100 - if request.params[:show_columns] - response.format = :json - response.body = [find_table('42')].to_json - else - response.format = :json - response.body = [find_table].to_json - end + response.format = :json + + response.body = if request.params[:show_columns] + [find_table('42')].to_json + else + [find_table].to_json + end end end end diff --git a/spec/apps/hanami/app/actions/tables/table_action.rb b/spec/apps/hanami/app/actions/tables/table_action.rb index 79e2b3cc..ed97748a 100644 --- a/spec/apps/hanami/app/actions/tables/table_action.rb +++ b/spec/apps/hanami/app/actions/tables/table_action.rb @@ -14,15 +14,15 @@ class TableAction < HanamiTest::Action private - def handle_not_fount_error(_request, response, _exception) + def handle_not_fount_error(_request, _response, _exception) halt 404, { message: 'not found' }.to_json end def authenticate(request, response) - if request.get_header('AUTHORIZATION') != APIKEY - response.format = :json - halt 401, { message: 'Unauthorized' }.to_json - end + return unless request.get_header('AUTHORIZATION') != APIKEY + + response.format = :json + halt 401, { message: 'Unauthorized' }.to_json end end end diff --git a/spec/apps/hanami/config.ru b/spec/apps/hanami/config.ru index 879c0858..83dc7857 100644 --- a/spec/apps/hanami/config.ru +++ b/spec/apps/hanami/config.ru @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "hanami/boot" +require 'hanami/boot' run Hanami.app diff --git a/spec/apps/hanami/config/app.rb b/spec/apps/hanami/config/app.rb index d8bbb296..102b93c9 100644 --- a/spec/apps/hanami/config/app.rb +++ b/spec/apps/hanami/config/app.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "hanami" +require 'hanami' module HanamiTest class App < Hanami::App diff --git a/spec/apps/hanami/config/puma.rb b/spec/apps/hanami/config/puma.rb index 1866af83..df893721 100644 --- a/spec/apps/hanami/config/puma.rb +++ b/spec/apps/hanami/config/puma.rb @@ -3,16 +3,16 @@ # # Environment and port # -port ENV.fetch("HANAMI_PORT", 2300) -environment ENV.fetch("HANAMI_ENV", "development") +port ENV.fetch('HANAMI_PORT', 2300) +environment ENV.fetch('HANAMI_ENV', 'development') # # Threads within each Puma/Ruby process (aka worker) # # Configure the minimum and maximum number of threads to use to answer requests. -max_threads_count = ENV.fetch("HANAMI_MAX_THREADS", 5) -min_threads_count = ENV.fetch("HANAMI_MIN_THREADS") { max_threads_count } +max_threads_count = ENV.fetch('HANAMI_MAX_THREADS', 5) +min_threads_count = ENV.fetch('HANAMI_MIN_THREADS') { max_threads_count } threads min_threads_count, max_threads_count @@ -20,7 +20,7 @@ # Workers (aka Puma/Ruby processes) # -puma_concurrency = Integer(ENV.fetch("HANAMI_WEB_CONCURRENCY", 0)) +puma_concurrency = Integer(ENV.fetch('HANAMI_WEB_CONCURRENCY', 0)) puma_cluster_mode = puma_concurrency > 1 # How many worker (Puma/Ruby) processes to run. diff --git a/spec/apps/hanami/config/routes.rb b/spec/apps/hanami/config/routes.rb index a3caec99..6d6caf52 100644 --- a/spec/apps/hanami/config/routes.rb +++ b/spec/apps/hanami/config/routes.rb @@ -3,36 +3,36 @@ module HanamiTest class Routes < Hanami::Routes # Add your routes here. See https://guides.hanamirb.org/routing/overview/ for details. - get "/secret_items", to: "secret_items.index" + get '/secret_items', to: 'secret_items.index' - get "/tables", to: "tables.index" - get "/tables/:id", to: "tables.show" - post "/tables", to: "tables.create" - patch "/tables/:id", to: "tables.update" - delete "/tables/:id", to: "tables.destroy" + get '/tables', to: 'tables.index' + get '/tables/:id', to: 'tables.show' + post '/tables', to: 'tables.create' + patch '/tables/:id', to: 'tables.update' + delete '/tables/:id', to: 'tables.destroy' - get "/images", to: "images.index" - get "/images/:id", to: "images.show" - post "/images/upload", to: "images.upload" - post "/images/upload_nested", to: "images.upload_nested" - post "/images/upload_multiple", to: "images.upload_multiple" - post "/images/upload_multiple_nested", to: "images.upload_multiple_nested" + get '/images', to: 'images.index' + get '/images/:id', to: 'images.show' + post '/images/upload', to: 'images.upload' + post '/images/upload_nested', to: 'images.upload_nested' + post '/images/upload_multiple', to: 'images.upload_multiple' + post '/images/upload_multiple_nested', to: 'images.upload_multiple_nested' - post "/users", to: "users.create" - get "/users/:id", to: "users.show" - get "/users/active", to: "users.active" + post '/users', to: 'users.create' + get '/users/:id', to: 'users.show' + get '/users/active', to: 'users.active' get '/test_block', to: ->(_env) { [200, { 'Content-Type' => 'text/plain' }, ['A TEST']] } - slice :my_engine, at: "/my_engine" do + slice :my_engine, at: '/my_engine' do get '/test', to: ->(_env) { [200, { 'Content-Type' => 'text/plain' }, ['ANOTHER TEST']] } - get "/eng/example", to: "eng.example" + get '/eng/example', to: 'eng.example' end - scope "admin" do - scope "masters" do - get "/extensions", to: "extensions.index" - post "/extensions", to: "extensions.create" + scope 'admin' do + scope 'masters' do + get '/extensions', to: 'extensions.index' + post '/extensions', to: 'extensions.create' end end end From 8b2579f0bd6143bb240c43febdefee860ce6b4ae Mon Sep 17 00:00:00 2001 From: Aleksei <9ceb2990-3744-4629-82f3-19bc5c80b3a2@mackevich.addymail.com> Date: Mon, 1 Apr 2024 18:53:03 +0500 Subject: [PATCH 17/17] Skip hanami on ruby 2 --- .rubocop.yml | 2 +- Gemfile | 8 +++++--- spec/requests/hanami_spec.rb | 2 ++ spec/rspec/hanami_spec.rb | 2 ++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index f88aedf2..b17a921b 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -5,7 +5,7 @@ AllCops: SuggestExtensions: false TargetRubyVersion: 2.7 Exclude: - - 'spec/rails/**/*' + - 'spec/apps/**/*' - 'vendor/**/*' Style/TrailingCommaInHashLiteral: diff --git a/Gemfile b/Gemfile index ae751823..4fad7e7f 100644 --- a/Gemfile +++ b/Gemfile @@ -7,9 +7,11 @@ gemspec gem 'rails', ENV['RAILS_VERSION'] || '6.0.3.7' -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' +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' diff --git a/spec/requests/hanami_spec.rb b/spec/requests/hanami_spec.rb index d84d5d51..1dadb4b4 100644 --- a/spec/requests/hanami_spec.rb +++ b/spec/requests/hanami_spec.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +return unless Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0') + ENV['TZ'] ||= 'UTC' ENV['HANAMI_ENV'] ||= 'test' ENV['OPENAPI_OUTPUT'] ||= 'yaml' diff --git a/spec/rspec/hanami_spec.rb b/spec/rspec/hanami_spec.rb index f1f3599f..57cdbd4e 100644 --- a/spec/rspec/hanami_spec.rb +++ b/spec/rspec/hanami_spec.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +return unless Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0') + require 'spec_helper' require 'yaml' require 'json'