blacklight-spotlight 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/spotlight/check_user_existence.js +16 -9
  3. data/app/assets/javascripts/spotlight/tabs.js +6 -0
  4. data/app/assets/javascripts/spotlight/users.js +1 -1
  5. data/app/assets/stylesheets/spotlight/_upload.scss +0 -5
  6. data/app/controllers/spotlight/admin_users_controller.rb +49 -0
  7. data/app/controllers/spotlight/catalog_controller.rb +0 -7
  8. data/app/controllers/spotlight/concerns/user_existable.rb +24 -0
  9. data/app/controllers/spotlight/concerns/user_invitable.rb +30 -0
  10. data/app/controllers/spotlight/exhibits_controller.rb +3 -0
  11. data/app/controllers/spotlight/resources/csv_upload_controller.rb +42 -0
  12. data/app/controllers/spotlight/resources/upload_controller.rb +2 -27
  13. data/app/controllers/spotlight/resources_controller.rb +7 -24
  14. data/app/controllers/spotlight/roles_controller.rb +2 -29
  15. data/app/models/spotlight/exhibit.rb +2 -0
  16. data/app/models/spotlight/resource.rb +0 -14
  17. data/app/views/devise/mailer/invitation_instructions.html.erb +11 -4
  18. data/app/views/shared/_site_sidebar.html.erb +2 -1
  19. data/app/views/spotlight/admin_users/index.html.erb +57 -0
  20. data/app/views/spotlight/catalog/_admin_header.html.erb +3 -9
  21. data/app/views/spotlight/exhibits/_tags.html.erb +11 -0
  22. data/app/views/spotlight/exhibits/index.html.erb +12 -3
  23. data/app/views/spotlight/home_pages/_empty.html.erb +2 -2
  24. data/app/views/spotlight/resources/_external_resources_form.html.erb +20 -0
  25. data/app/views/spotlight/resources/_missing_external_resources_partials.html.erb +5 -0
  26. data/app/views/spotlight/resources/{upload/_multi_item_form.html.erb → csv_upload/_form.html.erb} +1 -1
  27. data/app/views/spotlight/resources/new.html.erb +18 -3
  28. data/app/views/spotlight/resources/upload/{_single_item_form.html.erb → _form.html.erb} +0 -0
  29. data/config/locales/spotlight.en.yml +40 -12
  30. data/config/routes.rb +18 -6
  31. data/lib/spotlight/engine.rb +2 -3
  32. data/lib/spotlight/version.rb +1 -1
  33. data/spec/controllers/spotlight/admin_users_controller_spec.rb +83 -0
  34. data/spec/controllers/spotlight/catalog_controller_spec.rb +0 -11
  35. data/spec/controllers/spotlight/resources/csv_upload_controller_spec.rb +59 -0
  36. data/spec/controllers/spotlight/resources/upload_controller_spec.rb +1 -51
  37. data/spec/controllers/spotlight/resources_controller_spec.rb +0 -12
  38. data/spec/controllers/spotlight/roles_controller_spec.rb +1 -1
  39. data/spec/features/{upload_non_repository_item_spec.rb → add_items_spec.rb} +28 -16
  40. data/spec/features/exhibits_index_spec.rb +31 -0
  41. data/spec/features/site_admin_management_spec.rb +67 -0
  42. data/spec/models/spotlight/resource_spec.rb +0 -9
  43. data/spec/views/spotlight/catalog/admin.html.erb_spec.rb +7 -8
  44. data/spec/views/spotlight/exhibits/index.html.erb_spec.rb +47 -1
  45. data/spec/views/spotlight/home_pages/_empty.html.erb_spec.rb +4 -3
  46. data/spec/views/spotlight/resources/_external_resources_form.html.erb_spec.rb +23 -0
  47. data/spec/views/spotlight/{catalog → resources}/new.html.erb_spec.rb +2 -2
  48. metadata +26 -19
  49. data/app/models/spotlight/resource_provider.rb +0 -24
  50. data/app/views/layouts/spotlight/popup.html.erb +0 -52
  51. data/app/views/spotlight/catalog/new.html.erb +0 -7
  52. data/app/views/spotlight/resources/_bookmarklet.html.erb +0 -5
  53. data/app/views/spotlight/resources/_form.html.erb +0 -23
  54. data/app/views/spotlight/resources/upload/new.html.erb +0 -22
  55. data/spec/features/add_item_bookmarklet_spec.rb +0 -33
  56. data/spec/models/spotlight/resource_provider_spec.rb +0 -27
