'run'] entry behind, and callAction('run') then hit * __call() and produced a 500 (seen in production on /calendar/showMyCalendar * and /timesheets/showMy). A cached entry must only be trusted if its class and * method still exist; otherwise it gets dropped and the route re-resolved. */ class FrontcontrollerRouteCacheTest extends TestCase { protected function setUp(): void { parent::setUp(); // The cached-route read path is only taken when debug is off (writes happen // regardless), so the validation under test requires debug to be disabled. config(['debug' => false]); } private function frontcontroller(): Frontcontroller { // Built by hand: container resolution would pull in the real // PermissionEnforcer, which needs a database connection. return new Frontcontroller( IncomingRequest::create('/calendar/showMyCalendar', 'GET'), $this->createMock(PermissionEnforcer::class), ); } private function cacheKey(string $module, string $action, string $method): string { return 'routes.'.$module.'.Controllers.'.$action.'.'.$method; } public function test_stale_cached_method_is_dropped_and_route_reresolved(): void { // Simulate a pre-deploy cache entry pointing at the removed run() method. $key = $this->cacheKey('Calendar', 'ShowMyCalendar', 'get'); Cache::store('installation')->set($key, [ 'class' => \Leantime\Domain\Calendar\Controllers\ShowMyCalendar::class, 'method' => 'run', ]); $result = $this->frontcontroller()->getValidControllerCall('calendar', 'showMyCalendar', 'get', 'Controllers'); $this->assertSame('get', $result['method']); $this->assertSame(\Leantime\Domain\Calendar\Controllers\ShowMyCalendar::class, $result['class']); // The stale entry must have been replaced with the fresh resolution. $this->assertSame($result, Cache::store('installation')->get($key)); } public function test_cached_entry_with_missing_class_is_dropped(): void { $key = $this->cacheKey('Calendar', 'ShowMyCalendar', 'get'); Cache::store('installation')->set($key, [ 'class' => 'Leantime\\Domain\\Calendar\\Controllers\\NoLongerExists', 'method' => 'get', ]); $result = $this->frontcontroller()->getValidControllerCall('calendar', 'showMyCalendar', 'get', 'Controllers'); $this->assertSame(\Leantime\Domain\Calendar\Controllers\ShowMyCalendar::class, $result['class']); $this->assertSame('get', $result['method']); } public function test_valid_cached_entry_is_returned_as_is(): void { $key = $this->cacheKey('Calendar', 'ShowMyCalendar', 'get'); $cached = [ 'class' => \Leantime\Domain\Calendar\Controllers\ShowMyCalendar::class, 'method' => 'get', ]; Cache::store('installation')->set($key, $cached); $result = $this->frontcontroller()->getValidControllerCall('calendar', 'showMyCalendar', 'get', 'Controllers'); $this->assertSame($cached, $result); } }