RSpec.describe OffersController, type: :controller do let(:organization) { Fabricate(:organization) } let(:member) { Fabricate(:member, organization: organization) } let(:another_member) { Fabricate(:member, organization: organization) } let(:yet_another_member) { Fabricate(:member) } let(:test_category) { Fabricate(:category) } let!(:offer) do Fabricate(:offer, user: member.user, organization: organization, category: test_category) end let!(:other_offer) do Fabricate(:offer, user: another_member.user, organization: organization, category: test_category) end describe "GET #index" do context "with a logged user" do before { login(another_member.user) } it "populates an array of offers" do get :index expect(assigns(:offers)).to eq([other_offer, offer]) end context "when one offer is not active" do before do other_offer.active = false other_offer.save! end it "only returns active offers" do get :index expect(assigns(:offers)).to eq([offer]) end end context "when one offer's user is not active" do before do member.active = false member.save! end it "only returns offers from active users" do get :index expect(assigns(:offers)).to eq([other_offer]) end end end context "with another organization" do it "skips the original org's offers" do login(yet_another_member.user) get :index expect(assigns(:offers)).to eq([]) end end end describe "GET #index (search)" do before do login(another_member.user) offer.title = "Queridos compañeros" offer.save! end it "populates an array of offers" do get :index, params: { q: 'compañeros' } expect(assigns(:offers)).to eq([offer]) end it "allows to search by partial word" do get :index, params: { q: 'compañ' } expect(assigns(:offers)).to eq([offer]) end it "applies organization filter if passed" do get :index, params: { q: offer.title, org: 2 } expect(assigns(:offers)).to eq([]) end context "when one offer is not active" do before do other_offer.active = false other_offer.save! end it "only returns active offers" do login(another_member.user) get :index expect(assigns(:offers)).to eq([offer]) end end context "when one offer's user is not active" do before do member.active = false member.save! end it "only returns offers from active users" do login(another_member.user) get :index expect(assigns(:offers)).to eq([other_offer]) end end end describe 'GET #show' do context 'when the user is logged in' do before { login(another_member.user) } context 'when the requested offer' do context 'is not active' do before do offer.active = false offer.save! end it 'renders the 404 page' do get :show, params: { id: offer.id } expect(response.status).to eq(404) end end context 'is active' do context 'and the user that created the offer is not active anymore' do before do member.active = false member.save! end it 'renders the 404 page' do get :show, params: { id: offer.id } expect(response.status).to eq(404) end end context 'and the user that created the offer is active' do it 'renders a successful response' do get :show, params: { id: offer.id } expect(response.status).to eq(200) end it 'assigns the requested offer to @offer' do get :show, params: { id: offer.id } expect(assigns(:offer)).to eq(offer) end it 'assigns the account destination of the transfer' do get :show, params: { id: offer.id } expect(assigns(:destination_account)).to eq(member.account) end end end end context 'when the user pertains to multiple organizations' do context 'and user\'s current organization is different than offer\'s organization' do let(:another_organization) { Fabricate(:organization) } before do Fabricate(:member, user: another_member.user, organization: another_organization) allow(controller).to receive(:@current_organization).and_return(another_organization) end it 'sets the offer\'s organization as user\'s current organization' do get :show, params: { id: offer.id } expect(session[:current_organization_id]).to eq(offer.organization_id) expect(assigns(:current_organization)).to eq(offer.organization) end end end end context 'when the user is not a member of the organization where the offer is published' do let(:another_user) { Fabricate(:user) } before { login(another_user) } end context 'when the user is not logged in' do it 'assigns the requested offer to @offer' do get :show, params: { id: offer.id } expect(assigns(:offer)).to eq(offer) end end end describe "POST #create" do context "with valid params" do context "with a logged user" do it "creates a new offer" do login(another_member.user) expect do post "create", params: { offer: { user: another_member.user, category_id: test_category, title: "New title" } } end.to change(Offer, :count).by(1) end end end end describe "PUT #update" do context "with valid params" do context "with a logged user" do it "located the requested @offer" do login(member.user) put "update", params: { id: offer.id, offer: Fabricate.to_params(:offer) } expect(assigns(:offer)).to eq(offer) end it "changes @offer's attributes" do login(member.user) put "update", params: { id: offer.id, offer: Fabricate.to_params(:offer, user: member, title: "New title", description: "New description", tag_list: ["foo"]) } offer.reload expect(offer.title).to eq("New title") expect(offer.description).to eq("New description") expect(offer.tags).to include("foo") end end end context "with invalid params" do context "with a logged user" do it "does not change @offer's attributes" do login(member.user) put :update, params: { id: offer.id, offer: Fabricate.to_params(:offer, user: nil, title: "New title", description: "New description") } expect(offer.title).not_to eq("New title") expect(offer.description).not_to eq("New description") end end end end describe "DELETE destroy" do it "toggle active field" do login(member.user) delete :destroy, params: { id: offer.id } offer.reload expect(offer.active).to be false end it "redirects to offers#index" do login(member.user) delete :destroy, params: { id: offer.id } expect(response).to redirect_to offers_url end end end