@@ -190,17 +190,6 @@ describe Spotlight::CatalogController, type: :controller do
190
190
  expect(controller.blacklight_config.view.admin_table.document_actions).to be_empty
191
191
  end
192
192
 
193
- describe 'GET new' do
194
- it 'is successful' do
195
- expect(controller).to receive(:add_breadcrumb).with('Home', exhibit_path(exhibit, q: ''))
196
- expect(controller).to receive(:add_breadcrumb).with('Curation', exhibit_dashboard_path(exhibit))
197
- expect(controller).to receive(:add_breadcrumb).with('Items', admin_exhibit_catalog_index_path(exhibit))
198
- expect(controller).to receive(:add_breadcrumb).with('Import items', new_exhibit_catalog_path(exhibit))
199
- get :new, exhibit_id: exhibit
200
- expect(response).to be_successful
201
- end
202
- end
203
-
204
193
  describe 'GET edit' do
205
194
  it 'is successful' do
206
195
  get :edit, exhibit_id: exhibit, id: 'dq287tq6352'
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spotlight::Resources::CsvUploadController, type: :controller do
4
+ routes { Spotlight::Engine.routes }
5
+ let(:exhibit) { FactoryGirl.create(:exhibit) }
6
+
7
+ describe 'when not logged in' do
8
+ describe 'POST create' do
9
+ it 'is not allowed' do
10
+ post :create, exhibit_id: exhibit
11
+ expect(response).to redirect_to main_app.new_user_session_path
12
+ end
13
+ end
14
+ end
15
+
16
+ describe 'when signed in as a curator' do
17
+ let(:user) { FactoryGirl.create(:exhibit_curator, exhibit: exhibit) }
18
+ before { sign_in user }
19
+
20
+ describe 'POST create' do
21
+ let(:csv) { fixture_file_upload(File.expand_path(File.join('..', 'spec', 'fixtures', 'csv-upload-fixture.csv'), Rails.root), 'text/csv') }
22
+ let(:serialized_csv) do
23
+ [
24
+ {
25
+ 'url' => 'http://lorempixel.com/800/500/',
26
+ 'full_title_tesim' => 'A random image',
27
+ 'spotlight_upload_description_tesim' => 'A random 800 by 500 image from lorempixel',
28
+ 'spotlight_upload_attribution_tesim' => 'lorempixel.com',
29
+ 'spotlight_upload_date_tesim' => '2015'
30
+ },
31
+ {
32
+ 'url' => 'http://lorempixel.com/900/600/',
33
+ 'full_title_tesim' => 'Another random image',
34
+ 'spotlight_upload_description_tesim' => 'A random 900 by 600 image from lorempixel',
35
+ 'spotlight_upload_attribution_tesim' => 'lorempixel.com',
36
+ 'spotlight_upload_date_tesim' => '2014'
37
+ }
38
+ ]
39
+ end
40
+ before do
41
+ request.env['HTTP_REFERER'] = 'http://test.host/'
42
+ end
43
+ it 'starts an AddUploadsFromCSV job with the serialized CSV' do
44
+ expect(Spotlight::AddUploadsFromCSV).to receive(:perform_later).with(serialized_csv, exhibit, user).and_return(nil)
45
+ post :create, exhibit_id: exhibit, resources_csv_upload: { url: csv }
46
+ end
47
+ it 'sets the flash message' do
48
+ expect(Spotlight::AddUploadsFromCSV).to receive(:perform_later).and_return(nil)
49
+ post :create, exhibit_id: exhibit, resources_csv_upload: { url: csv }
50
+ expect(flash[:notice]).to eq "'csv-upload-fixture.csv' has been uploaded. An email will be sent to you once indexing is complete."
51
+ end
52
+ it 'redirects back' do
53
+ expect(Spotlight::AddUploadsFromCSV).to receive(:perform_later).and_return(nil)
54
+ post :create, exhibit_id: exhibit, resources_csv_upload: { url: csv }
55
+ expect(response).to redirect_to :back
56
+ end
57
+ end
58
+ end
59
+ end
@@ -17,56 +17,6 @@ describe Spotlight::Resources::UploadController, type: :controller do
17
17
  let(:user) { FactoryGirl.create(:exhibit_curator, exhibit: exhibit) }
