System Tests - Turbo & Stimulus Integration
Created: December 2, 2025 Status: ✅ Test Suite Created
🎯 Purpose
Section titled “🎯 Purpose”This test suite verifies that Turbo Drive navigation and Stimulus controllers work correctly together. These tests specifically target race conditions and integration issues that can occur when:
- Turbo caches pages and restores them from cache
- Stimulus controllers reconnect after cache restoration
- Event listeners accumulate due to improper cleanup
- Bootstrap components interfere with Turbo’s lifecycle
🔧 Setup
Section titled “🔧 Setup”Install Playwright
Section titled “Install Playwright”Playwright provides fast, reliable JavaScript testing:
./scripts/setup_playwrightThis will:
- Install the
capybara-playwright-drivergem - Download Chromium browser
- Configure Capybara to use Playwright
📁 Test Files
Section titled “📁 Test Files”test/system/turbo_navigation_test.rb
Section titled “test/system/turbo_navigation_test.rb”Tests for Bootstrap dropdown and collapse components after Turbo navigation:
| Test | Description |
|---|---|
desktop dropdown menu works after Turbo navigation | Verifies dropdowns expand after clicking through Turbo links |
dropdown menu works after navigating back with browser history | Tests Turbo cache restoration |
multiple dropdowns work after multiple Turbo navigations | Stress test for repeated navigation |
mobile menu collapse works after Turbo navigation | Tests offcanvas/collapse on mobile |
test/system/stimulus_controller_race_condition_test.rb
Section titled “test/system/stimulus_controller_race_condition_test.rb”Tests for Stimulus controller race conditions:
| Test | Description |
|---|---|
quantity increment fires exactly once after Turbo navigation | Detects double-firing bug |
quantity decrement fires exactly once after Turbo navigation | Same for decrement |
rapid clicking doesn't cause quantity drift | Tests rapid click handling |
quantity controller works correctly after multiple Turbo navigations | Tests back/forward navigation |
add to cart fires exactly once after Turbo navigation | Cart controller race condition |
add to cart button becomes disabled during processing | UI locking test |
double clicking add to cart only adds once | Double-click protection |
stimulus controllers are initialized exactly once | Lazy loader race condition |
controllers reconnect properly after Turbo cache restoration | Cache restoration test |
🚀 Running Tests
Section titled “🚀 Running Tests”Run All System Tests
Section titled “Run All System Tests”bundle exec rails test:systemRun Specific Test File
Section titled “Run Specific Test File”bundle exec rails test test/system/turbo_navigation_test.rbbundle exec rails test test/system/stimulus_controller_race_condition_test.rbRun Single Test
Section titled “Run Single Test”bundle exec rails test test/system/turbo_navigation_test.rb -n "test_desktop_dropdown_menu_works_after_Turbo_navigation"Debugging Options
Section titled “Debugging Options”# Run with visible browser (headful mode)HEADFUL=1 bundle exec rails test:system
# Run with Selenium instead of PlaywrightUSE_SELENIUM=1 bundle exec rails test:system
# Run with specific test seedSEED=12345 bundle exec rails test:system🐛 Common Issues
Section titled “🐛 Common Issues”Test Fails: “Dropdown didn’t expand”
Section titled “Test Fails: “Dropdown didn’t expand””Symptom: Dropdown menu doesn’t show after clicking toggle
Cause: Bootstrap’s data-api wasn’t properly cleaned up before Turbo cached the page
Fix: Ensure turbo:before-cache event disposes Bootstrap instances:
document.addEventListener('turbo:before-cache', () => { document.querySelectorAll('[data-bs-toggle="dropdown"]').forEach(el => { const instance = window.bootstrap.Dropdown.getInstance(el); if (instance) { instance.hide(); instance.dispose(); } });});Test Fails: “Quantity increased by 2 instead of 1”
Section titled “Test Fails: “Quantity increased by 2 instead of 1””Symptom: Clicking increment once adds 2+ to quantity
Cause: Event listener firing multiple times due to:
- Missing
event.stopPropagation() - Controller not properly cleaned up
- Lazy loader initializing controller twice
Fix: Ensure controller uses stopPropagation and proper cleanup:
increment(event) { event.stopPropagation() event.preventDefault() // ... rest of method}Test Fails: “Controller initialized twice”
Section titled “Test Fails: “Controller initialized twice””Symptom: Multiple controller instances on same element
Cause: Dataset guards like element.dataset.controllerConnected break Turbo cache
Fix: Remove dataset guards - Stimulus handles instance management:
// ❌ BADconnect() { if (this.element.dataset.connected === 'true') return; this.element.dataset.connected = 'true';}
// ✅ GOODconnect() { // Just initialize - Stimulus manages instances}📊 Test Helper Methods
Section titled “📊 Test Helper Methods”The ApplicationSystemTestCase provides these helpers:
| Method | Description |
|---|---|
wait_for_turbo | Waits for Turbo navigation to complete |
wait_for_stimulus_controller(name) | Waits for controller to connect |
get_quantity_value | Gets current quantity input value |
turbo_visit(path) | Visit with Turbo wait |
turbo_click(locator) | Click with Turbo wait |
🔍 Debugging Tips
Section titled “🔍 Debugging Tips”1. Run with visible browser
Section titled “1. Run with visible browser”HEADFUL=1 bundle exec rails test test/system/turbo_navigation_test.rb2. Add debugging pauses
Section titled “2. Add debugging pauses”test "debugging example" do visit "/en-US/floor-heating/underlayment"
# Pause to inspect binding.pry # or sleep 30 # gives you 30 seconds to inspectend3. Check browser console
Section titled “3. Check browser console”test "check console" do visit "/page"
# Get console messages messages = page.driver.browser.logs.get(:browser) puts messages.map(&:message)end4. Take screenshots
Section titled “4. Take screenshots”test "screenshot example" do visit "/page" save_screenshot("debug_screenshot.png")end✅ CI/CD Integration
Section titled “✅ CI/CD Integration”Add to your CI workflow:
system_tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Install Playwright run: npx playwright install chromium --with-deps
- name: Run system tests run: bundle exec rails test:system📚 Related Documentation
Section titled “📚 Related Documentation”- Stimulus Controllers - Controller documentation
- Skills Index - Coding conventions by area
- Turbo Documentation - Official Turbo docs
- Stimulus Documentation - Official Stimulus docs
🧪 Test Coverage Goals
Section titled “🧪 Test Coverage Goals”| Area | Tests | Status |
|---|---|---|
| Dropdown menus | 4 | ✅ Created |
| Mobile collapse | 1 | ✅ Created |
| Quantity controller | 4 | ✅ Created |
| Cart controller | 3 | ✅ Created |
| Lazy loader | 2 | ✅ Created |
Total: 14 tests covering the most critical Turbo/Stimulus integration points.
Created: December 2, 2025 Test Files: 2 Test Cases: 14 Framework: Minitest + Capybara + Playwright