fix: properly gate menus by role
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Menu;
|
||||
|
||||
use App\Menu\AdminMenuBuilder;
|
||||
use App\Menu\ManagerMenuBuilder;
|
||||
use Knp\Menu\ItemInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
/**
|
||||
* The back item degrades silently: without an uri it is rendered as a dead label
|
||||
* instead of a link (see templates/_partials/_menu.html.twig), so it is guarded here.
|
||||
*/
|
||||
class TeamerMenuBackItemTest extends KernelTestCase
|
||||
{
|
||||
private const OVERVIEW_PATH = '/administrative/teamer';
|
||||
|
||||
private RequestStack $requestStack;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$this->requestStack = self::getContainer()->get(RequestStack::class);
|
||||
}
|
||||
|
||||
public function testTheReturnUrlOptionIsUsed(): void
|
||||
{
|
||||
$this->pushRequest();
|
||||
|
||||
$item = $this->buildBackItem(AdminMenuBuilder::class, ['return_url' => '/administrative/teamer?page=3']);
|
||||
|
||||
self::assertSame('/administrative/teamer?page=3', $item->getUri());
|
||||
}
|
||||
|
||||
public function testTheReturnUrlOptionWinsOverTheRequestParameter(): void
|
||||
{
|
||||
$this->pushRequest(rawurlencode('/administrative/teamer?page=9'));
|
||||
|
||||
$item = $this->buildBackItem(AdminMenuBuilder::class, ['return_url' => '/administrative/teamer?page=3']);
|
||||
|
||||
self::assertSame('/administrative/teamer?page=3', $item->getUri());
|
||||
}
|
||||
|
||||
public function testTheRequestParameterIsDecoded(): void
|
||||
{
|
||||
$this->pushRequest(rawurlencode('/administrative/teamer?page=3&sort=name'));
|
||||
|
||||
$item = $this->buildBackItem(AdminMenuBuilder::class);
|
||||
|
||||
self::assertSame('/administrative/teamer?page=3&sort=name', $item->getUri());
|
||||
}
|
||||
|
||||
/**
|
||||
* The regression guard: reachable e.g. after the status update in
|
||||
* Admin\Teamer\SkillsController, which redirects without carrying "r" forward.
|
||||
*
|
||||
* @dataProvider builderProvider
|
||||
*/
|
||||
public function testWithoutAnyReturnUrlTheOverviewIsLinked(string $builderClass): void
|
||||
{
|
||||
$this->pushRequest();
|
||||
|
||||
$deprecations = [];
|
||||
set_error_handler(
|
||||
static function (int $level, string $message) use (&$deprecations): bool {
|
||||
$deprecations[] = $message;
|
||||
|
||||
return true;
|
||||
},
|
||||
\E_DEPRECATED
|
||||
);
|
||||
|
||||
try {
|
||||
$item = $this->buildBackItem($builderClass);
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
self::assertSame(self::OVERVIEW_PATH, $item->getUri());
|
||||
self::assertSame([], $deprecations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<string, array{string}>
|
||||
*/
|
||||
public static function builderProvider(): iterable
|
||||
{
|
||||
yield 'admin' => [AdminMenuBuilder::class];
|
||||
yield 'manager' => [ManagerMenuBuilder::class];
|
||||
}
|
||||
|
||||
private function pushRequest(?string $returnUrlParameter = null): void
|
||||
{
|
||||
$query = null !== $returnUrlParameter ? '?r='.$returnUrlParameter : '';
|
||||
|
||||
$this->requestStack->push(Request::create('/administrative/teamer/profile/0'.$query));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
private function buildBackItem(string $builderClass, array $options = []): ItemInterface
|
||||
{
|
||||
$builder = self::getContainer()->get($builderClass);
|
||||
$children = $builder->createTeamerMenu($options)->getChildren();
|
||||
$backItem = end($children);
|
||||
|
||||
self::assertInstanceOf(ItemInterface::class, $backItem);
|
||||
self::assertSame('zurück zur Übersicht', $backItem->getLabel());
|
||||
|
||||
return $backItem;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user