Merge pull request #5989 from consuldemocracy/nested-documentable-specs

Make nested documentable specs faster
This commit is contained in:
Sebastia
2025-06-10 09:30:18 +02:00
committed by GitHub
16 changed files with 447 additions and 681 deletions

View File

@@ -0,0 +1,37 @@
require "rails_helper"
describe Documents::DocumentComponent do
let(:user) { create(:user) }
let(:proposal) { create(:proposal, author: user) }
let(:document) { create(:document, documentable: proposal) }
let(:component) { Documents::DocumentComponent.new(document, show_destroy_link: true) }
describe "Delete document button" do
it "is not shown when no user is logged in" do
render_inline component
expect(page).not_to have_button "Delete document"
end
it "is shown when the author is logged in" do
sign_in(user)
render_inline component
expect(page).to have_button "Delete document"
end
it "is not shown when an administrator that isn't the author is logged in", :admin do
render_inline component
expect(page).not_to have_button "Delete document"
end
it "is not shown when a user that isn't the author is logged in" do
login_as(create(:user))
render_inline component
expect(page).not_to have_button "Delete document"
end
end
end

View File

@@ -1,107 +0,0 @@
shared_examples "documentable" do |documentable_factory_name, documentable_path, documentable_path_arguments|
let(:user) { create(:user) }
let(:arguments) { {} }
let(:documentable) { create(documentable_factory_name, author: user) }
let!(:document) { create(:document, documentable: documentable, user: documentable.author) }
before do
documentable_path_arguments.each do |argument_name, path_to_value|
arguments.merge!("#{argument_name}": documentable.send(path_to_value))
end
end
context "Show documents" do
scenario "Download action should be availabe to anyone and open in the same tab" do
visit send(documentable_path, arguments)
within "#documents" do
expect(page).to have_link text: document.title
expect(page).to have_css "a[rel=nofollow]", text: document.title
expect(page).not_to have_css "a[target=_blank]"
end
end
describe "Destroy action" do
scenario "Should not be able when no user logged in" do
visit send(documentable_path, arguments)
expect(page).not_to have_button "Delete document"
end
scenario "Should be able when documentable author is logged in" do
login_as documentable.author
visit send(documentable_path, arguments)
expect(page).to have_button "Delete document"
end
scenario "Administrators cannot destroy documentables they have not authored", :admin do
visit send(documentable_path, arguments)
expect(page).not_to have_button "Delete document"
end
scenario "Users cannot destroy documentables they have not authored" do
login_as(create(:user))
visit send(documentable_path, arguments)
expect(page).not_to have_button "Delete document"
end
end
describe "When allow attached documents setting is enabled" do
before do
Setting["feature.allow_attached_documents"] = true
end
scenario "Documents list should be available" do
login_as(user)
visit send(documentable_path, arguments)
expect(page).to have_css("#documents")
expect(page).to have_content("Documents (1)")
end
scenario "Documents list increase documents number" do
create(:document, documentable: documentable, user: documentable.author)
login_as(user)
visit send(documentable_path, arguments)
expect(page).to have_css("#documents")
expect(page).to have_content("Documents (2)")
end
end
describe "When allow attached documents setting is disabled" do
before do
Setting["feature.allow_attached_documents"] = false
end
scenario "Documents list should not be available" do
login_as(create(:user))
visit send(documentable_path, arguments)
expect(page).not_to have_css("#documents")
end
end
end
context "Destroy" do
scenario "Should show success notice after successful document upload" do
login_as documentable.author
visit send(documentable_path, arguments)
within "#document_#{document.id}" do
accept_confirm { click_button "Delete document" }
end
expect(page).to have_content "Document was deleted successfully."
expect(page).not_to have_content "Documents (0)"
within "##{ActionView::RecordIdentifier.dom_id(documentable)}" do
expect(page).to have_css "h1", text: documentable.title
end
end
end
end

View File

