Testing Guide
Overview
OpenWatchParty uses a combination of automated tests and manual testing procedures.
Automated Tests
Rust Session Server
cd server
# Run all tests
cargo test
# Run with output
cargo test -- --nocapture
# Run specific test
cargo test test_name
# Run with coverage (requires cargo-tarpaulin)
cargo tarpaulin
Test Categories
Test Type
Description
Unit tests
Individual function tests
Integration tests
Module interaction tests
Example Test
#[cfg(test)]
mod tests {
use super :: * ;
#[test]
fn test_all_ready_empty_room () {
let room = Room {
clients : vec! [],
ready_clients : HashSet :: new (),
.. Default :: default ()
};
assert! ( all_ready ( & room ));
}
#[test]
fn test_all_ready_partial () {
let room = Room {
clients : vec! [ "a" .into (), "b" .into ()],
ready_clients : HashSet :: from ([ "a" .into ()]),
.. Default :: default ()
};
assert! ( ! all_ready ( & room ));
}
}
C# Plugin
cd plugins/jellyfin/OpenWatchParty
# Run tests
dotnet test
# With coverage
dotnet test --collect :"XPlat Code Coverage"
Manual Testing
Test Environment
Start the development environment:
Open Jellyfin in two browser windows/tabs
Log in to both
Test Scenarios
Room Management
Test
Steps
Expected Result
Create room
Click Watch Party > Enter name > Start Room
Room created, you are host
Join room
Click Watch Party > Select room > Join
Joined room, synced to host
Leave room
In room > Leave
Left room, panel shows lobby
Host leaves
Host leaves room
All participants see “Room closed”
Playback Sync
Test
Steps
Expected Result
Play sync
Host plays
All clients start playing
Pause sync
Host pauses
All clients pause
Seek sync
Host seeks to position
All clients seek to same position
Drift correction
Play for 5 minutes
Clients stay within 200ms
Edge Cases
Test
Steps
Expected Result
Rapid seek
Seek multiple times quickly
Only last seek applied
Buffering
Let video buffer mid-play
No false pause sent
Disconnect
Disconnect network briefly
Auto-reconnect when restored
Different quality
Clients use different quality
Sync maintained
Browser Testing
Browser
Status
Notes
Chrome
Primary
Full support
Firefox
Secondary
Full support
Safari
Test
May need WebSocket fixes
Edge
Test
Same as Chrome
Mobile Chrome
Test
Touch interactions
Mobile Safari
Test
iOS-specific issues
Network Testing
Simulate Latency
# Linux (requires tc)
tc qdisc add dev eth0 root netem delay 200ms
# Reset
tc qdisc del dev eth0 root
Test Scenarios
Condition
Test
High latency (500ms+)
Sync should work but feel delayed
Packet loss (5%)
Should recover gracefully
Disconnect/reconnect
Auto-reconnect after 3s
Load Testing
WebSocket Connections
Using websocat:
# Multiple concurrent connections
for i in { 1..100} ; do
websocat -n ws://localhost:3000/ws &
done
Stress Test Script
#!/usr/bin/env python3
import asyncio
import websockets
import json
async def client ( client_id ):
async with websockets . connect ( 'ws://localhost:3000/ws' ) as ws :
# Receive client_hello
await ws . recv ()
# Create room
await ws . send ( json . dumps ({
'type' : 'create_room' ,
'payload' : { 'name' : f 'Room { client_id } ' },
'ts' : 0
}))
# Wait
await asyncio . sleep ( 60 )
async def main ():
tasks = [ client ( i ) for i in range ( 50 )]
await asyncio . gather ( * tasks )
asyncio . run ( main ())
Sync Accuracy
Start playing video with precise timestamp
Record actual playback time from multiple clients
Calculate drift over time
Target: < 200ms drift after 10 minutes
Message Latency
// In browser console
const start = Date . now ();
OSP . ws . send ( JSON . stringify ({ type : ' ping ' , ts : start }));
// Check pong response for round-trip time
Target: < 100ms RTT on local network
Test Data
For testing, use:
Short video clips (1-5 minutes)
Various formats (MP4, MKV)
HLS streams (to test buffering)
Test Users
Create test users in Jellyfin:
testhost - For hosting
testclient1 - For joining
testclient2 - For joining
Continuous Integration
GitHub Actions (Planned)
# .github/workflows/test.yml
name : Test
on : [ push , pull_request ]
jobs :
test-rust :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v3
- uses : actions-rs/toolchain@v1
with :
toolchain : stable
- run : cargo test
working-directory : server
test-csharp :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v3
- uses : actions/setup-dotnet@v3
with :
dotnet-version : ' 9.0'
- run : dotnet test
working-directory : plugins/jellyfin/OpenWatchParty
Debugging Test Failures
Rust Test Failures
# Run with backtrace
RUST_BACKTRACE = 1 cargo test
# Run single test with logging
RUST_LOG = debug cargo test test_name -- --nocapture
JavaScript Issues
Check browser console for errors
Enable debug logging:
OSP . constants . DEBUG = true ;
Network Issues
# Check WebSocket is accessible
curl http://localhost:3000/health
# Test WebSocket connection
wscat -c ws://localhost:3000/ws
Writing New Tests
Test File Location
Component
Location
Rust
server/src/*.rs (inline)
Rust integration
server/tests/
C#
plugins/jellyfin/OpenWatchParty.Tests/
Test Naming
// Rust
#[test]
fn test_function_name_scenario () { }
// Example
#[test]
fn test_all_ready_returns_false_when_not_all_clients_ready () { }
// C#
[ Fact ]
public void MethodName_Scenario_ExpectedResult () { }
// Example
[ Fact ]
public void GetToken_WhenAuthenticated_ReturnsValidToken () { }
Test Coverage Goals
Component
Goal
Rust business logic
80%
C# controllers
70%
JavaScript
Manual testing
Next Steps