require "pact_broker/webhooks/repository"

module PactBroker
  module Webhooks
    describe Repository do
      let(:url) { "http://example.org" }
      let(:body) { {"some" => "json" } }
      let(:headers) { {"Content-Type" => "application/json", "Accept" => "application/json"} }
      let(:request) do
        Webhooks::WebhookRequestTemplate.new(
          method: "post",
          url: url,
          headers: headers,
          username: "username",
          password: "password",
          body: body)
      end
      let(:event) do
        PactBroker::Webhooks::WebhookEvent.new(name: "something_happened")
      end
      let(:events) { [event]}
      let(:webhook) { Domain::Webhook.new(request: request, events: events) }
      let(:consumer) { td.create_pacticipant("Consumer").and_return(:pacticipant) }
      let(:provider) { td.create_pacticipant("Provider").and_return(:pacticipant) }
      let(:webhook_consumer) { Domain::WebhookPacticipant.new(name: consumer.name) }
      let(:webhook_provider) { Domain::WebhookPacticipant.new(name: provider.name) }
      let(:uuid) { "the-uuid" }
      let(:created_webhook_record) { PactBroker::Webhooks::Webhook.db[:webhooks].order(:id).last }
      let(:created_events) { PactBroker::Webhooks::Webhook.db[:webhook_events].where(webhook_id: created_webhook_record[:id]).order(:name).all }
      let(:expected_webhook_record) do
        {
          uuid: "the-uuid",
          method: "post",
          url: "http://example.org",
          username: "username",
          password:  "cGFzc3dvcmQ=",
          body: body.to_json,
          consumer_id:  consumer.id,
          provider_id:  provider.id
        }
      end

      describe "#create" do
        subject { Repository.new.create(uuid, webhook, consumer, provider) }

        it "saves webhook" do
          subject
          expect(created_webhook_record).to include expected_webhook_record
        end

        it "saves the webhook headers as JSON" do
          subject
          expect(JSON.parse(created_webhook_record[:headers])).to eq headers.transform_keys { |k| k.downcase }
        end

        it "saves the webhook events" do
          expect(subject.events.first[:name]).to eq "something_happened"
        end

        context "when consumer and provider domain objects are set on the object rather than passed in" do
          let(:webhook) { Domain::Webhook.new(request: request, events: events, consumer: webhook_consumer, provider: webhook_provider) }

          subject { Repository.new.create(uuid, webhook, nil, nil) }

          it "sets the consumer and provider relationships" do
            expect(subject.consumer.name).to eq consumer.name
            expect(subject.provider.name).to eq provider.name
          end
        end
      end

      describe "delete_by_uuid" do
        before do
          Repository.new.create uuid, webhook, consumer, provider
          Repository.new.create "another-uuid", webhook, consumer, provider
        end

        subject { Repository.new.delete_by_uuid(uuid) }

        it "deletes the webhook" do
          expect { subject }.to change { PactBroker::Webhooks::Webhook.db[:webhooks].where(uuid: uuid).count }.by(-1)
        end
      end

      describe "delete_by_pacticipant" do
        before do
          td.create_consumer("other-consumer")
            .create_provider("other-provider")
            .create_consumer_version
            .create_pact
            .create_webhook(uuid: "other-uuid")
            .create_triggered_webhook
            .create_webhook_execution
            .create_consumer("foo")
            .create_provider("bar")
            .create_consumer_version
            .create_pact
            .create_webhook(uuid: "1234")
            .create_triggered_webhook
            .create_webhook_execution
            .create_webhook(uuid: "5555")
            .create_triggered_webhook
            .create_webhook_execution
          # simulate resource already deleted
          Webhook.where(uuid: "5555").delete
        end

        context "when the pacticipant is the consumer" do

          subject { Repository.new.delete_by_pacticipant td.consumer }

          it "deletes the matching webhook" do
            expect { subject }.to change { Webhook.where(uuid: "1234").count }.by(-1)
          end

          it "does not delete the unmatching webhooks" do
            expect { subject }.to change { Webhook.count }.by(-1)
          end

          it "deletes the triggered webhooks" do
            expect { subject }.to change { TriggeredWebhook.count }.by(-2)
          end
        end

        context "when the pacticipant is the provider" do
          subject { Repository.new.delete_by_pacticipant(td.provider) }

          it "deletes the matching webhooks" do
            expect { subject }.to change { Webhook.where(uuid: "1234").count }.by(-1)
          end

          it "does not delete the unmatching webhooks" do
            expect { subject }.to change { Webhook.count }.by(-1)
          end

          it "deletes the triggered webhooks" do
            expect { subject }.to change { TriggeredWebhook.count }.by(-2)
          end
        end
      end

      describe "delete_by_consumer_and_provider" do
        before do
          td.create_consumer("foo")
            .create_provider("other-provider")
            .create_consumer_version
            .create_pact
            .create_webhook(uuid: "other-uuid")
            .comment("kept because doesn't match provider")
            .create_triggered_webhook
            .create_webhook_execution
            .create_provider("bar")
            .create_consumer_version
            .create_pact
            .create_webhook(uuid: "1234")
            .create_triggered_webhook
            .create_webhook_execution
            .create_webhook(uuid: "5555")
            .create_triggered_webhook
            .create_webhook_execution
          # simulate resource already deleted
          Webhook.where(uuid: "5555").delete
        end

        subject { Repository.new.delete_by_consumer_and_provider(td.consumer, td.provider) }

        it "deletes the webhooks that match both consumer and provider" do
          expect { subject }.to change { Webhook.where(uuid: "1234").count }.by(-1)
        end

        it "does not delete the unmatching webhooks" do
          expect { subject }.to change { Webhook.count }.by(-1)
        end

        it "deletes the triggered webhooks" do
          expect { subject }.to change { TriggeredWebhook.count }.by(-2)
        end
      end

      describe "find_by_uuid" do
        subject { Repository.new.find_by_uuid(uuid) }

        context "when a webhook is found" do
          before do
            Repository.new.create uuid, webhook, consumer, provider
          end

          it "returns a webhook with the consumer set" do
            expect(subject.consumer.name).to eq consumer.name
          end

          it "returns a webhook with the provider set" do
            expect(subject.provider.name).to eq provider.name
          end

          it "returns a webhook with the uuid set" do
            expect(subject.uuid).to eq uuid
          end

          it "returns a webhook with the body set" do
            expect(subject.request.body).to eq body
          end

          it "returns a webhook with the headers set" do
            expect(subject.request.headers).to eq headers.transform_keys { |k| k.downcase }
          end

          it "returns a webhook with the username set" do
            expect(subject.request.username).to eq "username"
          end

          it "returns a webhook with the password set" do
            expect(subject.request.password).to eq "password"
          end

          it "returns a webhook with the url set" do
            expect(subject.request.url).to eq url
          end

          it "returns a webhook with a created_at date" do
            expect(subject.created_at).to be_datey
          end

          it "returns a webhook with a updated_at date" do
            expect(subject.updated_at).to be_datey
          end

          context "when the body is a XML string" do
            let(:body) { "<xml>Why would you do this?</xml>" }

            it "returns the body as the XML String, not an JSON Object" do
              expect(subject.request.body).to eq body
            end
          end

          context "when the optional attributes are nil" do
            let(:body) { nil }
            let(:headers) { nil }

            it "does not blow up" do
              expect(subject.request.body).to eq body
              expect(subject.request.headers).to eq({})
            end
          end
        end

        context "when a webhook is not found" do
          it "returns nil" do
            expect(subject).to be nil
          end
        end

      end

      describe "update_by_uuid" do
        before do
          td.create_consumer("Foo")
            .create_provider
            .create_webhook(old_webhook_params)
            .create_consumer("Foo2")
        end

        let(:uuid) { "1234" }
        let(:old_webhook_params) do
          {
            events: [{ name: "something" }],
            uuid: uuid,
            method: "POST",
            url: "http://example.org",
            body: '{"foo":1}',
            headers: {"Content-Type" => "application/json"},
            username: "username",
            password: "password"
          }
        end
        let(:new_request_webhook_params) do
          {
            method: "GET",
            url: "http://example.com",
            body: "foo",
            headers: {"Content-Type" => "text/plain"}
          }
        end
        let(:new_request) { PactBroker::Domain::WebhookRequest.new(new_request_webhook_params) }
        let(:new_event) do
          PactBroker::Webhooks::WebhookEvent.new(name: "something_else")
        end
        let(:new_consumer) { Domain::WebhookPacticipant.new(name: "Foo2") }
        let(:new_webhook) do
          PactBroker::Domain::Webhook.new(
            consumer: new_consumer,
            events: [new_event],
            request: new_request
          )
        end

        subject { Repository.new.update_by_uuid(uuid, new_webhook) }

        it "updates the webhook" do
          expect(subject.uuid).to eq uuid
          expect(subject.request.method).to eq "GET"
          expect(subject.request.url).to eq "http://example.com"
          expect(subject.request.body).to eq "foo"
          expect(subject.request.headers).to eq "content-type" => "text/plain"
          expect(subject.request.username).to eq nil
          expect(subject.request.password).to eq nil
          expect(subject.events.first.name).to eq "something_else"
          expect(subject.consumer.name).to eq "Foo2"
        end

        context "when the updated params do not contain a consumer or provider" do
          let(:new_webhook) do
            PactBroker::Domain::Webhook.new(
              events: [new_event],
              request: new_request
            )
          end

          it "removes the existing consumer or provider" do
            expect(subject.consumer).to be nil
          end
        end
      end

      describe "find_all" do
        before do
          allow(PactBroker).to receive(:policy_scope!).and_call_original
          Repository.new.create uuid, webhook, consumer, provider
          Repository.new.create "some-other-uuid", webhook, consumer, provider
        end

        subject { Repository.new.find_all }

        it "returns a list of webhooks" do
          expect(subject.size).to be 2
          expect(subject.first).to be_instance_of Domain::Webhook
        end

        it "uses the policy" do
          expect(PactBroker).to receive(:policy_scope!)
          subject
        end
      end

      describe "find_by_consumer_and_provider" do
        let(:consumer) { td.consumer }
        let(:provider) { td.provider }

        subject { Repository.new.find_by_consumer_and_provider(consumer, provider) }

        context "when a webhook exists with a matching consumer and provider" do
          before do
            td.create_consumer("Consumer")
              .create_provider("Another Provider")
              .create_webhook
              .create_provider("Provider")
              .create_webhook
          end

          it "returns an array of webhooks" do
            expect(subject).to be_instance_of Array
            expect(subject.first.uuid).to eq td.webhook.uuid
          end
        end

        context "when a webhook does not exist with a matching consumer and provider" do
          before do
            td
              .create_consumer("Consumer")
              .create_provider("Provider")
              .create_webhook
              .create_provider("Another Provider")
          end

          it "returns an empty array" do
            expect(subject).to eq []
          end
        end

        context "when the consumer argument is nil" do
          let(:consumer) { nil }

          before do
            td.create_provider("Provider")
              .create_consumer("Consumer")
              .create_provider_webhook
              .create_webhook
          end

          it "returns all the webhooks where the provider matches and the consumer id is nil" do
            expect(subject.size).to be 1
            expect(subject.first.consumer).to be nil
            expect(subject.first.provider).to_not be nil
          end
        end

        context "when the provider argument is nil" do
          let(:provider) { nil }

          before do
            td.create_consumer("Consumer")
              .create_provider("Provider")
              .create_consumer_webhook
              .create_webhook
          end

          it "returns all the webhooks where the consumer matches and the provider id is nil" do
            expect(subject.size).to be 1
            expect(subject.first.provider).to be nil
            expect(subject.first.consumer).to_not be nil
          end
        end
      end

      describe "find_webhooks_to_trigger" do
        before do
          allow(PactBroker).to receive(:policy_scope!).and_call_original
        end

        let(:enabled) { true }

        subject { Repository.new.find_webhooks_to_trigger(consumer: td.consumer, provider: td.provider, event_name: "contract_published") }

        it "does not use a policy" do
          td.create_webhook(event_names: ["contract_published"], enabled: enabled, description: "Enabled webhook")
            .create_consumer("Foo")
            .create_provider("Bar")
          expect(PactBroker).to_not receive(:policy_scope!)
          is_expected.to contain_exactly(
            have_attributes(description: "Enabled webhook")
          )
        end

        context "when the webhook is disabled" do
          before do
            td.create_webhook(event_names: ["contract_published"], enabled: enabled)
              .create_consumer("Foo")
              .create_provider("Bar")
          end
          let(:enabled) { false }

          it "finds no webhooks to trigger" do
            is_expected.to be_empty
          end
        end

        context "when the webhook is specified for a consumer and all providers" do
          before do
            td.create_consumer("Foo1")
              .create_provider("Bar1")
              .create_webhook(provider: nil, event_names: ["contract_published"], description: "Right webhook")
          end

          let(:webhook_consumer) { Domain::WebhookPacticipant.new(name: td.consumer.name) }

          it "finds one webhook to trigger" do
            is_expected.to contain_exactly(
              have_attributes(description: "Right webhook")
            )
          end
        end

        context "when the webhook is specified for matching consumer but not provider" do
          before do
            td.create_consumer("Foo1")
              .create_provider("Bar1")
              .create_webhook(event_names: ["contract_published"])
              .create_provider("Bar3")
          end

          it "finds no webhooks to trigger" do
            is_expected.to be_empty
          end
        end

        context "when the webhook is specified for matching consumer label" do
          before do
            td.create_webhook(
                event_names: ["contract_published"],
                consumer_label: "my_label",
                description: "Labeled webhook"
              )
              .create_consumer("Consumer")
              .create_label("my_label")
              .create_provider("Provider")
          end

          it "finds one webhook to trigger" do
            is_expected.to contain_exactly(
              have_attributes(description: "Labeled webhook")
            )
          end
        end

        context "when the webhook is specified for matching consumer label and specific provider" do
          before do
            td.create_provider("Provider")
              .create_webhook(
                event_names: ["contract_published"],
                consumer_label: "my_label",
                description: "Labeled webhook"
              )
              .create_consumer("Consumer")
              .create_label("my_label")
          end

          it "finds one webhook to trigger" do
            is_expected.to contain_exactly(
              have_attributes(description: "Labeled webhook")
            )
          end
        end

        context "when the webhook is specified for consumer label that does not match" do
          before do
            td.create_webhook(event_names: ["contract_published"], consumer_label: "my_label")
              .create_consumer("Consumer")
              .create_label("other_label")
              .create_provider("Provider")
          end

          it "finds no webhooks to trigger" do
            is_expected.to be_empty
          end
        end

        context "when the webhook is specified for matching provider label" do
          before do
            td.create_webhook(
                event_names: ["contract_published"],
                provider_label: "my_label",
                description: "Labeled webhook"
              )
              .create_consumer("Consumer")
              .create_provider("Provider")
              .create_label("my_label")
          end

          it "finds one webhook to trigger" do
            is_expected.to contain_exactly(
              have_attributes(description: "Labeled webhook")
            )
          end
        end

        context "when the webhook is specified for matching provider label and specific consumer" do
          before do
            td.create_consumer("Consumer")
              .create_webhook(
                event_names: ["contract_published"],
                provider_label: "my_label",
                description: "Labeled webhook"
              )
              .create_provider("Provider")
              .create_label("my_label")
          end

          it "finds one webhook to trigger" do
            is_expected.to contain_exactly(
              have_attributes(description: "Labeled webhook")
            )
          end
        end

        context "when the webhook is specified for provider label that does not match" do
          before do
            td.create_webhook(event_names: ["contract_published"], provider_label: "my_label")
              .create_consumer("Consumer")
              .create_provider("Provider")
              .create_label("other_label")
          end

          it "find no webhooks to trigger" do
            is_expected.to be_empty
          end
        end

        context "when the webhook is specified for consumer and provider label" do
          before do
            td.create_webhook(
                event_names: ["contract_published"],
                consumer_label: "clabel",
                provider_label: "plabel",
                description: "Labeled webhook"
              )
              .create_webhook(
                event_names: ["contract_published"],
                consumer_label: "clabel",
                provider_label: "plabel2",
                description: "Labeled consumer webhook"
              )
              .create_webhook(
                event_names: ["contract_published"],
                consumer_label: "clabel2",
                provider_label: "plabel",
                description: "Labeled provider webhook"
              )
              .create_consumer("Consumer")
              .create_label("clabel")
              .create_provider("Provider")
              .create_label("plabel")
          end

          it "finds one webhook to trigger" do
            is_expected.to contain_exactly(
              have_attributes(description: "Labeled webhook")
            )
          end
        end
      end

      describe "create_triggered_webhook" do
        before do
          td.create_consumer
            .create_provider
            .create_webhook
            .create_consumer_version
            .create_pact
            .create_verification
        end

        let(:event_context) { { "some" => "info" } }

        subject { Repository.new.create_triggered_webhook "1234", td.webhook, td.pact, td.verification, "publication", "some_event", event_context }

        it "creates a TriggeredWebhook" do
          expect(subject.webhook_uuid ).to eq td.webhook.uuid
          expect(subject.consumer).to eq td.consumer
          expect(subject.provider).to eq td.provider
          expect(subject.verification).to eq td.verification
          expect(subject.uuid).to eq "1234"
          expect(subject.trigger_type).to eq "publication"
          expect(subject.event_name).to eq "some_event"
          expect(subject.event_context).to eq event_context
        end

        it "sets the webhook" do
          expect(subject.webhook.uuid).to eq td.webhook.uuid
        end

        it "sets the webhook_uuid" do
          expect(subject.webhook_uuid).to eq td.webhook.uuid
        end

        it "sets the consumer" do
          expect(subject.consumer).to eq td.consumer
        end

        it "sets the provider" do
          expect(subject.provider).to eq td.provider
        end

        it "sets the PactPublication" do
          expect(subject.pact_publication.id).to eq td.pact.id
        end

        context "without a verification" do
          subject { Repository.new.create_triggered_webhook "1234", td.webhook, td.pact, nil, "publication", "some_event", {} }

          it "does not set the verification" do
            expect(subject.verification).to be nil
          end
        end
      end

      describe "create_execution" do
        before do
          td.create_consumer
            .create_provider
            .create_consumer_version
            .create_pact
            .create_webhook
            .create_triggered_webhook
        end

        let(:webhook_domain) { Repository.new.find_by_uuid td.webhook.uuid }
        let(:webhook_execution_result) { instance_double("PactBroker::Domain::WebhookExecutionResult", success?: true, logs: "logs") }
        let(:repository) { Repository.new }

        subject { repository.create_execution td.triggered_webhook, webhook_execution_result }

        it "saves a new webhook execution " do
          expect { subject }.to change { Execution.count }.by(1)
        end

        it "sets the success" do
          expect(subject.success).to be true
        end

        it "sets the logs" do
          expect(subject.logs).to eq "logs"
        end

        context "when the triggered webhook has been deleted in the meantime" do
          before do
            TriggeredWebhook.where(id: td.triggered_webhook.id).delete
            allow(repository).to receive(:logger).and_return(logger)
          end

          let(:logger) { double("logger") }

          it "just logs the error" do
            expect(logger).to receive(:info).with(/triggered webhook with id #{td.triggered_webhook.id}/)
            subject
          end
        end
      end

      describe "find_latest_triggered_webhooks" do
        before do
          td
            .create_pact_with_hierarchy("Foo", "1.0.0", "Bar")
            .create_webhook
            .create_triggered_webhook
            .create_webhook_execution
            .create_pact_with_hierarchy
            .create_webhook(uuid: "123")
            .create_triggered_webhook(uuid: "256", created_at: DateTime.new(2016))
            .create_webhook_execution
            .create_triggered_webhook(uuid: "332", created_at: DateTime.new(2017))
            .create_webhook_execution
            .create_webhook(uuid: "987")
            .create_triggered_webhook(uuid: "876", created_at: DateTime.new(2017))
            .create_webhook_execution
            .create_triggered_webhook(uuid: "638", created_at: DateTime.new(2018))
            .create_webhook_execution
        end

        subject { Repository.new.find_latest_triggered_webhooks(td.consumer, td.provider) }

        it "finds the latest triggered webhooks" do
          expect(subject.collect(&:uuid).sort).to eq ["332", "638"]
        end

        context "when a webhook has been triggered by different events" do
          before do
            td.create_pact_with_hierarchy("Foo2", "1.0.0", "Bar2")
              .create_webhook
              .create_triggered_webhook(uuid: "333", event_name: "foo")
              .create_triggered_webhook(uuid: "555", event_name: "foo")
              .create_webhook_execution
              .create_triggered_webhook(uuid: "444", event_name: "bar")
              .create_triggered_webhook(uuid: "777", event_name: "bar")
              .create_webhook_execution
              .create_triggered_webhook(uuid: "111", event_name: nil)
              .create_triggered_webhook(uuid: "888", event_name: nil)
              .create_webhook_execution
          end

          it "returns one for each event" do
            # ignoring the ones with nil event_names because they're old data, and shouldn't be
            # considered as a separate "group"
            expect(subject.collect(&:uuid).sort).to eq ["555", "777"]
          end
        end

        context "when there are two 'latest' triggered webhooks at the same time" do
          before do
            td.create_triggered_webhook(uuid: "888", created_at: DateTime.new(2018))
              .create_webhook_execution
          end

          it "returns the one with the bigger ID" do
            expect(subject.collect(&:uuid).sort).to eq ["332", "888"]
          end
        end

        context "when there are no triggered webhooks for the given consumer and provider" do
          before do
            td.create_consumer
              .create_provider
          end

          it "returns an empty list" do
            expect(subject).to be_empty
          end
        end
      end

      describe "find_latest_triggered_webhooks_for_pact" do
        before do
          td
            .create_pact_with_hierarchy("Foo", "1.0.0", "Bar")
            .create_webhook
            .create_triggered_webhook
            .create_webhook_execution
            .create_pact_with_hierarchy
            .create_webhook
            .create_triggered_webhook(uuid: "256", created_at: DateTime.new(2016))
            .create_webhook_execution
            .create_triggered_webhook(uuid: "332", created_at: DateTime.new(2017))
            .create_webhook_execution
            .create_provider_webhook(uuidd: "987")
            .create_triggered_webhook(uuid: "876", created_at: DateTime.new(2017))
            .create_webhook_execution
            .create_triggered_webhook(uuid: "638", created_at: DateTime.new(2018))
            .create_webhook_execution
            .create_consumer_webhook
            .create_triggered_webhook(uuid: "555", created_at: DateTime.new(2017))
            .create_webhook_execution
            .create_triggered_webhook(uuid: "777", created_at: DateTime.new(2018))
            .create_webhook_execution
        end

        subject { Repository.new.find_latest_triggered_webhooks_for_pact(td.pact) }

        it "finds the latest triggered webhooks" do
          expect(subject.collect(&:uuid).sort).to eq ["332", "638", "777"]
        end
      end

      describe "find_triggered_webhooks_for_pact" do
        before do
          td
            .create_pact_with_hierarchy("Foo", "1", "Bar")
            .create_webhook
            .create_triggered_webhook(uuid: "1")
            .create_webhook_execution
            .create_consumer_version("2")
            .create_pact
            .create_triggered_webhook(uuid: "2")
            .create_webhook_execution
        end

        subject { Repository.new.find_triggered_webhooks_for_pact(td.pact) }

        it "finds the triggered webhooks" do
          expect(subject.collect(&:uuid).sort).to eq ["2"]
        end
      end

      describe "find_triggered_webhooks_for_verification" do
        before do
          td
            .create_pact_with_hierarchy("Foo", "1", "Bar")
            .create_verification_webhook
            .create_verification(provider_version: "1")
            .create_triggered_webhook(uuid: "1")
            .create_verification(provider_version: "2", number: 2)
            .create_triggered_webhook(uuid: "2")
        end

        subject { Repository.new.find_triggered_webhooks_for_verification(td.verification) }

        it "finds the triggered webhooks" do
          expect(subject.collect(&:uuid).sort).to eq ["2"]
        end
      end

      describe "fail_retrying_triggered_webhooks" do
        before do
          td.create_pact_with_hierarchy
            .create_webhook
            .create_triggered_webhook(status: TriggeredWebhook::STATUS_RETRYING)
            .create_triggered_webhook(status: TriggeredWebhook::STATUS_SUCCESS)
            .create_triggered_webhook(status: TriggeredWebhook::STATUS_NOT_RUN)
            .create_triggered_webhook(status: TriggeredWebhook::STATUS_FAILURE)
        end

        it "sets the triggered_webhooks with retrying status to failed" do
          Repository.new.fail_retrying_triggered_webhooks
          expect(TriggeredWebhook.failed.count).to eq 2
          expect(TriggeredWebhook.retrying.count).to eq 0
          expect(TriggeredWebhook.successful.count).to eq 1
          expect(TriggeredWebhook.not_run.count).to eq 1
        end
      end

      describe "delete_triggered_webhooks_by_pact_publication_id" do
        before do
          td.create_pact_with_hierarchy
            .create_webhook
            .create_triggered_webhook
            .create_webhook_execution
            .create_pact_with_hierarchy("A Consumer", "1.2.3", "A Provider")
            .create_webhook
            .create_triggered_webhook
            .create_webhook_execution
        end

        subject { Repository.new.delete_triggered_webhooks_by_pact_publication_ids [td.pact.id] }

        it "deletes the triggered webhook" do
          expect { subject }.to change {
            TriggeredWebhook.count
          }.by(-1)
        end

        it "deletes the webhook_execution" do
          expect { subject }.to change {
            Execution.exclude(triggered_webhook_id: nil).count
          }.by(-1)
        end
      end

      describe "delete_triggered_webhooks_by_version_id" do
        subject { Repository.new.delete_triggered_webhooks_by_version_id(version.id) }

        context "when deleting a triggered webhook by consumer version" do
          let!(:version) do
            td
              .create_pact_with_hierarchy
              .create_webhook
              .create_triggered_webhook
              .create_webhook_execution
              .and_return(:consumer_version)
          end

          it "deletes the webhooks belonging to the consumer version" do
            expect { subject }.to change{ TriggeredWebhook.count }.by(-1)
          end
        end

        context "when deleting a triggered webhook by provider version" do
          let!(:version) do
            td
              .create_pact_with_hierarchy
              .create_verification(provider_version: "1")
              .create_provider_webhook(event_names: ["provider_verification_published"])
              .create_triggered_webhook
              .create_webhook_execution
              .and_return(:provider_version)
          end

          it "deletes the webhooks belonging to the consumer version" do
            expect { subject }.to change{ TriggeredWebhook.count }.by(-1)
          end
        end
      end
    end
  end
end