@@ -21,7 +21,7 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name,
do_login_for user, management: management do_login_for user, management: management
visit send(mappable_new_path, arguments) visit send(mappable_new_path, arguments)
send("fill_in_#{mappable_factory_name}_form") send("fill_in_#{mappable_factory_name}")
within ".map-location" do within ".map-location" do
expect(page).not_to have_css(".map-icon") expect(page).not_to have_css(".map-icon")
@@ -32,7 +32,7 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name,
do_login_for user, management: management do_login_for user, management: management
visit send(mappable_new_path, arguments) visit send(mappable_new_path, arguments)
send("fill_in_#{mappable_factory_name}_form") send("fill_in_#{mappable_factory_name}")
find("#new_map_location").click find("#new_map_location").click
within ".map-location" do within ".map-location" do
@@ -44,7 +44,7 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name,
do_login_for user, management: management do_login_for user, management: management
visit send(mappable_new_path, arguments) visit send(mappable_new_path, arguments)
send("fill_in_#{mappable_factory_name}_form") send("fill_in_#{mappable_factory_name}")
find("#new_map_location").click find("#new_map_location").click
send("submit_#{mappable_factory_name}_form") send("submit_#{mappable_factory_name}_form")
@@ -57,7 +57,7 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name,
do_login_for user, management: management do_login_for user, management: management
visit send(mappable_new_path, arguments) visit send(mappable_new_path, arguments)
send("fill_in_#{mappable_factory_name}_form") send("fill_in_#{mappable_factory_name}")
expect(page).to have_css ".map-location" expect(page).to have_css ".map-location"
send("submit_#{mappable_factory_name}_form") send("submit_#{mappable_factory_name}_form")
@@ -69,7 +69,7 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name,
do_login_for user, management: management do_login_for user, management: management
visit send(mappable_new_path, arguments) visit send(mappable_new_path, arguments)
send("fill_in_#{mappable_factory_name}_form") send("fill_in_#{mappable_factory_name}")
expect(page).not_to have_css ".map-location" expect(page).not_to have_css ".map-location"
send("submit_#{mappable_factory_name}_form") send("submit_#{mappable_factory_name}_form")
@@ -171,7 +171,7 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name,
do_login_for user, management: management do_login_for user, management: management
visit send(mappable_new_path, arguments) visit send(mappable_new_path, arguments)
send("fill_in_#{mappable_factory_name}_form") send("fill_in_#{mappable_factory_name}")
send("submit_#{mappable_factory_name}_form") send("submit_#{mappable_factory_name}_form")
expect(page).not_to have_content "Map location can't be blank" expect(page).not_to have_content "Map location can't be blank"

View File

