Skip to content

Commit

Permalink
Fix/admin proposals answers import (#131)
Browse files Browse the repository at this point in the history
* fix: override private_body partial to add condition to show private body

* test: add system test

* test: update missing keys in i18n tasks file

* ci: update upload-artifact action

* ci: add imagemagick for tests

* ci: update ci again

* ci: add chrome version

* ci: update ci

* ci: updating again
  • Loading branch information
Stef-Rousset authored Feb 18, 2025
1 parent 8c2f272 commit 003d0f8
Show file tree
Hide file tree
Showing 4 changed files with 278 additions and 1 deletion.
6 changes: 5 additions & 1 deletion .github/workflows/ci_cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ jobs:
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ env.RUBY_VERSION }}
bundler-cache: true
bundler-cache: true
- run: |
sudo apt install libu2f-udev imagemagick
wget --no-verbose -O /tmp/chrome.deb https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${{env.CHROME_VERSION}}-1_amd64.deb
Expand All @@ -112,6 +112,8 @@ jobs:
- run: mkdir -p ./spec/tmp/screenshots
name: Create the screenshots folder
- uses: nanasess/setup-chromedriver@v2
with:
chromedriver-version: ${{ env.CHROME_VERSION }}
- run: bundle exec rake "test:run[exclude, spec/system/**/*_spec.rb, ${{ matrix.slice }}]"
name: RSpec
- run: ./.github/upload_coverage.sh decidim-app $GITHUB_EVENT_PATH
Expand Down Expand Up @@ -184,6 +186,8 @@ jobs:
- run: mkdir -p ./spec/tmp/screenshots
name: Create the screenshots folder
- uses: nanasess/setup-chromedriver@v2
with:
chromedriver-version: ${{ env.CHROME_VERSION }}
- run: bundle exec rake "test:run[include, spec/system/**/*_spec.rb, ${{ matrix.slice }}]"
name: RSpec
- run: ./.github/upload_coverage.sh decidim-app $GITHUB_EVENT_PATH
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div class="card-section" data-component="accordion" id="accordion-private_body">
<button class="card-divider-button" data-controls="panel-private_body" type="button">
<%= icon "arrow-right-s-line" %>
<h2 class="card-title">
<%= t "decidim.decidim_awesome.admin.proposal_custom_fields.private_body" %>
</h2>
</button>
<div id="panel-private_body">
<div class="component__show_private_data-grid">
<% if proposal.private_body %>
<div><%= Decidim::ContentProcessor.render_without_format(render_sanitized_content(proposal, :private_body)).html_safe %></div>
<% end %>
<% if proposal&.extra_fields&.private_body_updated_at %>
<div class="date_info">
<%= t("decidim.decidim_awesome.admin.proposal_custom_fields.private_data_last_update", time_ago: time_ago_in_words(proposal.extra_fields.private_body_updated_at)) if proposal.extra_fields.private_body.present? %>
<%= t("decidim.decidim_awesome.admin.proposal_custom_fields.private_data_last_remove", time_ago: time_ago_in_words(proposal.extra_fields.private_body_updated_at)) if proposal.extra_fields.private_body.blank? %>
<%= link_to t("decidim.decidim_awesome.admin.proposal_custom_fields.remove_private_data"), decidim_admin_decidim_awesome.maintenance_path(:private_data) if proposal.extra_fields.private_body_updated_at && proposal.extra_fields.private_body_updated_at < Decidim::DecidimAwesome.private_data_expiration_time.ago %>
</div>
<% end %>
</div>
</div>
</div>
1 change: 1 addition & 0 deletions config/i18n-tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ ignore_missing:
- decidim.budgets_importer.actions.import
- index.confirmed_orders_count
- decidim.proposals.proposals.index.{new_proposal,collaborative_drafts_list}
- decidim.decidim_awesome.admin.proposal_custom_fields.*
# Consider these keys used:
ignore_unused:
- faker.*
Expand Down
250 changes: 250 additions & 0 deletions spec/system/admin_edit_proposals_custom_fields_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
# frozen_string_literal: true

require "spec_helper"

describe "Admin edits proposals", type: :system do
let(:manifest_name) { "proposals" }
let(:organization) { participatory_process.organization }
let!(:user) { create(:user, :admin, :confirmed, organization: organization) }
let!(:config) { create(:awesome_config, organization: organization, var: :proposal_custom_fields, value: custom_fields) }
let!(:private_config) { create(:awesome_config, organization: organization, var: :proposal_private_custom_fields, value: private_custom_fields) }
let(:config_helper) { create(:awesome_config, organization: organization, var: :proposal_custom_field_bar) }
let(:private_config_helper) { create(:awesome_config, organization: organization, var: :proposal_private_custom_field_baz) }
let!(:constraint) { create(:config_constraint, awesome_config: config_helper, settings: { "participatory_space_manifest" => "participatory_processes", "participatory_space_slug" => slug }) }
let!(:private_constraint) { create(:config_constraint, awesome_config: private_config_helper, settings: { "participatory_space_manifest" => "participatory_processes" }) }
let(:slug) { participatory_process.slug }

