Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more comprehensive testing for publications controller #338

Merged
merged 5 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion app/controllers/publications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,14 @@ def index
end

def show
@submitter = helpers.find_submitter(instance_variable_get("@#{controller_name.singularize}").id) if session[:admin]
return unless session[:admin]

resource = controller_name.singularize
resource_instance = instance_variable_get("@#{resource}")

raise ActiveRecord::RecordNotFound unless resource_instance

@submitter = helpers.find_submitter(resource_instance.id)
end

def new
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

# The PublicationsController is responsible for handling the requests for all
# publications. Each model inherits its CRUD actions from this controller.
# We do not actually have a Publications model, so for testing purposes
# we will use the Book model, which is a child of the Publication model.
#
require 'rails_helper'

# We are calling BooksController, a "child" of PublicationsController, so we
# need to define it here.
RSpec.describe BooksController, type: :controller do
it_behaves_like 'restricts non-logged-in users', {
'index' => :get,
'show' => :get,
'new' => :get,
'edit' => :get,
'create' => :post,
'update' => :put,
'destroy' => :delete
}
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# frozen_string_literal: true

# The PublicationsController is responsible for handling the requests for all
# publications. Each model inherits its CRUD actions from this controller.
# We do not actually have a Publications model, so for testing purposes
# we will use the Book model, which is a child of the Publication model.
#
require 'rails_helper'

# We are calling BooksController, a "child" of PublicationsController, so we
# need to define it here.
RSpec.describe BooksController, type: :controller do
let(:submitter) { FactoryBot.create(:submitter) }
let(:another_submitter) { FactoryBot.create(:submitter) }

let(:submitter_id) { submitter.id.to_s }
let(:another_submitter_id) { another_submitter.id.to_s }

let(:valid_attributes) do
{ 'author_first_name' => %w[Test Person],
'author_last_name' => %w[Case 2],
'college_ids' => ['', '1', '2'],
'uc_department' => 'Dept',
'work_title' => 'WT',
'other_title' => 'OT',
'publisher' => 'Pub',
'city' => 'City',
'publication_date' => 'Today',
'url' => 'www.fake.com',
'doi' => 'doi:' }
end

let(:invalid_attributes) do
{ 'author_first_name' => ['Bad'],
'author_last_name' => [''],
'college_ids' => [''],
'uc_department' => '',
'work_title' => '',
'other_title' => '',
'publisher' => '',
'city' => '',
'publication_date' => '',
'url' => '',
'doi' => '' }
end

let(:already_created_book_by_submitter) { FactoryBot.create(:book, valid_attributes.merge(submitter_id:)) }
let(:already_created_book_by_another_submitter) { FactoryBot.create(:book, valid_attributes.merge(submitter_id: another_submitter_id)) }

describe 'POST #create' do
before do
already_created_book_by_submitter
login_as_submitter_of(already_created_book_by_submitter)
end

context 'with valid params' do
it 'creates a new Book' do
expect do
post :create, params: { book: valid_attributes }
end.to change(Book, :count).by(1)
end

it 'redirects to the publications path after creation' do
post :create, params: { book: valid_attributes }
expect(response).to redirect_to(publications_path)
end
end

context 'with invalid params' do
it 'does not create a new Book' do
expect do
post :create, params: { book: invalid_attributes }
end.not_to change(Book, :count)
end

it "redirects to the 'new' template with status 'unprocessable_entity'" do
post :create, params: { book: invalid_attributes }
expect(response).to render_template(:new)
expect(response.status).to eql 422
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# frozen_string_literal: true

# The PublicationsController is responsible for handling the requests for all
# publications. Each model inherits its CRUD actions from this controller.
# We do not actually have a Publications model, so for testing purposes
# we will use the Book model, which is a child of the Publication model.
#
require 'rails_helper'

