Back to Repositories

Testing Webhook Request Processing Implementation in Postal

This test suite validates the ProcessWebhookRequestsJob functionality in Postal’s webhook processing system. It ensures proper handling of webhook requests with various states and retry conditions, covering core webhook delivery mechanisms.

Test Coverage Overview

The test suite provides comprehensive coverage of webhook request processing scenarios:

  • Empty request queue handling
  • Processing of unlocked requests with no retry time
  • Handling of requests with past retry times
  • Future retry time request management
  • Locked request handling

Implementation Analysis

The testing approach utilizes RSpec’s behavior-driven development patterns with context-based test organization. It leverages doubles for service isolation and factory-based test data generation. The implementation demonstrates effective use of RSpec’s subject and let declarations for clean test setup.

Technical Details

  • RSpec testing framework
  • Factory-based test data generation
  • Service double mocking
  • Rails test helper integration
  • Webhook delivery service isolation

Best Practices Demonstrated

The test suite exemplifies several testing best practices including proper test isolation, clear context organization, and effective use of test doubles. It maintains single responsibility per test while covering both happy path and edge cases systematically.

  • Clear context separation
  • Effective service mocking
  • Comprehensive state coverage
  • Clean test setup patterns

postalserver/postal

spec/lib/worker/jobs/process_webhook_requests_job_spec.rb

            
# frozen_string_literal: true

require "rails_helper"

module Worker
  module Jobs

    RSpec.describe ProcessWebhookRequestsJob do
      subject(:job) { described_class.new(logger: Postal.logger) }

      let(:mocked_service) { double("Service") }

      before do
        allow(WebhookDeliveryService).to receive(:new).and_return(mocked_service)
        allow(mocked_service).to receive(:call).with(no_args)
      end

      context "when there are no requests to process" do
        it "does nothing" do
          job.call
          expect(job.work_completed?).to be false
        end
      end

      context "when there is a unlocked request with no retry time" do
        it "delivers the request" do
          request = create(:webhook_request)
          job.call
          expect(WebhookDeliveryService).to have_received(:new).with(webhook_request: request)
          expect(job.work_completed?).to be true
        end
      end

      context "when there is an unlocked request with a retry time in the past" do
        it "delivers the request" do
          request = create(:webhook_request, retry_after: 1.minute.ago)
          job.call
          expect(WebhookDeliveryService).to have_received(:new).with(webhook_request: request)
          expect(job.work_completed?).to be true
        end
      end

      context "when there is an unlocked request with a retry time in the future" do
        it "does nothing" do
          create(:webhook_request, retry_after: 1.minute.from_now)
          job.call
          expect(job.work_completed?).to be false
        end
      end

      context "when there is a locked requested without a retry time" do
        it "does nothing" do
          create(:webhook_request, :locked)
          job.call
          expect(job.work_completed?).to be false
        end
      end
    end

  end
end