summaryrefslogtreecommitdiff
path: root/spec/models/concerns
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/concerns')
-rw-r--r--spec/models/concerns/cache_markdown_field_spec.rb5
-rw-r--r--spec/models/concerns/has_status_spec.rb54
-rw-r--r--spec/models/concerns/issuable_spec.rb50
-rw-r--r--spec/models/concerns/milestoneish_spec.rb26
-rw-r--r--spec/models/concerns/relative_positioning_spec.rb204
-rw-r--r--spec/models/concerns/routable_spec.rb4
-rw-r--r--spec/models/concerns/uniquify_spec.rb33
7 files changed, 369 insertions, 7 deletions
diff --git a/spec/models/concerns/cache_markdown_field_spec.rb b/spec/models/concerns/cache_markdown_field_spec.rb
index 2e3702f7520..6151d53cd91 100644
--- a/spec/models/concerns/cache_markdown_field_spec.rb
+++ b/spec/models/concerns/cache_markdown_field_spec.rb
@@ -1,7 +1,8 @@
require 'spec_helper'
describe CacheMarkdownField do
- CacheMarkdownField::CACHING_CLASSES << "ThingWithMarkdownFields"
+ caching_classes = CacheMarkdownField::CACHING_CLASSES
+ CacheMarkdownField::CACHING_CLASSES = ["ThingWithMarkdownFields"].freeze
# The minimum necessary ActiveModel to test this concern
class ThingWithMarkdownFields
@@ -54,7 +55,7 @@ describe CacheMarkdownField do
end
end
- CacheMarkdownField::CACHING_CLASSES.delete("ThingWithMarkdownFields")
+ CacheMarkdownField::CACHING_CLASSES = caching_classes
def thing_subclass(new_attr)
Class.new(ThingWithMarkdownFields) { add_attr(new_attr) }
diff --git a/spec/models/concerns/has_status_spec.rb b/spec/models/concerns/has_status_spec.rb
index dbfe3cd2d36..82abad0e2f6 100644
--- a/spec/models/concerns/has_status_spec.rb
+++ b/spec/models/concerns/has_status_spec.rb
@@ -109,6 +109,42 @@ describe HasStatus do
it { is_expected.to eq 'running' }
end
+
+ context 'when one status finished and second is still created' do
+ let!(:statuses) do
+ [create(type, status: :success), create(type, status: :created)]
+ end
+
+ it { is_expected.to eq 'running' }
+ end
+
+ context 'when there is a manual status before created status' do
+ let!(:statuses) do
+ [create(type, status: :success),
+ create(type, status: :manual, allow_failure: false),
+ create(type, status: :created)]
+ end
+
+ it { is_expected.to eq 'manual' }
+ end
+
+ context 'when one status is a blocking manual action' do
+ let!(:statuses) do
+ [create(type, status: :failed),
+ create(type, status: :manual, allow_failure: false)]
+ end
+
+ it { is_expected.to eq 'manual' }
+ end
+
+ context 'when one status is a non-blocking manual action' do
+ let!(:statuses) do
+ [create(type, status: :failed),
+ create(type, status: :manual, allow_failure: true)]
+ end
+
+ it { is_expected.to eq 'failed' }
+ end
end
context 'ci build statuses' do
@@ -218,6 +254,18 @@ describe HasStatus do
it_behaves_like 'not containing the job', status
end
end
+
+ describe '.manual' do
+ subject { CommitStatus.manual }
+
+ %i[manual].each do |status|
+ it_behaves_like 'containing the job', status
+ end
+
+ %i[failed success skipped canceled].each do |status|
+ it_behaves_like 'not containing the job', status
+ end
+ end
end
describe '::DEFAULT_STATUS' do
@@ -225,4 +273,10 @@ describe HasStatus do
expect(described_class::DEFAULT_STATUS).to eq 'created'
end
end
+
+ describe '::BLOCKED_STATUS' do
+ it 'is a status manual' do
+ expect(described_class::BLOCKED_STATUS).to eq 'manual'
+ end
+ end
end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 545a11912e3..9574796a945 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -278,6 +278,16 @@ describe Issue, "Issuable" do
end
end
+ context 'issue has labels' do
+ let(:labels) { [create(:label), create(:label)] }
+
+ before { issue.update_attribute(:labels, labels)}
+
+ it 'includes labels in the hook data' do
+ expect(data[:labels]).to eq(labels.map(&:hook_attrs))
+ end
+ end
+
include_examples 'project hook data'
include_examples 'deprecated repository hook data'
end
@@ -344,6 +354,46 @@ describe Issue, "Issuable" do
end
end
+ describe '.order_due_date_and_labels_priority' do
+ let(:project) { create(:empty_project) }
+
+ def create_issue(milestone, labels)
+ create(:labeled_issue, milestone: milestone, labels: labels, project: project)
+ end
+
+ it 'sorts issues in order of milestone due date, then label priority' do
+ first_priority = create(:label, project: project, priority: 1)
+ second_priority = create(:label, project: project, priority: 2)
+ no_priority = create(:label, project: project)
+
+ first_milestone = create(:milestone, project: project, due_date: Time.now)
+ second_milestone = create(:milestone, project: project, due_date: Time.now + 1.month)
+ third_milestone = create(:milestone, project: project)
+
+ # The issues here are ordered by label priority, to ensure that we don't
+ # accidentally just sort by creation date.
+ second_milestone_first_priority = create_issue(second_milestone, [first_priority, second_priority, no_priority])
+ third_milestone_first_priority = create_issue(third_milestone, [first_priority, second_priority, no_priority])
+ first_milestone_second_priority = create_issue(first_milestone, [second_priority, no_priority])
+ second_milestone_second_priority = create_issue(second_milestone, [second_priority, no_priority])
+ no_milestone_second_priority = create_issue(nil, [second_priority, no_priority])
+ first_milestone_no_priority = create_issue(first_milestone, [no_priority])
+ second_milestone_no_labels = create_issue(second_milestone, [])
+ third_milestone_no_priority = create_issue(third_milestone, [no_priority])
+
+ result = Issue.order_due_date_and_labels_priority
+
+ expect(result).to eq([first_milestone_second_priority,
+ first_milestone_no_priority,
+ second_milestone_first_priority,
+ second_milestone_second_priority,
+ second_milestone_no_labels,
+ third_milestone_first_priority,
+ no_milestone_second_priority,
+ third_milestone_no_priority])
+ end
+ end
+
describe '.order_labels_priority' do
let(:label_1) { create(:label, title: 'label_1', project: issue.project, priority: 1) }
let(:label_2) { create(:label, title: 'label_2', project: issue.project, priority: 2) }
diff --git a/spec/models/concerns/milestoneish_spec.rb b/spec/models/concerns/milestoneish_spec.rb
index ad703a6c8bb..68e4c0a522b 100644
--- a/spec/models/concerns/milestoneish_spec.rb
+++ b/spec/models/concerns/milestoneish_spec.rb
@@ -116,21 +116,41 @@ describe Milestone, 'Milestoneish' do
end
end
+ describe '#remaining_days' do
+ it 'shows 0 if no due date' do
+ milestone = build_stubbed(:milestone)
+
+ expect(milestone.remaining_days).to eq(0)
+ end
+
+ it 'shows 0 if expired' do
+ milestone = build_stubbed(:milestone, due_date: 2.days.ago)
+
+ expect(milestone.remaining_days).to eq(0)
+ end
+
+ it 'shows correct remaining days' do
+ milestone = build_stubbed(:milestone, due_date: 2.days.from_now)
+
+ expect(milestone.remaining_days).to eq(2)
+ end
+ end
+
describe '#elapsed_days' do
it 'shows 0 if no start_date set' do
- milestone = build(:milestone)
+ milestone = build_stubbed(:milestone)
expect(milestone.elapsed_days).to eq(0)
end
it 'shows 0 if start_date is a future' do
- milestone = build(:milestone, start_date: Time.now + 2.days)
+ milestone = build_stubbed(:milestone, start_date: Time.now + 2.days)
expect(milestone.elapsed_days).to eq(0)
end
it 'shows correct amount of days' do
- milestone = build(:milestone, start_date: Time.now - 2.days)
+ milestone = build_stubbed(:milestone, start_date: Time.now - 2.days)
expect(milestone.elapsed_days).to eq(2)
end
diff --git a/spec/models/concerns/relative_positioning_spec.rb b/spec/models/concerns/relative_positioning_spec.rb
new file mode 100644
index 00000000000..255b584a85e
--- /dev/null
+++ b/spec/models/concerns/relative_positioning_spec.rb
@@ -0,0 +1,204 @@
+require 'spec_helper'
+
+describe Issue, 'RelativePositioning' do
+ let(:project) { create(:empty_project) }
+ let(:issue) { create(:issue, project: project) }
+ let(:issue1) { create(:issue, project: project) }
+ let(:new_issue) { create(:issue, project: project) }
+
+ before do
+ [issue, issue1].each do |issue|
+ issue.move_to_end && issue.save
+ end
+ end
+
+ describe '#max_relative_position' do
+ it 'returns maximum position' do
+ expect(issue.max_relative_position).to eq issue1.relative_position
+ end
+ end
+
+ describe '#prev_relative_position' do
+ it 'returns previous position if there is an issue above' do
+ expect(issue1.prev_relative_position).to eq issue.relative_position
+ end
+
+ it 'returns nil if there is no issue above' do
+ expect(issue.prev_relative_position).to eq nil
+ end
+ end
+
+ describe '#next_relative_position' do
+ it 'returns next position if there is an issue below' do
+ expect(issue.next_relative_position).to eq issue1.relative_position
+ end
+
+ it 'returns nil if there is no issue below' do
+ expect(issue1.next_relative_position).to eq nil
+ end
+ end
+
+ describe '#move_before' do
+ it 'moves issue before' do
+ [issue1, issue].each(&:move_to_end)
+
+ issue.move_before(issue1)
+
+ expect(issue.relative_position).to be < issue1.relative_position
+ end
+ end
+
+ describe '#move_after' do
+ it 'moves issue after' do
+ [issue, issue1].each(&:move_to_end)
+
+ issue.move_after(issue1)
+
+ expect(issue.relative_position).to be > issue1.relative_position
+ end
+ end
+
+ describe '#move_to_end' do
+ it 'moves issue to the end' do
+ new_issue.move_to_end
+
+ expect(new_issue.relative_position).to be > issue1.relative_position
+ end
+ end
+
+ describe '#shift_after?' do
+ it 'returns true' do
+ issue.update(relative_position: issue1.relative_position - 1)
+
+ expect(issue.shift_after?).to be_truthy
+ end
+
+ it 'returns false' do
+ issue.update(relative_position: issue1.relative_position - 2)
+
+ expect(issue.shift_after?).to be_falsey
+ end
+ end
+
+ describe '#shift_before?' do
+ it 'returns true' do
+ issue.update(relative_position: issue1.relative_position + 1)
+
+ expect(issue.shift_before?).to be_truthy
+ end
+
+ it 'returns false' do
+ issue.update(relative_position: issue1.relative_position + 2)
+
+ expect(issue.shift_before?).to be_falsey
+ end
+ end
+
+ describe '#move_between' do
+ it 'positions issue between two other' do
+ new_issue.move_between(issue, issue1)
+
+ expect(new_issue.relative_position).to be > issue.relative_position
+ expect(new_issue.relative_position).to be < issue1.relative_position
+ end
+
+ it 'positions issue between on top' do
+ new_issue.move_between(nil, issue)
+
+ expect(new_issue.relative_position).to be < issue.relative_position
+ end
+
+ it 'positions issue between to end' do
+ new_issue.move_between(issue1, nil)
+
+ expect(new_issue.relative_position).to be > issue1.relative_position
+ end
+
+ it 'positions issues even when after and before positions are the same' do
+ issue1.update relative_position: issue.relative_position
+
+ new_issue.move_between(issue, issue1)
+
+ expect(new_issue.relative_position).to be > issue.relative_position
+ expect(issue.relative_position).to be < issue1.relative_position
+ end
+
+ it 'positions issues between other two if distance is 1' do
+ issue1.update relative_position: issue.relative_position + 1
+
+ new_issue.move_between(issue, issue1)
+
+ expect(new_issue.relative_position).to be > issue.relative_position
+ expect(issue.relative_position).to be < issue1.relative_position
+ end
+
+ it 'positions issue in the middle of other two if distance is big enough' do
+ issue.update relative_position: 6000
+ issue1.update relative_position: 10000
+
+ new_issue.move_between(issue, issue1)
+
+ expect(new_issue.relative_position).to eq(8000)
+ end
+
+ it 'positions issue closer to the middle if we are at the very top' do
+ issue1.update relative_position: 6000
+
+ new_issue.move_between(nil, issue1)
+
+ expect(new_issue.relative_position).to eq(6000 - RelativePositioning::IDEAL_DISTANCE)
+ end
+
+ it 'positions issue closer to the middle if we are at the very bottom' do
+ issue.update relative_position: 6000
+ issue1.update relative_position: nil
+
+ new_issue.move_between(issue, nil)
+
+ expect(new_issue.relative_position).to eq(6000 + RelativePositioning::IDEAL_DISTANCE)
+ end
+
+ it 'positions issue in the middle of other two if distance is not big enough' do
+ issue.update relative_position: 100
+ issue1.update relative_position: 400
+
+ new_issue.move_between(issue, issue1)
+
+ expect(new_issue.relative_position).to eq(250)
+ end
+
+ it 'positions issue in the middle of other two is there is no place' do
+ issue.update relative_position: 100
+ issue1.update relative_position: 101
+
+ new_issue.move_between(issue, issue1)
+
+ expect(new_issue.relative_position).to be_between(issue.relative_position, issue1.relative_position)
+ end
+
+ it 'uses rebalancing if there is no place' do
+ issue.update relative_position: 100
+ issue1.update relative_position: 101
+ issue2 = create(:issue, relative_position: 102, project: project)
+ new_issue.update relative_position: 103
+
+ new_issue.move_between(issue1, issue2)
+ new_issue.save!
+
+ expect(new_issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
+ expect(issue.reload.relative_position).not_to eq(100)
+ end
+
+ it 'positions issue right if we pass none-sequential parameters' do
+ issue.update relative_position: 99
+ issue1.update relative_position: 101
+ issue2 = create(:issue, relative_position: 102, project: project)
+ new_issue.update relative_position: 103
+
+ new_issue.move_between(issue, issue2)
+ new_issue.save!
+
+ expect(new_issue.relative_position).to be(100)
+ end
+ end
+end
diff --git a/spec/models/concerns/routable_spec.rb b/spec/models/concerns/routable_spec.rb
index e008ec28fa4..677e60e1282 100644
--- a/spec/models/concerns/routable_spec.rb
+++ b/spec/models/concerns/routable_spec.rb
@@ -86,7 +86,7 @@ describe Group, 'Routable' do
let(:nested_group) { create(:group, parent: group) }
it { expect(group.full_path).to eq(group.path) }
- it { expect(nested_group.full_path).to eq("#{group.path}/#{nested_group.path}") }
+ it { expect(nested_group.full_path).to eq("#{group.full_path}/#{nested_group.path}") }
end
describe '#full_name' do
@@ -102,7 +102,7 @@ describe Project, 'Routable' do
describe '#full_path' do
let(:project) { build_stubbed(:empty_project) }
- it { expect(project.full_path).to eq "#{project.namespace.path}/#{project.path}" }
+ it { expect(project.full_path).to eq "#{project.namespace.full_path}/#{project.path}" }
end
describe '#full_name' do
diff --git a/spec/models/concerns/uniquify_spec.rb b/spec/models/concerns/uniquify_spec.rb
new file mode 100644
index 00000000000..83187d732e4
--- /dev/null
+++ b/spec/models/concerns/uniquify_spec.rb
@@ -0,0 +1,33 @@
+require 'spec_helper'
+
+describe Uniquify, models: true do
+ let(:uniquify) { described_class.new }
+
+ describe "#string" do
+ it 'returns the given string if it does not exist' do
+ result = uniquify.string('test_string') { |s| false }
+
+ expect(result).to eq('test_string')
+ end
+
+ it 'returns the given string with a counter attached if the string exists' do
+ result = uniquify.string('test_string') { |s| s == 'test_string' }
+
+ expect(result).to eq('test_string1')
+ end
+
+ it 'increments the counter for each candidate string that also exists' do
+ result = uniquify.string('test_string') { |s| s == 'test_string' || s == 'test_string1' }
+
+ expect(result).to eq('test_string2')
+ end
+
+ it 'allows passing in a base function that defines the location of the counter' do
+ result = uniquify.string(-> (counter) { "test_#{counter}_string" }) do |s|
+ s == 'test__string'
+ end
+
+ expect(result).to eq('test_1_string')
+ end
+ end
+end