diff --git a/lib/pact_broker/configuration.rb b/lib/pact_broker/configuration.rb index fe4afb086..c7a54c736 100644 --- a/lib/pact_broker/configuration.rb +++ b/lib/pact_broker/configuration.rb @@ -27,13 +27,14 @@ class Configuration ] attr_accessor :log_dir, :database_connection, :auto_migrate_db, :use_hal_browser, :html_pact_renderer - attr_accessor :validate_database_connection_config, :enable_diagnostic_endpoints, :version_parser + attr_accessor :validate_database_connection_config, :enable_diagnostic_endpoints, :version_parser, :sha_generator attr_accessor :use_case_sensitive_resource_names, :order_versions_by_date attr_accessor :check_for_potential_duplicate_pacticipant_names attr_accessor :semver_formats attr_accessor :enable_public_badge_access, :shields_io_base_url attr_accessor :webhook_retry_schedule attr_accessor :disable_ssl_verification + attr_accessor :base_equality_only_on_content_that_affects_verification_results attr_reader :api_error_reporters attr_writer :logger @@ -51,6 +52,8 @@ def logger def self.default_configuration require 'pact_broker/versions/parse_semantic_version' + require 'pact_broker/pacts/generate_sha' + config = Configuration.new config.log_dir = File.expand_path("./log") config.auto_migrate_db = true @@ -62,6 +65,8 @@ def self.default_configuration config.use_case_sensitive_resource_names = true config.html_pact_renderer = default_html_pact_render config.version_parser = PactBroker::Versions::ParseSemanticVersion + config.sha_generator = PactBroker::Pacts::GenerateSha + config.base_equality_only_on_content_that_affects_verification_results = false # Not recommended to set this to true unless there is no way to # consistently extract an orderable object from the consumer application version number. config.order_versions_by_date = false diff --git a/lib/pact_broker/pacts/content.rb b/lib/pact_broker/pacts/content.rb new file mode 100644 index 000000000..05be78a95 --- /dev/null +++ b/lib/pact_broker/pacts/content.rb @@ -0,0 +1,66 @@ +require 'pact_broker/pacts/parse' +require 'pact_broker/pacts/sort_content' + +module PactBroker + module Pacts + class Content + + def initialize pact_hash + @pact_hash = pact_hash + end + + def self.from_json json_content + new(Parse.call(json_content)) + end + + def self.from_hash pact_hash + new(pact_hash) + end + + def to_hash + pact_hash + end + + def to_json + pact_hash.to_json + end + + def sort + Content.from_hash(SortContent.call(pact_hash)) + end + + # Half thinking this belongs in GenerateSha + def content_that_affects_verification_results + if interactions || messages + cont = {} + cont['interactions'] = interactions if interactions + cont['messages'] = messages if messages + cont['pact_specification_version'] = pact_specification_version if pact_specification_version + cont + else + pact_hash + end + end + + def messages + pact_hash.is_a?(Hash) ? pact_hash['messages'] : nil + end + + def interactions + pact_hash.is_a?(Hash) ? pact_hash['interactions'] : nil + end + + def pact_specification_version + maybe_pact_specification_version_1 = pact_hash['metadata']['pactSpecification']['version'] rescue nil + maybe_pact_specification_version_2 = pact_hash['metadata']['pact-specification']['version'] rescue nil + maybe_pact_specification_version_3 = pact_hash['metadata'] && pact_hash['metadata']['pactSpecificationVersion'] rescue nil + maybe_pact_specification_version_1 || maybe_pact_specification_version_2 || maybe_pact_specification_version_3 + end + + private + + attr_reader :pact_hash + + end + end +end diff --git a/lib/pact_broker/pacts/create_formatted_diff.rb b/lib/pact_broker/pacts/create_formatted_diff.rb index e09fa87ee..fa4e2795e 100644 --- a/lib/pact_broker/pacts/create_formatted_diff.rb +++ b/lib/pact_broker/pacts/create_formatted_diff.rb @@ -14,7 +14,6 @@ def self.call pact_json_content, previous_pact_json_content difference = diff(previous_pact_hash, pact_hash) Pact::Matchers::UnixDiffFormatter.call(difference, colour: false, include_explanation: false) end - end end end diff --git a/lib/pact_broker/pacts/diff.rb b/lib/pact_broker/pacts/diff.rb index 4733d4b97..90d2beb0b 100644 --- a/lib/pact_broker/pacts/diff.rb +++ b/lib/pact_broker/pacts/diff.rb @@ -1,7 +1,8 @@ require 'pact_broker/api/pact_broker_urls' require 'pact_broker/date_helper' require 'pact_broker/pacts/create_formatted_diff' -require 'pact_broker/pacts/sort_verifiable_content' +require 'pact_broker/pacts/sort_content' +require 'pact_broker/pacts/parse' require 'pact_broker/repositories' require 'yaml' @@ -110,7 +111,7 @@ def prepare_content json_content if options[:raw] json_content else - PactBroker::Pacts::SortVerifiableContent.call(json_content) + SortContent.call(Parse.call(json_content)).to_json end end end diff --git a/lib/pact_broker/pacts/generate_sha.rb b/lib/pact_broker/pacts/generate_sha.rb new file mode 100644 index 000000000..bb47f113f --- /dev/null +++ b/lib/pact_broker/pacts/generate_sha.rb @@ -0,0 +1,24 @@ +require 'digest/sha1' +require 'pact_broker/configuration' +require 'pact_broker/pacts/sort_content' +require 'pact_broker/pacts/parse' +require 'pact_broker/pacts/content' + +module PactBroker + module Pacts + class GenerateSha + def self.call json_content, options = {} + content_for_sha = if PactBroker.configuration.base_equality_only_on_content_that_affects_verification_results + extract_verifiable_content_for_sha(json_content) + else + json_content + end + Digest::SHA1.hexdigest(content_for_sha) + end + + def self.extract_verifiable_content_for_sha json_content + Content.from_json(json_content).sort.content_that_affects_verification_results.to_json + end + end + end +end diff --git a/lib/pact_broker/pacts/parse.rb b/lib/pact_broker/pacts/parse.rb new file mode 100644 index 000000000..768c9ab26 --- /dev/null +++ b/lib/pact_broker/pacts/parse.rb @@ -0,0 +1,11 @@ +require 'pact_broker/json' + +module PactBroker + module Pacts + class Parse + def self.call(json) + JSON.parse(json, PACT_PARSING_OPTIONS) + end + end + end +end diff --git a/lib/pact_broker/pacts/repository.rb b/lib/pact_broker/pacts/repository.rb index 873415f2d..3edea2195 100644 --- a/lib/pact_broker/pacts/repository.rb +++ b/lib/pact_broker/pacts/repository.rb @@ -1,7 +1,7 @@ -require 'digest/sha1' require 'sequel' require 'ostruct' require 'pact_broker/logging' +require 'pact_broker/pacts/generate_sha' require 'pact_broker/pacts/pact_publication' require 'pact_broker/pacts/all_pact_publications' require 'pact_broker/pacts/latest_pact_publications_by_consumer_version' @@ -9,6 +9,7 @@ require 'pact_broker/pacts/latest_tagged_pact_publications' require 'pact/shared/json_differ' require 'pact_broker/domain' +require 'pact_broker/pacts/parse' module PactBroker module Pacts @@ -197,7 +198,7 @@ def different? pact, other_pact end def find_or_create_pact_version consumer_id, provider_id, json_content - sha = Digest::SHA1.hexdigest(json_content) + sha = PactBroker.configuration.sha_generator.call(json_content) PactVersion.find(sha: sha, consumer_id: consumer_id, provider_id: provider_id) || create_pact_version(consumer_id, provider_id, sha, json_content) end @@ -206,7 +207,6 @@ def create_pact_version consumer_id, provider_id, sha, json_content pact_version = PactVersion.new(consumer_id: consumer_id, provider_id: provider_id, sha: sha, content: json_content) pact_version.save end - end end end diff --git a/lib/pact_broker/pacts/sort_content.rb b/lib/pact_broker/pacts/sort_content.rb new file mode 100644 index 000000000..e661d3640 --- /dev/null +++ b/lib/pact_broker/pacts/sort_content.rb @@ -0,0 +1,54 @@ +require 'pact_broker/json' + +module PactBroker + module Pacts + class SortContent + def self.call pact_hash + key = verifiable_content_key_for(pact_hash) + + if key + content = pact_hash[key] + sorted_pact_hash = order_object(pact_hash) + sorted_pact_hash[key] = order_verifiable_content(content) + sorted_pact_hash + else + pact_hash + end + end + + def self.verifiable_content_key_for pact_hash + if pact_hash['interactions'] + 'interactions' + elsif pact_hash['messages'] + 'messages' + else + nil + end + end + + + def self.order_verifiable_content array + array_with_ordered_hashes = order_object(array) + array_with_ordered_hashes.sort{|a, b| a.to_json <=> b.to_json } + end + + def self.order_object thing + case thing + when Hash then order_hash(thing) + when Array then order_child_array(thing) + else thing + end + end + + def self.order_child_array array + array.collect{|thing| order_object(thing) } + end + + def self.order_hash hash + hash.keys.sort.each_with_object({}) do | key, new_hash | + new_hash[key] = order_object(hash[key]) + end + end + end + end +end diff --git a/lib/pact_broker/pacts/sort_verifiable_content.rb b/lib/pact_broker/pacts/sort_verifiable_content.rb deleted file mode 100644 index b9149e506..000000000 --- a/lib/pact_broker/pacts/sort_verifiable_content.rb +++ /dev/null @@ -1,41 +0,0 @@ -require 'pact_broker/json' - -module PactBroker - module Pacts - class SortVerifiableContent - - def self.call json - hash = JSON.parse(json, PACT_PARSING_OPTIONS) - verifiable_content = if hash['interactions'] - hash['interactions'] - elsif hash['messages'] - hash['messages'] - end - order_verifiable_content(verifiable_content).to_json - end - - def self.order_verifiable_content array - array_with_ordered_hashes = order_hashes(array) - array_with_ordered_hashes.sort{|a, b| a.to_json <=> b.to_json } - end - - def self.order_hashes thing - case thing - when Hash then order_hash(thing) - when Array then order_child_array(thing) - else thing - end - end - - def self.order_child_array array - array.collect{|thing| order_hashes(thing) } - end - - def self.order_hash hash - hash.keys.sort.each_with_object({}) do | key, new_hash | - new_hash[key] = order_hashes(hash[key]) - end - end - end - end -end diff --git a/spec/features/base_equality_only_on_content_that_affects_verification_results_spec.rb b/spec/features/base_equality_only_on_content_that_affects_verification_results_spec.rb new file mode 100644 index 000000000..d6c21883a --- /dev/null +++ b/spec/features/base_equality_only_on_content_that_affects_verification_results_spec.rb @@ -0,0 +1,34 @@ +RSpec.describe "base_equality_only_on_content_that_affects_verification_results" do + let(:td) { TestDataBuilder.new } + let(:json_content_1) { load_fixture('foo-bar.json') } + let(:json_content_2) do + pact_hash = load_json_fixture('foo-bar.json') + pact_hash['interactions'] = pact_hash['interactions'].reverse + pact_hash.to_json + end + let(:base_equality_only_on_content_that_affects_verification_results) { true } + + before do + PactBroker.configuration.base_equality_only_on_content_that_affects_verification_results = base_equality_only_on_content_that_affects_verification_results + td.create_pact_with_hierarchy("Foo", "1", "Bar", json_content_1) + .create_verification(provider_version: "5") + .create_consumer_version("2") + .create_pact(json_content: json_content_2) + end + + context "when a pact is published with a different order of interactions to a previous version, but which is otherwise the same" do + context "when base_equality_only_on_content_that_affects_verification_results is true" do + it "applies the verifications from the previous version" do + expect(PactBroker::Matrix::Row.all).to contain_hash(consumer_version_number: "2", provider_version_number: "5") + end + end + + context "when base_equality_only_on_content_that_affects_verification_results is false" do + let(:base_equality_only_on_content_that_affects_verification_results) { false } + + it "does not apply the verifications from the previous version" do + expect(PactBroker::Matrix::Row.all).to_not contain_hash(consumer_version_number: "2", provider_version_number: "5") + end + end + end +end diff --git a/spec/lib/pact_broker/pacts/content_spec.rb b/spec/lib/pact_broker/pacts/content_spec.rb new file mode 100644 index 000000000..54c67f08e --- /dev/null +++ b/spec/lib/pact_broker/pacts/content_spec.rb @@ -0,0 +1,166 @@ +require 'pact_broker/pacts/content' + +module PactBroker + module Pacts + describe Content do + describe "content_that_affects_verification_results" do + + subject { Content.from_hash(pact_hash).content_that_affects_verification_results } + + context "with messages" do + let(:pact_hash) do + { + 'ignored' => 'foo', + 'messages' => [1], + 'metadata' => { + 'pactSpecification' => { + 'version' => '1' + } + } + } + end + + let(:expected_content) do + { + 'messages' => [1], + 'pact_specification_version' => '1' + } + end + + it "extracts the messages and pact_specification_version" do + expect(subject).to eq expected_content + end + end + + context "with interactions" do + let(:pact_hash) do + { + 'ignored' => 'foo', + 'interactions' => [1], + 'metadata' => { + 'pactSpecification' => { + 'version' => '1' + } + } + } + end + + let(:expected_content) do + { + 'interactions' => [1], + 'pact_specification_version' => '1' + } + end + + it "extracts the interactions and pact_specification_version" do + expect(subject).to eq expected_content + end + end + + context "with both messages and interactions, even though this should never happen" do + let(:pact_hash) do + { + 'ignored' => 'foo', + 'interactions' => [1], + 'messages' => [2], + 'metadata' => { + 'pactSpecification' => { + 'version' => '1' + } + } + } + end + + let(:expected_content) do + { + 'interactions' => [1], + 'messages' => [2], + 'pact_specification_version' => '1' + } + end + + it "extracts the interactions and pact_specification_version" do + expect(subject).to eq expected_content + end + end + + context "with neither messages nor interactions" do + let(:pact_hash) do + { + 'ignored' => 'foo', + 'foo' => [1], + 'metadata' => { + 'pactSpecification' => { + 'version' => '1' + } + } + } + end + + it "returns the entire hash" do + expect(subject).to eq pact_hash + end + end + + context "when somebody publishes an array as the top level element" do + let(:pact_hash) do + [{ "foo" => "bar" }] + end + + it "returns the entire document" do + expect(subject).to eq pact_hash + end + end + end + + describe "#pact_specification_version" do + subject { Content.from_hash(json) } + context 'with pactSpecification.version' do + let(:json) do + { + 'metadata' => { + 'pactSpecification' => { + 'version' => '1' + } + } + } + end + + its(:pact_specification_version) { is_expected.to eq '1' } + end + + context 'with pact-specification.version' do + let(:json) do + { + 'metadata' => { + 'pact-specification' => { + 'version' => '1' + } + } + } + end + + its(:pact_specification_version) { is_expected.to eq '1' } + end + + context 'with pactSpecificationVersion' do + let(:json) do + { + 'metadata' => { + 'pactSpecificationVersion' => '1' + } + } + end + + its(:pact_specification_version) { is_expected.to eq '1' } + end + + context 'with an array for content' do + let(:json) { [] } + + its(:pact_specification_version) { is_expected.to eq nil } + end + end + end + end +end diff --git a/spec/lib/pact_broker/pacts/create_formatted_diff_spec.rb b/spec/lib/pact_broker/pacts/create_formatted_diff_spec.rb index 0d3306757..672fedceb 100644 --- a/spec/lib/pact_broker/pacts/create_formatted_diff_spec.rb +++ b/spec/lib/pact_broker/pacts/create_formatted_diff_spec.rb @@ -5,7 +5,6 @@ module PactBroker module Pacts describe CreateFormattedDiff do - describe ".call" do let(:pact_content_version_1) do @@ -24,9 +23,7 @@ module Pacts expect(subject).to match /\+.*get/ expect(subject).to_not include 'Key' end - end - end end end diff --git a/spec/lib/pact_broker/pacts/generate_sha_spec.rb b/spec/lib/pact_broker/pacts/generate_sha_spec.rb new file mode 100644 index 000000000..c7edb1f67 --- /dev/null +++ b/spec/lib/pact_broker/pacts/generate_sha_spec.rb @@ -0,0 +1,92 @@ +require 'pact_broker/pacts/generate_sha' + +module PactBroker + module Pacts + describe GenerateSha do + describe ".call integration test" do + let(:json_content) do + { + interactions: [{a: 1, b: 2}, {c: 3, d: 4}], + metadata: { + pactSpecification: { + version: '1' + } + } + }.to_json + end + + let(:json_content_with_only_order_difference) do + { + interactions: [{d: 4, c: 3}, {b: 2, a: 1}], + metadata: { + :'pact-specification' => { + version: '1' + } + } + }.to_json + end + + let(:json_content_with_diff_interactions) do + { + interactions: [{a: 9999, b: 2}, {c: 3, d: 4}], + metadata: { + pactSpecification: { + version: '1' + } + } + }.to_json + end + + before do + allow(Content).to receive(:from_json).and_return(content) + allow(content).to receive(:sort).and_return(content) + end + + let(:content) { instance_double('PactBroker::Pacts::Content', content_that_affects_verification_results: content_that_affects_verification_results) } + let(:content_that_affects_verification_results) { double('content', to_json: 'foo') } + + subject { GenerateSha.call(json_content) } + + it "accepts options in case there is any future requirement for a second argument" do + expect{ GenerateSha.call(json_content, some: 'options') }.to_not raise_error + end + + context "when equality is based on the verifiable content only" do + before do + PactBroker.configuration.base_equality_only_on_content_that_affects_verification_results = true + end + + it "sorts the content" do + expect(content).to receive(:sort) + subject + end + + it "creates the sha from the sorted content JSON" do + expect(Digest::SHA1).to receive(:hexdigest).with(content_that_affects_verification_results.to_json) + subject + end + + it "returns the sha" do + expect(subject).to eq "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" + end + end + + context "when equality is based on the verifiable content only" do + it "does not sort the content" do + expect(Content).to_not receive(:from_json) + subject + end + + it "creates the sha from the original JSON" do + expect(Digest::SHA1).to receive(:hexdigest).with(json_content) + subject + end + + it "returns the sha" do + expect(subject).to eq "ebc0feee91fb7fc0acf8420426184478ebaf648a" + end + end + end + end + end +end diff --git a/spec/lib/pact_broker/pacts/repository_spec.rb b/spec/lib/pact_broker/pacts/repository_spec.rb index 3ef33adbc..114b0dd1c 100644 --- a/spec/lib/pact_broker/pacts/repository_spec.rb +++ b/spec/lib/pact_broker/pacts/repository_spec.rb @@ -38,7 +38,11 @@ module Pacts expect(subject.created_at).to be_datey end - context "when a pact already exists with the same content" do + context "when a pact already exists with exactly the same content" do + before do + PactBroker.configuration.base_equality_only_on_content_that_affects_verification_results = false + end + let(:another_version) { Versions::Repository.new.create number: '2.0.0', pacticipant_id: consumer.id } before do @@ -49,8 +53,47 @@ module Pacts Repository.new.create version_id: another_version.id, consumer_id: consumer.id, provider_id: provider.id, json_content: json_content end + it "does not the content" do + expect_any_instance_of(Content).to_not receive(:sort) + subject + end + + it "creates a new PactPublication" do + expect { subject }.to change{ PactPublication.count }.by(1) + end + it "reuses the same PactVersion to save room" do - expect { subject }.to change{ PactVersion.count }.by(0) + expect { subject }.to_not change{ PactVersion.count } + end + end + + context "when base_equality_only_on_content_that_affects_verification_results is true" do + let(:another_version) { Versions::Repository.new.create number: '2.0.0', pacticipant_id: consumer.id } + let(:sha_1) { '1' } + let(:sha_2) { '1' } + + before do + PactBroker.configuration.base_equality_only_on_content_that_affects_verification_results = true + allow(PactBroker.configuration.sha_generator).to receive(:call).and_return(sha_1, sha_2) + Repository.new.create version_id: version.id, consumer_id: consumer.id, provider_id: provider.id, json_content: json_content + end + + subject do + Repository.new.create version_id: another_version.id, consumer_id: consumer.id, provider_id: provider.id, json_content: json_content + end + + context "when the sha is the same" do + it "reuses the same PactVersion to save room" do + expect { subject }.to_not change{ PactVersion.count } + end + end + + context "when the sha is not the same" do + let(:sha_2) { '2' } + + it "creates a new PactVersion" do + expect { subject }.to change{ PactVersion.count }.by(1) + end end end @@ -65,7 +108,7 @@ module Pacts Repository.new.create version_id: another_version.id, consumer_id: consumer.id, provider_id: provider.id, json_content: json_content end - it "does not reuse the same PactVersion to save room" do + it "does not reuse the same PactVersion" do expect { subject }.to change{ PactVersion.count }.by(1) end end @@ -524,7 +567,7 @@ module Pacts let(:pact_content_version_1) { load_fixture('consumer-provider.json') } let(:pact_content_version_2) do hash = load_json_fixture('consumer-provider.json') - hash['foo'] = 'bar' # Extra key will affect equality + hash['interactions'].first['foo'] = 'bar' # Extra key in interactions will affect equality hash.to_json end let(:pact_content_version_3) { load_fixture('consumer-provider.json') } diff --git a/spec/lib/pact_broker/pacts/sort_content_spec.rb b/spec/lib/pact_broker/pacts/sort_content_spec.rb new file mode 100644 index 000000000..ca4304b51 --- /dev/null +++ b/spec/lib/pact_broker/pacts/sort_content_spec.rb @@ -0,0 +1,44 @@ +require 'pact_broker/pacts/sort_content' + +module PactBroker + module Pacts + describe SortContent do + let(:pact_content_1) do + { + 'a' => 1, + 'interactions' => [{ 'a' => 1, 'b' => 2 }, { 'a' => [2, 1, 3], 'b' => 3 }] + } + end + + let(:pact_content_2) do + { + 'interactions' => [{ 'b' => 3, 'a' => [2, 1, 3]}, { 'b' => 2, 'a' => 1 }], + 'a' => 1 + } + end + + let(:expected_sorted_content) do + '{"a":1,"interactions":[{"a":1,"b":2},{"a":[2,1,3],"b":3}]}' + end + + it "sorts the interactions/messages and keys in a deterministic way" do + expect(SortContent.call(pact_content_1).to_json).to eq(expected_sorted_content) + expect(SortContent.call(pact_content_2).to_json).to eq(expected_sorted_content) + end + + context "when there is no messages or interactions key" do + let(:other_content) do + { + 'z' => 1, + 'a' => 1, + 'b' => 1, + } + end + + it "does not change the content" do + expect(SortContent.call(other_content)).to eq other_content + end + end + end + end +end diff --git a/spec/lib/pact_broker/pacts/sort_verifiable_content_spec.rb b/spec/lib/pact_broker/pacts/sort_verifiable_content_spec.rb deleted file mode 100644 index 459e916d1..000000000 --- a/spec/lib/pact_broker/pacts/sort_verifiable_content_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'pact_broker/pacts/sort_verifiable_content' - -module PactBroker - module Pacts - describe SortVerifiableContent do - let(:pact_content_1) do - { - a: 1, - interactions: [{ a: 1, b: 2 }, { a: 2, b: 3 }] - }.to_json - end - - let(:pact_content_2) do - { - interactions: [{ b: 3, a: 2}, { b: 2, a: 1 }], - a: 1 - }.to_json - end - - it "sorts the interactions/messages and keys in a deterministic way" do - expect(SortVerifiableContent.call(pact_content_1).to_json).to eq(SortVerifiableContent.call(pact_content_2).to_json) - end - end - end -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a510046a0..ed2b8ca1e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -28,6 +28,7 @@ RSpec.configure do | config | config.before :each do PactBroker.reset_configuration + PactBroker.configuration.base_equality_only_on_content_that_affects_verification_results = false require 'pact_broker/badges/service' PactBroker::Badges::Service.clear_cache end diff --git a/spec/support/foo-bar.json b/spec/support/foo-bar.json new file mode 100644 index 000000000..7f0d88f24 --- /dev/null +++ b/spec/support/foo-bar.json @@ -0,0 +1,34 @@ +{ + "consumer": { + "name": "Foo" + }, + "provider": { + "name": "Bar" + }, + "interactions": [ + { + "description": "a retrieve thing request", + "request": { + "method": "get", + "path": "/thing" + }, + "response": { + "status": 200 + } + },{ + "description": "another retrieve thing request", + "request": { + "method": "get", + "path": "/another-thing" + }, + "response": { + "status": 200 + } + } + ], + "metadata": { + "pactSpecification": { + "version": "2.0.0" + } + } +} diff --git a/spec/support/test_data_builder.rb b/spec/support/test_data_builder.rb index c762bffa0..07fc70a53 100644 --- a/spec/support/test_data_builder.rb +++ b/spec/support/test_data_builder.rb @@ -340,5 +340,4 @@ def default_json_content "random" => rand }.to_json end - end