@@ -1,318 +0,0 @@
shared_examples "nested documentable" do |login_as_name, documentable_factory_name, path,
documentable_path_arguments, fill_resource_method_name,
submit_button, documentable_success_notice, management: false|
let!(:administrator) { create(:user) }
let!(:user) { create(:user, :level_two) }
let!(:arguments) { {} }
if documentable_factory_name == "dashboard_action"
let!(:documentable) { create(documentable_factory_name) }
else
let!(:documentable) { create(documentable_factory_name, author: user) }
end
let!(:user_to_login) { send(login_as_name) }
let(:management) { management }
before do
create(:administrator, user: administrator)
documentable_path_arguments&.each do |argument_name, path_to_value|
arguments.merge!("#{argument_name}": documentable.send(path_to_value))
end
end
describe "at #{path}" do
scenario "Should show new document link when max documents allowed limit is not reached" do
do_login_for user_to_login, management: management
visit send(path, arguments)
expect(page).to have_link id: "new_document_link"
end
scenario "Should not show new document link when
documentable max documents allowed limit is reached" do
do_login_for user_to_login, management: management
visit send(path, arguments)
documentable.class.max_documents_allowed.times.each do
click_link "Add new document"
end
expect(page).not_to have_css "#new_document_link"
end
scenario "Should not show max documents warning when no documents added" do
do_login_for user_to_login, management: management
visit send(path, arguments)
expect(page).not_to have_css ".max-documents-notice"
end
scenario "Should show max documents warning when max documents allowed limit is reached" do
do_login_for user_to_login, management: management
visit send(path, arguments)
documentable.class.max_documents_allowed.times.each do
documentable_attach_new_file(file_fixture("empty.pdf"))
end
expect(page).to have_css ".max-documents-notice"
expect(page).to have_content "Remove document"
end
scenario "Should hide max documents warning after any document removal" do
do_login_for user_to_login, management: management
visit send(path, arguments)
documentable.class.max_documents_allowed.times.each do
click_link "Add new document"
end
all("a", text: "Cancel").last.click
expect(page).not_to have_css ".max-documents-notice"
end
scenario "Should update nested document file name after choosing a file" do
do_login_for user_to_login, management: management
visit send(path, arguments)
click_link "Add new document"
within "#nested-documents" do
attach_file "Choose document", file_fixture("empty.pdf")
expect(page).to have_css ".loading-bar.complete"
end
expect(page).to have_css ".file-name", text: "empty.pdf"
end
scenario "Should update nested document file title with
file name after choosing a file when no title defined" do
do_login_for user_to_login, management: management
visit send(path, arguments)
documentable_attach_new_file(file_fixture("empty.pdf"))
expect_document_has_title(0, "empty.pdf")
end
scenario "Should not update nested document file title with
file name after choosing a file when title already defined" do
do_login_for user_to_login, management: management
visit send(path, arguments)
click_link "Add new document"
within "#nested-documents" do
input = find("input[name$='[title]']")
fill_in input[:id], with: "My Title"
attach_file "Choose document", file_fixture("empty.pdf")
expect(page).to have_css ".loading-bar.complete"
end
expect_document_has_title(0, "My Title")
end
scenario "Should update loading bar style after valid file upload" do
do_login_for user_to_login, management: management
visit send(path, arguments)
documentable_attach_new_file(file_fixture("empty.pdf"))
expect(page).to have_css ".loading-bar.complete"
end
scenario "Should update loading bar style after invalid file upload" do
do_login_for user_to_login, management: management
visit send(path, arguments)
documentable_attach_new_file(file_fixture("logo_header.gif"), false)
expect(page).to have_css ".loading-bar.errors"
end
scenario "Should update document cached_attachment field after valid file upload" do
do_login_for user_to_login, management: management
visit send(path, arguments)
click_link "Add new document"
cached_attachment_field = find("input[name$='[cached_attachment]']", visible: :hidden)
expect(cached_attachment_field.value).to be_empty
attach_file "Choose document", file_fixture("empty.pdf")
expect(page).to have_css(".loading-bar.complete")
expect(cached_attachment_field.value).not_to be_empty
end
scenario "Should not update document cached_attachment field after invalid file upload" do
do_login_for user_to_login, management: management
visit send(path, arguments)
documentable_attach_new_file(file_fixture("logo_header.gif"), false)
cached_attachment_field = find("input[name$='[cached_attachment]']", visible: :hidden)
expect(cached_attachment_field.value).to be_empty
end
scenario "Should show document errors after documentable submit with
empty document fields" do
do_login_for user_to_login, management: management
visit send(path, arguments)
click_link "Add new document"
click_button submit_button
within "#nested-documents .document-fields" do
expect(page).to have_content("can't be blank", count: 2)
end
end
scenario "Should delete document after valid file upload and click on remove button" do
do_login_for user_to_login, management: management
visit send(path, arguments)
documentable_attach_new_file(file_fixture("empty.pdf"))
click_link "Remove document"
expect(page).not_to have_css("#nested-documents .document-fields")
end
scenario "Should show successful notice when
resource filled correctly without any nested documents" do
do_login_for user_to_login, management: management
visit send(path, arguments)
send(fill_resource_method_name) if fill_resource_method_name
click_button submit_button
expect(page).to have_content documentable_success_notice
end
scenario "Should show successful notice when
resource filled correctly and after valid file uploads" do
do_login_for user_to_login, management: management
visit send(path, arguments)
send(fill_resource_method_name) if fill_resource_method_name
documentable_attach_new_file(file_fixture("empty.pdf"))
click_button submit_button
expect(page).to have_content documentable_success_notice
end
scenario "Should show new document after successful creation with one uploaded file",
unless: documentable_factory_name == "dashboard_action" do
do_login_for user_to_login, management: management
visit send(path, arguments)
send(fill_resource_method_name) if fill_resource_method_name
documentable_attach_new_file(file_fixture("empty.pdf"))
click_button submit_button
expect(page).to have_content documentable_success_notice
documentable_redirected_to_resource_show_or_navigate_to
expect(page).to have_content "Documents"
expect(page).to have_content "empty.pdf"
# Review
# Doble check why the file is stored with a name different to empty.pdf
expect(page).to have_link href: /.pdf\Z/
end
scenario "Should show resource with new document after successful creation with
maximum allowed uploaded files", unless: documentable_factory_name == "dashboard_action" do
do_login_for user_to_login, management: management
visit send(path, arguments)
send(fill_resource_method_name) if fill_resource_method_name
%w[clippy empty logo].take(documentable.class.max_documents_allowed).each do |filename|
documentable_attach_new_file(file_fixture("#{filename}.pdf"))
end
click_button submit_button
expect(page).to have_content documentable_success_notice
documentable_redirected_to_resource_show_or_navigate_to
expect(page).to have_content "Documents (#{documentable.class.max_documents_allowed})"
end
if path.include? "edit"
scenario "Should show persisted documents and remove nested_field" do
create(:document, documentable: documentable)
do_login_for user_to_login, management: management
visit send(path, arguments)
expect(page).to have_css ".document-fields", count: 1
end
scenario "Should not show add document button when
documentable has reached maximum of documents allowed" do
create_list(:document, documentable.class.max_documents_allowed, documentable: documentable)
do_login_for user_to_login, management: management
visit send(path, arguments)
expect(page).not_to have_css "#new_document_link"
end
scenario "Should show add document button after destroy one document" do
create_list(:document, documentable.class.max_documents_allowed, documentable: documentable)
do_login_for user_to_login, management: management
visit send(path, arguments)
last_document = all("#nested-documents .document-fields").last
within last_document do
click_link "Remove document"
end
expect(page).to have_link id: "new_document_link"
end
scenario "Should remove nested field after remove document" do
create(:document, documentable: documentable)
do_login_for user_to_login, management: management
visit send(path, arguments)
click_link "Remove document"
expect(page).not_to have_css ".document-fields"
end
scenario "Same attachment URL after editing the title" do
do_login_for user_to_login, management: management
visit send(path, arguments)
documentable_attach_new_file(file_fixture("empty.pdf"))
within_fieldset("Documents") { fill_in "Title", with: "Original" }
click_button submit_button
expect(page).to have_content documentable_success_notice
original_url = find_link(text: "Original")[:href]
visit send(path, arguments)
within_fieldset("Documents") { fill_in "Title", with: "Updated" }
click_button submit_button
expect(page).to have_content documentable_success_notice
expect(find_link(text: "Updated")[:href]).to eq original_url
end
end
describe "When allow attached documents setting is disabled" do
before do
Setting["feature.allow_attached_documents"] = false
end
scenario "Add new document button should not be available" do
do_login_for user_to_login, management: management
visit send(path, arguments)
expect(page).not_to have_content("Add new document")
end
end
end
end

