diff --git a/.rubocop.yml b/.rubocop.yml index b283ef0..4d89ea7 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,5 @@ +inherit_gem: + bixby: bixby_default.yml inherit_from: .rubocop_todo.yml AllCops: @@ -10,17 +12,75 @@ AllCops: - 'script/**/*' - 'spec/test_app_templates/**/*' -Metrics/LineLength: - Max: 400 +Bundler/DuplicatedGem: + Exclude: + - 'Gemfile' + +Layout/IndentationConsistency: + EnforcedStyle: rails Metrics/AbcSize: Max: 50 +Metrics/BlockLength: + Exclude: + - 'hydra-editor.gemspec' + - 'spec/views/records/_form.html.erb_spec.rb' + - 'spec/helpers/records_helper_spec.rb' + - 'spec/inputs/multi_value_input_spec.rb' + - 'spec/controllers/records_controller_spec.rb' + - 'spec/routing/records_routing_spec.rb' + - 'spec/presenters/hydra_editor_presenter_spec.rb' + - 'spec/forms/hydra_editor_form_permissions_spec.rb' + - 'spec/forms/hydra_editor_form_spec.rb' + - 'spec/features/record_editing_spec.rb' + +Metrics/LineLength: + Max: 400 + Metrics/MethodLength: Max: 30 -Style/IndentationConsistency: - EnforcedStyle: rails +Naming/FileName: + Exclude: + - 'lib/tasks/hydra-editor_tasks.rake' + - 'lib/hydra-editor.rb' + - 'hydra-editor.gemspec' + - 'Gemfile' + - 'spec/hydra-editor_spec.rb' + +Rails: + Enabled: true + +RSpec/AnyInstance: + Exclude: + - 'spec/features/record_editing_spec.rb' + - 'spec/features/create_record_spec.rb' + +RSpec/DescribeClass: + Exclude: + - 'spec/views/records/edit_fields/_default.html.erb_spec.rb' + - 'spec/views/records/_form.html.erb_spec.rb' + - 'spec/routing/records_routing_spec.rb' + - 'spec/javascripts/jasmine_spec.rb' + - 'spec/features/record_editing_spec.rb' + +RSpec/ExampleLength: + Exclude: + - 'spec/helpers/records_helper_spec.rb' + - 'spec/javascripts/jasmine_spec.rb' + - 'spec/features/record_editing_spec.rb' + - 'spec/features/create_record_spec.rb' + +RSpec/InstanceVariable: + Exclude: + - 'spec/controllers/records_controller_spec.rb' + +RSpec/VerifiedDoubles: + Exclude: + - 'spec/inputs/multi_value_input_spec.rb' + - 'spec/helpers/records_helper_spec.rb' + - 'spec/forms/hydra_editor_form_spec.rb' Style/CollectionMethods: PreferredMethods: @@ -30,11 +90,9 @@ Style/CollectionMethods: detect: 'find' find_all: 'select' + Style/RegexpLiteral: Enabled: false Style/SingleLineBlockParams: Enabled: false - -Rails: - Enabled: true diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index aef7d2b..c43e6ea 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -44,11 +44,11 @@ Metrics/MethodLength: # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. # SupportedStyles: outdent, indent -Style/AccessModifierIndentation: +Layout/AccessModifierIndentation: Enabled: false # Offense count: 1 -Style/AccessorMethodName: +Naming/AccessorMethodName: Exclude: - 'app/controllers/concerns/records_controller_behavior.rb' @@ -65,7 +65,7 @@ Style/BlockDelimiters: # Offense count: 1 # Cop supports --auto-correct. -Style/BlockEndNewline: +Layout/BlockEndNewline: Exclude: - 'spec/forms/hydra_editor_form_permissions_spec.rb' @@ -98,7 +98,7 @@ Style/Documentation: # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: leading, trailing -Style/DotPosition: +Layout/DotPosition: Enabled: false # Offense count: 1 @@ -109,13 +109,13 @@ Style/EachWithObject: # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: AllowAdjacentOneLineDefs. -Style/EmptyLineBetweenDefs: +Layout/EmptyLineBetweenDefs: Exclude: - 'app/controllers/concerns/records_controller_behavior.rb' # Offense count: 1 # Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts. -Style/FileName: +Naming/FileName: Exclude: - 'lib/hydra-editor.rb' @@ -123,12 +123,12 @@ Style/FileName: # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. # SupportedStyles: special_inside_parentheses, consistent, align_brackets -Style/IndentArray: +Layout/IndentArray: Enabled: false # Offense count: 1 # Cop supports --auto-correct. -Style/MultilineBlockLayout: +Layout/MultilineBlockLayout: Exclude: - 'spec/forms/hydra_editor_form_permissions_spec.rb' @@ -136,7 +136,7 @@ Style/MultilineBlockLayout: # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. # SupportedStyles: aligned, indented -Style/MultilineMethodCallIndentation: +Layout/MultilineMethodCallIndentation: Enabled: false # Offense count: 1 @@ -150,7 +150,7 @@ Style/MutableConstant: # NamePrefix: is_, has_, have_ # NamePrefixBlacklist: is_, has_, have_ # NameWhitelist: is_a? -Style/PredicateName: +Naming/PredicateName: Exclude: - 'app/controllers/concerns/records_controller_behavior.rb' - 'lib/hydra_editor/controller_resource.rb' diff --git a/Gemfile b/Gemfile index 059c681..b146d6d 100644 --- a/Gemfile +++ b/Gemfile @@ -31,6 +31,4 @@ else end # END ENGINE_CART BLOCK -if !ENV['RAILS_VERSION'] || ENV['RAILS_VERSION'] =~ /^5.0/ - gem 'rails-controller-testing' -end +gem 'rails-controller-testing' if !ENV['RAILS_VERSION'] || ENV['RAILS_VERSION'] =~ /^5.0/ diff --git a/app/presenters/hydra/presenter.rb b/app/presenters/hydra/presenter.rb index b84a016..6206bb4 100644 --- a/app/presenters/hydra/presenter.rb +++ b/app/presenters/hydra/presenter.rb @@ -24,9 +24,7 @@ def to_model module ClassMethods def model_name - if model_class.nil? - raise "You must set `self.model_class = ' after including Hydra::Presenter on #{self}." - end + raise "You must set `self.model_class = ' after including Hydra::Presenter on #{self}." if model_class.nil? model_class.model_name end end diff --git a/hydra-editor.gemspec b/hydra-editor.gemspec index c1768d8..5dc2db8 100644 --- a/hydra-editor.gemspec +++ b/hydra-editor.gemspec @@ -24,6 +24,7 @@ Gem::Specification.new do |s| s.add_dependency 'sprockets-es6' s.add_dependency 'thor', '~> 0.19' + s.add_development_dependency "bixby" s.add_development_dependency "capybara", '~> 2.4' s.add_development_dependency "devise", '~> 4.0' s.add_development_dependency "engine_cart", '~> 2.2' diff --git a/lib/hydra_editor/engine.rb b/lib/hydra_editor/engine.rb index 61fbb36..a6cdcbc 100644 --- a/lib/hydra_editor/engine.rb +++ b/lib/hydra_editor/engine.rb @@ -4,10 +4,10 @@ class Engine < ::Rails::Engine require 'sprockets/es6' require 'almond-rails' engine_name 'hydra_editor' - config.eager_load_paths += %W( + config.eager_load_paths += %W[ #{config.root}/app/helpers/concerns #{config.root}/app/presenters - ) + ] initializer 'hydra-editor.initialize' do require 'cancan' Sprockets::ES6.configuration = { 'modules' => 'amd', 'moduleIds' => true } diff --git a/spec/controllers/records_controller_spec.rb b/spec/controllers/records_controller_spec.rb index c4fb2d2..9042edd 100644 --- a/spec/controllers/records_controller_spec.rb +++ b/spec/controllers/records_controller_spec.rb @@ -12,12 +12,12 @@ sign_in user end describe 'who goes to the new page' do - it 'should be successful' do + it 'renders the template for choosing a format type' do get :new expect(response).to be_successful expect(response).to render_template(:choose_type) end - it 'should be successful' do + it 'renders the template for a new audio work' do get :new, params: { type: 'Audio' } expect(response).to be_successful expect(response).to render_template(:new) @@ -29,28 +29,28 @@ before do allow(stub_audio).to receive(:persisted?).and_return(true) - expect(Audio).to receive(:new).and_return(stub_audio) + allow(Audio).to receive(:new).and_return(stub_audio) end context 'when save is successful' do before do - expect(stub_audio).to receive(:save).and_return(true) + allow(stub_audio).to receive(:save).and_return(true) end - it 'should be successful' do + it 'saves the audio work with a title' do post :create, params: { type: 'Audio', audio: { title: ['My title'] } } expect(response).to redirect_to("/catalog/#{assigns[:record].id}") expect(assigns[:record].title).to eq ['My title'] end - it "should not set attributes that aren't listed in terms_for_editing" do + it "does not set attributes that aren't listed in terms_for_editing" do # params[:audio][:collection_id] would be a good test, but that doesn't work in ActiveFedora 6.7 post :create, params: { type: 'Audio', audio: { isPartOf: 'my collection' } } expect(response).to redirect_to("/catalog/#{assigns[:record].id}") expect(assigns[:record].isPartOf).to eq [] end - it 'should be successful with json' do + it 'is successful with json' do post :create, params: { type: 'Audio', audio: { title: ['My title'] } }, format: :json expect(response.status).to eq 201 end @@ -60,7 +60,7 @@ controller.current_ability.cannot :create, ActiveFedora::Base controller.current_ability.can :create, Audio end - it 'should be successful' do + it 'permits users to create works with the authorized format types' do post :create, params: { type: 'Audio', audio: { title: ['My title'] } } expect(response).to redirect_to("/catalog/#{assigns[:record].id}") expect(assigns[:record].title).to eq ['My title'] @@ -68,16 +68,18 @@ end describe 'when set_attributes is overloaded' do - controller(RecordsController) do + controller(described_class) do def set_attributes super @record.creator = ['Fleece Vest'] end end # since this is using an an anonymous class, we have to stub - before { allow(controller).to receive(:resource_instance_name).and_return('record') } + before do + allow(controller).to receive(:resource_instance_name).and_return('record') + end - it 'should run set_attributes' do + it 'runs set_attributes' do post :create, params: { type: 'Audio', audio: { title: ['My title'] } } expect(response).to redirect_to("/catalog/#{assigns[:record].id}") expect(assigns[:record].creator).to eq ['Fleece Vest'] @@ -89,7 +91,7 @@ def set_attributes allow(controller).to receive(:object_as_json).and_return(message: 'it works') end - it 'should run object_as_json' do + it 'runs object_as_json' do post :create, params: { type: 'Audio', audio: { title: ['My title'] } }, format: 'json' expect(JSON.parse(response.body)).to eq('message' => 'it works') expect(response.code).to eq '201' @@ -97,7 +99,7 @@ def set_attributes end describe 'when redirect_after_create is overridden' do - it 'should redirect to the alternate location' do + it 'redirects to the alternate location' do allow(controller).to receive(:redirect_after_create).and_return('/') post :create, params: { type: 'Audio', audio: { title: ['My title'] } } expect(response).to redirect_to('/') @@ -107,9 +109,9 @@ def set_attributes context 'when it fails to save' do before do - expect(stub_audio).to receive(:save).and_return(false) + allow(stub_audio).to receive(:save).and_return(false) end - it 'should draw the form' do + it 'draws the form' do post :create, params: { type: 'Audio', audio: { title: ['My title'] } } expect(response).to render_template('records/new') expect(assigns[:form].title).to eq ['My title'] @@ -122,11 +124,11 @@ def set_attributes let(:audio) { Audio.new(title: ['My title2'], id: 'test:7') } before do allow(audio).to receive(:persisted?).and_return(true) - expect(ActiveFedora::Base).to receive(:find).with('test:7').and_return(audio) - expect(controller).to receive(:authorize!).with(:edit, audio) + allow(ActiveFedora::Base).to receive(:find).and_return(audio) + allow(controller).to receive(:authorize!) end - it 'should be successful' do + it 'updates the audio work' do get :edit, params: { id: audio } expect(response).to be_successful expect(assigns[:record].title).to eq ['My title2'] @@ -137,16 +139,16 @@ def set_attributes let(:audio) { Audio.new(title: ['My title2'], id: 'test:7') } before do allow(audio).to receive(:persisted?).and_return(true) - expect(ActiveFedora::Base).to receive(:find).with('test:7').and_return(audio) - expect(controller).to receive(:authorize!).with(:update, audio) + allow(ActiveFedora::Base).to receive(:find).with('test:7').and_return(audio) + allow(controller).to receive(:authorize!) end context 'when saving is unsuccessful' do before do - expect(audio).to receive(:save).and_return(false) + allow(audio).to receive(:save).and_return(false) end - it 'should draw the form' do + it 'draws the form' do put :update, params: { id: audio, audio: { title: ['My title 3'] } } expect(response).to be_successful expect(response).to render_template('records/edit') @@ -157,22 +159,22 @@ def set_attributes context 'when saving is successful' do before do - expect(audio).to receive(:save).and_return(true) + allow(audio).to receive(:save).and_return(true) end - it 'should be successful' do + it 'updates the work and redirects to the work show view' do put :update, params: { id: audio, audio: { title: ['My title 3'] } } expect(response).to redirect_to("/catalog/#{assigns[:record].id}") expect(assigns[:record].title).to eq ['My title 3'] end - it 'should be successful with json' do + it 'is successful with json' do put :update, params: { id: audio, audio: { title: ['My title'] } }, format: :json expect(response.status).to eq 204 end context 'when redirect_after_update is overridden' do - it 'should redirect to the alternate location' do + it 'redirects to the alternate location' do allow(controller).to receive(:redirect_after_update).and_return('/') put :update, params: { id: audio, audio: { title: ['My title 3'] } } expect(response).to redirect_to('/') @@ -190,7 +192,7 @@ def set_attributes end describe 'who goes to the new page' do - it 'should not be allowed' do + it 'is not allowed' do get :new, params: { type: 'Audio' } expect(response).to redirect_to '/' expect(flash[:alert]).to eq 'You are not authorized to access this page.' diff --git a/spec/features/create_record_spec.rb b/spec/features/create_record_spec.rb index 675121e..ff5d040 100644 --- a/spec/features/create_record_spec.rb +++ b/spec/features/create_record_spec.rb @@ -2,11 +2,11 @@ feature 'User creates an object' do let(:user) { FactoryBot.create(:user) } - let(:params) { + let(:params) do ActionController::Parameters.new( 'title' => ['My title'], 'creator' => [], 'description' => [], 'subject' => [], 'isPartOf' => [] ) - } + end before do HydraEditor.models = ['Audio'] @@ -22,12 +22,10 @@ select 'Audio', from: 'Select an object type' click_button 'Next' - fill_in 'Title', with: 'My title' - - allow_any_instance_of(Audio).to receive(:attributes=).with({}) # called when initializing a new object - expect_any_instance_of(Audio).to receive(:attributes=).with(params) - # Avoid the catalog so we don't have to run Solr - expect_any_instance_of(Audio).to receive(:save).and_return(true) + fill_in 'Title', with: 'My audio work at Tufts' click_button 'Save' + + audio_work = Audio.all.to_a.find { |audio| audio.title.include?('My audio work at Tufts') } + expect(audio_work).not_to be nil end end diff --git a/spec/features/record_editing_spec.rb b/spec/features/record_editing_spec.rb index 968796e..5ad1497 100644 --- a/spec/features/record_editing_spec.rb +++ b/spec/features/record_editing_spec.rb @@ -2,30 +2,31 @@ describe 'record editing' do let(:user) { FactoryBot.create(:user) } - let(:record) { Audio.new(id: 'audio-1', title: ['Cool Track']) } - # We need a clone to give to the edit view b/c it gets changed by initialize_fields - let(:record_clone) { Audio.new(id: 'audio-1', title: ['Cool Track']) } + let(:record) do + begin + Audio.find('audio-1') + rescue ActiveFedora::ObjectNotFoundError + Audio.create(id: 'audio-1', title: ['Cool Track']) + end + end before do HydraEditor.models = ['Audio'] allow_any_instance_of(Ability).to receive(:authorize!).and_return(true) # Avoid the catalog so we don't have to run Solr allow_any_instance_of(RecordsController).to receive(:redirect_after_update).and_return('/404.html') - allow_any_instance_of(Audio).to receive(:new_record?).and_return(false) - allow_any_instance_of(Audio).to receive(:save).and_return(true) - - # We use the original record for the update view to start clean and apply the form data - expect(ActiveFedora::Base).to receive(:find).with(record.id).and_return(record_clone, record) login_as user end after do Warden.test_reset! end - it 'should be idempotent' do + it 'is idempotent' do visit "/records/#{record.id}/edit" + fill_in 'Title', with: 'Even Better Track' click_button 'Save' - expect(record.title).to eq ['Cool Track'] + record.reload + expect(record.title).to eq ['Even Better Track'] expect(record.creator).to eq [] expect(record.description).to eq [] expect(record.subject).to eq [] diff --git a/spec/forms/hydra_editor_form_permissions_spec.rb b/spec/forms/hydra_editor_form_permissions_spec.rb index 571017b..c7452ef 100644 --- a/spec/forms/hydra_editor_form_permissions_spec.rb +++ b/spec/forms/hydra_editor_form_permissions_spec.rb @@ -22,17 +22,17 @@ class TestForm end describe 'model_attributes' do + subject(:permissions) { TestForm.model_attributes(params) } let(:params) { ActionController::Parameters.new(title: [''], creator: 'bob', description: ['huh'], permissions_attributes: { '0' => { id: '123', _destroy: 'true' } }) } - subject { TestForm.model_attributes(params) } it { is_expected.to eq('creator' => 'bob', 'title' => [], 'permissions_attributes' => { '0' => { 'id' => '123', '_destroy' => 'true' } }) } end describe 'permissions_attributes=' do - subject { TestForm.new(TestModel.new) } - it 'should respond to permissions_attributes=' do - expect(subject).to respond_to(:permissions_attributes=) + subject(:form) { TestForm.new(TestModel.new) } + it 'responds to permissions_attributes=' do + expect(form).to respond_to(:permissions_attributes=) end end end diff --git a/spec/forms/hydra_editor_form_spec.rb b/spec/forms/hydra_editor_form_spec.rb index 8f44e79..b295fe4 100644 --- a/spec/forms/hydra_editor_form_spec.rb +++ b/spec/forms/hydra_editor_form_spec.rb @@ -25,8 +25,8 @@ class TestForm it { is_expected.to eq 'TestModel' } describe 'model_attributes' do - let(:params) { ActionController::Parameters.new(title: [''], creator: 'bob', description: ['huh']) } subject { TestForm.model_attributes(params) } + let(:params) { ActionController::Parameters.new(title: [''], creator: 'bob', description: ['huh']) } it { is_expected.to eq('creator' => 'bob', 'title' => []) } @@ -62,7 +62,7 @@ class TestForm form[:title] = nil end - it 'should put an empty element in the value' do + it 'puts an empty element in the value' do expect { form.send(:initialize_field, :title) }.to change { form[:title] }. from(nil).to(['']) end @@ -73,7 +73,7 @@ class TestForm before do allow(object).to receive(:errors).and_return(errors) end - it 'should delegate to model' do + it 'delegates to model' do expect(form.errors).to eq errors end end @@ -83,14 +83,14 @@ class TestForm before do TestForm.required_fields = [:title] end - it 'should create them for required fields' do + it 'creates them for required fields' do expect(TestForm.validators_on(:title).first).to be_instance_of HydraEditor::Form::Validator expect(TestForm.validators_on(:title).first.options).to eq({}) expect(TestForm.validators_on(:title).first.kind).to eq :presence end end context 'without required fields' do - it 'should create them for required fields' do + it 'creates them for required fields' do expect(TestForm.validators_on(:title)).to eq [] end end diff --git a/spec/helpers/records_helper_spec.rb b/spec/helpers/records_helper_spec.rb index f7d85d0..69a55bd 100644 --- a/spec/helpers/records_helper_spec.rb +++ b/spec/helpers/records_helper_spec.rb @@ -1,15 +1,22 @@ require 'spec_helper' describe RecordsHelper do - it 'should have object_type_options' do + let(:title_values) do + double(title: 'My Title') + end + + before do HydraEditor.models = ['Audio', 'Pdf'] + allow(helper).to receive(:form).and_return(title_values) + end + + it 'has object_type_options' do allow(I18n).to receive(:t).with('hydra_editor.form.model_label.Audio', default: 'Audio').and_return('Audio') allow(I18n).to receive(:t).with('hydra_editor.form.model_label.Pdf', default: 'Pdf').and_return('PDF') expect(helper.object_type_options).to eq('Audio' => 'Audio', 'PDF' => 'Pdf') end it 'draws edit_record_title' do - allow(helper).to receive(:form).and_return(double(title: 'My Title')) expect(helper.edit_record_title).to eq 'Edit My Title' end @@ -17,36 +24,71 @@ before do class Dragon extend ActiveModel::Naming + + def multiple?(_key) + false + end + + def required?(_key) + false + end end class Serpent extend ActiveModel::Naming + + def multiple?(_key) + false + end + + def required?(_key) + false + end end end + + after do + Object.send(:remove_const, :Dragon) + Object.send(:remove_const, :Serpent) + end + let(:f) { double('form') } it 'draws partial elements based on class of the object' do allow(f).to receive(:object).and_return(Dragon.new) - expect(helper).to receive(:partial_exists?).and_return(true) - expect(helper).to receive(:render).with('dragons/edit_fields/name', f: f, key: :name) - helper.render_edit_field_partial(:name, f: f) - allow(f).to receive(:object).and_return(Serpent.new) - expect(helper).to receive(:partial_exists?).and_return(true) - expect(helper).to receive(:render).with('serpents/edit_fields/name', f: f, key: :name) + allow(helper).to receive(:partial_exists?).and_return(true) + allow(helper).to receive(:render) helper.render_edit_field_partial(:name, f: f) + expect(helper).to have_received(:partial_exists?) + expect(helper).to have_received(:render).with('dragons/edit_fields/name', f: f, key: :name) + end + + context "with a serpent" do + it "draws partial elements for the Serpent model" do + allow(f).to receive(:object).and_return(Serpent.new) + allow(f).to receive(:input) + allow(helper).to receive(:partial_exists?).and_return(true) + allow(helper).to receive(:render) + helper.render_edit_field_partial(:name, f: f) + expect(helper).to have_received(:partial_exists?) + expect(helper).to have_received(:render).with('serpents/edit_fields/name', f: f, key: :name) + end end it "draws the default partial if the path isn't found" do allow(f).to receive(:object).and_return(Dragon.new) - expect(helper).to receive(:partial_exists?).exactly(4).times.and_return(false, false, false, true) - expect(helper).to receive(:render).with('records/edit_fields/default', f: f, key: :name) + allow(helper).to receive(:partial_exists?).exactly(4).times.and_return(false, false, false, true) + allow(helper).to receive(:render) helper.render_edit_field_partial(:name, f: f) + expect(helper).to have_received(:render).with('records/edit_fields/default', f: f, key: :name) end it 'logs the paths it looked for' do allow(f).to receive(:object).and_return(Dragon.new) - expect(helper).to receive(:partial_exists?).and_return(false, true) - expect(Rails.logger).to receive(:debug).exactly(2).times - expect(helper).to receive(:render).with('records/edit_fields/name', f: f, key: :name) + allow(helper).to receive(:partial_exists?).and_return(false, true) + allow(helper).to receive(:render) + allow(Rails.logger).to receive(:debug) helper.render_edit_field_partial(:name, f: f) + expect(Rails.logger).to have_received(:debug).exactly(2).times + expect(helper).to have_received(:render).with('records/edit_fields/name', f: f, key: :name) end end end diff --git a/spec/inputs/multi_value_input_spec.rb b/spec/inputs/multi_value_input_spec.rb index a85b26f..8d752c4 100644 --- a/spec/inputs/multi_value_input_spec.rb +++ b/spec/inputs/multi_value_input_spec.rb @@ -1,67 +1,69 @@ require 'spec_helper' -describe 'MultiValueInput', type: :input do +describe MultiValueInput, type: :input do class Foo < ActiveFedora::Base property :bar, predicate: ::RDF::URI('http://example.com/bar') def double_bar - bar.map { |b| b+ b } + bar.map { |b| b + b } end end - context 'happy case' do + context 'when provided an Array for an attribute' do let(:foo) do Foo.new.tap { |f| f.bar = bar } end let(:bar) { ['bar1', 'bar2'] } context "for values from a property on the object" do - subject { input_for(foo, :bar, as: :multi_value, required: true) } + subject(:multi_value_input) { input_for(foo, :bar, as: :multi_value, required: true) } it 'renders multi-value' do - # For handling older releases of SimpleForm - expect(subject).to have_selector('.form-group.foo_bar.multi_value label.required[for=foo_bar]', text: /(\*\s)?Bar(\s\*)?/) - expect(subject).to have_selector('.form-group.foo_bar.multi_value ul.listing li input.foo_bar', count: 3) + expect(multi_value_input).to have_selector('.form-group.foo_bar.multi_value label.required[for=foo_bar]', text: /(\*\s)?Bar(\s\*)?/) + expect(multi_value_input).to have_selector('.form-group.foo_bar.multi_value ul.listing li input.foo_bar', count: 3) end end context 'for values from a method on the object' do - subject { input_for(foo, :double_bar, as: :multi_value) } + subject(:multi_value_input) { input_for(foo, :double_bar, as: :multi_value) } # For handling older releases of SimpleForm it 'renders multi-value' do - expect(subject).to have_selector('.form-group.foo_double_bar.multi_value ul.listing li input.foo_double_bar', count: 3) + expect(multi_value_input).to have_selector('.form-group.foo_double_bar.multi_value ul.listing li input.foo_double_bar', count: 3) end end end - context 'unhappy case' do - let(:foo) { Foo.new } - let(:bar) { nil } - subject do + context 'when provided a nil value for an attribute' do + subject(:multi_value_input) do foo.bar = bar input_for(foo, :bar, as: :multi_value, required: true) end + let(:foo) { Foo.new } + let(:bar) { nil } it 'renders multi-value given a nil object' do - expect(subject).to have_selector('.form-group.foo_bar.multi_value label.required[for=foo_bar]', text: /(\*\s)?Bar(\s\*)?/) - expect(subject).to have_selector('.form-group.foo_bar.multi_value ul.listing li input.foo_bar') + expect(multi_value_input).to have_selector('.form-group.foo_bar.multi_value label.required[for=foo_bar]', text: /(\*\s)?Bar(\s\*)?/) + expect(multi_value_input).to have_selector('.form-group.foo_bar.multi_value ul.listing li input.foo_bar') end end describe '#build_field' do + let(:multi_value_input) { described_class.new(builder, :bar, nil, :multi_value, {}) } let(:foo) { Foo.new } - before { foo.bar = ['bar1', 'bar2'] } let(:builder) { double('builder', object: foo, object_name: 'foo') } - - subject { MultiValueInput.new(builder, :bar, nil, :multi_value, {}) } + before do + allow(builder).to receive(:text_field) + allow(multi_value_input).to receive(:build_field) + foo.bar = ['bar1', 'bar2'] + end it 'renders multi-value' do - expect(subject).to receive(:build_field).with('bar1', Integer) - expect(subject).to receive(:build_field).with('bar2', Integer) - expect(subject).to receive(:build_field).with('', 2) - subject.input({}) + multi_value_input.input({}) + expect(multi_value_input).to have_received(:build_field).with('bar1', Integer) + expect(multi_value_input).to have_received(:build_field).with('bar2', Integer) + expect(multi_value_input).to have_received(:build_field).with('', 2) end end end diff --git a/spec/javascripts/jasmine_spec.rb b/spec/javascripts/jasmine_spec.rb index f8b4895..4a4a132 100644 --- a/spec/javascripts/jasmine_spec.rb +++ b/spec/javascripts/jasmine_spec.rb @@ -16,11 +16,10 @@ puts "************************ Jasmine Output *************\n\n" end expect(jasmine_out).to include "0 failures" - expect(jasmine_out).to_not include "\n0 specs" + expect(jasmine_out).not_to include "\n0 specs" end end def jasmine_path Gem.loaded_specs['jasmine'].full_gem_path end - diff --git a/spec/javascripts/support/jasmine_helper.rb b/spec/javascripts/support/jasmine_helper.rb index d1f19b5..b32f0eb 100644 --- a/spec/javascripts/support/jasmine_helper.rb +++ b/spec/javascripts/support/jasmine_helper.rb @@ -1,14 +1,14 @@ -#Use this file to set/override Jasmine configuration options -#You can remove it if you don't need it. -#This file is loaded *after* jasmine.yml is interpreted. +# Use this file to set/override Jasmine configuration options +# You can remove it if you don't need it. +# This file is loaded *after* jasmine.yml is interpreted. # -#Example: using a different boot file. -#Jasmine.configure do |config| +# Example: using a different boot file. +# Jasmine.configure do |config| # config.boot_dir = '/absolute/path/to/boot_dir' # config.boot_files = lambda { ['/absolute/path/to/boot_dir/file.js'] } -#end +# end # -#Example: prevent PhantomJS auto install, uses PhantomJS already on your path. +# Example: prevent PhantomJS auto install, uses PhantomJS already on your path. Jasmine.configure do |config| - config.prevent_phantom_js_auto_install = true + config.prevent_phantom_js_auto_install = true end diff --git a/spec/views/records/_form.html.erb_spec.rb b/spec/views/records/_form.html.erb_spec.rb index 78f9863..c2ffa3d 100644 --- a/spec/views/records/_form.html.erb_spec.rb +++ b/spec/views/records/_form.html.erb_spec.rb @@ -14,7 +14,7 @@ it 'does not have the error class' do render expect(response).to have_selector '.form-group' - expect(response).to_not have_selector '.has-error' + expect(response).not_to have_selector '.has-error' end end diff --git a/spec/views/records/edit_fields/_default.html.erb_spec.rb b/spec/views/records/edit_fields/_default.html.erb_spec.rb index a7b3abb..966cf06 100644 --- a/spec/views/records/edit_fields/_default.html.erb_spec.rb +++ b/spec/views/records/edit_fields/_default.html.erb_spec.rb @@ -14,7 +14,7 @@ end context 'when the field is multivalued' do - it 'should have the input-group class and the add another button' do + it 'has the input-group class and the add another button' do render expect(response).to have_selector '.multi_value' end @@ -23,9 +23,9 @@ context 'when the field is not multivalued' do before { allow(Audio).to receive(:multiple?).with(:title).and_return(false) } - it 'should not have the input-group class or the add another button' do + it 'does not have the input-group class or the add another button' do render - expect(response).to_not have_selector '.multi_value' + expect(response).not_to have_selector '.multi_value' end end end