18
18
  before { sign_in user }
19
19
 
20
- describe 'GET new' do
21
- it 'is successful' do
22
- expect(controller).to receive(:add_breadcrumb).with('Home', exhibit_path(exhibit))
23
- expect(controller).to receive(:add_breadcrumb).with('Curation', exhibit_dashboard_path(exhibit))
24
- expect(controller).to receive(:add_breadcrumb).with('Items', admin_exhibit_catalog_index_path(exhibit))
25
- expect(controller).to receive(:add_breadcrumb).with('Add non-repository items', new_exhibit_resources_upload_path(exhibit))
26
- get :new, exhibit_id: exhibit
27
- expect(response).to be_successful
28
- end
29
- end
30
-
31
- describe 'POST csv_upload' do
32
- let(:csv) { fixture_file_upload(File.expand_path(File.join('..', 'spec', 'fixtures', 'csv-upload-fixture.csv'), Rails.root), 'text/csv') }
33
- let(:serialized_csv) do
34
- [
35
- {
36
- 'url' => 'http://lorempixel.com/800/500/',
37
- 'full_title_tesim' => 'A random image',
38
- 'spotlight_upload_description_tesim' => 'A random 800 by 500 image from lorempixel',
39
- 'spotlight_upload_attribution_tesim' => 'lorempixel.com',
40
- 'spotlight_upload_date_tesim' => '2015'
41
- },
42
- {
43
- 'url' => 'http://lorempixel.com/900/600/',
44
- 'full_title_tesim' => 'Another random image',
45
- 'spotlight_upload_description_tesim' => 'A random 900 by 600 image from lorempixel',
46
- 'spotlight_upload_attribution_tesim' => 'lorempixel.com',
47
- 'spotlight_upload_date_tesim' => '2014'
48
- }
49
- ]
50
- end
51
- before do
52
- request.env['HTTP_REFERER'] = 'http://test.host/'
53
- end
54
- it 'starts an AddUploadsFromCSV job with the serialized CSV' do
55
- expect(Spotlight::AddUploadsFromCSV).to receive(:perform_later).with(serialized_csv, exhibit, user).and_return(nil)
56
- post :csv_upload, exhibit_id: exhibit, resources_csv_upload: { url: csv }
57
- end
58
- it 'sets the flash message' do
59
- expect(Spotlight::AddUploadsFromCSV).to receive(:perform_later).and_return(nil)
60
- post :csv_upload, exhibit_id: exhibit, resources_csv_upload: { url: csv }
61
- expect(flash[:notice]).to eq "'csv-upload-fixture.csv' has been uploaded. An email will be sent to you once indexing is complete."
62
- end
63
- it 'redirects back' do
64
- expect(Spotlight::AddUploadsFromCSV).to receive(:perform_later).and_return(nil)
65
- post :csv_upload, exhibit_id: exhibit, resources_csv_upload: { url: csv }
66
- expect(response).to redirect_to :back
67
- end
68
- end
69
-
70
20
  describe 'POST create' do
71
21
  let(:blacklight_solr) { double }
72
22
 
@@ -88,7 +38,7 @@ describe Spotlight::Resources::UploadController, type: :controller do
88
38
  it 'redirects to the upload form when the add-and-continue parameter is present' do
89
39
  post :create, exhibit_id: exhibit, 'add-and-continue' => 'true', resources_upload: { url: 'url-data' }
90
40
  expect(flash[:notice]).to eq 'Object uploaded successfully.'
91
- expect(response).to redirect_to new_exhibit_resources_upload_path(exhibit)
41
+ expect(response).to redirect_to new_exhibit_resource_path(exhibit, anchor: 'new_resources_upload')
92
42
  end
93
43
  end
94
44
  end
@@ -43,18 +43,6 @@ describe Spotlight::ResourcesController, type: :controller do
43
43
  get :new, exhibit_id: exhibit
44
44
  expect(response).to render_template 'spotlight/resources/new'
45
45
  end
46
-
47
- it 'populates the resource with parameters from the url' do
48
- get :new, exhibit_id: exhibit, resource: { url: 'info:uri' }
49
- expect(assigns[:resource].url).to eq 'info:uri'
50
- end
51
-
52
- describe 'Within a popup' do
53
- it 'renders with the simplified popup layout' do
54
- get :new, exhibit_id: exhibit, popup: true
55
- expect(response).to render_template 'layouts/spotlight/popup'
56
- end
57
- end
58
46
  end
