setFirstName('Rita') ->setLastName('Vorschlag') ->setRoles([Role::TEAMER, Role::pending(Role::GROUPS_ADMIN)]) ; $widget = $this->provider([$user])->build(); $this->assertNotNull($widget); $this->assertCount(1, $widget->entries); $this->assertStringContainsString('Rita Vorschlag', $widget->entries[0]->label); $this->assertStringContainsString(Role::labels()[Role::GROUPS_ADMIN], $widget->entries[0]->label); } /** * The approval modal cannot be linked to directly, so the entry leads to the user list * filtered down to that account — which needs the filter marker to bind at all. */ public function testEntryLinksToTheUserListFilteredToThatAccount(): void { $user = (new User('nominee@example.com')) ->setRoles([Role::pending(Role::ADMIN)]) ; $widget = $this->provider([$user])->build(); $this->assertNotNull($widget); $this->assertSame('/admin/user?f=1&q=nominee%40example.com', $widget->entries[0]->url); } public function testRendersAsAnEmptyCardRatherThanDisappearingWhenNothingIsPending(): void { $widget = $this->provider([])->build(); $this->assertNotNull($widget); $this->assertSame([], $widget->entries); $this->assertSame('Keine offenen Rollenfreigaben.', $widget->emptyText); } public function testRequiresTheRoleThatMayActuallyApprove(): void { $this->assertSame(Role::ADMIN, $this->provider([])->getRequiredRole()); } /** * @param User[] $pending */ private function provider(array $pending): PendingRoleApprovalsWidgetProvider { $repository = $this->createStub(UserRepository::class); $repository->method('findWithPendingRoles')->willReturn($pending); $urlGenerator = $this->createStub(UrlGeneratorInterface::class); $urlGenerator->method('generate')->willReturnCallback( static function (string $route, array $parameters = []): string { $path = '/'.str_replace('_', '/', substr($route, \strlen('app_'))); return [] === $parameters ? $path : $path.'?'.http_build_query($parameters); }, ); return new PendingRoleApprovalsWidgetProvider( $repository, $urlGenerator, new RoleApprovalUrlGenerator($urlGenerator), ); } }