test: cover OrmListPositionTest and teardown
This commit is contained in:
1 parent
6b7a2bd965
commit
f5598988d4
1 file changed
+161
@@ -0,0 +1,161 @@
|
|||||||
|
require 'minitest/autorun'
|
||||||
|
require 'prism'
|
||||||
|
require 'tmpdir'
|
||||||
|
require 'fileutils'
|
||||||
|
|
||||||
|
class OrmListPositionTest < Minitest::Test
|
||||||
|
def setup
|
||||||
|
@dir = Dir.mktmpdir('prism-list-position-store')
|
||||||
|
@store = Prism::Orm::Store.new(File.join(@dir, 'test.pstore'))
|
||||||
|
@store.create_table(:tasks, %w[id title position deleted_at])
|
||||||
|
@store.create_table(:cards, %w[id title position board_id])
|
||||||
|
|
||||||
|
task_class = Class.new(Prism::Orm::Model) do
|
||||||
|
table_name :tasks
|
||||||
|
acts_as_paranoid
|
||||||
|
acts_as_list column: :position
|
||||||
|
end
|
||||||
|
card_class = Class.new(Prism::Orm::Model) do
|
||||||
|
table_name :cards
|
||||||
|
acts_as_list column: :position, scope: :board_id
|
||||||
|
end
|
||||||
|
plain_class = Class.new(Prism::Orm::Model) { table_name :tasks }
|
||||||
|
|
||||||
|
[task_class, card_class].each { |klass| klass.store = @store }
|
||||||
|
plain_class.store = @store
|
||||||
|
Object.const_set(:Task, task_class)
|
||||||
|
Object.const_set(:Card, card_class)
|
||||||
|
Object.const_set(:PlainTask, plain_class)
|
||||||
|
end
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
FileUtils.remove_entry(@dir)
|
||||||
|
%i[Task Card PlainTask].each { |name| Object.send(:remove_const, name) if Object.const_defined?(name) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_a_model_that_never_called_acts_as_list_is_unaffected
|
||||||
|
refute PlainTask.acts_as_list?
|
||||||
|
assert Task.acts_as_list?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_fresh_records_are_appended_to_the_bottom_in_creation_order
|
||||||
|
a = Task.create!(title: 'a')
|
||||||
|
b = Task.create!(title: 'b')
|
||||||
|
c = Task.create!(title: 'c')
|
||||||
|
assert_equal [1, 2, 3], [a, b, c].map(&:list_position)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_move_higher_swaps_with_the_previous_item_and_is_a_noop_at_the_top
|
||||||
|
a = Task.create!(title: 'a')
|
||||||
|
b = Task.create!(title: 'b')
|
||||||
|
b.move_higher
|
||||||
|
assert_equal 1, b.list_position
|
||||||
|
assert_equal 2, a.reload.list_position
|
||||||
|
|
||||||
|
b.reload.move_higher # b is already first - nothing above it to swap with
|
||||||
|
assert_equal 1, b.list_position
|
||||||
|
assert_equal 2, a.reload.list_position
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_move_lower_swaps_with_the_next_item_and_is_a_noop_at_the_bottom
|
||||||
|
a = Task.create!(title: 'a')
|
||||||
|
b = Task.create!(title: 'b')
|
||||||
|
a.move_lower
|
||||||
|
assert_equal 2, a.list_position
|
||||||
|
assert_equal 1, b.reload.list_position
|
||||||
|
|
||||||
|
b.reload.move_lower # b is now first (pos 1), a is last (pos 2) - moving b lower swaps back
|
||||||
|
assert_equal 2, b.list_position
|
||||||
|
assert_equal 1, a.reload.list_position
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_move_lower_on_the_last_item_is_a_noop
|
||||||
|
a = Task.create!(title: 'a')
|
||||||
|
Task.create!(title: 'b')
|
||||||
|
b2 = Task.find_by!(title: 'b')
|
||||||
|
b2.move_lower
|
||||||
|
assert_equal 2, b2.list_position
|
||||||
|
assert_equal 1, a.reload.list_position
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_move_higher_on_the_first_item_is_a_noop
|
||||||
|
a = Task.create!(title: 'a')
|
||||||
|
Task.create!(title: 'b')
|
||||||
|
a.move_higher
|
||||||
|
assert_equal 1, a.list_position
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_first_and_last_in_list_predicates
|
||||||
|
a = Task.create!(title: 'a')
|
||||||
|
b = Task.create!(title: 'b')
|
||||||
|
c = Task.create!(title: 'c')
|
||||||
|
assert a.first_in_list?
|
||||||
|
refute a.last_in_list?
|
||||||
|
assert c.last_in_list?
|
||||||
|
refute c.first_in_list?
|
||||||
|
refute b.first_in_list?
|
||||||
|
refute b.last_in_list?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_move_to_top_and_move_to_bottom_reposition_and_shift_everyone_between
|
||||||
|
a = Task.create!(title: 'a')
|
||||||
|
b = Task.create!(title: 'b')
|
||||||
|
c = Task.create!(title: 'c')
|
||||||
|
d = Task.create!(title: 'd')
|
||||||
|
|
||||||
|
c.move_to_top
|
||||||
|
assert_equal [1, 2, 3, 4], [c, a, b, d].map { |t| t.reload.list_position }
|
||||||
|
|
||||||
|
a.reload.move_to_bottom
|
||||||
|
assert_equal [1, 2, 3, 4], [c, b, d, a].map { |t| t.reload.list_position }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_insert_at_moves_an_item_to_an_arbitrary_middle_slot
|
||||||
|
a = Task.create!(title: 'a')
|
||||||
|
b = Task.create!(title: 'b')
|
||||||
|
c = Task.create!(title: 'c')
|
||||||
|
d = Task.create!(title: 'd')
|
||||||
|
|
||||||
|
d.insert_at(2)
|
||||||
|
assert_equal [1, 2, 3, 4], [a, d, b, c].map { |t| t.reload.list_position }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_insert_at_on_a_record_that_is_not_persisted_raises
|
||||||
|
task = Task.new(title: 'unsaved')
|
||||||
|
assert_raises(Prism::Orm::RecordNotFound) { task.insert_at(1) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_destroying_an_item_closes_the_gap_for_everyone_below_it
|
||||||
|
a = Task.create!(title: 'a')
|
||||||
|
b = Task.create!(title: 'b')
|
||||||
|
c = Task.create!(title: 'c')
|
||||||
|
b.destroy
|
||||||
|
assert_equal 1, a.reload.list_position
|
||||||
|
assert_equal 2, c.reload.list_position
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_soft_deleting_a_paranoid_item_also_closes_the_gap
|
||||||
|
a = Task.create!(title: 'a')
|
||||||
|
b = Task.create!(title: 'b')
|
||||||
|
c = Task.create!(title: 'c')
|
||||||
|
b.destroy # paranoid: soft-delete, not a real row removal
|
||||||
|
assert b.deleted?
|
||||||
|
assert_equal 1, a.reload.list_position
|
||||||
|
assert_equal 2, c.reload.list_position
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_restoring_a_soft_deleted_item_reappends_it_to_the_bottom_not_its_old_slot
|
||||||
|
a = Task.create!(title: 'a')
|
||||||
|
b = Task.create!(title: 'b')
|
||||||
|
c = Task.create!(title: 'c')
|
||||||
|
b.destroy
|
||||||
|
d = Task.create!(title: 'd')
|
||||||
|
assert_equal [1, 2, 3], [a.reload, c.reload, d.reload].map(&:list_position)
|
||||||
|
|
||||||
|
restored = Task.only_deleted.find_by!(title: 'b')
|
||||||
|
restored.restore
|
||||||
|
assert_equal 4, restored.list_position
|
||||||
|
# nobody else collides with the reappended slot
|
||||||
|
assert_equal [1, 2, 3, 4], [a.reload, c.reload, d.reload, restored.reload].map(&:list_position).sort
|
||||||
|
end
|
||||||
|
|
||||||
Reference in new issue
Block a user