  ....⨯...
  ────────────────────────────────────────────────────────────────────────────
   FAILED  Tests\Feature\Admin\DiscountManagementTest > admin discount form…
  Expected response status code [201, 301, 302, 303, 307, 308] but received 500.
Failed asserting that false is true.

The following exception occurred during the last request:

ErrorException: Undefined property: Livewire\Features\SupportRedirects\Redirector::$headers in /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php:189
Stack trace:
#0 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(258): Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2, 'Undefined prope...', '/Users/fabianwe...', 189)
#1 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(189): Illuminate\Foundation\Bootstrap\HandleExceptions->{closure:Illuminate\Foundation\Bootstrap\HandleExceptions::forwardsTo():257}(2, 'Undefined prope...', '/Users/fabianwe...', 189)
#2 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(89): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->addCookieToResponse(Object(Illuminate\Http\Request), Object(Livewire\Features\SupportRedirects\Redirector))
#3 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Support/helpers.php(388): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->{closure:Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::handle():87}(Object(Livewire\Features\SupportRedirects\Redirector))
#4 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(87): tap(Object(Livewire\Features\SupportRedirects\Redirector), Object(Closure))
#5 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->handle(Object(Illuminate\Http\Request), Object(Closure))
#6 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(48): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#7 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#8 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(120): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#9 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(63): Illuminate\Session\Middleware\StartSession->handleStatefulRequest(Object(Illuminate\Http\Request), Object(Illuminate\Session\EncryptedStore), Object(Closure))
#10 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#11 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(36): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#12 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#13 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(74): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#14 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#15 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#16 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Routing/Router.php(821): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#17 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Routing/Router.php(800): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#18 /Users/fabianwesner/Herd/shop/vendo…5085 chars truncated…uminate/Http/Middleware/ValidatePathEncoding.php(26): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#41 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Http\Middleware\ValidatePathEncoding->handle(Object(Illuminate\Http\Request), Object(Closure))
#42 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#43 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#44 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#45 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php(607): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#46 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php(368): Illuminate\Foundation\Testing\TestCase->call('GET', '/admin/discount...', Array, Array, Array, Array)
#47 /Users/fabianwesner/Herd/shop/tests/Feature/Admin/DiscountManagementTest.php(183): Illuminate\Foundation\Testing\TestCase->get('/admin/discount...')
#48 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Factories/TestCaseMethodFactory.php(168): P\Tests\Feature\Admin\DiscountManagementTest->{closure:/Users/fabianwesner/Herd/shop/tests/Feature/Admin/DiscountManagementTest.php:162}()
#49 [internal function]: P\Tests\Feature\Admin\DiscountManagementTest->{closure:Pest\Factories\TestCaseMethodFactory::getClosure():158}()
#50 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Concerns/Testable.php(429): call_user_func_array(Object(Closure), Array)
#51 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Support/ExceptionTrace.php(26): P\Tests\Feature\Admin\DiscountManagementTest->{closure:Pest\Concerns\Testable::__callClosure():429}()
#52 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Concerns/Testable.php(429): Pest\Support\ExceptionTrace::ensure(Object(Closure))
#53 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Concerns/Testable.php(331): P\Tests\Feature\Admin\DiscountManagementTest->__callClosure(Object(Closure), Array)
#54 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Factories/TestCaseFactory.php(169) : eval()'d code(53): P\Tests\Feature\Admin\DiscountManagementTest->__runTest(Object(Closure))
#55 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestCase.php(1332): P\Tests\Feature\Admin\DiscountManagementTest->__pest_evaluable_admin_discount_form_enforces_mutation_policies_and_verified_users()
#56 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestCase.php(519): PHPUnit\Framework\TestCase->runTest()
#57 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestRunner/TestRunner.php(99): PHPUnit\Framework\TestCase->runBare()
#58 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestCase.php(359): PHPUnit\Framework\TestRunner->run(Object(P\Tests\Feature\Admin\DiscountManagementTest))
#59 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestSuite.php(374): PHPUnit\Framework\TestCase->run()
#60 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(64): PHPUnit\Framework\TestSuite->run()
#61 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/TextUI/Application.php(229): PHPUnit\TextUI\TestRunner->run(Object(PHPUnit\TextUI\Configuration\Configuration), Object(PHPUnit\Runner\ResultCache\DefaultResultCache), Object(PHPUnit\Framework\TestSuite))
#62 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Kernel.php(103): PHPUnit\TextUI\Application->run(Array)
#63 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/bin/pest(184): Pest\Kernel->handle(Array, Array)
#64 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/bin/pest(192): {closure:/Users/fabianwesner/Herd/shop/vendor/pestphp/pest/bin/pest:18}()
#65 {main}

----------------------------------------------------------------------------------

Undefined property: Livewire\Features\SupportRedirects\Redirector::$headers

  at tests/Feature/Admin/DiscountManagementTest.php:184
    180▕
    181▕     $this->actingAs($unverifiedUser)
    182▕         ->withSession(['current_store_id' => $store->getKey()])
    183▕         ->get('/admin/discounts/create')
  ➜ 184▕         ->assertRedirect('/email/verify');
    185▕
    186▕     Livewire::actingAs($supportUser)
    187▕         ->test(AdminDiscountForm::class)
    188▕         ->assertStatus(403);

  Tests:    1 failed, 7 passed (51 assertions)
  Duration: 3.18s


Output:
Chunk ID: 45888e
Wall time: 0.0000 seconds
Process exited with code 1
Original token count: 3772
Output:

  ....⨯...
  ────────────────────────────────────────────────────────────────────────────
   FAILED  Tests\Feature\Admin\DiscountManagementTest > admin discount form…
  Expected response status code [201, 301, 302, 303, 307, 308] but received 500.
Failed asserting that false is true.

The following exception occurred during the last request:

ErrorException: Undefined property: Livewire\Features\SupportRedirects\Redirector::$headers in /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php:189
Stack trace:
#0 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(258): Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2, 'Undefined prope...', '/Users/fabianwe...', 189)
#1 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(189): Illuminate\Foundation\Bootstrap\HandleExceptions->{closure:Illuminate\Foundation\Bootstrap\HandleExceptions::forwardsTo():257}(2, 'Undefined prope...', '/Users/fabianwe...', 189)
#2 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(89): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->addCookieToResponse(Object(Illuminate\Http\Request), Object(Livewire\Features\SupportRedirects\Redirector))
#3 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Support/helpers.php(388): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->{closure:Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::handle():87}(Object(Livewire\Features\SupportRedirects\Redirector))
#4 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(87): tap(Object(Livewire\Features\SupportRedirects\Redirector), Object(Closure))
#5 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->handle(Object(Illuminate\Http\Request), Object(Closure))
#6 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(48): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#7 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#8 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(120): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#9 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(63): Illuminate\Session\Middleware\StartSession->handleStatefulRequest(Object(Illuminate\Http\Request), Object(Illuminate\Session\EncryptedStore), Object(Closure))
#10 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#11 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(36): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#12 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#13 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(74): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#14 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#15 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#16 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Routing/Router.php(821): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#17 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Routing/Router.php(800): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#18 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Routing/Router.php(764): Illuminate\Routing\Router->runRoute(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))
#19 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Routing/Router.php(753): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#20 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(200): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#21 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Foundation\Http\Kernel->{closure:Illuminate\Foundation\Http\Kernel::dispatchToRouter():197}(Object(Illuminate\Http\Request))
#22 /Users/fabianwesner/Herd/shop/vendor/livewire/livewire/src/Features/SupportDisablingBackButtonCache/DisableBackButtonCacheMiddleware.php(19): Illuminate\Pipeline\Pipeline->{closure:Illuminate\Pipeline\Pipeline::prepareDestination():178}(Object(Illuminate\Http\Request))
#23 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Livewire\Features\SupportDisablingBackButtonCache\DisableBackButtonCacheMiddleware->handle(Object(Illuminate\Http\Request), Object(Closure))
#24 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#25 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))
#26 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull->handle(Object(Illuminate\Http\Request), Object(Closure))
#27 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#28 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(51): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))
#29 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Foundation\Http\Middleware\TrimStrings->handle(Object(Illuminate\Http\Request), Object(Closure))
#30 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php(27): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#31 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Http\Middleware\ValidatePostSize->handle(Object(Illuminate\Http\Request), Object(Closure))
#32 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(109): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#33 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle(Object(Illuminate\Http\Request), Object(Closure))
#34 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(61): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#35 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Http\Middleware\HandleCors->handle(Object(Illuminate\Http\Request), Object(Closure))
#36 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(58): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#37 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Http\Middleware\TrustProxies->handle(Object(Illuminate\Http\Request), Object(Closure))
#38 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php(22): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#39 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Foundation\Http\Middleware\InvokeDeferredCallbacks->handle(Object(Illuminate\Http\Request), Object(Closure))
#40 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePathEncoding.php(26): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#41 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Http\Middleware\ValidatePathEncoding->handle(Object(Illuminate\Http\Request), Object(Closure))
#42 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#43 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#44 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#45 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php(607): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#46 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php(368): Illuminate\Foundation\Testing\TestCase->call('GET', '/admin/discount...', Array, Array, Array, Array)
#47 /Users/fabianwesner/Herd/shop/tests/Feature/Admin/DiscountManagementTest.php(183): Illuminate\Foundation\Testing\TestCase->get('/admin/discount...')
#48 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Factories/TestCaseMethodFactory.php(168): P\Tests\Feature\Admin\DiscountManagementTest->{closure:/Users/fabianwesner/Herd/shop/tests/Feature/Admin/DiscountManagementTest.php:162}()
#49 [internal function]: P\Tests\Feature\Admin\DiscountManagementTest->{closure:Pest\Factories\TestCaseMethodFactory::getClosure():158}()
#50 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Concerns/Testable.php(429): call_user_func_array(Object(Closure), Array)
#51 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Support/ExceptionTrace.php(26): P\Tests\Feature\Admin\DiscountManagementTest->{closure:Pest\Concerns\Testable::__callClosure():429}()
#52 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Concerns/Testable.php(429): Pest\Support\ExceptionTrace::ensure(Object(Closure))
#53 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Concerns/Testable.php(331): P\Tests\Feature\Admin\DiscountManagementTest->__callClosure(Object(Closure), Array)
#54 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Factories/TestCaseFactory.php(169) : eval()'d code(53): P\Tests\Feature\Admin\DiscountManagementTest->__runTest(Object(Closure))
#55 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestCase.php(1332): P\Tests\Feature\Admin\DiscountManagementTest->__pest_evaluable_admin_discount_form_enforces_mutation_policies_and_verified_users()
#56 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestCase.php(519): PHPUnit\Framework\TestCase->runTest()
#57 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestRunner/TestRunner.php(99): PHPUnit\Framework\TestCase->runBare()
#58 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestCase.php(359): PHPUnit\Framework\TestRunner->run(Object(P\Tests\Feature\Admin\DiscountManagementTest))
#59 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestSuite.php(374): PHPUnit\Framework\TestCase->run()
#60 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(64): PHPUnit\Framework\TestSuite->run()
#61 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/TextUI/Application.php(229): PHPUnit\TextUI\TestRunner->run(Object(PHPUnit\TextUI\Configuration\Configuration), Object(PHPUnit\Runner\ResultCache\DefaultResultCache), Object(PHPUnit\Framework\TestSuite))
#62 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Kernel.php(103): PHPUnit\TextUI\Application->run(Array)
#63 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/bin/pest(184): Pest\Kernel->handle(Array, Array)
#64 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/bin/pest(192): {closure:/Users/fabianwesner/Herd/shop/vendor/pestphp/pest/bin/pest:18}()
#65 {main}

