From ae7ce71335c890285cc58b29061dba5498431b80 Mon Sep 17 00:00:00 2001 From: Patryk Ptasinski Date: Wed, 10 Apr 2024 17:05:56 +0200 Subject: [PATCH 1/2] Add RSpec::OpenAPI.post_process_hook --- README.md | 7 +++++++ lib/rspec/openapi.rb | 4 +++- lib/rspec/openapi/result_recorder.rb | 3 +++ spec/apps/rails/doc/openapi.json | 3 ++- spec/apps/rails/doc/openapi.yaml | 1 + spec/integration_tests/rails_test.rb | 4 ++++ 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9eb956a..4d89b49 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,13 @@ RSpec::OpenAPI.ignored_path_params = %i[controller action format] # In that case, you can specify the paths to ignore. # String or Regexp is acceptable. RSpec::OpenAPI.ignored_paths = ["/admin/full/path/", Regexp.new("^/_internal/")] + +# Your custom post-processing hook (like unrandomizing IDs) +RSpec::OpenAPI.post_process_hook = -> (path, records, spec) do + RSpec::OpenAPI::HashHelper.matched_paths(spec, 'paths.*.*.responses.*.content.*.*.*.id').each do |paths| + spec.dig(*paths[0..-2]).merge!(id: '123') + end +end ``` ### Can I use rspec-openapi with `$ref` to minimize duplication of schema? diff --git a/lib/rspec/openapi.rb b/lib/rspec/openapi.rb index 995093b..826eb32 100644 --- a/lib/rspec/openapi.rb +++ b/lib/rspec/openapi.rb @@ -33,6 +33,7 @@ module RSpec::OpenAPI @path_records = Hash.new { |h, k| h[k] = [] } @ignored_path_params = %i[controller action format] @ignored_paths = [] + @post_process_hook = nil # This is the configuraion override file name we look for within each path. @config_filename = 'rspec_openapi.rb' @@ -54,7 +55,8 @@ class << self :response_headers, :path_records, :ignored_paths, - :ignored_path_params + :ignored_path_params, + :post_process_hook attr_reader :config_filename end diff --git a/lib/rspec/openapi/result_recorder.rb b/lib/rspec/openapi/result_recorder.rb index 0371b0b..f3c7e12 100644 --- a/lib/rspec/openapi/result_recorder.rb +++ b/lib/rspec/openapi/result_recorder.rb @@ -34,6 +34,9 @@ def record_results! RSpec::OpenAPI::ComponentsUpdater.update!(spec, new_from_zero) RSpec::OpenAPI::SchemaCleaner.cleanup_empty_required_array!(spec) RSpec::OpenAPI::SchemaSorter.deep_sort!(spec) + if RSpec::OpenAPI.post_process_hook.is_a?(Proc) + RSpec::OpenAPI.post_process_hook.call(path, records, spec) + end end end end diff --git a/spec/apps/rails/doc/openapi.json b/spec/apps/rails/doc/openapi.json index 9eecf8c..e048b2b 100644 --- a/spec/apps/rails/doc/openapi.json +++ b/spec/apps/rails/doc/openapi.json @@ -1139,5 +1139,6 @@ "name": "Secret-Key" } } - } + }, + "custom_field": "custom_value" } \ No newline at end of file diff --git a/spec/apps/rails/doc/openapi.yaml b/spec/apps/rails/doc/openapi.yaml index b08aa9b..dbafbec 100644 --- a/spec/apps/rails/doc/openapi.yaml +++ b/spec/apps/rails/doc/openapi.yaml @@ -742,3 +742,4 @@ components: type: apiKey in: header name: Secret-Key +custom_field: custom_value diff --git a/spec/integration_tests/rails_test.rb b/spec/integration_tests/rails_test.rb index b7a8dc9..44b3fc1 100644 --- a/spec/integration_tests/rails_test.rb +++ b/spec/integration_tests/rails_test.rb @@ -34,6 +34,10 @@ }, } +RSpec::OpenAPI.post_process_hook = -> (path, records, spec) do + spec['custom_field'] = 'custom_value' +end + class TablesIndexTest < ActionDispatch::IntegrationTest i_suck_and_my_tests_are_order_dependent! openapi! From b8f39d69abc7d80ce50a10e8785e021a41419bbb Mon Sep 17 00:00:00 2001 From: Patryk Ptasinski Date: Wed, 10 Apr 2024 17:12:52 +0200 Subject: [PATCH 2/2] Rubocop fixes --- lib/rspec/openapi/result_recorder.rb | 24 ++++++++++++++++-------- spec/integration_tests/rails_test.rb | 4 +--- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/rspec/openapi/result_recorder.rb b/lib/rspec/openapi/result_recorder.rb index f3c7e12..a57c3fd 100644 --- a/lib/rspec/openapi/result_recorder.rb +++ b/lib/rspec/openapi/result_recorder.rb @@ -29,14 +29,8 @@ def record_results! rescue StandardError, NotImplementedError => e # e.g. SchemaBuilder raises a NotImplementedError @error_records[e] = record # Avoid failing the build end - RSpec::OpenAPI::SchemaCleaner.cleanup_conflicting_security_parameters!(spec) - RSpec::OpenAPI::SchemaCleaner.cleanup!(spec, new_from_zero) - RSpec::OpenAPI::ComponentsUpdater.update!(spec, new_from_zero) - RSpec::OpenAPI::SchemaCleaner.cleanup_empty_required_array!(spec) - RSpec::OpenAPI::SchemaSorter.deep_sort!(spec) - if RSpec::OpenAPI.post_process_hook.is_a?(Proc) - RSpec::OpenAPI.post_process_hook.call(path, records, spec) - end + cleanup_schema!(new_from_zero, spec) + execute_post_process_hook(path, records, spec) end end end @@ -52,4 +46,18 @@ def error_message #{@error_records.map { |e, record| "#{e.inspect}: #{record.inspect}" }.join("\n")} ERR_MSG end + + private + + def execute_post_process_hook(path, records, spec) + RSpec::OpenAPI.post_process_hook.call(path, records, spec) if RSpec::OpenAPI.post_process_hook.is_a?(Proc) + end + + def cleanup_schema!(new_from_zero, spec) + RSpec::OpenAPI::SchemaCleaner.cleanup_conflicting_security_parameters!(spec) + RSpec::OpenAPI::SchemaCleaner.cleanup!(spec, new_from_zero) + RSpec::OpenAPI::ComponentsUpdater.update!(spec, new_from_zero) + RSpec::OpenAPI::SchemaCleaner.cleanup_empty_required_array!(spec) + RSpec::OpenAPI::SchemaSorter.deep_sort!(spec) + end end diff --git a/spec/integration_tests/rails_test.rb b/spec/integration_tests/rails_test.rb index 44b3fc1..27793de 100644 --- a/spec/integration_tests/rails_test.rb +++ b/spec/integration_tests/rails_test.rb @@ -34,9 +34,7 @@ }, } -RSpec::OpenAPI.post_process_hook = -> (path, records, spec) do - spec['custom_field'] = 'custom_value' -end +RSpec::OpenAPI.post_process_hook = ->(_path, _records, spec) { spec['custom_field'] = 'custom_value' } class TablesIndexTest < ActionDispatch::IntegrationTest i_suck_and_my_tests_are_order_dependent!