59
47
 
60
48
  describe 'GET monitor' do
@@ -116,7 +116,7 @@ describe Spotlight::RolesController, type: :controller do
116
116
 
117
117
  it 'redirects back with a flash notice upon success' do
118
118
  post :invite, exhibit_id: exhibit, user: 'user@example.com', role: 'curator'
119
- expect(flash[:notice]).to eq 'User has been updated.'
119
+ expect(flash[:notice]).to eq 'User has been invited.'
120
120
  expect(response).to redirect_to(:back)
121
121
  end
122
122
 
@@ -8,9 +8,11 @@ describe 'Uploading a non-repository item', type: :feature do
8
8
 
9
9
  describe 'forms' do
10
10
  it 'displays the single item upload form' do
11
- visit spotlight.new_exhibit_resources_upload_path(exhibit)
11
+ visit spotlight.new_exhibit_resource_path(exhibit)
12
12
  expect(page).to have_css('h1', text: /Curation/)
13
- expect(page).to have_css 'h1 small', text: 'Add non-repository items'
13
+ expect(page).to have_css 'h1 small', text: 'Add items'
14
+
15
+ click_link 'Upload item'
14
16
 
15
17
  within('form#new_resources_upload') do
16
18
  expect(page).to have_css('#resources_upload_url[type="file"]')
@@ -22,20 +24,12 @@ describe 'Uploading a non-repository item', type: :feature do
22
24
  expect(page).to have_css("#resources_upload_data_#{custom_field.field}[type='text']")
23
25
  end
24
26
  end
25
- it 'displays the multi-item CSV upload form' do
26
- visit spotlight.new_exhibit_resources_upload_path(exhibit)
27
- expect(page).to have_css('h1', text: /Curation/)
28
- expect(page).to have_css 'h1 small', text: 'Add non-repository items'
29
- within('form#new_resources_csv_upload') do
30
- expect(page).to have_css('#resources_csv_upload_url[type="file"]')
31
- expect(page).to have_css('.help-block a', text: 'Download template')
32
- end
33
- end
34
- end
35
27
 
36
- describe 'upload' do
37
- it 'creates a new non-repository item' do
38
- visit spotlight.new_exhibit_resources_upload_path(exhibit)
28
+ it 'creates a new item' do
29
+ visit spotlight.new_exhibit_resource_path(exhibit)
30
+
31
+ click_link 'Upload item'
32
+
39
33
  attach_file('resources_upload_url', File.join(FIXTURES_PATH, '800x600.png'))
40
34
  fill_in 'Title', with: '800x600'
41
35
 
@@ -49,8 +43,26 @@ describe 'Uploading a non-repository item', type: :feature do
49
43
  Blacklight.default_index.connection.commit
50
44
  end
51
45
 
46
+ it 'displays the multi-item CSV upload form' do
47
+ visit spotlight.new_exhibit_resource_path(exhibit)
48
+ expect(page).to have_css('h1', text: /Curation/)
49
+ expect(page).to have_css 'h1 small', text: 'Add items'
50
+
51
+ click_link 'Upload multiple items'
52
+
53
+ within('form#new_resources_csv_upload') do
54
+ expect(page).to have_css('#resources_csv_upload_url[type="file"]')
55
+ expect(page).to have_css('.help-block a', text: 'Download template')
56
+ end
57
+ end
58
+ end
59
+
60
+ describe 'upload' do
52
61
  it 'is editable' do
53
- visit spotlight.new_exhibit_resources_upload_path(exhibit)
62
+ visit spotlight.new_exhibit_resource_path(exhibit)
63
+
64
+ click_link 'Upload item'
65
+
54
66
  attach_file('resources_upload_url', File.join(FIXTURES_PATH, '800x600.png'))
55
67
  fill_in 'Title', with: '800x600'
56
68
 
@@ -12,6 +12,37 @@ describe 'Exhibits index page', type: :feature do
12
12
  expect(page).to have_selector 'h2', text: 'Some Exhibit Title'
13
13
  end
14
14
  end
