From 5d7941429c871a95e27184366918883c61e9811c Mon Sep 17 00:00:00 2001 From: Christophe Vila Date: Sat, 4 Jul 2026 10:20:56 +0200 Subject: [PATCH] test: add PadelMatch engine test suite (failing) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Writes the complete TDD test suite for PadelMatch before the engine exists. Build intentionally fails to compile (RED phase) — undefined symbols PadelMatch, RulesConfig, US, THEM, and QUAD_* constants are all defined in Task 3. Co-Authored-By: Claude Opus 4.8 (1M context) --- source/PadelMatchTest.mc | 156 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 source/PadelMatchTest.mc diff --git a/source/PadelMatchTest.mc b/source/PadelMatchTest.mc new file mode 100644 index 0000000..83aa060 --- /dev/null +++ b/source/PadelMatchTest.mc @@ -0,0 +1,156 @@ +import Toybox.Lang; +import Toybox.Test; + +// ---- plain helpers (not annotated :test, so not run as cases) ---- + +function newMatch() as PadelMatch { + return new PadelMatch(new RulesConfig()); +} + +function newAdvantageMatch() as PadelMatch { + var r = new RulesConfig(); + r.goldenPoint = false; + return new PadelMatch(r); +} + +// Win one game for `team` under golden-point rules (4 straight points). +function winGameFor(m as PadelMatch, team as Number) as Void { + for (var i = 0; i < 4; i += 1) { m.pointTo(team); } +} + +// ---- test cases ---- + +(:test) function testInitialState(logger as Logger) as Boolean { + var m = newMatch(); + Test.assertEqualMessage(m.sets(US), 0, "sets US"); + Test.assertEqualMessage(m.games(US), 0, "games US"); + Test.assertEqualMessage(m.pointLabel(US), "0", "points US"); + Test.assertEqualMessage(m.isMatchOver(), false, "not over"); + Test.assertEqualMessage(m.servingQuadrant(), QUAD_BOTTOM_RIGHT, "US serves deuce"); + return true; +} + +(:test) function testPointLabelsProgress(logger as Logger) as Boolean { + var m = newMatch(); + m.pointTo(US); + Test.assertEqualMessage(m.pointLabel(US), "15", "15"); + m.pointTo(US); + Test.assertEqualMessage(m.pointLabel(US), "30", "30"); + m.pointTo(US); + Test.assertEqualMessage(m.pointLabel(US), "40", "40"); + return true; +} + +(:test) function testGoldenGameWin(logger as Logger) as Boolean { + var m = newMatch(); + winGameFor(m, US); + Test.assertEqualMessage(m.games(US), 1, "US won a game"); + Test.assertEqualMessage(m.pointLabel(US), "0", "points reset"); + return true; +} + +(:test) function testAdvantageDeuceCycle(logger as Logger) as Boolean { + var m = newAdvantageMatch(); + // 3-3 deuce + for (var i = 0; i < 3; i += 1) { m.pointTo(US); m.pointTo(THEM); } + Test.assertEqualMessage(m.pointLabel(US), "40", "deuce US 40"); + m.pointTo(US); + Test.assertEqualMessage(m.pointLabel(US), "AD", "US advantage"); + m.pointTo(THEM); + Test.assertEqualMessage(m.pointLabel(US), "40", "back to deuce"); + m.pointTo(US); m.pointTo(US); + Test.assertEqualMessage(m.games(US), 1, "US won from advantage"); + return true; +} + +(:test) function testWinSetSixLove(logger as Logger) as Boolean { + var m = newMatch(); + for (var g = 0; g < 6; g += 1) { winGameFor(m, US); } + Test.assertEqualMessage(m.sets(US), 1, "US won the set"); + Test.assertEqualMessage(m.games(US), 0, "games reset"); + return true; +} + +(:test) function testTiebreakEntryAndWin(logger as Logger) as Boolean { + var m = newMatch(); + for (var i = 0; i < 6; i += 1) { winGameFor(m, US); winGameFor(m, THEM); } + Test.assertEqualMessage(m.isInTiebreak(), true, "6-6 tiebreak"); + Test.assertEqualMessage(m.games(US), 6, "games 6-6"); + for (var p = 0; p < 7; p += 1) { m.pointTo(US); } + Test.assertEqualMessage(m.isInTiebreak(), false, "tiebreak done"); + Test.assertEqualMessage(m.sets(US), 1, "US won the set via tiebreak"); + return true; +} + +(:test) function testServeSideParity(logger as Logger) as Boolean { + var m = newMatch(); // US serving + Test.assertEqualMessage(m.servingQuadrant(), QUAD_BOTTOM_RIGHT, "0 pts deuce"); + m.pointTo(THEM); // 1 point played + Test.assertEqualMessage(m.servingQuadrant(), QUAD_BOTTOM_LEFT, "1 pt ad"); + m.pointTo(US); // 2 points played + Test.assertEqualMessage(m.servingQuadrant(), QUAD_BOTTOM_RIGHT, "2 pts deuce"); + return true; +} + +(:test) function testServerAlternation(logger as Logger) as Boolean { + var m = newMatch(); + winGameFor(m, US); // serve passes to THEM + Test.assertEqualMessage(m.servingQuadrant(), QUAD_UPPER_LEFT, "THEM serves deuce"); + return true; +} + +(:test) function testTiebreakServing(logger as Logger) as Boolean { + var m = newMatch(); + for (var i = 0; i < 6; i += 1) { winGameFor(m, US); winGameFor(m, THEM); } + // 12 games played, start server US -> US serves first in tiebreak + Test.assertEqualMessage(m.servingQuadrant(), QUAD_BOTTOM_RIGHT, "P0 US deuce"); + m.pointTo(US); + Test.assertEqualMessage(m.servingQuadrant(), QUAD_UPPER_RIGHT, "P1 THEM ad"); + m.pointTo(US); + Test.assertEqualMessage(m.servingQuadrant(), QUAD_UPPER_LEFT, "P2 THEM deuce"); + m.pointTo(US); + Test.assertEqualMessage(m.servingQuadrant(), QUAD_BOTTOM_LEFT, "P3 US ad"); + return true; +} + +(:test) function testUndoAcrossGame(logger as Logger) as Boolean { + var m = newMatch(); + winGameFor(m, US); // US 1 game, points 0-0, THEM to serve + m.pointTo(THEM); // THEM has 15 + m.undo(); // back to just-after-game + Test.assertEqualMessage(m.pointLabel(THEM), "0", "point undone"); + m.undo(); // undo the game-winning point + Test.assertEqualMessage(m.games(US), 0, "game undone"); + Test.assertEqualMessage(m.pointLabel(US), "40", "back to 40"); + return true; +} + +(:test) function testUndoAtStartIsNoop(logger as Logger) as Boolean { + var m = newMatch(); + m.undo(); + Test.assertEqualMessage(m.games(US), 0, "still zero"); + return true; +} + +(:test) function testStartingServerToggle(logger as Logger) as Boolean { + var m = newMatch(); + m.toggleStartingServer(); + Test.assertEqualMessage(m.servingQuadrant(), QUAD_UPPER_LEFT, "THEM serves first"); + m.pointTo(US); // match started; toggle now locked + m.toggleStartingServer(); + Test.assertEqualMessage(m.canSetServer(), false, "server locked after first point"); + return true; +} + +(:test) function testMatchOver(logger as Logger) as Boolean { + var m = newMatch(); + for (var s = 0; s < 2; s += 1) { + for (var g = 0; g < 6; g += 1) { winGameFor(m, US); } + } + Test.assertEqualMessage(m.isMatchOver(), true, "match over"); + Test.assertEqualMessage(m.winner(), US, "US wins"); + var setsBefore = m.sets(US); + m.pointTo(US); // ignored after match over + Test.assertEqualMessage(m.sets(US), setsBefore, "no scoring after match"); + return true; +}