temporary = sys_get_temp_dir().'/livewire-material-errors-'.Str::random(8); File::ensureDirectoryExists($this->temporary); Route::middleware('web')->get('/abort/{code}', fn (string $code) => abort((int) $code, request()->query('message', ''))); }); afterEach(function () { File::deleteDirectory($this->temporary); }); /** * Testbench's skeleton application ships an errors/503.blade.php of its own — an application * view, which rightly wins over the package's. A test of the package's 503 stands in an * application without one. */ function withoutSkeletonErrorViews(): void { $views = test()->temporary.'/views'; File::ensureDirectoryExists($views); config(['view.paths' => [$views, LivewireMaterialServiceProvider::errorViewPath()]]); } it('renders the package page for each status', function (int $code, string $headline, string $sentence) { withoutSkeletonErrorViews(); $this->withoutVite() ->get("/abort/{$code}") ->assertStatus($code) ->assertSee('data-md-error-page', false) ->assertSee("{$code}
", false) ->assertSee($headline) ->assertSee($sentence); })->with([ [403, 'You don’t have access', 'Your account isn’t allowed to open this page.'], [404, 'Page not found', 'The page you’re looking for doesn’t exist or has moved.'], [419, 'This page has expired', 'Refresh the page'], [429, 'Slow down a little', 'Wait a moment, then try again.'], [500, 'Something went wrong', 'An error on our side'], [503, 'We’ll be right back', 'We’re making some improvements.'], ]); it('draws the framework\'s own error pages in the package layout', function () { $this->withoutVite() ->get('/abort/401') ->assertStatus(401) ->assertSee('data-md-error-page', false) ->assertSee('Unauthorized') ->assertSee('Go home'); }); it('appends the error-view root to view.paths after the application\'s, before the view finder is built', function () { $root = LivewireMaterialServiceProvider::errorViewPath(); expect(realpath($root))->toBe(realpath(__DIR__.'/../../resources/views/error-pages')) ->and(File::directories($root))->toBe([$root.'/errors']) ->and(config('view.paths'))->toBe([resource_path('views'), $root]) ->and(app()->viewPath())->toBe(resource_path('views')) ->and(app('view')->getFinder()->getPaths())->toContain($root); $provider = app()->getProvider(LivewireMaterialServiceProvider::class); (fn () => $this->registerErrorViews())->call($provider); expect(config('view.paths'))->toBe([resource_path('views'), $root]); }); it('lets the application\'s own error view win', function () { File::ensureDirectoryExists($this->temporary.'/errors'); File::put($this->temporary.'/errors/404.blade.php', 'The application view'); config(['view.paths' => [$this->temporary, ...config('view.paths')]]); $this->withoutVite() ->get('/abort/404') ->assertNotFound() ->assertSee('The application view') ->assertDontSee('data-md-error-page', false); $this->get('/abort/403')->assertSee('data-md-error-page', false); }); it('loads the application\'s Vite entries', function () { File::ensureDirectoryExists($this->temporary.'/build'); File::put($this->temporary.'/build/manifest.json', json_encode([ 'workbench/resources/css/package.css' => ['file' => 'assets/package-probe.css', 'src' => 'workbench/resources/css/package.css', 'isEntry' => true], 'workbench/resources/css/app.css' => ['file' => 'assets/app-probe.css', 'src' => 'workbench/resources/css/app.css', 'isEntry' => true], 'workbench/resources/js/app.js' => ['file' => 'assets/app-probe.js', 'src' => 'workbench/resources/js/app.js', 'isEntry' => true], ])); app()->usePublicPath($this->temporary); Vite::useHotFile($this->temporary.'/hot'); $this->get('/abort/404') ->assertNotFound() ->assertSee('build/assets/package-probe.css', false) ->assertSee('build/assets/app-probe.css', false) ->assertSee('build/assets/app-probe.js', false) ->assertDontSee('data-md-error-fallback', false); }); it('still renders, in the application\'s scheme, when the Vite manifest is missing', function () { File::put($this->temporary.'/material-scheme.json', json_encode([ 'light' => ['surface' => '#fafaf0', 'primary' => '#123456'], 'dark' => ['surface' => '#101010'], ])); config(['livewire-material.scheme' => $this->temporary.'/material-scheme.json']); app()->usePublicPath($this->temporary); Vite::useHotFile($this->temporary.'/hot'); $this->get('/abort/500') ->assertStatus(500) ->assertSee('Something went wrong') ->assertSee('