'2026-04-01', 'duration' => 7200, 'count' => 3], ['day' => '2026-04-02', 'duration' => 3600, 'count' => 1], ]; $service = $this->createServiceWithResults($mockResults); $result = $service->getDailyAggregation( $this->createMock(User::class), new \DateTimeImmutable('2026-04-01'), new \DateTimeImmutable('2026-04-30') ); $this->assertCount(2, $result); $this->assertEquals('2026-04-01', $result[0]['date']); $this->assertEquals(2.0, $result[0]['hours']); $this->assertEquals(3, $result[0]['count']); $this->assertEquals('2026-04-02', $result[1]['date']); $this->assertEquals(1.0, $result[1]['hours']); $this->assertEquals(1, $result[1]['count']); } public function testGetDailyAggregationReturnsEmptyForNoData(): void { $service = $this->createServiceWithResults([]); $result = $service->getDailyAggregation( $this->createMock(User::class), new \DateTimeImmutable('2026-04-01'), new \DateTimeImmutable('2026-04-30') ); $this->assertCount(0, $result); } public function testHoursRoundedToTwoDecimals(): void { $mockResults = [ ['day' => '2026-04-01', 'duration' => 5431, 'count' => 2], ]; $service = $this->createServiceWithResults($mockResults); $result = $service->getDailyAggregation( $this->createMock(User::class), new \DateTimeImmutable('2026-04-01'), new \DateTimeImmutable('2026-04-30') ); $this->assertEquals(1.51, $result[0]['hours']); } private function createServiceWithResults(array $results): HeatmapService { $query = $this->createMock(AbstractQuery::class); $query->method('getResult')->willReturn($results); $qb = $this->createMock(QueryBuilder::class); $qb->method('select')->willReturnSelf(); $qb->method('addSelect')->willReturnSelf(); $qb->method('andWhere')->willReturnSelf(); $qb->method('setParameter')->willReturnSelf(); $qb->method('groupBy')->willReturnSelf(); $qb->method('orderBy')->willReturnSelf(); $qb->method('expr')->willReturn(new Expr()); $qb->method('getQuery')->willReturn($query); $repo = $this->createMock(TimesheetRepository::class); $repo->method('createQueryBuilder')->willReturn($qb); return new HeatmapService($repo); } }