diff --git a/CHANGELOG.md b/CHANGELOG.md index 76c5e04..2132975 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Pagination boundary tests — `describe "pagination"` blocks added to jobs, failed jobs, cache entries, history, and cable message list specs; covers pagination controls appearing at 26+ records, page 2 returning 200, and out-of-range pages returning 200 without error +- `spec/support/request_helpers.rb` — shared `engine_root` let for all request specs; `rails_helper.rb` auto-loads `spec/support/**/*.rb` + ## [0.7.0] - 2026-05-26 ### Added diff --git a/ROADMAP.md b/ROADMAP.md index f4b732e..dab2d6c 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -10,12 +10,8 @@ The path to v1.0.0 is staged: first achieve feature parity with `solid_queue_das > _Make the test suite match the surface area of the engine._ -### Added -- Request specs for every controller action (index, show, create, update, destroy) across all sections -- Service class unit tests (stats aggregation, alert webhook, metrics payload) -- Edge-case coverage: empty states, pagination boundaries, auth rejection, format variants (HTML / Turbo Stream / JSON / CSV) -- Shared request spec helpers extracted to `spec/support/` -- CI matrix coverage target raised to ≥ 90% +### Remaining +- Service class unit tests — `CableStats`, `CacheStats`, `QueueStats`, `CableTimeline`, `CacheSizeStats`, `CacheTimeline` have no specs; `AlertWebhook`, `QueueDepthSparkline`, `ThroughputSparkline` are already covered --- diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index da5676a..40119c2 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -7,6 +7,8 @@ require "rspec/rails" +Dir[File.join(__dir__, "support/**/*.rb")].each { |f| require f } + ActionController::Base.allow_forgery_protection = false ActiveRecord::Schema.verbose = false diff --git a/spec/requests/solid_stack_web/cable_messages_spec.rb b/spec/requests/solid_stack_web/cable_messages_spec.rb index 365b6c6..2cdb1d3 100644 --- a/spec/requests/solid_stack_web/cable_messages_spec.rb +++ b/spec/requests/solid_stack_web/cable_messages_spec.rb @@ -115,4 +115,33 @@ def channel_hash_for(channel) expect(response.body).to include("Clear") end end + + describe "pagination" do + it "shows pagination controls when messages exceed one page" do + 26.times { |i| broadcast("logs", "msg#{i}") } + hash = channel_hash_for("logs") + + get "#{engine_root}/cable/channels/#{hash}" + + expect(response.body).to include("page=2") + end + + it "returns 200 for page 2" do + 26.times { |i| broadcast("logs", "msg#{i}") } + hash = channel_hash_for("logs") + + get "#{engine_root}/cable/channels/#{hash}", params: { page: 2 } + + expect(response).to have_http_status(:ok) + end + + it "returns 200 for an out-of-range page" do + broadcast("logs", "single") + hash = channel_hash_for("logs") + + get "#{engine_root}/cable/channels/#{hash}", params: { page: 999 } + + expect(response).to have_http_status(:ok) + end + end end diff --git a/spec/requests/solid_stack_web/cache_entries_spec.rb b/spec/requests/solid_stack_web/cache_entries_spec.rb index f475e32..b07a4ae 100644 --- a/spec/requests/solid_stack_web/cache_entries_spec.rb +++ b/spec/requests/solid_stack_web/cache_entries_spec.rb @@ -93,4 +93,30 @@ def create_entry(key: "mykey", value: "myval") expect(SolidCache::Entry.count).to eq(0) end end + + describe "pagination" do + it "shows pagination controls when entries exceed one page" do + 26.times { |i| create_entry(key: "key#{i}", value: "v") } + + get "#{engine_root}/cache/entries" + + expect(response.body).to include("page=2") + end + + it "returns 200 for page 2" do + 26.times { |i| create_entry(key: "key#{i}", value: "v") } + + get "#{engine_root}/cache/entries", params: { page: 2 } + + expect(response).to have_http_status(:ok) + end + + it "returns 200 for an out-of-range page" do + create_entry + + get "#{engine_root}/cache/entries", params: { page: 999 } + + expect(response).to have_http_status(:ok) + end + end end diff --git a/spec/requests/solid_stack_web/failed_jobs_spec.rb b/spec/requests/solid_stack_web/failed_jobs_spec.rb index 592f3f7..0c1eda3 100644 --- a/spec/requests/solid_stack_web/failed_jobs_spec.rb +++ b/spec/requests/solid_stack_web/failed_jobs_spec.rb @@ -198,4 +198,30 @@ def create_failed(class_name: "FailingJob", queue_name: "default") expect(SolidQueue::FailedExecution.exists?(execution.id)).to be false end end + + describe "pagination" do + it "shows pagination controls when failed jobs exceed one page" do + 26.times { create_failed } + + get "#{engine_root}/failed_jobs" + + expect(response.body).to include("page=2") + end + + it "returns 200 for page 2" do + 26.times { create_failed } + + get "#{engine_root}/failed_jobs", params: { page: 2 } + + expect(response).to have_http_status(:ok) + end + + it "returns 200 for an out-of-range page" do + create_failed + + get "#{engine_root}/failed_jobs", params: { page: 999 } + + expect(response).to have_http_status(:ok) + end + end end diff --git a/spec/requests/solid_stack_web/history_spec.rb b/spec/requests/solid_stack_web/history_spec.rb index 4368308..f8b378c 100644 --- a/spec/requests/solid_stack_web/history_spec.rb +++ b/spec/requests/solid_stack_web/history_spec.rb @@ -131,4 +131,30 @@ def finished_job(class_name: "TestJob", queue_name: "default", duration: 30, fin expect(rows.first["duration_seconds"]).to eq("12") end end + + describe "pagination" do + it "shows pagination controls when finished jobs exceed one page" do + 26.times { finished_job } + + get "#{engine_root}/history" + + expect(response.body).to include("page=2") + end + + it "returns 200 for page 2" do + 26.times { finished_job } + + get "#{engine_root}/history", params: { page: 2 } + + expect(response).to have_http_status(:ok) + end + + it "returns 200 for an out-of-range page" do + finished_job + + get "#{engine_root}/history", params: { page: 999 } + + expect(response).to have_http_status(:ok) + end + end end diff --git a/spec/requests/solid_stack_web/jobs_spec.rb b/spec/requests/solid_stack_web/jobs_spec.rb index e5f52a0..a9bc2b4 100644 --- a/spec/requests/solid_stack_web/jobs_spec.rb +++ b/spec/requests/solid_stack_web/jobs_spec.rb @@ -413,4 +413,30 @@ def create_ready(class_name: "MyJob", queue_name: "default", priority: 0) expect(response.body).to include("period=24h") end end + + describe "pagination" do + it "shows pagination controls when jobs exceed one page" do + 26.times { create_ready } + + get "#{engine_root}/jobs" + + expect(response.body).to include("page=2") + end + + it "returns 200 for page 2" do + 26.times { create_ready } + + get "#{engine_root}/jobs", params: { page: 2 } + + expect(response).to have_http_status(:ok) + end + + it "returns 200 for an out-of-range page" do + create_ready + + get "#{engine_root}/jobs", params: { page: 999 } + + expect(response).to have_http_status(:ok) + end + end end diff --git a/spec/support/request_helpers.rb b/spec/support/request_helpers.rb new file mode 100644 index 0000000..7cd63ed --- /dev/null +++ b/spec/support/request_helpers.rb @@ -0,0 +1,9 @@ +module RequestHelpers + def self.included(base) + base.let(:engine_root) { "/solid_stack" } + end +end + +RSpec.configure do |config| + config.include RequestHelpers, type: :request +end