Files

8.8 KiB

Test Plan: UX & API Verification

Scope

Test every block-related API endpoint and the UI's interaction with it. Covers both the React SPA at pedal.local and the REST/WebSocket APIs.


1. API Health & Baseline

# Test Method Path Expected Result
1.1 State endpoint GET /api/state 200 — returns current preset, bypass, volume, routing
1.2 Preset list GET /api/presets 200 — Bank 0 with 4 slots (2 presets, 2 null)
1.3 Models list GET /api/models 200 — both .nam files visible, loaded states
1.4 Profiles GET /api/audio/profiles 200 — standard + low listed
1.5 Profile detail GET /api/audio/profile 200 — period=256, jack_running=true

2. Block Toggle (PATCH /api/blocks)

Core bug: previously enabled changed but bypass stayed true, so blocks remained skipped.

# Test Payload Expected Result
2.1 Enable a disabled block {"id": "nam_amp", "enabled": true} bypass: false returned
2.2 Disable an enabled block {"id": "nam_amp", "enabled": false} bypass: true returned
2.3 Toggle enabled→disabled GET state before & after Chain shows block with enabled=false, bypass=true
2.4 Toggle disabled→enabled GET state before & after Chain shows block with enabled=true, bypass=false
2.5 Toggle nonexistent block ID {"id": "phaser", "enabled": true} 404 — "Block 'phaser' not found"
2.6 Missing ID field {"enabled": true} 400 — "Missing 'id' or 'enabled'"
2.7 Missing enabled field {"id": "nam_amp"} 400 — "Missing 'id' or 'enabled'"
2.8 Toggle and confirm audio Toggle off → play guitar → toggle on → play guitar Audio is muted when bypassed, flows when not

3. Block Param Update (PATCH /api/block)

# Test Payload Expected Result
3.1 Update volume param {"id": "nam_amp", "level": 0.5} params.level == 0.5 returned
3.2 Update with max value {"id": "nam_amp", "level": 1.0} Accepted, no clipping
3.3 Update with zero value {"id": "nam_amp", "level": 0.0} Accepted (mute)
3.4 Update nonexistent block {"id": "flanger", "rate": 0.5} 404
3.5 Update multiple params {"id": "nam_amp", "level": 0.7, "some_custom": 0.3} Both params stored
3.6 Readback after save GET preset → confirm params persisted Matches last write

4. Preset CRUD

# Test Method Path/Payload Expected Result
4.1 Get preset 0 GET /api/presets/0/0 200 — Fender Deluxe Reverb Clean
4.2 Get preset 1 GET /api/presets/0/1 200 — Marshall JCM 900 Dirty
4.3 Get empty slot GET /api/presets/0/2 404 — "Preset not found"
4.4 Activate preset 0 POST /api/presets/0/0/activate 200, preset == "Fender Deluxe Reverb Clean"
4.5 Activate preset 1 POST /api/presets/0/1/activate 200, preset == "Marshall JCM 900 Dirty"
4.6 Create preset in slot 2 PUT /api/presets/0/2 with nam_amp chain 200
4.7 Delete preset in slot 2 DELETE /api/presets/0/2 200 — slot returns to null
4.8 Save preset with IR + NAM PUT block with ir_file_path + nam_model_path Both saved
4.9 Cross-channel isolation GET /api/presets?channel=bass Returns bass bank, not guitar

5. Audio Profile Switching

# Test Payload Expected Result
5.1 Switch to low latency {"profile": "low"} 200, period: 64, restarted: true
5.2 Verify JACK restarted GET /api/audio/profile period == 64, jack_running == true
5.3 Switch back to standard {"profile": "standard"} 200, period: 256, restarted: true
5.4 Verify JACK restarted GET /api/audio/profile period == 256, jack_running == true
5.5 Audio still flows after switch Play guitar No crackles, no silence
5.6 Switch to same profile {"profile": "standard"} restarted: false
5.7 Invalid profile {"profile": "extreme"} 400 — unknown profile
5.8 Xrun count not null GET /api/audio/profile xrun_count is int or null (not error)

6. Volume & Bypass (Pipeline level)