# We are calling BooksController, a "child" of PublicationsController, so we
# need to define it here.
RSpec.describe BooksController, type: :controller do
let(:submitter) { FactoryBot.create(:submitter) }
let(:another_submitter) { FactoryBot.create(:submitter) }

let(:submitter_id) { submitter.id.to_s }
let(:another_submitter_id) { another_submitter.id.to_s }

let(:valid_attributes) do
{ 'author_first_name' => %w[Test Person],
'author_last_name' => %w[Case 2],
'college_ids' => ['', '1', '2'],
'uc_department' => 'Dept',
'work_title' => 'WT',
'other_title' => 'OT',
'publisher' => 'Pub',
'city' => 'City',
'publication_date' => 'Today',
'url' => 'www.fake.com',
'doi' => 'doi:' }
end

let(:already_created_book_by_submitter) { FactoryBot.create(:book, valid_attributes.merge(submitter_id:)) }
let(:already_created_book_by_another_submitter) { FactoryBot.create(:book, valid_attributes.merge(submitter_id: another_submitter_id)) }

describe 'DELETE #destroy' do
before do
already_created_book_by_submitter
already_created_book_by_another_submitter
end

context 'when attempting to delete books as a submitter' do
before do
login_as_submitter_of(already_created_book_by_submitter)
end

context 'and the book belongs to the submitter' do
it 'destroys only the requested book' do
expect { Book.find(already_created_book_by_submitter.id) }.not_to raise_error
expect do
delete :destroy, params: { id: already_created_book_by_submitter.id }
end.to change(Book, :count).by(-1)
expect { Book.find(already_created_book_by_submitter.id) }.to raise_error(ActiveRecord::RecordNotFound)
end

it 'redirects to the publications_path' do
delete :destroy, params: { id: already_created_book_by_submitter.id }
expect(response).to redirect_to(publications_path)
end

it 'displays a success flash notice' do
delete :destroy, params: { id: already_created_book_by_submitter.id }
expect(flash[:warning]).to eql 'Book was successfully destroyed.'
end
end

context 'and the book does not belong to the submitter' do
it 'raises a 404 error and does not destroy the requested book' do
expect { Book.find(already_created_book_by_another_submitter.id) }.not_to raise_error
initial_book_count = Book.count
expect do
delete :destroy, params: { id: already_created_book_by_another_submitter.id }
end.to raise_error(ActiveRecord::RecordNotFound)
expect(Book.count).to eql initial_book_count
expect { Book.find(already_created_book_by_another_submitter.id) }.not_to raise_error
end
end
end

context 'when attempting to delete books as an admin' do
before do
login_as_admin_unit_test
end

it 'destroys the requested books by either submitter' do
expect { Book.find(already_created_book_by_submitter.id) }.not_to raise_error
expect { Book.find(already_created_book_by_another_submitter.id) }.not_to raise_error

expect do
delete :destroy, params: { id: already_created_book_by_submitter.id }
end.to change(Book, :count).by(-1)
expect do
delete :destroy, params: { id: already_created_book_by_another_submitter.id }
end.to change(Book, :count).by(-1)

expect do
Book.find(already_created_book_by_submitter.id)
end.to raise_error(ActiveRecord::RecordNotFound)
expect do
Book.find(already_created_book_by_another_submitter.id)
end.to raise_error(ActiveRecord::RecordNotFound)
end

it 'redirects to the publications_path' do
delete :destroy, params: { id: already_created_book_by_submitter.id }
expect(response).to redirect_to(publications_path)
end

it 'displays a success flash notice' do
delete :destroy, params: { id: already_created_book_by_submitter.id }
expect(flash[:warning]).to eql 'Book was successfully destroyed.'
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# frozen_string_literal: true

# The PublicationsController is responsible for handling the requests for all
# publications. Each model inherits its CRUD actions from this controller.
# We do not actually have a Publications model, so for testing purposes
# we will use the Book model, which is a child of the Publication model.
#
require 'rails_helper'

