otwarchive-symphonyarchive/spec/controllers/collection_items_controller_spec.rb
2026-03-11 22:22:11 +00:00

635 lines
26 KiB
Ruby

require "spec_helper"
describe CollectionItemsController do
include LoginMacros
include RedirectExpectationHelper
let(:user) { create(:user) }
let(:collection) { create(:collection) }
describe "GET #index" do
let(:pseud) { user.default_pseud }
let(:rejected_by_collection_work) { create(:work, authors: [pseud]) }
let(:rejected_by_user_work) { create(:work, authors: [pseud]) }
let(:approved_work) { create(:work, authors: [pseud]) }
let(:unreviewed_by_user_work) { create(:work, authors: [pseud]) }
let(:unreviewed_by_collection_work) { create(:work, authors: [pseud]) }
let!(:rejected_by_collection_work_item) { collection.collection_items.create(item: rejected_by_collection_work) }
let!(:rejected_by_user_work_item) { collection.collection_items.create(item: rejected_by_user_work) }
let!(:approved_work_item) { collection.collection_items.create(item: approved_work) }
let!(:unreviewed_by_user_work_item) { collection.collection_items.create(item: unreviewed_by_user_work) }
let!(:unreviewed_by_collection_work_item) { collection.collection_items.create(item: unreviewed_by_collection_work) }
before do
rejected_by_collection_work_item.rejected_by_collection!
rejected_by_user_work_item.rejected_by_user!
unreviewed_by_user_work_item.unreviewed_by_user!
unreviewed_by_collection_work_item.unreviewed_by_collection!
end
context "with collection params" do
context "when the user is not a maintainer" do
it "redirects and shows an error message" do
fake_login_known_user(user)
get :index, params: { collection_id: collection.id }
it_redirects_to_with_error(collections_path, "You don't have permission to see that, sorry!")
end
end
context "with no additional params" do
let(:owner) { collection.owners.first.user }
it "includes items awaiting collection approval" do
fake_login_known_user(owner)
get :index, params: { collection_id: collection.name }
expect(response).to have_http_status(:success)
expect(assigns(:collection_items)).to include unreviewed_by_collection_work_item
end
it "excludes items that are invited, approved by both parties, or rejected by the collection or user" do
fake_login_known_user(owner)
get :index, params: { collection_id: collection.name }
expect(assigns(:collection_items)).not_to include unreviewed_by_user_work_item
expect(assigns(:collection_items)).not_to include approved_work_item
expect(assigns(:collection_items)).not_to include rejected_by_collection_work_item
expect(assigns(:collection_items)).not_to include rejected_by_user_work_item
end
end
context "with params[:status] = \"rejected_by_collection\"" do
let(:owner) { collection.owners.first.user }
it "includes items rejected by the collection" do
fake_login_known_user(owner)
get :index, params: { collection_id: collection.name, status: "rejected_by_collection" }
expect(response).to have_http_status(:success)
expect(assigns(:collection_items)).to include rejected_by_collection_work_item
end
it "excludes items that are invited, approved by both parties, rejected by the user, or awaiting approval from collection" do
fake_login_known_user(owner)
get :index, params: { collection_id: collection.name, status: "rejected_by_collection" }
expect(assigns(:collection_items)).not_to include approved_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_user_work_item
expect(assigns(:collection_items)).not_to include rejected_by_user_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_collection_work_item
end
end
context "with params[:status] = \"rejected_by_user\"" do
let(:owner) { collection.owners.first.user }
it "includes items rejected by the user" do
fake_login_known_user(owner)
get :index, params: { collection_id: collection.name, status: "rejected_by_user" }
expect(response).to have_http_status(:success)
expect(assigns(:collection_items)).to include rejected_by_user_work_item
end
it "excludes items that are invited, approved by both parties, rejected by the collection, or awaiting approval from collection" do
fake_login_known_user(owner)
get :index, params: { collection_id: collection.name, status: "rejected_by_user" }
expect(assigns(:collection_items)).not_to include approved_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_user_work_item
expect(assigns(:collection_items)).not_to include rejected_by_collection_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_collection_work_item
end
end
context "with params[:status] = \"unreviewed_by_user\"" do
let(:owner) { collection.owners.first.user }
it "includes invited items" do
fake_login_known_user(owner)
get :index, params: { collection_id: collection.name, status: "unreviewed_by_user" }
expect(response).to have_http_status(:success)
expect(assigns(:collection_items)).to include unreviewed_by_user_work_item
end
it "excludes items that are approved, rejected by the collection or user, or awaiting approval from collection" do
fake_login_known_user(owner)
get :index, params: { collection_id: collection.name, status: "unreviewed_by_user" }
expect(assigns(:collection_items)).not_to include approved_work_item
expect(assigns(:collection_items)).not_to include rejected_by_collection_work_item
expect(assigns(:collection_items)).not_to include rejected_by_user_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_collection_work_item
end
end
context "with params[:status] = \"approved\"" do
let(:owner) { collection.owners.first.user }
it "includes approved items" do
fake_login_known_user(owner)
get :index, params: { collection_id: collection.name, status: "approved" }
expect(response).to have_http_status(:success)
expect(assigns(:collection_items)).to include approved_work_item
end
it "excludes items that are invited, rejected by the collection or user, or awaiting approval from collection" do
fake_login_known_user(owner)
get :index, params: { collection_id: collection.name, status: "approved" }
expect(assigns(:collection_items)).not_to include unreviewed_by_user_work_item
expect(assigns(:collection_items)).not_to include rejected_by_collection_work_item
expect(assigns(:collection_items)).not_to include rejected_by_user_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_collection_work_item
end
end
context "with other params" do
let(:owner) { collection.owners.first.user }
it "includes items awaiting collection approval" do
fake_login_known_user(owner)
get :index, params: { collection_id: collection.name, fake: true }
expect(response).to have_http_status(:success)
expect(assigns(:collection_items)).to include unreviewed_by_collection_work_item
end
it "excludes items that are invited, approved by both parties, or rejected by the collection or user" do
fake_login_known_user(owner)
get :index, params: { collection_id: collection.name, fake: true }
expect(assigns(:collection_items)).not_to include unreviewed_by_user_work_item
expect(assigns(:collection_items)).not_to include approved_work_item
expect(assigns(:collection_items)).not_to include rejected_by_collection_work_item
expect(assigns(:collection_items)).not_to include rejected_by_user_work_item
end
end
end
context "with user params" do
context "with no additional params" do
it "includes invited items" do
fake_login_known_user(user)
get :index, params: { user_id: user.login }
expect(response).to have_http_status(:success)
expect(assigns(:collection_items)).to include unreviewed_by_user_work_item
end
it "excludes items that are approved by both parties, rejected by the collection or user, or awaiting approval from collection" do
fake_login_known_user(user)
get :index, params: { user_id: user.login }
expect(assigns(:collection_items)).not_to include approved_work_item
expect(assigns(:collection_items)).not_to include rejected_by_collection_work_item
expect(assigns(:collection_items)).not_to include rejected_by_user_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_collection_work_item
end
end
context "with params[:status] = \"unreviewed_by_collection\"" do
it "includes items awaiting collection approval" do
fake_login_known_user(user)
get :index, params: { user_id: user.login, status: "unreviewed_by_collection" }
expect(response).to have_http_status(:success)
expect(assigns(:collection_items)).to include unreviewed_by_collection_work_item
end
it "excludes items that are invited, approved by both parties, or rejected by the collection or user" do
fake_login_known_user(user)
get :index, params: { user_id: user.login, status: "unreviewed_by_collection" }
expect(assigns(:collection_items)).not_to include unreviewed_by_user_work_item
expect(assigns(:collection_items)).not_to include approved_work_item
expect(assigns(:collection_items)).not_to include rejected_by_collection_work_item
expect(assigns(:collection_items)).not_to include rejected_by_user_work_item
end
end
context "with params[:status] = \"rejected_by_collection\"" do
it "includes items rejected by the collection" do
fake_login_known_user(user)
get :index, params: { user_id: user.login, status: "rejected_by_collection" }
expect(response).to have_http_status(:success)
expect(assigns(:collection_items)).to include rejected_by_collection_work_item
end
it "excludes items that are invited, approved by both parties, rejected by the user, or awaiting approval from collection" do
fake_login_known_user(user)
get :index, params: { user_id: user.login, status: "rejected_by_collection" }
expect(assigns(:collection_items)).not_to include approved_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_user_work_item
expect(assigns(:collection_items)).not_to include rejected_by_user_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_collection_work_item
end
end
context "with params[:status] = \"rejected_by_user\"" do
it "includes items rejected by the user" do
fake_login_known_user(user)
get :index, params: { user_id: user.login, status: "rejected_by_user" }
expect(response).to have_http_status(:success)
expect(assigns(:collection_items)).to include rejected_by_user_work_item
end
it "excludes items that are invited, approved by both parties, rejected by the collection, or awaiting approval from collection" do
fake_login_known_user(user)
get :index, params: { user_id: user.login, status: "rejected_by_user" }
expect(assigns(:collection_items)).not_to include approved_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_user_work_item
expect(assigns(:collection_items)).not_to include rejected_by_collection_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_collection_work_item
end
end
context "with params[:status] = \"approved\"" do
it "includes approved items" do
fake_login_known_user(user)
get :index, params: { user_id: user.login, status: "approved" }
expect(response).to have_http_status(:success)
expect(assigns(:collection_items)).to include approved_work_item
end
it "excludes items that are invited, rejected by the collection or user, or awaiting approval from collection" do
fake_login_known_user(user)
get :index, params: { user_id: user.login, status: "approved" }
expect(assigns(:collection_items)).not_to include unreviewed_by_user_work_item
expect(assigns(:collection_items)).not_to include rejected_by_collection_work_item
expect(assigns(:collection_items)).not_to include rejected_by_user_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_collection_work_item
end
end
context "with other params" do
it "includes invited items" do
fake_login_known_user(user)
get :index, params: { user_id: user.login, fake: true }
expect(response).to have_http_status(:success)
expect(assigns(:collection_items)).to include unreviewed_by_user_work_item
end
it "excludes items that are approved by both parties, rejected by the collection or user, or awaiting approval from collection" do
fake_login_known_user(user)
get :index, params: { user_id: user.login, fake: true }
expect(assigns(:collection_items)).not_to include approved_work_item
expect(assigns(:collection_items)).not_to include rejected_by_collection_work_item
expect(assigns(:collection_items)).not_to include rejected_by_user_work_item
expect(assigns(:collection_items)).not_to include unreviewed_by_collection_work_item
end
end
end
end
describe "GET #new" do
context "denies access for work that isn't visible to user" do
subject { get :new, params: { work_id: work.id } }
let(:work) { create(:work) }
let(:success) { expect(response).to render_template("new") }
let(:redirects_to_login) do
it_redirects_to_with_error(
new_user_session_path,
"Sorry, you don't have permission to access the page you were trying to reach. Please log in."
)
end
let(:success_admin) { redirects_to_login }
include_examples "denies access for work that isn't visible to user"
it "redirects to login if logged out" do
subject
redirects_to_login
end
end
end
describe "POST #create" do
context "creation" do
let(:collection) { FactoryBot.create(:collection) }
it "fails if collection names missing" do
post :create, params: { collection_id: collection.id }
it_redirects_to_with_error(root_path, "What collections did you want to add?")
end
it "fails if items missing" do
post :create, params: { collection_names: collection.name, collection_id: collection.id }
it_redirects_to_with_error(root_path, "What did you want to add to a collection?")
end
end
context "when logged in as the collection maintainer" do
before { fake_login_known_user(collection.owners.first.user) }
context "when the item is a work" do
let(:work) { create(:work) }
let(:params) do
{
collection_names: collection.name,
work_id: work.id
}
end
context "when the creator does not allow invitations" do
it "does not create an invitation" do
post :create, params: params
it_redirects_to_with_error(work, "This item could not be invited.")
expect(work.reload.collections).to be_empty
end
end
context "when the creator allows invitations" do
before do
work.users.each { |user| user.preference.update!(allow_collection_invitation: true) }
end
it "creates an invitation" do
post :create, params: params
it_redirects_to_simple(work)
expect(work.reload.collections).to include(collection)
end
end
end
end
context "as an archivist" do
let(:archivist) { create(:archivist) }
let(:work) { create(:work) }
let(:collection) do
create(:collection, owner: archivist.default_pseud)
end
let(:params) do
{
collection_names: collection.name,
work_id: work.id
}
end
before do
fake_login_known_user(archivist)
end
context "when the item's creator does not allow collection invitations" do
it "adds the item anyway" do
post :create, params: params
it_redirects_to_with_notice(work, "Added to collection(s): #{collection.title}.")
expect(work.reload.collections).to include(collection)
end
end
context "when the item's creator allows collection invitations" do
it "adds the item" do
post :create, params: params
it_redirects_to_with_notice(work, "Added to collection(s): #{collection.title}.")
expect(work.reload.collections).to include(collection)
end
end
end
end
describe "PATCH #update_multiple" do
let(:collection) { create(:collection) }
let(:work) { create(:work) }
let(:item) { create(:collection_item, collection: collection, item: work) }
let(:attributes) { { remove: "1" } }
describe "on the user collection items page for the work's owner" do
let(:work_owner) { work.pseuds.first.user }
let(:params) do
{
user_id: work_owner.login,
collection_items: {
item.id => attributes
}
}
end
context "when logged out" do
before { fake_logout }
it "errors and redirects" do
patch :update_multiple, params: params
it_redirects_to_with_error(work_owner, "You don't have permission to do that, sorry!")
end
end
context "when logged in as a random user" do
before { fake_login }
it "errors and redirects" do
patch :update_multiple, params: params
it_redirects_to_with_error(work_owner, "You don't have permission to do that, sorry!")
end
end
context "when logged in as the collection owner" do
before { fake_login_known_user(collection.owners.first.user) }
it "errors and redirects" do
patch :update_multiple, params: params
it_redirects_to_with_error(work_owner, "You don't have permission to do that, sorry!")
end
end
context "when logged in as the work's owner" do
before { fake_login_known_user(work_owner) }
context "setting user_approval_status" do
let(:attributes) { { user_approval_status: "rejected" } }
it "updates the collection item and redirects" do
patch :update_multiple, params: params
expect(item.reload.user_approval_status).to eq("rejected")
it_redirects_to_with_notice(user_collection_items_path(work_owner),
"Collection status updated!")
end
end
context "setting remove" do
let(:attributes) { { remove: "1" } }
it "deletes approved collection item and redirects" do
patch :update_multiple, params: params
expect { item.reload }.to \
raise_exception(ActiveRecord::RecordNotFound)
it_redirects_to_with_notice(user_collection_items_path(work_owner),
"Collection status updated!")
end
it "deletes item rejected by user and redirects" do
item.rejected_by_user!
patch :update_multiple, params: params
expect { item.reload }.to \
raise_exception(ActiveRecord::RecordNotFound)
it_redirects_to_with_notice(user_collection_items_path(work_owner),
"Collection status updated!")
end
it "deletes item rejected by collection and redirects" do
item.rejected_by_collection!
patch :update_multiple, params: params
expect { item.reload }.to \
raise_exception(ActiveRecord::RecordNotFound)
it_redirects_to_with_notice(user_collection_items_path(work_owner),
"Collection status updated!")
end
end
{
collection_approval_status: "rejected",
unrevealed: true,
anonymous: true
}.each_pair do |field, value|
context "setting #{field}" do
let(:attributes) { { field => value } }
it "throws an error and doesn't update" do
expect do
patch :update_multiple, params: params
end.to raise_exception(ActionController::UnpermittedParameters)
expect(item.reload.send(field)).not_to eq(value)
end
end
end
end
end
describe "on the collection items page for the work's collection" do
let(:params) do
{
collection_id: collection.name,
collection_items: {
item.id => attributes
}
}
end
context "when logged out" do
before { fake_logout }
it "errors and redirects" do
patch :update_multiple, params: params
it_redirects_to_with_error(collection, "You don't have permission to do that, sorry!")
end
end
context "when logged in as a random user" do
before { fake_login }
it "errors and redirects" do
patch :update_multiple, params: params
it_redirects_to_with_error(collection, "You don't have permission to do that, sorry!")
end
end
context "when logged in as a maintainer" do
before { fake_login_known_user(collection.owners.first.user) }
{
collection_approval_status: "rejected",
unrevealed: true,
anonymous: true
}.each_pair do |field, value|
context "setting #{field}" do
let(:attributes) { { field => value } }
it "updates the collection item and redirects" do
patch :update_multiple, params: params
expect(item.reload.send(field)).to eq(value)
it_redirects_to_with_notice(collection_items_path(collection),
"Collection status updated!")
end
end
end
context "setting remove" do
let(:attributes) { { remove: "1" } }
it "deletes approved collection item and redirects" do
patch :update_multiple, params: params
expect { item.reload }.to \
raise_exception(ActiveRecord::RecordNotFound)
it_redirects_to_with_notice(collection_items_path(collection),
"Collection status updated!")
end
context "when item is rejected by user" do
context "when maintainer is not collectible's creator" do
before { item.rejected_by_user! }
it "silently fails to delete item" do
patch :update_multiple, params: params
expect(collection.collection_items).to include item
it_redirects_to_with_notice(collection_items_path(collection),
"Collection status updated!")
end
end
context "when maintainer is also collectible's creator" do
let(:work) { create(:work, authors: [collection.owners.first]) }
before { item.rejected_by_user! }
it "deletes item and redirects" do
patch :update_multiple, params: params
expect { item.reload }.to \
raise_exception(ActiveRecord::RecordNotFound)
it_redirects_to_with_notice(collection_items_path(collection),
"Collection status updated!")
end
end
end
end
context "setting user_approval_status" do
let(:attributes) { { user_approval_status: "rejected" } }
it "throws an error and doesn't update" do
expect do
patch :update_multiple, params: params
end.to raise_exception(ActionController::UnpermittedParameters)
expect(item.reload.user_approval_status).not_to eq("rejected")
end
end
end
end
describe "on the collection items page for a different user" do
let(:user) { create(:user) }
let(:params) do
{
user_id: user.login,
collection_items: {
item.id => { user_approval_status: "rejected" }
}
}
end
before { fake_login_known_user(user) }
it "silently fails to update the collection item" do
patch :update_multiple, params: params
expect(item.reload.user_approval_status).not_to eq("rejected")
it_redirects_to_with_notice(user_collection_items_path(user),
"Collection status updated!")
end
end
describe "on the collection items page for a different collection" do
let(:other_collection) { create(:collection) }
let(:params) do
{
collection_id: other_collection.name,
collection_items: {
item.id => { collection_approval_status: "rejected" }
}
}
end
before { fake_login_known_user(other_collection.owners.first.user) }
it "silently fails to update the collection item" do
patch :update_multiple, params: params
expect(item.reload.collection_approval_status).not_to eq("rejected")
it_redirects_to_with_notice(collection_items_path(other_collection),
"Collection status updated!")
end
end
end
end