now = new DateTimeImmutable( '2026-05-06T12:00:00', new DateTimeZone('UTC') ); $this->sessionRepo = new FakeSessionRepository; $this->tokenGenerator = new FakeTokenGenerator(['token-abc']); $this->clock = new FakeClock($this->now); $this->useCase = new CreateSession( $this->sessionRepo, $this->tokenGenerator, $this->clock, ); } private function makeUser(): User { return new User( id: 7, email: new EmailAddress('user@example.com'), passwordHash: 'hashed:irrelevant', isAdmin: false, ); } public function test_creates_session_with_generated_token(): void { $session = $this->useCase->execute($this->makeUser()); $this->assertInstanceOf(Session::class, $session); $this->assertSame('token-abc', $session->getToken()); $this->assertSame(7, $session->getUser()->getId()); } public function test_session_created_at_is_clock_now(): void { $session = $this->useCase->execute($this->makeUser()); $this->assertEquals($this->now, $session->getCreatedAt()); } public function test_session_expires_seven_days_from_now(): void { $session = $this->useCase->execute($this->makeUser()); $expected = $this->now->modify('+7 days'); $this->assertEquals($expected, $session->getExpiresAt()); } public function test_session_is_findable_by_token(): void { $this->useCase->execute($this->makeUser()); $found = $this->sessionRepo->findByToken('token-abc'); $this->assertNotNull($found); $this->assertSame(7, $found->getUser()->getId()); } }