docbrown/spec/models/application_record_spec.rb
PJ 6de70e3810
Sort organization members and tag moderators by badge count (#19582)
* show tag moderators in descending badge count order

* show organization users in descending badge count order

* specs & docs for find_each_respecting_scope
2023-06-09 15:30:46 +01:00

128 lines
4.5 KiB
Ruby

require "rails_helper"
# ApplicationRecord is an abstract class, tests will use one of the core models
RSpec.describe ApplicationRecord do
describe ".estimated_count" do
it "does not raise errors if there are no rows" do
expect { User.estimated_count }.not_to raise_error
end
end
describe "#class_name" do
it "is expected to be a string" do
user = User.new
expect(user.class_name).to eq("User")
end
end
describe "#decorate" do
it "decorates an object that has a decorator" do
article = build(:article)
expect(article.decorate).to be_a(ArticleDecorator)
end
it "raises an error if an object has no decorator" do
badge = build(:badge)
expect { badge.decorate }.to raise_error(UninferrableDecoratorError)
end
end
describe "#decorated?" do
it "returns false" do
article = build(:article)
expect(article.decorated?).to be(false)
end
end
describe ".decorate" do
before do
create(:article, approved: true)
end
it "decorates a relation" do
decorated_collection = Article.approved.decorate
expect(decorated_collection.size).to eq(Article.approved.size)
expect(decorated_collection.first).to be_a(ArticleDecorator)
end
end
describe ".with_statement_timeout" do
it "sets the SQL statement timeout to the specified duration" do
original_timeout = described_class.statement_timeout
described_class.with_statement_timeout 1.second do
expect(described_class.statement_timeout).to eq 1.second
described_class.with_statement_timeout 10.seconds do
expect(described_class.statement_timeout).to eq 10.seconds
end
expect(described_class.statement_timeout).to eq 1.second
end
expect(described_class.statement_timeout).to eq original_timeout
end
end
describe "batch querying respecting scope" do
let!(:alice) { create(:user, username: "alice", confirmed_at: 12.hours.ago) }
let!(:bob) { create(:user, username: "bob", confirmed_at: 3.days.ago) }
let!(:charles) { create(:user, username: "charles", confirmed_at: 3.hours.ago) }
let!(:doreen) { create(:user, username: "doreen", confirmed_at: 1.day.ago) }
let!(:esther) { create(:user, username: "esther", confirmed_at: 2.weeks.ago) }
describe ".in_batches_respecting_scope" do
it "fetches records in batches of specified size" do
expect { |block| User.in_batches_respecting_scope(batch_size: 2, &block) }
.to yield_successive_args(
[alice, bob],
[charles, doreen],
[esther],
)
end
it "respects scopes such as WHERE and ORDER" do
scope = User.where("confirmed_at > ?", 2.days.ago).order(username: :desc)
expect { |block| scope.in_batches_respecting_scope(batch_size: 2, &block) }
.to yield_successive_args(
[doreen, charles],
[alice],
)
end
it "handles limit and offset appropriately regardless of batch size" do
scope = User.order(username: :desc).limit(2).offset(2)
expect { |block| scope.in_batches_respecting_scope(batch_size: 10, &block) }
.to yield_successive_args([charles, bob])
end
end
describe ".find_each_respecting_scope" do
it "fetches records in batches" do
allow(User).to receive(:in_batches_respecting_scope).with(batch_size: 2).and_call_original
expect { |block| User.find_each_respecting_scope(batch_size: 2, &block) }
.to yield_successive_args(alice, bob, charles, doreen, esther)
expect(User).to have_received(:in_batches_respecting_scope).once
end
it "respects scopes such as WHERE and ORDER" do
scope = User.where("confirmed_at < ?", 18.hours.ago).order(confirmed_at: :asc)
expect { |block| scope.find_each_respecting_scope(batch_size: 2, &block) }
.to yield_successive_args(esther, bob, doreen)
end
it "returns an enumerator and defers batch querying if called without a block" do
allow(User).to receive(:in_batches_respecting_scope).and_call_original
query = User.order(username: :desc).find_each_respecting_scope
expect(query).to be_an(Enumerator)
expect(User).not_to have_received(:in_batches_respecting_scope)
expect(query.map(&:username)).to contain_exactly("esther", "doreen", "charles", "bob", "alice")
expect(User).to have_received(:in_batches_respecting_scope)
end
end
end
end