gitlab-org--gitlab-foss/spec/models/discussion_spec.rb
Bob Van Landuyt 1123057ab7 Feature: delegate all open discussions to Issue
When a merge request can only be merged when all discussions are
resolved. This feature allows to easily delegate those discussions to a
new issue, while marking them as resolved in the merge request.

The user is presented with a new issue, prepared with mentions of all
unresolved discussions, including the first unresolved note of the
discussion, time and link to the note.

When the issue is created, the discussions in the merge request will get
a system note directing the user to the newly created issue.
2016-12-05 20:55:45 +01:00

621 lines
17 KiB
Ruby

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