Repository navigation
Improve Fleet-Ops server test coverage - #277
Merged
Merged
Conversation
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. Thanks for integrating Codecov - We've got you covered ☂️ |
Adds server/tests/Unit/Models/SensorReadingsTest.php covering the Sensor model reading pipeline against SQLite with the token-guard auth manager and disabled activity log: out-of-threshold readings opening a single threshold alert without duplication, normal readings resolving open alerts, severity mapping and alert message generation, and subject position creation from latitude/longitude and location-keyed attributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Internal/VendorControllerEndpointsTest.php covering the internal VendorController against SQLite with an excel fake: the export download with filename/format handling, the distinct status listing, the import pipeline with resolved files and the invalid-file error branch, the vendor/driver/contact lookup helpers including trashed and or-fail variants, the contact resource payload projection, and the vendor personnel updateOrCreate/list/create/delete helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Internal/ContactControllerEndpointsTest.php covering the internal ContactController against SQLite with an excel fake: export downloads, the import pipeline with the invalid-file error branch, contact lookup and vendor-conversion helpers (creation, personnel linkage, transaction wrapper, vendor resource payload), the customer context migration rewriting orders and customer-portal issue metadata onto the converted vendor, and the customer portal welcome-email guard branches with extension detection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Support/OperationalQueryDistributionTest.php covering the OperationalQueryCapability driver geofence distribution against SQLite with spatial containment stand-ins: the empty-fleet short circuit, online and updated_at filter application, packed-WKB point hydration, and per-service-area/zone containment counting as an admin session user. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Notifications/OrderFailedChannelsTest.php covering the OrderFailed notification title construction with the waypoint-tracking-number preference, broadcast channel construction across company/api/order channels, and the fcm/apn delegation seams. Adds server/tests/Unit/Console/AssignCustomerRolesCommandTest.php covering the fleetops:assign-customer-roles command traversal with user resolution, the role-assignment error branch, and the quiet empty run. Adds server/tests/Unit/Models/IntegratedVendorLifecycleTest.php covering the IntegratedVendor created/updated/deleted boot hooks resolving the lalamove provider, credential access, the provider/api bridges, and the webhook-url mutator's explicit and derived-default branches. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Http/Resources/MaintenanceResourcesTest.php covering both maintenance API resources: the Ember maintenance-subject and facilitator type injections with empty passthroughs, the morph transformer null and JsonResource fallbacks, and full serialization of loaded polymorphic subject/maintainable relations through the whenLoaded callbacks against SQLite. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Api/OrderControllerStartActivityTest.php covering the API OrderController startOrder and updateActivity endpoints against SQLite with a real transport order-config flow: the unknown-order, already-started, missing-driver, adhoc-without-driver, and not-dispatched error branches; the skip-dispatch success path that starts the order, assigns the driver's current job, fires OrderStarted, and delegates into updateActivity with the started activity; and the updateActivity unknown/completed rejections plus the dispatched-activity branch firing OrderDispatchFailed when no driver is assigned. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Api/OrderControllerLifecycleActionsTest.php covering the API OrderController lifecycle endpoints against SQLite with the transport order-config flow: getNextActivity resolving flow steps with the 404 branch and proof-of-delivery flag/method injection on completing activities, completeOrder's incomplete-waypoint guard, cancelOrder transitioning the order to canceled, and setDestination's validation and current-service-stop persistence. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Api/OrderControllerPersistenceHelpersTest.php covering the API OrderController protected persistence helpers against SQLite: customer contact firstOrCreate dedupe, the company timezone fallback, order/proof/file creation, the finalize-order job dispatch through the chainable dispatch shim, the routing-engine delegation seam, storage writes via a filesystem fake, proof subject scoping for order and entity subjects, entity editing settings lookup, and the order/proof/comment resource wrappers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Internal/OrderControllerActivityFlowsTest.php covering the internal OrderController against SQLite with the transport order-config flow: start's unknown/already-started/driverless guards and the success path assigning the driver's current job and firing OrderStarted, updateActivity's proof-of-delivery requirement with the bypass flag, the dispatched-activity failure without an assigned driver, lifecycle activity updates writing tracking statuses, next-activity flow resolution, and setDestination's single-stop rejection plus multi-waypoint validation and persistence. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Support/FuelEfficiencyAndCanceledHandlersTest.php covering the FuelEfficiency weekly cost-per-distance aggregation with a YEARWEEK SQLite stand-in and the empty-series fallback, the HandleOrderCanceled listener's driver lookup and notification helpers through a dispatcher fake with the unassigned fallback, and the OrderCompleted notification broadcast channels plus fcm/apn delegation seams. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Models/ServiceAreaGeometryTest.php covering the ServiceArea geometry helpers: circular multi-polygon creation from a point with ring closure, polygon extraction from the border with geotools point-in-polygon containment for single and multiple coordinates, and the centroid/location accessor seam that requires the GEOS engine. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Internal/ServiceQuoteControllerQueryRecordTest.php covering queryRecord against SQLite with the calculate distance-matrix provider: quoting a stored payload against a specific service rate with single-quote selection, quoting all servicable company rates with best-quote picking, the integrated-vendor resolution seam, and the preliminary fallback for unknown payloads. Exercising queryRecord surfaced a latent fatal, now fixed: the endpoint called getAllStops()->mapInto(Place::class), but getAllStops() already normalizes every stop into a Place instance — re-wrapping passed Place models into the model constructor and threw a TypeError for every real payload quote. The stops collection is now used directly. Seventh production bug found and fixed by this campaign. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Models/DriverModelHelpersTest.php covering the Driver model helpers against SQLite: position creation from latitude/longitude and location-keyed coordinate variants with subject scoping, user resolution through the relation with the uuid fallback, driver creation from import rows exercising both the existing-user lookup and fresh-user provisioning branches with vehicle resolution and country normalization, and identifier lookups matching user name/email and driver license/public-id columns. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Internal/OrchestrationControllerImportOrdersTest.php covering the internal OrchestrationController importOrders endpoint against SQLite: the empty-rows 422 rejection; a full pickup/dropoff row import resolving the order config, creating customer contacts and facilitator vendors on demand, matching vehicles by plate and drivers by identifier, persisting pickup/dropoff places with locations, required skills, and entities; multi-waypoint groups collapsing into a single order with one waypoint per row; and per-group failure capture with transaction rollback on invalid dates. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Models/SmallModelSurfacesTest.php covering small remaining surfaces against SQLite: Zone creation with the active-status default and its relations/polygon construction with the GEOS centroid seam, PurchaseRate relations plus resolveFromRequest by uuid and public id, the Customer creating hook forcing the customer type, ContactObserver email/phone availability checks with the user deletion path, and the CreateTrackingStatusRequest session authorization plus its duplicate-status validation closure across matched, unmatched, and bypassed inputs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Support/TelematicServiceTest.php covering the TelematicService against SQLite: device linking with provider-identity validation, telemetry reconciliation, and dedupe on re-link; device event storage with full telemetry field mapping, location normalization, and payload-resolved device attachment; sensor storage with identity validation, default locations, and device-linked identity fallback; device filtering by status and search; connection test recording across success and failure; credential decryption fallbacks for plain json and empty values through an encrypter fake; and webhook telematic resolution by integration id, provider account metadata, and device identity. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Internal/PositionControllerReplayMetricsTest.php covering the internal PositionController replay endpoint (channel and position-id guards, missing-position rejection, and the replay job dispatch with speed handling), the metrics endpoint with input guards and calculation over stored positions with packed-WKB coordinates, and the API ContactController protected helpers: create/update input normalization with phone formatting and type defaults, contact instantiation and upsert persistence, public-id lookup, place uuid and related-user resolution, resource wrappers, and json/error responses. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Support/MaintainableAndOperationalAlertsTest.php covering the Maintainable trait through the Part model against SQLite: needsMaintenance across no-history, overdue-scheduled, and interval-configured paths, maintenance scheduling with priority details, and cost/frequency aggregation over completed history. Also covers the ProcessOperationalAlerts helper bodies: the operational orders query window with status/company filters, latest-position lookup, alert settings resolution with defaults, route point collection with pair normalization and axis-swap handling, minimum distance measurement, and the once-only notification metadata guard. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Internal/WorkOrderAndConfigSurfacesTest.php covering the internal WorkOrderController sendEmail flow (missing assignee and missing email 422 guards, and the success path sending the dispatch mail through a mailer fake with activity logging disabled), the excel export/import delegation helpers, the OrderConfigController delete flow with the core-service guard and soft deletion, and the SensorFilter public-relation resolution with company scoping against SQLite. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Models/OrderPurchaseAndDriversTest.php covering the Order purchase helpers against SQLite: service quote resolution by uuid and public id with purchase-rate creation, the unresolvable-quote failure, the no-quote fallback creating an internal dispatch transaction, purchase-rate attachment relinking the new transaction to the order and voiding the superseded one, and closest-driver discovery through the spatial company/user/driver chain with the located-pickup requirement. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Support/OrchestrationPayloadBuilderTest.php covering the OrchestrationPayloadBuilder computation helpers: payload demand aggregation across entities with gram/pound weight conversion and centimetre dimension normalization into litres, the order-meta fallback for entity-less payloads, vehicle-only VROOM entries with location requirements, capacity arrays, and max-task handling, safe meta access swallowing accessor failures, and coordinate validation with place-location resolution. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Api/DeviceControllerCrudTest.php covering the API DeviceController against SQLite: find/delete with not-found handling and soft deletion, detach with the missing-device 404 and the failure branch logging, device creation/update persistence helpers with resource wrappers, input mapping building last-position points from latitude/longitude, blank-attachable clearing, and the attachment failure logging helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Internal/FleetAssignmentsAndTriggersTest.php covering the internal FleetController static helpers against SQLite: fleet/driver/vehicle uuid lookups with missing fallbacks, driver and vehicle assignment existence/creation/deletion, operations-monitor cache invalidation through a cache fake, and json responses. Also covers the ProcessMaintenanceTriggers helpers: sandbox/mysql connection selection, the active-schedule query with due-marker filters, open work-order existence, work-order counting and creation, and the triggered-event dispatch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Feature/Http/Internal/MaintenanceScheduleControllerSurfacesTest.php covering the internal MaintenanceScheduleController against SQLite with an excel fake: export downloads, the import pipeline with the invalid-file error branch, schedule lookups by uuid and public id with relation loading, the active calendar-schedule window query, session user resolution, the ical response seam, and work-order derivation from schedule attributes with priority and category mapping. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Observers/PurchaseRateObserverAndOrderJobsTest.php covering the PurchaseRateObserver protected helpers against SQLite (uuid generation, relation loading, service-quote currency/amount/item access, company and currency resolution, transaction and transaction-item creation, and payload-based order resolution with the null fallback), the FinalizeInternalOrderCreation job firing OrderReady with the missing-order exit, and the OrderCanceled notification mail seams with waypoint tracking plus the fcm/apn delegation seams. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Console/FixCommandsAndMaintenanceControllerTest.php covering the FixCustomerCompanies command helpers against SQLite (customer/user/company lookups, membership checks, and existing-user assignment persistence), the polymorphic namespace fixer traversing all five configured models, and the internal MaintenanceController export download, import pipeline, line-item lookup, and parts/total cost recalculation from quantity and unit costs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Support/OsrmProofAndIssueFilterTest.php covering the OSRM routing client with faked HTTP and cache (point routes, the minimum-points guard, multi-point routes with cache reuse, nearest, table, and trip endpoints), the internal ProofController subject lookups by uuid and public id across order/waypoint/entity types with the unknown-type fallback, proof creation, signature storage through a filesystem fake, and response payloads, plus the IssueFilter relation subqueries across uuid/public-id/free-text variants and date-window filtering. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds server/tests/Unit/Support/OptimizeOrderRouteCapabilityTest.php covering the OptimizeOrderRouteCapability against SQLite as an admin session user: the not-ready-preview, missing-order, and insufficient-waypoint guards, the successful apply transaction updating payload waypoints and marking the order route-optimized with the completed resource payload, prompt matching for route-optimization phrasing, and order resolution from prompt search terms. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Place::insertFromMixed() called insertFromGeocodingLookup() for any plain address string, but no such method existed on Place or any ancestor, so the call always raised BadMethodCallException. Define it as the insert-side twin of createFromGeocodingLookup, mirroring insertFromGoogleAddress. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Rule stand-in accepted where() closures and discarded them, so the company/soft-delete scoping inside them never executed. Run them against a recording double instead and assert the recorded constraints. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…y fallback Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two defects surfaced while auditing unreachable code. GeocoderController::reverse validated coordinates only after converting them with Utils::getPointFromCoordinates(), which is typed `: Point` and falls back to Point(0, 0) for unusable input. The 'Invalid coordinates provided.' branch was therefore unreachable and garbage input silently reverse-geocoded Null Island. Resolve strictly instead so the guard works. An existing test asserted the old behaviour (reverseCalls[0] === [0.0, 0.0]) and now asserts the error fires with no lookup attempted. Casts/Polygon returned the raw geometry from its GeometryInterface arm while Casts/Point and Casts/MultiPolygon return a SpatialExpression. Only inserts survive the raw form, because SpatialTrait::performInsert wraps the attribute itself; there is no performUpdate, so on updates the value is bound directly and BaseBuilder::cleanBindings only expands a SpatialExpression into the WKT and SRID bindings that ST_GeomFromText(?, ?) needs. A bare Geometry has no __toString and cannot be bound. Align Polygon with the other two casts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deletes branches no input can reach: concrete spatial-type arms shadowed by instanceof GeometryInterface; a duplicate isCoordinatesStrict test inside a branch already gated on it; Lalamove __callStatic's 'instance' case, which a declared public static never routes there; guards a type declaration makes redundant (getLocationAsPoint(): SpatialPoint, Request::date()'s Carbon, Find::httpResourceForModel() always resolving, Str::isUuid on a model); DriverController's company re-check after an early return; and the order-type fallback after an unconditional assignment, replaced by ?? at the assignment. Relocates Place::insertFromMixed's address-key check out of the is_string branch (empty() on a non-numeric string offset is always true) into the array branch, and moves the GoogleAddress arm above is_array||is_object so it is not swallowed and flattened. Makes coordsToCircle's loop exclusive so the ring is closed explicitly rather than by recomputing the 0-degree vertex, removing a duplicated point; output is otherwise identical. Keeps and annotates three guards that are deliberate: Casts/Point's SpatialExpression arm (the guard shadowing it skips the geometries bookkeeping, so the asymmetry is documented rather than erased), the globe-data ISO check (all 255 bundled features carry both codes), the post-validate photo check, and updateActivity's not-found guard pending the upstream core-api findByIdOrFail fix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review feedback on #281: deleting a shadowed arm erases the intent it documented. Reorder so each previously-unreachable guard fires, with runtime behaviour unchanged. Casts/Point checks SpatialExpression before the generic Expression guard that was swallowing it. Casts/Polygon and Casts/MultiPolygon check their concrete type before the broader GeometryInterface guard. MultiPolygon's restored arm must wrap in a SpatialExpression exactly as the general arm does — reordering it verbatim would have flipped MultiPolygon writes from wrapped to raw, which is the write path this review was guarding. Reverts the Casts/Polygon SpatialExpression alignment. Polygon returning a bare geometry while Point and MultiPolygon wrap is a real divergence on the update path, but it is a write-path behaviour change that deserves its own review with MySQL verification, so it is documented and tested rather than altered here. Also corrects two misleading comments: the company guard note in DriverController sat on a line whose subject is , and the updateActivity annotation implied its guard becomes reachable once core-api is patched when in fact findOrder() is typed ': Order' and it stays unreachable regardless. Adds a deliberately failing test for the nextActivity not-found branch, which becomes live when core-api 1.6.55 ships the findByIdOrFail fix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The nearby-filter fixture registered ST_X, ST_Y and ST_Distance_Sphere as constants (103.8, 1.3, 100.0), so the distance filter those tests exercise was never actually evaluated. Decode the packed point for ST_X/ST_Y and compute st_distance_sphere with the haversine formula on MySQL's 6370986m earth radius. This verifies selection semantics rather than MySQL's exact arithmetic. Two further defects in this file are left as-is and reported: the assertions use toBeGreaterThanOrEqual(0), which cannot fail, and cross-test connection isolation leaks so the controller can query a previous test's rows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…anup Remove unreachable backend code and fix two defects it was hiding
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This is a progressive backend-only coverage PR for Fleet-Ops
./server.server/tests/Unit/...andserver/tests/Feature/...instead of adding more flat root-level coverage files.response()->apiError(...)) and job dispatch branches (Job::dispatch/dispatchIf) are reachable under test — previously these fatally errored and structurally blocked coverage on nearly every controller.Latest Local Coverage
Fresh host run from
COMPOSER_PROCESS_TIMEOUT=0 composer coverage:baseline:Coverage gate verification:
php scripts/coverage-summary.php coverage/clover.xml --fail-under=100correctly fails while coverage is below 100%.Latest Progress
collection()scoping (17 classes),queryWithRequestacross every API controller (19 classes), importcreateFromImportdelegation (13 classes), filter date ranges, Excel download/import seams, requestauthorize()gates, resource relation resolution, observer/listener query seams, and assorted controller/command/job seams.Place::insertFromMixed()calledinsertFromGeocodingLookup()for any plain address string, but no such method existed onPlaceor any ancestor — every such call raisedBadMethodCallException. Defined it as the insert-side twin ofcreateFromGeocodingLookup, mirroring the existinginsertFromGoogleAddressshape (the already-present but callerlessgetValuesFromGeocodingLookup()is exactly its other half).Place::insertFromCoordinates()guarded empty reverse-geocoding results with!$results->count() === 0, comparing a bool to an int so the guard never fired — with no results the code fell through to an address array carrying location0,0, whicharray_mergelayered over the caller's real coordinates, silently inserting places at Null Island instead of returningfalseas documented.Lalamove::getQuotationForMarket()calledinstance(null, null, $market), putting the market in thebool $sandboxslot — withoutstrict_typesthe string coerced totrue, so market-scoped quotations ran against the sandbox host with the market silently dropped.OrderConfig::default()declared a non-nullableselfreturn while returningfirst(), so companies without a stored transport config fataled instead of having one provisioned.ServiceRatecalledCollection::sortByDesc()with no argument, throwing whenever a parcel outsized every fee tier.queryWithRequestseam on all 19 API controllers, Lalamove response handling (Guzzle client is an injectable property),Support\Auth::can()and the form requests gating on it (a real spatie fixture works), and every GEOS-dependent geometry accessor (inject aBrick\Geo\Engine\GeometryEngineRegistryfake — no native extension needed). Blocked labels are worth re-probing rather than trusting.Test-quality findings
Coverage percentage is not the same as verification, and two things found while working on this PR are worth stating plainly rather than leaving implied:
OrderControllerNearbyFiltersTestregistered its spatial functions as constants —ST_Xalways returned103.8,ST_Distance_Spherealways100.0— so the distance filter those tests appear to exercise was never evaluated. They now decode the packed point and compute haversine on MySQL's earth radius, which verifies selection semantics (which rows fall inside the radius) though still not MySQL's exact arithmetic.->toBeGreaterThanOrEqual(0)on a count, which can never fail; and cross-test connection isolation leaks, so the controller can return rows seeded by a previous test. A test added there passed in isolation and failed in-file for exactly that reason, and was withdrawn rather than shipped green-by-ordering.More broadly: this suite runs on in-memory SQLite with eval'd function shims, container stand-ins and hand-registered spatial UDFs. It is good at proving branch logic and contracts, and poor at proving anything about real MySQL behaviour — the spatial write paths especially, where a fixture's
prepareBindingsoverride compensates for a real cast divergence. Treat a green run as "the branches behave as described", not "the feature works against a real database".Validation
Run on the host runtime (asdf PHP 8.4 with Xdebug,
XDEBUG_MODE=coverage), no Docker:php -l <changed test file>php scripts/pest-runner.php <changed test file>— pass count compared against the declaredtest(count, since a fatal truncates a run without reporting any failureXDEBUG_MODE=coverage php scripts/coverage-file-runner.php --coverage-clover=... <changed test file>— per-line slice check that the intended lines actually executed, before trusting a green assertionvendor/bin/php-cs-fixer fix --using-cache=no <changed file>composer test:lintPATH=<asdf php 8.4 bin>:$PATH XDEBUG_MODE=coverage COMPOSER_PROCESS_TIMEOUT=0 composer coverage:baselinephp scripts/coverage-summary.php coverage/clover.xml --fail-under=100git diff --check/git diff --cached --checkCurrent Lowest Coverage Targets
Next backend coverage slices, from the fresh local Clover report (highest absolute uncovered):
server/src/Http/Controllers/Api/v1/OrderController.phpserver/src/Http/Controllers/Internal/v1/OrderController.phpserver/src/Models/Place.phpserver/src/Http/Controllers/Api/v1/DriverController.phpserver/src/Models/Payload.phpThese files are now majority-dead rather than untested: 5 of the 7 remaining in
Models/Place.php, 2 of the 5 inApi/v1/DriverController.php, and 2 of the 5 inModels/Payload.phpare confirmed unreachable (see below).Practical ceiling
A growing share of what remains is provably unreachable rather than untested. Confirmed by direct analysis so far:
Casts/{Point,Polygon,MultiPolygon}instanceof GeometryInterface(orExpression) is tested before each concrete spatial type, so the later arms are shadowedHttp/Resources/v1/{Maintenance,MaintenanceSchedule,WorkOrder,Order}Find::httpResourceForModel()always resolves a class, falling back toFleetbaseResource, so theJsonResourcefallbacks never runModels/Place::createFromMixedisCoordinatesStrict()inside a branch already gated on it one arm aboveModels/Place::findExistingSharedPlace$locationis initialised to aSpatialPointand the catch assigns one, so the non-point guard cannot fireModels/Place::insertFromMixed(address key)is_string($place)branch, andempty()on a non-numeric string offset is always true, so it never firesModels/Place::insertFromMixed(GoogleAddress arm)is_array($place) || is_object($place)arm that catches every object firstHttp/Controllers/Api/v1/OrderController::updateActivityif (!$order)guard follows a try/catch whosefindOrder()is: Order-typed and throws rather than returning nullSupport/Utils::coordsToCircle0..360loop closes the circle exactly, so the closing-point guard never triggersHttp/Controllers/Internal/v1/GeocoderControllergetPointFromCoordinates(), declared: Point(non-nullable)Http/Controllers/Internal/v1/MetricsController$request->date()against not being aDateTime; it returns Carbon, which extends itHttp/Controllers/Api/v1/DriverControllerIntegrations/Lalamove::__callStaticinstanceis a defined public static, so PHP never routes it through__callStaticHttp/Controllers/Internal/v1/OrderController::statusesmethod_exists($config, 'activities'), butOrderConfig::activities()is declaredHttp/Controllers/Internal/v1/TelematicController::testCredentialsregistry->resolve(), typed: TelematicProviderInterface, which throws rather than returning null (the surrounding try/catch reports it)Models/ServiceArea::createMultiPolygonFromPointUtils::coordsToCircle()already returns a closed ring, sofirst !== lastis never trueHttp/Resources/v1/{PurchaseRate,TrackingStatus}relation accessorsmethod_exists($this, 'loadMissing'), but no class in the hierarchy (FleetbaseResource->JsonResource) declares it — it only resolves via__call, whichmethod_existsdoes not seeModels/Payload::setPlacePlace::createFromMixed(): ?Placealways yields a Model or null, so theStr::isUuid()arm and the trailingelseare both shadowed by theinstanceof Modelarm between themModels/ServiceRate::getLngLatFromPlacePlace::getLocationAsPoint(), declared: SpatialPoint(non-nullable), and aSpatialPointalways exposesgetLat/getLngExports/VehicleExport::locationPartUtils::castPoint(), which catches every failure and falls back toPoint(0, 0), so it is never falsyModels/Place::insertFromMixed/createFromMixedThree things previously written off as untestable turned out not to be, and are now covered:
queryWithRequestseam on all 19 API controllers — it needed only a session store, route-resolver stub and a couple of request macros;post/requesthelpers are private, but the Guzzle client is an injectable property, so aMockHandlerexercises the real code path without network access;Support\Auth::can()and the form requests that gate on it — a real spatie fixture works (permissions seeded with guardsanctum, plusmodel_has_permissionsrows keyed to the session user's CompanyUser uuid). The internal create-driver and create-order-config requests now resolve opposite ways through that one gate, which proves the permission is genuinely consulted rather than blanket-true.The lesson is to re-probe "blocked" labels periodically rather than trusting them.
Two further lines (
Internal/v1/OrderController887-888) are reachable only once the upstreamfindByIdOrFaildefect below is fixed, and are deliberately left uncovered rather than shimmed green.A handful more are blocked by genuinely external dependencies — Firebase-backed push payloads, the
Illuminate\Encryption\Encrypter(absent from this vendor tree), and MySQL-onlyst_distance_spherespatial predicates that SQLite cannot evaluate.Known upstream defect (needs a
core-apipatch)Model::findByIdOrFail()infleetbase/core-apithrowsBadMethodCallExceptioninstead of theModelNotFoundExceptionit documents, because it calls agetModelNotFoundException()method that does not exist on Eloquent's Builder. Four call sites in this package havecatch (ModelNotFoundException)blocks that can never fire, so missing records surface as HTTP 500s. Details, affected lines and a suggested fix are in this PR comment. Two lines inInternal/v1/OrderController.phpare intentionally left uncovered pending that fix rather than shimmed green.Known in-package defect (deferred, not fixed here)
Api\v1\ServiceQuoteController::bestQuote()returnsnullfor an empty collection and is passed straight intoserviceQuoteResource(ServiceQuote $serviceQuote), which is non-nullable — so requestingsingle=1when no service rate is servicable for the given waypoints returns HTTP 500 instead of a meaningful "no quotes available" response. The same shape appears at two entry points in that file. Details and a suggested guard are in this PR comment. Left unfixed deliberately: it is a behavior change that does not belong in a coverage PR.Notes