View File

@@ -2,14 +2,13 @@ Dir["./spec/support/common_actions/*.rb"].each { |f| require f }
Dir["./spec/support/common_actions/custom/*.rb"].each { |f| require f } Dir["./spec/support/common_actions/custom/*.rb"].each { |f| require f }
module CommonActions module CommonActions
include Attachables
include Budgets include Budgets
include Comments include Comments
include Cookies include Cookies
include Debates include Debates
include Documents
include Emails include Emails
include GraphQLAPI include GraphQLAPI
include Images
include Maps include Maps
include Notifications include Notifications
include Polls include Polls
@@ -43,12 +42,24 @@ module CommonActions
end end
def fill_in_proposal def fill_in_proposal
fill_in_new_proposal_title with: "Help refugees" fill_in_new_proposal_title with: "Proposal title"
fill_in "Proposal summary", with: "In summary, what we want is..." fill_in "Proposal summary", with: "Proposal summary"
fill_in_ckeditor "Proposal text", with: "This is very important because..." check :proposal_terms_of_service
fill_in "External video URL", with: "https://www.youtube.com/watch?v=yPQfcG-eimk" end
fill_in "Full name of the person submitting the proposal", with: "Isabel Garcia"
check "I agree to the Privacy Policy and the Terms and conditions of use" def fill_in_budget
fill_in "Name", with: "Budget name"
end
def fill_in_dashboard_action
fill_in :dashboard_action_title, with: "Dashboard title"
fill_in_ckeditor "Description", with: "Dashboard description"
end
def fill_in_budget_investment
fill_in_new_investment_title with: "Budget investment title"
fill_in_ckeditor "Description", with: "Budget investment description"
check :budget_investment_terms_of_service
end end
def fill_in_new_proposal_title(with:) def fill_in_new_proposal_title(with:)

View File

@@ -0,0 +1,91 @@
module Attachables
def imageable_attach_new_file(path, success: true)
attach_new_file("Add image", "nested-image", "image", "Choose image", path, success)
end
def documentable_attach_new_file(path, success: true)
attach_new_file("Add new document", "nested-documents", "document", "Choose document", path, success)
end
def attach_new_file(link_text, wrapper_id, field_class, input_label, path, success)
click_link link_text
within "##{wrapper_id}" do
attach_file input_label, path
within ".#{field_class}-fields" do
if success
expect(page).to have_css ".loading-bar.complete"
else
expect(page).to have_css ".loading-bar.errors"
end
end
end
end
def admin_section?(path)
path.starts_with?("/admin/")
end
def management_section?(path)
path.starts_with?("/management/")
end
def edit_path?(path)
path.ends_with?("/edit")
end
def fill_in_required_fields(factory, path)
return if edit_path?(path)
case factory
when :budget then fill_in_budget
when :budget_investment then fill_in_budget_investment
when :dashboard_action then fill_in_dashboard_action
when :proposal then fill_in_proposal
end
end
def attachable_path_for(factory, attachable)
case factory
when :budget then new_admin_budgets_wizard_budget_path
when :budget_investment
[
new_budget_investment_path(budget_id: attachable.budget_id),
new_management_budget_investment_path(budget_id: attachable.budget_id)
].sample
when :dashboard_action then new_admin_dashboard_action_path
when :future_poll_question_option then new_admin_option_image_path(option_id: attachable.id)
when :proposal then [new_proposal_path, edit_proposal_path(attachable)].sample
end
end
def submit_button_text_for(factory, path)
case factory
when :budget then "Continue to groups"
when :budget_investment then "Create Investment"
when :dashboard_action then "Save"
when :future_poll_question_option then "Save image"
when :proposal
if edit_path?(path)
"Save changes"
else
"Create proposal"
end
end
end
def notice_text_for(factory, path)
case factory
when :budget then "New participatory budget created successfully!"
when :budget_investment then "Budget Investment created successfully."
when :dashboard_action then "Action created successfully"
when :future_poll_question_option then "Image uploaded successfully"
when :proposal
if edit_path?(path)
"Proposal updated successfully"
else
"Proposal created successfully"
end
end
end
end

