getMethod($method); $target->setAccessible(true); return $target->invokeArgs($route, $args); } it('normalizes type lists from csv json and arrays', function (): void { $_SERVER['REQUEST_URI'] = '/search/system'; $route = new systemSearchRoute(); $csv = system_search_route_invoke_private($route, 'parseTypeList', [' Orders,customers ,ORDERS']); $json = system_search_route_invoke_private($route, 'parseTypeList', ['["invoices","Orders","invoices"]']); $array = system_search_route_invoke_private($route, 'parseTypeList', [[ ' Vehicles ', 'vehicles', 'ORDERS', 123, ]]); expect($csv)->toBe(['orders', 'customers']); expect($json)->toBe(['invoices', 'orders']); expect($array)->toBe(['vehicles', 'orders']); }); it('parses booleans and clamps integers using route defaults', function (): void { $_SERVER['REQUEST_URI'] = '/search/system'; $route = new systemSearchRoute(); expect(system_search_route_invoke_private($route, 'toBool', ['true', false]))->toBeTrue(); expect(system_search_route_invoke_private($route, 'toBool', ['0', true]))->toBeFalse(); expect(system_search_route_invoke_private($route, 'toBool', ['not-a-bool', true]))->toBeTrue(); expect(system_search_route_invoke_private($route, 'clampInt', [0, 1, 200, 50]))->toBe(50); expect(system_search_route_invoke_private($route, 'clampInt', [999, 1, 200, 50]))->toBe(200); expect(system_search_route_invoke_private($route, 'clampInt', [-4, 1, 200, 50]))->toBe(1); expect(system_search_route_invoke_private($route, 'clampMaxResults', [0]))->toBe(50); expect(system_search_route_invoke_private($route, 'clampMaxResults', [999]))->toBe(50); expect(system_search_route_invoke_private($route, 'clampMaxResults', [-4]))->toBe(1); expect(system_search_route_invoke_private($route, 'clampMaxResults', [12]))->toBe(12); }); it('exposes expected searchable entity types', function (): void { $_SERVER['REQUEST_URI'] = '/search/system'; $route = new systemSearchRoute(); $types = system_search_route_invoke_private($route, 'allEntityTypes'); expect($types)->toContain('orders'); expect($types)->toContain('customers'); expect($types)->toContain('users'); expect($types)->toContain('invoices'); expect($types)->toContain('module_config'); expect($types)->toContain('objects'); expect($types)->toContain('bookings'); expect($types)->toContain('products'); expect($types)->toContain('product_options'); expect($types)->toContain('plate_scans'); expect($types)->toContain('notifications'); expect($types)->toContain('department_time_bookings_entries'); expect($types)->toContain('stripe_module_orders'); expect($types)->toContain('xlvask_usage_logs'); }); it('does not grant global users search through narrow id and name lookup permissions', function (): void { $_SERVER['REQUEST_URI'] = '/search/system'; $route = new systemSearchRoute(); $map = system_search_route_invoke_private($route, 'entityPermissionMap'); $usersAll = $map['users']['all'] ?? []; expect($usersAll)->toContain('list_users'); expect($usersAll)->toContain('get_user'); expect($usersAll)->not->toContain('get_user_id'); expect($usersAll)->not->toContain('get_user_name'); });