test(docs): RSpec + Capybara + Playwright system suite for the dogfood site#51
Merged
Conversation
…d site
The docs-kit gem's CI never exercised the /docs app, so the og:image 404
(a logical asset path that only breaks through a booted app's asset pipeline)
shipped with zero coverage. This adds a real browser suite to the dogfood site,
matching the stack the sibling gems use (cosmos/phlex-reactive/pgbus): rspec-rails
+ capybara + capybara-playwright-driver, chromium via Playwright.
## What's covered
- spec/system/seo_meta_tags_spec.rb — the regression guard for the 404: visit /,
assert og:image is a /assets URL, and that VISITING it returns 200 (a shared
link's image must actually load). Renders through the real server + Propshaft.
- spec/system/docs_chrome_spec.rb — landing hero, a doc page (masthead + Rouge
code), active sidebar link (server-rendered), sidebar navigation.
- spec/system/theme_persistence_spec.rb — theme applies in place + survives
navigation (docs-nav + localStorage, no flash).
- spec/requests/progressive_enhancement_spec.rb — the JS-off invariant: complete
HTML document, sidebar <details open>, active nav server-side, the .md twin,
llms.txt.
## Setup (matches the sibling repos)
- Gemfile: rspec-rails, capybara + capybara-playwright-driver (require: false),
rubocop-capybara/rspec. package.json: playwright. bin/rspec binstub.
- spec/spec_helper.rb, rails_helper.rb (DB-less — use_active_record = false),
system_helper.rb; spec/system/support/{playwright,capybara}_setup.rb
(Puma server, chromium, HEADLESS env, viewport matrix with a desktop_only skip).
- spec/support/assets.rb precompiles once before a system/request run, so
image_url (Propshaft Static resolver) resolves og:image — mirrors deploy-time.
- Replaces the throwaway minitest test/ from the previous fix.
## CI
- docs/config/ci.rb gains a "Test: RSpec" step (bin/ci).
- .github/workflows/ci.yml gains a docs-site job: bundle in docs/, setup-bun,
cache + install Playwright chromium, run rspec. BUNDLE_FROZEN=false (the
path-gem digest changes every commit). Commits docs/Gemfile.lock for
reproducible installs (un-ignored — it's a real app, like phlex-reactive/docs).
## Verification
- [x] docs: bundle exec rspec — 15 examples, 0 failures (from a clean asset state)
- [x] docs: responsive matrix — desktop 10, mobile 8 (desktop_only skipped)
- [x] docs: bin/rubocop — 34 files, no offenses
- [x] gem: bundle exec rake — 714 examples, 0 failures, no offenses (untouched)
Refs #48
Claude-Session: https://claude.ai/code/session_01FPQb6z3YwcKRMbvoJhdxnX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The gem's CI never exercised the
/docsapp, so theog:image404 shipped with zero coverage — it was a bug that only manifests through a booted app's asset pipeline (a logicalog_imagepath resolving to the served, digested/assetsURL), which no isolated component spec can reach. This gives the dogfood site a real browser suite so that class of regression can't ship again.Matches the stack you use everywhere else (cosmos / phlex-reactive / pgbus): RSpec + Capybara + Playwright (chromium). Replaces the throwaway minitest test from the fix PR.
What's covered
System specs (real browser + Puma + Propshaft):
seo_meta_tags_spec.rb— the 404 regression guard: visit/, assertog:imageis a/assetsURL, and that visiting it returns 200 (a shared link's image must actually load). Also og/twitter parity + per-page description.docs_chrome_spec.rb— landing hero, a doc page (masthead + Rouge code block), active sidebar link, sidebar navigation.theme_persistence_spec.rb— theme applies in place and survives navigation (docs-nav + localStorage, no flash).Request specs (no browser — the JS-off invariant):
progressive_enhancement_spec.rb— complete HTML document, sidebar<details open>, server-side active nav, the.mdtwin,llms.txt.Setup (mirrors the sibling repos)
rspec-rails,capybara+capybara-playwright-driver(require: false),rubocop-capybara/rubocop-rspec. package.json:playwright.bin/rspecbinstub.spec/spec_helper.rb,rails_helper.rb(DB-less —use_active_record = false),system_helper.rb;spec/system/support/{playwright,capybara}_setup.rb— Puma server, chromium,HEADLESSenv, a viewport matrix (CAPYBARA_SCREEN) with a:desktop_onlyskip for the always-open-drawer sidebar specs.spec/support/assets.rbprecompiles once before a system/request run, soimage_url(Propshaft'sStaticresolver) resolvesog:image— mirroring the deploy-timeassets:precompilecondition, so the suite is self-sufficient.CI
docs/config/ci.rbgains aTest: RSpecstep (sobin/ciruns it)..github/workflows/ci.ymlgains a docs-site job: bundle indocs/,setup-bun, cache + install Playwright chromium, runrspec.BUNDLE_FROZEN: "false"(thepath: ".."gemspec digest changes every commit). Commitsdocs/Gemfile.lockfor reproducible installs — un-ignored, since it's a real deployable app (same asphlex-reactive/docs).Verification
docs:bundle exec rspec→ 15 examples, 0 failures from a clean asset state (CI parity).docs: responsive matrix → desktop 10, mobile 8 (:desktop_onlyskipped).docs:bin/rubocop→ 34 files, no offenses.gem:bundle exec rake→ 714 examples, 0 failures, rubocop clean (untouched).Refs #48.
https://claude.ai/code/session_01FPQb6z3YwcKRMbvoJhdxnX