View File

@@ -1,48 +0,0 @@
module Documents
def documentable_redirected_to_resource_show_or_navigate_to
find("a", text: "Not now, go to my proposal")
click_link "Not now, go to my proposal"
rescue
nil
end
def documentable_attach_new_file(path, success = true)
click_link "Add new document"
document = all(".document-fields").last
attach_file "Choose document", path
within document do
if success
expect(page).to have_css ".loading-bar.complete"
else
expect(page).to have_css ".loading-bar.errors"
end
end
end
def expect_document_has_title(index, title)
document = all(".document-fields")[index]
within document do
expect(find("input[name$='[title]']").value).to eq title
end
end
def documentable_fill_new_valid_proposal
fill_in_new_proposal_title with: "Proposal title #{rand(9999)}"
fill_in "Proposal summary", with: "Proposal summary"
check :proposal_terms_of_service
end
def documentable_fill_new_valid_dashboard_action
fill_in :dashboard_action_title, with: "Dashboard title"
fill_in_ckeditor "Description", with: "Dashboard description"
end
def documentable_fill_new_valid_budget_investment
fill_in_new_investment_title with: "Budget investment title"
fill_in_ckeditor "Description", with: "Budget investment description"
check :budget_investment_terms_of_service
end
end

View File

@@ -1,16 +0,0 @@
module Images
def imageable_attach_new_file(path, success = true)
click_link "Add image"
within "#nested-image" do
image = find(".image-fields")
attach_file "Choose image", path
within image do
if success
expect(page).to have_css(".loading-bar.complete")
else
expect(page).to have_css(".loading-bar.errors")
end
end
end
end
end

View File

@@ -1,11 +1,5 @@
module Maps module Maps
def fill_in_proposal_form
fill_in_new_proposal_title with: "Help refugees"
fill_in "Proposal summary", with: "In summary, what we want is..."
end
def submit_proposal_form def submit_proposal_form
check :proposal_terms_of_service
click_button "Create proposal" click_button "Create proposal"
expect(page).to have_content "Proposal created successfully." expect(page).to have_content "Proposal created successfully."
@@ -16,14 +10,7 @@ module Maps
end end
end end
def fill_in_budget_investment_form
fill_in_new_investment_title with: "Budget investment title"
fill_in_ckeditor "Description", with: "Budget investment description"
check :budget_investment_terms_of_service
end
def submit_budget_investment_form def submit_budget_investment_form
check :budget_investment_terms_of_service
click_button "Create Investment" click_button "Create Investment"
expect(page).to have_content "Budget Investment created successfully" expect(page).to have_content "Budget Investment created successfully"
end end

View File

@@ -1,15 +1,6 @@
require "rails_helper" require "rails_helper"
describe "Admin dashboard actions", :admin do describe "Admin dashboard actions", :admin do
it_behaves_like "nested documentable",
"administrator",
"dashboard_action",
"new_admin_dashboard_action_path",
{},
"documentable_fill_new_valid_dashboard_action",
"Save",
"Action created successfully"
context "when visiting index" do context "when visiting index" do
context "and no actions defined" do context "and no actions defined" do
before do before do

View File

@@ -1110,20 +1110,6 @@ describe "Budget Investments" do
"budget_investment_path", "budget_investment_path",
{ budget_id: "budget_id", id: "id" } { budget_id: "budget_id", id: "id" }
it_behaves_like "documentable",
"budget_investment",
"budget_investment_path",
{ budget_id: "budget_id", id: "id" }
it_behaves_like "nested documentable",
"user",
"budget_investment",
"new_budget_investment_path",
{ budget_id: "budget_id" },
"documentable_fill_new_valid_budget_investment",
"Create Investment",
"Budget Investment created successfully."
it_behaves_like "mappable", it_behaves_like "mappable",
"budget_investment", "budget_investment",
"investment", "investment",

View File

@@ -1,28 +0,0 @@
require "rails_helper"
describe "Documents" do
describe "Metadata" do
scenario "download document without metadata" do
login_as(create(:user))
visit new_proposal_path
fill_in_new_proposal_title with: "debate"
fill_in "Proposal summary", with: "In summary, what we want is..."
fill_in "Full name of the person submitting the proposal", with: "Isabel Garcia"
documentable_attach_new_file(file_fixture("logo_with_metadata.pdf"))
check "I agree to the Privacy Policy and the Terms and conditions of use"
click_button "Create proposal"
expect(page).to have_content "Proposal created successfully"
io = URI.parse(find_link(text: "PDF")[:href]).open
reader = PDF::Reader.new(io)
expect(reader.info[:Keywords]).not_to eq "Test Metadata"
expect(reader.info[:Author]).not_to eq "Test Developer"
expect(reader.info[:Title]).not_to eq "logo_with_metadata.pdf"
expect(reader.info[:Producer]).not_to eq "Test Producer"
expect(reader.info).to eq({})
end
end
end

