From ac7e535986396f2c1357e417a2c92dab620943cb Mon Sep 17 00:00:00 2001 From: DualFroz Date: Sun, 13 Sep 2026 11:44:11 +0200 Subject: [PATCH] test: cover OrmQueryBatchesTest, teardown and OrmQueryCombinatorsTest --- test/test_orm_query_batches.rb | 48 ++++++++++++++++ test/test_orm_query_combinators.rb | 64 ++++++++++++++++++++++ test/test_orm_query_predicates.rb | 88 ++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 test/test_orm_query_batches.rb create mode 100644 test/test_orm_query_combinators.rb create mode 100644 test/test_orm_query_predicates.rb diff --git a/test/test_orm_query_batches.rb b/test/test_orm_query_batches.rb new file mode 100644 index 0000000..d882634 --- /dev/null +++ b/test/test_orm_query_batches.rb @@ -0,0 +1,48 @@ +require 'minitest/autorun' +require 'prism' +require 'tmpdir' + +class OrmQueryBatchesTest < Minitest::Test + def setup + @dir = Dir.mktmpdir('prism-query-batches') + @store = Prism::Orm::Store.new(File.join(@dir, 'test.pstore')) + @store.create_table(:records, %w[id seq]) + record_class = Class.new(Prism::Orm::Model) do + table_name :records + end + record_class.store = @store + Object.const_set(:Rec, record_class) + + 25.times { |i| Rec.create!(seq: i) } + end + + def teardown + FileUtils.remove_entry(@dir) + Object.send(:remove_const, :Rec) if Object.const_defined?(:Rec) + end + + def test_find_each_yields_every_record_once + seen = [] + Rec.order(:seq).find_each(batch_size: 7) { |record| seen << record.seq } + assert_equal (0..24).to_a, seen + end + + def test_find_each_without_block_returns_enumerator + enum = Rec.order(:seq).find_each + assert_kind_of Enumerator, enum + assert_equal 25, enum.to_a.size + end + + def test_find_in_batches_respects_batch_size + batch_sizes = [] + Rec.order(:seq).find_in_batches(batch_size: 10) { |batch| batch_sizes << batch.size } + assert_equal [10, 10, 5], batch_sizes + end + + def test_find_in_batches_default_size_yields_single_batch_for_small_sets + batches = [] + Rec.order(:seq).find_in_batches { |batch| batches << batch } + assert_equal 1, batches.size + assert_equal 25, batches.first.size + end +end diff --git a/test/test_orm_query_combinators.rb b/test/test_orm_query_combinators.rb new file mode 100644 index 0000000..dfbd2a5 --- /dev/null +++ b/test/test_orm_query_combinators.rb @@ -0,0 +1,64 @@ +require 'minitest/autorun' +require 'prism' +require 'tmpdir' + +class OrmQueryCombinatorsTest < Minitest::Test + def setup + @dir = Dir.mktmpdir('prism-query-combinators') + @store = Prism::Orm::Store.new(File.join(@dir, 'test.pstore')) + @store.create_table(:tickets, %w[id title status priority]) + ticket_class = Class.new(Prism::Orm::Model) do + table_name :tickets + end + ticket_class.store = @store + Object.const_set(:Ticket, ticket_class) + + Ticket.create!(title: 'a', status: 'open', priority: 'low') + Ticket.create!(title: 'b', status: 'open', priority: 'high') + Ticket.create!(title: 'c', status: 'closed', priority: 'high') + Ticket.create!(title: 'd', status: 'closed', priority: 'low') + end + + def teardown + FileUtils.remove_entry(@dir) + Object.send(:remove_const, :Ticket) if Object.const_defined?(:Ticket) + end + + def test_not_excludes_matching_rows + titles = Ticket.where(status: 'open').not(priority: 'low').pluck(:title) + assert_equal ['b'], titles + end + + def test_model_level_not_shorthand + titles = Ticket.not(status: 'open').order(:title).pluck(:title) + assert_equal %w[c d], titles + end + + def test_or_combines_two_relations + titles = Ticket.where(status: 'open').or(Ticket.where(priority: 'high')).order(:title).pluck(:title) + assert_equal %w[a b c], titles + end + + def test_or_with_plain_hash + titles = Ticket.where(status: 'closed').or(priority: 'high').order(:title).pluck(:title) + assert_equal %w[b c d], titles + end + + def test_chained_and_or_and_not + titles = Ticket.where(status: 'open').not(priority: 'low').or(Ticket.where(status: 'closed').not(priority: 'high')) + .order(:title).pluck(:title) + assert_equal %w[b d], titles + end + + def test_none_returns_empty_relation_without_touching_store + relation = Ticket.none + assert_equal 0, relation.count + assert_equal [], relation.to_a + refute relation.exists? + end + + def test_where_still_ands_across_chained_calls + titles = Ticket.where(status: 'open').where(priority: 'high').pluck(:title) + assert_equal ['b'], titles + end +end diff --git a/test/test_orm_query_predicates.rb b/test/test_orm_query_predicates.rb new file mode 100644 index 0000000..2a03c5c --- /dev/null +++ b/test/test_orm_query_predicates.rb @@ -0,0 +1,88 @@ +require 'minitest/autorun' +require 'prism' +require 'tmpdir' + +class OrmQueryPredicatesTest < Minitest::Test + def setup + @dir = Dir.mktmpdir('prism-query-predicates') + @store = Prism::Orm::Store.new(File.join(@dir, 'test.pstore')) + @store.create_table(:products, %w[id name price stock]) + product_class = Class.new(Prism::Orm::Model) do + table_name :products + end + product_class.store = @store + Object.const_set(:Product, product_class) + + Product.create!(name: 'Widget', price: 10, stock: 5) + Product.create!(name: 'Gadget', price: 25, stock: 0) + Product.create!(name: 'Gizmo', price: 40, stock: 12) + Product.create!(name: nil, price: 15, stock: 3) + end + + def teardown + FileUtils.remove_entry(@dir) + Object.send(:remove_const, :Product) if Object.const_defined?(:Product) + end + + def test_gt_operator + assert_equal %w[Gadget Gizmo], Product.where(price: { gt: 15 }).order(:name).pluck(:name) + end + + def test_gte_operator + assert_equal %w[Gadget Gizmo], Product.where(price: { gte: 25 }).order(:name).pluck(:name) + end + + def test_lt_operator + assert_equal ['Widget'], Product.where(price: { lt: 15 }).pluck(:name) + end + + def test_lte_operator + assert_equal %w[Widget], Product.where(price: { lte: 10 }).pluck(:name) + end + + def test_ne_operator + result = Product.where(stock: { ne: 0 }).count + assert_equal 3, result + end + + def test_combined_operators_in_same_hash + matches = Product.where(price: { gt: 15, lt: 40 }).order(:name).pluck(:name) + assert_equal %w[Gadget], matches + end + + def test_in_operator + assert_equal %w[Gadget Widget], Product.where(price: { in: [10, 25] }).order(:name).pluck(:name) + end + + def test_not_in_operator + assert_equal %w[Gizmo], Product.where(price: { not_in: [10, 25, 15] }).pluck(:name) + end + + def test_like_operator_supports_percent_wildcard + assert_equal %w[Gadget Gizmo], Product.where(name: { like: 'g%' }).order(:name).pluck(:name) + end + + def test_like_operator_is_case_insensitive + assert_equal %w[Widget], Product.where(name: { like: 'WIDGET' }).pluck(:name) + end + + def test_not_like_operator + names = Product.where(name: { not_like: 'g%' }).pluck(:name) + assert_equal %w[Widget], names + end + + def test_is_null_true + assert_equal 1, Product.where(name: { is_null: true }).count + end + + def test_is_null_false + assert_equal 3, Product.where(name: { is_null: false }).count + end + + def test_unknown_operator_raises + error = assert_raises(Prism::Orm::Query::Predicates::UnknownOperator) do + Product.where(price: { bogus: 1 }).to_a + end + assert_match(/bogus/, error.message) + end +end