Files
openfoodnetwork/spec/services/order_cycles/webhook_service_spec.rb
David Cook a8490a9b11 Record the exact event time for the webhook
There might be a delay before it gets sent, so it's better to record the time the event occurred at.
It would have been simpler to just add it to the data hash, but I felt it was an important detail for an event and should be at the top level along with event name.

In the case of order cycle opening, this is the same as opened_at. I've included this in the payload for clarity too.
2025-03-25 10:38:30 +11:00

150 lines
5.1 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe OrderCycles::WebhookService do
let(:order_cycle) {
create(
:simple_order_cycle,
name: "Order cycle 1",
orders_open_at: Time.zone.parse("2022-09-19 09:00:00"),
opened_at: Time.zone.parse("2022-09-19 09:00:01"),
orders_close_at: Time.zone.parse("2022-09-19 17:00:00"),
coordinator:,
)
}
let(:coordinator) { create :distributor_enterprise, name: "Starship Enterprise" }
let(:at) { Time.zone.parse("2022-09-19 09:00:02") }
subject { OrderCycles::WebhookService.create_webhook_job(order_cycle, "order_cycle.opened", at) }
describe "creating payloads" do
it "doesn't create webhook payload for enterprise users" do
# The co-ordinating enterprise has a non-owner user with an endpoint.
# They shouldn't receive a notification.
coordinator_user = create(:user, enterprises: [coordinator])
coordinator_user.webhook_endpoints.create!(url: "http://coordinator_user_url")
expect{ subject }
.not_to enqueue_job(WebhookDeliveryJob).with("http://coordinator_user_url", any_args)
end
context "coordinator owner has endpoint configured" do
before do
coordinator.owner.webhook_endpoints.create! url: "http://coordinator_owner_url"
end
it "creates webhook payload for order cycle coordinator" do
expect{ subject }
.to enqueue_job(WebhookDeliveryJob).with("http://coordinator_owner_url", any_args)
end
it "creates webhook payload with details for the specified order cycle only" do
# The coordinating enterprise has another OC. It should be ignored.
order_cycle.dup.save
data = {
id: order_cycle.id,
name: "Order cycle 1",
orders_open_at: Time.zone.parse("2022-09-19 09:00:00"),
opened_at: Time.zone.parse("2022-09-19 09:00:01"),
orders_close_at: Time.zone.parse("2022-09-19 17:00:00"),
coordinator_id: coordinator.id,
coordinator_name: "Starship Enterprise",
}
expect{ subject }
.to enqueue_job(WebhookDeliveryJob).exactly(1).times
.with("http://coordinator_owner_url", "order_cycle.opened", hash_including(data), at:)
end
end
context "coordinator owner doesn't have endpoint configured" do
it "doesn't create webhook payload" do
expect{ subject }
.not_to enqueue_job(WebhookDeliveryJob)
end
end
describe "distributors" do
context "multiple distributors have owners with endpoint configured" do
let(:order_cycle) {
create(
:simple_order_cycle,
coordinator:,
distributors: two_distributors,
)
}
let(:two_distributors) {
(1..2).map do |i|
user = create(:user)
user.webhook_endpoints.create!(url: "http://distributor#{i}_owner_url")
create(:distributor_enterprise, owner: user)
end
}
it "creates webhook payload for each order cycle distributor" do
data = {
coordinator_id: order_cycle.coordinator_id,
coordinator_name: "Starship Enterprise",
}
expect{ subject }
.to enqueue_job(WebhookDeliveryJob).with("http://distributor1_owner_url",
"order_cycle.opened", hash_including(data),
at:)
.and enqueue_job(WebhookDeliveryJob).with("http://distributor2_owner_url",
"order_cycle.opened", hash_including(data),
at:)
end
end
context "distributor owner is same user as coordinator owner" do
let(:user) { coordinator.owner }
let(:order_cycle) {
create(
:simple_order_cycle,
coordinator:,
distributors: [create(:distributor_enterprise, owner: user)],
)
}
it "creates only one webhook payload for the user's endpoint" do
user.webhook_endpoints.create! url: "http://coordinator_owner_url"
expect{ subject }
.to enqueue_job(WebhookDeliveryJob).with("http://coordinator_owner_url", any_args)
end
end
end
describe "suppliers" do
context "supplier has owner with endpoint configured" do
let(:order_cycle) {
create(
:simple_order_cycle,
coordinator:,
suppliers: [supplier],
)
}
let(:supplier) {
user = create(:user)
user.webhook_endpoints.create!(url: "http://supplier_owner_url")
create(:supplier_enterprise, owner: user)
}
it "doesn't create a webhook payload for supplier owner" do
expect{ subject }
.not_to enqueue_job(WebhookDeliveryJob).with("http://supplier_owner_url", any_args)
end
end
end
end
context "without webhook subscribed to enterprise" do
it "doesn't create webhook payload" do
expect{ subject }
.not_to enqueue_job(WebhookDeliveryJob)
end
end
end