diff --git a/Gemfile b/Gemfile index 2df89f64a..38d4afd64 100644 --- a/Gemfile +++ b/Gemfile @@ -86,6 +86,7 @@ group :development, :test do gem 'factory_bot_rails', '~> 6.5.0' gem 'jettywrapper', '>=1.4.0', git: 'https://github.com/samvera-deprecated/jettywrapper.git', branch: 'master' # gem 'json_spec' + gem 'rails-controller-testing' gem 'rspec-its', '~> 2.0.0' gem 'rspec-rails', '~> 8.0.0' gem 'selenium-webdriver', '~> 4.11' diff --git a/Gemfile.lock b/Gemfile.lock index 7ec8d5441..4ea052fa1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -446,6 +446,10 @@ GEM activesupport (= 8.0.4) bundler (>= 1.15.0) railties (= 8.0.4) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) rails-dom-testing (2.3.0) activesupport (>= 5.0.0) minitest @@ -760,6 +764,7 @@ DEPENDENCIES premailer-rails puma (~> 5.2) rails (= 8.0.4) + rails-controller-testing rainbow resque (~> 2.7.0) resque-scheduler (>= 4.10.2) diff --git a/app/components/blacklight/search_bar_component.html.erb b/app/components/blacklight/search_bar_component.html.erb index 3e9f59a2d..527760895 100644 --- a/app/components/blacklight/search_bar_component.html.erb +++ b/app/components/blacklight/search_bar_component.html.erb @@ -12,7 +12,7 @@ <% before_input_groups.each do |input_group| %> <%= input_group %> <% end %> -
<%= f.label :uni %> <%= f.text_field :uni %> diff --git a/app/views/admin/index.html.erb b/app/views/admin/index.html.erb index dc1b11612..db45f3401 100644 --- a/app/views/admin/index.html.erb +++ b/app/views/admin/index.html.erb @@ -1,5 +1,5 @@ <% title 'Admin' %>
diff --git a/app/views/admin/site_configurations/_alert_message_form.html.erb b/app/views/admin/site_configurations/_alert_message_form.html.erb index 50e5fdada..9f1502b88 100644 --- a/app/views/admin/site_configurations/_alert_message_form.html.erb +++ b/app/views/admin/site_configurations/_alert_message_form.html.erb @@ -1,6 +1,8 @@ -<%= form_with url: admin_site_configuration_path, method: :patch, local: true, data: { turbo: false } do |form| %> -You do not have access.
diff --git a/app/views/errors/internal_server_error.html.erb b/app/views/errors/internal_server_error.html.erb index 67298f269..17b2c9842 100644 --- a/app/views/errors/internal_server_error.html.erb +++ b/app/views/errors/internal_server_error.html.erb @@ -1,3 +1,5 @@ +<%# ERROR CODE 500 %> +The server has encountered an unexpected error.
diff --git a/app/views/errors/not_found.html.erb b/app/views/errors/not_found.html.erb index 7b311c369..4b2807717 100644 --- a/app/views/errors/not_found.html.erb +++ b/app/views/errors/not_found.html.erb @@ -1,3 +1,5 @@ +<%# ERROR CODE 404 %> +The page you are looking for doesn't exist. Please try again or visit our <%= link_to 'homepage', root_path %>.
diff --git a/app/views/errors/record_not_found.html.erb b/app/views/errors/record_not_found.html.erb index 1c7fb1283..69326e036 100644 --- a/app/views/errors/record_not_found.html.erb +++ b/app/views/errors/record_not_found.html.erb @@ -1,3 +1,5 @@ +<%# ERROR CODE 404 for Blacklight Records %> +This item does not exist in Academic Commons or may have been removed.
diff --git a/app/views/user/my_works.html.erb b/app/views/user/my_works.html.erb index 04b0b7439..fd08b281a 100644 --- a/app/views/user/my_works.html.erb +++ b/app/views/user/my_works.html.erb @@ -2,7 +2,7 @@ <% unless @pending_works.empty? %>| <%= document.title %> | diff --git a/spec/factories/email_preference.rb b/spec/factories/email_preference.rb new file mode 100644 index 000000000..8c4ccc8bb --- /dev/null +++ b/spec/factories/email_preference.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :email_preference do + id { 1 } + uni { 'testuser' } + unsubscribe { false } + email { 'testuser@example.com' } + end +end diff --git a/spec/features/admin/email_preferences_spec.rb b/spec/features/admin/email_preferences_spec.rb new file mode 100644 index 000000000..777fd3bc2 --- /dev/null +++ b/spec/features/admin/email_preferences_spec.rb @@ -0,0 +1,122 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'admin email preferences management', type: :feature do + include_context 'admin user for feature' + + before do + FactoryBot.create(:email_preference) + end + + it 'redirects to login if not authorized' do + logout(:user) + visit admin_email_preferences_path + expect(page).to have_current_path new_user_session_path + end + + context 'when visiting email preferences index page' do + before do + visit admin_email_preferences_path + end + + it 'displays the email preferences list' do + expect(page).to have_content 'Email Preferences' + expect(page).to have_content 'testuser@example.com' + end + + it 'has link to create new email preference' do + expect(page).to have_link 'Create New Email Preference', href: new_admin_email_preference_path + end + + it 'has edit buttons for each email preference' do + expect(page).to have_link 'Edit', href: edit_admin_email_preference_path(EmailPreference.first) + end + + it 'has delete buttons for each email preference' do + expect(page).to have_button 'Destroy' + end + end + + context 'when creating a new email preference' do + before do + visit new_admin_email_preference_path + end + + it 'has the email preference form' do + expect(page).to have_content 'New Email Preference' + expect(page).to have_selector('[id="email-preference-form"]') + end + + it 'has a go back to index link' do + expect(page).to have_link 'Back to Email Preferences', href: admin_email_preferences_path + end + + it 'flashes error when creating with missing uni' do + fill_in 'email_preference[uni]', with: '' + click_button 'Create Email preference' + expect(page).to have_css 'div.alert-dismissible' + end + + it 'displays the created email preference when successful' do + fill_in 'email_preference[uni]', with: 'newuser123' + check 'email_preference[unsubscribe]' + fill_in 'email_preference[email]', with: 'newuser123preference@example.com' + click_button 'Create Email preference' + expect(page).to have_content 'Email Preference' + expect(page).to have_content 'newuser123' + expect(page).to have_content 'true' + expect(page).to have_content 'newuser123preference@example.com' + end + + it 'flashes success message when created successfully' do + fill_in 'email_preference[uni]', with: 'newuser123' + check 'email_preference[unsubscribe]' + fill_in 'email_preference[email]', with: 'newuser123preference@example.com' + click_button 'Create Email preference' + expect(page).to have_content 'Successfully created email preference.' + end + + context 'when editing an existing email preference' do + before do + visit edit_admin_email_preference_path(EmailPreference.first) + end + + it 'has the email preference form' do + expect(page).to have_content 'Edit Email Preference' + expect(page).to have_selector('[id="email-preference-form"]') + end + + it 'displays existing values in the form fields' do + expect(find_field('email_preference[uni]').value).to eq 'testuser' + expect(find_field('email_preference[unsubscribe]').checked?).to be false + expect(find_field('email_preference[email]').value).to eq 'testuser@example.com' + end + + it 'has a go back to index link' do + expect(page).to have_link 'Back to Email Preferences', href: admin_email_preferences_path + end + + it 'flashes error when updating with missing uni' do + fill_in 'email_preference[uni]', with: '' + click_button 'Update Email preference' + expect(page).to have_css 'div.alert-dismissible' + end + + it 'displays the updated email preference when successful' do + check 'email_preference[unsubscribe]' + fill_in 'email_preference[email]', with: 'updateduser@example.com' + click_button 'Update Email preference' + expect(page).to have_content 'testuser' # not changed + expect(page).to have_content 'true' + expect(page).to have_content 'updateduser@example.com' + end + + it 'flashes success message when updated successfully' do + fill_in 'email_preference[email]', with: 'updateduser123@example.com' + click_button 'Update Email preference' + expect(page).to have_content 'Successfully updated email preference.' + end + end + end +end diff --git a/spec/features/admin/featured_search_form_spec.rb b/spec/features/admin/featured_search_form_spec.rb index 4d55b6999..68c26ddf0 100644 --- a/spec/features/admin/featured_search_form_spec.rb +++ b/spec/features/admin/featured_search_form_spec.rb @@ -20,10 +20,48 @@ fill_in 'featured_search[url]', with: feature_url fill_in 'featured_search[description]', with: description click_button 'Submit' + sleep(1) # unfortunately, without this many of these tests fail indeterminately end it 'renders document title' do expect(page).to have_content "Edit featured search at #{slug}" end + + describe 'after creating a featured search', js: false do + let(:new_featured_search) { FeaturedSearch.find_by(slug: slug) } + it 'appears in the list features panel' do + visit admin_featured_searches_path + expect(page).to have_content 'Featured Searches' + expect(page).to have_content slug + end + + it 'has slug link to edit the featured search' do + visit admin_featured_searches_path + expect(page).to have_link slug, href: edit_admin_featured_search_path(new_featured_search) + end + + it 'has filter-value link to edit the featured search' do + visit admin_featured_searches_path + expect(page).to have_link filter_value, href: edit_admin_featured_search_path(new_featured_search) + end + + it 'the slug is a valid search link' do + visit "/detail/#{new_featured_search.slug}" + expect(page).to have_current_path("/search?f%5Bfeatured_search%5D%5B%5D=#{new_featured_search.slug}") + end + + it 'has link to delete the featured search' do + visit admin_featured_searches_path + expect(page).to have_link 'Delete', href: admin_featured_search_path(new_featured_search) + end + + it 'clicking delete renders a confirmation dialog', js: true do + visit admin_featured_searches_path + accept_confirm do + click_link 'Delete', href: admin_featured_search_path(new_featured_search) + end + expect(page).to have_content "Deleted feature at #{slug}!" + end + end end end diff --git a/spec/features/admin/self_deposits_spec.rb b/spec/features/admin/self_deposits_spec.rb new file mode 100644 index 000000000..14ae4069b --- /dev/null +++ b/spec/features/admin/self_deposits_spec.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +require 'rails_helper' + +# N.B.: we test for the creation of a new self deposit via the upload feature spec (features/upload_spec.rb) +describe 'self deposits management by admin', type: :feature do + include_context 'admin user for feature' + + let!(:deposit) { FactoryBot.create(:deposit) } + + it 'redirects to login if not authorized' do + logout(:user) + visit admin_deposits_path + expect(page).to have_current_path new_user_session_path + end + + # Below is gen + context 'when visiting self deposits index page' do + before do + visit admin_deposits_path + end + + it 'displays the self deposits list' do + expect(page).to have_content 'Self-Deposits' + expect(page).to have_content 'Test Deposit' + end + + it 'has link to view each self deposit' do + expect(page).to have_link 'Test Deposit', href: admin_deposit_path(deposit) + end + end + + context 'when viewing a self deposit' do + before do + visit admin_deposit_path(deposit) + end + + it 'displays the self deposit details' do # rubocop:disable RSpec/MultipleExpectations + expect(page).to have_content 'Test Deposit' + expect(page).to have_content 'Jane Doe' + expect(page).to have_content 'This deposit is just for testing purposes.' + expect(page).to have_content '2018' + expect(page).to have_content 'https://www.example.com' + expect(page).to have_content 'http://rightsstatements.org/vocab/InC/1.0/' + expect(page).to have_content 'https://creativecommons.org/licenses/by/4.0/' + expect(page).to have_content 'true' + expect(page).to have_content 'false' + end + + it 'has the file attachment download link' do + expect(page).to have_link 'test_file.txt', href: rails_blob_path(deposit.files.first, disposition: 'attachment') + end + + it 'has link to go back to index' do + expect(page).to have_link 'Back to Self-Deposits', href: admin_deposits_path + end + end +end diff --git a/spec/features/admin/site_configuration_spec.rb b/spec/features/admin/site_configuration_spec.rb new file mode 100644 index 000000000..879f76a46 --- /dev/null +++ b/spec/features/admin/site_configuration_spec.rb @@ -0,0 +1,177 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'site configuration', type: :feature do + include_context 'admin user for feature' + before do + FactoryBot.create(:site_configuration) + visit edit_admin_site_configuration_path + end + + context 'alert message configuration' do + it 'has the alert message form' do + expect(page).to have_css 'div#alert-message-form' + end + + it 'renders existing alert message in the form' do + within 'div#alert-message-form' do + expect(page).to have_field 'alert_message', with: 'Test alert message' + end + end + + it 'displays alert message in site banner when set' do + within 'div#alert-message-form' do + fill_in 'alert_message', with: 'This is a new test alert message.' + click_button 'Submit' + end + within 'div.alert-box' do + expect(page).to have_content 'This is a new test alert message.' + end + end + + it 'does not display alert message in site banner when not set' do + within 'div#alert-message-form' do + fill_in 'alert_message', with: '' + click_button 'Submit' + end + end + + it 'removes an alert message from site banner when empty form submitted' do + within 'div.alert-box' do + expect(page).to have_content 'Test alert message' # ensure message initially set + end + within 'div#alert-message-form' do + fill_in 'alert_message', with: '' + click_button 'Submit' + end + expect(page).not_to have_content 'div.alert-box' + end + end + + context 'download configuration' do + it 'has the downloads toggle form' do + expect(page).to have_css 'div#downloads-toggle-form' + end + + it 'renders the existing downloads toggle state' do + within 'div#downloads-toggle-form' do + # Factory sets downloads_enabled to true + expect(page).to have_button 'Disable Downloads' + end + end + + it 'has the set download message form' do + expect(page).to have_css 'div#downloads-message-form' + end + + it 'renders the existing downloads message in the form' do + within 'div#downloads-message-form' do + expect(page).to have_field 'downloads_message', with: 'Test downloads message' + end + end + + describe 'when downloads toggled off' do + before do + within 'div#downloads-toggle-form' do + click_button 'Disable Downloads' + end + end + + it 'disabled downloading on item page when toggled off' do + visit root_path + visit solr_document_path('10.7916/ALICE') # Visit an item page + # click_link 'Test Deposit' # from factory + expect(page).to have_content 'Test downloads message' + end + + it 'displays the downloads disabled message set in the form' do + within 'div#downloads-message-form' do + fill_in 'downloads_message', with: '(Custom message) Downloads are currently disabled for maintenance.' + click_button 'Save Message' + end + visit root_path + visit solr_document_path('10.7916/ALICE') # Visit an item page + expect(page).to have_content '(Custom message) Downloads are currently disabled for maintenance.' + end + end + + describe 'when downloads toggled on' do + it 'enables downloading on item page when toggled on' do + visit solr_document_path('10.7916/ALICE') # Visit an item page + expect(page).to have_css 'a.download-button' + end + end + end + + context 'deposits configuration' do + it 'has the deposits toggle form' do + expect(page).to have_css 'div#deposits-toggle-form' + end + + it 'renders the existing deposits toggle state' do + within 'div#deposits-toggle-form' do + expect(page).to have_button 'Disable Deposits' + end + end + + describe 'when deposits are enabled' do + it "renders 'Add New Work' tab when deposits are enabled" do + within 'div#dashboard-nav' do + expect(page).to have_content 'Add New Work' + end + end + + it 'allows navigation to new upload form when deposits are enabled' do + visit new_upload_path + expect(page).to have_current_path new_upload_path + end + + it "renders 'Upload Your Research' button on home page" do + visit root_path + expect(page).to have_content 'Upload Your Research' + end + + it "includes 'Upload' link in user utility links navbar" do + within 'div#links-navbar' do + expect(page).to have_link 'Upload', href: '/upload' + end + end + end + + describe 'when deposits are disabled' do + before do + within 'div#deposits-toggle-form' do + click_button 'Disable Deposits' + end + end + + it "does not render 'Add New Work' tab when deposits are disabled" do + within 'div#dashboard-nav' do + expect(page).not_to have_content 'Add New Work' + end + end + + it 'redirects to home page when deposits are disabled and user attempts to access new deposit page' do + visit new_upload_path + expect(page).to have_current_path root_path + end + + it 'displays deposits disabled message in admin self-deposits section' do + visit admin_deposits_path + expect(page).to have_content 'Deposits are currently disabled.' + end + + it "does not render 'Upload Your Research' button on home page" do + visit root_path + expect(page).not_to have_content 'Upload Your Research' + end + + it "does not include 'Upload' link in user utility links navbar" do + within 'div#links-navbar' do + expect(page).not_to have_link 'Upload', href: '/upload' + end + end + end + end +end diff --git a/spec/features/admin_spec.rb b/spec/features/admin_spec.rb new file mode 100644 index 000000000..444730eea --- /dev/null +++ b/spec/features/admin_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'admin', type: :feature do + context 'when admin user' do + include_context 'admin user for feature' + + before do + visit admin_path + end + + it 'renders admin dashboard panel button' do + within('#dashboard-nav') do + expect(page).to have_link 'Admin', href: admin_path + end + end + + it 'renders admin dashboard' do + expect(page).to have_current_path admin_path + expect(page).to have_content 'Choose an item from the Administration menu.' + end + + it 'renders user admin sidebar' do + expect(page).to have_css '.admin-sidebar' + end + end +end diff --git a/spec/features/authentication_spec.rb b/spec/features/authentication_spec.rb new file mode 100644 index 000000000..8c46ef1c8 --- /dev/null +++ b/spec/features/authentication_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'rails_helper' + +# TODO : Add more feature tests after the update to omniauth-cul 0.3.0 is complete (in review PR #345) +describe 'authentication', type: :feature do + context 'when user not logged in' do + before do + logout(:user) + end + + it 'contains log in link' do + visit root_path + expect(page).to have_link 'Log In', href: '/sign_in' + end + end + + context 'when user logged in as non-admin' do + include_context 'non-admin user for feature' + it 'redirects access to protected pages to root path' do + expect(page).to have_current_path root_path + end + end + + context 'when user logged in as admin' do + include_context 'admin user for feature' + it 'allows access to protected pages' do + visit admin_path + expect(page).to have_current_path admin_path + end + end +end diff --git a/spec/features/errors_spec.rb b/spec/features/errors_spec.rb new file mode 100644 index 000000000..7401185ac --- /dev/null +++ b/spec/features/errors_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'error pages', type: :feature do + context 'when visiting 404 page (not found)' do + before do + visit '/this_page_does_not_exist' + end + + it 'displays custom 404 error message' do + expect(page).to have_content "The page you are looking for doesn't exist." + expect(page).to have_link 'homepage', href: root_path + end + end + + context 'when visiting a 404 page for a blacklight record (record not found)' do + before do + allow_any_instance_of(CatalogController).to receive(:show).and_raise(Blacklight::Exceptions::RecordNotFound) # rubocop:disable RSpec/AnyInstance + visit solr_document_path('nonexistent_id') + end + + it 'displays custom record not found error message' do + expect(page).to have_content 'This item does not exist in Academic Commons or may have been removed.' + end + end + + context 'when visiting 500 page (internal server error)' do + before do + allow_any_instance_of(CatalogController).to receive(:index).and_raise(StandardError) # rubocop:disable RSpec/AnyInstance + end + + it 'displays custom 500 error message' do + visit search_catalog_path + expect(page).to have_content 'Internal Server Error' + end + end + + context 'when visiting 403 page (forbidden)' do + include_context 'non-admin user for feature' + + before do + visit admin_path + end + + it 'displays custom 403 error message' do + expect(page).to have_content 'You do not have access.' + end + end +end diff --git a/spec/features/item_page_spec.rb b/spec/features/item_page_spec.rb index 204c49cd1..6ee936f92 100644 --- a/spec/features/item_page_spec.rb +++ b/spec/features/item_page_spec.rb @@ -43,14 +43,30 @@ expect(page).to have_xpath('//a[@href=\'/search?f%5Bsubject_ssim%5D%5B%5D=Tea+Parties\']', text: 'Tea Parties') end + it 'clicking subject link shows correct results' do + find('//a[@href=\'/search?f%5Bsubject_ssim%5D%5B%5D=Tea+Parties\']', text: 'Tea Parties').click + expect(page).to have_current_path '/search?f%5Bsubject_ssim%5D%5B%5D=Tea+Parties' + expect(page).to have_content 'Alice\'s Adventures in Wonderland' + end + it 'has linked publisher doi' do expect(page).to have_xpath('//a[@href=\'https://doi.org/10.1378/wonderland.01-2345\']', text: 'https://doi.org/10.1378/wonderland.01-2345') end - xit 'links to the MODS download' do # TODO: Only for administrators - expect(page).to have_css('a[href="/download/fedora_content/show_pretty/actest:1/descMetadata/actest1_description.xml?data=meta"]', text: 'text') - page.find('a[href="/download/fedora_content/show_pretty/actest:1/descMetadata/actest1_description.xml?data=meta"]', text: 'text').click - expect(page).to have_text('Alice\'s Adventures in Wonderland') + # TODO: Only for administrators - not sure how to test this right now + context 'when admin' do + include_context 'admin user for feature' + + xit 'shows the correct Fedora PID' do + expect(page).to have_content 'Fedora 3 PID' + expect(page).to have_content 'actest:1' + end + + xit 'links to the MODS download' do + expect(page).to have_css('a[href="/download/fedora_content/show_pretty/actest:1/descMetadata/actest1_description.xml?data=meta"]', text: 'text') + page.find('a[href="/download/fedora_content/show_pretty/actest:1/descMetadata/actest1_description.xml?data=meta"]', text: 'text').click + expect(page).to have_text('Alice\'s Adventures in Wonderland') + end end it 'has license/rights information' do @@ -128,4 +144,22 @@ expect(page).to have_xpath('//head/meta[@name="citation_pdf_url"][@content="http://www.example.com/doi/10.7916/TESTDOC4/download"]', visible: false) end end + + describe 'author section' do + it 'displays all authors' do + expect(page).to have_content 'Carroll, Lewis' + expect(page).to have_content 'Weird Old Guys' + end + + it 'names are clickable links' do + expect(page).to have_xpath('//a[@href="/search?f%5Bauthor_ssim%5D%5B%5D=Carroll%2C+Lewis"]', text: 'Carroll, Lewis') + expect(page).to have_xpath('//a[@href="/search?f%5Bauthor_ssim%5D%5B%5D=Weird+Old+Guys."]', text: 'Weird Old Guys.') + end + + it 'clicking author link shows correct results' do + find('//a[@href="/search?f%5Bauthor_ssim%5D%5B%5D=Carroll%2C+Lewis"]', text: 'Carroll, Lewis').click + expect(page).to have_current_path '/search?f%5Bauthor_ssim%5D%5B%5D=Carroll%2C+Lewis' + expect(page).to have_content 'Alice\'s Adventures in Wonderland' + end + end end diff --git a/spec/features/static_pages_spec.rb b/spec/features/static_pages_spec.rb index 44ea29277..2e62c1069 100644 --- a/spec/features/static_pages_spec.rb +++ b/spec/features/static_pages_spec.rb @@ -2,9 +2,70 @@ RSpec.describe 'static pages', type: :feature do context 'about' do - it 'render about page' do + before do visit 'about' + end + + it 'render about page' do expect(page).to have_content 'Columbia University Libraries' + expect(page).to have_content 'About' + end + + it 'has link to API documentation' do + expect(page).to have_link 'Academic Commons API', href: developers_path(anchor: 'api') + end + end + + context 'credits' do + it 'render credits page' do + visit 'credits' + expect(page).to have_content 'Credits' + expect(page).to have_content 'Core team' + end + end + + context 'developers' do + before do + visit 'developers' + end + + it 'render developer resources page' do + expect(page).to have_content 'Developer Resources' + expect(page).to have_css '#api' + expect(page).to have_css '#oai' + expect(page).to have_css '#sword' + end + + it 'includes the metadata license' do + expect(page).to have_link href: 'https://creativecommons.org/publicdomain/zero/1.0/' + end + end + + context 'faq' do + it 'render faq page' do + visit 'faq' + expect(page).to have_content 'Frequently Asked Questions' + expect(page).to have_content 'How do I contact repository staff?' + expect(page).to have_css '#policies' + end + end + + context 'policies' do + before do + visit 'policies' + end + + it 'render policies page' do + expect(page).to have_content 'Policies' + expect(page).to have_content 'Terms of Use' + end + + it 'has link to University Confidentiality of Library Records Policy' do + expect(page).to have_link href: 'http://library.columbia.edu/about/policies/confidentiality.html' + end + + it 'has link to Columbia University Data breach Reporting and Responsibility Policy' do + expect(page).to have_link href: 'https://universitypolicies.columbia.edu/content/electronic-data-security-breach-reporting-and-response-policy' # rubocop:disable Layout/LineLength end end end diff --git a/spec/features/upload_spec.rb b/spec/features/upload_spec.rb index 704d51f0b..4246154f8 100644 --- a/spec/features/upload_spec.rb +++ b/spec/features/upload_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe 'Upload', type: :feature do @@ -140,8 +142,34 @@ it 'sends student reminder email' do email = ActionMailer::Base.deliveries.pop expect(email.subject).to eql 'Department approval may be needed' + expect(email.to).to include User.first.email end + + it 'appears in the myworks list' do + visit myworks_path + expect(page).to have_content 'Test Deposit' + end + + it 'appears in the myworks list as pending' do + visit myworks_path + within '[id="pending-works-table"]' do + expect(page).to have_content 'Test Deposit' + end + end + + it 'appears in the admin self-deposits list' do + logout(:user) + login_as FactoryBot.create(:admin), scope: :user + visit admin_deposits_path + expect(page).to have_content 'Test Deposit' + end + + it 'is downloadable within the admin self-deposits section' do + deposit = Deposit.last + visit admin_deposit_path(deposit) + expect(page).to have_link 'test_file.txt', href: rails_blob_path(deposit.files.first, disposition: 'attachment') + end end context 'when student submits form with missing required data' do diff --git a/spec/models/deposit_spec.rb b/spec/models/deposit_spec.rb index ec2b4de68..cf7a7b9e5 100644 --- a/spec/models/deposit_spec.rb +++ b/spec/models/deposit_spec.rb @@ -1,6 +1,97 @@ require 'rails_helper' describe Deposit, type: :model do + it 'saves deposit with valid attributes' do + deposit = FactoryBot.build(:deposit) + expect(deposit).to be_valid + expect { deposit.save! }.not_to raise_error + end + + it 'saves the metadata store attributes' do # rubocop:disable RSpec/MultipleExpectations + deposit = FactoryBot.create(:deposit) + deposit.save! + expect(deposit.metadata).to be_present + expect(deposit.title).to eq 'Test Deposit' + expect(deposit.abstract).to eq 'foobar' + expect(deposit.year).to eq '2018' + expect(deposit.doi).to eq 'https://www.example.com' + expect(deposit.license).to eq 'https://creativecommons.org/licenses/by/4.0/' + expect(deposit.rights).to eq 'http://rightsstatements.org/vocab/InC/1.0/' + expect(deposit.notes).to eq 'This deposit is just for testing purposes.' + expect(deposit.creators).to eq [ + { 'first_name' => 'Jane', 'last_name' => 'Doe', 'uni' => 'abc123' }, + { 'first_name' => 'John', 'last_name' => 'Doe', 'uni' => '' } + ] + end + + describe 'validations' do + describe 'should be invalid' do + it 'without a title' do + deposit = FactoryBot.build(:deposit, title: nil) + expect(deposit).not_to be_valid + end + + it 'without an abstract' do + deposit = FactoryBot.build(:deposit, abstract: nil) + expect(deposit).not_to be_valid + end + + it 'without a year' do + deposit = FactoryBot.build(:deposit, year: nil) + expect(deposit).not_to be_valid + end + + it 'without rights' do + deposit = FactoryBot.build(:deposit, rights: nil) + expect(deposit).not_to be_valid + end + + it 'without uploaded files' do + deposit = FactoryBot.build(:deposit).tap do |dep| + dep.files.detach # files added by factory in after(:build) hook -- detach them here + end + expect(deposit).not_to be_valid + end + + it 'without previously_published value' do + deposit = FactoryBot.build(:deposit, previously_published: nil) + expect(deposit).not_to be_valid + end + + it 'without current_student value' do + deposit = FactoryBot.build(:deposit, current_student: nil) + expect(deposit).not_to be_valid + end + + it 'with invalid rights' do + deposit = FactoryBot.build(:deposit, rights: 'invalid') + expect(deposit).not_to be_valid + end + + it 'with invalid license' do + deposit = FactoryBot.build(:deposit, license: 'invalid') + expect(deposit).not_to be_valid + end + + describe 'when current_student is true' do + it 'without degree_program' do + deposit = FactoryBot.build(:deposit, current_student: true, degree_program: nil) + expect(deposit).not_to be_valid + end + + it 'without academic_advisor' do + deposit = FactoryBot.build(:deposit, current_student: true, academic_advisor: nil) + expect(deposit).not_to be_valid + end + + it 'without thesis_or_dissertation' do + deposit = FactoryBot.build(:deposit, current_student: true, thesis_or_dissertation: nil) + expect(deposit).not_to be_valid + end + end + end + end + describe '#mets' do shared_examples 'generates expected mets' do it 'generates correct mets' do diff --git a/spec/models/email_preference_spec.rb b/spec/models/email_preference_spec.rb index 386b54840..202560c6f 100644 --- a/spec/models/email_preference_spec.rb +++ b/spec/models/email_preference_spec.rb @@ -1,13 +1,19 @@ require 'rails_helper' describe EmailPreference, type: :model do - context 'when creating multiple records with the same uni' do - before do - EmailPreference.create!(uni: 'abc123') + context 'when creating an invalid record' do + it 'with missing uni returns error' do + expect { EmailPreference.create! }.to raise_error ActiveRecord::RecordInvalid end - it 'returns error' do - expect { EmailPreference.create!(uni: 'abc123') }.to raise_error ActiveRecord::RecordInvalid + describe 'with a uni that already has existing preferences' do + before do + EmailPreference.create!(uni: 'abc123') + end + + it 'returns error' do + expect { EmailPreference.create!(uni: 'abc123') }.to raise_error ActiveRecord::RecordInvalid + end end end @@ -32,7 +38,7 @@ expect(preferred_emails).to include('nop123' => 'nop123@columbia.edu') end - it 'removes unsubcribed users' do + it 'removes unsubscribed users' do expect(preferred_emails).not_to include 'abc123' end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 78e0deaf3..daec6c342 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -41,7 +41,8 @@ RSpec.configure do |config| config.include Devise::Test::ControllerHelpers, type: :controller config.include Devise::Test::ControllerHelpers, type: :view - config.include ActiveJob::TestHelper, type: :job + config.include Devise::Test::IntegrationHelpers, type: :request + config.include ActiveJob::TestHelper, type: :job config.include FixtureHelpers config.include Warden::Test::Helpers config.include ActiveSupport::Testing::TimeHelpers diff --git a/spec/requests/authentication_spec.rb b/spec/requests/authentication_spec.rb new file mode 100644 index 000000000..d2dd37bdb --- /dev/null +++ b/spec/requests/authentication_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'authentication', type: :request do + include_context 'mock ldap request' # provides uni, cul_ldap, and cul_ldap entry as well as mocks LDAP methods + describe 'when user not logged in' do + it 'redirects access to protected pages to sign in page' do + get '/admin' + expect(response).to redirect_to new_user_session_path + end + end + + describe 'when user signed in as non-admin' do + before do + user = FactoryBot.create(:user) + sign_in user + get '/admin' + end + + it 'renders error page when accessing admin-only routes' do + expect(response).to have_http_status(:forbidden) + expect(response.body).to include 'You do not have access' + end + end + + describe 'when user is admin' do + before do + admin_user = FactoryBot.create(:admin) + sign_in admin_user + get '/admin' + end + + it 'allows access to admin-only routes' do + expect(response).to render_template(:index) + end + end +end diff --git a/spec/support/authorization_for_feature_tests.rb b/spec/support/authorization_for_feature_tests.rb index 1be18690e..45cf07528 100644 --- a/spec/support/authorization_for_feature_tests.rb +++ b/spec/support/authorization_for_feature_tests.rb @@ -7,6 +7,8 @@ ldap = instance_double('Cul::LDAP') allow(Cul::LDAP).to receive(:new).and_return(ldap) allow(ldap).to receive(:find_by_uni).with('tu123').and_return(nil) + # for tests where we need to login as an admin user to test a non-admin action + allow(ldap).to receive(:find_by_uni).with('ta123').and_return(nil) login_as FactoryBot.create(:user), scope: :user end end