require 'spec_helper' describe Discussion, model: true do subject { described_class.new([first_note, second_note, third_note]) } let(:first_note) { create(:diff_note_on_merge_request) } let(:second_note) { create(:diff_note_on_merge_request) } let(:third_note) { create(:diff_note_on_merge_request) } describe "#resolvable?" do context "when a diff discussion" do before do allow(subject).to receive(:diff_discussion?).and_return(true) end context "when all notes are unresolvable" do before do allow(first_note).to receive(:resolvable?).and_return(false) allow(second_note).to receive(:resolvable?).and_return(false) allow(third_note).to receive(:resolvable?).and_return(false) end it "returns false" do expect(subject.resolvable?).to be false end end context "when some notes are unresolvable and some notes are resolvable" do before do allow(first_note).to receive(:resolvable?).and_return(true) allow(second_note).to receive(:resolvable?).and_return(false) allow(third_note).to receive(:resolvable?).and_return(true) end it "returns true" do expect(subject.resolvable?).to be true end end context "when all notes are resolvable" do before do allow(first_note).to receive(:resolvable?).and_return(true) allow(second_note).to receive(:resolvable?).and_return(true) allow(third_note).to receive(:resolvable?).and_return(true) end it "returns true" do expect(subject.resolvable?).to be true end end end context "when not a diff discussion" do before do allow(subject).to receive(:diff_discussion?).and_return(false) end it "returns false" do expect(subject.resolvable?).to be false end end end describe "#resolved?" do context "when not resolvable" do before do allow(subject).to receive(:resolvable?).and_return(false) end it "returns false" do expect(subject.resolved?).to be false end end context "when resolvable" do before do allow(subject).to receive(:resolvable?).and_return(true) allow(first_note).to receive(:resolvable?).and_return(true) allow(second_note).to receive(:resolvable?).and_return(false) allow(third_note).to receive(:resolvable?).and_return(true) end context "when all resolvable notes are resolved" do before do allow(first_note).to receive(:resolved?).and_return(true) allow(third_note).to receive(:resolved?).and_return(true) end it "returns true" do expect(subject.resolved?).to be true end end context "when some resolvable notes are not resolved" do before do allow(first_note).to receive(:resolved?).and_return(true) allow(third_note).to receive(:resolved?).and_return(false) end it "returns false" do expect(subject.resolved?).to be false end end end end describe "#to_be_resolved?" do context "when not resolvable" do before do allow(subject).to receive(:resolvable?).and_return(false) end it "returns false" do expect(subject.to_be_resolved?).to be false end end context "when resolvable" do before do allow(subject).to receive(:resolvable?).and_return(true) allow(first_note).to receive(:resolvable?).and_return(true) allow(second_note).to receive(:resolvable?).and_return(false) allow(third_note).to receive(:resolvable?).and_return(true) end context "when all resolvable notes are resolved" do before do allow(first_note).to receive(:resolved?).and_return(true) allow(third_note).to receive(:resolved?).and_return(true) end it "returns false" do expect(subject.to_be_resolved?).to be false end end context "when some resolvable notes are not resolved" do before do allow(first_note).to receive(:resolved?).and_return(true) allow(third_note).to receive(:resolved?).and_return(false) end it "returns true" do expect(subject.to_be_resolved?).to be true end end end end describe "#can_resolve?" do let(:current_user) { create(:user) } context "when not resolvable" do before do allow(subject).to receive(:resolvable?).and_return(false) end it "returns false" do expect(subject.can_resolve?(current_user)).to be false end end context "when resolvable" do before do allow(subject).to receive(:resolvable?).and_return(true) end context "when not signed in" do let(:current_user) { nil } it "returns false" do expect(subject.can_resolve?(current_user)).to be false end end context "when signed in" do context "when the signed in user is the noteable author" do before do subject.noteable.author = current_user end it "returns true" do expect(subject.can_resolve?(current_user)).to be true end end context "when the signed in user can push to the project" do before do subject.project.team << [current_user, :master] end it "returns true" do expect(subject.can_resolve?(current_user)).to be true end end context "when the signed in user is a random user" do it "returns false" do expect(subject.can_resolve?(current_user)).to be false end end end end end describe "#resolve!" do let(:current_user) { create(:user) } context "when not resolvable" do before do allow(subject).to receive(:resolvable?).and_return(false) end it "returns nil" do expect(subject.resolve!(current_user)).to be_nil end it "doesn't set resolved_at" do subject.resolve!(current_user) expect(subject.resolved_at).to be_nil end it "doesn't set resolved_by" do subject.resolve!(current_user) expect(subject.resolved_by).to be_nil end it "doesn't mark as resolved" do subject.resolve!(current_user) expect(subject.resolved?).to be false end end context "when resolvable" do let(:user) { create(:user) } let(:second_note) { create(:diff_note_on_commit) } # unresolvable before do allow(subject).to receive(:resolvable?).and_return(true) end context "when all resolvable notes are resolved" do before do first_note.resolve!(user) third_note.resolve!(user) first_note.reload third_note.reload end it "doesn't change resolved_at on the resolved notes" do expect(first_note.resolved_at).not_to be_nil expect(third_note.resolved_at).not_to be_nil expect { subject.resolve!(current_user) }.not_to change { first_note.resolved_at } expect { subject.resolve!(current_user) }.not_to change { third_note.resolved_at } end it "doesn't change resolved_by on the resolved notes" do expect(first_note.resolved_by).to eq(user) expect(third_note.resolved_by).to eq(user) expect { subject.resolve!(current_user) }.not_to change { first_note.resolved_by } expect { subject.resolve!(current_user) }.not_to change { third_note.resolved_by } end it "doesn't change the resolved state on the resolved notes" do expect(first_note.resolved?).to be true expect(third_note.resolved?).to be true expect { subject.resolve!(current_user) }.not_to change { first_note.resolved? } expect { subject.resolve!(current_user) }.not_to change { third_note.resolved? } end it "doesn't change resolved_at" do expect(subject.resolved_at).not_to be_nil expect { subject.resolve!(current_user) }.not_to change { subject.resolved_at } end it "doesn't change resolved_by" do expect(subject.resolved_by).to eq(user) expect { subject.resolve!(current_user) }.not_to change { subject.resolved_by } end it "doesn't change resolved state" do expect(subject.resolved?).to be true expect { subject.resolve!(current_user) }.not_to change { subject.resolved? } end end context "when some resolvable notes are resolved" do before do first_note.resolve!(user) end it "doesn't change resolved_at on the resolved note" do expect(first_note.resolved_at).not_to be_nil expect { subject.resolve!(current_user) }. not_to change { first_note.reload.resolved_at } end it "doesn't change resolved_by on the resolved note" do expect(first_note.resolved_by).to eq(user) expect { subject.resolve!(current_user) }. not_to change { first_note.reload && first_note.resolved_by } end it "doesn't change the resolved state on the resolved note" do expect(first_note.resolved?).to be true expect { subject.resolve!(current_user) }. not_to change { first_note.reload && first_note.resolved? } end it "sets resolved_at on the unresolved note" do subject.resolve!(current_user) third_note.reload expect(third_note.resolved_at).not_to be_nil end it "sets resolved_by on the unresolved note" do subject.resolve!(current_user) third_note.reload expect(third_note.resolved_by).to eq(current_user) end it "marks the unresolved note as resolved" do subject.resolve!(current_user) third_note.reload expect(third_note.resolved?).to be true end it "sets resolved_at" do subject.resolve!(current_user) expect(subject.resolved_at).not_to be_nil end it "sets resolved_by" do subject.resolve!(current_user) expect(subject.resolved_by).to eq(current_user) end it "marks as resolved" do subject.resolve!(current_user) expect(subject.resolved?).to be true end end context "when no resolvable notes are resolved" do it "sets resolved_at on the unresolved notes" do subject.resolve!(current_user) first_note.reload third_note.reload expect(first_note.resolved_at).not_to be_nil expect(third_note.resolved_at).not_to be_nil end it "sets resolved_by on the unresolved notes" do subject.resolve!(current_user) first_note.reload third_note.reload expect(first_note.resolved_by).to eq(current_user) expect(third_note.resolved_by).to eq(current_user) end it "marks the unresolved notes as resolved" do subject.resolve!(current_user) first_note.reload third_note.reload expect(first_note.resolved?).to be true expect(third_note.resolved?).to be true end it "sets resolved_at" do subject.resolve!(current_user) first_note.reload third_note.reload expect(subject.resolved_at).not_to be_nil end it "sets resolved_by" do subject.resolve!(current_user) first_note.reload third_note.reload expect(subject.resolved_by).to eq(current_user) end it "marks as resolved" do subject.resolve!(current_user) first_note.reload third_note.reload expect(subject.resolved?).to be true end end end end describe "#unresolve!" do context "when not resolvable" do before do allow(subject).to receive(:resolvable?).and_return(false) end it "returns nil" do expect(subject.unresolve!).to be_nil end end context "when resolvable" do let(:user) { create(:user) } before do allow(subject).to receive(:resolvable?).and_return(true) allow(first_note).to receive(:resolvable?).and_return(true) allow(second_note).to receive(:resolvable?).and_return(false) allow(third_note).to receive(:resolvable?).and_return(true) end context "when all resolvable notes are resolved" do before do first_note.resolve!(user) third_note.resolve!(user) end it "unsets resolved_at on the resolved notes" do subject.unresolve! first_note.reload third_note.reload expect(first_note.resolved_at).to be_nil expect(third_note.resolved_at).to be_nil end it "unsets resolved_by on the resolved notes" do subject.unresolve! first_note.reload third_note.reload expect(first_note.resolved_by).to be_nil expect(third_note.resolved_by).to be_nil end it "unmarks the resolved notes as resolved" do subject.unresolve! first_note.reload third_note.reload expect(first_note.resolved?).to be false expect(third_note.resolved?).to be false end it "unsets resolved_at" do subject.unresolve! first_note.reload third_note.reload expect(subject.resolved_at).to be_nil end it "unsets resolved_by" do subject.unresolve! first_note.reload third_note.reload expect(subject.resolved_by).to be_nil end it "unmarks as resolved" do subject.unresolve! expect(subject.resolved?).to be false end end context "when some resolvable notes are resolved" do before do first_note.resolve!(user) end it "unsets resolved_at on the resolved note" do subject.unresolve! expect(subject.first_note.resolved_at).to be_nil end it "unsets resolved_by on the resolved note" do subject.unresolve! expect(subject.first_note.resolved_by).to be_nil end it "unmarks the resolved note as resolved" do subject.unresolve! expect(subject.first_note.resolved?).to be false end end end end describe "#first_note_to_resolve" do it "returns the first not that still needs to be resolved" do allow(first_note).to receive(:to_be_resolved?).and_return(false) allow(second_note).to receive(:to_be_resolved?).and_return(true) expect(subject.first_note_to_resolve).to eq(second_note) end end describe "#collapsed?" do context "when a diff discussion" do before do allow(subject).to receive(:diff_discussion?).and_return(true) end context "when resolvable" do before do allow(subject).to receive(:resolvable?).and_return(true) end context "when resolved" do before do allow(subject).to receive(:resolved?).and_return(true) end it "returns true" do expect(subject.collapsed?).to be true end end context "when not resolved" do before do allow(subject).to receive(:resolved?).and_return(false) end it "returns false" do expect(subject.collapsed?).to be false end end end context "when not resolvable" do before do allow(subject).to receive(:resolvable?).and_return(false) end context "when active" do before do allow(subject).to receive(:active?).and_return(true) end it "returns false" do expect(subject.collapsed?).to be false end end context "when outdated" do before do allow(subject).to receive(:active?).and_return(false) end it "returns true" do expect(subject.collapsed?).to be true end end end end context "when not a diff discussion" do before do allow(subject).to receive(:diff_discussion?).and_return(false) end it "returns false" do expect(subject.collapsed?).to be false end end end describe "#truncated_diff_lines" do let(:truncated_lines) { subject.truncated_diff_lines } context "when diff is greater than allowed number of truncated diff lines " do it "returns fewer lines" do expect(subject.diff_lines.count).to be > described_class::NUMBER_OF_TRUNCATED_DIFF_LINES expect(truncated_lines.count).to be <= described_class::NUMBER_OF_TRUNCATED_DIFF_LINES end end context "when some diff lines are meta" do it "returns no meta lines" do expect(subject.diff_lines).to include(be_meta) expect(truncated_lines).not_to include(be_meta) end end end end