Act on the screen-by-screen review: 17 findings
All checks were successful
Build TV app / build (push) Successful in 43s
All checks were successful
Build TV app / build (push) Successful in 43s
Defects. "Kopplung zurücksetzen" now asks first, naming how many phones would have to scan again — one stray OK used to wipe a working pairing, and the settings put the focus right on it: entering the screen landed on the gear, one press down jumped into the right column onto that very action, and every further press down did nothing. Focus now starts on the first row of the left column. 1. FC Köln was labelled "EFC". An unreachable source used to look like an evening without programmes — cached list, empty EPG, club menus counting down to zero — so both repositories now record when they last came through, and the top bar says "Server nicht erreichbar · Stand 14:46". The field labels on "Erweitert" sat on the outline with the border running through them; they sit above their field now. Polish. The app opens on the channel list — on the channel last watched, which survives a restart — instead of the settings gear. Rows without EPG fill their empty half with the channel's group. The club chip says "ab 15:06" like the row next to it, the club menu carries the club's name instead of "FCSP", and a fixture title is shortened to the fixture, so "Pokal: Nordstadt - FC St. P…" became "Nordstadt - FC St. Pauli". The settings are three columns and no longer scroll (CONTEXT.md's ten-foot rule). Features. Favourites work for a plain M3U source too, stored on the device and mirrored to the phone; they used to exist only with a Dispatcharr login. The channel keys jump the list by initial letter, left and right jump a division in the club picker, and right on a channel opens its day plan — the EPG beyond now/next, which was parsed all along and never shown. When a club match starts elsewhere the player offers to switch. The remote asked for a code "unten auf dem TV-Bildschirm" where none was; the welcome screen shows it now and the wording points at where it is. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,9 +13,17 @@ p = argparse.ArgumentParser()
|
||||
p.add_argument("--out", default=os.path.dirname(os.path.abspath(__file__)))
|
||||
p.add_argument("--kickoff-in", type=int, default=18,
|
||||
help="minutes until the club match starts")
|
||||
p.add_argument("--now", default=None,
|
||||
help="base time as YYYY-mm-ddTHH:MM:SS; defaults to this "
|
||||
"machine's clock. An emulator restored from a snapshot "
|
||||
"runs on the clock it was saved with, so pass its time "
|
||||
"here or every programme lands in the wrong hour")
|
||||
args = p.parse_args()
|
||||
|
||||
now = datetime.datetime.now().astimezone()
|
||||
if args.now:
|
||||
now = datetime.datetime.strptime(args.now, "%Y-%m-%dT%H:%M:%S").astimezone()
|
||||
else:
|
||||
now = datetime.datetime.now().astimezone()
|
||||
|
||||
|
||||
def fmt(dt):
|
||||
|
||||
@@ -56,7 +56,12 @@ step "Emulator starten"
|
||||
"$HELPERS/emulator.sh" start | tee -a "$LOG"
|
||||
|
||||
step "Demo-Quelle bereitstellen"
|
||||
python3 "$ROOT/tests/demo/make-demo-data.py" >>"$LOG" 2>&1 || fail "Demo-Daten fehlgeschlagen"
|
||||
# The emulator restores its snapshot with the clock frozen at save time, so
|
||||
# the demo programme has to be built around *its* idea of now, not ours.
|
||||
EMU_NOW="$("$ADB" -s "$SERIAL" shell date +%Y-%m-%dT%H:%M:%S | tr -d '\r')"
|
||||
echo " Emulator-Uhr: $EMU_NOW" | tee -a "$LOG"
|
||||
python3 "$ROOT/tests/demo/make-demo-data.py" --now "$EMU_NOW" >>"$LOG" 2>&1 ||
|
||||
fail "Demo-Daten fehlgeschlagen"
|
||||
# The emulator reaches the host at 10.0.2.2, which is the address baked into
|
||||
# the demo playlist.
|
||||
# A leftover server from an earlier run happily answers on this port while
|
||||
|
||||
59
tests/unit/FixtureTest.kt
Normal file
59
tests/unit/FixtureTest.kt
Normal file
@@ -0,0 +1,59 @@
|
||||
package dev.castarr.tv.data
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Test
|
||||
|
||||
class FixtureTest {
|
||||
|
||||
@Test
|
||||
fun `competition prefix and round suffix fall away`() {
|
||||
assertEquals(
|
||||
"Nordstadt - FC St. Pauli",
|
||||
TeamFilters.fixture("Pokal: Nordstadt - FC St. Pauli, 1. Runde"),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a bare pairing survives unchanged`() {
|
||||
assertEquals(
|
||||
"FC Bayern München - Borussia Dortmund",
|
||||
TeamFilters.fixture("FC Bayern München - Borussia Dortmund"),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `en dash and vs count as separators`() {
|
||||
assertEquals("Schalke - HSV", TeamFilters.fixture("2. Liga: Schalke – HSV"))
|
||||
assertEquals("Kiel - Rostock", TeamFilters.fixture("Kiel vs. Rostock"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `trailing channel detail is dropped`() {
|
||||
assertEquals(
|
||||
"Werder - Union Berlin",
|
||||
TeamFilters.fixture("Bundesliga: Werder - Union Berlin | live"),
|
||||
)
|
||||
}
|
||||
|
||||
/** A magazine about the club is a hit, but has no pairing to shorten. */
|
||||
@Test
|
||||
fun `a title without a pairing keeps the original`() {
|
||||
assertNull(TeamFilters.fixture("FC St. Pauli: Der Rückblick"))
|
||||
assertNull(TeamFilters.fixture("Sportschau"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a dangling separator is not a pairing`() {
|
||||
assertNull(TeamFilters.fixture("Pokal: - , 1. Runde"))
|
||||
}
|
||||
|
||||
/** Hyphenated club names must not be mistaken for the separator. */
|
||||
@Test
|
||||
fun `hyphens inside a name do not split`() {
|
||||
assertEquals(
|
||||
"Rot-Weiss Essen - Preußen Münster",
|
||||
TeamFilters.fixture("3. Liga: Rot-Weiss Essen - Preußen Münster"),
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user