package snake import M09Helpers.{classicMain, drawn} class M09AppSuite extends munit.FunSuite: private def time(t: Long): Event = Event.Time(t) private def down(key: String): Event = Event.KeyDown(key) test("the game ticks every 150 ms") { assertEquals(App.TICK_MS, 150L) } test("classicActions turns the clock into Tick actions and keys into Turn actions") { assertEquals( App.classicActions.run(List(time(150), down("ArrowUp"), down("x"), time(300))), List(Action.Tick, Action.Turn(Direction.Up), Action.Tick) ) } test("states starts with the new game, then yields one state per action") { val out = App.states(42, App.classicActions).run(List(time(150), down("ArrowUp"), time(300))) assertEquals(out.length, 4) assertEquals(out.head, Spawn.newGame(42)) assertEquals(out.map(_.snake.head), List(Point(10, 10), Point(11, 10), Point(11, 10), Point(11, 9))) assertEquals(out.map(_.nextDir), List(Direction.Right, Direction.Right, Direction.Up, Direction.Up)) assertEquals(out.map(_.dir), List(Direction.Right, Direction.Right, Direction.Right, Direction.Up)) } test("render draws the whole view of the state") { assertEquals(IO.trace(App.render(Spawn.newGame(42)), 0).ops, View.view(Spawn.newGame(42)).map(Op.Draw(_))) } test("main asks for a random seed, then builds the stream from it") { val traced = IO.trace(App.main, 42) assertEquals(traced.ops, List(Op.RandomSeed)) val (outs, _) = traced.result.step(time(0)) assertEquals(outs.length, 1) assertEquals(drawn(outs.head), View.view(Spawn.newGame(42))) } // `main` itself switches to speedActions in m10, so the 150 ms behaviour is checked on the same program built from classicActions. test("the program built from classicActions draws the new game first, then the ticked game after 150 ms") { val stream = IO.trace(classicMain, 42).result val (first, next) = stream.step(time(0)) val (second, _) = next.step(time(150)) assertEquals(drawn(first.head), View.view(Spawn.newGame(42))) assertEquals(second.length, 1) assertNotEquals(drawn(second.head), drawn(first.head)) } // Holds before and after m10: whatever `main` ticks with, the clock must be wired in, so time passing produces more drawings. test("main draws again once time has passed") { val stream = IO.trace(App.main, 42).result val (first, next) = stream.step(time(0)) val (later, _) = next.step(time(150)) assertEquals(first.length, 1) assert(later.nonEmpty) }