require "spec_helper" describe ChallengeAssignmentsController do include LoginMacros include RedirectExpectationHelper let(:gift_exchange) { create(:gift_exchange) } let(:collection) { create(:collection, challenge: gift_exchange) } let(:assignment) do create(:challenge_assignment, collection_id: collection.id, sent_at: gift_exchange.assignments_sent_at) end let(:assignment_owner) { assignment.offering_user } let(:collection_owner) { collection.owners.first.user } let(:other_user) { create(:user) } before { fake_login_known_user(user) } describe "default" do let(:gift_exchange) { create(:gift_exchange, assignments_sent_at: Faker::Time.backward) } context "when logged in as the owner of the collection" do let(:user) { collection_owner } it "doesn't default the assignment, and redirects with an error" do get :default, params: { collection_id: collection.name, id: assignment.id } it_redirects_to_with_error(root_path, "You aren't the owner of that assignment.") expect(assignment.reload.defaulted_at).to be_nil end end context "when logged in as the owner of the assignment" do let(:user) { assignment_owner } it "defaults and redirects to the current user's assignments path" do get :default, params: { collection_id: collection.name, id: assignment.id } it_redirects_to_with_notice(user_assignments_path(user), "We have notified the collection maintainers that you had to default on your assignment.") expect(assignment.reload.defaulted_at).not_to be_nil end context "when assignments have not been sent" do let(:gift_exchange) { create(:gift_exchange, assignments_sent_at: nil) } it "doesn't default the assignment, and redirects with an error" do get :default, params: { collection_id: collection.name, id: assignment.id } it_redirects_to_with_error(collection_path(collection), "Assignments have not been sent! You might want matching instead.") expect(assignment.reload.defaulted_at).to be_nil end end context "when the assignment doesn't exist" do it "causes a 404 error" do expect do get :default, params: { collection_id: collection.name, id: -1 } end.to raise_exception(ActiveRecord::RecordNotFound) end end context "when the assignment is from another collection" do let(:other_assignment) { create(:challenge_assignment) } it "causes a 404 error" do expect do get :default, params: { collection_id: collection.name, id: other_assignment.id } end.to raise_exception(ActiveRecord::RecordNotFound) end end context "when the collection doesn't exist" do it "redirects with an error" do get :default, params: { collection_id: "--MISSING--", id: assignment.id } it_redirects_to_with_error(root_path, "What challenge did you want to work with?") end end context "when the collection is not a challenge" do let(:collection) { create(:collection) } it "redirects with an error" do get :default, params: { collection_id: collection.name, id: assignment.id } it_redirects_to_with_error(collection_path(collection), "What challenge did you want to work with?") end end end context "when logged in as a random user" do let(:user) { other_user } it "doesn't default the assignment, and redirects with an error" do get :default, params: { collection_id: collection.name, id: assignment.id } it_redirects_to_with_error(root_path, "You aren't the owner of that assignment.") expect(assignment.reload.defaulted_at).to be_nil end end end describe "set" do let(:signup1) { create(:challenge_signup, collection: assignment.collection) } let(:signup2) { create(:challenge_signup, collection: assignment.collection) } let(:params) do { collection_id: collection.name, challenge_assignments: { assignment.id => { request_signup_pseud: signup1.pseud.byline, offer_signup_pseud: signup2.pseud.byline } } } end context "when logged in as the collection maintainer" do let(:user) { collection_owner } it "successfully updates the assignment" do PotentialMatch.create(request_signup: signup1, offer_signup: signup2, collection: collection) put :set, params: params expect { assignment.reload }.to \ change { assignment.request_signup_id }.to(signup1.id).and \ change { assignment.offer_signup_id }.to(signup2.id) it_redirects_to_with_notice(collection_potential_matches_path(collection), "Assignments updated") end context "when there is no potential match" do it "doesn't update the assignment, and renders the potential matches index" do put :set, params: params expect { assignment.reload }.not_to \ change { [assignment.request_signup_id, assignment.offer_signup_id] } expect(flash[:error]).to eq("These assignments could not be saved because the two participants do not match. Did you mean to write in a giver?") expect(assigns[:assignments]).to include(assignment) expect(response).to render_template("potential_matches/index") end end context "when assignments have been sent" do let(:gift_exchange) { create(:gift_exchange, assignments_sent_at: Faker::Time.backward) } it "doesn't update the assignment, and redirects with an error" do put :set, params: params expect { assignment.reload }.not_to \ change { [assignment.request_signup_id, assignment.offer_signup_id] } it_redirects_to_with_error(collection_assignments_path(collection), "Assignments have already been sent! If necessary, you can purge them.") end end context "when the assignment is from another collection" do let(:other_collection) { create(:collection, challenge: create(:gift_exchange)) } let(:assignment) do create(:challenge_assignment, collection: other_collection, sent_at: Faker::Time.backward) end it "silently ignores the assignment" do put :set, params: params expect { assignment.reload }.not_to \ change { [assignment.request_signup_id, assignment.offer_signup_id] } it_redirects_to_with_notice(collection_potential_matches_path(collection), "Assignments updated") end end end context "when logged in as a random user" do let(:user) { other_user } it "doesn't update the assignment, and redirects with an error" do put :set, params: params expect { assignment.reload }.not_to \ change { [assignment.request_signup_id, assignment.offer_signup_id] } it_redirects_to_with_error(user_path(user), "Sorry, you don't have permission to access the page you were trying to reach.") end end end describe "update_multiple" do let(:gift_exchange) { create(:gift_exchange, assignments_sent_at: Faker::Time.backward) } context "when logged in as the collection maintainer" do let(:user) { collection_owner } context "defaulting" do let(:params) do { collection_id: collection.name, "default_#{assignment.id}" => true } end it "marks the assignment as defaulted" do put :update_multiple, params: params it_redirects_to_with_notice(collection_assignments_path(collection), "Assignment updates complete!") assignment.reload expect(assignment.defaulted_at).not_to be_nil end context "when the assignment is from another collection" do let(:other_collection) { create(:collection, challenge: create(:gift_exchange)) } let(:assignment) do create(:challenge_assignment, collection: other_collection, sent_at: Faker::Time.backward) end it "doesn't mark the assignment as defaulted, and redirects with an error" do put :update_multiple, params: params it_redirects_to_with_error(collection_assignments_path(collection), ["Couldn't find assignment with id #{assignment.id}!"]) assignment.reload expect(assignment.defaulted_at).to be_nil end end end context "undefaulting" do let(:params) do { collection_id: collection.name, "undefault_#{assignment.id}" => true } end before { assignment.update!(defaulted_at: Faker::Time.backward) } it "marks the assignment as undefaulted" do put :update_multiple, params: params it_redirects_to_with_notice(collection_assignments_path(collection), "Assignment updates complete!") assignment.reload expect(assignment.defaulted_at).to be_nil end end context "approving" do let(:params) do { collection_id: collection.name, "approve_#{assignment.id}" => true } end let(:work) do create(:work, challenge_assignments: [assignment], collections: [collection]) end let(:collection_item) { work.collection_items.find_by(collection: collection) } before do collection_item.update!(collection_approval_status: CollectionItem::NEUTRAL) end it "marks the collection item as approved", pending: "AO3-6106" do put :update_multiple, params: params it_redirects_to_with_notice(collection_assignments_path(collection), "Assignment updates complete!") collection_item.reload expect(collection_item.collection_approval_status).to eq(CollectionItem::APPROVED) end end context "covering" do let(:pinch_hitter) { create(:pseud) } let(:params) do { collection_id: collection.name, "cover_#{assignment.id}" => pinch_hitter.byline } end before { assignment.update!(defaulted_at: Faker::Time.backward) } it "marks the assignment as undefaulted" do expect do put :update_multiple, params: params end.to change { ChallengeAssignment.count }.by(1) it_redirects_to_with_notice(collection_assignments_path(collection), "Assignment updates complete!") assignment.reload expect(assignment.covered_at).not_to be_nil expect(collection.assignments.find_by(pinch_hitter: pinch_hitter)).not_to be_nil end end end end describe "show" do shared_examples "allowed to see assignment" do it "shows the assignment" do get :show, params: { id: assignment.id, collection_id: collection.name } expect(response).to have_http_status(:success) expect(response).to render_template :show end context "when the assignment is defaulted" do before { assignment.update_attribute(:defaulted_at, Faker::Time.backward) } it "shows a message" do get :show, params: { id: assignment.id, collection_id: collection.name } expect(flash[:notice]).to eq("This assignment has been defaulted-on.") end end context "when the assignment is from a different collection" do let(:assignment) { create(:challenge_assignment) } it "causes a 404 error" do expect do get :show, params: { id: assignment.id, collection_id: collection.name } end.to raise_exception(ActiveRecord::RecordNotFound) end end end context "when logged in as the owner of the assignment" do let(:user) { assignment_owner } include_examples "allowed to see assignment" end context "when logged in as a moderator of the collection" do let(:user) { collection_owner } include_examples "allowed to see assignment" end context "when logged in as a random user" do let(:user) { other_user } it "doesn't show the assignment" do get :show, params: { id: assignment.id, collection_id: collection.name } it_redirects_to_with_error(root_path, "You aren't allowed to see that assignment!") end end end describe "index" do let(:gift_exchange) { create(:gift_exchange, assignments_sent_at: Faker::Time.backward) } let!(:open_assignment) do create(:challenge_assignment, collection_id: collection.id, sent_at: gift_exchange.assignments_sent_at) end let!(:defaulted_assignment) do create(:challenge_assignment, collection_id: collection.id, sent_at: gift_exchange.assignments_sent_at, defaulted_at: Faker::Time.backward) end context "when logged in as a maintainer of the collection", work_search: true, bookmark_search: true do render_views let(:user) { collection_owner } it "shows defaulted assignments within a collection" do get :index, params: { collection_id: collection.name } expect(response).to have_http_status(:success) expect(response.body).to include "Assignments for" expect(response.body).to include collection.title expect(response.body).to include defaulted_assignment.request_byline expect(response.body).not_to include "No assignments to review!" end it "shows unfulfilled assignments within a collection" do get :index, params: { collection_id: collection.name, unfulfilled: true } expect(response).to have_http_status(:success) expect(response.body).to include "Assignments for" expect(response.body).to include collection.title expect(response.body).to include open_assignment.request_byline expect(response.body).not_to include "No assignments to review!" end end context "when logged in as the owner of an open assignment" do let(:user) { open_assignment.offering_user } it "lists the assignment" do get :index, params: { collection_id: collection.name, user_id: user.login } expect(response).to have_http_status(:success) expect(assigns[:challenge_assignments]).to include(open_assignment) expect(assigns[:challenge_assignments]).not_to include(defaulted_assignment) expect(response).to render_template(:index) end end context "when logged in as the owner of a defaulted assignment" do let(:user) { defaulted_assignment.offering_user } it "doesn't list the assignment" do get :index, params: { collection_id: collection.name, user_id: user.login } expect(response).to have_http_status(:success) expect(assigns[:challenge_assignments]).not_to include(defaulted_assignment) expect(assigns[:challenge_assignments]).not_to include(open_assignment) expect(response).to render_template(:index) end end context "when logged in as a random user" do let(:user) { other_user } it "doesn't show any assignments" do get :index, params: { collection_id: collection.name, user_id: user.login } expect(response).to have_http_status(:success) expect(assigns[:challenge_assignments]).not_to include(defaulted_assignment) expect(assigns[:challenge_assignments]).not_to include(open_assignment) expect(response).to render_template(:index) end context "when trying to access another user's assignments" do it "redirects with an error" do get :index, params: { collection_id: collection.name, user_id: open_assignment.offering_user.login } it_redirects_to_with_error(root_path, "You aren't allowed to see that user's assignments.") end end context "when trying to access a non-existent user's assignments" do it "redirects with an error" do get :index, params: { collection_id: collection.name, user_id: "--MISSING--" } it_redirects_to_with_error(user_path(user), "Sorry, you don't have permission to access the page you were trying to reach.") end end end end end