----------------------------------------------------------------------------------

Undefined property: Livewire\Features\SupportRedirects\Redirector::$headers

  at tests/Feature/Admin/DiscountManagementTest.php:184
    180▕
    181▕     $this->actingAs($unverifiedUser)
    182▕         ->withSession(['current_store_id' => $store->getKey()])
    183▕         ->get('/admin/discounts/create')
  ➜ 184▕         ->assertRedirect('/email/verify');
    185▕
    186▕     Livewire::actingAs($supportUser)
    187▕         ->test(AdminDiscountForm::class)
    188▕         ->assertStatus(403);

  Tests:    1 failed, 7 passed (51 assertions)
  Duration: 3.18s


php artisan test --compact tests/Feature/Admin/DiscountManagementTest.php --filter='admin discount form enforces mutation policies and verified users'


Output:
Chunk ID: 03eab7
Wall time: 0.8018 seconds
Process exited with code 1
Original token count: 3767
Output:

  ⨯
  ────────────────────────────────────────────────────────────────────────────
   FAILED  Tests\Feature\Admin\DiscountManagementTest > admin discount form…
  Expected response status code [201, 301, 302, 303, 307, 308] but received 500.
Failed asserting that false is true.

The following exception occurred during the last request:

ErrorException: Undefined property: Livewire\Features\SupportRedirects\Redirector::$headers in /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php:189
Stack trace:
#0 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(258): Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2, 'Undefined prope...', '/Users/fabianwe...', 189)
#1 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(189): Illuminate\Foundation\Bootstrap\HandleExceptions->{closure:Illuminate\Foundation\Bootstrap\HandleExceptions::forwardsTo():257}(2, 'Undefined prope...', '/Users/fabianwe...', 189)
#2 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(89): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->addCookieToResponse(Object(Illuminate\Http\Request), Object(Livewire\Features\SupportRedirects\Redirector))
#3 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Support/helpers.php(388): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->{closure:Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::handle():87}(Object(Livewire\Features\SupportRedirects\Redirector))
#4 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(87): tap(Object(Livewire\Features\SupportRedirects\Redirector), Object(Closure))
#5 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->handle(Object(Illuminate\Http\Request), Object(Closure))
#6 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(48): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#7 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#8 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(120): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#9 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(63): Illuminate\Session\Middleware\StartSession->handleStatefulRequest(Object(Illuminate\Http\Request), Object(Illuminate\Session\EncryptedStore), Object(Closure))
#10 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#11 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(36): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#12 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#13 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(74): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#14 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#15 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#16 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Routing/Router.php(821): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#17 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Routing/Router.php(800): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#18 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Routing/Router.php(764): Illuminate\Routing\Router->runRoute(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))
#19 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Routing/Router.php(753): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#20 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(200): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#21 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Foundation\Http\Kernel->{closure:Illuminate\Foundation\Http\Kernel::dispatchToRouter():197}(Object(Illuminate\Http\Request))
#22 /Users/fabianwesner/Herd/shop/vendor/livewire/livewire/src/Features/SupportDisablingBackButtonCache/DisableBackButtonCacheMiddleware.php(19): Illuminate\Pipeline\Pipeline->{closure:Illuminate\Pipeline\Pipeline::prepareDestination():178}(Object(Illuminate\Http\Request))
#23 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Livewire\Features\SupportDisablingBackButtonCache\DisableBackButtonCacheMiddleware->handle(Object(Illuminate\Http\Request), Object(Closure))
#24 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#25 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))
#26 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull->handle(Object(Illuminate\Http\Request), Object(Closure))
#27 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#28 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(51): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))
#29 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Foundation\Http\Middleware\TrimStrings->handle(Object(Illuminate\Http\Request), Object(Closure))
#30 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php(27): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#31 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Http\Middleware\ValidatePostSize->handle(Object(Illuminate\Http\Request), Object(Closure))
#32 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(109): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#33 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle(Object(Illuminate\Http\Request), Object(Closure))
#34 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(61): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#35 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Http\Middleware\HandleCors->handle(Object(Illuminate\Http\Request), Object(Closure))
#36 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(58): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#37 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Http\Middleware\TrustProxies->handle(Object(Illuminate\Http\Request), Object(Closure))
#38 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php(22): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#39 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Foundation\Http\Middleware\InvokeDeferredCallbacks->handle(Object(Illuminate\Http\Request), Object(Closure))
#40 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePathEncoding.php(26): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#41 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Http\Middleware\ValidatePathEncoding->handle(Object(Illuminate\Http\Request), Object(Closure))
#42 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#43 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#44 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#45 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php(607): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#46 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php(368): Illuminate\Foundation\Testing\TestCase->call('GET', '/admin/discount...', Array, Array, Array, Array)
#47 /Users/fabianwesner/Herd/shop/tests/Feature/Admin/DiscountManagementTest.php(183): Illuminate\Foundation\Testing\TestCase->get('/admin/discount...')
#48 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Factories/TestCaseMethodFactory.php(168): P\Tests\Feature\Admin\DiscountManagementTest->{closure:/Users/fabianwesner/Herd/shop/tests/Feature/Admin/DiscountManagementTest.php:162}()
#49 [internal function]: P\Tests\Feature\Admin\DiscountManagementTest->{closure:Pest\Factories\TestCaseMethodFactory::getClosure():158}()
#50 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Concerns/Testable.php(429): call_user_func_array(Object(Closure), Array)
#51 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Support/ExceptionTrace.php(26): P\Tests\Feature\Admin\DiscountManagementTest->{closure:Pest\Concerns\Testable::__callClosure():429}()
#52 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Concerns/Testable.php(429): Pest\Support\ExceptionTrace::ensure(Object(Closure))
#53 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Concerns/Testable.php(331): P\Tests\Feature\Admin\DiscountManagementTest->__callClosure(Object(Closure), Array)
#54 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Factories/TestCaseFactory.php(169) : eval()'d code(53): P\Tests\Feature\Admin\DiscountManagementTest->__runTest(Object(Closure))
#55 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestCase.php(1332): P\Tests\Feature\Admin\DiscountManagementTest->__pest_evaluable_admin_discount_form_enforces_mutation_policies_and_verified_users()
#56 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestCase.php(519): PHPUnit\Framework\TestCase->runTest()
#57 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestRunner/TestRunner.php(99): PHPUnit\Framework\TestCase->runBare()
#58 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestCase.php(359): PHPUnit\Framework\TestRunner->run(Object(P\Tests\Feature\Admin\DiscountManagementTest))
#59 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestSuite.php(374): PHPUnit\Framework\TestCase->run()
#60 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(64): PHPUnit\Framework\TestSuite->run()
#61 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/TextUI/Application.php(229): PHPUnit\TextUI\TestRunner->run(Object(PHPUnit\TextUI\Configuration\Configuration), Object(PHPUnit\Runner\ResultCache\DefaultResultCache), Object(PHPUnit\Framework\TestSuite))
#62 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Kernel.php(103): PHPUnit\TextUI\Application->run(Array)
#63 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/bin/pest(184): Pest\Kernel->handle(Array, Array)
#64 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/bin/pest(192): {closure:/Users/fabianwesner/Herd/shop/vendor/pestphp/pest/bin/pest:18}()
#65 {main}

