From 60a4a0c911c278a92a5b2cf8af56ce449e504730 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Fri, 28 Aug 2026 16:48:50 +0800 Subject: [PATCH] fix: build query string explicitly in Utils::apiUrl Laravel's url() helper renders its second argument as rawurlencoded path segments with keys discarded, so apiUrl('/api/user', ['id' => 1]) produced https://host/api/user/1 instead of the documented ?id=1. Build the query string with http_build_query after the port insertion instead. Also correct the test bootstrap's url() shim to mirror the real UrlGenerator::to() path-segment semantics, which had been masking the divergence in UtilsTest. --- src/Support/Utils.php | 8 +++++++- tests/Pest.php | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Support/Utils.php b/src/Support/Utils.php index 58ec2700..b9f1ab9b 100644 --- a/src/Support/Utils.php +++ b/src/Support/Utils.php @@ -38,7 +38,9 @@ class Utils public static function apiUrl(string $path, ?array $queryParams = [], int $port = 80): string { $isLocalDevelopment = app()->environment(['local', 'development']); - $baseURL = url($path, $queryParams, !$isLocalDevelopment); + // Laravel's url() renders extra parameters as path segments, not a query string, + // so the query string must be built here + $baseURL = url($path, [], !$isLocalDevelopment); // Check if default port is used to avoid appending it unnecessarily if (!in_array($port, [80, 443])) { @@ -52,6 +54,10 @@ public static function apiUrl(string $path, ?array $queryParams = [], int $port } } + if (!empty($queryParams)) { + $baseURL .= (str_contains($baseURL, '?') ? '&' : '?') . http_build_query($queryParams); + } + return $baseURL; } diff --git a/tests/Pest.php b/tests/Pest.php index 28ddbb13..77acb87e 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -311,11 +311,15 @@ function storage_path(string $path = ''): string if (!function_exists('url')) { function url(string $path = '', mixed $parameters = [], ?bool $secure = null): string { + // Mirrors Illuminate\Routing\UrlGenerator::to(): extra parameters become + // rawurlencoded path segments with keys discarded, NOT a query string $base = $secure ? 'https://fleetbase.test' : 'http://fleetbase.test'; $path = '/' . ltrim($path, '/'); if (is_array($parameters) && $parameters !== []) { - return $base . $path . '?' . http_build_query($parameters); + $tail = implode('/', array_map('rawurlencode', array_values($parameters))); + + return $base . rtrim($path, '/') . '/' . $tail; } return $base . $path;