# frozen_string_literal: true require "spec_helper" describe CollectionParticipantsController do include LoginMacros include RedirectExpectationHelper let(:user) { create(:user) } let(:collection) { create(:collection) } describe "join" do context "where user isn't logged in" do it "redirects to new user session with error" do get :join, params: { collection_id: collection.name } 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 end context "where the user is logged in" do before do fake_login_known_user(user) end context "where there is no collection" do it "raises a RecordNotFound error" do expect do get :join, params: { collection_id: 0 } end.to raise_exception(ActiveRecord::RecordNotFound) end end context "where there is a collection" do let(:current_role) { CollectionParticipant::NONE } context "where the user is already a participant" do let!(:participant) do create( :collection_participant, collection: collection, pseud: user.default_pseud, participant_role: current_role ) end context "where the user has been invited" do let(:current_role) { CollectionParticipant::INVITED } it "approves the participant and redirects to the index" do get :join, params: { collection_id: collection.name } expect(CollectionParticipant.find(participant.id).participant_role).to eq CollectionParticipant::MEMBER it_redirects_to_with_notice(root_path, "You are now a member of #{collection.title}.") end end context "where the user is not currently invited" do it "redirects to the index and displays a notice that the user has already joined or applied" do get :join, params: { collection_id: collection.name } it_redirects_to_with_notice(root_path, "You have already joined (or applied to) this collection.") end end end context "where user isn't a participant yet" do it "creates a participant for the user, redirects to index and notifies them that they have applied" do get :join, params: { collection_id: collection.name } participant = CollectionParticipant.find_by(pseud_id: user.default_pseud.id) expect(participant).to be_present expect(participant.participant_role).to eq CollectionParticipant::NONE it_redirects_to_with_notice(root_path, "You have applied to join #{collection.title}.") end end end end end describe "index" do let(:current_role) { CollectionParticipant::NONE } context "user is not logged in" do it "redirects to the index and displays an access denied message" do get :index, params: { collection_id: collection.name } 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 end context "user is logged in" do let!(:participant) do create( :collection_participant, collection: collection, pseud: user.default_pseud, participant_role: current_role ) end let(:params) { { collection_id: collection.name } } before do fake_login_known_user(user) end context "where the user is not a maintainer" do it "redirects to the index" do get :index, params: params 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 context "where the user is a maintainer", work_search: true, bookmark_search: true do render_views let(:current_role) { CollectionParticipant::MODERATOR } context "where the collection has several participants" do let!(:users) do Array.new(3) do user = create(:user) create( :collection_participant, collection: collection, pseud: user.default_pseud ) user end end it "displays the participants" do get :index, params: params expect(response).to have_http_status(:success) users.each do |user| expect(response.body).to include user.default_pseud.name end end end end end end describe "update" do let(:user_role) { CollectionParticipant::NONE } let!(:user_participant) do create( :collection_participant, pseud: user.default_pseud, collection: collection, participant_role: user_role ) end let(:id_to_update) { "" } let(:params) do { id: id_to_update, collection_id: collection.name, collection_participant: { participant_role: CollectionParticipant::MEMBER } } end before do fake_login_known_user(user) end context "where there is no participant" do it "raises a RecordNotFound error" do expect do put :update, params: params end.to raise_exception(ActiveRecord::RecordNotFound) end end context "where there is a participant" do let(:participant) do create( :collection_participant, collection: user_participant.collection, participant_role: CollectionParticipant::NONE ) end let(:id_to_update) { participant.id } context "where the user is not a collection maintainer" do it "redirects to the collection page and displays an error" do put :update, params: params it_redirects_to_with_error(collection_path(collection), "Sorry, you're not allowed to do that.") end end context "when the participant is from another collection" do let(:id_to_update) { create(:collection_participant).id } it "raises a RecordNotFound error" do expect do put :update, params: params end.to raise_exception(ActiveRecord::RecordNotFound) end end context "where the user is a collection maintainer" do let(:user_role) { CollectionParticipant::MODERATOR } context "where the participant is updated successfully" do it "successfully updates and redirects to collection participants" do put :update, params: params it_redirects_to_with_notice(collection_participants_path(collection), "Updated #{participant.pseud.name}.") end end context "where the participant is not updated successfully" do before do allow_any_instance_of(CollectionParticipant).to receive(:update).and_return(false) end it "displays an error notice and and redirects to collection participants" do put :update, params: params it_redirects_to_with_error(collection_participants_path(collection), "Couldn't update #{participant.pseud.name}.") end end end end end describe "destroy" do let(:pseud_name) { user.default_pseud.name } let(:user_participant_role) { CollectionParticipant::MEMBER } let!(:user_participant) do create( :collection_participant, pseud: user.default_pseud, collection: collection, participant_role: user_participant_role ) end let(:params) do { id: user_participant.id, collection_id: collection.name } end before do fake_login_known_user(user) end context "where there is no participant" do let(:params) { { id: 0, collection_id: collection.name } } it "raises a RecordNotFound error" do expect do delete :destroy, params: params end.to raise_exception(ActiveRecord::RecordNotFound) end end context "where there is a participant found" do context "where user is not a maintainer" do context "where the user is destroying their own participant" do it "destroys the participant successfully and redirects to index" do delete :destroy, params: params it_redirects_to_with_notice(root_path, "Removed #{pseud_name} from collection.") expect(CollectionParticipant.find_by(pseud_id: user.default_pseud.id)).to_not be_present end end context "when the participant is from another collection" do it "raises a RecordNotFound error" do expect do put :update, params: { id: create(:collection_participant).id, collection_id: collection.name } end.to raise_exception(ActiveRecord::RecordNotFound) end end context "where the user is trying to destroy another participant" do let(:other_participant) do create( :collection_participant, collection: collection, participant_role: CollectionParticipant::MEMBER ) end let(:pseud_name) { other_participant.pseud.name } let(:params) { { id: other_participant.id, collection_id: collection.name } } it "doesn't allow the destroy and redirects to the collection page" do delete :destroy, params: params it_redirects_to_with_error(collection_path(collection), "Sorry, you're not allowed to do that.") expect(CollectionParticipant.find(other_participant.id)).to be_present end end end context "where user is a maintainer" do let(:user_participant_role) { CollectionParticipant::MODERATOR } let(:other_participant) do create( :collection_participant, collection: collection, participant_role: CollectionParticipant::MEMBER ) end let(:pseud_name) { other_participant.pseud.name } let(:params) do { id: other_participant.id, collection_id: collection.name } end context "where participant to be destroyed is not an owner" do it "destroys the participant successfully and redirects to index" do delete :destroy, params: params it_redirects_to_with_notice(root_path, "Removed #{pseud_name} from collection.") expect(CollectionParticipant.find_by(pseud_id: other_participant.pseud_id)).to_not be_present end end context "where participant to be destroyed is an owner" do let(:delete_participant_id) { CollectionParticipant.find_by(pseud_id: collection.owners.first.id) } let(:params) { { id: delete_participant_id, collection_id: collection.name } } context "where there are no other owners" do it "displays an error and redirects to the collection participants path" do delete :destroy, params: params it_redirects_to_with_error(collection_participants_path(collection), "You can't remove the only owner!") expect(CollectionParticipant.find(delete_participant_id.id)).to be_present end end context "where there are other owners" do let!(:pseud_name) { CollectionParticipant.find(delete_participant_id.id).pseud.name } let!(:other_owner) do create( :collection_participant, collection: collection, participant_role: CollectionParticipant::OWNER ) end it "destroys the participant successfully and redirects to index" do delete :destroy, params: params it_redirects_to_with_notice(root_path, "Removed #{pseud_name} from collection.") expect(CollectionParticipant.where(id: delete_participant_id)).to be_empty end end end end end end describe "add" do let(:participants_to_invite) { "" } let!(:params) do { collection_id: collection.name, participants_to_invite: participants_to_invite } end let(:user_participant_role) { CollectionParticipant::MEMBER } let!(:user_participant) do create( :collection_participant, pseud: user.default_pseud, collection: collection, participant_role: user_participant_role ) end before do fake_login_known_user(user) end context "where the user is not a maintainer" do it "redirects and shows an error message" do get :add, params: params 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 context "where the user is a maintainer" do let(:user_participant_role) { CollectionParticipant:: MODERATOR } let(:banned) { false } let(:users) { Array.new(3) { create(:user, banned: banned) } } let(:participants_to_invite) do users.map(&:default_pseud).map(&:byline).map(&:to_s).join(",") end context "where users to be added have already applied to the collection" do let!(:participants) do users.each do |user| create( :collection_participant, collection: collection, pseud: user.default_pseud, participant_role: CollectionParticipant::NONE ) end end it "approves those users, redirects to the collection participants page and displays a notification" do get :add, params: params it_redirects_to_simple(collection_participants_path(collection)) expect(flash[:notice]).to include "Members added:" users.each do |user| expect(flash[:notice]).to include user.default_pseud.byline participant = CollectionParticipant.find_by(pseud_id: user.default_pseud.id) expect(participant.participant_role).to eq CollectionParticipant::MEMBER end end end context "where the users to be added haven't yet applied to the collection" do it "creates new participants with the member role and redirects" do get :add, params: params it_redirects_to_simple(collection_participants_path(collection)) expect(flash[:notice]).to include "New members invited:" users.each do |user| expect(flash[:notice]).to include user.default_pseud.byline participant = CollectionParticipant.find_by(pseud_id: user.default_pseud.id) expect(participant.participant_role).to eq CollectionParticipant::MEMBER end end end context "where users to be added are banned users" do let(:banned) { true } it "doesn't approve the member, displays an error and redirects" do get :add, params: params it_redirects_to_with_error(collection_participants_path(collection), "#{users.map(&:default_pseud).map(&:byline).to_sentence} cannot participate in challenges.") users.each do |user| expect(CollectionParticipant.where(pseud_id: user.default_pseud.id)).to be_empty end end end context "where users to be added can't be found" do let!(:pseud_ids) { users.map(&:default_pseud).map(&:id) } it "displays an error and redirects" do users.each do |user| user.default_pseud.destroy end get :add, params: params it_redirects_to_with_error(collection_participants_path(collection), "We couldn't find anyone new by that name to add.") pseud_ids.each do |pseud_id| expect(CollectionParticipant.where(pseud_id: pseud_id)).to be_empty end end end end end end