gitlab-org--gitlab-foss/spec/support/matchers/be_sorted.rb

79 lines
1.6 KiB
Ruby

# frozen_string_literal: true
# Assert that this collection is sorted by argument and order
#
# By default, this checks that the collection is sorted ascending
# but you can check order by specific field and order by passing
# them, either as arguments, or using the fluent interface, eg:
#
# ```
# # Usage examples:
# expect(collection).to be_sorted
# expect(collection).to be_sorted(:field)
# expect(collection).to be_sorted(:field, :desc)
# expect(collection).to be_sorted.asc
# expect(collection).to be_sorted.desc.by(&:field)
# expect(collection).to be_sorted.by(&:field).desc
# expect(collection).to be_sorted.by { |x| [x.foo, x.bar] }
# ```
RSpec::Matchers.define :be_sorted do |on = :itself, order = :asc|
def by(&block)
@comparator = block
self
end
def asc
@direction = :asc
self
end
def desc
@direction = :desc
self
end
def format_with(proc)
@format_with = proc
self
end
define_method :comparator do
@comparator || on
end
define_method :descending? do
(@direction || order.to_sym) == :desc
end
def order(items)
descending? ? items.reverse : items
end
def sort(items)
items.sort_by(&comparator)
end
match do |actual|
next true unless actual.present? # empty collection is sorted
actual = actual.to_a if actual.respond_to?(:to_a) && !actual.respond_to?(:sort_by)
@got = actual
@expected = order(sort(actual))
@expected == actual
end
def failure_message
"Expected #{show(@expected)}, got #{show(@got)}"
end
def show(things)
if @format_with
things.map(&@format_with)
else
things
end
end
end