Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 65 additions & 9 deletions lib/decidim/term_customizer/context/job_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ module TermCustomizer
module Context
class JobContext < Base
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
def resolve!
# Figure out the organization and user through the job arguments if
# passed for the job.
Expand All @@ -14,7 +13,7 @@ def resolve!
@organization ||= organization_from_argument(arg)
@space ||= space_from_argument(arg)
@component ||= component_from_argument(arg)
user ||= arg if arg.is_a?(Decidim::User)
user ||= find_object_by_class(arg, Decidim::User)
end

# In case a component was found, define the space as the component
Expand All @@ -30,26 +29,83 @@ def resolve!
@organization ||= user.organization if user
end
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/PerceivedComplexity

protected

def organization_from_argument(arg)
return arg if arg.is_a?(Decidim::Organization)
org = find_object_by_class(arg, Decidim::Organization)

arg.organization if arg.respond_to?(:organization)
org || find_value_by_method(arg, :organization)
end

def space_from_argument(arg)
return arg if arg.is_a?(Decidim::Participable)
space = find_object_by_class(arg, Decidim::Participable)

arg.participatory_space if arg.respond_to?(:participatory_space)
space || find_value_by_method(arg, :participatory_space)
end

def component_from_argument(arg)
return arg if arg.is_a?(Decidim::Component)
component = find_object_by_class(arg, Decidim::Component)
return component if component

arg.component if arg.respond_to?(:component)
found = find_value_by_method(arg, :component)
return found if found.is_a?(Decidim::Component)

if defined?(Decidim::Forms::Questionnaire)
component = find_questionnaire_component(arg)
return component if component
end

nil
end

def find_questionnaire_component(arg)
questionnaire_component = find_object_by_class(arg, Decidim::Forms::Questionnaire)&.questionnaire_for
return questionnaire_component if questionnaire_component.is_a?(Decidim::Component)
return questionnaire_component.component if questionnaire_component.respond_to?(:component)

nil
end

def find_object_by_class(obj, klass, seen = {})
return obj if obj.is_a?(klass)
return nil if obj.nil?
return nil if seen[obj.__id__]

seen[obj.__id__] = true

values_from_iterable(obj).each do |item|
found = find_object_by_class(item, klass, seen)
return found if found
end

nil
end

def find_value_by_method(obj, method, seen = {})
return nil if obj.nil?
return nil if seen[obj.__id__]

seen[obj.__id__] = true
return obj.send(method) if obj.respond_to?(method)

values_from_iterable(obj).each do |item|
found = find_value_by_method(item, method, seen)
return found if found
end

nil
end

def values_from_iterable(obj)
case obj
when Hash
obj.values
when Array
obj
else
[]
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@

it "passes" do
task.reenable
expect { task.invoke("te") }.to output("Combined 1 file(s) into 'config/locales/te.yml'\nTranslations combined successfully!\n").to_stdout
check_no_errors_have_been_printed
expect { task.invoke("te") }
.to output("Combined 1 file(s) into 'config/locales/te.yml'\nTranslations combined successfully!\n").to_stdout
.and(not_output.to_stderr)
end

it "writes file correctly" do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@

it "passes" do
task.reenable
expect { task.invoke("te", "file:#{file_path}") }.to output("Combined 1 file(s) into 'config/locales/te.yml'\nTranslations combined successfully!\n").to_stdout
check_no_errors_have_been_printed
expect { task.invoke("te", "file:#{file_path}") }
.to output("Combined 1 file(s) into 'config/locales/te.yml'\nTranslations combined successfully!\n").to_stdout
.and(not_output.to_stderr)
end

it "writes file correctly" do
Expand Down
59 changes: 59 additions & 0 deletions spec/lib/decidim/term_customizer/context/job_context_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,39 @@
end
end

context "with user passed inside an array in the arguments" do
let(:user) { create(:user) }
let(:arguments) { [[user]] }

it "resolves the user's organization" do
expect(subject.organization).to be(user.organization)
expect(subject.space).to be_nil
expect(subject.component).to be_nil
end
end

context "with user passed inside a hash in the arguments" do
let(:user) { create(:user) }
let(:arguments) { [{ arg: user }] }

it "resolves the user's organization" do
expect(subject.organization).to be(user.organization)
expect(subject.space).to be_nil
expect(subject.component).to be_nil
end
end

context "with user passed inside a sub-hash in the arguments" do
let(:user) { create(:user) }
let(:arguments) { [{ job: { arg: user } }] }

it "resolves the user's organization" do
expect(subject.organization).to be(user.organization)
expect(subject.space).to be_nil
expect(subject.component).to be_nil
end
end

context "with participatory process passed in the arguments" do
let(:space) { create(:participatory_process, organization:) }
let(:arguments) { [organization, space] }
Expand Down Expand Up @@ -105,6 +138,32 @@
end
end

context "with a questionnaire passed in the arguments" do
let(:space) { create(:participatory_process, organization:) }
let(:questionnaire) { create(:questionnaire, questionnaire_for: component) }
let(:component) do
create(:component, manifest_name: :meetings, participatory_space: space)
end
let(:arguments) { [[questionnaire]] }

it "resolves the participatory space based on the questionnaire" do
expect(subject.organization).to be(organization)
expect(subject.space).to be(space)
expect(subject.component).to be(component)
end

context "and questionnaire is for an intermediary object" do
let(:questionnaire) { create(:questionnaire, questionnaire_for: meeting) }
let(:meeting) { create(:meeting, component: component) }

it "resolves the participatory space based on the questionnaire" do
expect(subject.organization).to be(organization)
expect(subject.space).to be(space)
expect(subject.component).to be(component)
end
end
end

context "with organization and space passed in the arguments" do
let(:other_organization) { create(:organization) }
let(:space) { create(:participatory_process, organization:) }
Expand Down
2 changes: 2 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

require "decidim/dev/test/base_spec_helper"

RSpec::Matchers.define_negated_matcher :not_output, :output

RSpec.configure do |config|
# Add extra traslation load path for the tests
I18n.load_path << File.join(__dir__, "fixtures", "locales", "en.yml")
Expand Down
Loading