15
+
16
+ context 'with tagged exhibits' do
17
+ before do
18
+ exhibit.tag_list = %w(a)
19
+ other_exhibit.tag_list = %w(a b)
20
+
21
+ exhibit.save
22
+ other_exhibit.save
23
+ end
24
+
25
+ it 'shows controls to filter exhibits by tags' do
26
+ visit spotlight.exhibits_path
27
+
28
+ expect(page).to have_selector '.exhibit-card', count: 2
29
+
30
+ within '.tags' do
31
+ expect(page).to have_selector '.active', text: 'All'
32
+
33
+ click_link 'a'
34
+ end
35
+
36
+ expect(page).to have_selector '.exhibit-card', count: 2
37
+
38
+ within '.tags' do
39
+ expect(page).to have_selector '.active', text: 'a'
40
+ click_link 'b'
41
+ end
42
+
43
+ expect(page).to have_selector '.exhibit-card', count: 1
44
+ end
45
+ end
15
46
  end
16
47
 
17
48
  context 'with a single exhibit' do
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Site admin management', js: true do
4
+ let(:user) { FactoryGirl.create(:site_admin) }
5
+ let(:existing_user) { FactoryGirl.create(:exhibit_visitor) }
6
+
7
+ before do
8
+ login_as(user)
9
+ visit spotlight.admin_users_path
10
+ end
11
+
12
+ it 'displays the current admin users' do
13
+ expect(page).to have_css('td', text: user.email)
14
+ end
15
+
16
+ it 'allows for existing users to be added as site adminstrators' do
17
+ expect(page).not_to have_css('td', text: existing_user.email)
18
+ click_link 'Add new administrator'
19
+
20
+ fill_in 'user_email', with: existing_user.email
21
+ click_button 'Add role'
22
+
23
+ expect(page).to have_content('Added user as exhibts adminstrator')
24
+ expect(page).to have_css('td', text: existing_user.email)
25
+ end
26
+
27
+ it 'allows non-existing users to be invited' do
28
+ click_link 'Add new administrator'
29
+
30
+ fill_in 'user_email', with: 'not-an-existing-user@example.com'
31
+
32
+ expect(page).to have_content('This user does not yet exist. Would you like to send them an invite?')
33
+
34
+ expect { click_link('invite') }.to change { ActionMailer::Base.deliveries.count }.by(1)
35
+
36
+ expect(page).to have_content('User has been invited.')
37
+ end
38
+
39
+ it 'allows the admin to remove the admin role from the user' do
40
+ click_link 'Add new administrator'
41
+
42
+ fill_in 'user_email', with: 'not-an-admin@example.com'
43
+
44
+ click_link 'invite'
45
+ expect(page).to have_content('User has been invited.')
46
+
47
+ expect(page).to have_css(:td, text: 'not-an-admin@example.com')
48
+
49
+ expect(page).to have_css(:a, text: 'Remove from role', count: 2)
50
+ within(all('table tbody tr').last) do
51
+ click_link 'Remove from role'
52
+ end
53
+
54
+ expect(page).to have_content 'User removed from site adminstrator role'
55
+ expect(page).to have_css(:a, text: 'Remove from role', count: 1)
56
+
57
+ expect(page).not_to have_css(:td, text: 'not-an-admin@example.com')
58
+ end
59
+
60
+ it 'does not provide a button for users to remove their own adminstrator privs' do
61
+ click_link 'Add new administrator'
62
+
63
+ expect(page).to have_css('td', text: user.email)
64
+ # There are two users, the original site admin and our admin user so only one button
65
+ expect(page).to have_css(:a, text: 'Remove from role', count: 1)
66
+ end
67
+ end
@@ -89,15 +89,6 @@ describe Spotlight::Resource, type: :model do
89
89
  end
90
90
  end
91
91
 
92
- describe '#becomes_provider' do
93
- it 'converts the resource to a provider-specific resource' do
94
- SomeClass = Class.new(described_class)
95
- allow(Spotlight::ResourceProvider).to receive_messages(for_resource: SomeClass)
96
- expect(subject.becomes_provider).to be_a_kind_of(SomeClass)
97
- expect(subject.becomes_provider.type).to eq 'SomeClass'
98
- end
99
- end
100
-
101
92
  describe '#save_and_index' do
102
93
  before do
103
94
  allow(subject.send(:blacklight_solr)).to receive(:update)
@@ -7,8 +7,7 @@ module Spotlight
7
7
  allow(view).to receive(:blacklight_config).and_return(CatalogController.blacklight_config)
