From bf47f8257055a8b9d003bd96207bdc15df4c2a48 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 10 Dec 2025 12:35:49 +0100 Subject: [PATCH 01/26] WIP --- src/Config/SharpConfigBuilder.php | 1 + src/Http/Context/SharpBreadcrumb.php | 28 +++++++++++++++---- src/Http/Controllers/DashboardController.php | 3 +- src/Http/Controllers/EntityListController.php | 2 +- src/Http/Controllers/FormController.php | 6 ++-- src/Http/Controllers/ShowController.php | 2 +- src/Http/Controllers/SingleShowController.php | 2 +- src/Http/Middleware/HandleGlobalFilters.php | 22 +++++++++++++++ src/routes/api.php | 4 +-- src/routes/web.php | 26 ++++++++++++----- 10 files changed, 75 insertions(+), 21 deletions(-) create mode 100644 src/Http/Middleware/HandleGlobalFilters.php diff --git a/src/Config/SharpConfigBuilder.php b/src/Config/SharpConfigBuilder.php index ce8fcf3df..9950ade02 100644 --- a/src/Config/SharpConfigBuilder.php +++ b/src/Config/SharpConfigBuilder.php @@ -44,6 +44,7 @@ class SharpConfigBuilder \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::class, + \Code16\Sharp\Http\Middleware\HandleGlobalFilters::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'web' => [ diff --git a/src/Http/Context/SharpBreadcrumb.php b/src/Http/Context/SharpBreadcrumb.php index a3f88c956..991e5bbb6 100644 --- a/src/Http/Context/SharpBreadcrumb.php +++ b/src/Http/Context/SharpBreadcrumb.php @@ -2,6 +2,7 @@ namespace Code16\Sharp\Http\Context; +use Code16\Sharp\Filters\GlobalRequiredFilter; use Code16\Sharp\Http\Context\Util\BreadcrumbItem; use Code16\Sharp\Utils\Entities\SharpEntityManager; use Code16\Sharp\Utils\Entities\ValueObjects\EntityKey; @@ -76,8 +77,9 @@ public function getCurrentSegmentUrl(): string { return url( sprintf( - '%s/%s', + '%s/%s/%s', sharp()->config()->get('custom_url_segment'), + $this->getGlobalFilterKey(), $this->getCurrentPath() ) ); @@ -94,8 +96,9 @@ public function getPreviousSegmentUrl(): string { return url( sprintf( - '%s/%s', + '%s/%s/%s', sharp()->config()->get('custom_url_segment'), + $this->getGlobalFilterKey(), $this->breadcrumbItems() ->slice(0, -1) ->map(fn (BreadcrumbItem $item) => $item->toUri()) @@ -311,12 +314,17 @@ protected function getSegmentsFromRequest(): Collection $urlToParse = request()->header(static::CURRENT_PAGE_URL_HEADER) ?? request()->query('current_page_url'); return collect(explode('/', parse_url($urlToParse)['path'])) - ->filter(fn (string $segment) => strlen(trim($segment)) - && $segment !== sharp()->config()->get('custom_url_segment') - ) + ->filter(fn (string $segment) => strlen(trim($segment))) + ->skip(2) ->values(); } + if (request()->isMethod('GET')) { + // Have to skip /sharp/{filterKey} + return collect(request()->segments())->skip(2)->values(); + } + + // Have to skip /sharp return collect(request()->segments())->skip(1)->values(); } @@ -325,4 +333,14 @@ public function forceRequestSegments(array|Collection $segments): void $this->breadcrumbItems = null; $this->forcedSegments = collect($segments)->values(); } + + private function getGlobalFilterKey(): string + { + $globalFilterValues = collect(sharp()->config()->get('global_filters')) + ->map(fn ($globalFilterClassOrInstance) => is_string($globalFilterClassOrInstance) ? app($globalFilterClassOrInstance) : $globalFilterClassOrInstance) + ->map(fn (GlobalRequiredFilter $globalFilter) => $globalFilter->currentValue()) + ->filter(); + + return $globalFilterValues->isEmpty() ? 'root' : $globalFilterValues->implode('-'); + } } diff --git a/src/Http/Controllers/DashboardController.php b/src/Http/Controllers/DashboardController.php index 7c328dd87..a74ca61de 100644 --- a/src/Http/Controllers/DashboardController.php +++ b/src/Http/Controllers/DashboardController.php @@ -4,11 +4,12 @@ use Code16\Sharp\Data\BreadcrumbData; use Code16\Sharp\Data\Dashboard\DashboardData; +use Code16\Sharp\Utils\Entities\ValueObjects\EntityKey; use Inertia\Inertia; class DashboardController extends SharpProtectedController { - public function show(string $dashboardKey) + public function show(string $filterKey, EntityKey $dashboardKey) { $this->authorizationManager->check('entity', $dashboardKey); diff --git a/src/Http/Controllers/EntityListController.php b/src/Http/Controllers/EntityListController.php index 7476a7bbb..bdcd1708e 100644 --- a/src/Http/Controllers/EntityListController.php +++ b/src/Http/Controllers/EntityListController.php @@ -18,7 +18,7 @@ class EntityListController extends SharpProtectedController use HandlesEntityListItems; use HandlesSharpNotificationsInRequest; - public function show(string $entityKey) + public function show(string $filterKey, EntityKey $entityKey) { $this->authorizationManager->check('entity', $entityKey); diff --git a/src/Http/Controllers/FormController.php b/src/Http/Controllers/FormController.php index f65300c55..a63fd0141 100644 --- a/src/Http/Controllers/FormController.php +++ b/src/Http/Controllers/FormController.php @@ -22,7 +22,7 @@ public function __construct( parent::__construct(); } - public function create(string $parentUri, EntityKey $entityKey) + public function create(string $filterKey, string $parentUri, EntityKey $entityKey) { $entity = $this->entityManager->entityFor($entityKey); @@ -30,7 +30,7 @@ public function create(string $parentUri, EntityKey $entityKey) if ($form instanceof SharpSingleForm) { // There is no creation in SingleForms - return $this->edit($parentUri, $entityKey); + return $this->edit($filterKey, $parentUri, $entityKey); } $this->authorizationManager->check('create', $entityKey); @@ -56,7 +56,7 @@ public function create(string $parentUri, EntityKey $entityKey) ]); } - public function edit(string $parentUri, EntityKey $entityKey, ?string $instanceId = null) + public function edit(string $filterKey, string $parentUri, EntityKey $entityKey, ?string $instanceId = null) { $entity = $this->entityManager->entityFor($entityKey); diff --git a/src/Http/Controllers/ShowController.php b/src/Http/Controllers/ShowController.php index b10f81ea2..5fab94463 100644 --- a/src/Http/Controllers/ShowController.php +++ b/src/Http/Controllers/ShowController.php @@ -14,7 +14,7 @@ class ShowController extends SharpProtectedController use HandlesSharpNotificationsInRequest; use PreloadsShowFields; - public function show(string $parentUri, EntityKey $entityKey, string $instanceId) + public function show(string $filterKey, string $parentUri, EntityKey $entityKey, string $instanceId) { $this->authorizationManager->check('view', $entityKey, $instanceId); diff --git a/src/Http/Controllers/SingleShowController.php b/src/Http/Controllers/SingleShowController.php index 9484ffba6..9621ab8d5 100644 --- a/src/Http/Controllers/SingleShowController.php +++ b/src/Http/Controllers/SingleShowController.php @@ -13,7 +13,7 @@ class SingleShowController extends SharpProtectedController use HandlesSharpNotificationsInRequest; use PreloadsShowFields; - public function show(EntityKey $entityKey) + public function show(string $filterKey, EntityKey $entityKey) { $this->authorizationManager->check('view', $entityKey); diff --git a/src/Http/Middleware/HandleGlobalFilters.php b/src/Http/Middleware/HandleGlobalFilters.php new file mode 100644 index 000000000..a8da13279 --- /dev/null +++ b/src/Http/Middleware/HandleGlobalFilters.php @@ -0,0 +1,22 @@ +config()->get('global_filters')) + ->map(fn ($globalFilterClassOrInstance) => is_string($globalFilterClassOrInstance) ? app($globalFilterClassOrInstance) : $globalFilterClassOrInstance) + ->map(fn (GlobalRequiredFilter $globalFilter) => $globalFilter->currentValue()) + ->filter(); + + URL::defaults(['filterKey' => $globalFilterValues->isEmpty() ? 'root' : $globalFilterValues->implode('-')]); + + return $next($request); + } +} diff --git a/src/routes/api.php b/src/routes/api.php index d5546e5b3..584a953e8 100644 --- a/src/routes/api.php +++ b/src/routes/api.php @@ -39,7 +39,7 @@ ->name('code16.sharp.api.list.command.quick-creation-form.store'); // EmbeddedEntityLists - Route::get('/list/{entityKey}', [EntityListController::class, 'show']) + Route::get('/{filterKey}/list/{entityKey}', [EntityListController::class, 'show']) ->name('code16.sharp.api.list') ->middleware('cache.headers:no_store'); @@ -68,7 +68,7 @@ ->name('code16.sharp.api.list.command.instance.form'); // EmbeddedDashboards - Route::get('/dashboard/{dashboardKey}', [DashboardController::class, 'show']) + Route::get('/{filterKey}/dashboard/{dashboardKey}', [DashboardController::class, 'show']) ->name('code16.sharp.api.dashboard') ->middleware('cache.headers:no_store'); diff --git a/src/routes/web.php b/src/routes/web.php index 7c4737137..4734b1c3b 100644 --- a/src/routes/web.php +++ b/src/routes/web.php @@ -20,40 +20,52 @@ Route::get('/', [HomeController::class, 'index']) ->name('code16.sharp.home'); - Route::get('/s-dashboard/{dashboardKey}', [DashboardController::class, 'show']) + Route::get('s-dashboard/{dashboardKey}', fn ($entityKey) => redirect( + route('code16.sharp.dashboard', ['root', $entityKey]) + )); + + Route::get('{filterKey}/s-dashboard/{dashboardKey}', [DashboardController::class, 'show']) ->name('code16.sharp.dashboard'); Route::post('/s-dashboard/{dashboardKey}', [DashboardFiltersController::class, 'store']) ->name('code16.sharp.dashboard.filters.store'); - Route::get('/s-list/{entityKey}', [EntityListController::class, 'show']) + Route::get('s-list/{entityKey}', fn ($entityKey) => redirect( + route('code16.sharp.list', ['root', $entityKey]) + )); + + Route::get('{filterKey}/s-list/{entityKey}', [EntityListController::class, 'show']) ->name('code16.sharp.list'); Route::post('/s-list/{entityKey}/filters', [EntityListFiltersController::class, 'store']) ->name('code16.sharp.list.filters.store'); - Route::get('/s-show/{entityKey}', [SingleShowController::class, 'show']) + Route::get('s-show/{entityKey}', fn ($entityKey) => redirect( + route('code16.sharp.single-show', ['root', $entityKey]) + )); + + Route::get('{filterKey}/s-show/{entityKey}', [SingleShowController::class, 'show']) ->name('code16.sharp.single-show'); - Route::get('/download/{entityKey}/{instanceId?}', [DownloadController::class, 'show']) + Route::get('download/{entityKey}/{instanceId?}', [DownloadController::class, 'show']) ->name('code16.sharp.download.show'); Route::where([ 'parentUri' => '(s-list|s-show)/.+', ])->group(function () { - Route::get('/{parentUri}/s-show/{entityKey}/{instanceId}', [ShowController::class, 'show']) + Route::get('/{filterKey}/{parentUri}/s-show/{entityKey}/{instanceId}', [ShowController::class, 'show']) ->name('code16.sharp.show.show'); Route::delete('/{parentUri}/s-show/{entityKey}/{instanceId}', [ShowController::class, 'delete']) ->name('code16.sharp.show.delete'); - Route::get('/{parentUri}/s-form/{entityKey}', [FormController::class, 'create']) + Route::get('/{filterKey}/{parentUri}/s-form/{entityKey}', [FormController::class, 'create']) ->name('code16.sharp.form.create'); Route::post('/{parentUri}/s-form/{entityKey}', [FormController::class, 'store']) ->name('code16.sharp.form.store'); - Route::get('/{parentUri}/s-form/{entityKey}/{instanceId?}', [FormController::class, 'edit']) + Route::get('/{filterKey}/{parentUri}/s-form/{entityKey}/{instanceId?}', [FormController::class, 'edit']) ->name('code16.sharp.form.edit'); Route::post('/{parentUri}/s-form/{entityKey}/{instanceId?}', [FormController::class, 'update']) From bcbbd557f7b257a07ebce77a1b43dd4202283d20 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 10 Dec 2025 12:35:57 +0100 Subject: [PATCH 02/26] WIP tests --- tests/Http/Api/ApiDashboardControllerTest.php | 7 +-- .../Http/Api/ApiEntityListControllerTest.php | 42 +++++++++------- ...ListQuickCreationCommandControllerTest.php | 11 ++--- tests/Http/Api/SearchControllerTest.php | 14 +++--- tests/Http/Auth/AuthenticationTest.php | 6 +-- tests/Http/Auth/AuthorizationsTest.php | 48 +++++++++---------- tests/Http/Auth/PolicyAuthorizationsTest.php | 36 +++++++------- 7 files changed, 85 insertions(+), 79 deletions(-) diff --git a/tests/Http/Api/ApiDashboardControllerTest.php b/tests/Http/Api/ApiDashboardControllerTest.php index 788c0738d..713780973 100644 --- a/tests/Http/Api/ApiDashboardControllerTest.php +++ b/tests/Http/Api/ApiDashboardControllerTest.php @@ -52,9 +52,10 @@ protected function buildWidgetsData(): void } }); - $this->getJson('/sharp/api/dashboard/'.DashboardEntity::$entityKey, headers: [ - SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/s-list/person/s-show/person/1'), - ]) + $this + ->getJson('/sharp/api/root/dashboard/'.DashboardEntity::$entityKey, headers: [ + SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/root/s-list/person/s-show/person/1'), + ]) ->assertOk() ->assertJson(fn (AssertableJson $json) => $json ->has('data.panel.data', fn (AssertableJson $json) => $json diff --git a/tests/Http/Api/ApiEntityListControllerTest.php b/tests/Http/Api/ApiEntityListControllerTest.php index 66f546b41..cd3ef7bea 100644 --- a/tests/Http/Api/ApiEntityListControllerTest.php +++ b/tests/Http/Api/ApiEntityListControllerTest.php @@ -139,9 +139,10 @@ public function getListData(): array|Arrayable } }); - $this->getJson('/sharp/api/list/person', headers: [ - SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/s-list/person/s-show/person/1'), - ]) + $this + ->getJson('/sharp/api/root/list/person', headers: [ + SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/root/s-list/person/s-show/person/1'), + ]) ->assertOk() ->assertJson(fn (AssertableJson $json) => $json ->has('data.0', fn (AssertableJson $json) => $json->where('id', 1) @@ -168,9 +169,10 @@ public function getListData(): array|Arrayable } }); - $this->getJson('/sharp/api/list/person', headers: [ - SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/s-list/person/s-show/person/1'), - ]) + $this + ->getJson('/sharp/api/root/list/person', headers: [ + SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/root/s-list/person/s-show/person/1'), + ]) ->assertOk() ->assertJson(fn (AssertableJson $json) => $json ->has('data.0', fn (AssertableJson $json) => $json @@ -211,9 +213,10 @@ public function getListData(): array|Arrayable fakeShowFor('person', null); - $this->getJson('/sharp/api/list/person', headers: [ - SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/s-list/person/s-show/person/1'), - ]) + $this + ->getJson('/sharp/api/root/list/person', headers: [ + SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/root/s-list/person/s-show/person/1'), + ]) ->assertOk() ->assertJson(fn (AssertableJson $json) => $json ->has('data.0', fn (AssertableJson $json) => $json @@ -268,9 +271,10 @@ public function buildListConfig(): void } }); - $this->getJson('/sharp/api/list/person', headers: [ - SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/s-list/person/s-show/person/1'), - ]) + $this + ->getJson('/sharp/api/root/list/person', headers: [ + SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/root/s-list/person/s-show/person/1'), + ]) ->assertOk() ->assertJson(fn (AssertableJson $json) => $json ->count('data', 3) @@ -303,9 +307,10 @@ public function getListData(): array|Arrayable } }); - $this->getJson('/sharp/api/list/person', headers: [ - SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/s-list/person/s-show/person/1'), - ]) + $this + ->getJson('/sharp/api/root/list/person', headers: [ + SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/root/s-list/person/s-show/person/1'), + ]) ->assertOk() ->assertJson(fn (AssertableJson $json) => $json ->has('data.0', fn (AssertableJson $json) => $json->where('id', 1) @@ -360,9 +365,10 @@ public function buildListConfig(): void } }); - $this->getJson('/sharp/api/list/person', headers: [ - SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/s-list/person/s-show/person/1'), - ]) + $this + ->getJson('/sharp/api/root/list/person', headers: [ + SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/root/s-list/person/s-show/person/1'), + ]) ->assertOk() ->assertJson(fn (AssertableJson $json) => $json ->count('data', 3) diff --git a/tests/Http/Api/Commands/ApiEntityListQuickCreationCommandControllerTest.php b/tests/Http/Api/Commands/ApiEntityListQuickCreationCommandControllerTest.php index 8359cf5d9..fcac2411a 100644 --- a/tests/Http/Api/Commands/ApiEntityListQuickCreationCommandControllerTest.php +++ b/tests/Http/Api/Commands/ApiEntityListQuickCreationCommandControllerTest.php @@ -153,7 +153,6 @@ public function update($id, array $data) {} }); it('sharp()->context()->breadcrumb() is correct', function () { - fakeListFor('person', new class() extends PersonList { public function buildListConfig(): void @@ -171,8 +170,8 @@ public function update($id, array $data) ->isForm()->toBeTrue() ->entityKey()->toBe('person'); - expect(sharp()->context()->breadcrumb()) - ->getCurrentSegmentUrl()->toBe(url('/sharp/s-list/person/s-form/person')); + expect(sharp()->context()->breadcrumb()->getCurrentSegmentUrl()) + ->toBe(url('/sharp/root/s-list/person/s-form/person')); } }); @@ -181,7 +180,7 @@ public function update($id, array $data) route('code16.sharp.api.list.command.quick-creation-form.create', ['person', 'person']), ['data' => []], [ - SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/s-list/person'), + SharpBreadcrumb::CURRENT_PAGE_URL_HEADER => url('/sharp/root/s-list/person'), ] ) ->assertOk() @@ -246,7 +245,7 @@ public function update($id, array $data) } }); - $this->get(route('code16.sharp.list', ['person'])); + $this->get(route('code16.sharp.list', ['root', 'person'])); $this ->postJson( @@ -256,7 +255,7 @@ public function update($id, array $data) ->assertOk() ->assertJson([ 'action' => 'link', - 'link' => url('/sharp/s-list/person/s-show/person/4'), + 'link' => url('/sharp/root/s-list/person/s-show/person/4'), ]); }); diff --git a/tests/Http/Api/SearchControllerTest.php b/tests/Http/Api/SearchControllerTest.php index f442b98eb..252045229 100644 --- a/tests/Http/Api/SearchControllerTest.php +++ b/tests/Http/Api/SearchControllerTest.php @@ -35,12 +35,12 @@ public function searchFor(array $terms): void 'resultLinks' => [ [ 'label' => 'John Wayne', - 'link' => url('sharp/s-list/person/s-show/person/1'), + 'link' => url('sharp/root/s-list/person/s-show/person/1'), 'detail' => null, ], [ 'label' => 'Jane Ford', - 'link' => url('sharp/s-list/person/s-show/person/2'), + 'link' => url('sharp/root/s-list/person/s-show/person/2'), 'detail' => 'Some detail', ], ], @@ -157,7 +157,7 @@ public function searchFor(array $terms): void 'resultLinks' => [ [ 'label' => 'John Wayne', - 'link' => url('sharp/s-list/person/s-show/person/1'), + 'link' => url('sharp/root/s-list/person/s-show/person/1'), 'detail' => null, ], ], @@ -171,7 +171,7 @@ public function searchFor(array $terms): void 'resultLinks' => [ [ 'label' => 'Aston Martin', - 'link' => url('sharp/s-list/car/s-show/car/1'), + 'link' => url('sharp/root/s-list/car/s-show/car/1'), 'detail' => null, ], ], @@ -238,7 +238,7 @@ public function authorize(): bool sharp()->config()->declareEntity(PersonEntity::class); $this - ->get('/sharp/s-list/person') + ->get('/sharp/root/s-list/person') ->assertInertia(fn (Assert $page) => $page ->where('globalSearch', null) ); @@ -256,14 +256,14 @@ public function authorize(): bool ); $this - ->get('/sharp/s-list/person') + ->get('/sharp/root/s-list/person') ->assertInertia(fn (Assert $page) => $page ->where('globalSearch', null) ); $this ->actingAs(User::make(['email' => 'authorized-user@test.fr'])) - ->get('/sharp/s-list/person') + ->get('/sharp/root/s-list/person') ->assertInertia(fn (Assert $page) => $page ->where('globalSearch', [ 'config' => [ diff --git a/tests/Http/Auth/AuthenticationTest.php b/tests/Http/Auth/AuthenticationTest.php index 597f4c796..c4d243f5c 100644 --- a/tests/Http/Auth/AuthenticationTest.php +++ b/tests/Http/Auth/AuthenticationTest.php @@ -17,7 +17,7 @@ function setTestAuthGuard(): void } it('redirects guests to the login page', function () { - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertRedirect(route('code16.sharp.login')); }); @@ -165,12 +165,12 @@ public function setUser(\Illuminate\Contracts\Auth\Authenticatable $user) login(new User(['name' => 'ok'])); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk(); login(new User(['name' => 'ko'])); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertRedirect(route('code16.sharp.login')); }); diff --git a/tests/Http/Auth/AuthorizationsTest.php b/tests/Http/Auth/AuthorizationsTest.php index f156f02e1..6c920d01e 100644 --- a/tests/Http/Auth/AuthorizationsTest.php +++ b/tests/Http/Auth/AuthorizationsTest.php @@ -25,11 +25,11 @@ ->setProhibitedActions(['delete', 'create', 'update', 'view']); // Can't access to the show - $this->get('/sharp/s-list/person/s-show/person/1')->assertForbidden(); + $this->get('/sharp/root/s-list/person/s-show/person/1')->assertForbidden(); // Can't access to the form - $this->get('/sharp/s-list/person/s-form/person')->assertForbidden(); - $this->get('/sharp/s-list/person/s-form/person/1')->assertForbidden(); + $this->get('/sharp/root/s-list/person/s-form/person')->assertForbidden(); + $this->get('/sharp/root/s-list/person/s-form/person/1')->assertForbidden(); $this->post('/sharp/s-list/person/s-form/person')->assertForbidden(); $this->post('/sharp/s-list/person/s-form/person/1')->assertForbidden(); @@ -38,7 +38,7 @@ $this->delete('/sharp/s-list/person/s-show/person/1')->assertForbidden(); // We can still view the list - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (AssertableJson $json) => $json ->where('entityList.authorizations.create', false) @@ -58,7 +58,7 @@ ->entityFor('person') ->setProhibitedActions(['update']); - $this->get('/sharp/s-list/person/s-form/person/1')->assertOk(); + $this->get('/sharp/root/s-list/person/s-form/person/1')->assertOk(); $this->post('/sharp/s-list/person/s-form/person/1')->assertForbidden(); }); @@ -67,10 +67,10 @@ ->entityFor('person') ->setProhibitedActions(['delete', 'update']); - $this->get('/sharp/s-list/person')->assertOk(); - $this->get('/sharp/s-list/person/s-show/person/50')->assertOk(); - $this->get('/sharp/s-list/person/s-form/person')->assertOk(); - $this->get('/sharp/s-list/person/s-form/person/50')->assertForbidden(); + $this->get('/sharp/root/s-list/person')->assertOk(); + $this->get('/sharp/root/s-list/person/s-show/person/50')->assertOk(); + $this->get('/sharp/root/s-list/person/s-form/person')->assertOk(); + $this->get('/sharp/root/s-list/person/s-form/person/50')->assertForbidden(); $this->post('/sharp/s-list/person/s-form/person')->assertRedirect(); $this->post('/sharp/s-list/person/s-form/person/50')->assertForbidden(); $this->delete('/sharp/s-list/person/s-show/person/50')->assertForbidden(); @@ -82,7 +82,7 @@ ->setProhibitedActions(['delete', 'update']); $this - ->get('/sharp/s-list/person/s-form/person') + ->get('/sharp/root/s-list/person/s-form/person') ->assertInertia(fn (AssertableJson $json) => $json ->where('form.authorizations', [ 'delete' => false, @@ -92,7 +92,7 @@ ]) ); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertInertia(fn (AssertableJson $json) => $json ->where('show.authorizations', [ 'delete' => false, @@ -118,7 +118,7 @@ public function findSingle(): array fakePolicyFor('single_person', new class() extends SharpEntityPolicy {}); $this - ->get('/sharp/s-show/single_person') + ->get('/sharp/root/s-show/single_person') ->assertOk() ->assertInertia(fn (AssertableJson $json) => $json ->where('show.authorizations', [ @@ -147,7 +147,7 @@ public function getListData(): array|Arrayable ->setProhibitedActions(['delete']); $this - ->get('/sharp/s-list/person') + ->get('/sharp/root/s-list/person') ->assertInertia(fn (AssertableJson $json) => $json ->where('entityList.authorizations.reorder', true) ->where('entityList.authorizations.create', true) @@ -172,7 +172,7 @@ public function getListData(): array|Arrayable // Create (no instanceId, only create is allowed) $this - ->get('/sharp/s-list/person/s-form/person') + ->get('/sharp/root/s-list/person/s-form/person') ->assertInertia(fn (AssertableJson $json) => $json ->where('form.authorizations', [ 'delete' => false, @@ -184,7 +184,7 @@ public function getListData(): array|Arrayable // Edit $this - ->get('/sharp/s-list/person/s-form/person/1') + ->get('/sharp/root/s-list/person/s-form/person/1') ->assertInertia(fn (AssertableJson $json) => $json ->where('form.authorizations', [ 'delete' => true, @@ -196,7 +196,7 @@ public function getListData(): array|Arrayable // EL (inertia) $this - ->get('/sharp/s-list/person') + ->get('/sharp/root/s-list/person') ->assertInertia(fn (AssertableJson $json) => $json ->where('entityList.authorizations.reorder', true) ->where('entityList.authorizations.create', true) @@ -208,7 +208,7 @@ public function getListData(): array|Arrayable // EEL (json) $this - ->getJson('/sharp/api/list/person') + ->getJson('/sharp/api/root/list/person') ->assertJson(fn (AssertableJson $json) => $json ->where('authorizations.reorder', true) ->where('authorizations.create', true) @@ -228,12 +228,12 @@ public function getListData(): array|Arrayable ]) ->setProhibitedActions(['delete']); - $this->get('/sharp/s-list/person/s-form/person:big')->assertOk(); + $this->get('/sharp/root/s-list/person/s-form/person:big')->assertOk(); $this->post('/sharp/s-list/person/s-form/person:big')->assertRedirect(); - $this->get('/sharp/s-list/person/s-form/person:big/50')->assertOk(); + $this->get('/sharp/root/s-list/person/s-form/person:big/50')->assertOk(); $this->post('/sharp/s-list/person/s-form/person:big/50')->assertRedirect(); $this->delete('/sharp/s-list/person/s-show/person:big/50')->assertForbidden(); - $this->get('/sharp/s-list/person')->assertOk(); + $this->get('/sharp/root/s-list/person')->assertOk(); }); it('handles custom auth check', function () { @@ -249,11 +249,11 @@ public function check($user): bool ); login(new User(['name' => 'ok'])); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk(); login(new User(['name' => 'ko'])); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertRedirect(route('code16.sharp.login')); }); @@ -261,10 +261,10 @@ public function check($user): bool Gate::define('viewSharp', fn ($user) => $user->name === 'ok'); login(new User(['name' => 'ok'])); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk(); login(new User(['name' => 'ko'])); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertRedirect(route('code16.sharp.login')); }); diff --git a/tests/Http/Auth/PolicyAuthorizationsTest.php b/tests/Http/Auth/PolicyAuthorizationsTest.php index 11b1b1952..2c03b4c4a 100644 --- a/tests/Http/Auth/PolicyAuthorizationsTest.php +++ b/tests/Http/Auth/PolicyAuthorizationsTest.php @@ -33,10 +33,10 @@ public function delete($user, $instanceId): bool } }); - $this->get('/sharp/s-list/person')->assertOk(); - $this->get('/sharp/s-list/person/s-show/person/1')->assertOk(); - $this->get('/sharp/s-list/person/s-form/person/1')->assertOk(); - $this->get('/sharp/s-list/person/s-form/person')->assertOk(); + $this->get('/sharp/root/s-list/person')->assertOk(); + $this->get('/sharp/root/s-list/person/s-show/person/1')->assertOk(); + $this->get('/sharp/root/s-list/person/s-form/person/1')->assertOk(); + $this->get('/sharp/root/s-list/person/s-form/person')->assertOk(); $this->post('/sharp/s-list/person/s-form/person/1')->assertRedirect(); $this->post('/sharp/s-list/person/s-form/person')->assertRedirect(); @@ -62,7 +62,7 @@ public function delete($user, $instanceId): bool }); $this - ->get('/sharp/s-list/person/s-form/person') + ->get('/sharp/root/s-list/person/s-form/person') ->assertInertia(fn (Assert $page) => $page ->where('form.authorizations', [ 'delete' => false, @@ -72,7 +72,7 @@ public function delete($user, $instanceId): bool ]) ); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertInertia(fn (Assert $page) => $page ->where('show.authorizations', [ 'delete' => false, @@ -82,7 +82,7 @@ public function delete($user, $instanceId): bool ]) ); - $this->get('/sharp/s-list/person/s-show/person/2') + $this->get('/sharp/root/s-list/person/s-show/person/2') ->assertInertia(fn (Assert $page) => $page ->where('show.authorizations', [ 'delete' => false, @@ -102,11 +102,11 @@ public function update($user, $instanceId): bool } }); - $this->get('/sharp/s-list/person/s-form/person/2')->assertForbidden(); + $this->get('/sharp/root/s-list/person/s-form/person/2')->assertForbidden(); fakeShowFor('person', null); - $this->get('/sharp/s-list/person/s-form/person/2')->assertOk(); + $this->get('/sharp/root/s-list/person/s-form/person/2')->assertOk(); }); it('returns policies with a list get request', function () { @@ -130,7 +130,7 @@ public function delete($user, $instanceId): bool }); $this - ->get('/sharp/s-list/person') + ->get('/sharp/root/s-list/person') ->assertInertia(fn (Assert $page) => $page ->where('entityList.authorizations', [ 'reorder' => true, @@ -168,7 +168,7 @@ public function entity($user): bool $this ->actingAs(new User(['name' => 'bob'])) - ->get('/sharp/s-list/person/s-show/person/1') + ->get('/sharp/root/s-list/person/s-show/person/1') ->assertInertia(fn (Assert $page) => $page ->where('show.fields.'.PersonPhysicistEntity::class.'.authorizations', [ 'view' => false, @@ -177,7 +177,7 @@ public function entity($user): bool $this ->actingAs(new User(['name' => 'admin'])) - ->get('/sharp/s-list/person/s-show/person/1') + ->get('/sharp/root/s-list/person/s-show/person/1') ->assertInertia(fn (Assert $page) => $page ->where('show.fields.'.PersonPhysicistEntity::class.'.authorizations', [ 'view' => true, @@ -206,7 +206,7 @@ public function entity($user): bool $this ->actingAs(new User(['name' => 'bob'])) - ->get('/sharp/s-list/person/s-show/person/1') + ->get('/sharp/root/s-list/person/s-show/person/1') ->assertInertia(fn (Assert $page) => $page ->where('show.fields.'.DashboardEntity::class.'.authorizations', [ 'view' => false, @@ -215,7 +215,7 @@ public function entity($user): bool $this ->actingAs(new User(['name' => 'admin'])) - ->get('/sharp/s-list/person/s-show/person/1') + ->get('/sharp/root/s-list/person/s-show/person/1') ->assertInertia(fn (Assert $page) => $page ->where('show.fields.'.DashboardEntity::class.'.authorizations', [ 'view' => true, @@ -237,7 +237,7 @@ public function update($user, $instanceId): bool }); $this - ->get('/sharp/s-list/person/s-show/person/1') + ->get('/sharp/root/s-list/person/s-show/person/1') ->assertInertia(fn (Assert $page) => $page ->where('show.authorizations.update', false) ); @@ -254,7 +254,7 @@ public function entity($user): bool login(new User(['name' => 'unauthorized-user'])); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertForbidden(); }); @@ -271,11 +271,11 @@ public function entity($user): bool login(new User(['name' => 'unauthorized-user'])); - $this->get('/sharp/s-dashboard/'.DashboardEntity::$entityKey)->assertForbidden(); + $this->get('/sharp/root/s-dashboard/'.DashboardEntity::$entityKey)->assertForbidden(); }); it('does not check view, update and delete policies on create case', function () { - $this->get('/sharp/s-list/person/s-form/person') + $this->get('/sharp/root/s-list/person/s-form/person') ->assertInertia(fn (Assert $page) => $page ->where('form.authorizations', [ 'delete' => false, From ac91f507c07ded4a3c320aa13711151133eeec51 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 10 Dec 2025 12:46:09 +0100 Subject: [PATCH 03/26] WIP fix more tests --- tests/Http/Context/SharpContextTest.php | 26 ++++++------ tests/Http/DashboardControllerTest.php | 6 +-- tests/Http/DataLocalizationTest.php | 14 +++---- tests/Http/EntityListControllerTest.php | 44 ++++++++++---------- tests/Http/ExceptionTest.php | 12 +++--- tests/Http/Form/FormControllerTest.php | 44 ++++++++++---------- tests/Http/GlobalFilterControllerTest.php | 4 +- tests/Http/ShowControllerTest.php | 32 +++++++------- tests/Unit/Utils/CurrentSharpRequestTest.php | 14 +++---- tests/Unit/Utils/FakesBreadcrumb.php | 5 +-- 10 files changed, 100 insertions(+), 101 deletions(-) diff --git a/tests/Http/Context/SharpContextTest.php b/tests/Http/Context/SharpContextTest.php index f1b00407b..3d029e6f2 100644 --- a/tests/Http/Context/SharpContextTest.php +++ b/tests/Http/Context/SharpContextTest.php @@ -13,7 +13,7 @@ uses(FakesBreadcrumb::class); it('allows to get form update state from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/1/s-form/child/2'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/1/s-form/child/2'); expect(sharp()->context()) ->isForm()->toBeTrue() @@ -28,7 +28,7 @@ app()->bind('child_entity', fn () => new class() extends SharpEntity {}); sharp()->config()->addEntity('child', 'child_entity'); - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/1/s-form/child'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/1/s-form/child'); expect(sharp()->context()) ->isForm()->toBeTrue() @@ -39,7 +39,7 @@ }); it('allows to get show state from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/1'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/1'); expect(sharp()->context()) ->isForm()->toBeFalse() @@ -50,7 +50,7 @@ }); it('allows to get entity list state from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person'); expect(sharp()->context()) ->isForm()->toBeFalse() @@ -61,7 +61,7 @@ }); it('allows to get current breadcrumb item from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/1/s-form/child/2'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/1/s-form/child/2'); expect(sharp()->context()->breadcrumb()->currentSegment()) ->isForm()->toBeTrue() @@ -71,7 +71,7 @@ }); it('allows to get previous show from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/42/s-form/child/2'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/42/s-form/child/2'); expect(sharp()->context()->breadcrumb()->previousShowSegment()) ->entityKey()->toBe('person') @@ -79,7 +79,7 @@ }); it('allows to get previous show of a given key from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/31/s-show/person/42/s-show/child/84/s-form/child/84'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/31/s-show/person/42/s-show/child/84/s-form/child/84'); expect(sharp()->context()->breadcrumb()) ->previousShowSegment()->entityKey()->toBe('child') @@ -90,7 +90,7 @@ it('allows to get previous show of a given entity class name from request', function () { app(SharpConfigBuilder::class)->declareEntity(PersonEntity::class); - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/31/s-show/person/42/s-show/child/84/s-form/child/84'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/31/s-show/person/42/s-show/child/84/s-form/child/84'); expect(sharp()->context()->breadcrumb()) ->previousShowSegment()->entityKey()->toBe('child') @@ -104,7 +104,7 @@ app(SharpEntityManager::class)->entityFor('person')->setMultiforms([ 'multiform' => [PersonForm::class, 'Multiform'], ]); - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/31/s-show/person:multiform/42/s-show/child:multiform/84/s-form/child/84'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/31/s-show/person:multiform/42/s-show/child:multiform/84/s-form/child/84'); expect(sharp()->context()->breadcrumb()) ->previousShowSegment()->entityKey()->toBe('child:multiform') @@ -118,7 +118,7 @@ it('allows to check entity of a segment', function () { app(SharpConfigBuilder::class)->declareEntity(PersonEntity::class); app(SharpConfigBuilder::class)->declareEntity(SinglePersonEntity::class); - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/1/s-form/person/1'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/1/s-form/person/1'); expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs(PersonEntity::class))->toBeTrue(); expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs('person'))->toBeTrue(); @@ -137,7 +137,7 @@ app(SharpEntityManager::class)->entityFor('person')->setMultiforms([ 'multiform' => [PersonForm::class, 'Multiform'], ]); - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person:multiform/1/s-form/person:multiform/1'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person:multiform/1/s-form/person:multiform/1'); expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs(PersonEntity::class))->toBeTrue(); expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs('person'))->toBeTrue(); @@ -156,10 +156,10 @@ }); it('allows to get previous url from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/42/s-form/child/2'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/42/s-form/child/2'); expect(sharp()->context()->breadcrumb()->getPreviousSegmentUrl()) - ->toEqual(url('/sharp/s-list/person/s-show/person/42')); + ->toEqual(url('/sharp/root/s-list/person/s-show/person/42')); }); it('allow to retrieve retained filters value in the context', function () { diff --git a/tests/Http/DashboardControllerTest.php b/tests/Http/DashboardControllerTest.php index 10311bacd..8f1474747 100644 --- a/tests/Http/DashboardControllerTest.php +++ b/tests/Http/DashboardControllerTest.php @@ -56,7 +56,7 @@ protected function buildWidgetsData(): void $this->withoutExceptionHandling(); - $this->get('/sharp/s-dashboard/'.DashboardEntity::$entityKey) + $this->get('/sharp/root/s-dashboard/'.DashboardEntity::$entityKey) ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('dashboard', fn (Assert $dashboard) => $dashboard @@ -90,7 +90,7 @@ public function buildPageAlert(PageAlert $pageAlert): void } }); - $this->get('/sharp/s-dashboard/'.DashboardEntity::$entityKey) + $this->get('/sharp/root/s-dashboard/'.DashboardEntity::$entityKey) ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('dashboard.pageAlert', [ @@ -127,7 +127,7 @@ protected function buildWidgetsData(): void } }); - $this->get('/sharp/s-dashboard/'.DashboardEntity::$entityKey) + $this->get('/sharp/root/s-dashboard/'.DashboardEntity::$entityKey) ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('dashboard.pageAlert', [ diff --git a/tests/Http/DataLocalizationTest.php b/tests/Http/DataLocalizationTest.php index f94a5b5f9..63da1a739 100644 --- a/tests/Http/DataLocalizationTest.php +++ b/tests/Http/DataLocalizationTest.php @@ -38,13 +38,13 @@ public function getDataLocalizations(): array } }); - $this->get('/sharp/s-list/person/s-form/person') + $this->get('/sharp/root/s-list/person/s-form/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.locales', ['fr', 'en']) ); - $this->get('/sharp/s-list/person/s-form/person/1') + $this->get('/sharp/root/s-list/person/s-form/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.locales', ['fr', 'en']) @@ -70,7 +70,7 @@ public function find(mixed $id): array $this->withoutExceptionHandling(); - $this->get('/sharp/s-list/person/s-form/person'); + $this->get('/sharp/root/s-list/person/s-form/person'); }) ->throws(\Code16\Sharp\Exceptions\SharpInvalidConfigException::class, 'The "name" field is localized but no locales are defined'); @@ -95,7 +95,7 @@ public function getDataLocalizations(): array } }); - $this->get('/sharp/s-list/person/s-form/person') + $this->get('/sharp/root/s-list/person/s-form/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.locales', []) @@ -126,13 +126,13 @@ public function getDataLocalizations(): array } }); - $this->get('/sharp/s-list/person/s-form/person') + $this->get('/sharp/root/s-list/person/s-form/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.locales', ['fr', 'en']) ); - $this->get('/sharp/s-list/person/s-form/person/1') + $this->get('/sharp/root/s-list/person/s-form/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.locales', ['fr', 'en']) @@ -161,7 +161,7 @@ public function getDataLocalizations(): array } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.locales', ['fr', 'en']) diff --git a/tests/Http/EntityListControllerTest.php b/tests/Http/EntityListControllerTest.php index 4e3160784..43c13c1bf 100644 --- a/tests/Http/EntityListControllerTest.php +++ b/tests/Http/EntityListControllerTest.php @@ -38,7 +38,7 @@ public function getListData(): array|Arrayable } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.data.0', fn (Assert $json) => $json @@ -67,7 +67,7 @@ public function getListData(): array|Arrayable } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.data.0', fn (Assert $json) => $json @@ -108,7 +108,7 @@ public function getListData(): array|Arrayable fakeShowFor('person', null); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.data.0', fn (Assert $json) => $json @@ -163,7 +163,7 @@ public function buildListConfig(): void } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.data.0', fn (Assert $json) => $json @@ -203,7 +203,7 @@ public function getListData(): array|Arrayable } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.data.0', fn (Assert $json) => $json @@ -258,7 +258,7 @@ public function buildListConfig(): void } }); - $this->get('/sharp/s-list/person?search=Curie') + $this->get('/sharp/root/s-list/person?search=Curie') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.data.0', fn (Assert $json) => $json @@ -286,7 +286,7 @@ public function getListData(): array|Arrayable } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->missing('entityList.data.list.items.0.job') @@ -318,7 +318,7 @@ public function buildList(EntityListFieldsContainer $fields): void } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.fields', 3) @@ -360,7 +360,7 @@ public function buildListConfig(): void } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.config', fn (Assert $config) => $config @@ -398,7 +398,7 @@ public function delete($user, $instanceId): bool } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('entityList.authorizations', [ @@ -441,7 +441,7 @@ public function buildListConfig(): void 'nope' => [PersonForm::class, 'No Nobel prize'], ]); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.entities', 2) @@ -495,7 +495,7 @@ public function buildListConfig(): void 'nope' => [PersonForm::class, 'No Nobel prize'], ]); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.data.0', fn (Assert $json) => $json @@ -512,7 +512,7 @@ public function buildListConfig(): void ->entityFor('person') ->setForm(null); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.data.0', fn (Assert $json) => $json @@ -556,7 +556,7 @@ public function buildListConfig(): void } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.entities', 3) @@ -593,7 +593,7 @@ public function buildListConfig(): void $this->withoutExceptionHandling(); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('notifications', 1) @@ -605,7 +605,7 @@ public function buildListConfig(): void ) ); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('notifications', 0) @@ -614,7 +614,7 @@ public function buildListConfig(): void (new PersonForm())->notify('title1'); (new PersonForm())->notify('title2'); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('notifications', 2) @@ -622,14 +622,14 @@ public function buildListConfig(): void }); it('returns a 404 with invalid entity key', function () { - $this->get('/sharp/s-list/not-a-valid-entity-key') + $this->get('/sharp/root/s-list/not-a-valid-entity-key') ->assertStatus(404); }); it('handles hasShowPage in config', function () { fakeShowFor('person', new PersonShow()); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.config', fn (Assert $config) => $config @@ -640,7 +640,7 @@ public function buildListConfig(): void fakeShowFor('person', null); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('entityList.config', fn (Assert $config) => $config @@ -664,7 +664,7 @@ public function buildPageAlert(PageAlert $pageAlert): void } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('entityList.pageAlert', [ @@ -698,7 +698,7 @@ public function getListData(): array|Arrayable } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('entityList.pageAlert', [ diff --git a/tests/Http/ExceptionTest.php b/tests/Http/ExceptionTest.php index 4e8c259a4..508fc3c37 100644 --- a/tests/Http/ExceptionTest.php +++ b/tests/Http/ExceptionTest.php @@ -20,7 +20,7 @@ public function getListData(): array } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertStatus(500) ->assertInertia(fn (Assert $page) => $page ->component('Error') @@ -38,7 +38,7 @@ public function getListData(): array } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertStatus(404) ->assertInertia(fn (Assert $page) => $page ->component('Error') @@ -56,7 +56,7 @@ public function getListData(): array } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertStatus(403) ->assertInertia(fn (Assert $page) => $page ->component('Error') @@ -72,7 +72,7 @@ public function getListData(): array } }); - $this->get('/sharp/s-list/person') + $this->get('/sharp/root/s-list/person') ->assertStatus(417) ->assertInertia(fn (Assert $page) => $page ->component('Error') @@ -94,7 +94,7 @@ public function getListData(): array config()->set('app.debug', true); - $response = $this->get('/sharp/s-list/person') + $response = $this->get('/sharp/root/s-list/person') ->assertStatus(500); // response is not rendered in inertia @@ -114,7 +114,7 @@ public function getListData(): array config()->set('app.debug', true); - $this->getJson('/sharp/api/list/person') + $this->getJson('/sharp/api/root/list/person') ->assertStatus(500) ->assertHeader('Content-Type', 'text/html; charset=utf-8'); }); diff --git a/tests/Http/Form/FormControllerTest.php b/tests/Http/Form/FormControllerTest.php index 94e2694d0..ca99693ab 100644 --- a/tests/Http/Form/FormControllerTest.php +++ b/tests/Http/Form/FormControllerTest.php @@ -40,7 +40,7 @@ public function find($id): array } }); - $this->get('/sharp/s-list/person/s-form/person/1') + $this->get('/sharp/root/s-list/person/s-form/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.data.name', 'James Clerk Maxwell') @@ -59,7 +59,7 @@ public function create(): array } }); - $this->get('/sharp/s-list/person/s-form/person') + $this->get('/sharp/root/s-list/person/s-form/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.data.name', 'Who is this guy?') @@ -84,7 +84,7 @@ public function find($id): array } }); - $this->get('/sharp/s-list/person/s-form/person/1') + $this->get('/sharp/root/s-list/person/s-form/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('form.data.name') @@ -102,7 +102,7 @@ public function buildFormFields(FieldsContainer $formFields): void } }); - $this->get('/sharp/s-list/person/s-form/person/1') + $this->get('/sharp/root/s-list/person/s-form/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('form.fields.name', fn (Assert $page) => $page @@ -137,7 +137,7 @@ public function buildFormLayout(FormLayout $formLayout): void } }); - $this->get('/sharp/s-list/person/s-form/person/1') + $this->get('/sharp/root/s-list/person/s-form/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('form.layout.tabs.0.columns.0', fn (Assert $page) => $page @@ -172,13 +172,13 @@ public function buildFormLayout(FormLayout $formLayout): void }); it('redirects to the show after an update', function () { - $this->get('/sharp/s-list/person/s-show/person/1/s-form/person/1'); + $this->get('/sharp/root/s-list/person/s-show/person/1/s-form/person/1'); $this ->post('/sharp/s-list/person/s-show/person/1/s-form/person/1', [ 'name' => 'Stephen Hawking', ]) - ->assertRedirectContains('/sharp/s-list/person/s-show/person/1') + ->assertRedirectContains('/sharp/root/s-list/person/s-show/person/1') ->assertRedirectContains('highlighted_entity_key=person') ->assertRedirectContains('highlighted_instance_id=1'); }); @@ -196,7 +196,7 @@ public function buildFormConfig(): void ->post('/sharp/s-list/person/s-form/person', [ 'name' => 'Stephen Hawking', ]) - ->assertRedirect('/sharp/s-list/person/s-show/person/1'); + ->assertRedirect('/sharp/root/s-list/person/s-show/person/1'); }); it('logs an error if the update() method does not return the instance id', function () { @@ -356,7 +356,7 @@ public function find($id): array }); $this - ->get('/sharp/s-list/person/s-form/person/5') + ->get('/sharp/root/s-list/person/s-form/person/5') ->assertStatus(417); }); @@ -373,7 +373,7 @@ public function findSingle(): array } }); - $this->get('/sharp/s-show/single-person/s-form/single-person') + $this->get('/sharp/root/s-show/single-person/s-form/single-person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.data.name', 'Ernest Rutherford') @@ -387,7 +387,7 @@ public function findSingle(): array ->post('/sharp/s-show/single-person/s-form/single-person', [ 'name' => 'Stephen Hawking', ]) - ->assertRedirect('/sharp/s-show/single-person'); + ->assertRedirect('/sharp/root/s-show/single-person'); }); it('gets form data for an instance of a sub entity (multiforms case)', function () { @@ -424,13 +424,13 @@ public function find($id): array ], ]); - $this->get('/sharp/s-list/person/s-form/person:nobelized/1') + $this->get('/sharp/root/s-list/person/s-form/person:nobelized/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.data.name', 'Marie Curie') ); - $this->get('/sharp/s-list/person/s-form/person:nope/1') + $this->get('/sharp/root/s-list/person/s-form/person:nope/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.data.name', 'Rosalind Franklin') @@ -451,7 +451,7 @@ public function buildPageAlert(PageAlert $pageAlert): void } }); - $this->get('/sharp/s-list/person/s-form/person/1') + $this->get('/sharp/root/s-list/person/s-form/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.pageAlert', [ @@ -485,7 +485,7 @@ public function find($id): array } }); - $this->get('/sharp/s-list/person/s-form/person/1') + $this->get('/sharp/root/s-list/person/s-form/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.pageAlert', [ @@ -534,10 +534,10 @@ public function find($id): array fakeFormFor('person', new PersonForm()); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk(); - $this->get('/sharp/s-list/person/s-show/person/1/s-form/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1/s-form/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.title', 'Edit “Marie Curie”') @@ -577,10 +577,10 @@ public function find($id): array } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk(); - $this->get('/sharp/s-list/person/s-show/person/1/s-form/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1/s-form/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.title', 'Edit “Albert Einstein”') @@ -597,13 +597,13 @@ public function buildFormConfig(): void } }); - $this->get('/sharp/s-list/person/s-form/person/1') + $this->get('/sharp/root/s-list/person/s-form/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.title', 'My custom edit title') ); - $this->get('/sharp/s-list/person/s-form/person') + $this->get('/sharp/root/s-list/person/s-form/person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.title', 'My custom create title') @@ -674,7 +674,7 @@ public function find($id): array public function update(mixed $id, array $data) {} }); - $this->get('/sharp/s-list/person/s-form/person/1') + $this->get('/sharp/root/s-list/person/s-form/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('form.data.html_string', '

Albert Einstein

example

') diff --git a/tests/Http/GlobalFilterControllerTest.php b/tests/Http/GlobalFilterControllerTest.php index a440310ed..5686951ca 100644 --- a/tests/Http/GlobalFilterControllerTest.php +++ b/tests/Http/GlobalFilterControllerTest.php @@ -62,7 +62,7 @@ public function defaultValue(): mixed sharp()->config()->declareEntity(PersonEntity::class); $this - ->get('/sharp/s-list/person') + ->get('/sharp/root/s-list/person') ->assertInertia(fn (Assert $page) => $page ->has('globalFilters.config.filters._root.0', fn (Assert $filter) => $filter ->where('key', 'test') @@ -77,7 +77,7 @@ public function defaultValue(): mixed ->post(route('code16.sharp.filters.update', 'test'), ['value' => 3]); $this - ->get('/sharp/s-list/person') + ->get('/sharp/root/s-list/person') ->assertInertia(fn (Assert $page) => $page ->has('globalFilters.config.filters._root.0', fn (Assert $filter) => $filter ->where('key', 'test') diff --git a/tests/Http/ShowControllerTest.php b/tests/Http/ShowControllerTest.php index 6c4600299..3ecae2bf3 100644 --- a/tests/Http/ShowControllerTest.php +++ b/tests/Http/ShowControllerTest.php @@ -33,7 +33,7 @@ public function find($id): array } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.data.name', ['text' => 'James Clerk Maxwell']) @@ -52,7 +52,7 @@ public function find($id): array } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.data.name', ['text' => 'James Clerk Maxwell']) @@ -76,7 +76,7 @@ public function find($id): array } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('show.data.name') @@ -114,7 +114,7 @@ public function find($id): array } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('show.data.name') @@ -133,7 +133,7 @@ public function buildShowFields(FieldsContainer $showFields): void } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('show.fields.name', fn (Assert $page) => $page @@ -170,7 +170,7 @@ public function buildShowLayout(ShowLayout $showLayout): void $this->withoutExceptionHandling(); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->has('show.layout.sections.0.columns.0', fn (Assert $page) => $page @@ -191,7 +191,7 @@ public function buildShowConfig(): void } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.config.breadcrumbAttribute', 'name') @@ -211,7 +211,7 @@ public function findSingle(): array } }); - $this->get('/sharp/s-show/single-person') + $this->get('/sharp/root/s-show/single-person') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.data.name.text', 'Ernest Rutherford') @@ -273,13 +273,13 @@ public function authorizeFor(mixed $instanceId): bool } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.config.commands.instance.0.0.authorization', true) ); - $this->get('/sharp/s-list/person/s-show/person/11') + $this->get('/sharp/root/s-list/person/s-show/person/11') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.config.commands.instance.0.0.authorization', false) @@ -298,7 +298,7 @@ public function buildPageAlert(PageAlert $pageAlert): void } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.pageAlert', [ @@ -324,7 +324,7 @@ public function buildPageAlert(PageAlert $pageAlert): void } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.pageAlert', [ @@ -359,7 +359,7 @@ public function find($id): array } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.pageAlert', [ @@ -385,7 +385,7 @@ public function find($id): array } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.data.name', ['text' => 'JAMES CLERK MAXWELL']) @@ -409,7 +409,7 @@ public function find($id): array } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.title', 'James Clerk Maxwell') @@ -441,7 +441,7 @@ public function getDataLocalizations(): array } }); - $this->get('/sharp/s-list/person/s-show/person/1') + $this->get('/sharp/root/s-list/person/s-show/person/1') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->where('show.title', [ diff --git a/tests/Unit/Utils/CurrentSharpRequestTest.php b/tests/Unit/Utils/CurrentSharpRequestTest.php index ebce11fd5..ad3439f0c 100644 --- a/tests/Unit/Utils/CurrentSharpRequestTest.php +++ b/tests/Unit/Utils/CurrentSharpRequestTest.php @@ -6,7 +6,7 @@ uses(FakesBreadcrumb::class); it('allows to get form update state from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/1/s-form/child/2'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/1/s-form/child/2'); expect(currentSharpRequest()->isForm())->toBeTrue() ->and(currentSharpRequest()->isUpdate())->toBeTrue() @@ -20,7 +20,7 @@ app()->bind('child_entity', fn () => new class() extends SharpEntity {}); sharp()->config()->addEntity('child', 'child_entity'); - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/1/s-form/child'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/1/s-form/child'); expect(currentSharpRequest()->isForm())->toBeTrue() ->and(currentSharpRequest()->isUpdate())->toBeFalse() @@ -30,7 +30,7 @@ }); it('allows to get show state from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/1'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/1'); expect(currentSharpRequest()->isForm())->toBeFalse() ->and(currentSharpRequest()->isUpdate())->toBeFalse() @@ -40,7 +40,7 @@ }); it('allows to get entity list state from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person'); expect(currentSharpRequest()->isForm())->toBeFalse() ->and(currentSharpRequest()->isUpdate())->toBeFalse() @@ -50,7 +50,7 @@ }); it('allows to get current breadcrumb item from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/1/s-form/child/2'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/1/s-form/child/2'); expect(currentSharpRequest()->getCurrentBreadcrumbItem()->isForm())->toBeTrue() ->and(currentSharpRequest()->getCurrentBreadcrumbItem()->isSingleForm())->toBeFalse() @@ -59,14 +59,14 @@ }); it('allows to get previous show from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/42/s-form/child/2'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/42/s-form/child/2'); expect(currentSharpRequest()->getPreviousShowFromBreadcrumbItems()->entityKey())->toBe('person') ->and(currentSharpRequest()->getPreviousShowFromBreadcrumbItems()->instanceId())->toEqual(42); }); it('allows to get previous show of a given key from request', function () { - $this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/31/s-show/person/42/s-show/child/84/s-form/child/84'); + $this->fakeBreadcrumbWithUrl('/sharp/root/s-list/person/s-show/person/31/s-show/person/42/s-show/child/84/s-form/child/84'); expect(currentSharpRequest()->getPreviousShowFromBreadcrumbItems()->entityKey())->toBe('child') ->and(currentSharpRequest()->getPreviousShowFromBreadcrumbItems()->instanceId())->toEqual(84) diff --git a/tests/Unit/Utils/FakesBreadcrumb.php b/tests/Unit/Utils/FakesBreadcrumb.php index a3cf85f2d..88fee2377 100644 --- a/tests/Unit/Utils/FakesBreadcrumb.php +++ b/tests/Unit/Utils/FakesBreadcrumb.php @@ -24,9 +24,8 @@ public function __construct(string $url) protected function getSegmentsFromRequest(): Collection { return collect(explode('/', parse_url(url($this->url))['path'])) - ->filter(fn (string $segment) => strlen(trim($segment)) - && $segment !== sharp()->config()->get('custom_url_segment') - ) + ->filter() + ->skip(2) ->values(); } }; From 73fb7864fab379fed007ef138b95f05480968eaf Mon Sep 17 00:00:00 2001 From: antoine Date: Wed, 10 Dec 2025 15:51:40 +0100 Subject: [PATCH 04/26] fix show edit form url --- resources/js/Pages/Show/Show.vue | 2 +- .../js/entity-list/components/EntityList.vue | 4 +- resources/js/show/Show.ts | 16 ------ resources/js/types/generated.d.ts | 1 + resources/js/types/routes.d.ts | 44 +++++++++++++-- resources/js/utils/url.ts | 3 -- src/Data/Show/ShowConfigData.php | 1 + src/Http/Controllers/ShowController.php | 9 +++- src/Http/Controllers/SingleShowController.php | 8 ++- tests/Http/ShowControllerTest.php | 53 ++++++++++++++++++- 10 files changed, 112 insertions(+), 29 deletions(-) diff --git a/resources/js/Pages/Show/Show.vue b/resources/js/Pages/Show/Show.vue index fec820e87..93f3a37b8 100644 --- a/resources/js/Pages/Show/Show.vue +++ b/resources/js/Pages/Show/Show.vue @@ -340,7 +340,7 @@