# Test Method/Payload Expected Result
6.1 Set volume PUT /api/volume {"volume": 0.5} volume: 0.5 returned
6.2 Volume clamping PUT /api/volume {"volume": 2.0} volume: 1.0 (clamped)
6.3 Volume clamping low PUT /api/volume {"volume": -1.0} volume: 0.0 (clamped)
6.4 Bypass toggle POST /api/bypass {"bypass": true} bypass: true
6.5 Bypass toggle off POST /api/bypass {"bypass": false} bypass: false
6.6 Bypass flip POST /api/bypass (no body) bypass toggles from current state
6.7 Bypass + audio Toggle bypass ON → play guitar Bypassed: clean DI signal, no FX
6.8 Bypass + audio Toggle bypass OFF → play guitar Active: NAM model processing audible
6.9 POST alias at /api/bypass/toggle POST /api/bypass/toggle {"bypass": true} Same as 6.4

7. WebSocket Real-Time Updates

# Test Action Expected Result
7.1 Connect WS wscat -c ws://pedal.local/ws Receives {"type": "connected", "state": {...}}
7.2 Ping/pong Send {"type": "ping"} Response {"type": "pong"}
7.3 Block toggle broadcast Toggle block via PATCH /api/blocks WS message {"type": "block_toggled", ...}
7.4 Preset change broadcast Activate preset via API WS message {"type": "preset_changed", ...}
7.5 Bypass broadcast Toggle bypass WS message {"type": "bypass_changed", ...}
7.6 Volume change broadcast Set volume WS message {"type": "volume_changed", ...}
7.7 Audio profile broadcast Switch profile WS message {"type": "audio_profile_changed", ...}

8. UI Visual Block Tests (Browser)

# Test Action Expected Result
8.1 Page loads Navigate to http://pedal.local/ React SPA renders, block chain visible
8.2 NAM block visible Check the block chain "nam_amp" tile shown with correct icon
8.3 Block label Read tile text Shows "nam_amp" or friendly name
8.4 Toggle block ON/OFF Click the block's power icon Block appears enabled/disabled visually
8.5 State persists on refresh Toggle OFF → F5 → check Block still shows OFF
8.6 Reverb/delay blocks render Check all FX types All known FX types have unique icons
8.7 Empty slot display Preset with empty chain Shows "no blocks" or empty chain area
8.8 Block reorder (if supported) Drag block Chain updates after drop
8.9 URL root works GET / Returns React SPA (not 404 or redirect)

9. Edge Cases & Robustness

# Test Action Expected Result
9.1 Missing preset directory Delete ~/.pedal/presets, restart Pedal boots, creates one empty stub
9.2 Missing models directory Remove .nam files /api/models returns [], preset fails gracefully
9.3 Corrupt preset JSON Inject bad JSON into preset_0.json API returns 500, pedal continues running
9.4 Web server restart systemctl restart pi-multifx-pedal 30s max downtime, then all endpoints respond
9.5 Concurrent API calls Fire 10 rapid toggle requests All return 200, final state is deterministic
9.6 JACK not running Kill jackd mid-session Audio stops, API still responds, JACK restarts on next profile switch
9.7 Rate-limited toggle Toggle block on/off 50 times No memory leak, state remains consistent
9.8 SD card at 95%+ Fill disk to near-capacity API still responds (read-only ops work)

10. Channel Isolation (if applicable)

# Test Action Expected Result
10.1 Guitar state doesn't affect bass Set guitar volume 0.0, check bass Bass volume unchanged
10.2 Dual-mono routing POST /api/channel-mode {"channel_mode": "dual-mono"} 200, mode switched
10.3 Stereo mode POST /api/channel-mode {"channel_mode": "stereo"} 200, unified state

Test Execution

Run in order. Mark each cell:

  • — passes
  • — fails (log issue + fix before moving on)
  • ⚠️ — non-critical/optional (label reason)
  • ⏭️ — skipped (label why)

For curl tests, use this template:

curl -sv http://pedal.local/api/presets | python3 -m json.tool

For WS tests:

# Connect, wait, then send toggle commands in another terminal
wscat -c ws://pedal.local/ws