View File

@@ -7,16 +7,6 @@ describe "Budget Investments" do
let(:heading) { create(:budget_heading, group: group, name: "Health") } let(:heading) { create(:budget_heading, group: group, name: "Health") }
let(:user) { create(:user, :level_two) } let(:user) { create(:user, :level_two) }
it_behaves_like "nested documentable",
"user",
"budget_investment",
"new_management_budget_investment_path",
{ budget_id: "budget_id" },
"documentable_fill_new_valid_budget_investment",
"Create Investment",
"Budget Investment created successfully.",
management: true
it_behaves_like "mappable", it_behaves_like "mappable",
"budget_investment", "budget_investment",
"investment", "investment",

View File

@@ -0,0 +1,283 @@
require "rails_helper"
describe "Nested documentable" do
factories = [
:budget_investment,
:dashboard_action,
:proposal
]
let(:factory) { factories.sample }
let!(:documentable) { create(factory) }
let!(:user) { create(:user, :level_two) }
let(:path) { attachable_path_for(factory, documentable) }
let(:submit_button_text) { submit_button_text_for(factory, path) }
let(:notice_text) { notice_text_for(factory, path) }
context "New and edit path" do
before do
Setting["uploads.documents.max_amount"] = 1
create(:administrator, user: user) if admin_section?(path)
documentable.update!(author: user) if edit_path?(path)
end
scenario "Shows or hides new document link depending on max documents limit" do
do_login_for(user, management: management_section?(path))
visit path
expect(page).to have_link "Add new document"
documentable_attach_new_file(file_fixture("empty.pdf"))
expect(page).not_to have_link "Add new document"
click_link "Remove document"
expect(page).to have_link "Add new document"
end
scenario "Shows or hides max documents warning depending on max documents limit" do
do_login_for(user, management: management_section?(path))
visit path
expect(page).not_to have_css ".max-documents-notice"
expect(page).not_to have_content "Remove document"
documentable_attach_new_file(file_fixture("empty.pdf"))
expect(page).to have_css ".max-documents-notice"
click_link "Remove document"
expect(page).not_to have_css ".max-documents-notice"
end
scenario "Should update file name and title after choosing a file with no title defined" do
do_login_for(user, management: management_section?(path))
visit path
documentable_attach_new_file(file_fixture("empty.pdf"))
expect(page).to have_css ".file-name", text: "empty.pdf"
expect(page).to have_field("Title", with: "empty.pdf")
end
scenario "Should not change existing titles except when removing the document" do
do_login_for(user, management: management_section?(path))
visit path
click_link "Add new document"
expect(page).not_to have_link "Add new document"
within "#nested-documents" do
fill_in "Title", with: "My Title"
attach_file "Choose document", file_fixture("empty.pdf")
expect(page).to have_css ".loading-bar.complete"
expect(page).to have_field "Title", with: "My Title"
click_link "Remove document"
expect(page).not_to have_css ".document-fields"
expect(page).not_to have_field "Title"
end
click_link "Add new document"
within "#nested-documents" do
expect(page).to have_field "Title", with: ""
expect(page).not_to have_field "Title", with: "My Title"
end
end
scenario "Should update document cached_attachment field after valid file upload" do
do_login_for(user, management: management_section?(path))
visit path
click_link "Add new document"
cached_attachment_field = find("input[name$='[cached_attachment]']", visible: :hidden)
expect(cached_attachment_field.value).to be_empty
attach_file "Choose document", file_fixture("empty.pdf")
expect(page).to have_css(".loading-bar.complete")
expect(cached_attachment_field.value).not_to be_empty
end
scenario "Should not update document cached_attachment field after invalid file upload" do
do_login_for(user, management: management_section?(path))
visit path
documentable_attach_new_file(file_fixture("logo_header.gif"), success: false)
cached_attachment_field = find("input[name$='[cached_attachment]']", visible: :hidden)
expect(cached_attachment_field.value).to be_empty
end
scenario "Should show document errors after documentable submit with empty document fields" do
do_login_for(user, management: management_section?(path))
visit path
click_link "Add new document"
click_button submit_button_text
within "#nested-documents .document-fields" do
expect(page).to have_content("can't be blank", count: 2)
end
end
scenario "Should show successful notice when resource filled correctly without any nested documents" do
do_login_for(user, management: management_section?(path))
visit path
fill_in_required_fields(factory, path)
click_button submit_button_text
expect(page).to have_content notice_text
end
scenario "Should show successful notice when resource filled correctly and after valid file uploads" do
Setting["uploads.documents.max_amount"] = 3
do_login_for(user, management: management_section?(path))
visit path
fill_in_required_fields(factory, path)
%w[clippy empty logo].each do |filename|
click_link "Add new document"
attach_file "Choose document", file_fixture("#{filename}.pdf")
within all(".document-fields").last do
expect(page).to have_css ".loading-bar.complete"
end
end
expect(page).not_to have_link "Add new document"
click_button submit_button_text
expect(page).to have_content notice_text
if factory != :dashboard_action
within "#documents" do
expect(page).to have_content "Documents (3)"
expect(page).to have_link href: /.pdf\Z/, count: 3
expect(page).to have_link text: "empty.pdf"
expect(page).to have_css "a[rel=nofollow]"
expect(page).to have_link text: "clippy.pdf"
expect(page).to have_css "a[rel=nofollow]"
expect(page).to have_link text: "logo.pdf"
expect(page).to have_css "a[rel=nofollow]"
expect(page).not_to have_css "a[target=_blank]"
end
end
end
describe "Metadata" do
let(:factory) { (factories - [:dashboard_action]).sample }
scenario "download document without metadata" do
do_login_for(user, management: management_section?(path))
visit path
fill_in_required_fields(factory, path)
documentable_attach_new_file(file_fixture("logo_with_metadata.pdf"))
click_button submit_button_text
expect(page).to have_content notice_text
io = URI.parse(find_link(text: "PDF")[:href]).open
reader = PDF::Reader.new(io)
expect(reader.info[:Keywords]).not_to eq "Test Metadata"
expect(reader.info[:Author]).not_to eq "Test Developer"
expect(reader.info[:Title]).not_to eq "logo_with_metadata.pdf"
expect(reader.info[:Producer]).not_to eq "Test Producer"
expect(reader.info).to eq({})
end
end
describe "When allow attached documents setting is disabled" do
before { Setting["feature.allow_attached_documents"] = false }
scenario "Add new document button should not be available" do
do_login_for(user, management: management_section?(path))
visit path
expect(page).not_to have_content("Add new document")
end
end
end
describe "Only for edit path" do
let!(:proposal) { create(:proposal, author: user) }
scenario "Should show persisted documents and remove nested_field" do
Setting["uploads.documents.max_amount"] = 1
create(:document, documentable: proposal)
login_as user
visit edit_proposal_path(proposal)
expect(page).not_to have_link "Add new document"
expect(page).to have_css ".document-fields", count: 1
click_link "Remove document"
expect(page).to have_link "Add new document"
expect(page).not_to have_css ".document-fields"
end
scenario "Same attachment URL after editing the title" do
login_as user
visit edit_proposal_path(proposal)
documentable_attach_new_file(file_fixture("empty.pdf"))
within_fieldset("Documents") { fill_in "Title", with: "Original" }
click_button "Save changes"
expect(page).to have_content "Proposal updated successfully"
original_url = find_link(text: "Original")[:href]
visit edit_proposal_path(proposal)
within_fieldset("Documents") { fill_in "Title", with: "Updated" }
click_button "Save changes"
expect(page).to have_content "Proposal updated successfully"
expect(find_link(text: "Updated")[:href]).to eq original_url
end
end
context "Show path" do
let(:factory) { (factories - [:dashboard_action]).sample }
let(:path) { polymorphic_path(documentable) }
scenario "Documents list should not be available when allow attached documents setting is disabled" do
Setting["feature.allow_attached_documents"] = false
create(:document, documentable: documentable)
visit path
expect(page).not_to have_css("#documents")
end
context "Destroy" do
scenario "Should show success notice after successful document upload" do
create(:document, documentable: documentable)
documentable.update!(author: user)
login_as(user)
visit path
accept_confirm { click_button "Delete document" }
expect(page).to have_content "Document was deleted successfully."
expect(page).not_to have_content "Documents (0)"
within "##{ActionView::RecordIdentifier.dom_id(documentable)}" do
expect(page).to have_css "h1", text: documentable.title
end
end
end
end
end

