# frozen_string_literal: true require "rails_helper" describe UseCase::Question::Create do subject do UseCase::Question::Create.call( source_user_id: source_user&.id, target_user_id: target_user.id, content:, anonymous:, author_identifier: ) end shared_examples "creates the question" do |should_send_to_inbox = true| it "creates the question" do expect { subject }.to change { Question.count }.by(1) question = Question.last expect(question.content).to eq(content) expect(question.author_is_anonymous).to eq(anonymous) expect(question.author_identifier).to eq(author_identifier) expect(question.direct).to eq(true) if should_send_to_inbox expect(target_user.inbox_entries.first.question_id).to eq(question.id) else expect(target_user.inbox_entries.first).to be_nil end end end shared_examples "invalid params" do it "raises an error" do expect { subject }.to raise_error(Errors::BadRequest) end end shared_examples "forbidden" do it "raises an error" do expect { subject }.to raise_error(Errors::Forbidden) end end shared_examples "not authorized" do it "raises an error" do expect { subject }.to raise_error(Errors::NotAuthorized) end end shared_examples "validates content" do context "content is empty" do let(:content) { "" } it "raises an error" do expect { subject }.to raise_error(ActiveRecord::RecordInvalid) end end context "content is over 512 characters long" do let(:content) { "a" * 513 } context "recipient does not allow long questions" do it "raises an error" do expect { subject }.to raise_error(Errors::QuestionTooLong) end end context "recipient allows long questions" do before do target_user.profile.allow_long_questions = true target_user.profile.save end it_behaves_like "creates the question" end end end shared_examples "filters questions" do context "user blocks this anon" do before do target_user.anonymous_blocks.create!( identifier: author_identifier, question_id: FactoryBot.create(:question).id ) end it_behaves_like "creates the question", false end context "user mutes a term used in the question" do before { target_user.mute_rules.create!(muted_phrase: "hello") } it_behaves_like "creates the question", false end context "question is from an anon who is blocked globally" do before do AnonymousBlock.create!( identifier: author_identifier, question_id: FactoryBot.create(:question).id, user_id: nil ) end it_behaves_like "creates the question", false end end shared_examples "filters signed in questions" do context "user blocks this anonymized user" do before do target_user.anonymous_blocks.create!( identifier: "r4nd0m", question_id: FactoryBot.create(:question).id, target_user_id: source_user&.id ) end it_behaves_like "creates the question", false end end context "user signed in" do let!(:source_user) { FactoryBot.create(:user) } context "target user exists" do let(:target_user) { FactoryBot.create(:user, privacy_allow_anonymous_questions: allow_anon) } let(:allow_anon) { true } context "content is not empty" do let(:content) { "Hello world" } context "question is anonymous" do let(:anonymous) { true } let(:author_identifier) { "abcdef" } context "recipient allows anonymous questions" do it_behaves_like "filters questions" it_behaves_like "filters signed in questions" it_behaves_like "creates the question" it_behaves_like "validates content" it "doesn't increment the source user's asked count" do expect { subject }.not_to(change { source_user.reload.asked_count }) end end context "recipient does not allow anonymous questions" do let(:allow_anon) { false } it_behaves_like "forbidden" end end context "question is not anonymous" do let(:anonymous) { false } let(:author_identifier) { "qwerty" } it_behaves_like "creates the question" it_behaves_like "validates content" it "doesn't increment the source user's asked count" do expect { subject }.not_to(change { source_user.reload.asked_count }) end end end end end context "user not signed in" do let!(:source_user) { nil } context "target user exists" do let(:target_user) { FactoryBot.create(:user, privacy_allow_anonymous_questions: allow_anon) } context "content is not empty" do let(:content) { "Hello world" } context "question is anonymous" do let(:anonymous) { true } let(:author_identifier) { "abcdef" } context "recipient allows anonymous questions" do let(:allow_anon) { true } it_behaves_like "filters questions" it_behaves_like "creates the question" it_behaves_like "validates content" end context "recipient does not allow anonymous questions" do let(:allow_anon) { false } it_behaves_like "forbidden" end end context "question is not anonymous" do let(:allow_anon) { true } # irrelevant for this test, but needs to be set let(:anonymous) { false } let(:author_identifier) { "qwerty" } it_behaves_like "invalid params" end end context "target user does not allow non-logged in questions" do let(:allow_anon) { true } let(:anonymous) { true } let(:content) { "Hello world" } let(:author_identifier) { "qwerty" } before do target_user.update!(privacy_require_user: true) end it_behaves_like "not authorized" end end end end