From f8d78ec4ab9c55e63743faef2f6c3c77cc5b36df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?= Date: Sat, 23 Sep 2017 17:14:32 +0200 Subject: [PATCH] Remove new_nested action from images controller. Use cocoon gem to manage new nested fields creation on images. --- app/assets/javascripts/documentable.js.coffee | 23 +++- app/assets/javascripts/imageable.js.coffee | 60 ++------ app/assets/stylesheets/mixins.scss | 3 +- app/controllers/images_controller.rb | 5 +- app/helpers/documents_helper.rb | 30 ++-- app/helpers/images_helper.rb | 69 ++++------ app/models/abilities/common.rb | 2 - app/models/concerns/imageable.rb | 2 +- app/views/budgets/investments/_form.html.erb | 2 +- .../documents/_nested_documents.html.erb | 7 +- app/views/images/_form.html.erb | 2 +- app/views/images/_image_fields.html.erb | 31 +++++ app/views/images/_nested_fields.html.erb | 51 ------- app/views/images/_nested_image.html.erb | 25 ++++ app/views/images/_nested_images.html.erb | 16 --- app/views/images/destroy.js.erb | 8 +- app/views/images/new_nested.js.erb | 2 - app/views/images/upload.js.erb | 12 -- app/views/proposals/_form.html.erb | 2 +- config/routes.rb | 4 +- spec/shared/features/imageable.rb | 6 +- spec/shared/features/nested_documentable.rb | 39 +++++- spec/shared/features/nested_imageable.rb | 130 +++++++++++++----- 23 files changed, 263 insertions(+), 268 deletions(-) create mode 100644 app/views/images/_image_fields.html.erb delete mode 100644 app/views/images/_nested_fields.html.erb create mode 100644 app/views/images/_nested_image.html.erb delete mode 100644 app/views/images/_nested_images.html.erb delete mode 100644 app/views/images/new_nested.js.erb delete mode 100644 app/views/images/upload.js.erb diff --git a/app/assets/javascripts/documentable.js.coffee b/app/assets/javascripts/documentable.js.coffee index cf5e3cad1..4dfc9024c 100644 --- a/app/assets/javascripts/documentable.js.coffee +++ b/app/assets/javascripts/documentable.js.coffee @@ -6,8 +6,11 @@ App.Documentable = App.Documentable.initializeDirectUploadInput(input) if $(nested_document).closest('#nested-documents').find('.document').length >= $('#nested-documents').data('max-documents-allowed') - $('#max-documents-notice').removeClass('hide') - $('#new_document_link').addClass('hide') + App.Documentable.lockUploads() + + inputFiles = $('.js-document-attachment') + $.each inputFiles, (index, input) -> + App.Documentable.initializeDirectUploadInput(input) initializeDirectUploadInput: (input) -> @@ -108,6 +111,14 @@ App.Documentable = errors = '' + data.jqXHR.responseJSON.errors + '' $(data.errorContainer).append(errors) + lockUploads: -> + $('#max-documents-notice').removeClass('hide') + $('#new_document_link').addClass('hide') + + unlockUploads: -> + $('#max-documents-notice').addClass('hide') + $('#new_document_link').removeClass('hide') + doDeleteCachedAttachmentRequest: (url, data) -> $.ajax type: "POST" @@ -122,8 +133,7 @@ App.Documentable = App.Documentable.clearInputErrors(data) App.Documentable.clearProgressBar(data) - $('#new_document_link').removeClass('hide') - $('#max-documents-notice').addClass('hide') + App.Documentable.unlockUploads() $(data.wrapper).find(".attachment-actions").addClass('small-12').removeClass('small-6 float-right') $(data.wrapper).find(".attachment-actions .action-remove").addClass('small-3').removeClass('small-12') @@ -136,8 +146,7 @@ App.Documentable = $(remove_document_link).on 'click', (e) -> e.preventDefault() $(wrapper).remove() - $('#new_document_link').removeClass('hide') - $('#max-documents-notice').addClass('hide') + App.Documentable.unlockUploads() initializeRemoveCachedDocumentLink: (input, data) -> wrapper = $(input).closest(".direct-upload") @@ -149,3 +158,5 @@ App.Documentable = destroyNestedDocument: (id) -> $('#' + id).remove() + if $('#nested-documents .document').length < $('#nested-documents').data('max-documents-allowed') + App.Documentable.unlockUploads() diff --git a/app/assets/javascripts/imageable.js.coffee b/app/assets/javascripts/imageable.js.coffee index 608eb9b1b..2f4e4c791 100644 --- a/app/assets/javascripts/imageable.js.coffee +++ b/app/assets/javascripts/imageable.js.coffee @@ -1,12 +1,16 @@ App.Imageable = initialize: -> - inputFiles = $('input.js-document-attachment[type=file]') + $('#nested-image').on 'cocoon:after-insert', (e, nested_image) -> + input = $(nested_image).find('.js-image-attachment') + App.Imageable.initializeDirectUploadInput(input) + inputFiles = $('.js-image-attachment') $.each inputFiles, (index, input) -> App.Imageable.initializeDirectUploadInput(input) - $("#new_image_link").on 'click', -> $(this).hide() + $("#new_image_link").on 'click', -> + $(this).addClass('hide') initializeDirectUploadInput: (input) -> @@ -52,8 +56,8 @@ App.Imageable = $(data.addAttachmentLabel).hide() $(data.wrapper).find(".attachment-actions").removeClass('small-12').addClass('small-6 float-right') $(data.wrapper).find(".attachment-actions .action-remove").removeClass('small-3').addClass('small-12') - App.Imageable.setPreview(data) + destroyAttachmentLink = $(data.result.destroy_link) $(data.destroyAttachmentLinkContainer).html(destroyAttachmentLink) $(destroyAttachmentLink).on 'click', (e) -> @@ -80,8 +84,8 @@ App.Imageable = data.fileNameContainer = $(wrapper).find('p.file-name') data.destroyAttachmentLinkContainer = $(wrapper).find('.action-remove') data.addAttachmentLabel = $(wrapper).find('.action-add label') - data.cachedAttachmentField = $(wrapper).find("#" + $(input).data('cached-attachment-input-field')) - data.titleField = $(wrapper).find("#" + $(input).data('title-input-field')) + data.cachedAttachmentField = $(wrapper).find("input[name$='[cached_attachment]']") + data.titleField = $(wrapper).find("input[name$='[title]']") $(wrapper).find('.progress-bar-placeholder').css('display', 'block') return data @@ -114,7 +118,6 @@ App.Imageable = $(data.errorContainer).append(errors) setPreview: (data) -> - console.log 'App.Imageable.setPreview' image_preview = '
' if $(data.preview).length > 0 $(data.preview).replaceWith(image_preview) @@ -122,13 +125,6 @@ App.Imageable = $(image_preview).insertBefore($(data.wrapper).find(".attachment-actions")) data.preview = $(data.wrapper).find('.image-preview') - watchRemoveImagebutton: (wrapper) -> - remove_image_button = $(wrapper).find('a.delete[href="#"]') - $(remove_image_button).on 'click', (e) -> - e.preventDefault() - $(wrapper).remove() - $('#new_image_link').show() - doDeleteCachedAttachmentRequest: (url, data) -> $.ajax type: "POST" @@ -144,9 +140,10 @@ App.Imageable = App.Imageable.clearProgressBar(data) App.Imageable.clearPreview(data) + $('#new_image_link').removeClass('hide') + if $(data.input).data('nested-image') == true $(data.wrapper).remove() - $('#new_image_link').show() else $(data.destroyAttachmentLinkContainer).find('a.delete').remove() @@ -156,7 +153,7 @@ App.Imageable = $(remove_image_link).on 'click', (e) -> e.preventDefault() $(wrapper).remove() - $('#new_image_link').show() + $('#new_image_link').removeClass('hide') initializeRemoveCachedImageLink: (input, data) -> wrapper = $(input).closest(".direct-upload") @@ -166,37 +163,6 @@ App.Imageable = e.stopPropagation() App.Imageable.doDeleteCachedAttachmentRequest(this.href, data) - new: (nested_field) -> - nested_field = $(nested_field) - $(".images-list").append(nested_field) - input = nested_field.find("input[type='file']") - @initializeDirectUploadInput(input) - $("#new_image_link").hide() - destroyNestedImage: (id, notice) -> $('#' + id).remove() - $("#new_image_link").show() - @updateNotice(notice) - - replacePlainImage: (id, notice, plain_image) -> - $('#' + id).replaceWith(plain_image) - @updateNotice(notice) - @initialize() - - updateNotice: (notice) -> - if $('[data-alert]').length > 0 - $('[data-alert]').replaceWith(notice) - else - $("body").append(notice) - - updateNewImageButton: (link) -> - if $('.image').length >= $('.images').data('max-images') - $('#new_image_link').hide() - $('.max-images-notice').removeClass('hide') - $('.max-images-notice').show() - else if $('#new_image_link').length > 0 - $('#new_image_link').replaceWith(link) - $('.max-images-notice').hide() - else - $('.max-images-notice').hide() - $(link).insertBefore('.images hr:last') + $("#new_image_link").removeClass('hide') diff --git a/app/assets/stylesheets/mixins.scss b/app/assets/stylesheets/mixins.scss index 102401d80..58de36b74 100644 --- a/app/assets/stylesheets/mixins.scss +++ b/app/assets/stylesheets/mixins.scss @@ -77,7 +77,8 @@ margin-bottom: 0; } } - .js-document-attachment{ + input.js-document-attachment, + input.js-image-attachment{ display: none; } } diff --git a/app/controllers/images_controller.rb b/app/controllers/images_controller.rb index 870570ed7..5af4dcf60 100644 --- a/app/controllers/images_controller.rb +++ b/app/controllers/images_controller.rb @@ -1,7 +1,7 @@ class ImagesController < ApplicationController before_action :authenticate_user! before_filter :find_imageable, except: :destroy - before_filter :prepare_new_image, only: [:new, :new_nested] + before_filter :prepare_new_image, only: [:new] before_filter :prepare_image_for_creation, only: :create load_and_authorize_resource @@ -9,9 +9,6 @@ class ImagesController < ApplicationController def new end - def new_nested - end - def create recover_attachments_from_cache diff --git a/app/helpers/documents_helper.rb b/app/helpers/documents_helper.rb index 8ead51f8c..ba816ff5f 100644 --- a/app/helpers/documents_helper.rb +++ b/app/helpers/documents_helper.rb @@ -46,23 +46,19 @@ module DocumentsHelper end def render_attachment(builder, document) - html = builder.file_field :attachment, - label: false, - accept: accepted_content_types_extensions(document.documentable_type.constantize), - class: 'js-document-attachment', - data: { - url: document_direct_upload_url(document), - nested_document: true - } - if document.attachment.blank? && document.cached_attachment.blank? - klass = document.errors[:attachment].any? ? "error" : "" - html += builder.label :attachment, t("documents.upload_document"), class: "button hollow" - if document.errors[:attachment].any? - html += content_tag :small, class: "error" do - document_errors_on_attachment(document) - end - end - end + klass = document.errors[:attachment].any? ? "error" : "" + klass = document.persisted? ? " hide" : "" + html = builder.label :attachment, + t("documents.upload_document"), + class: "button hollow #{klass}" + html += builder.file_field :attachment, + label: false, + accept: accepted_content_types_extensions(document.documentable_type.constantize), + class: 'js-document-attachment', + data: { + url: document_direct_upload_url(document), + nested_document: true + } html end diff --git a/app/helpers/images_helper.rb b/app/helpers/images_helper.rb index 9596f1a82..8b9d15be6 100644 --- a/app/helpers/images_helper.rb +++ b/app/helpers/images_helper.rb @@ -31,22 +31,8 @@ module ImagesHelper bytes / Numeric::MEGABYTE end - def image_nested_field_name(image, field) - parent = image.imageable_type.parameterize.underscore - "#{parent.parameterize}[image_attributes]#{field}" - end - - def image_nested_field_id(image, field) - parent = image.imageable_type.parameterize.underscore - "#{parent.parameterize}_image_attributes_#{field}" - end - - def image_nested_field_wrapper_id - "nested_image" - end - def image_class(image) - image.persisted? ? "image" : "cached-image" + image.persisted? ? "persisted-image" : "cached-image" end def render_destroy_image_link(image) @@ -59,10 +45,10 @@ module ImagesHelper class: "delete remove-image" elsif !image.persisted? && image.cached_attachment.present? link_to t('images.form.delete_button'), - destroy_upload_images_path(path: image.cached_attachment, - nested_image: true, - imageable_type: image.imageable_type, - imageable_id: image.imageable_id), + direct_upload_destroy_url("direct_upload[resource_type]": image.imageable_type, + "direct_upload[resource_id]": image.imageable_id, + "direct_upload[resource_relation]": "image", + "direct_upload[cached_attachment]": image.cached_attachment), method: :delete, remote: true, class: "delete remove-cached-attachment" @@ -73,30 +59,21 @@ module ImagesHelper end end - def render_image_attachment(image) - html = file_field_tag :attachment, - accept: imageable_accepted_content_types_extensions, - class: 'js-document-attachment', - data: { - url: image_direct_upload_url(image), - cached_attachment_input_field: image_nested_field_id(image, :cached_attachment), - title_input_field: image_nested_field_id(image, :title), - multiple: false, - nested_image: true - }, - name: image_nested_field_name(image, :attachment), - id: image_nested_field_id(image, :attachment) - if image.attachment.blank? && image.cached_attachment.blank? - klass = image.errors[:attachment].any? ? "error" : "" - html += label_tag image_nested_field_id(image, :attachment), - t("images.form.attachment_label"), - class: "button hollow #{klass}" - if image.errors[:attachment].any? - html += content_tag :small, class: "error" do - image_errors_on_attachment(image) - end - end - end + def render_image_attachment(builder, imageable, image) + klass = image.errors[:attachment].any? ? "error" : "" + klass = image.persisted? ? " hide" : "" + html = builder.label :attachment, + t("images.form.attachment_label"), + class: "button hollow #{klass}" + html += builder.file_field :attachment, + label: false, + accept: imageable_accepted_content_types_extensions, + class: 'js-image-attachment', + data: { + url: image_direct_upload_url(imageable), + nested_image: true + } + html end @@ -107,9 +84,9 @@ module ImagesHelper show_caption: show_caption } end - def image_direct_upload_url(image) - direct_uploads_url("direct_upload[resource_type]": image.imageable_type, - "direct_upload[resource_id]": image.imageable_id, + def image_direct_upload_url(imageable) + direct_uploads_url("direct_upload[resource_type]": imageable.class.name, + "direct_upload[resource_id]": imageable.id, "direct_upload[resource_relation]": "image") end diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb index da34dd65b..b4248c3b6 100644 --- a/app/models/abilities/common.rb +++ b/app/models/abilities/common.rb @@ -38,10 +38,8 @@ module Abilities can [:create, :destroy], Follow can [:create, :destroy, :new], Document, documentable: { author_id: user.id } - can [:upload, :destroy_upload], Document can [:create, :destroy, :new], Image, imageable: { author_id: user.id } - can [:new_nested, :upload, :destroy_upload], Image can [:create, :destroy], DirectUpload diff --git a/app/models/concerns/imageable.rb b/app/models/concerns/imageable.rb index 04a4ba3a3..a2a2f537d 100644 --- a/app/models/concerns/imageable.rb +++ b/app/models/concerns/imageable.rb @@ -5,7 +5,7 @@ module Imageable included do has_one :image, as: :imageable, dependent: :destroy - accepts_nested_attributes_for :image, allow_destroy: true + accepts_nested_attributes_for :image, allow_destroy: true, update_only: true def image_url(style) image.attachment.url(style) if image && image.attachment.exists? diff --git a/app/views/budgets/investments/_form.html.erb b/app/views/budgets/investments/_form.html.erb index 300635e5d..0d0bdd7f1 100644 --- a/app/views/budgets/investments/_form.html.erb +++ b/app/views/budgets/investments/_form.html.erb @@ -22,7 +22,7 @@
- <%= render 'images/nested_images', imageable: @investment %> + <%= render 'images/nested_image', imageable: @investment, f: f %>
diff --git a/app/views/documents/_nested_documents.html.erb b/app/views/documents/_nested_documents.html.erb index a186a7f95..ecbe46ce7 100644 --- a/app/views/documents/_nested_documents.html.erb +++ b/app/views/documents/_nested_documents.html.erb @@ -10,13 +10,8 @@ <%= link_to_add_association t('documents.form.add_new_document'), f, :documents, partial: "documents/document_fields", - render_options: { - locals: { - document: Document.new(documentable: documentable) - }, - }, id: "new_document_link", - class: "button hollow", + class: "button hollow #{"hide" if documentable.documents.count >= documentable.class.max_documents_allowed}", data: { association_insertion_node: "#nested-documents", association_insertion_method: "append" diff --git a/app/views/images/_form.html.erb b/app/views/images/_form.html.erb index b44940f94..8f8cd6995 100644 --- a/app/views/images/_form.html.erb +++ b/app/views/images/_form.html.erb @@ -24,7 +24,7 @@ <%= f.file_field :attachment, accept: imageable_accepted_content_types_extensions, label: false, - class: 'js-document-attachment', + class: 'js-image-attachment', data: { url: direct_uploads_url("direct_upload[resource_type]": @image.imageable_type, "direct_upload[resource_id]": @image.imageable_id, diff --git a/app/views/images/_image_fields.html.erb b/app/views/images/_image_fields.html.erb new file mode 100644 index 000000000..43a79a2c2 --- /dev/null +++ b/app/views/images/_image_fields.html.erb @@ -0,0 +1,31 @@ +
+ <%= f.hidden_field :id %> + <%= f.hidden_field :user_id, value: current_user.id %> + <%= f.hidden_field :cached_attachment %> + +
+ <%= f.text_field :title, placeholder: t("images.new.form.title_placeholder") %> +
+ + <%= render_image(f.object, :thumb, false) if f.object.attachment.exists? %> + +
+
+ <%= render_image_attachment(f, imageable, f.object) %> +
+
+ <%= render_destroy_image_link(f.object) %> +
+
+ +
+

+ <%= image_attachment_file_name(f.object) %> +

+
+ +
+
+
+ +
diff --git a/app/views/images/_nested_fields.html.erb b/app/views/images/_nested_fields.html.erb deleted file mode 100644 index 73afa44ee..000000000 --- a/app/views/images/_nested_fields.html.erb +++ /dev/null @@ -1,51 +0,0 @@ -
- <%= hidden_field_tag :id, - image.id, - name: image_nested_field_name(image, :id), - id: image_nested_field_id(image, :id) if image.persisted? %> - <%= hidden_field_tag :user_id, - current_user.id, - name: image_nested_field_name(image, :user_id), - id: image_nested_field_id(image, :user_id) %> - <%= hidden_field_tag :cached_attachment, - image.cached_attachment, - name: image_nested_field_name(image, :cached_attachment), - id: image_nested_field_id(image, :cached_attachment) %> - -
- <%= label_tag :title, - t("activerecord.attributes.image.title"), - class: image.errors[:title].any? ? "error" : "" %> - - <%= text_field_tag :title, - image.title, - placeholder: t("images.new.form.title_placeholder"), - name: image_nested_field_name(image, :title), - id: image_nested_field_id(image, :title), - class: image.errors[:title].any? ? "error" : "" %> - <% if image.errors[:title].any? %> - <%= image.errors[:title].join(", ") %> - <% end %> -
- - <%= render_image(image, :thumb, false) if image.attachment.exists? %> - -
-
- <%= render_image_attachment(image) %> -
-
- <%= render_destroy_image_link(image) %> -
-
- -
-

- <%= image_attachment_file_name(image) %> -

-
- -
-
-
-
diff --git a/app/views/images/_nested_image.html.erb b/app/views/images/_nested_image.html.erb new file mode 100644 index 000000000..a981dd190 --- /dev/null +++ b/app/views/images/_nested_image.html.erb @@ -0,0 +1,25 @@ +
+ <%= f.label :image, t("images.form.title") %> +

<%= imageables_note(imageable) %>

+ +
+ <%= f.fields_for :image do |image_builder| %> + <%= render 'images/image_fields', f: image_builder, imageable: imageable %> + <% end %> +
+
+ +<%= link_to_add_association t('images.form.add_new_image'), f, :image, + force_non_association_create: true, + partial: "images/image_fields", + id: "new_image_link", + class: "button hollow #{"hide" if imageable.image.present?}", + render_options: { + locals: { imageable: imageable } + }, + data: { + association_insertion_node: "#nested-image", + association_insertion_method: "append" + } %> + +
diff --git a/app/views/images/_nested_images.html.erb b/app/views/images/_nested_images.html.erb deleted file mode 100644 index 31c8ba417..000000000 --- a/app/views/images/_nested_images.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -
- <%= label_tag :image, t("images.form.title") %> -

<%= imageables_note(imageable) %>

- - <%= render 'images/nested_fields', image: imageable.image, index: 0 if imageable.image.present? %> -
- -<% if imageable.image.blank? %> - <%= link_to t("images.form.add_new_image"), - new_nested_images_path(imageable_type: imageable.class.name, index: 0), - remote: true, - id: "new_image_link", - class: "button hollow" %> -<% end %> - -
diff --git a/app/views/images/destroy.js.erb b/app/views/images/destroy.js.erb index fddb55300..0fdac4b76 100644 --- a/app/views/images/destroy.js.erb +++ b/app/views/images/destroy.js.erb @@ -1,7 +1 @@ -App.Imageable.destroyNestedImage("<%= image_nested_field_wrapper_id %>", "<%= j render('layouts/flash') %>") -<% new_image_link = link_to t("images.form.add_new_image"), - new_nested_images_path(imageable_type: @image.imageable_type), - remote: true, - id: "new_image_link", - class: "button hollow" %> -App.Imageable.updateNewImageButton("<%= j new_image_link %>") +App.Imageable.destroyNestedImage("<%= dom_id(@image) %>") \ No newline at end of file diff --git a/app/views/images/new_nested.js.erb b/app/views/images/new_nested.js.erb deleted file mode 100644 index 00c00b132..000000000 --- a/app/views/images/new_nested.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -App.Imageable.new("<%= j render('images/nested_fields', image: @image) %>") -App.DirectUploads.initializeDirectUpload($('#nested_image input.direct_upload_attachment[type=file]')) \ No newline at end of file diff --git a/app/views/images/upload.js.erb b/app/views/images/upload.js.erb deleted file mode 100644 index 9177a35cd..000000000 --- a/app/views/images/upload.js.erb +++ /dev/null @@ -1,12 +0,0 @@ -<% if params[:nested_image] == "true" %> - - App.Imageable.uploadNestedImage("<%= image_nested_field_wrapper_id %>", - "<%= j render('images/nested_fields', image: @image) %>", - <%= @image.cached_attachment.present? %>) -<% else %> - - App.Imageable.uploadPlainImage("plain_image_fields", - "<%= j render('images/plain_fields', image: @image) %>", - <%= @image.cached_attachment.present? %>) - -<% end %> \ No newline at end of file diff --git a/app/views/proposals/_form.html.erb b/app/views/proposals/_form.html.erb index 16855cc03..df1e096e9 100644 --- a/app/views/proposals/_form.html.erb +++ b/app/views/proposals/_form.html.erb @@ -47,7 +47,7 @@
- <%= render 'images/nested_images', imageable: @proposal %> + <%= render 'images/nested_image', imageable: @proposal, f: f %>
diff --git a/config/routes.rb b/config/routes.rb index 8be1a8a7a..14a8faf19 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -102,9 +102,7 @@ Rails.application.routes.draw do resources :documents, only: [:new, :create, :destroy] - resources :images, only: [:new, :create, :destroy] do - get :new_nested, on: :collection - end + resources :images, only: [:new, :create, :destroy] resources :direct_uploads, only: [:create] delete "direct_uploads/destroy", to: "direct_uploads#destroy", as: :direct_upload_destroy diff --git a/spec/shared/features/imageable.rb b/spec/shared/features/imageable.rb index 3030869d3..a6e5ae4ae 100644 --- a/spec/shared/features/imageable.rb +++ b/spec/shared/features/imageable.rb @@ -159,6 +159,8 @@ shared_examples "imageable" do |imageable_factory_name, imageable_path, imageabl attach_image("spec/fixtures/files/clippy.jpg", true) + expect(page).to have_selector ".loading-bar.complete" + expect(page).to have_css("figure img") expect(page).not_to have_css("figure figcaption") end @@ -342,7 +344,9 @@ shared_examples "imageable" do |imageable_factory_name, imageable_path, imageabl end def attach_image(path, success = true) - attach_file :image_attachment, path, make_visible: true + image = find(".image") + image_input = image.find("input[type=file]", visible: false) + attach_file image_input[:id], path, make_visible: true if success expect(page).to have_css ".loading-bar.complete" else diff --git a/spec/shared/features/nested_documentable.rb b/spec/shared/features/nested_documentable.rb index 09c706d1f..cadc7d2da 100644 --- a/spec/shared/features/nested_documentable.rb +++ b/spec/shared/features/nested_documentable.rb @@ -195,21 +195,28 @@ shared_examples "nested documentable" do |documentable_factory_name, path, docum end scenario "Should show resource with new document after successful creation with maximum allowed uploaded files", :js do - skip "weird behavior" - # page.driver.resize_window 1200, 2500 + skip "due to weird behaviour" + page.driver.resize_window 1200, 2500 login_as user visit send(path, arguments) send(fill_resource_method_name) if fill_resource_method_name - documentable.class.max_documents_allowed.times.each do |index| - documentable_attach_new_file(documentable_factory_name, index , "spec/fixtures/files/empty.pdf") - end + click_link "Add new document" + click_link "Add new document" + click_link "Add new document" + documents = all(".document") + documents.each_with_index do |document, index| + document_input = document.find("input[type=file]", visible: false) + attach_file(document_input[:id], "spec/fixtures/files/empty.pdf", make_visible: true) + within all(".document")[index] do + expect(page).to have_css ".loading-bar.complete" + end + end click_on submit_button documentable_redirected_to_resource_show_or_navigate_to - save_screenshot expect(page).to have_content "Documents (#{documentable.class.max_documents_allowed})" end @@ -223,6 +230,26 @@ shared_examples "nested documentable" do |documentable_factory_name, path, docum expect(page).to have_css ".document", count: 1 end + scenario "Should not show add document button when documentable has reached maximum of documents allowed", :js do + login_as user + create_list(:document, documentable.class.max_documents_allowed, documentable: documentable) + visit send(path, arguments) + + expect(page).to have_css "#new_document_link", visible: false + end + + scenario "Should show add document button after destroy one document", :js do + login_as user + create_list(:document, documentable.class.max_documents_allowed, documentable: documentable) + visit send(path, arguments) + last_document = all("#nested-documents .document").last + within last_document do + click_on "Remove document" + end + + expect(page).to have_css "#new_document_link", visible: true + end + scenario "Should remove nested field after remove document", :js do login_as user create(:document, documentable: documentable) diff --git a/spec/shared/features/nested_imageable.rb b/spec/shared/features/nested_imageable.rb index ebbe4f9a2..242686bd6 100644 --- a/spec/shared/features/nested_imageable.rb +++ b/spec/shared/features/nested_imageable.rb @@ -27,16 +27,24 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p expect(page).to have_selector "#new_image_link", visible: true end + scenario "Should hide new image link after add one image" do + login_as user + visit send(path, arguments) + + click_on "Add image" + + expect(page).to have_selector "#new_image_link", visible: true + end + scenario "Should update nested image file name after choosing any file", :js do login_as user visit send(path, arguments) click_link "Add image" - # next line is to force capybara to wait for ajax response and new DOM elements rendering - find("input[name='#{imageable_factory_name}[image_attributes]attachment']", visible: false) - attach_file("#{imageable_factory_name}[image_attributes]attachment", "spec/fixtures/files/empty.pdf", make_visible: true) + image_input = find(".image").find("input[type=file]", visible: false) + attach_file(image_input[:id], "spec/fixtures/files/clippy.jpg", make_visible: true) - expect(page).to have_selector ".file-name", text: "empty.pdf" + expect(page).to have_selector ".file-name", text: "clippy.jpg" end scenario "Should update nested image file title with file name after choosing a file when no title defined", :js do @@ -45,7 +53,7 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p imageable_attach_new_file(imageable_factory_name, "spec/fixtures/files/clippy.jpg") - expect(find("##{imageable_factory_name}_image_attributes_title").value).to eq("clippy.jpg") + expect_image_has_title("clippy.jpg") end scenario "Should not update nested image file title with file name after choosing a file when title already defined", :js do @@ -53,10 +61,10 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p visit send(path, arguments) click_link "Add image" - fill_in "#{imageable_factory_name}[image_attributes]title", with: "Title" - attach_file("#{imageable_factory_name}[image_attributes]attachment", "spec/fixtures/files/empty.pdf", make_visible: true) - # force capybara to wait for AJAX response to ensure new input has correct value after direct upload - have_css(".loading-bar.complete") + input_title = find(".image input[name$='[title]']") + fill_in input_title[:id], with: "Title" + image_input = find(".image").find("input[type=file]", visible: false) + attach_file(image_input[:id], "spec/fixtures/files/clippy.jpg", make_visible: true) expect(find("##{imageable_factory_name}_image_attributes_title").value).to eq "Title" end @@ -85,7 +93,7 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p imageable_attach_new_file(imageable_factory_name, "spec/fixtures/files/clippy.jpg") - expect(page).to have_selector("input[name='#{imageable_factory_name}[image_attributes]cached_attachment'][value$='.jpg']", visible: false) + expect_image_has_cached_attachment(".jpg") end scenario "Should not update image cached_attachment field after unvalid file upload", :js do @@ -94,7 +102,7 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p imageable_attach_new_file(imageable_factory_name, "spec/fixtures/files/logo_header.png", false) - expect(find("input[name='#{imageable_factory_name}[image_attributes]cached_attachment']", visible: false).value).to eq "" + expect_image_has_cached_attachment("") end scenario "Should show nested image errors after unvalid form submit", :js do @@ -102,34 +110,23 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p visit send(path, arguments) click_link "Add image" - find("input[id$='_image_attributes_title']") # force to wait for ajax response new DOM elements click_on submit_button - expect(page).to have_css("#nested_image .error") + within "#nested-image .image" do + expect(page).to have_content("can't be blank", count: 2) + end end - scenario "Should delete image after valid file upload and click on remove button", :js do + scenario "Should remove nested image after valid file upload and click on remove button", :js do login_as user visit send(path, arguments) imageable_attach_new_file(imageable_factory_name, "spec/fixtures/files/clippy.jpg") - within "#nested_image" do + within "#nested-image .image" do click_link "Remove image" end - expect(page).not_to have_selector("#nested_image") - end - - scenario "Should delete image after valid file upload and click on remove button", :js do - login_as user - visit send(path, arguments) - - imageable_attach_new_file(imageable_factory_name, "spec/fixtures/files/clippy.jpg") - within "#nested_image" do - click_link "Remove image" - end - - expect(page).not_to have_css "#nested_image" + expect(page).not_to have_selector("#nested-image .image") end scenario "Should show successful notice when resource filled correctly without any nested images", :js do @@ -162,10 +159,48 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p click_on submit_button imageable_redirected_to_resource_show_or_navigate_to - expect(page).to have_selector "figure .image" + expect(page).to have_selector "figure img" expect(page).to have_selector "figure figcaption" end + if path.include? "edit" + + scenario "Should show persisted image" do + login_as user + create(:image, imageable: imageable) + visit send(path, arguments) + + expect(page).to have_css ".image", count: 1 + end + + scenario "Should not show add image button when image already exists", :js do + login_as user + create(:image, imageable: imageable) + visit send(path, arguments) + + expect(page).to have_css "a#new_image_link", visible: false + end + + scenario "Should remove nested field after remove image", :js do + login_as user + create(:image, imageable: imageable) + visit send(path, arguments) + click_on "Remove image" + + expect(page).not_to have_css ".image" + end + + scenario "Should show add image button after remove image", :js do + login_as user + create(:image, imageable: imageable) + visit send(path, arguments) + click_on "Remove image" + + expect(page).to have_css "a#new_image_link", visible: true + end + + end + end end @@ -179,14 +214,17 @@ end def imageable_attach_new_file(imageable_factory_name, path, success = true) click_link "Add image" - # next line is to force capybara to wait for ajax response and new DOM elements rendering - find("input[name='#{imageable_factory_name}[image_attributes]attachment']", visible: false) - attach_file("#{imageable_factory_name}[image_attributes]attachment", path, make_visible: true) - # next line is to force capybara to wait for ajax response and new DOM elements rendering - if success - expect(page).to have_css(".loading-bar.complete") - else - expect(page).to have_css(".loading-bar.errors") + within "#nested-image" do + image = find(".image") + image_input = image.find("input[type=file]", visible: false) + attach_file(image_input[:id], path, make_visible: true) + 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 @@ -202,4 +240,22 @@ def imageable_fill_new_valid_budget_investment fill_in :budget_investment_title, with: "Budget investment title" fill_in_ckeditor "budget_investment_description", with: "Budget investment description" check :budget_investment_terms_of_service +end + +def expect_image_has_title(title) + image = find(".image") + + within image do + expect(find("input[name$='[title]']").value).to eq title + end +end + +def expect_image_has_cached_attachment(extension) + within "#nested-image" do + image = find(".image") + + within image do + expect(find("input[name$='[cached_attachment]']", visible: false).value).to end_with(extension) + end + end end \ No newline at end of file