View File

@@ -11,50 +11,15 @@ describe "Nested imageable" do
let(:factory) { factories.sample } let(:factory) { factories.sample }
let!(:imageable) { create(factory) } let!(:imageable) { create(factory) }
let!(:user) { create(:user, :level_two) } let!(:user) { create(:user, :level_two) }
let(:path) do let(:path) { attachable_path_for(factory, imageable) }
case factory let(:submit_button_text) { submit_button_text_for(factory, path) }
when :budget then new_admin_budgets_wizard_budget_path let(:notice_text) { notice_text_for(factory, path) }
when :budget_investment
[
new_budget_investment_path(budget_id: imageable.budget_id),
new_management_budget_investment_path(budget_id: imageable.budget_id)
].sample
when :future_poll_question_option then new_admin_option_image_path(option_id: imageable.id)
when :proposal then [new_proposal_path, edit_proposal_path(imageable)].sample
end
end
let(:submit_button_text) do
case factory
when :budget then "Continue to groups"
when :budget_investment then "Create Investment"
when :future_poll_question_option then "Save image"
when :proposal
if edit_path?
"Save changes"
else
"Create proposal"
end
end
end
let(:notice_text) do
case factory
when :budget then "New participatory budget created successfully!"
when :budget_investment then "Budget Investment created successfully."
when :future_poll_question_option then "Image uploaded successfully"
when :proposal
if edit_path?
"Proposal updated successfully"
else
"Proposal created successfully"
end
end
end
context "New and edit path" do context "New and edit path" do
before do before do
create(:administrator, user: user) if admin_section? || management_section? create(:administrator, user: user) if admin_section?(path)
imageable.update!(author: user) if edit_path? imageable.update!(author: user) if edit_path?(path)
do_login_for(user, management: management_section?) do_login_for(user, management: management_section?(path))
visit path visit path
end end
@@ -96,7 +61,7 @@ describe "Nested imageable" do
end end
scenario "Should not update image cached_attachment field after invalid file upload" do scenario "Should not update image cached_attachment field after invalid file upload" do
imageable_attach_new_file(file_fixture("logo_header.png"), false) imageable_attach_new_file(file_fixture("logo_header.png"), success: false)
cached_attachment_field = find("input[name$='[cached_attachment]']", visible: :hidden) cached_attachment_field = find("input[name$='[cached_attachment]']", visible: :hidden)
@@ -136,7 +101,7 @@ describe "Nested imageable" do
let(:factory) { (factories - [:future_poll_question_option]).sample } let(:factory) { (factories - [:future_poll_question_option]).sample }
scenario "Should show successful notice when resource filled correctly without any nested images" do scenario "Should show successful notice when resource filled correctly without any nested images" do
fill_in_required_fields fill_in_required_fields(factory, path)
click_button submit_button_text click_button submit_button_text
@@ -145,7 +110,7 @@ describe "Nested imageable" do
end end
scenario "Should show successful notice when resource filled correctly and after valid file uploads" do scenario "Should show successful notice when resource filled correctly and after valid file uploads" do
fill_in_required_fields fill_in_required_fields(factory, path)
imageable_attach_new_file(file_fixture("clippy.jpg")) imageable_attach_new_file(file_fixture("clippy.jpg"))
@@ -155,7 +120,7 @@ describe "Nested imageable" do
end end
scenario "Should show new image after successful creation with one uploaded file" do scenario "Should show new image after successful creation with one uploaded file" do
fill_in_required_fields fill_in_required_fields(factory, path)
imageable_attach_new_file(file_fixture("clippy.jpg")) imageable_attach_new_file(file_fixture("clippy.jpg"))
@@ -205,42 +170,4 @@ describe "Nested imageable" do
expect(page).to have_css ".image-fields", count: 1, visible: :all expect(page).to have_css ".image-fields", count: 1, visible: :all
end end
end end
def fill_in_required_fields
return if edit_path?
case factory
when :budget then fill_budget
when :budget_investment then fill_budget_investment
when :proposal then fill_proposal
end
end
def fill_proposal
fill_in_new_proposal_title with: "Proposal title"
fill_in "Proposal summary", with: "Proposal summary"
check :proposal_terms_of_service
end
def fill_budget
fill_in "Name", with: "Budget name"
end
def fill_budget_investment
fill_in_new_investment_title with: "Budget investment title"
fill_in_ckeditor "Description", with: "Budget investment description"
check :budget_investment_terms_of_service
end
def admin_section?
path.starts_with?("/admin/")
end
def management_section?
path.starts_with?("/management/")
end
def edit_path?
path.ends_with?("/edit")
end
end end

View File

@@ -559,7 +559,7 @@ describe "Proposals" do
scenario "Default whole city" do scenario "Default whole city" do
create(:geozone) create(:geozone)
author = create(:user) author = create(:user, :level_two)
login_as(author) login_as(author)
visit new_proposal_path visit new_proposal_path
@@ -1295,26 +1295,6 @@ describe "Proposals" do
it_behaves_like "imageable", "proposal", "proposal_path", { id: "id" } it_behaves_like "imageable", "proposal", "proposal_path", { id: "id" }
it_behaves_like "documentable", "proposal", "proposal_path", { id: "id" }
it_behaves_like "nested documentable",
"user",
"proposal",
"new_proposal_path",
{},
"documentable_fill_new_valid_proposal",
"Create proposal",
"Proposal created successfully"
it_behaves_like "nested documentable",
"user",
"proposal",
"edit_proposal_path",
{ id: "id" },
nil,
"Save changes",
"Proposal updated successfully"
it_behaves_like "mappable", it_behaves_like "mappable",
"proposal", "proposal",
"proposal", "proposal",