8
8
  allow(view).to receive(:spotlight_page_path_for).and_return(nil)
9
9
  allow(view).to receive(:current_exhibit).and_return(exhibit)
10
- allow(view).to receive(:new_exhibit_catalog_path).and_return('')
11
- allow(view).to receive(:new_exhibit_resources_upload_path).and_return('')
10
+ allow(view).to receive(:new_exhibit_resource_path).and_return('')
12
11
  allow(view).to receive(:reindex_all_exhibit_resources_path).and_return('')
13
12
  allow(view).to receive(:monitor_exhibit_resources_path).and_return('')
14
13
  assign(:exhibit, exhibit)
@@ -23,16 +22,16 @@ module Spotlight
23
22
  expect(rendered).to have_link 'Browse'
24
23
  end
25
24
 
26
- it "does not render the 'add repository item' link if no repository sources are configured" do
27
- allow(Spotlight::Engine.config).to receive(:new_resource_partials).and_return([])
25
+ it "renders the 'add items' link if any repository sources are configured" do
26
+ allow(Spotlight::Engine.config).to receive(:resource_partials).and_return(['a'])
28
27
  render
29
- expect(rendered).to_not have_link 'Add repository item'
28
+ expect(rendered).to have_link 'Add items'
30
29
  end
31
30
 
32
- it "does not render the 'add repository item' link if no repository sources are configured" do
33
- allow(Spotlight::Engine.config).to receive(:new_resource_partials).and_return(['a'])
31
+ it "does not render the 'add items' link if no repository sources are configured" do
32
+ allow(Spotlight::Engine.config).to receive(:resource_partials).and_return([])
34
33
  render
35
- expect(rendered).to have_link 'Add repository item'
34
+ expect(rendered).not_to have_link 'Add items'
36
35
  end
37
36
  end
38
37
  end
@@ -3,12 +3,15 @@ require 'spec_helper'
3
3
  module Spotlight
4
4
  describe 'spotlight/exhibits/index', type: :view do
5
5
  let(:exhibits) { Spotlight::Exhibit.none }
6
+ let(:published_exhibits) { exhibits.published.page(1) }
7
+
6
8
  let(:ability) { ::Ability.new(user) }
7
9
  let(:user) { Spotlight::Engine.user_class.new }
8
10
 
9
11
  before do
10
12
  assign(:exhibits, exhibits)
11
- allow(view).to receive_messages(exhibit_path: '/', current_user: user, current_ability: ability)
13
+ assign(:published_exhibits, published_exhibits)
14
+ allow(view).to receive_messages(exhibits_path: '/', exhibit_path: '/', current_user: user, current_ability: ability)
12
15
  end
13
16
 
14
17
  context 'with published exhibits' do
@@ -35,6 +38,49 @@ module Spotlight
35
38
  expect(rendered).not_to have_selector '.nav-tabs'
36
39
  end
37
40
 
41
+ it 'does not include tags controls' do
42
+ render
43
+
44
+ expect(rendered).not_to have_selector '.tags'
45
+ end
46
+
47
+ it 'does not include pagination controls' do
48
+ render
49
+
50
+ expect(rendered).not_to have_selector '.pager'
51
+ end
52
+
53
+ context 'with tagged exhibits' do
54
+ before do
55
+ exhibit_a.tag_list = ['a']
56
+ exhibit_b.tag_list = ['a']
57
+ exhibit_c.tag_list = ['b']
58
+
59
+ exhibit_a.save
60
+ exhibit_b.save
61
+ exhibit_c.save
62
+ end
63
+
64
+ it 'filters by tags' do
65
+ render
66
+
67
+ expect(rendered).to have_link 'All'
68
+ expect(rendered).to have_link 'a'
69
+ expect(rendered).to have_link 'b'
70
+ end
71
+ end
72
+
73
+ context 'with paginated exhibits' do
74
+ let(:published_exhibits) { exhibits.published.page(1).per(1) }
75
+
76
+ it 'renders pagination controls' do
77
+ render
78
+
79
+ expect(rendered).to have_selector '.pager'
80
+ expect(rendered).to have_link 'Next', href: '/?page=2'
81
+ end
82
+ end
83
+
38
84
  context 'with an exhibit admin' do
39
85
  let(:user) { FactoryGirl.create(:exhibit_admin) }
40
86