test(attachments): more components tests & improvements

This commit is contained in:
Colin Darie 2022-11-22 17:12:16 +01:00
parent fefc326e6b
commit 6ac0114992
8 changed files with 152 additions and 19 deletions

View file

@ -5,11 +5,13 @@
- if user_can_destroy?
= link_to('Supprimer', destroy_attachment_path, **remove_button_options, class: "fr-btn fr-btn--tertiary fr-btn--sm fr-icon-delete-line", title: "Supprimer le fichier #{attachment.filename}")
.fr-py-1v
= link_to_if(downloadable?, attachment.filename.to_s, attachment.url, class: "attachment-filename", download: "") do
%span.attachment-filename= attachment.filename.to_s
.fr-py-1v
- if downloadable?
= render Dsfr::DownloadComponent.new(attachment:)
- else
%span.attachment-filename.fr-mr-1w-= attachment.filename.to_s
= render Attachment::ProgressComponent.new(attachment: attachment)
= render Attachment::ProgressComponent.new(attachment: attachment)
- if error?
%p.fr-error-text= error_message

View file

@ -1,27 +1,27 @@
# Display a widget for uploading, editing and deleting a file attachment
class Attachment::MultipleComponent < ApplicationComponent
DEFAULT_MAX_ATTACHMENTS = 10
renders_one :template
attr_reader :form
attr_reader :champ
attr_reader :attached_file
attr_reader :user_can_download
attr_reader :user_can_destroy
attr_reader :max
delegate :count, :empty?, to: :attachments, prefix: true
def initialize(form:, attached_file:, user_can_destroy: false, max: nil)
@form = form
def initialize(champ:, attached_file:, user_can_download: false, user_can_destroy: true, max: nil)
@champ = champ
@attached_file = attached_file
@user_can_download = user_can_download
@user_can_destroy = user_can_destroy
@max = max || 10
@max = max || DEFAULT_MAX_ATTACHMENTS
@attachments = attached_file.attachments || []
end
def champ
form.object
end
def each_attachment(&block)
@attachments.each_with_index(&block)
end
@ -31,7 +31,7 @@ class Attachment::MultipleComponent < ApplicationComponent
end
def empty_component_id
"attachment-multiple-empty-#{form.object.id}"
"attachment-multiple-empty-#{champ.id}"
end
def in_progress?
@ -54,7 +54,7 @@ class Attachment::MultipleComponent < ApplicationComponent
end
def auto_attach_url
helpers.auto_attach_url(form.object)
helpers.auto_attach_url(champ)
end
private

View file

@ -3,7 +3,7 @@
- each_attachment do |attachment, index|
%div{ id: dom_id(attachment) }
= render Attachment::EditComponent.new(champ:, attached_file:, attachment:, index:, as_multiple: true, user_can_destroy:)
= render Attachment::EditComponent.new(champ:, attached_file:, attachment:, index:, as_multiple: true, user_can_destroy:, user_can_download:)
%div{ id: empty_component_id, class: class_names("hidden": !can_attach_next?) }
= render Attachment::EditComponent.new(champ:, attached_file:, attachment: nil, index: attachments_count, user_can_destroy:)

View file

@ -1,2 +1,2 @@
%p.fr-badge.fr-badge--info.fr-badge--sm.fr-badge--no-icon.fr-ml-1w
%p.fr-badge.fr-badge--info.fr-badge--sm.fr-badge--no-icon
= progress_label

View file

@ -6,7 +6,7 @@
(ce fichier na pas été analysé par notre antivirus, téléchargez-le avec précaution)
- else
.attachment-filename.fr-mb-1w= attachment.filename.to_s
.attachment-filename.fr-mb-1w.fr-mr-1w= attachment.filename.to_s
= render Attachment::ProgressComponent.new(attachment: attachment)

View file