let(:data1) { '{"type":"text","label":"Full Name","subtype":"text","className":"form-control","name":"text-1476748004559"}' }
let(:data2) { '{"type":"select","label":"Occupation","className":"form-control","name":"select-1476748006618","values":[{"label":"Street Sweeper","value":"option-1","selected":true},{"label":"Moth Man","value":"option-2"},{"label":"Chemist","value":"option-3"}]}' }
let(:data3) { '{"type":"textarea","label":"Short Bio","rows":"5","className":"form-control","name":"textarea-1476748007461"}' }
let(:private_data1) { '{"type":"text","label":"Phone Number","subtype":"text","className":"form-control","name":"text-1476748004579"}' }

let(:custom_fields) do
{
"foo" => "[#{data1},#{data2}]",
"bar" => "[#{data3}]"
}
end
let(:private_custom_fields) do
{
"baz" => "[#{private_data1}]"
}
end

let!(:proposal) do
create(:extended_proposal,
:official,
component: component,
body: {
en: '<xml><dl><dt>Bio</dt><dd id="textarea-1476748007461"><div>I shot the sheriff</div></dd></dl></xml>',
ca: '<xml><dl><dt>Bio</dt><dd id="textarea-1476748007461"><div>Jo disparo al sheriff</div></dd></dl></xml>'
})
end

include_context "when managing a component as an admin"

before do
visit_component_admin

proposal.update_private_body!('<xml><dl><dt>Phone Number</dt><dd id="text-1476748004579"><div>555-555-555</div></dd></dl></xml>')
end

context "when editing the proposal" do
before do
find("a.action-icon--edit-proposal").click
end

it "displays custom fields" do
expect(page).to have_content("Title")
expect(page).not_to have_content("Body")
expect(page).to have_content("Full Name")
expect(page).to have_content("Occupation")
expect(page).to have_content("Street Sweeper")
expect(page).to have_content("Short Bio")
expect(page).to have_xpath("//textarea[@class='form-control'][@id='textarea-1476748007461'][@user-data='I shot the sheriff']")
expect(page).not_to have_css(".form-error.is-visible")
expect(page).to have_content("This information won't be published")
within "#proposal-custom-field-private_body" do
expect(page).to have_content("Phone Number")
expect(page).to have_xpath("//input[@class='form-control'][@id='text-1476748004579'][@user-data='555-555-555']")
end

within "#proposal-body-tabs" do
click_link_or_button "Català"
expect(page).to have_xpath("//textarea[@class='form-control'][@id='textarea-1476748007461'][@user-data='Jo disparo al sheriff']")
end
end

context "and there are out of scope" do
let(:custom_fields) do
{
"bar" => "[#{data3}]"
}
end
let(:slug) { "another-slug" }

it "displays normal proposal editor" do
expect(page).to have_content("Title")
expect(page).to have_content("Body")
expect(page).not_to have_content("Full Name")
expect(page).not_to have_content("Occupation")
expect(page).not_to have_content("Street Sweeper")
expect(page).not_to have_content("Short Bio")
expect(page).to have_content("This information won't be published")
within "#proposal-custom-field-private_body" do
expect(page).to have_content("Phone Number")
end
end
end

context "and some are scoped to other places" do
let(:slug) { "another-slug" }

it "displays the scoped fields" do
expect(page).to have_content("Title")
expect(page).not_to have_content("Body")
expect(page).to have_content("Full Name")
expect(page).to have_content("Occupation")
expect(page).to have_content("Street Sweeper")
expect(page).not_to have_content("Short Bio")
expect(page).not_to have_css(".form-error.is-visible")
expect(page).to have_content("This information won't be published")
within "#proposal-custom-field-private_body" do
expect(page).to have_content("Phone Number")
end
end
end

context "when private fields are scoped to other places" do
let!(:private_constraint) { create(:config_constraint, awesome_config: private_config_helper, settings: { "participatory_space_manifest" => "assemblies" }) }