----------------------------------------------------------------------------------

Undefined property: Livewire\Features\SupportRedirects\Redirector::$headers

  at tests/Feature/Admin/DiscountManagementTest.php:184
    180▕
    181▕     $this->actingAs($unverifiedUser)
    182▕         ->withSession(['current_store_id' => $store->getKey()])
    183▕         ->get('/admin/discounts/create')
  ➜ 184▕         ->assertRedirect('/email/verify');
    185▕
    186▕     Livewire::actingAs($supportUser)
    187▕         ->test(AdminDiscountForm::class)
    188▕         ->assertStatus(403);

  Tests:    1 failed (3 assertions)
  Duration: 0.70s


php artisan test --compact tests/Feature/Admin/DiscountManagementTest.php --filter='admin discount form enforces mutation policies and verified users'

  ⨯
  ────────────────────────────────────────────────────────────────────────────
   FAILED  Tests\Feature\Admin\DiscountManagementTest > admin discount form…
  Expected response status code [201, 301, 302, 303, 307, 308] but received 500.
Failed asserting that false is true.

The following exception occurred during the last request:

ErrorException: Undefined property: Livewire\Features\SupportRedirects\Redirector::$headers in /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php:189
Stack trace:
#0 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(258): Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2, 'Undefined prope...', '/Users/fabianwe...', 189)
#1 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(189): Illuminate\Foundation\Bootstrap\HandleExceptions->{closure:Illuminate\Foundation\Bootstrap\HandleExceptions::forwardsTo():257}(2, 'Undefined prope...', '/Users/fabianwe...', 189)
#2 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(89): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->addCookieToResponse(Object(Illuminate\Http\Request), Object(Livewire\Features\SupportRedirects\Redirector))
#3 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Support/helpers.php(388): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->{closure:Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::handle():87}(Object(Livewire\Features\SupportRedirects\Redirector))
#4 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(87): tap(Object(Livewire\Features\SupportRedirects\Redirector), Object(Closure))
#5 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->handle(Object(Illuminate\Http\Request), Object(Closure))
#6 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(48): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#7 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#8 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(120): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#9 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(63): Illuminate\Session\Middleware\StartSession->handleStatefulRequest(Object(Illuminate\Http\Request), Object(Illuminate\Session\EncryptedStore), Object(Closure))
#10 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#11 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(36): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#12 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#13 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(74): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#14 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#15 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#16 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Routing/Router.php(821): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#17 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Routing/Router.php(800): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#18 /Users/fabianwesner/Herd/shop/vendor/larav…5067 chars truncated…ork/src/Illuminate/Http/Middleware/ValidatePathEncoding.php(26): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#41 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(219): Illuminate\Http\Middleware\ValidatePathEncoding->handle(Object(Illuminate\Http\Request), Object(Closure))
#42 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Pipeline\Pipeline->{closure:{closure:Illuminate\Pipeline\Pipeline::carry():194}:195}(Object(Illuminate\Http\Request))
#43 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#44 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#45 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php(607): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#46 /Users/fabianwesner/Herd/shop/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php(368): Illuminate\Foundation\Testing\TestCase->call('GET', '/admin/discount...', Array, Array, Array, Array)
#47 /Users/fabianwesner/Herd/shop/tests/Feature/Admin/DiscountManagementTest.php(183): Illuminate\Foundation\Testing\TestCase->get('/admin/discount...')
#48 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Factories/TestCaseMethodFactory.php(168): P\Tests\Feature\Admin\DiscountManagementTest->{closure:/Users/fabianwesner/Herd/shop/tests/Feature/Admin/DiscountManagementTest.php:162}()
#49 [internal function]: P\Tests\Feature\Admin\DiscountManagementTest->{closure:Pest\Factories\TestCaseMethodFactory::getClosure():158}()
#50 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Concerns/Testable.php(429): call_user_func_array(Object(Closure), Array)
#51 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Support/ExceptionTrace.php(26): P\Tests\Feature\Admin\DiscountManagementTest->{closure:Pest\Concerns\Testable::__callClosure():429}()
#52 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Concerns/Testable.php(429): Pest\Support\ExceptionTrace::ensure(Object(Closure))
#53 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Concerns/Testable.php(331): P\Tests\Feature\Admin\DiscountManagementTest->__callClosure(Object(Closure), Array)
#54 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Factories/TestCaseFactory.php(169) : eval()'d code(53): P\Tests\Feature\Admin\DiscountManagementTest->__runTest(Object(Closure))
#55 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestCase.php(1332): P\Tests\Feature\Admin\DiscountManagementTest->__pest_evaluable_admin_discount_form_enforces_mutation_policies_and_verified_users()
#56 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestCase.php(519): PHPUnit\Framework\TestCase->runTest()
#57 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestRunner/TestRunner.php(99): PHPUnit\Framework\TestCase->runBare()
#58 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestCase.php(359): PHPUnit\Framework\TestRunner->run(Object(P\Tests\Feature\Admin\DiscountManagementTest))
#59 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/Framework/TestSuite.php(374): PHPUnit\Framework\TestCase->run()
#60 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(64): PHPUnit\Framework\TestSuite->run()
#61 /Users/fabianwesner/Herd/shop/vendor/phpunit/phpunit/src/TextUI/Application.php(229): PHPUnit\TextUI\TestRunner->run(Object(PHPUnit\TextUI\Configuration\Configuration), Object(PHPUnit\Runner\ResultCache\DefaultResultCache), Object(PHPUnit\Framework\TestSuite))
#62 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/src/Kernel.php(103): PHPUnit\TextUI\Application->run(Array)
#63 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/bin/pest(184): Pest\Kernel->handle(Array, Array)
#64 /Users/fabianwesner/Herd/shop/vendor/pestphp/pest/bin/pest(192): {closure:/Users/fabianwesner/Herd/shop/vendor/pestphp/pest/bin/pest:18}()
#65 {main}

----------------------------------------------------------------------------------

Undefined property: Livewire\Features\SupportRedirects\Redirector::$headers

  at tests/Feature/Admin/DiscountManagementTest.php:184
    180▕
    181▕     $this->actingAs($unverifiedUser)
    182▕         ->withSession(['current_store_id' => $store->getKey()])
    183▕         ->get('/admin/discounts/create')
  ➜ 184▕         ->assertRedirect('/email/verify');
    185▕
    186▕     Livewire::actingAs($supportUser)
    187▕         ->test(AdminDiscountForm::class)
    188▕         ->assertStatus(403);

  Tests:    1 failed (3 assertions)
  Duration: 0.70s


The failure is a real interaction between Laravel’s stock `verified` middleware redirect and Livewire full-page routes in this app: the redirect response is being created through Livewire’s redirector. I’m replacing the admin group’s `verified` alias with an app middleware that performs the same check but returns a normal HTTP redirect response.


php artisan make:middleware EnsureUserEmailIsVerified --no-interaction


Output:
Chunk ID: e79102
Wall time: 0.1567 seconds
Process exited with code 0
Original token count: 25
Output:

   INFO  Middleware [app/Http/Middleware/EnsureUserEmailIsVerified.php] created successfully.


php artisan make:middleware EnsureUserEmailIsVerified --no-interaction

INFO  Middleware [app/Http/Middleware/EnsureUserEmailIsVerified.php] created successfully.


sed -n '1,160p' app/Http/Middleware/EnsureUserEmailIsVerified.php


sed -n '1,160p' app/Http/Middleware/EnsureUserEmailIsVerified.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class EnsureUserEmailIsVerified
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        return $next($request);
    }
}