@ -1,6 +1,7 @@
- user_can_destroy = !@champ.mandatory? || @champ.dossier.brouillon?
- max = [true, nil].include?(@champ.procedure&.piece_justificative_multiple?) ? 10 : 1
= render Attachment::MultipleComponent.new(form: @form, attached_file: @champ.piece_justificative_file, user_can_destroy:, max:) do |c|
- user_can_download = !@champ.dossier.brouillon?
- max = [true, nil].include?(@champ.procedure&.piece_justificative_multiple?) ? Attachment::MultipleComponent::DEFAULT_MAX_ATTACHMENTS : 1
= render Attachment::MultipleComponent.new(champ: @champ, attached_file: @champ.piece_justificative_file, user_can_destroy:, user_can_download:, max:) do |c|
- if @champ.type_de_champ.piece_justificative_template&.attached?
- c.with_template do
= render Dsfr::DownloadComponent.new(attachment: @champ.type_de_champ.piece_justificative_template, name: "Modèle à télécharger") do |c|

View file

@ -117,6 +117,28 @@ RSpec.describe Attachment::EditComponent, type: :component do
expect(subject).to have_no_link(text: filename)
expect(subject).to have_text('Analyse antivirus en cours')
end
it 'setup polling' do
expect(subject).to have_selector('[data-controller=turbo-poll]')
end
context "process is taking longer than expected" do
before do
champ.piece_justificative_file.attachments[0].update!(created_at: 5.minutes.ago)
end
it 'renders a refresh button' do
expect(subject).to have_button("Rafraîchir")
end
end
context "when used as multiple context" do
let(:kwargs) { { as_multiple: true } }
it 'does not setup polling' do
expect(subject).to have_no_selector('[data-controller=turbo-poll]')
end
end
end
context 'when the file is scanned and safe' do

View file

@ -0,0 +1,108 @@
RSpec.describe Attachment::MultipleComponent, type: :component do
let(:champ) { create(:champ_titre_identite) }
let(:attached_file) { champ.piece_justificative_file }
let(:kwargs) { {} }
let(:component) do
described_class.new(
champ:,
attached_file:,
**kwargs
)
end
subject { render_inline(component).to_html }
context 'when there is no attachment yet' do
let(:champ) { create(:champ_titre_identite, skip_default_attachment: true) }
it 'renders a form field for uploading a file' do
expect(subject).to have_no_selector('.hidden input[type=file]')
expect(subject).to have_selector('input[type=file]:not(.hidden)')
end
it 'renders max size' do
expect(subject).to have_content(/Taille maximale :\s+20 Mo/)
end
end
context 'when there is a template' do
before do
component.with_template { "the template to render" }
end
it 'renders the template' do
expect(subject).to have_text("the template to render")
end
end
context 'when there is an attachment' do
before do
attached_file.attach(
io: StringIO.new("x" * 2),
filename: "me.jpg",
content_type: "image/jpeg",
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
)
champ.save!
end
it 'renders the filenames' do
expect(subject).to have_content(attached_file.attachments[0].filename.to_s)
expect(subject).to have_content(attached_file.attachments[1].filename.to_s)
end
it 'shows the Delete button by default' do
expect(subject).to have_link(title: "Supprimer le fichier #{attached_file.attachments[0].filename}")
expect(subject).to have_link(title: "Supprimer le fichier #{attached_file.attachments[1].filename}")
end
it 'renders a form field for uploading a new file' do
expect(subject).to have_selector('input[type=file]:not(.hidden)')
end
it 'does not renders max size anymore' do
expect(subject).to have_no_content(/Taille maximale/)
end
end
context 'when the user cannot destroy the attachment' do
let(:kwargs) { { user_can_destroy: false } }
it 'hides the Delete button' do
expect(subject).to have_no_link(title: "Supprimer le fichier #{attached_file.attachments[0].filename}")
end
it 'still renders the filename' do
expect(subject).to have_content(attached_file.attachments[0].filename.to_s)
end
end
context 'max attachments' do
let(:kwargs) { { max: 1 } }
it 'does not render visible input file where max attachments has been reached' do
expect(subject).to have_selector('.hidden input[type=file]')
end
end
context 'attachment process in progress' do
let(:created_at) { 1.second.ago }
before do
attached_file.attachments[0].blob.update(metadata: { virus_scan_result: ActiveStorage::VirusScanner::PENDING })
attached_file.attachments[0].update!(created_at:)
end
it 'setup polling' do
expect(subject).to have_selector('[data-controller=turbo-poll]')
end
context "process is taking longer than expected" do
let(:created_at) { 5.minutes.ago }
it 'renders a refresh button' do
expect(subject).to have_button("Rafraîchir")
end
end
end
end