From 2530ae9859c7483d3ed2a7900ad304be847b4628 Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Tue, 28 Aug 2018 11:46:51 +0200 Subject: [PATCH 01/15] ADD has_preview, tests for has_preview and read_only --- .../binda/components/form_item.scss | 9 ++++ .../binda/field_groups_controller.rb | 4 +- .../binda/field_settings_controller.rb | 2 +- .../_form_item_editor_existing_item.html.erb | 5 +- config/locales/en.yml | 1 + db/migrate/1_create_binda_tables.rb | 1 + ...add_has_preview_to_binda_field_settings.rb | 5 ++ ...ec.rb => field_groups_edit_editor_spec.rb} | 49 ++++++++++++++++++- spec/models/binda/field_setting_spec.rb | 29 ++++++++++- 9 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20180828084441_add_has_preview_to_binda_field_settings.rb rename spec/features/{field_groups_edit__editor_spec.rb => field_groups_edit_editor_spec.rb} (78%) diff --git a/app/assets/stylesheets/binda/components/form_item.scss b/app/assets/stylesheets/binda/components/form_item.scss index 9fa46fad..4391172d 100644 --- a/app/assets/stylesheets/binda/components/form_item.scss +++ b/app/assets/stylesheets/binda/components/form_item.scss @@ -8,6 +8,15 @@ padding: 12px; } +.form-item--quarter-size { + display: inline-block; + width: calc(25% - 3px); + + .form-group { + border-top: none !important; + } +} + .form-item--half-size { // OLD SOLUTION (nicer, but can't be used with max-height=0 and overflow-y=hidden) // position: relative; diff --git a/app/controllers/binda/field_groups_controller.rb b/app/controllers/binda/field_groups_controller.rb index 556771c8..265ec450 100644 --- a/app/controllers/binda/field_groups_controller.rb +++ b/app/controllers/binda/field_groups_controller.rb @@ -95,7 +95,7 @@ def set_field_group def field_group_params params.require(:field_group).permit( :name, :slug, :description, :position, :layout, :structure_id, field_settings_attributes: [ - :id, :field_group_id, :field_setting_id, :name, :slug, :description, :field_type, :position, :required, :read_only, :default_text, :ancestry, :default_choice_id, :allow_null, accepted_structure_ids: [], choices: [], choices_attributes: [ + :id, :field_group_id, :field_setting_id, :name, :slug, :description, :field_type, :position, :required, :read_only, :has_preview, :default_text, :ancestry, :default_choice_id, :allow_null, accepted_structure_ids: [], choices: [], choices_attributes: [ :id, :field_setting_id, :label, :value ] ] @@ -105,7 +105,7 @@ def field_group_params def new_params params.require(:field_group).permit( new_field_settings: [ - :id, :field_group_id, :field_setting_id, :name, :slug, :description, :field_type, :position, :required, :read_only, :ancestry, :default_choice_id, :allow_null, choices: [] + :id, :field_group_id, :field_setting_id, :name, :slug, :description, :field_type, :position, :required, :read_only, :has_preview, :ancestry, :default_choice_id, :allow_null, choices: [] ], new_choices: [ :id, :field_setting_id, :label, :value diff --git a/app/controllers/binda/field_settings_controller.rb b/app/controllers/binda/field_settings_controller.rb index 4a2cbff7..20885c46 100644 --- a/app/controllers/binda/field_settings_controller.rb +++ b/app/controllers/binda/field_settings_controller.rb @@ -72,7 +72,7 @@ def set_field_setting # Only allow a trusted parameter "white list" through. def field_setting_params - params.require(:field_setting).permit(:name, :slug, :description, :position, :required, :default_text, :field_group_id, :field_type ) + params.require(:field_setting).permit(:name, :slug, :description, :position, :preview, :required, :default_text, :field_group_id, :field_type ) end end end diff --git a/app/views/binda/field_groups/form_item/_form_item_editor_existing_item.html.erb b/app/views/binda/field_groups/form_item/_form_item_editor_existing_item.html.erb index bc7390dd..e646f690 100644 --- a/app/views/binda/field_groups/form_item/_form_item_editor_existing_item.html.erb +++ b/app/views/binda/field_groups/form_item/_form_item_editor_existing_item.html.erb @@ -8,9 +8,12 @@ <%= ff.input :field_type, as: :string, disabled: true, input_html: { class: "form-item--input" } %> <% end %> -
+
<%= ff.input :read_only, as: :boolean, label: " #{ t('binda.read_only')}".html_safe, wrapper_html: { class: 'standard-form--radio' } %>
+
+ <%= ff.input :has_preview, as: :boolean, label: " #{ t('binda.preview')}".html_safe, wrapper_html: { class: 'standard-form--radio' } %> +
<%= ff.input :description, input_html: { class: "form-item--input tinymce" } %>
diff --git a/config/locales/en.yml b/config/locales/en.yml index a0ba8b14..1911f464 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -118,6 +118,7 @@ en: has_categories: Enable categories has_preview: Enable preview read_only: Read Only + preview: Preview has_categories_hint: Enable a taxonomy specific to this structure preview_path_warning: Make preview available. Once enabled, remember to create a route in you application for relation_warning: This relation isn't set properly. Ensure the setup of this relation refers to at least one structure. diff --git a/db/migrate/1_create_binda_tables.rb b/db/migrate/1_create_binda_tables.rb index ac35b02e..c0eecff5 100644 --- a/db/migrate/1_create_binda_tables.rb +++ b/db/migrate/1_create_binda_tables.rb @@ -49,6 +49,7 @@ def change t.integer :position t.boolean :required, default: false t.boolean :read_only, default: false + t.boolean :preview, default: false t.text :default_text t.string :field_type t.belongs_to :field_group diff --git a/db/migrate/20180828084441_add_has_preview_to_binda_field_settings.rb b/db/migrate/20180828084441_add_has_preview_to_binda_field_settings.rb new file mode 100644 index 00000000..d176cc33 --- /dev/null +++ b/db/migrate/20180828084441_add_has_preview_to_binda_field_settings.rb @@ -0,0 +1,5 @@ +class AddHasPreviewToBindaFieldSettings < ActiveRecord::Migration[5.1] + def change + add_column :binda_field_settings, :has_preview, :boolean, default: false + end +end diff --git a/spec/features/field_groups_edit__editor_spec.rb b/spec/features/field_groups_edit_editor_spec.rb similarity index 78% rename from spec/features/field_groups_edit__editor_spec.rb rename to spec/features/field_groups_edit_editor_spec.rb index c666ad03..8dd0cc74 100644 --- a/spec/features/field_groups_edit__editor_spec.rb +++ b/spec/features/field_groups_edit_editor_spec.rb @@ -138,6 +138,53 @@ it "allows to sort field settings" do skip "not implemented yet" - end + end + + it "allows to mark a field setting as read only" do + field_group = @structure.field_groups.first + field_setting = field_group.field_settings.create!(name: 'read-only-test', field_type: 'string') + path_to_field_group = binda.edit_structure_field_group_path( structure_id: @structure.slug, id: field_group.slug ) + visit path_to_field_group + + within "#form--list-item-#{field_setting.id}" do + find('.form-item--collapse-btn').click + # Make sure the form item appeared + sleep 1 + end + + find("#read-only").click + # Make sure the form item appeared + sleep 1 + click_button "save" + + # look for anything, just to make sure the page isn't throwing a error + expect(page).to have_field("field_group_name", with: field_group.name) + end + + it "allows to mark a field setting as has_preview" do + field_group = @structure.field_groups.first + field_setting = field_group.field_settings.create!(name: 'has-preview-test', field_type: 'string') + path_to_field_group = binda.edit_structure_field_group_path( structure_id: @structure.slug, id: field_group.slug ) + visit path_to_field_group + + within "#form--list-item-#{field_setting.id}" do + find('.form-item--collapse-btn').click + # Make sure the form item appeared + sleep 1 + end + + find("#has-preview").click + # Make sure the form item appeared + sleep 1 + click_button "save" + + # look for anything, just to make sure the page isn't throwing a error + expect(page).to have_field("field_group_name", with: field_group.name) + end + + it "allows to mark a field setting as required" do + # TODO MARCO P + skip "not implemented yet" + end end diff --git a/spec/models/binda/field_setting_spec.rb b/spec/models/binda/field_setting_spec.rb index 7e5617f1..00189216 100644 --- a/spec/models/binda/field_setting_spec.rb +++ b/spec/models/binda/field_setting_spec.rb @@ -29,7 +29,7 @@ module Binda ).first }.not_to raise_error end - it "generates a field #{field_class.downcase.underscore} for each component to which is associated" do + it "generates a field #{field_class.downcase.underscore} for each board to which is associated" do field_setting = create( :field_setting, field_type: field_class.underscore, @@ -262,5 +262,32 @@ module Binda expect(second_field_setting.reload.position).to eq 1 expect(first_field_setting.reload.position).to eq 2 end + + it "isn't read only by default" do + pending("not implemented yet") + end + + it "can be read only" do + pending("not implemented yet") + end + + + it "hasn't a preview by default" do + pending("not implemented yet") + end + + it "can have a preview" do + pending("not implemented yet") + end + + + it "isn't required by default" do + pending("not implemented yet") + end + + it "can be required" do + pending("not implemented yet") + end + end end \ No newline at end of file From bff62e57952142b25eb0634c1a227dd32461f196 Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Tue, 28 Aug 2018 11:53:01 +0200 Subject: [PATCH 02/15] ADD required and feature test for it --- .../binda/components/form_item.scss | 4 ++-- .../_form_item_editor_existing_item.html.erb | 7 +++++-- config/locales/en.yml | 1 + .../features/field_groups_edit_editor_spec.rb | 20 +++++++++++++++++-- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/binda/components/form_item.scss b/app/assets/stylesheets/binda/components/form_item.scss index 4391172d..67c012da 100644 --- a/app/assets/stylesheets/binda/components/form_item.scss +++ b/app/assets/stylesheets/binda/components/form_item.scss @@ -8,9 +8,9 @@ padding: 12px; } -.form-item--quarter-size { +.form-item--sixth-size { display: inline-block; - width: calc(25% - 3px); + width: calc(16.6% - 3px); .form-group { border-top: none !important; diff --git a/app/views/binda/field_groups/form_item/_form_item_editor_existing_item.html.erb b/app/views/binda/field_groups/form_item/_form_item_editor_existing_item.html.erb index e646f690..999184ff 100644 --- a/app/views/binda/field_groups/form_item/_form_item_editor_existing_item.html.erb +++ b/app/views/binda/field_groups/form_item/_form_item_editor_existing_item.html.erb @@ -8,12 +8,15 @@ <%= ff.input :field_type, as: :string, disabled: true, input_html: { class: "form-item--input" } %> <% end %>
-
+
<%= ff.input :read_only, as: :boolean, label: " #{ t('binda.read_only')}".html_safe, wrapper_html: { class: 'standard-form--radio' } %>
-
+
<%= ff.input :has_preview, as: :boolean, label: " #{ t('binda.preview')}".html_safe, wrapper_html: { class: 'standard-form--radio' } %>
+
+ <%= ff.input :required, as: :boolean, label: " #{ t('binda.required')}".html_safe, wrapper_html: { class: 'standard-form--radio' } %> +
<%= ff.input :description, input_html: { class: "form-item--input tinymce" } %>
diff --git a/config/locales/en.yml b/config/locales/en.yml index 1911f464..ac2ace62 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -119,6 +119,7 @@ en: has_preview: Enable preview read_only: Read Only preview: Preview + required: Required has_categories_hint: Enable a taxonomy specific to this structure preview_path_warning: Make preview available. Once enabled, remember to create a route in you application for relation_warning: This relation isn't set properly. Ensure the setup of this relation refers to at least one structure. diff --git a/spec/features/field_groups_edit_editor_spec.rb b/spec/features/field_groups_edit_editor_spec.rb index 8dd0cc74..37ee11bd 100644 --- a/spec/features/field_groups_edit_editor_spec.rb +++ b/spec/features/field_groups_edit_editor_spec.rb @@ -183,8 +183,24 @@ end it "allows to mark a field setting as required" do - # TODO MARCO P - skip "not implemented yet" + field_group = @structure.field_groups.first + field_setting = field_group.field_settings.create!(name: 'is-required-test', field_type: 'string') + path_to_field_group = binda.edit_structure_field_group_path( structure_id: @structure.slug, id: field_group.slug ) + visit path_to_field_group + + within "#form--list-item-#{field_setting.id}" do + find('.form-item--collapse-btn').click + # Make sure the form item appeared + sleep 1 + end + + find("#is-required").click + # Make sure the form item appeared + sleep 1 + click_button "save" + + # look for anything, just to make sure the page isn't throwing a error + expect(page).to have_field("field_group_name", with: field_group.name) end end From 06804e3daa91eb427f93f4c17a887ff761298150 Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Wed, 29 Aug 2018 12:08:27 +0200 Subject: [PATCH 03/15] ADD tests for preview, require and read only --- spec/models/binda/field_setting_spec.rb | 54 ++++++++++++++++--------- spec/models/binda/image_spec.rb | 41 +++++++++++++++++++ 2 files changed, 75 insertions(+), 20 deletions(-) diff --git a/spec/models/binda/field_setting_spec.rb b/spec/models/binda/field_setting_spec.rb index 00189216..50716ebe 100644 --- a/spec/models/binda/field_setting_spec.rb +++ b/spec/models/binda/field_setting_spec.rb @@ -263,31 +263,45 @@ module Binda expect(first_field_setting.reload.position).to eq 2 end - it "isn't read only by default" do - pending("not implemented yet") - end - - it "can be read only" do - pending("not implemented yet") - end - + FieldSetting.get_field_classes.each do |field_class| + it "#{field_class} isn't read only by default" do + first_field_setting = create(:field_setting, + field_type: field_class.underscore) + expect(first_field_setting.read_only?).to be(false) + end - it "hasn't a preview by default" do - pending("not implemented yet") - end + it "#{field_class} can be read only" do + first_field_setting = create(:field_setting, + field_type: field_class.underscore) + first_field_setting.read_only = true + expect(first_field_setting.save).to be true + end - it "can have a preview" do - pending("not implemented yet") - end + it "#{field_class} hasn't a preview by default" do + first_field_setting = create(:field_setting, + field_type: field_class.underscore) + expect(first_field_setting.has_preview?).to be(false) + end + it "#{field_class} can have a preview" do + first_field_setting = create(:field_setting, + field_type: field_class.underscore) + first_field_setting.has_preview = true + expect(first_field_setting.save).to be true + end - it "isn't required by default" do - pending("not implemented yet") - end + it "#{field_class} isn't required by default" do + first_field_setting = create(:field_setting, + field_type: field_class.underscore) + expect(first_field_setting.required?).to be(false) + end - it "can be required" do - pending("not implemented yet") + it "#{field_class} can be required" do + first_field_setting = create(:field_setting, + field_type: field_class.underscore) + first_field_setting.required = true + expect(first_field_setting.save).to be true + end end - end end \ No newline at end of file diff --git a/spec/models/binda/image_spec.rb b/spec/models/binda/image_spec.rb index 8fdbc678..160f67ec 100644 --- a/spec/models/binda/image_spec.rb +++ b/spec/models/binda/image_spec.rb @@ -41,5 +41,46 @@ module Binda it "registers details if you call register_details method (also in rake task)" do skip("don't know how to test it") end + + describe "when is read only" do + it "blocks any upload" do + @component = create(:component) + @image_setting = create(:image_setting, field_group_id: @component.structure.field_groups.first.id) + @image_setting.read_only = true + image_name = 'test-image.jpg' + image_path = ::Binda::Engine.root.join('spec', 'support', image_name) + image_record = @component.reload.images.first + image_record.image = image_path.open + expect(image_record.save!).to be(false) + end + describe "when there is already a image" do + it "avoid image to be deleted" do + @component = create(:component) + @image_setting = create(:image_setting, field_group_id: @component.structure.field_groups.first.id) + image_name = 'test-image.jpg' + image_path = ::Binda::Engine.root.join('spec', 'support', image_name) + image_record = @component.reload.images.first + image_record.image = image_path.open + expect(image_record.save!).to be_truthy + @image_setting.read_only = true + expect(image_record.image.remove!).to be(false) + end + it "blocks any update" do + @component = create(:component) + @image_setting = create(:image_setting, field_group_id: @component.structure.field_groups.first.id) + image_name = 'test-image.jpg' + image_path = ::Binda::Engine.root.join('spec', 'support', image_name) + image_record = @component.reload.images.first + image_record.image = image_path.open + expect(image_record.save!).to be_truthy + @image_setting.read_only = true + image_name = 'test-image.jpg' + image_path = ::Binda::Engine.root.join('spec', 'support', image_name) + image_record = @component.reload.images.first + image_record.image = image_path.open + expect(image_record.save!).to be(false) + end + end + end end end From 481049d97afbf7670ade127784a2403f50b71053 Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Tue, 4 Sep 2018 12:59:47 +0200 Subject: [PATCH 04/15] ADD task for cleaning dummy app --- app/models/concerns/binda/fields.rb | 27 +++++++++++++++++++++++-- config/initializers/devise.rb | 6 ++---- lib/tasks/clean_dummy_app.rake | 31 +++++++++++++++++++++++++++++ spec/models/binda/radio_spec.rb | 9 +++++++++ 4 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 lib/tasks/clean_dummy_app.rake diff --git a/app/models/concerns/binda/fields.rb b/app/models/concerns/binda/fields.rb index 3720ac3e..8a3662b3 100644 --- a/app/models/concerns/binda/fields.rb +++ b/app/models/concerns/binda/fields.rb @@ -1,3 +1,22 @@ +require 'pry' + +class ReadOnlyValidator < ActiveModel::Validator + def validate(record) +=begin + binding.pry +=end +=begin + get field setting of current record + return false if field setting has been set to read only + else true +=end + +=begin + !record.read_only? +=end + end +end + module Binda # Fieldable associated are Binda's core fields. # @@ -14,8 +33,12 @@ module Fields validates :field_setting, presence: true validates :fieldable_id, presence: true - validates :fieldable_type, presence: true + validates :fieldable_type, presence: true + include ActiveModel::Validations + validates_with ReadOnlyValidator end - end end + + + diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 2abb684b..5d7f5baa 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -16,8 +16,7 @@ # by default. You can change it below and use your own secret key. # config.secret_key = 'a8395fa034e067da620d70f7f39ad4765d163e44ce05d5c243393e1bbfdc10f9a464aaf34fcac3291a6746424ea2b9f9564a01c31820e28bf1737c16d139cd5c' # binda.hook.1 - config.secret_key = '81113efa8b7abba0674471b5b4429cb9da5182d3eab248be196f58f62f8de2c3a7174fcf0f17fbf32bb0e76ba46c02410fecef1101d9da64c010bab2104aba6e' - config.secret_key = '940fcbf616f851acdbcfb5af5629435e0ce550b51a0bf1db4cfb609b537d93b98a9ddefbf03a8274fa59a6483fe82df3aa1a6609a8ca0e62ae3269a91374cccd' + config.secret_key = 'b92bf46fe2bb9554025eaaa638e127a97958df22e965fbc4cc065e0b47abdcd63029442b5714b2824784f3149a585cf5c7bf5a6c73cbb2f5a167b75180ec0fe2' # ==> Mailer Configuration # Configure the e-mail address which will be shown in Devise::Mailer, @@ -115,8 +114,7 @@ # Set up a pepper to generate the hashed password. # config.pepper = '124ef1b08a92f891a392a9594b868887c945ca8438bd7852f8ac4d91e51f2cc699b8b6c7b12057c0f0e6dc03d04f8ee4eab72278b0f948e2c1e43f8b449c2262' # binda.hook.2 - config.pepper = '03af0d695bb86b8274e1f93261a7f885ca85f0e2356cd3fd279ad13ac70af811a1f7d221de07c137aadc327e1f95b3b00ca6ed8836d09010893631c1eb01a36c' - config.pepper = '0586297a053d9c535c607464fb45c15325e4faa6f31f1b5361a431c1978c2dce2776047cef7b89500600bbfa82818b853ab896ad8b48334656bb907a06c8a9bb' + config.pepper = 'fb7dd6ba2c94638fdf2c4500f44788e7d491b9cb985be333f6c2c83514ce6759cab1e05ba9e02cb568231239f8054878984d1670bb269162f0139c402340de12' # Send a notification email when the user's password is changed # config.send_password_change_notification = false diff --git a/lib/tasks/clean_dummy_app.rake b/lib/tasks/clean_dummy_app.rake new file mode 100644 index 00000000..6bcdc7d0 --- /dev/null +++ b/lib/tasks/clean_dummy_app.rake @@ -0,0 +1,31 @@ +namespace :binda do + + desc "Update dummy app migrations and schema" + task :update_dummy => :environment do + puts "---------------------" + puts "Remove current schema" + puts "---------------------" + sh "cd #{Rails.root} && rm -r db/schema.rb" + puts "" + puts "----------------------------------------------" + puts "Drop and create new dev db, then install Binda" + puts "----------------------------------------------" + sh "rails db:drop && rails db:create && rails generate binda:install" + puts "" + puts "--------------------------------------------------" + puts "Remove old dummy migrations and devise config file" + puts "--------------------------------------------------" + sh "rm -rf #{Rails.root}/db/migrate && rm -rf #{Rails.root}/config/initializers/devise_backup_*.rb && + cd #{Rails.root}/../.." + puts "" + puts "------------------------" + puts "Create new clean test db" + puts "------------------------" + sh "rails db:drop RAILS_ENV=test && rails db:create RAILS_ENV=test && rails db:migrate RAILS_ENV=test" + puts "" + puts "------------------------" + puts "Dummy updated" + puts "------------------------" + end + +end \ No newline at end of file diff --git a/spec/models/binda/radio_spec.rb b/spec/models/binda/radio_spec.rb index 37f65325..be7f0236 100644 --- a/spec/models/binda/radio_spec.rb +++ b/spec/models/binda/radio_spec.rb @@ -37,5 +37,14 @@ module Binda skip('not implemented yet') end + it "shouldn't let you select choice if read only" do + radio = @component.radios.first + radio.choices.clear + @radio_setting.read_only = true + + radio.choices << @radio_setting.choices.first + expect( radio.choices.first.id ).to be( nil ) + end + end end From 97e6b5f1b2789cedc02ebbbca0d02bae06baef98 Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Tue, 6 Nov 2018 11:06:57 +0100 Subject: [PATCH 05/15] ADD read only model validation --- app/models/binda/image.rb | 9 ++++++++- app/views/binda/components/index.html.erb | 2 -- spec/models/binda/image_spec.rb | 5 +++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/models/binda/image.rb b/app/models/binda/image.rb index 4d068253..9c4cae80 100644 --- a/app/models/binda/image.rb +++ b/app/models/binda/image.rb @@ -4,6 +4,13 @@ class Image < Asset mount_uploader :image, ImageUploader + validate :is_read_only + + # Check if is read_only + def is_read_only + errors.add(:base, "This instance is read_only. You can't upload an image") if self.field_setting.read_only? + end + # Register image details # # Do not delete. This method is used by a rake task @@ -18,7 +25,7 @@ def register_details register_details_of(file) end end - + # Register image details # # This method is used by register_details in a rake task diff --git a/app/views/binda/components/index.html.erb b/app/views/binda/components/index.html.erb index be647770..e336fcb6 100644 --- a/app/views/binda/components/index.html.erb +++ b/app/views/binda/components/index.html.erb @@ -2,7 +2,6 @@ <%= @structure.name.humanize.split.map(&:capitalize).join(' ').pluralize %> <% end %> - <% content_for :header do %>
<% end %> - <% content_for :content do %>
" end end @@ -86,7 +88,7 @@ module Details def detail(wrapper_options = nil) @detail ||= begin obj = options[:object] - + html = '' - end end + end # Used when the preview is optional def has_detail? diff --git a/config/initializers/simple_form_custom.rb b/config/initializers/simple_form_custom.rb index 3e93c273..afb81c62 100644 --- a/config/initializers/simple_form_custom.rb +++ b/config/initializers/simple_form_custom.rb @@ -120,11 +120,72 @@ b.optional :readonly b.use :preview + + # ApplicationController.render( + # assigns: { builder: b }, + # template: 'binda/fieldable/_form_item_upload_file', + # layout: false + # ) + b.wrapper tag: 'div', class: 'fileupload--dashboard' do |bb| bb.use :label, class: 'control-label b-btn b-btn-primary', wrap_with: { tag: 'div', class: 'control-label-wrap' } bb.use :delete_button bb.use :detail end + + b.use :input + end + + config.wrappers :file_read_only do |b| + b.optional :error, wrap_with: { tag: 'span', class: 'help-block' } + b.wrapper tag: :p, class: 'help-block', unless_blank: true do |bb| + bb.optional :hint + end + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :readonly + + b.use :preview + + # ApplicationController.render( + # assigns: { builder: b }, + # template: 'binda/fieldable/_form_item_upload_file', + # layout: false + # ) + + b.wrapper tag: 'div', class: 'fileupload--dashboard' do |bb| + bb.use :delete_button + bb.use :detail + end + + b.use :input + end + + config.wrappers :file_uploadable do |b| + b.optional :error, wrap_with: { tag: 'span', class: 'help-block' } + b.wrapper tag: :p, class: 'help-block', unless_blank: true do |bb| + bb.optional :hint + end + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :readonly + + b.use :preview + + # ApplicationController.render( + # assigns: { builder: b }, + # template: 'binda/fieldable/_form_item_upload_file', + # layout: false + # ) + + b.wrapper tag: 'div', class: 'fileupload--dashboard' do |bb| + bb.use :label, class: 'control-label b-btn b-btn-primary', wrap_with: { tag: 'div', class: 'control-label-wrap' } + bb.use :delete_button + bb.use :detail + end + b.use :input end @@ -139,7 +200,7 @@ ba.use :label_input end end - + config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| b.use :html5 b.optional :readonly @@ -168,7 +229,8 @@ config.wrapper_mappings = { check_boxes: :vertical_radio_and_checkboxes, radio_buttons: :vertical_radio_and_checkboxes, - file: :fileupload, + file: :file_uploadable, + file2: :file_read_only, boolean: :vertical_boolean, datetime: :multi_select, date: :multi_select, From 39163d557a73088f87a9dd330728ea0d7e39da8c Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Tue, 6 Nov 2018 18:16:15 +0100 Subject: [PATCH 07/15] ADD feature test for read only --- Gemfile.lock | 5 +- .../fieldable/_form_item_upload_file.html.erb | 6 - binda.gemspec | 1 + config/initializers/cypress_dev.rb | 9 + config/initializers/simple_form_custom.rb | 15 +- package.json | 1 + spec/cypress.json | 4 + .../app_commands/activerecord_fixtures.rb | 21 + spec/cypress/app_commands/clean.rb | 8 + spec/cypress/app_commands/eval.rb | 1 + spec/cypress/app_commands/factory_bot.rb | 12 + spec/cypress/app_commands/scenarios/basic.rb | 3 + spec/cypress/cypress_helper.rb | 30 + spec/cypress/fixtures/example.json | 5 + .../integration/examples/actions.spec.js | 272 +++++++ .../integration/examples/aliasing.spec.js | 42 ++ .../integration/examples/assertions.spec.js | 63 ++ .../integration/examples/connectors.spec.js | 55 ++ .../integration/examples/cookies.spec.js | 78 ++ .../integration/examples/cypress_api.spec.js | 211 ++++++ .../integration/examples/files.spec.js | 86 +++ .../examples/local_storage.spec.js | 52 ++ .../integration/examples/location.spec.js | 32 + .../cypress/integration/examples/misc.spec.js | 68 ++ .../integration/examples/navigation.spec.js | 54 ++ .../examples/network_requests.spec.js | 108 +++ .../integration/examples/querying.spec.js | 65 ++ .../examples/spies_stubs_clocks.spec.js | 62 ++ .../integration/examples/traversal.spec.js | 121 +++ .../integration/examples/utilities.spec.js | 89 +++ .../integration/examples/viewport.spec.js | 59 ++ .../integration/examples/waiting.spec.js | 34 + .../integration/examples/window.spec.js | 22 + .../integration/rails_examples/other_spec.js | 25 + .../rails_examples/using_factory_bot.js | 31 + .../rails_examples/using_fixtures.js | 33 + .../rails_examples/using_scenarios_spec.js | 26 + spec/cypress/support/commands.js | 25 + spec/cypress/support/index.js | 21 + spec/cypress/support/on-rails.js | 37 + spec/dummy/config/environments/test.rb | 2 +- spec/features/components_edit_spec.rb | 13 +- yarn.lock | 709 +++++++++++++++++- 43 files changed, 2581 insertions(+), 35 deletions(-) delete mode 100644 app/views/binda/fieldable/_form_item_upload_file.html.erb create mode 100644 config/initializers/cypress_dev.rb create mode 100644 spec/cypress.json create mode 100644 spec/cypress/app_commands/activerecord_fixtures.rb create mode 100644 spec/cypress/app_commands/clean.rb create mode 100644 spec/cypress/app_commands/eval.rb create mode 100644 spec/cypress/app_commands/factory_bot.rb create mode 100644 spec/cypress/app_commands/scenarios/basic.rb create mode 100644 spec/cypress/cypress_helper.rb create mode 100644 spec/cypress/fixtures/example.json create mode 100644 spec/cypress/integration/examples/actions.spec.js create mode 100644 spec/cypress/integration/examples/aliasing.spec.js create mode 100644 spec/cypress/integration/examples/assertions.spec.js create mode 100644 spec/cypress/integration/examples/connectors.spec.js create mode 100644 spec/cypress/integration/examples/cookies.spec.js create mode 100644 spec/cypress/integration/examples/cypress_api.spec.js create mode 100644 spec/cypress/integration/examples/files.spec.js create mode 100644 spec/cypress/integration/examples/local_storage.spec.js create mode 100644 spec/cypress/integration/examples/location.spec.js create mode 100644 spec/cypress/integration/examples/misc.spec.js create mode 100644 spec/cypress/integration/examples/navigation.spec.js create mode 100644 spec/cypress/integration/examples/network_requests.spec.js create mode 100644 spec/cypress/integration/examples/querying.spec.js create mode 100644 spec/cypress/integration/examples/spies_stubs_clocks.spec.js create mode 100644 spec/cypress/integration/examples/traversal.spec.js create mode 100644 spec/cypress/integration/examples/utilities.spec.js create mode 100644 spec/cypress/integration/examples/viewport.spec.js create mode 100644 spec/cypress/integration/examples/waiting.spec.js create mode 100644 spec/cypress/integration/examples/window.spec.js create mode 100644 spec/cypress/integration/rails_examples/other_spec.js create mode 100644 spec/cypress/integration/rails_examples/using_factory_bot.js create mode 100644 spec/cypress/integration/rails_examples/using_fixtures.js create mode 100644 spec/cypress/integration/rails_examples/using_scenarios_spec.js create mode 100644 spec/cypress/support/commands.js create mode 100644 spec/cypress/support/index.js create mode 100644 spec/cypress/support/on-rails.js diff --git a/Gemfile.lock b/Gemfile.lock index b2aa04fc..9fe60a56 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -97,6 +97,8 @@ GEM coderay (1.1.2) concurrent-ruby (1.0.5) crass (1.0.4) + cypress-on-rails (1.1.1) + rack database_cleaner (1.7.0) devise (4.4.3) bcrypt (~> 3.0) @@ -338,6 +340,7 @@ DEPENDENCIES binda! bullet (>= 5.6, < 6) capybara (>= 2.14, < 3) + cypress-on-rails (~> 1.1) database_cleaner (>= 1.6, < 2) factory_bot_rails (~> 4.8) generator_spec (~> 0.9.4) @@ -356,4 +359,4 @@ DEPENDENCIES yard-activesupport-concern (~> 0.0.1, < 0.1) BUNDLED WITH - 1.16.2 + 1.16.6 diff --git a/app/views/binda/fieldable/_form_item_upload_file.html.erb b/app/views/binda/fieldable/_form_item_upload_file.html.erb deleted file mode 100644 index 25e36ebc..00000000 --- a/app/views/binda/fieldable/_form_item_upload_file.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -<% binding.pry %> -<%# b.wrapper tag: 'div', class: 'fileupload--dashboard' do |bb| - bb.use :label, class: 'control-label b-btn b-btn-primary', wrap_with: { tag: 'div', class: 'control-label-wrap' } - bb.use :delete_button - bb.use :detail - end %> \ No newline at end of file diff --git a/binda.gemspec b/binda.gemspec index 449c37ed..dd298b79 100644 --- a/binda.gemspec +++ b/binda.gemspec @@ -59,5 +59,6 @@ Gem::Specification.new do |s| s.add_development_dependency "rubocop", "~> 0.52.1" s.add_development_dependency "mry", "~> 0.52" s.add_development_dependency "generator_spec", "~> 0.9.4" + s.add_development_dependency "cypress-on-rails", "~> 1.1" end diff --git a/config/initializers/cypress_dev.rb b/config/initializers/cypress_dev.rb new file mode 100644 index 00000000..a6523395 --- /dev/null +++ b/config/initializers/cypress_dev.rb @@ -0,0 +1,9 @@ +if defined?(CypressDev) + CypressDev.configure do |c| + c.cypress_folder = File.expand_path("#{__dir__}/../../spec/cypress") + # WARNING!! CypressDev can execute arbitrary ruby code + # please use with extra caution if enabling on hosted servers or starting your local server on 0.0.0.0 + c.use_middleware = Rails.env.test? + c.logger = Rails.logger + end +end \ No newline at end of file diff --git a/config/initializers/simple_form_custom.rb b/config/initializers/simple_form_custom.rb index afb81c62..c36a4031 100644 --- a/config/initializers/simple_form_custom.rb +++ b/config/initializers/simple_form_custom.rb @@ -148,12 +148,6 @@ b.use :preview - # ApplicationController.render( - # assigns: { builder: b }, - # template: 'binda/fieldable/_form_item_upload_file', - # layout: false - # ) - b.wrapper tag: 'div', class: 'fileupload--dashboard' do |bb| bb.use :delete_button bb.use :detail @@ -174,14 +168,8 @@ b.use :preview - # ApplicationController.render( - # assigns: { builder: b }, - # template: 'binda/fieldable/_form_item_upload_file', - # layout: false - # ) - b.wrapper tag: 'div', class: 'fileupload--dashboard' do |bb| - bb.use :label, class: 'control-label b-btn b-btn-primary', wrap_with: { tag: 'div', class: 'control-label-wrap' } + bb.use :label, class: 'control-label b-btn b-btn-primary', wrap_with: { tag: 'div', class: 'control-label-wrap test-label' } bb.use :delete_button bb.use :detail end @@ -230,7 +218,6 @@ check_boxes: :vertical_radio_and_checkboxes, radio_buttons: :vertical_radio_and_checkboxes, file: :file_uploadable, - file2: :file_read_only, boolean: :vertical_boolean, datetime: :multi_select, date: :multi_select, diff --git a/package.json b/package.json index be0aa3e6..90f56303 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-preset-env": "^1.2.2", "babel-preset-es2015": "^6.24.0", + "cypress": "^3.1.1", "jshint": "^2.9.4", "jshint-loader": "^0.8.4", "webpack": "^3.10.0" diff --git a/spec/cypress.json b/spec/cypress.json new file mode 100644 index 00000000..fe0e205e --- /dev/null +++ b/spec/cypress.json @@ -0,0 +1,4 @@ +{ + "baseUrl": "http://localhost:5002", + "defaultCommandTimeout": 10000 +} diff --git a/spec/cypress/app_commands/activerecord_fixtures.rb b/spec/cypress/app_commands/activerecord_fixtures.rb new file mode 100644 index 00000000..ff24f5bb --- /dev/null +++ b/spec/cypress/app_commands/activerecord_fixtures.rb @@ -0,0 +1,21 @@ +# you can delete this file if you don't use Rails Test Fixtures + +fixtures_dir = command_options.try(:[], 'fixtures_dir') +fixture_files = command_options.try(:[], 'fixtures') + +if defined?(ActiveRecord) + require "active_record/fixtures" + + fixtures_dir ||= ActiveRecord::Tasks::DatabaseTasks.fixtures_path + fixture_files ||= Dir["#{fixtures_dir}/**/*.yml"].map { |f| f[(fixtures_dir.size + 1)..-5] } + + logger.debug "loading fixtures: { dir: #{fixtures_dir}, files: #{fixture_files} }" + ActiveRecord::FixtureSet.reset_cache + ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, fixture_files) +else # this else part can be removed + logger.error "Looks like activerecord_fixtures has to be modified to suite your need" + Post.create(title: 'MyCypressFixtures') + Post.create(title: 'MyCypressFixtures2') + Post.create(title: 'MyRailsFixtures') + Post.create(title: 'MyRailsFixtures2') +end diff --git a/spec/cypress/app_commands/clean.rb b/spec/cypress/app_commands/clean.rb new file mode 100644 index 00000000..ce8c69e0 --- /dev/null +++ b/spec/cypress/app_commands/clean.rb @@ -0,0 +1,8 @@ +if defined?(DatabaseCleaner) + # cleaning the database using database_cleaner + DatabaseCleaner.strategy = :truncation + DatabaseCleaner.clean +else + logger.warn "add database_cleaner or update clean_db" + Post.delete_all if defined?(Post) +end diff --git a/spec/cypress/app_commands/eval.rb b/spec/cypress/app_commands/eval.rb new file mode 100644 index 00000000..3a39bf3e --- /dev/null +++ b/spec/cypress/app_commands/eval.rb @@ -0,0 +1 @@ +Kernel.eval(command_options) unless command_options.nil? diff --git a/spec/cypress/app_commands/factory_bot.rb b/spec/cypress/app_commands/factory_bot.rb new file mode 100644 index 00000000..04525ecc --- /dev/null +++ b/spec/cypress/app_commands/factory_bot.rb @@ -0,0 +1,12 @@ +Array.wrap(command_options).each do |factory_options| + factory_method = factory_options.shift + begin + logger.debug "running #{factory_method}, #{factory_options}" + CypressDev::SmartFactoryWrapper.public_send(factory_method, *factory_options) + rescue => e + logger.error "#{e.class}: #{e.message}" + logger.error e.backtrace.join("\n") + logger.error "#{e.record.inspect}" if e.is_a?(ActiveRecord::RecordInvalid) + raise e + end +end diff --git a/spec/cypress/app_commands/scenarios/basic.rb b/spec/cypress/app_commands/scenarios/basic.rb new file mode 100644 index 00000000..2c1fd35d --- /dev/null +++ b/spec/cypress/app_commands/scenarios/basic.rb @@ -0,0 +1,3 @@ +# You can setup your Rails state here +# MyModel.create name: 'something' +Post.create(title: 'I am a Postman') diff --git a/spec/cypress/cypress_helper.rb b/spec/cypress/cypress_helper.rb new file mode 100644 index 00000000..b3a8cd72 --- /dev/null +++ b/spec/cypress/cypress_helper.rb @@ -0,0 +1,30 @@ +# This is loaded once before the first command is executed + +begin + require 'database_cleaner' +rescue LoadError => e + puts e.message +end + +begin + require 'factory_bot_rails' +rescue LoadError => e + puts e.message + begin + require 'factory_girl_rails' + rescue LoadError => e + puts e.message + end +end + +require 'cypress_dev/smart_factory_wrapper' + +factory = CypressDev::SimpleRailsFactory +factory = FactoryBot if defined?(FactoryBot) +factory = FactoryGirl if defined?(FactoryGirl) + +CypressDev::SmartFactoryWrapper.configure( + always_reload: !Rails.configuration.cache_classes, + factory: factory, + files: %w(spec/factories.rb ./spec/factories/**/*.rb) +) diff --git a/spec/cypress/fixtures/example.json b/spec/cypress/fixtures/example.json new file mode 100644 index 00000000..da18d935 --- /dev/null +++ b/spec/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} \ No newline at end of file diff --git a/spec/cypress/integration/examples/actions.spec.js b/spec/cypress/integration/examples/actions.spec.js new file mode 100644 index 00000000..0375aba7 --- /dev/null +++ b/spec/cypress/integration/examples/actions.spec.js @@ -0,0 +1,272 @@ +/// + +context('Actions', () => { + beforeEach(() => { + cy.visit('https://example.cypress.io/commands/actions') + }) + + // https://on.cypress.io/interacting-with-elements + + it('.type() - type into a DOM element', () => { + // https://on.cypress.io/type + cy.get('.action-email') + .type('fake@email.com').should('have.value', 'fake@email.com') + + // .type() with special character sequences + .type('{leftarrow}{rightarrow}{uparrow}{downarrow}') + .type('{del}{selectall}{backspace}') + + // .type() with key modifiers + .type('{alt}{option}') //these are equivalent + .type('{ctrl}{control}') //these are equivalent + .type('{meta}{command}{cmd}') //these are equivalent + .type('{shift}') + + // Delay each keypress by 0.1 sec + .type('slow.typing@email.com', { delay: 100 }) + .should('have.value', 'slow.typing@email.com') + + cy.get('.action-disabled') + // Ignore error checking prior to type + // like whether the input is visible or disabled + .type('disabled error checking', { force: true }) + .should('have.value', 'disabled error checking') + }) + + it('.focus() - focus on a DOM element', () => { + // https://on.cypress.io/focus + cy.get('.action-focus').focus() + .should('have.class', 'focus') + .prev().should('have.attr', 'style', 'color: orange;') + }) + + it('.blur() - blur off a DOM element', () => { + // https://on.cypress.io/blur + cy.get('.action-blur').type('About to blur').blur() + .should('have.class', 'error') + .prev().should('have.attr', 'style', 'color: red;') + }) + + it('.clear() - clears an input or textarea element', () => { + // https://on.cypress.io/clear + cy.get('.action-clear').type('Clear this text') + .should('have.value', 'Clear this text') + .clear() + .should('have.value', '') + }) + + it('.submit() - submit a form', () => { + // https://on.cypress.io/submit + cy.get('.action-form') + .find('[type="text"]').type('HALFOFF') + cy.get('.action-form').submit() + .next().should('contain', 'Your form has been submitted!') + }) + + it('.click() - click on a DOM element', () => { + // https://on.cypress.io/click + cy.get('.action-btn').click() + + // You can click on 9 specific positions of an element: + // ----------------------------------- + // | topLeft top topRight | + // | | + // | | + // | | + // | left center right | + // | | + // | | + // | | + // | bottomLeft bottom bottomRight | + // ----------------------------------- + + // clicking in the center of the element is the default + cy.get('#action-canvas').click() + + cy.get('#action-canvas').click('topLeft') + cy.get('#action-canvas').click('top') + cy.get('#action-canvas').click('topRight') + cy.get('#action-canvas').click('left') + cy.get('#action-canvas').click('right') + cy.get('#action-canvas').click('bottomLeft') + cy.get('#action-canvas').click('bottom') + cy.get('#action-canvas').click('bottomRight') + + // .click() accepts an x and y coordinate + // that controls where the click occurs :) + + cy.get('#action-canvas') + .click(80, 75) // click 80px on x coord and 75px on y coord + .click(170, 75) + .click(80, 165) + .click(100, 185) + .click(125, 190) + .click(150, 185) + .click(170, 165) + + // click multiple elements by passing multiple: true + cy.get('.action-labels>.label').click({ multiple: true }) + + // Ignore error checking prior to clicking + cy.get('.action-opacity>.btn').click({ force: true }) + }) + + it('.dblclick() - double click on a DOM element', () => { + // https://on.cypress.io/dblclick + + // Our app has a listener on 'dblclick' event in our 'scripts.js' + // that hides the div and shows an input on double click + cy.get('.action-div').dblclick().should('not.be.visible') + cy.get('.action-input-hidden').should('be.visible') + }) + + it('.check() - check a checkbox or radio element', () => { + // https://on.cypress.io/check + + // By default, .check() will check all + // matching checkbox or radio elements in succession, one after another + cy.get('.action-checkboxes [type="checkbox"]').not('[disabled]') + .check().should('be.checked') + + cy.get('.action-radios [type="radio"]').not('[disabled]') + .check().should('be.checked') + + // .check() accepts a value argument + cy.get('.action-radios [type="radio"]') + .check('radio1').should('be.checked') + + // .check() accepts an array of values + cy.get('.action-multiple-checkboxes [type="checkbox"]') + .check(['checkbox1', 'checkbox2']).should('be.checked') + + // Ignore error checking prior to checking + cy.get('.action-checkboxes [disabled]') + .check({ force: true }).should('be.checked') + + cy.get('.action-radios [type="radio"]') + .check('radio3', { force: true }).should('be.checked') + }) + + it('.uncheck() - uncheck a checkbox element', () => { + // https://on.cypress.io/uncheck + + // By default, .uncheck() will uncheck all matching + // checkbox elements in succession, one after another + cy.get('.action-check [type="checkbox"]') + .not('[disabled]') + .uncheck().should('not.be.checked') + + // .uncheck() accepts a value argument + cy.get('.action-check [type="checkbox"]') + .check('checkbox1') + .uncheck('checkbox1').should('not.be.checked') + + // .uncheck() accepts an array of values + cy.get('.action-check [type="checkbox"]') + .check(['checkbox1', 'checkbox3']) + .uncheck(['checkbox1', 'checkbox3']).should('not.be.checked') + + // Ignore error checking prior to unchecking + cy.get('.action-check [disabled]') + .uncheck({ force: true }).should('not.be.checked') + }) + + it('.select() - select an option in a