5.9 KiB
Station Discovery & Browse Specification
Purpose
Discovery content as the Buscar tab's landing state, active-filter pills,
results counter, clear-all-filters, the Países browser over the verified
/json/countries contract, and a client-side search-sort control. Traceable
to WU5 (relocation), WU6 (Buscar), WU7 (Países + _get transport
extraction).
Requirements
Requirement: Buscar Landing State Shows Discovery Content
Buscar MUST render the existing discovery content (near-you, genres, trending, countries entry point) as its landing state whenever no search query is entered. Entering a query MUST replace that landing state with search results.
Scenario: Empty query shows discovery content
- GIVEN the user opens the Buscar tab with no prior query
- WHEN the screen renders
- THEN near-you, genre, trending, and a Países entry point are visible
Scenario: Entering a query replaces the landing state
- GIVEN the Buscar tab is showing discovery content
- WHEN the user types a non-empty query
- THEN discovery content is replaced by the search-results view
Requirement: Active-Filter Pills and Results Counter
The search-results view MUST show each active filter (country, language, minimum quality) as a removable pill, and MUST show a results counter ("N RESULTADOS").
Scenario: Applying a filter shows a removable pill
- GIVEN the user has an active search
- WHEN they apply a country filter
- THEN a pill labeled with that country and a close (x) affordance appears
- AND the results counter reflects the filtered count
Scenario: Removing a pill re-runs the search without that filter
- GIVEN a country filter pill is active
- WHEN the user taps its close affordance
- THEN the filter is cleared and results/count update accordingly
Requirement: One-Tap Clear-All-Filters on Empty Results
When 1 or more filters are active and the resulting search has zero results, the system MUST offer a single action that clears every active filter at once ("Quitar los N filtros").
Scenario: Two active filters, zero results
- GIVEN country and quality filters are both active and yield 0 results
- WHEN the empty state renders
- THEN a "Quitar los 2 filtros" action is shown
- AND tapping it clears both filters in one action, not one at a time
Requirement: Países Browser Over the Verified Countries Contract
The Países screen (new second-level screen) MUST fetch from
/json/countries (optional substring filter /json/countries/{filter})
and MUST NOT use /json/countrycodes, which is deprecated. It MUST parse
the stationcount field as a string via int.tryParse, never as a
direct int cast. Its request MUST NOT include lastcheckok, since that
parameter is meaningful only for station-listing calls.
Source: Engram reference/radio-browser-countries-endpoint (id 2500),
verified against https://api.radio-browser.info/.
Scenario: Countries list renders with counts
- GIVEN
/json/countriesreturns a list of country objects - WHEN the Países screen loads
- THEN "Tus idiomas" and the full alphabetical list render with each country's parsed station count
Scenario: stationcount arrives as a JSON string (edge case, critical)
- GIVEN a country entry has
"stationcount": "482"(a JSON string, not a number) - WHEN the screen parses and renders that entry
- THEN it displays
482without throwing a type-cast error
Scenario: Countries request omits the station-only filter
- GIVEN the Países screen issues its
/json/countriesrequest - WHEN the outgoing request is inspected
- THEN it does NOT include
lastcheckok
Requirement: Client-Side Search Sort Only
Buscar MUST expose an "Ordenar" control backed exclusively by client-side
ordering (OrdenEmisoras). The system MUST NOT adopt the Radio Browser
server-side order/reverse parameters for this control, because
server-side ordering sorts the full result set before limit is applied
while the app's client-side sort only reorders the page already fetched —
adopting it would silently change which stations users see, not just their
order. Every sort option rendered in the UI MUST map to a real
OrdenEmisoras case; the system MUST NOT render an option that does not
actually sort.
Source: Engram reference/radio-browser-sort-order (id 2505), verified
against https://api.radio-browser.info/.
Scenario: Selecting a sort option reorders the current page only
- GIVEN a set of search results is already fetched
- WHEN the user selects "Ordenar: calidad"
- THEN the currently-displayed page is reordered via
OrdenEmisoras.calidad - AND no new network request with an
orderparameter is issued
Scenario: Every rendered sort option is backed by a real case (regression guard)
- GIVEN the "Ordenar" control's rendered option list
- WHEN each option is checked against
OrdenEmisoras - THEN every option maps to an existing enum case with test coverage; no decorative option that does not sort is rendered
Requirement: Existing Station Calls Unchanged by Transport Extraction
Extracting _get's transport loop (server discovery, host rotation,
bounded retries, User-Agent, timeout, status check, json.decode) into a
shared helper for the Países call MUST NOT change the observable behavior
of the 8 existing ServicioRadio station methods: obtenerPopulares,
obtenerTendencias, buscarPorNombre, buscarPorPais, buscarPorIdioma,
buscarPorTag, buscar, registrarClick.
Scenario: Characterization tests pass unchanged before and after extraction
- GIVEN characterization tests exist for all 8 station methods
- WHEN the transport loop is extracted from
_get - THEN all 8 tests pass identically before and after the extraction
Scenario: Station calls still send lastcheckok
- GIVEN any of the 8 station methods issues a request
- WHEN the outgoing request is inspected
- THEN it still includes
lastcheckok=1, unchanged from before the extraction