-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
backport: Answer Initiatives Notifications (#464)
* backport: Add initiative answers notifications * lint: Rubocop fixes * fix: Add some tests and fix i18n * fix: Delete factory_bot_spec as we didn't do any customization of the factories * fix: Add new tests
- Loading branch information
Showing
12 changed files
with
400 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# frozen-string_literal: true | ||
|
||
module Decidim | ||
module Initiatives | ||
class AnswerInitiativeEvent < Decidim::Events::SimpleEvent | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
lib/extends/commands/decidim/initiatives/admin/update_initiative_answer_extends.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# frozen_string_literal: true | ||
|
||
module UpdateInitiativeAnswerExtends | ||
def call | ||
return broadcast(:invalid) if form.invalid? | ||
|
||
@initiative = Decidim.traceability.update!( | ||
initiative, | ||
current_user, | ||
attributes | ||
) | ||
notify_initiative_is_extended if @notify_extended | ||
notify_initiative_is_answered if @notify_answered | ||
broadcast(:ok, initiative) | ||
rescue ActiveRecord::RecordInvalid | ||
broadcast(:invalid, initiative) | ||
end | ||
|
||
private | ||
|
||
def attributes | ||
attrs = { | ||
answer: form.answer, | ||
answer_url: form.answer_url | ||
} | ||
|
||
attrs[:answered_at] = Time.current if form.answer.present? | ||
|
||
if form.signature_dates_required? | ||
attrs[:signature_start_date] = form.signature_start_date | ||
attrs[:signature_end_date] = form.signature_end_date | ||
|
||
if initiative.published? && form.signature_end_date != initiative.signature_end_date && | ||
form.signature_end_date > initiative.signature_end_date | ||
@notify_extended = true | ||
end | ||
end | ||
|
||
@notify_answered = form.answer != initiative.answer && !form.answer.values.all?(&:blank?) | ||
|
||
attrs | ||
end | ||
|
||
def notify_initiative_is_answered | ||
Decidim::EventsManager.publish( | ||
event: "decidim.events.initiatives.initiative_answered", | ||
event_class: Decidim::Initiatives::AnswerInitiativeEvent, | ||
resource: initiative, | ||
followers: initiative.followers | ||
) | ||
end | ||
end | ||
|
||
Decidim::Initiatives::Admin::UpdateInitiativeAnswer.class_eval do | ||
prepend UpdateInitiativeAnswerExtends | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# frozen_string_literal: true | ||
|
||
module IconHelperExtends | ||
def resource_icon(resource, options = {}) | ||
if resource.instance_of?(Decidim::Initiative) | ||
icon "initiatives", options | ||
elsif resource.instance_of?(Decidim::Comments::Comment) | ||
icon "comment-square", options | ||
elsif resource.respond_to?(:component) && resource.component | ||
component_icon(resource.component, options) | ||
elsif resource.respond_to?(:manifest) && resource.manifest | ||
manifest_icon(resource.manifest, options) | ||
elsif resource.is_a?(Decidim::User) | ||
icon "person", options | ||
else | ||
icon "bell", options | ||
end | ||
end | ||
end | ||
|
||
Decidim::IconHelper.module_eval do | ||
prepend(IconHelperExtends) | ||
end |
80 changes: 80 additions & 0 deletions
80
spec/commands/decidim/initiatives/admin/update_initiative_answer_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# frozen_string_literal: true | ||
|
||
require "spec_helper" | ||
|
||
module Decidim | ||
module Initiatives | ||
module Admin | ||
describe UpdateInitiativeAnswer do | ||
let(:form_klass) { Decidim::Initiatives::Admin::InitiativeAnswerForm } | ||
|
||
context "when valid data" do | ||
it_behaves_like "update an initiative answer" do | ||
context "when the user is an admin" do | ||
let!(:current_user) { create(:user, :admin, organization: initiative.organization) } | ||
let!(:follower) { create(:user, organization: organization) } | ||
let!(:follow) { create(:follow, followable: initiative, user: follower) } | ||
|
||
it "notifies the followers for extension and answer" do | ||
expect(Decidim::EventsManager) | ||
.to receive(:publish) | ||
.with( | ||
event: "decidim.events.initiatives.initiative_extended", | ||
event_class: Decidim::Initiatives::ExtendInitiativeEvent, | ||
resource: initiative, | ||
followers: [follower] | ||
) | ||
.ordered | ||
expect(Decidim::EventsManager) | ||
.to receive(:publish) | ||
.with( | ||
event: "decidim.events.initiatives.initiative_answered", | ||
event_class: Decidim::Initiatives::AnswerInitiativeEvent, | ||
resource: initiative, | ||
followers: [follower] | ||
) | ||
.ordered | ||
|
||
command.call | ||
end | ||
|
||
context "when the signature end time is not modified" do | ||
let(:signature_end_date) { initiative.signature_end_date } | ||
|
||
it "doesn't notify the followers" do | ||
expect(Decidim::EventsManager).not_to receive(:publish).with( | ||
event: "decidim.events.initiatives.initiative_extended", | ||
event_class: Decidim::Initiatives::ExtendInitiativeEvent, | ||
resource: initiative, | ||
followers: [follower] | ||
) | ||
|
||
command.call | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
context "when validation failure" do | ||
let(:organization) { create(:organization) } | ||
let!(:initiative) { create(:initiative, organization: organization) } | ||
let!(:form) do | ||
form_klass | ||
.from_model(initiative) | ||
.with_context(current_organization: organization, initiative: initiative) | ||
end | ||
|
||
let(:command) { described_class.new(initiative, form, initiative.author) } | ||
|
||
it "broadcasts invalid" do | ||
expect(initiative).to receive(:valid?) | ||
.at_least(:once) | ||
.and_return(false) | ||
expect { command.call }.to broadcast :invalid | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
# frozen_string_literal: true | ||
|
||
require "spec_helper" | ||
|
||
module Decidim | ||
describe IconHelper do | ||
describe "#component_icon" do | ||
let(:component) do | ||
create(:component, manifest_name: :dummy) | ||
end | ||
|
||
describe "when the component has no icon" do | ||
before do | ||
allow(component.manifest).to receive(:icon).and_return(nil) | ||
end | ||
|
||
it "returns a fallback" do | ||
result = helper.component_icon(component) | ||
expect(result).to include("question-mark") | ||
end | ||
end | ||
|
||
describe "when the component has icon" do | ||
it "returns the icon" do | ||
result = helper.component_icon(component) | ||
expect(result).to eq <<~SVG.strip | ||
<svg class="icon external-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36.02 36.02"><circle cx="18.01" cy="18.01" r="15.75" fill="none" stroke="#2ecc71" stroke-width="4"/><circle cx="18.01" cy="18.01" r="11.25" fill="none" stroke="#08BCD0" stroke-width="4"/></svg> | ||
SVG | ||
end | ||
|
||
context "with role attribute specified" do | ||
it "implements role attribute" do | ||
result = helper.component_icon(component, role: "img") | ||
expect(result).to eq <<~SVG.strip | ||
<svg class="icon external-icon" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36.02 36.02"><circle cx="18.01" cy="18.01" r="15.75" fill="none" stroke="#2ecc71" stroke-width="4"/><circle cx="18.01" cy="18.01" r="11.25" fill="none" stroke="#08BCD0" stroke-width="4"/></svg> | ||
SVG | ||
end | ||
end | ||
|
||
context "with no role attribute specified" do | ||
it "doesn't implement role attribute" do | ||
result = helper.component_icon(component) | ||
expect(result).to eq <<~SVG.strip | ||
<svg class="icon external-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36.02 36.02"><circle cx="18.01" cy="18.01" r="15.75" fill="none" stroke="#2ecc71" stroke-width="4"/><circle cx="18.01" cy="18.01" r="11.25" fill="none" stroke="#08BCD0" stroke-width="4"/></svg> | ||
SVG | ||
end | ||
end | ||
end | ||
|
||
describe "resource_icon" do | ||
let(:result) { helper.resource_icon(resource) } | ||
|
||
context "when it has a component" do | ||
let(:resource) { build :dummy_resource } | ||
|
||
it "renders the component icon" do | ||
expect(helper).to receive(:component_icon).with(resource.component, {}) | ||
|
||
result | ||
end | ||
end | ||
|
||
context "when it has a manifest" do | ||
let(:resource) { build(:component, manifest_name: :dummy) } | ||
|
||
it "renders the manifest icon" do | ||
expect(helper).to receive(:manifest_icon).with(resource.manifest, {}) | ||
|
||
result | ||
end | ||
end | ||
|
||
context "when it is a user" do | ||
let(:resource) { build :user } | ||
|
||
it "renders a person icon" do | ||
expect(result).to include("svg#icon-person") | ||
end | ||
end | ||
|
||
context "when the resource component and manifest are nil" do | ||
let(:resource) { build :dummy_resource } | ||
|
||
before do | ||
allow(resource).to receive(:component).and_return(nil) | ||
end | ||
|
||
it "renders a generic icon" do | ||
expect(result).to include("svg#icon-bell") | ||
end | ||
end | ||
|
||
context "when the manifest icon is nil" do | ||
let(:resource) { build(:component, manifest_name: :dummy) } | ||
|
||
before do | ||
allow(resource.manifest).to receive(:icon).and_return(nil) | ||
end | ||
|
||
it "renders a generic icon" do | ||
expect(result).to include("svg#icon-question-mark") | ||
end | ||
end | ||
|
||
context "when the resource is a comment" do | ||
let(:resource) { build :comment } | ||
|
||
it "renders a comment icon" do | ||
expect(result).to include("svg#icon-comment-square") | ||
end | ||
end | ||
|
||
context "when the resource is an initiative" do | ||
let(:resource) { build :initiative } | ||
|
||
it "renders an initiative icon" do | ||
expect(result).to include("svg#icon-initiatives") | ||
end | ||
end | ||
|
||
context "and in other cases" do | ||
let(:resource) { "Something" } | ||
|
||
it "renders a generic icon" do | ||
expect(result).to include("svg#icon-bell") | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.