Output:
Chunk ID: 1c7a1a
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 110
Output:
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class EnsureUserEmailIsVerified
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        return $next($request);
    }
}


Input:
*** Begin Patch
*** Update File: app/Http/Middleware/EnsureUserEmailIsVerified.php
@@
 namespace App\Http\Middleware;

 use Closure;
+use Illuminate\Contracts\Auth\MustVerifyEmail;
+use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\URL;
 use Symfony\Component\HttpFoundation\Response;

 class EnsureUserEmailIsVerified
@@
      *
      * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
      */
-    public function handle(Request $request, Closure $next): Response
+    public function handle(Request $request, Closure $next, ?string $redirectToRoute = null): Response
     {
+        $user = $request->user();
+
+        if (! $user || ($user instanceof MustVerifyEmail && ! $user->hasVerifiedEmail())) {
+            if ($request->expectsJson()) {
+                abort(403, 'Your email address is not verified.');
+            }
+
+            return new RedirectResponse(URL::route($redirectToRoute ?: 'verification.notice'));
+        }
+
         return $next($request);
     }
 }
*** End Patch


Success. Updated the following files:
M app/Http/Middleware/EnsureUserEmailIsVerified.php

@@ -5,3 +5,6 @@
 use Closure;
+use Illuminate\Contracts\Auth\MustVerifyEmail;
+use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\URL;
 use Symfony\Component\HttpFoundation\Response;
@@ -15,4 +18,14 @@
      */
