diff --git a/.gitignore b/.gitignore index 938d9225..155bf921 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ /coverage /spec/reports +spec/reports/pacts diff --git a/Gemfile b/Gemfile index 15712840..2f5d85e9 100644 --- a/Gemfile +++ b/Gemfile @@ -25,6 +25,8 @@ gem "whenever", require: false group :development do gem "listen" + gem "pact", require: false + gem "pact_broker-client" gem "spring" end diff --git a/Gemfile.lock b/Gemfile.lock index 6a71945f..7d6a5fc7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -78,6 +78,7 @@ GEM addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) ast (2.4.2) + awesome_print (1.9.2) aws-eventstream (1.3.0) aws-partitions (1.940.0) aws-sdk-core (3.197.0) @@ -117,12 +118,16 @@ GEM bigdecimal rexml crass (1.0.6) + csv (3.3.0) date (3.3.4) diff-lcs (1.5.1) + dig_rb (1.0.1) docile (1.4.0) domain_name (0.6.20240107) drb (2.2.1) erubi (1.12.0) + expgen (0.1.1) + parslet factory_bot (6.4.6) activesupport (>= 5.0.0) factory_bot_rails (6.4.3) @@ -135,6 +140,7 @@ GEM faraday-net_http (3.1.0) net-http ffi (1.16.3) + find_a_port (1.0.1) gds-api-adapters (96.0.1) addressable link_header @@ -180,6 +186,10 @@ GEM http-accept (1.7.0) http-cookie (1.0.5) domain_name (~> 0.5) + httparty (0.22.0) + csv + mini_mime (>= 1.0.0) + multi_xml (>= 0.5.2) i18n (1.14.5) concurrent-ruby (~> 1.0) inflection (1.0.0) @@ -477,10 +487,39 @@ GEM opentelemetry-semantic_conventions opentelemetry-semantic_conventions (1.10.0) opentelemetry-api (~> 1.0) + pact (1.64.0) + pact-mock_service (~> 3.0, >= 3.3.1) + pact-support (~> 1.16, >= 1.16.9) + rack-test (>= 0.6.3, < 3.0.0) + rspec (~> 3.0) + term-ansicolor (~> 1.7) + thor (>= 0.20, < 2.0) + webrick (~> 1.8) + pact-mock_service (3.11.2) + find_a_port (~> 1.0.1) + json + pact-support (~> 1.16, >= 1.16.4) + rack (~> 2.0) + rspec (>= 2.14) + thor (>= 0.19, < 2.0) + webrick (~> 1.8) + pact-support (1.20.0) + awesome_print (~> 1.9) + diff-lcs (~> 1.5) + expgen (~> 0.1) + rainbow (~> 3.1.1) + pact_broker-client (1.75.2) + dig_rb (~> 1.0) + httparty (>= 0.21.0, < 1.0.0) + rake (~> 13.0) + table_print (~> 1.5) + term-ansicolor (~> 1.7) + thor (>= 0.20, < 2.0) parallel (1.24.0) parser (3.3.2.0) ast (~> 2.4.1) racc + parslet (2.0.0) pg (1.5.6) plek (5.2.0) prometheus_exporter (2.1.0) @@ -650,9 +689,16 @@ GEM statsd-ruby (1.5.0) stringio (3.1.0) strscan (3.1.0) + sync (0.5.0) + table_print (1.5.7) + term-ansicolor (1.8.0) + tins (~> 1.0) thor (1.3.1) timecop (0.9.9) timeout (0.4.1) + tins (1.33.0) + bigdecimal + sync tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) @@ -702,6 +748,8 @@ DEPENDENCIES listen mail-notify mlanett-redis-lock + pact + pact_broker-client pg plek pry-byebug diff --git a/Rakefile b/Rakefile index fee1c835..377c52cf 100644 --- a/Rakefile +++ b/Rakefile @@ -12,5 +12,11 @@ rescue LoadError # Rubocop isn't available in all environments end +begin + require "pact/tasks" +rescue LoadError + # Pact isn't available in all environments +end + Rake::Task[:default].clear if Rake::Task.task_defined?(:default) -task default: %i[rubocop spec] +task default: %i[rubocop spec pact:verify] diff --git a/spec/service_consumers/pact_helper.rb b/spec/service_consumers/pact_helper.rb new file mode 100644 index 00000000..d8f574c1 --- /dev/null +++ b/spec/service_consumers/pact_helper.rb @@ -0,0 +1,53 @@ +ENV["PACT_DO_NOT_TRACK"] = "true" + +require "pact/provider/rspec" +require "webmock/rspec" +require ::File.expand_path("../../config/environment", __dir__) + +Pact.configure do |config| + config.reports_dir = "spec/reports/pacts" + config.include WebMock::API + config.include WebMock::Matchers +end + +WebMock.allow_net_connect! + +def url_encode(str) + ERB::Util.url_encode(str) +end + +Pact.service_provider "Support API" do + honours_pact_with "GDS API Adapters" do + if ENV["PACT_URI"] + pact_uri(ENV["PACT_URI"]) + else + base_url = "https://govuk-pact-broker-6991351eca05.herokuapp.com" + path = "pacts/provider/#{url_encode(name)}/consumer/#{url_encode(consumer_name)}" + version_modifier = "versions/#{url_encode(ENV.fetch('PACT_CONSUMER_VERSION', 'branch-main'))}" + + pact_uri("#{base_url}/#{path}/#{version_modifier}") + end + end +end + +Pact.provider_states_for "GDS API Adapters" do + provider_state "the parameters are valid" do + set_up do + params = { + subject: "Feedback for app", + tags: %w[app_name], + user_agent: "Safari", + description: "There is something wrong with this page.", + } + SupportTicket.new(params) + end + end + + provider_state "the required parameters are not provided" do + set_up do + params = { subject: "Feedback for app" } + + SupportTicket.new(params) + end + end +end