Commit 8b62bdd6 authored by Alex Kalderimis's avatar Alex Kalderimis

Increase test coverage of ItemContext

parent 42a4d53a
...@@ -18,6 +18,10 @@ module Gitlab ...@@ -18,6 +18,10 @@ module Gitlab
@ignoring = ignoring @ignoring = ignoring
end end
def ==(other)
other.is_a?(self.class) && other.object == object && other.range == range && other.ignoring == ignoring
end
def positioned? def positioned?
relative_position.present? relative_position.present?
end end
...@@ -143,6 +147,43 @@ module Gitlab ...@@ -143,6 +147,43 @@ module Gitlab
find_next_gap_after.tap { |gap| move_sequence_after(false, next_gap: gap) } find_next_gap_after.tap { |gap| move_sequence_after(false, next_gap: gap) }
end end
def find_next_gap_before
items_with_next_pos = scoped_items
.select('relative_position AS pos, LEAD(relative_position) OVER (ORDER BY relative_position DESC) AS next_pos')
.where('relative_position <= ?', relative_position)
.order(relative_position: :desc)
find_next_gap(items_with_next_pos, range.first)
end
def find_next_gap_after
items_with_next_pos = scoped_items
.select('relative_position AS pos, LEAD(relative_position) OVER (ORDER BY relative_position ASC) AS next_pos')
.where('relative_position >= ?', relative_position)
.order(:relative_position)
find_next_gap(items_with_next_pos, range.last)
end
def find_next_gap(items_with_next_pos, default_end)
gap = model_class
.from(items_with_next_pos, :items)
.where('next_pos IS NULL OR ABS(pos::bigint - next_pos::bigint) >= ?', MIN_GAP)
.limit(1)
.pluck(:pos, :next_pos)
.first
return if gap.nil? || gap.first == default_end
Gap.new(gap.first, gap.second || default_end)
end
def relative_position
object.relative_position
end
private
# Moves the sequence before the current item to the middle of the next gap # Moves the sequence before the current item to the middle of the next gap
# For example, we have # For example, we have
# #
...@@ -212,41 +253,6 @@ module Gitlab ...@@ -212,41 +253,6 @@ module Gitlab
object.update_relative_siblings(relation, (start_pos..end_pos), delta) object.update_relative_siblings(relation, (start_pos..end_pos), delta)
end end
def find_next_gap_before
items_with_next_pos = scoped_items
.select('relative_position AS pos, LEAD(relative_position) OVER (ORDER BY relative_position DESC) AS next_pos')
.where('relative_position <= ?', relative_position)
.order(relative_position: :desc)
find_next_gap(items_with_next_pos, range.first)
end
def find_next_gap_after
items_with_next_pos = scoped_items
.select('relative_position AS pos, LEAD(relative_position) OVER (ORDER BY relative_position ASC) AS next_pos')
.where('relative_position >= ?', relative_position)
.order(:relative_position)
find_next_gap(items_with_next_pos, range.last)
end
def find_next_gap(items_with_next_pos, default_end)
gap = model_class
.from(items_with_next_pos, :items)
.where('next_pos IS NULL OR ABS(pos::bigint - next_pos::bigint) >= ?', MIN_GAP)
.limit(1)
.pluck(:pos, :next_pos)
.first
return if gap.nil? || gap.first == default_end
Gap.new(gap.first, gap.second || default_end)
end
def relative_position
object.relative_position
end
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
end end
......
...@@ -11,12 +11,16 @@ RSpec.describe Gitlab::RelativePositioning::ItemContext do ...@@ -11,12 +11,16 @@ RSpec.describe Gitlab::RelativePositioning::ItemContext do
end end
# Increase the range size to convice yourself that this covers ALL arrangements # Increase the range size to convice yourself that this covers ALL arrangements
# We use plain variables here so we can use them in `where` blocks.
range = (101..108) range = (101..108)
indices = (0..).take(range.size) indices = (0..).take(range.size)
let(:start) { ((range.first + range.last) / 2.0).floor } let(:start) { ((range.first + range.last) / 2.0).floor }
let(:subjects) { issues.map { |i| described_class.new(i.reset, range) } } let(:subjects) { issues.map { |i| described_class.new(i.reset, range) } }
# This allows us to refer to range in methods and examples
let_it_be(:full_range) { range }
context 'there are gaps at the start and end' do context 'there are gaps at the start and end' do
let_it_be(:issues) { (range.first.succ..range.last.pred).map { |pos| create_issue(pos) } } let_it_be(:issues) { (range.first.succ..range.last.pred).map { |pos| create_issue(pos) } }
...@@ -36,11 +40,23 @@ RSpec.describe Gitlab::RelativePositioning::ItemContext do ...@@ -36,11 +40,23 @@ RSpec.describe Gitlab::RelativePositioning::ItemContext do
expect(subject.find_next_gap_after).not_to be_present expect(subject.find_next_gap_after).not_to be_present
end end
it 'is possible to create_space_right, which will move the gap to immediately after' do
subject.create_space_right
expect(subject.find_next_gap_after).to have_attributes(start_pos: subject.relative_position)
end
it 'is possible to shift_left, which will consume the gap at the start' do it 'is possible to shift_left, which will consume the gap at the start' do
subject.shift_left subject.shift_left
expect(subject.find_next_gap_before).not_to be_present expect(subject.find_next_gap_before).not_to be_present
end end
it 'is possible to create_space_left, which will move the gap to immediately before' do
subject.create_space_left
expect(subject.find_next_gap_before).to have_attributes(start_pos: subject.relative_position)
end
end end
end end
...@@ -80,10 +96,19 @@ RSpec.describe Gitlab::RelativePositioning::ItemContext do ...@@ -80,10 +96,19 @@ RSpec.describe Gitlab::RelativePositioning::ItemContext do
end end
end end
def issue_at(position)
issues.find { |i| i.relative_position == position }
end
where(:current_pos) { range.select(&:even?) } where(:current_pos) { range.select(&:even?) }
with_them do with_them do
let(:subject) { subjects.find { |s| s.relative_position == current_pos } } let(:subject) { subjects.find { |s| s.relative_position == current_pos } }
let(:siblings) { subjects.reject { |s| s.relative_position == current_pos } }
def covered_by_range(pos)
full_range.cover?(pos) ? pos : nil
end
it 'finds the closest gap' do it 'finds the closest gap' do
closest_gap_before = gaps closest_gap_before = gaps
...@@ -100,6 +125,34 @@ RSpec.describe Gitlab::RelativePositioning::ItemContext do ...@@ -100,6 +125,34 @@ RSpec.describe Gitlab::RelativePositioning::ItemContext do
find_next_gap_after: closest_gap_after find_next_gap_after: closest_gap_after
) )
end end
it 'finds the neighbours' do
expect(subject).to have_attributes(
lhs_neighbour: subject.neighbour(issue_at(subject.relative_position - 2)),
rhs_neighbour: subject.neighbour(issue_at(subject.relative_position + 2))
)
end
it 'finds the next relative_positions' do
expect(subject).to have_attributes(
prev_relative_position: covered_by_range(subject.relative_position - 2),
next_relative_position: covered_by_range(subject.relative_position + 2)
)
end
it 'finds the min/max positions' do
expect(subject).to have_attributes(
min_relative_position: issues.first.relative_position,
max_relative_position: issues.last.relative_position
)
end
it 'finds the min/max siblings' do
expect(subject).to have_attributes(
min_sibling: siblings.first,
max_sibling: siblings.last
)
end
end end
end end
...@@ -117,7 +170,7 @@ RSpec.describe Gitlab::RelativePositioning::ItemContext do ...@@ -117,7 +170,7 @@ RSpec.describe Gitlab::RelativePositioning::ItemContext do
to_the_right_of_gap = subjects.select { |s| free_space < s.relative_position } to_the_right_of_gap = subjects.select { |s| free_space < s.relative_position }
expect(to_the_right_of_gap) expect(to_the_right_of_gap)
.to all(have_attributes(find_next_gap_before: eq(expected_gap))) .to all(have_attributes(find_next_gap_before: eq(expected_gap), find_next_gap_after: be_nil))
end end
it 'can always find a gap after if there is space to the right' do it 'can always find a gap after if there is space to the right' do
...@@ -126,7 +179,7 @@ RSpec.describe Gitlab::RelativePositioning::ItemContext do ...@@ -126,7 +179,7 @@ RSpec.describe Gitlab::RelativePositioning::ItemContext do
to_the_left_of_gap = subjects.select { |s| s.relative_position < free_space } to_the_left_of_gap = subjects.select { |s| s.relative_position < free_space }
expect(to_the_left_of_gap) expect(to_the_left_of_gap)
.to all(have_attributes(find_next_gap_after: eq(expected_gap))) .to all(have_attributes(find_next_gap_before: be_nil, find_next_gap_after: eq(expected_gap)))
end end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment