# frozen_string_literal: true require "rails_helper" describe InboxController, type: :controller do let(:user) { FactoryBot.create(:user) } describe "#show" do shared_examples_for "sets the expected ivars" do let(:expected_assigns) { {} } it "sets the expected ivars" do subject expected_assigns.each do |name, value| expect(assigns[name]).to eq(value) end end end subject { get :show } it "redirects to the login page when not signed in" do expect(subject).to redirect_to(new_user_session_path) end context "when user is signed in" do before(:each) { sign_in(user) } it "renders the correct template" do subject expect(response).to render_template("show") end context "when inbox is empty" do include_examples "sets the expected ivars", inbox: [], inbox_last_id: nil, more_data_available: false, inbox_count: 0, delete_id: "ib-delete-all", disabled: true end context "when inbox has an amount of questions less than page size" do let!(:inbox_entry) { Inbox.create(user:, new: true, question: FactoryBot.create(:question)) } include_examples "sets the expected ivars" do let(:expected_assigns) do { inbox: [inbox_entry], inbox_last_id: inbox_entry.id, more_data_available: false, inbox_count: 1, delete_id: "ib-delete-all", disabled: nil } end end it "updates the inbox entry status" do expect { subject }.to change { inbox_entry.reload.new? }.from(true).to(false) end context "when requested the turbo stream format" do subject { get :show, format: :turbo_stream } it "updates the inbox entry status" do expect { subject }.to change { inbox_entry.reload.new? }.from(true).to(false) end end end context "when inbox has an amount of questions more than page size" do let(:inbox_entry_fillers_page1) do # 9 times => 1 entry less than default page size 9.times.map { Inbox.create(user:, question: FactoryBot.create(:question)) } end let(:last_inbox_entry_page1) { Inbox.create(user:, question: FactoryBot.create(:question)) } let(:inbox_entry_fillers_page2) do 5.times.map { Inbox.create(user:, question: FactoryBot.create(:question)) } end let(:last_inbox_entry_page2) { Inbox.create(user:, question: FactoryBot.create(:question)) } before do # create inbox entries in reverse so pagination works as expected last_inbox_entry_page2 inbox_entry_fillers_page2 last_inbox_entry_page1 inbox_entry_fillers_page1 end include_examples "sets the expected ivars" do let(:expected_assigns) do { inbox: [*inbox_entry_fillers_page1.reverse, last_inbox_entry_page1], inbox_last_id: last_inbox_entry_page1.id, more_data_available: true, inbox_count: 16, delete_id: "ib-delete-all", disabled: nil } end end context "when passed the last_id param" do subject { get :show, params: { last_id: last_inbox_entry_page1.id } } include_examples "sets the expected ivars" do let(:expected_assigns) do { inbox: [*inbox_entry_fillers_page2.reverse, last_inbox_entry_page2], inbox_last_id: last_inbox_entry_page2.id, more_data_available: false, inbox_count: 16, delete_id: "ib-delete-all", disabled: nil } end end end end context "when passed the author param" do let!(:other_user) { FactoryBot.create(:user) } let!(:unrelated_user) { FactoryBot.create(:user) } let!(:generic_inbox_entry1) do Inbox.create( user:, question: FactoryBot.create( :question, user: unrelated_user, author_is_anonymous: false ) ) end let!(:generic_inbox_entry2) { Inbox.create(user:, question: FactoryBot.create(:question)) } subject { get :show, params: { author: author_param } } context "with a nonexisting screen name" do let(:author_param) { "xXx420MegaGamer2003xXx" } it "sets the error flash" do subject expect(flash[:error]).to eq "No user with the name @xXx420MegaGamer2003xXx found, showing entries from all users instead!" end include_examples "sets the expected ivars" do let(:expected_assigns) do { inbox: [generic_inbox_entry2, generic_inbox_entry1], inbox_last_id: generic_inbox_entry1.id, more_data_available: false, inbox_count: 2, delete_id: "ib-delete-all", disabled: nil } end end end context "with an existing screen name" do let(:author_param) { other_user.screen_name } context "with no questions from the other user in the inbox" do it { is_expected.to redirect_to inbox_path } it "sets the info flash" do subject expect(flash[:info]).to eq "No questions from @#{other_user.screen_name} found, showing entries from all users instead!" end include_examples "sets the expected ivars" do # these are the ivars set before the redirect happened let(:expected_assigns) do { inbox: [], inbox_last_id: nil, more_data_available: false, inbox_count: 0 } end end end context "with no non-anonymous questions from the other user in the inbox" do let!(:anonymous_inbox_entry) do Inbox.create( user:, question: FactoryBot.create( :question, user: other_user, author_is_anonymous: true ) ) end it { is_expected.to redirect_to inbox_path } it "sets the info flash" do subject expect(flash[:info]).to eq "No questions from @#{other_user.screen_name} found, showing entries from all users instead!" end include_examples "sets the expected ivars" do # these are the ivars set before the redirect happened let(:expected_assigns) do { inbox: [], inbox_last_id: nil, more_data_available: false, inbox_count: 0 } end end end context "with both non-anonymous and anonymous questions from the other user in the inbox" do let!(:non_anonymous_inbox_entry) do Inbox.create( user:, question: FactoryBot.create( :question, user: other_user, author_is_anonymous: false ) ) end let!(:anonymous_inbox_entry) do Inbox.create( user:, question: FactoryBot.create( :question, user: other_user, author_is_anonymous: true ) ) end include_examples "sets the expected ivars" do let(:expected_assigns) do { inbox: [non_anonymous_inbox_entry], inbox_last_id: non_anonymous_inbox_entry.id, more_data_available: false, inbox_count: 1, delete_id: "ib-delete-all-author", disabled: nil } end end end end end end end describe "#create" do subject { post :create } it "redirects to the login page when not signed in" do expect(subject).to redirect_to(new_user_session_path) end context "when user is signed in" do before(:each) { sign_in(user) } it "creates an inbox entry" do expect { subject }.to(change { user.inboxes.count }.by(1)) end end end end