# We are calling BooksController, a "child" of PublicationsController, so we
# need to define it here.
RSpec.describe BooksController, type: :controller do
let(:submitter) { FactoryBot.create(:submitter) }
let(:another_submitter) { FactoryBot.create(:submitter) }

let(:submitter_id) { submitter.id.to_s }
let(:another_submitter_id) { another_submitter.id.to_s }

let(:valid_attributes) do
{ 'author_first_name' => %w[Test Person],
'author_last_name' => %w[Case 2],
'college_ids' => ['', '1', '2'],
'uc_department' => 'Dept',
'work_title' => 'WT',
'other_title' => 'OT',
'publisher' => 'Pub',
'city' => 'City',
'publication_date' => 'Today',
'url' => 'www.fake.com',
'doi' => 'doi:' }
end

let(:already_created_book_by_submitter) { FactoryBot.create(:book, valid_attributes.merge(submitter_id:)) }
let(:already_created_book_by_another_submitter) { FactoryBot.create(:book, valid_attributes.merge(submitter_id: another_submitter_id)) }

# We have some custom behavior for the index action. Firstly, it redirects
# the user to the publications path. Then it calls a series of partials
# that are indexes of each of the publication types.
describe 'GET #index' do
before do
already_created_book_by_submitter
already_created_book_by_another_submitter
end

context 'when a user is logged in as an admin' do
before do
login_as_admin_unit_test
get :index
end

it 'assigns all books to @books' do
expect(assigns(:books)).to include(already_created_book_by_submitter)
expect(assigns(:books)).to include(already_created_book_by_another_submitter)
end

it 'redirects to publications path' do
expect(response).to redirect_to(publications_path)
end
end

context 'when a user is logged in as a submitter' do
before do
login_as_submitter_of(already_created_book_by_submitter)
get :index
end

it 'assigns only the submitter\'s books to @books' do
expect(assigns(:books)).to eq([already_created_book_by_submitter])
expect(assigns(:books)).not_to include(already_created_book_by_another_submitter)
end

it 'redirects to publications path' do
expect(response).to redirect_to(publications_path)
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

# The PublicationsController is responsible for handling the requests for all
# publications. Each model inherits its CRUD actions from this controller.
# We do not actually have a Publications model, so for testing purposes
# we will use the Book model, which is a child of the Publication model.
#
require 'rails_helper'

# We are calling BooksController, a "child" of PublicationsController, so we
# need to define it here.
RSpec.describe BooksController, type: :controller do
let(:submitter) { FactoryBot.create(:submitter) }
let(:another_submitter) { FactoryBot.create(:submitter) }
let(:book) { FactoryBot.create(:book, submitter_id: submitter.id.to_s) }
let(:another_book) { FactoryBot.create(:book, submitter_id: another_submitter.id.to_s) }

before do
book
end

describe 'GET #show' do
context 'as an admin user' do
before do
session[:admin] = true
get :show, params: { id: book.id }
end

it 'sets @submitter correctly' do
expect(assigns(:submitter).id.to_s).to eq(book.submitter_id)
end

it 'renders the show template' do
expect(response).to render_template(:show)
end

context 'when the book does not exist' do
before do
session[:admin] = true
end

it 'responds with a 404 not found' do
expect { get :show, params: { id: 'nonexistent' } }.to raise_error(ActiveRecord::RecordNotFound)
end
end
end

context 'as a submitter' do
before do
session[:admin] = nil
book
login_as_submitter_of(book)
end

context 'who owns the book' do
it 'does not set @submitter' do
get :show, params: { id: book.id }
expect(assigns(:submitter)).to be_nil
end

it 'renders the show template' do
get :show, params: { id: book.id }
expect(response).to render_template(:show)
end
end

context 'who does not own the book' do
it 'raises a 404 not found error and does not set submitter' do
expect { get :show, params: { id: another_book.id } }.to raise_error(ActiveRecord::RecordNotFound)
expect(assigns(:submitter)).to be_nil
end
end
end
end
end
Loading