0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-06 10:47:18 +08:00
discourse/plugins/discourse-calendar/spec/services/discourse_post_event/invite_spec.rb
Renato Atilio c983787daa
DEV: Extract mutating EventsController actions into services (#41053)
Move the `invite`, `destroy`, `bulk_invite` and `csv_bulk_invite`
actions of `DiscoursePostEvent::EventsController` into one service per
endpoint:

- `DiscoursePostEvent::Invite`
- `DiscoursePostEvent::DestroyEvent`
- `DiscoursePostEvent::BulkInvite`
- `DiscoursePostEvent::CsvBulkInvite`

CSV row parsing lives in `DiscoursePostEvent::Action::ParseInviteesCsv`.

Behaviour is preserved exactly. Notably:

- Input presence (invitees/file) is enforced via policies after the
authorization policies, so unauthorized requests still return 403 rather
than 400/422.
- The CSV endpoint renders every outcome inside `hijack` instead of
raising, since exceptions raised there would surface as a 500.
- `destroy` builds the webhook payload from live state before deleting
the event, then enqueues the webhook after the deletion commits.
2026-06-24 18:45:06 -03:00

63 lines
1.8 KiB
Ruby
Vendored

# frozen_string_literal: true
RSpec.describe(DiscoursePostEvent::Invite) do
describe described_class::Contract, type: :model do
it { is_expected.to validate_presence_of(:event_id) }
end
describe ".call" do
subject(:result) { described_class.call(params:, **dependencies) }
fab!(:admin, :admin)
fab!(:topic) { Fabricate(:topic, user: admin) }
fab!(:post) { Fabricate(:post, user: admin, topic: topic) }
fab!(:event) { Fabricate(:event, post: post) }
fab!(:invited_user, :user)
let(:params) { { event_id: event.id, invites: [invited_user.username] } }
let(:dependencies) { { guardian: admin.guardian } }
before do
Jobs.run_immediately!
SiteSetting.calendar_enabled = true
SiteSetting.discourse_post_event_enabled = true
end
context "when contract is invalid" do
let(:params) { { event_id: nil, invites: [invited_user.username] } }
it { is_expected.to fail_a_contract }
end
context "when event does not exist" do
let(:params) { { event_id: -1, invites: [invited_user.username] } }
it { is_expected.to fail_to_find_a_model(:event) }
end
context "when user cannot act on the event" do
fab!(:other_user, :user)
let(:dependencies) { { guardian: other_user.guardian } }
it { is_expected.to fail_a_policy(:can_act_on_event) }
end
context "when everything is valid" do
it { is_expected.to run_successfully }
it "notifies the invited users" do
expect { result }.to change { invited_user.notifications.count }.by(1)
end
end
context "when invites is empty" do
let(:params) { { event_id: event.id, invites: [] } }
it { is_expected.to run_successfully }
it "notifies no one" do
expect { result }.not_to change { Notification.count }
end
end
end
end