-    public function handle(Request $request, Closure $next): Response
+    public function handle(Request $request, Closure $next, ?string $redirectToRoute = null): Response
     {
+        $user = $request->user();
+
+        if (! $user || ($user instanceof MustVerifyEmail && ! $user->hasVerifiedEmail())) {
+            if ($request->expectsJson()) {
+                abort(403, 'Your email address is not verified.');
+            }
+
+            return new RedirectResponse(URL::route($redirectToRoute ?: 'verification.notice'));
+        }
+
         return $next($request);


Output: {"output":"Success. Updated the following files:\nM app/Http/Middleware/EnsureUserEmailIsVerified.php\n","metadata":{"exit_code":0,"duration_seconds":0.0}}


Input:
*** Begin Patch
*** Update File: app/Providers/AppServiceProvider.php
@@
 use App\Contracts\PaymentProvider;
 use App\Http\Middleware\CheckStoreRole;
+use App\Http\Middleware\EnsureUserEmailIsVerified;
 use App\Http\Middleware\ResolveStore;
 use App\Models\Store;
 use App\Services\NavigationService;
 use App\Services\Payments\MockPaymentProvider;
 use App\Services\ThemeSettingsService;
 use Carbon\CarbonImmutable;
 use Illuminate\Auth\Middleware\Authenticate;
-use Illuminate\Auth\Middleware\EnsureEmailIsVerified;
@@
         Livewire::addPersistentMiddleware([
-            EnsureEmailIsVerified::class,
+            EnsureUserEmailIsVerified::class,
             ResolveStore::class,
             CheckStoreRole::class,
         ]);
*** End Patch


Success. Updated the following files:
M app/Providers/AppServiceProvider.php

@@ -7,2 +7,3 @@
 use App\Http\Middleware\CheckStoreRole;
+use App\Http\Middleware\EnsureUserEmailIsVerified;
 use App\Http\Middleware\ResolveStore;
@@ -14,3 +15,2 @@
 use Illuminate\Auth\Middleware\Authenticate;
-use Illuminate\Auth\Middleware\EnsureEmailIsVerified;
 use Illuminate\Cache\RateLimiting\Limit;
@@ -127,3 +127,3 @@
         Livewire::addPersistentMiddleware([
-            EnsureEmailIsVerified::class,
+            EnsureUserEmailIsVerified::class,
             ResolveStore::class,


Output: {"output":"Success. Updated the following files:\nM app/Providers/AppServiceProvider.php\n","metadata":{"exit_code":0,"duration_seconds":0.0}}


Input:
*** Begin Patch
*** Update File: routes/web.php
@@
 use App\Livewire\Storefront\Products\Show as StorefrontProductShow;
 use App\Livewire\Storefront\Search\Index as StorefrontSearchIndex;
+use App\Http\Middleware\EnsureUserEmailIsVerified;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Route;
@@
-Route::middleware(['auth', 'verified', 'admin'])->prefix('admin')->name('admin.')->group(function (): void {
+Route::middleware(['auth', EnsureUserEmailIsVerified::class, 'admin'])->prefix('admin')->name('admin.')->group(function (): void {
*** End Patch


Success. Updated the following files:
M routes/web.php

@@ -28,2 +28,3 @@
 use App\Livewire\Storefront\Search\Index as StorefrontSearchIndex;
+use App\Http\Middleware\EnsureUserEmailIsVerified;
 use Illuminate\Support\Facades\Auth;
@@ -56,3 +57,3 @@

-Route::middleware(['auth', 'verified', 'admin'])->prefix('admin')->name('admin.')->group(function (): void {
+Route::middleware(['auth', EnsureUserEmailIsVerified::class, 'admin'])->prefix('admin')->name('admin.')->group(function (): void {
     Route::livewire('/', AdminDashboard::class)->name('dashboard');


Output: {"output":"Success. Updated the following files:\nM routes/web.php\n","metadata":{"exit_code":0,"duration_seconds":0.0}}


Input:
*** Begin Patch
*** Update File: tests/Feature/Admin/DiscountManagementTest.php
@@
 use App\Enums\StoreUserRole;
 use App\Http\Middleware\CheckStoreRole;
+use App\Http\Middleware\EnsureUserEmailIsVerified;
 use App\Http\Middleware\ResolveStore;
@@
-use Illuminate\Auth\Middleware\EnsureEmailIsVerified;
 use Illuminate\Foundation\Testing\RefreshDatabase;
@@
     expect(Livewire::getPersistentMiddleware())
-        ->toContain(EnsureEmailIsVerified::class)
+        ->toContain(EnsureUserEmailIsVerified::class)
*** End Patch


Success. Updated the following files:
M tests/Feature/Admin/DiscountManagementTest.php

@@ -7,2 +7,3 @@
 use App\Http\Middleware\CheckStoreRole;
+use App\Http\Middleware\EnsureUserEmailIsVerified;
 use App\Http\Middleware\ResolveStore;
@@ -16,3 +17,2 @@
 use Database\Seeders\DatabaseSeeder;
-use Illuminate\Auth\Middleware\EnsureEmailIsVerified;
 use Illuminate\Foundation\Testing\RefreshDatabase;
@@ -53,3 +53,3 @@
     expect(Livewire::getPersistentMiddleware())
-        ->toContain(EnsureEmailIsVerified::class)
+        ->toContain(EnsureUserEmailIsVerified::class)
         ->toContain(ResolveStore::class)


Output: {"output":"Success. Updated the following files:\nM tests/Feature/Admin/DiscountManagementTest.php\n","metadata":{"exit_code":0,"duration_seconds":0.0}}


Output:
Chunk ID: 42feda
Wall time: 0.6409 seconds
Process exited with code 0
Original token count: 21
Output:
{"result":"fixed","files":[{"path":"routes\/web.php","fixers":["ordered_imports"]}]}


/bin/zsh
-lc
vendor/bin/pint --dirty --format agent


php artisan test --compact tests/Feature/Admin/DiscountManagementTest.php


php artisan test --compact tests/Feature/Checkout/PricingServicesTest.php


php artisan test --compact tests/Feature/Checkout/PricingServicesTest.php

  ....

  Tests:    4 passed (19 assertions)
  Duration: 0.37s


Output:
Chunk ID: a1d390
Wall time: 1.0012 seconds
Process running with session ID 94565
Original token count: 0
Output:


Output:
Chunk ID: 861802
Wall time: 0.6391 seconds
Process exited with code 0
Original token count: 17
Output:

  ....

  Tests:    4 passed (19 assertions)
  Duration: 0.37s


php artisan test --compact tests/Feature/Admin/DiscountManagementTest.php

  ........

  Tests:    8 passed (53 assertions)
  Duration: 3.05s


Output:
Chunk ID: 645565
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 18
Output:

  ........

  Tests:    8 passed (53 assertions)
  Duration: 3.05s


The targeted regressions now pass: admin discount management is 8 tests/53 assertions and pricing services are 4 tests/19 assertions. I’m widening to the affected admin/checkout/cart/orders/storefront/API set before browser-checking again.


php artisan test --compact tests/Feature/Admin tests/Feature/Checkout tests/Feature/Cart tests/Feature/Orders tests/Feature/Storefront tests/Feature/Api


Output:
Chunk ID: bb9a37
Wall time: 1.0015 seconds
Process running with session ID 3204
Original token count: 0
Output:


Output:
Chunk ID: 6e468f
Wall time: 5.0018 seconds
Process running with session ID 3204
Original token count: 17
Output:

  ................................................................


Output:
Chunk ID: 90c133
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 18
Output:
........

  Tests:    72 passed (462 assertions)
  Duration: 14.84s


sed -n '1,80p' app/Providers/AppServiceProvider.php


sed -n '1,180p' app/Services/DiscountService.php


sed -n '1,130p' app/Services/PricingEngine.php


sed -n '1,80p' app/Providers/AppServiceProvider.php

<?php

namespace App\Providers;

use App\Auth\CustomerUserProvider;
use App\Contracts\PaymentProvider;
use App\Http\Middleware\CheckStoreRole;
use App\Http\Middleware\EnsureUserEmailIsVerified;
use App\Http\Middleware\ResolveStore;
use App\Models\Store;
use App\Services\NavigationService;
use App\Services\Payments\MockPaymentProvider;
use App\Services\ThemeSettingsService;
use Carbon\CarbonImmutable;
use Illuminate\Auth\Middleware\Authenticate;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\Rules\Password;
use Illuminate\View\View as ViewInstance;
use Livewire\Livewire;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        $this->app->bind(PaymentProvider::class, MockPaymentProvider::class);

        Auth::provider('store_scoped_eloquent', function ($app, array $config): CustomerUserProvider {
            return new CustomerUserProvider($app['hash'], $config['model']);
        });

        $this->app->singleton(ThemeSettingsService::class);
        $this->app->singleton(NavigationService::class);
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        $this->configureDefaults();
        $this->configureLivewireMiddleware();
        $this->configureStorefrontViewData();
    }

    /**
     * Configure default behaviors for production-ready applications.
     */
    protected function configureDefaults(): void
    {
        Date::use(CarbonImmutable::class);

        DB::prohibitDestructiveCommands(
            app()->isProduction(),
        );

        Password::defaults(fn (): ?Password => app()->isProduction()
            ? Password::min(12)
                ->mixedCase()
                ->letters()
                ->numbers()
                ->symbols()
                ->uncompromised()
            : null
        );

        RateLimiter::for('api.storefront', function (Request $request): Limit {
            return Limit::perMinute(120)->by($request->ip());
        });

        RateLimiter::for('checkout', function (Request $request): Limit {


/bin/zsh
-lc
sed -n '1,90p' routes/web.php

<?php

use App\Http\Middleware\EnsureUserEmailIsVerified;
use App\Livewire\Admin\Auth\Login as AdminLogin;
use App\Livewire\Admin\Collections\Form as AdminCollectionForm;
use App\Livewire\Admin\Collections\Index as AdminCollectionsIndex;
use App\Livewire\Admin\Customers\Index as AdminCustomersIndex;
use App\Livewire\Admin\Customers\Show as AdminCustomerShow;
use App\Livewire\Admin\Dashboard as AdminDashboard;
use App\Livewire\Admin\Discounts\Form as AdminDiscountForm;
use App\Livewire\Admin\Discounts\Index as AdminDiscountsIndex;
use App\Livewire\Admin\Inventory\Index as AdminInventoryIndex;
use App\Livewire\Admin\Orders\Index as AdminOrdersIndex;
use App\Livewire\Admin\Orders\Show as AdminOrderShow;
use App\Livewire\Admin\Products\Form as AdminProductForm;
use App\Livewire\Admin\Products\Index as AdminProductsIndex;
use App\Livewire\Storefront\Account\Auth\Login as CustomerLogin;
use App\Livewire\Storefront\Account\Auth\Register as CustomerRegister;
use App\Livewire\Storefront\Account\Orders\Index as CustomerOrdersIndex;
use App\Livewire\Storefront\Account\Orders\Show as CustomerOrderShow;
use App\Livewire\Storefront\Cart\Show as StorefrontCartShow;
use App\Livewire\Storefront\Checkout\Confirmation as StorefrontCheckoutConfirmation;
use App\Livewire\Storefront\Checkout\Show as StorefrontCheckoutShow;
use App\Livewire\Storefront\Collections\Index as StorefrontCollectionsIndex;
use App\Livewire\Storefront\Collections\Show as StorefrontCollectionShow;
use App\Livewire\Storefront\Home as StorefrontHome;
use App\Livewire\Storefront\Pages\Show as StorefrontPageShow;
use App\Livewire\Storefront\Products\Show as StorefrontProductShow;
use App\Livewire\Storefront\Search\Index as StorefrontSearchIndex;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;

Route::middleware(['storefront'])->group(function (): void {
    Route::livewire('/', StorefrontHome::class)->name('home');
    Route::livewire('collections', StorefrontCollectionsIndex::class)->name('collections.index');
    Route::livewire('collections/{handle}', StorefrontCollectionShow::class)->name('collections.show');
    Route::livewire('products/{handle}', StorefrontProductShow::class)->name('products.show');
    Route::livewire('cart', StorefrontCartShow::class)->name('cart.show');
    Route::livewire('checkout', StorefrontCheckoutShow::class)->name('checkout.show');
    Route::livewire('checkout/confirmation/{order}', StorefrontCheckoutConfirmation::class)->name('checkout.confirmation');
    Route::livewire('search', StorefrontSearchIndex::class)->name('search.index');
    Route::livewire('pages/{handle}', StorefrontPageShow::class)->name('pages.show');
});

Route::livewire('admin/login', AdminLogin::class)
    ->middleware('guest')
    ->name('admin.login');

Route::post('admin/logout', function () {
    Auth::guard('web')->logout();

    request()->session()->invalidate();
    request()->session()->regenerateToken();

    return redirect()->route('admin.login');
})->middleware('auth')->name('admin.logout');

Route::middleware(['auth', EnsureUserEmailIsVerified::class, 'admin'])->prefix('admin')->name('admin.')->group(function (): void {
    Route::livewire('/', AdminDashboard::class)->name('dashboard');
    Route::livewire('products', AdminProductsIndex::class)->name('products.index');
    Route::livewire('products/create', AdminProductForm::class)->name('products.create');
    Route::livewire('products/{product}/edit', AdminProductForm::class)->name('products.edit');
    Route::livewire('inventory', AdminInventoryIndex::class)->name('inventory.index');
    Route::livewire('orders', AdminOrdersIndex::class)->name('orders.index');
    Route::livewire('orders/{order}', AdminOrderShow::class)->name('orders.show');
    Route::livewire('customers', AdminCustomersIndex::class)->name('customers.index');
    Route::livewire('customers/{customer}', AdminCustomerShow::class)->name('customers.show');
    Route::livewire('discounts', AdminDiscountsIndex::class)->name('discounts.index');
    Route::livewire('discounts/create', AdminDiscountForm::class)->name('discounts.create');
    Route::livewire('discounts/{discount}/edit', AdminDiscountForm::class)->name('discounts.edit');
    Route::livewire('collections', AdminCollectionsIndex::class)->name('collections.index');
    Route::livewire('collections/create', AdminCollectionForm::class)->name('collections.create');
    Route::livewire('collections/{collection}/edit', AdminCollectionForm::class)->name('collections.edit');
});

Route::middleware(['storefront'])->group(function (): void {
    Route::livewire('account/login', CustomerLogin::class)
        ->middleware('guest:customer')
        ->name('account.login');

    Route::livewire('account/register', CustomerRegister::class)
        ->middleware('guest:customer')
        ->name('account.register');

    Route::livewire('account', CustomerOrdersIndex::class)
        ->middleware('auth:customer')
        ->name('account.dashboard');

    Route::livewire('account/orders/{order}', CustomerOrderShow::class)
        ->middleware('auth:customer')


sed -n '1,130p' app/Services/PricingEngine.php

<?php

namespace App\Services;

use App\Exceptions\InvalidCheckoutTransitionException;
use App\Models\CartLine;
use App\Models\Checkout;
use App\Models\ShippingRate;
use App\Models\TaxSettings;
use App\ValueObjects\DiscountResult;
use App\ValueObjects\PricingResult;
use Illuminate\Support\Facades\DB;

class PricingEngine
{
    public function __construct(
        private readonly DiscountService $discounts,
        private readonly ShippingCalculator $shipping,
        private readonly TaxCalculator $taxes,
    ) {}

    public function calculate(Checkout $checkout): PricingResult
    {
        return DB::transaction(function () use ($checkout): PricingResult {
            $checkout = Checkout::withoutGlobalScopes()
                ->with(['cart.lines'])
                ->whereKey($checkout->getKey())
                ->firstOrFail();
            $cart = $checkout->cart;

            $this->resetLineAmounts($checkout);

            $lines = CartLine::withoutGlobalScopes()
                ->where('cart_id', $cart->getKey())
                ->orderBy('id')
                ->get();
            $subtotal = $lines->sum('line_subtotal_amount');
            $discountAmount = 0;
            $freeShipping = false;

            if ($checkout->discount_code) {
                $discount = $this->discounts->validate($checkout->discount_code, $checkout->store, $cart);
                $discountResult = $this->discounts->applyToCart($cart, $discount);
                $discountAmount += $discountResult->amount;
                $freeShipping = $freeShipping || $discountResult->freeShipping;
            }

            foreach ($this->discounts->automaticForCart($checkout->store, $cart) as $discount) {
                $discountResult = $this->discounts->applyToCart($cart, $discount);
                $discountAmount += $discountResult->amount;
                $freeShipping = $freeShipping || $discountResult->freeShipping;
            }

            $lines = CartLine::withoutGlobalScopes()
                ->where('cart_id', $cart->getKey())
                ->orderBy('id')
                ->get();
            $discountResult = new DiscountResult($discountAmount, [], $freeShipping);
            $shippingAmount = $this->shippingAmount($checkout, $discountResult);
            $taxSettings = $this->taxSettings($checkout);
            $taxResult = $this->taxes->calculateForAmounts(
                $lines->pluck('line_total_amount')->map(fn (int $amount): int => $amount)->all(),
                $shippingAmount,
                $taxSettings,
                $checkout->shipping_address_json ?? [],
            );
            $discountedSubtotal = $subtotal - $discountResult->amount;
            $total = $taxSettings->prices_include_tax
                ? $discountedSubtotal + $shippingAmount
                : $discountedSubtotal + $shippingAmount + $taxResult->totalAmount;

            $result = new PricingResult(
                subtotal: $subtotal,
                discount: $discountResult->amount,
                shipping: $shippingAmount,
                taxLines: $taxResult->taxLines,
                taxTotal: $taxResult->totalAmount,
                total: $total,
                currency: $cart->currency,
            );

            $checkout->forceFill([
                'tax_provider_snapshot_json' => $taxResult->toArray(),
                'totals_json' => $result->toArray(),
            ])->save();

            return $result;
        });
    }

    private function resetLineAmounts(Checkout $checkout): void
    {
        CartLine::withoutGlobalScopes()
            ->where('cart_id', $checkout->cart_id)
            ->get()
            ->each(function (CartLine $line): void {
                $subtotal = $line->unit_price_amount * $line->quantity;

                $line->forceFill([
                    'line_subtotal_amount' => $subtotal,
                    'line_discount_amount' => 0,
                    'line_total_amount' => $subtotal,
                ])->save();
            });
    }

    private function shippingAmount(Checkout $checkout, DiscountResult $discountResult): int
    {
        if (! $this->shipping->requiresShipping($checkout->cart)) {
            return 0;
        }

        if ($checkout->shipping_method_id === null) {
            return 0;
        }

        $rate = ShippingRate::withoutGlobalScopes()->find($checkout->shipping_method_id);

        if (! $rate instanceof ShippingRate) {
            throw InvalidCheckoutTransitionException::because('Shipping rate is not available.');
        }

        $amount = $this->shipping->calculate($rate, $checkout->cart);

        if ($amount === null) {
            throw InvalidCheckoutTransitionException::because('Shipping rate is not available for this cart.');
        }

        return $discountResult->freeShipping ? 0 : $amount;
    }


sed -n '1,180p' app/Services/DiscountService.php

<?php

namespace App\Services;

use App\Enums\DiscountStatus;
use App\Enums\DiscountType;
use App\Enums\DiscountValueType;
use App\Exceptions\InvalidDiscountException;
use App\Models\Cart;
use App\Models\CartLine;
use App\Models\Discount;
use App\Models\ProductVariant;
use App\Models\Store;
use App\ValueObjects\DiscountResult;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class DiscountService
{
    public function validate(string $code, Store $store, Cart $cart): Discount
    {
        $normalizedCode = mb_strtolower(trim($code));

        $discount = Discount::withoutGlobalScopes()
            ->where('store_id', $store->getKey())
            ->where('type', DiscountType::Code)
            ->whereRaw('lower(code) = ?', [$normalizedCode])
            ->first();

        if (! $discount instanceof Discount) {
            throw InvalidDiscountException::because('discount_not_found', 'Discount code was not found.');
        }

        $this->validateDiscountForCart($discount, $cart);

        return $discount;
    }

    /**
     * @return Collection<int, Discount>
     */
    public function automaticForCart(Store $store, Cart $cart): Collection
    {
        return Discount::withoutGlobalScopes()
            ->where('store_id', $store->getKey())
            ->where('type', DiscountType::Automatic->value)
            ->where('status', DiscountStatus::Active->value)
            ->orderBy('id')
            ->get()
            ->filter(function (Discount $discount) use ($cart): bool {
                try {
                    $this->validateDiscountForCart($discount, $cart);

                    return true;
                } catch (InvalidDiscountException) {
                    return false;
                }
            })
            ->values();
    }

    private function validateDiscountForCart(Discount $discount, Cart $cart): void
    {
        if ($discount->status !== DiscountStatus::Active) {
            throw InvalidDiscountException::because('discount_expired', 'Discount is not active.');
        }

        if ($discount->starts_at->isFuture()) {
            throw InvalidDiscountException::because('discount_not_yet_active', 'Discount is not active yet.');
        }

        if ($discount->ends_at !== null && $discount->ends_at->isPast()) {
            throw InvalidDiscountException::because('discount_expired', 'Discount has expired.');
        }

        if ($discount->usage_limit !== null && $discount->usage_count >= $discount->usage_limit) {
            throw InvalidDiscountException::because('discount_usage_limit_reached', 'Discount usage limit has been reached.');
        }

        $lines = $this->cartLines($cart);
        $subtotal = $lines->sum('line_subtotal_amount');
        $minimum = (int) data_get($discount->rules_json, 'min_purchase_amount', data_get($discount->rules_json, 'minimum_purchase', 0));

        if ($minimum > 0 && $subtotal < $minimum) {
            throw InvalidDiscountException::because('discount_min_purchase_not_met', 'Cart does not meet the minimum purchase amount.');
        }

        if ($this->qualifyingLines($discount, $lines)->isEmpty()) {
            throw InvalidDiscountException::because('discount_not_applicable', 'Discount does not apply to these cart lines.');
        }
    }

    /**
     * @param  array<int, CartLine>  $lines
     */
    public function calculate(Discount $discount, int $subtotal, array $lines): DiscountResult
    {
        if ($discount->value_type === DiscountValueType::FreeShipping) {
            return new DiscountResult(0, [], true);
        }

        $qualifyingLines = $this->qualifyingLines($discount, collect($lines));
        $qualifyingSubtotal = $qualifyingLines->sum('line_total_amount');

        if ($qualifyingSubtotal <= 0) {
            return new DiscountResult(0, []);
        }

        $discountAmount = match ($discount->value_type) {
            DiscountValueType::Percent => (int) round($qualifyingSubtotal * $discount->value_amount / 100),
            DiscountValueType::Fixed => min($discount->value_amount, $qualifyingSubtotal),
            DiscountValueType::FreeShipping => 0,
        };

        $remaining = $discountAmount;
        $allocations = [];
        $lastIndex = $qualifyingLines->keys()->last();

        foreach ($qualifyingLines as $index => $line) {
            if ($index === $lastIndex) {
                $allocations[$line->getKey()] = $remaining;

                continue;
            }

            $allocation = (int) round($discountAmount * $line->line_total_amount / $qualifyingSubtotal);
            $allocations[$line->getKey()] = $allocation;
            $remaining -= $allocation;
        }

        return new DiscountResult($discountAmount, $allocations);
    }

    public function applyToCart(Cart $cart, Discount $discount): DiscountResult
    {
        return DB::transaction(function () use ($cart, $discount): DiscountResult {
            $lines = $this->cartLines($cart);
            $result = $this->calculate($discount, $lines->sum('line_subtotal_amount'), $lines->all());

            $lines->each(function (CartLine $line) use ($result): void {
                $discountAmount = $result->allocations[$line->getKey()] ?? 0;

                $line->forceFill([
                    'line_discount_amount' => $line->line_discount_amount + $discountAmount,
                    'line_total_amount' => max(0, $line->line_total_amount - $discountAmount),
                ])->save();
            });

            return $result;
        });
    }

    /**
     * @return Collection<int, CartLine>
     */
    private function cartLines(Cart $cart): Collection
    {
        return CartLine::withoutGlobalScopes()
            ->where('cart_id', $cart->getKey())
            ->orderBy('id')
            ->get();
    }

    /**
     * @param  Collection<int, CartLine>  $lines
     * @return Collection<int, CartLine>
     */
    private function qualifyingLines(Discount $discount, Collection $lines): Collection
    {
        $productIds = collect(data_get($discount->rules_json, 'applicable_product_ids', []))
            ->filter()
            ->map(fn (mixed $id): int => (int) $id)
            ->values();
        $collectionIds = collect(data_get($discount->rules_json, 'applicable_collection_ids', []))
            ->filter()
            ->map(fn (mixed $id): int => (int) $id)
            ->values();

        if ($productIds->isEmpty() && $collectionIds->isEmpty()) {
            return $lines;


Output:
Chunk ID: 675b31
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 605
Output:
<?php

namespace App\Providers;

use App\Auth\CustomerUserProvider;
use App\Contracts\PaymentProvider;
use App\Http\Middleware\CheckStoreRole;
use App\Http\Middleware\EnsureUserEmailIsVerified;
use App\Http\Middleware\ResolveStore;
use App\Models\Store;
use App\Services\NavigationService;
use App\Services\Payments\MockPaymentProvider;
use App\Services\ThemeSettingsService;
use Carbon\CarbonImmutable;
use Illuminate\Auth\Middleware\Authenticate;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\Rules\Password;
use Illuminate\View\View as ViewInstance;
use Livewire\Livewire;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        $this->app->bind(PaymentProvider::class, MockPaymentProvider::class);

        Auth::provider('store_scoped_eloquent', function ($app, array $config): CustomerUserProvider {
            return new CustomerUserProvider($app['hash'], $config['model']);
        });

        $this->app->singleton(ThemeSettingsService::class);
        $this->app->singleton(NavigationService::class);
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        $this->configureDefaults();
        $this->configureLivewireMiddleware();
        $this->configureStorefrontViewData();
    }

    /**
     * Configure default behaviors for production-ready applications.
     */
    protected function configureDefaults(): void
    {
        Date::use(CarbonImmutable::class);

        DB::prohibitDestructiveCommands(
            app()->isProduction(),
        );

        Password::defaults(fn (): ?Password => app()->isProduction()
            ? Password::min(12)
                ->mixedCase()
                ->letters()
                ->numbers()
                ->symbols()
                ->uncompromised()
            : null
        );

        RateLimiter::for('api.storefront', function (Request $request): Limit {
            return Limit::perMinute(120)->by($request->ip());
        });

        RateLimiter::for('checkout', function (Request $request): Limit {


Output:
Chunk ID: 49150e
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1276
Output:
<?php

use App\Http\Middleware\EnsureUserEmailIsVerified;
use App\Livewire\Admin\Auth\Login as AdminLogin;
use App\Livewire\Admin\Collections\Form as AdminCollectionForm;
use App\Livewire\Admin\Collections\Index as AdminCollectionsIndex;
use App\Livewire\Admin\Customers\Index as AdminCustomersIndex;
use App\Livewire\Admin\Customers\Show as AdminCustomerShow;
use App\Livewire\Admin\Dashboard as AdminDashboard;
use App\Livewire\Admin\Discounts\Form as AdminDiscountForm;
use App\Livewire\Admin\Discounts\Index as AdminDiscountsIndex;
use App\Livewire\Admin\Inventory\Index as AdminInventoryIndex;
use App\Livewire\Admin\Orders\Index as AdminOrdersIndex;
use App\Livewire\Admin\Orders\Show as AdminOrderShow;
use App\Livewire\Admin\Products\Form as AdminProductForm;
use App\Livewire\Admin\Products\Index as AdminProductsIndex;
use App\Livewire\Storefront\Account\Auth\Login as CustomerLogin;
use App\Livewire\Storefront\Account\Auth\Register as CustomerRegister;
use App\Livewire\Storefront\Account\Orders\Index as CustomerOrdersIndex;
use App\Livewire\Storefront\Account\Orders\Show as CustomerOrderShow;
use App\Livewire\Storefront\Cart\Show as StorefrontCartShow;
use App\Livewire\Storefront\Checkout\Confirmation as StorefrontCheckoutConfirmation;
use App\Livewire\Storefront\Checkout\Show as StorefrontCheckoutShow;
use App\Livewire\Storefront\Collections\Index as StorefrontCollectionsIndex;
use App\Livewire\Storefront\Collections\Show as StorefrontCollectionShow;
use App\Livewire\Storefront\Home as StorefrontHome;
use App\Livewire\Storefront\Pages\Show as StorefrontPageShow;
use App\Livewire\Storefront\Products\Show as StorefrontProductShow;
use App\Livewire\Storefront\Search\Index as StorefrontSearchIndex;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;

Route::middleware(['storefront'])->group(function (): void {
    Route::livewire('/', StorefrontHome::class)->name('home');
    Route::livewire('collections', StorefrontCollectionsIndex::class)->name('collections.index');
    Route::livewire('collections/{handle}', StorefrontCollectionShow::class)->name('collections.show');
    Route::livewire('products/{handle}', StorefrontProductShow::class)->name('products.show');
    Route::livewire('cart', StorefrontCartShow::class)->name('cart.show');
    Route::livewire('checkout', StorefrontCheckoutShow::class)->name('checkout.show');
    Route::livewire('checkout/confirmation/{order}', StorefrontCheckoutConfirmation::class)->name('checkout.confirmation');
    Route::livewire('search', StorefrontSearchIndex::class)->name('search.index');
    Route::livewire('pages/{handle}', StorefrontPageShow::class)->name('pages.show');
});

Route::livewire('admin/login', AdminLogin::class)
    ->middleware('guest')
    ->name('admin.login');

Route::post('admin/logout', function () {
    Auth::guard('web')->logout();

    request()->session()->invalidate();
    request()->session()->regenerateToken();

    return redirect()->route('admin.login');
})->middleware('auth')->name('admin.logout');

Route::middleware(['auth', EnsureUserEmailIsVerified::class, 'admin'])->prefix('admin')->name('admin.')->group(function (): void {
    Route::livewire('/', AdminDashboard::class)->name('dashboard');
    Route::livewire('products', AdminProductsIndex::class)->name('products.index');
    Route::livewire('products/create', AdminProductForm::class)->name('products.create');
    Route::livewire('products/{product}/edit', AdminProductForm::class)->name('products.edit');
    Route::livewire('inventory', AdminInventoryIndex::class)->name('inventory.index');
    Route::livewire('orders', AdminOrdersIndex::class)->name('orders.index');
    Route::livewire('orders/{order}', AdminOrderShow::class)->name('orders.show');
    Route::livewire('customers', AdminCustomersIndex::class)->name('customers.index');
    Route::livewire('customers/{customer}', AdminCustomerShow::class)->name('customers.show');
    Route::livewire('discounts', AdminDiscountsIndex::class)->name('discounts.index');
    Route::livewire('discounts/create', AdminDiscountForm::class)->name('discounts.create');
    Route::livewire('discounts/{discount}/edit', AdminDiscountForm::class)->name('discounts.edit');
    Route::livewire('collections', AdminCollectionsIndex::class)->name('collections.index');
    Route::livewire('collections/create', AdminCollectionForm::class)->name('collections.create');
    Route::livewire('collections/{collection}/edit', AdminCollectionForm::class)->name('collections.edit');
});

Route::middleware(['storefront'])->group(function (): void {
    Route::livewire('account/login', CustomerLogin::class)
        ->middleware('guest:customer')
        ->name('account.login');

    Route::livewire('account/register', CustomerRegister::class)
        ->middleware('guest:customer')
        ->name('account.register');

    Route::livewire('account', CustomerOrdersIndex::class)
        ->middleware('auth:customer')
        ->name('account.dashboard');

    Route::livewire('account/orders/{order}', CustomerOrderShow::class)
        ->middleware('auth:customer')


Output:
Chunk ID: 13e699
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1631
Output:
<?php

namespace App\Services;

use App\Enums\DiscountStatus;
use App\Enums\DiscountType;
use App\Enums\DiscountValueType;
use App\Exceptions\InvalidDiscountException;
use App\Models\Cart;
use App\Models\CartLine;
use App\Models\Discount;
use App\Models\ProductVariant;
use App\Models\Store;
use App\ValueObjects\DiscountResult;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class DiscountService
{
    public function validate(string $code, Store $store, Cart $cart): Discount
    {
        $normalizedCode = mb_strtolower(trim($code));

        $discount = Discount::withoutGlobalScopes()
            ->where('store_id', $store->getKey())
            ->where('type', DiscountType::Code)
            ->whereRaw('lower(code) = ?', [$normalizedCode])
            ->first();

        if (! $discount instanceof Discount) {
            throw InvalidDiscountException::because('discount_not_found', 'Discount code was not found.');
        }

        $this->validateDiscountForCart($discount, $cart);

        return $discount;
    }

    /**
     * @return Collection<int, Discount>
     */
    public function automaticForCart(Store $store, Cart $cart): Collection
    {
        return Discount::withoutGlobalScopes()
            ->where('store_id', $store->getKey())
            ->where('type', DiscountType::Automatic->value)
            ->where('status', DiscountStatus::Active->value)
            ->orderBy('id')
            ->get()
            ->filter(function (Discount $discount) use ($cart): bool {
                try {
                    $this->validateDiscountForCart($discount, $cart);

                    return true;
                } catch (InvalidDiscountException) {
                    return false;
                }
            })
            ->values();
    }

    private function validateDiscountForCart(Discount $discount, Cart $cart): void
    {
        if ($discount->status !== DiscountStatus::Active) {
            throw InvalidDiscountException::because('discount_expired', 'Discount is not active.');
        }

        if ($discount->starts_at->isFuture()) {
            throw InvalidDiscountException::because('discount_not_yet_active', 'Discount is not active yet.');
        }

        if ($discount->ends_at !== null && $discount->ends_at->isPast()) {
            throw InvalidDiscountException::because('discount_expired', 'Discount has expired.');
        }

        if ($discount->usage_limit !== null && $discount->usage_count >= $discount->usage_limit) {
            throw InvalidDiscountException::because('discount_usage_limit_reached', 'Discount usage limit has been reached.');
        }

        $lines = $this->cartLines($cart);
        $subtotal = $lines->sum('line_subtotal_amount');
        $minimum = (int) data_get($discount->rules_json, 'min_purchase_amount', data_get($discount->rules_json, 'minimum_purchase', 0));

        if ($minimum > 0 && $subtotal < $minimum) {
            throw InvalidDiscountException::because('discount_min_purchase_not_met', 'Cart does not meet the minimum purchase amount.');
        }

        if ($this->qualifyingLines($discount, $lines)->isEmpty()) {
            throw InvalidDiscountException::because('discount_not_applicable', 'Discount does not apply to these cart lines.');
        }
    }

    /**
     * @param  array<int, CartLine>  $lines
     */
    public function calculate(Discount $discount, int $subtotal, array $lines): DiscountResult
    {
        if ($discount->value_type === DiscountValueType::FreeShipping) {
            return new DiscountResult(0, [], true);
        }

        $qualifyingLines = $this->qualifyingLines($discount, collect($lines));
        $qualifyingSubtotal = $qualifyingLines->sum('line_total_amount');

        if ($qualifyingSubtotal <= 0) {
            return new DiscountResult(0, []);
        }

        $discountAmount = match ($discount->value_type) {
            DiscountValueType::Percent => (int) round($qualifyingSubtotal * $discount->value_amount / 100),
            DiscountValueType::Fixed => min($discount->value_amount, $qualifyingSubtotal),
            DiscountValueType::FreeShipping => 0,
        };

        $remaining = $discountAmount;
        $allocations = [];
        $lastIndex = $qualifyingLines->keys()->last();

        foreach ($qualifyingLines as $index => $line) {
            if ($index === $lastIndex) {
                $allocations[$line->getKey()] = $remaining;

                continue;
            }

            $allocation = (int) round($discountAmount * $line->line_total_amount / $qualifyingSubtotal);
            $allocations[$line->getKey()] = $allocation;
            $remaining -= $allocation;
        }

        return new DiscountResult($discountAmount, $allocations);
    }

    public function applyToCart(Cart $cart, Discount $discount): DiscountResult
    {
        return DB::transaction(function () use ($cart, $discount): DiscountResult {
            $lines = $this->cartLines($cart);
            $result = $this->calculate($discount, $lines->sum('line_subtotal_amount'), $lines->all());

            $lines->each(function (CartLine $line) use ($result): void {
                $discountAmount = $result->allocations[$line->getKey()] ?? 0;

                $line->forceFill([
                    'line_discount_amount' => $line->line_discount_amount + $discountAmount,
                    'line_total_amount' => max(0, $line->line_total_amount - $discountAmount),
                ])->save();
            });

            return $result;
        });
    }

    /**
     * @return Collection<int, CartLine>
     */
    private function cartLines(Cart $cart): Collection
    {
        return CartLine::withoutGlobalScopes()
            ->where('cart_id', $cart->getKey())
            ->orderBy('id')
            ->get();
    }

    /**
     * @param  Collection<int, CartLine>  $lines
     * @return Collection<int, CartLine>
     */
    private function qualifyingLines(Discount $discount, Collection $lines): Collection
    {
        $productIds = collect(data_get($discount->rules_json, 'applicable_product_ids', []))
            ->filter()
            ->map(fn (mixed $id): int => (int) $id)
            ->values();
        $collectionIds = collect(data_get($discount->rules_json, 'applicable_collection_ids', []))
            ->filter()
            ->map(fn (mixed $id): int => (int) $id)
            ->values();

        if ($productIds->isEmpty() && $collectionIds->isEmpty()) {
            return $lines;


Output:
Chunk ID: 89f94b
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1216
Output:
<?php

namespace App\Services;

use App\Exceptions\InvalidCheckoutTransitionException;
use App\Models\CartLine;
use App\Models\Checkout;
use App\Models\ShippingRate;
use App\Models\TaxSettings;
use App\ValueObjects\DiscountResult;
use App\ValueObjects\PricingResult;
use Illuminate\Support\Facades\DB;

class PricingEngine
{
    public function __construct(
        private readonly DiscountService $discounts,
        private readonly ShippingCalculator $shipping,
        private readonly TaxCalculator $taxes,
    ) {}

    public function calculate(Checkout $checkout): PricingResult
    {
        return DB::transaction(function () use ($checkout): PricingResult {
            $checkout = Checkout::withoutGlobalScopes()
                ->with(['cart.lines'])
                ->whereKey($checkout->getKey())
                ->firstOrFail();
            $cart = $checkout->cart;

            $this->resetLineAmounts($checkout);

            $lines = CartLine::withoutGlobalScopes()
                ->where('cart_id', $cart->getKey())
                ->orderBy('id')
                ->get();
            $subtotal = $lines->sum('line_subtotal_amount');
            $discountAmount = 0;
            $freeShipping = false;

            if ($checkout->discount_code) {
                $discount = $this->discounts->validate($checkout->discount_code, $checkout->store, $cart);
                $discountResult = $this->discounts->applyToCart($cart, $discount);
                $discountAmount += $discountResult->amount;
                $freeShipping = $freeShipping || $discountResult->freeShipping;
            }

            foreach ($this->discounts->automaticForCart($checkout->store, $cart) as $discount) {
                $discountResult = $this->discounts->applyToCart($cart, $discount);
                $discountAmount += $discountResult->amount;
                $freeShipping = $freeShipping || $discountResult->freeShipping;
            }

            $lines = CartLine::withoutGlobalScopes()
                ->where('cart_id', $cart->getKey())
                ->orderBy('id')
                ->get();
            $discountResult = new DiscountResult($discountAmount, [], $freeShipping);
            $shippingAmount = $this->shippingAmount($checkout, $discountResult);
            $taxSettings = $this->taxSettings($checkout);
            $taxResult = $this->taxes->calculateForAmounts(
                $lines->pluck('line_total_amount')->map(fn (int $amount): int => $amount)->all(),
                $shippingAmount,
                $taxSettings,
                $checkout->shipping_address_json ?? [],
            );
            $discountedSubtotal = $subtotal - $discountResult->amount;
            $total = $taxSettings->prices_include_tax
                ? $discountedSubtotal + $shippingAmount
                : $discountedSubtotal + $shippingAmount + $taxResult->totalAmount;

            $result = new PricingResult(
                subtotal: $subtotal,
                discount: $discountResult->amount,
                shipping: $shippingAmount,
                taxLines: $taxResult->taxLines,
                taxTotal: $taxResult->totalAmount,
                total: $total,
                currency: $cart->currency,
            );

            $checkout->forceFill([
                'tax_provider_snapshot_json' => $taxResult->toArray(),
                'totals_json' => $result->toArray(),
            ])->save();

            return $result;
        });
    }

    private function resetLineAmounts(Checkout $checkout): void
    {
        CartLine::withoutGlobalScopes()
            ->where('cart_id', $checkout->cart_id)
            ->get()
            ->each(function (CartLine $line): void {
                $subtotal = $line->unit_price_amount * $line->quantity;

                $line->forceFill([
                    'line_subtotal_amount' => $subtotal,
                    'line_discount_amount' => 0,
                    'line_total_amount' => $subtotal,
                ])->save();
            });
    }

    private function shippingAmount(Checkout $checkout, DiscountResult $discountResult): int
    {
        if (! $this->shipping->requiresShipping($checkout->cart)) {
            return 0;
        }

        if ($checkout->shipping_method_id === null) {
            return 0;
        }

        $rate = ShippingRate::withoutGlobalScopes()->find($checkout->shipping_method_id);

        if (! $rate instanceof ShippingRate) {
            throw InvalidCheckoutTransitionException::because('Shipping rate is not available.');
        }

        $amount = $this->shipping->calculate($rate, $checkout->cart);

        if ($amount === null) {
            throw InvalidCheckoutTransitionException::because('Shipping rate is not available for this cart.');
        }

        return $discountResult->freeShipping ? 0 : $amount;
    }