8.0 KiB
MODIFIED Requirements
Requirement: Time-series chart fixed to the range
Edition: CE. The time-series chart SHALL render the given series between from and to in the given timezone with
granularity buckets; the x-axis never extends beyond the range nor ticks closer than the unit of its labels, wheel and
drag scroll the page, and no zoom component is enabled. It uses a shared tooltip keyed by x across the charts of a
page, 2 px lines, one y-axis per chart, and the shared formatters for bytes, bitrates, durations and percentages.
Scenario: Wheel over a chart
- GIVEN a chart in the page
- WHEN the user scrolls the mouse wheel over it
- THEN the page scrolls and the chart range is unchanged
Scenario: Sparse data
- GIVEN buckets exist only for half of the range
- WHEN the chart renders
- THEN the x-axis spans
fromtotoand missing buckets show gaps, not a shortened axis
Scenario: Labels of a short range
- GIVEN a chart from 10:06:20 to 10:09:50 with one-minute buckets
- WHEN it renders
- THEN the x-axis labels read whole minutes, each one once (
10:07,10:08,10:09), and a range of several days labelledMM-ddticks at most once a day
Scenario: Integer values
- GIVEN a series whose values are all integers, such as active participants 2, 3 and 2
- WHEN the chart renders
- THEN the y-axis ticks are whole numbers, never 0.5 or 2.5, and a chart holding a fractional value keeps fractional ticks
Scenario: Last step of a step series
- GIVEN a step series whose last bucket starts at 10:06 with the value 1, in a range ending at 10:06:55
- WHEN the chart renders
- THEN the line holds 1 from 10:06 to 10:06:55 instead of ending at 10:06
Requirement: Empty, skeleton and error states
Edition: CE. Empty state SHALL show icon, title, hint and up to two actions ("Clear filters", "Widen range"); skeletons match the height of what they replace, stay invisible for their first 300 ms and render only until the first response of what they replace; the error notice shows the message, a Retry action and the request id, inline in a card or at page level.
Scenario: No rooms match
- GIVEN a filtered list returns no rows
- WHEN the empty state renders
- THEN it reads "No rooms match" with the hint "Change the filters or widen the time range.", offers "Clear filters" and "Widen range", and the layout height does not jump
Scenario: Fast first response
- GIVEN a page whose first response arrives 120 ms after it opens
- WHEN the page loads
- THEN no skeleton bar is painted, the space of what it replaces is kept and the content appears without a layout jump
Scenario: Slow first response
- GIVEN a page whose first response takes 2 s
- WHEN the page loads
- THEN the skeleton becomes visible 300 ms after the page opened and the content replaces it when the response arrives
Requirement: Global search
Edition: CE. The global search SHALL debounce input and send no request below 2 characters, showing the hint "Type at
least 2 characters". An exact ID (RM_, PA_, EG_, IN_, TR_ prefix) shows "Open " first; Enter
opens that detail route (locked in CE) keeping the current range. Other text shows grouped prefix results (rooms,
participants, egress, ingress; up to five each) with "See all in …" links to the list filtered by q.
Scenario: Exact SID
- GIVEN the user types
PA_x1y2with the rangefrom=now-6h&to=now&tz=UTC - WHEN the results panel opens and the user presses Enter
- THEN its first option reads "Open participant PA_x1y2", the application navigates to
/participants/PA_x1y2, and the Participants breadcrumb links to/participants?from=now-6h&to=now&tz=UTC
Scenario: Exact track ID
- GIVEN the user types
TR_a2b3 - WHEN the results panel opens and the user presses Enter
- THEN its first option reads "Open track TR_a2b3" and the application navigates to
/tracks/TR_a2b3
Scenario: Prefix search
- GIVEN the user types
dem - WHEN results arrive
- THEN rooms starting with "dem" are listed under Rooms with "See all in Rooms" linking to
/rooms?q=dem
Scenario: One character
- GIVEN the user types
d - WHEN the debounce elapses
- THEN no search request is sent and the hint reads "Type at least 2 characters"
Scenario: Clear the search
- GIVEN the global search holding
demwith its results open - WHEN the user activates the "Clear search" button
- THEN the box is empty, the results close, the focus stays in the box and the button disappears
Scenario: Keyboard, placeholder and clear button
- WHEN the global search renders at any header width
- THEN it is keyboard navigable, its placeholder shows whole, without truncation, and while it holds text a clear button empties it and closes the results
Requirement: Formatters
Edition: CE. Shared formatters SHALL render numbers with Intl.NumberFormat('en'), percentages with one decimal and a
space before the sign ("96.4 %", donut labels included), bytes in decimal units with three significant digits and
durations as 850 ms, 42 s, 12 m 05 s, 1 h 02 m, 3 d 4 h, rounded to the smallest unit shown; timestamps
SHALL read as the timestamp format scenario states.
Scenario: Bytes and duration
- GIVEN 12345678 bytes and 3725000 ms
- WHEN formatted
- THEN they read "12.3 MB" and "1 h 02 m"
Scenario: Rounded durations
- GIVEN durations of 2 700 ms, 59 600 ms and 3 569 600 ms
- WHEN formatted
- THEN they read "3 s", "1 m 00 s" and "59 m 30 s"
Scenario: Percent in a donut
- GIVEN a connection success ratio of 0.9643 and a donut slice of 0.25
- WHEN they are shown
- THEN they read "96.4 %" and "25.0 %"
Scenario: Timestamp format
- WHEN a timestamp is formatted
- THEN it reads
2026-10-13 12:31:05(date omitted inside the current day of a 24 h range) with aUTCsuffix whentz=UTC
Requirement: Enum labels
Edition: CE. Every enum value outside a status badge SHALL show its friendly sentence-case label, in kind badges,
chart categories and filters: egress type, SDK, OS, browser, connection type and participant kind; the browser key
none reads "No browser". A value without a label shows the raw value, and an OS string a client reported reads as
its family label when it names one. Status badges keep their lowercase words.
Scenario: Chart category and filter
- GIVEN egresses of type
room_composite - WHEN the egress type breakdown and the Type filter render
- THEN both read "Room composite"
Scenario: Browser keys
- GIVEN a browser breakdown with the keys
chrome,noneandother - WHEN its donut renders
- THEN the slices read "Chrome", "No browser" and "Other"
Scenario: Reported OS
- GIVEN the client OS strings
linux,Linux,macosandChrome OS - WHEN they are shown through the shared OS label
- THEN they read "Linux", "Linux", "macOS" and "Chrome OS"
Requirement: Live durations
Edition: CE. Every duration of something still running SHALL count up live from its start between refreshes, in whole elapsed units and ignoring any stored duration it carries; a total that includes a running part adds that part's elapsed time. An ended item shows its stored duration, or its end minus its start without one, and an item with neither a stored duration nor the times to compute one shows "—".
Scenario: Running total
- GIVEN an ingress with a stored total duration of 1 h and a session publishing for 5 minutes
- WHEN its total duration renders
- THEN it reads "1 h 05 m" and keeps counting while the session runs
Scenario: Running and then ended
- GIVEN an egress active for 2 700 ms
- WHEN its duration renders
- THEN it reads "2 s", and once the egress ends with a stored duration of 2 700 ms it reads "3 s"
Scenario: Nothing to compute
- GIVEN a row with no stored duration and no start time
- WHEN it renders
- THEN its duration reads "—"