it "displays the scoped fields" do
expect(page).to have_content("Title")
expect(page).not_to have_content("Body")
expect(page).to have_content("Full Name")
expect(page).to have_content("Occupation")
expect(page).to have_content("Street Sweeper")
expect(page).to have_content("Short Bio")
expect(page).not_to have_css(".form-error.is-visible")
expect(page).not_to have_content("This information won't be published")
expect(page).not_to have_css("#proposal-custom-field-private_body")
expect(page).not_to have_content("Phone Number")
end
end

context "when creating the proposal" do
it "saves the proposal in XML" do
fill_in :proposal_title_en, with: "A far west character"
fill_in :"text-1476748004559", with: "Lucky Luke"
fill_in :"textarea-1476748007461", with: "I shot everything"

click_link_or_button "Update"

expect(Decidim::Proposals::Proposal.last.body["en"]).to include('<dd id="text-1476748004559" name="text"><div>Lucky Luke</div>')
expect(Decidim::Proposals::Proposal.last.body["en"]).to include('<dd id="textarea-1476748007461" name="textarea"><div>I shot everything</div></dd>')
end

context "and has multiple languages" do
it "saves the proposal in XML" do
fill_in :proposal_title_en, with: "A far west character"
fill_in :"text-1476748004559", with: "Lucky Luke"
fill_in :"textarea-1476748007461", with: "I shot everything"

within "#proposal-body-tabs" do
click_link_or_button "Català"
end

fill_in :"text-1476748004559", with: "Lucky Luke"
fill_in :"textarea-1476748007461", with: "Li agrada disparar"

click_link_or_button "Update"

expect(Decidim::Proposals::Proposal.last.body["en"]).to include('<dd id="text-1476748004559" name="text"><div>Lucky Luke</div>')
expect(Decidim::Proposals::Proposal.last.body["en"]).to include('<dd id="textarea-1476748007461" name="textarea"><div>I shot everything</div></dd>')
expect(Decidim::Proposals::Proposal.last.body["ca"]).to include('<dd id="textarea-1476748007461" name="textarea"><div>Li agrada disparar</div></dd>')
end
end
end
end

context "when answering the proposal" do
it "displays custom fields" do
find("a.action-icon--show-proposal").click
expect(page).to have_content("Bio")
within "#textarea-1476748007461" do
expect(page).to have_content("I shot the sheriff")
end
click_link_or_button "Private body"
expect(page).to have_content("Phone Number")
within "#text-1476748004579" do
expect(page).to have_content("555-555-555")
end
expect(page).to have_content("This data was last updated less than a minute ago.")
expect(page).not_to have_content("You might want to remove it")
end

context "when private data is required to be removed" do
before do
# rubocop:disable Rails/SkipsModelValidations
proposal.extra_fields.update_column(:private_body_updated_at, 4.months.ago)
# rubocop:enable Rails/SkipsModelValidations
find("a.action-icon--show-proposal").click
end

it "displays a warning" do
click_link_or_button "Private body"
expect(page).to have_content("Phone Number")
expect(page).to have_content("This data was last updated 4 months ago.")
expect(page).to have_content("You might want to remove it")
end
end

context "when private data is removed" do
before do
proposal.extra_fields.update(private_body: nil)
find("a.action-icon--show-proposal").click
end

it "shows destroyed date" do
click_link_or_button "Private body"
expect(page).not_to have_content("Phone Number")
expect(page).to have_content("This data was destroyed less than a minute ago.")
expect(page).not_to have_content("555-555-555")
expect(page).not_to have_content("You might want to remove it")
end
end

context "when no private data, nor private data last update is present" do
before do
# rubocop:disable Rails/SkipsModelValidations
proposal.extra_fields.update_column(:private_body, nil)
proposal.extra_fields.update_column(:private_body_updated_at, nil)
# rubocop:enable Rails/SkipsModelValidations
find("a.action-icon--show-proposal").click
end

it "does not display the private data" do
click_link_or_button "Private body"
expect(page).not_to have_content("Phone Number")
expect(page).not_to have_content("This data was last updated")
expect(page).not_to have_content("This data was last destroyed")
expect(page).not_to have_content("You might want to remove it")
end
end

context "when private fields are scoped to other places" do
let!(:private_constraint) { create(:config_constraint, awesome_config: private_config_helper, settings: { "participatory_space_manifest" => "assemblies" }) }

it "does not display private custom fields" do
find("a.action-icon--show-proposal").click
expect(page).to have_content("Bio")
within "#textarea-1476748007461" do
expect(page).to have_content("I shot the sheriff")
end
expect(page).not_to have_content("Private body")
expect(page).not_to have_content("Phone Number")
expect(page).not_to have_content("555-555-555")
end
end
end
end

0 comments on commit 003d0f8

Please sign in to comment.