@fleetbase/fleetops-engine 0.6.61 → 0.6.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/RELEASE.md +23 -8
- package/addon/services/map-settings.js +4 -1
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +1 -1
- package/server/migrations/2026_09_05_000001_add_unique_indexes_to_fleet_membership_pivots.php +129 -0
- package/server/src/Exceptions/PublicRelationNotFoundException.php +47 -0
- package/server/src/Http/Controllers/Api/v1/Concerns/ResolvesFleetOpsApiResources.php +42 -7
- package/server/src/Http/Controllers/Api/v1/Concerns/ResolvesPublicExpansions.php +187 -0
- package/server/src/Http/Controllers/Api/v1/DriverController.php +93 -57
- package/server/src/Http/Controllers/Api/v1/EntityController.php +1 -1
- package/server/src/Http/Controllers/Api/v1/FleetController.php +370 -33
- package/server/src/Http/Controllers/Api/v1/FuelReportController.php +1 -1
- package/server/src/Http/Controllers/Api/v1/IssueController.php +1 -1
- package/server/src/Http/Controllers/Api/v1/OrderController.php +1 -1
- package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +1 -1
- package/server/src/Http/Controllers/Api/v1/TrackingStatusController.php +1 -1
- package/server/src/Http/Controllers/Api/v1/VehicleController.php +134 -35
- package/server/src/Http/Controllers/Api/v1/ZoneController.php +1 -1
- package/server/src/Http/Filter/Concerns/ResolvesPublicRelationUuids.php +54 -0
- package/server/src/Http/Filter/DriverFilter.php +71 -15
- package/server/src/Http/Filter/FleetFilter.php +32 -33
- package/server/src/Http/Filter/VehicleFilter.php +57 -19
- package/server/src/Http/Requests/Concerns/ScopesPublicRelationRules.php +48 -0
- package/server/src/Http/Requests/CreateDriverRequest.php +100 -9
- package/server/src/Http/Requests/CreateFleetRequest.php +30 -2
- package/server/src/Http/Requests/CreateServiceRateRequest.php +7 -2
- package/server/src/Http/Requests/CreateVehicleRequest.php +150 -31
- package/server/src/Http/Resources/v1/Concerns/ResolvesPublicRelationFields.php +110 -0
- package/server/src/Http/Resources/v1/Driver.php +22 -2
- package/server/src/Http/Resources/v1/Fleet.php +38 -25
- package/server/src/Http/Resources/v1/Vehicle.php +46 -4
- package/server/src/Models/Driver.php +2 -2
- package/server/src/routes.php +8 -0
- package/server/tests/ApiDriverControllerContractsTest.php +284 -13
- package/server/tests/ApiEntityControllerContractsTest.php +1 -1
- package/server/tests/ApiEquipmentControllerContractsTest.php +2 -2
- package/server/tests/ApiFleetControllerContractsTest.php +354 -21
- package/server/tests/ApiFuelReportControllerContractsTest.php +1 -1
- package/server/tests/ApiIssueControllerContractsTest.php +1 -1
- package/server/tests/ApiOrderControllerContractsTest.php +1 -1
- package/server/tests/ApiPartControllerContractsTest.php +2 -2
- package/server/tests/ApiServiceAreaZoneControllerContractsTest.php +2 -2
- package/server/tests/ApiTrackingStatusControllerContractsTest.php +1 -1
- package/server/tests/ApiVehicleControllerContractsTest.php +175 -8
- package/server/tests/ControllerFilterContractsTest.php +132 -13
- package/server/tests/ControllerHelperContractsTest.php +6 -3
- package/server/tests/DriverFilterExecutionTest.php +130 -6
- package/server/tests/ExceptionContractsTest.php +15 -0
- package/server/tests/Feature/Http/Api/DeviceControllerContractsTest.php +1 -1
- package/server/tests/Feature/Http/Api/FleetMembershipMigrationTest.php +140 -0
- package/server/tests/Feature/Http/Api/FleetMembershipTest.php +333 -0
- package/server/tests/Feature/Http/Api/FleetPublicContractTest.php +439 -0
- package/server/tests/Feature/Http/Api/FuelTransactionControllerContractsTest.php +2 -2
- package/server/tests/Feature/Http/Api/NullRelationshipInputTest.php +191 -0
- package/server/tests/Feature/Http/Api/PublicIdentifierFilterTest.php +293 -0
- package/server/tests/Feature/Http/Api/SmallApiControllerHelpersTest.php +7 -1
- package/server/tests/Feature/Http/Api/VehicleControllerTrackingTest.php +3 -1
- package/server/tests/Feature/Http/Api/VehiclePublicContractTest.php +454 -0
- package/server/tests/Feature/Http/Api/WorkOrderControllerContractsTest.php +1 -1
- package/server/tests/FleetHierarchyResourceTest.php +56 -8
- package/server/tests/RequestContractsTest.php +100 -7
- package/server/tests/Unit/Http/Resources/FleetResourceTest.php +50 -6
- package/server/tests/VehicleControllerHelperContractsTest.php +1 -1
|
@@ -4,7 +4,9 @@ use Fleetbase\FleetOps\Http\Controllers\Api\v1\DriverController;
|
|
|
4
4
|
use Fleetbase\FleetOps\Http\Requests\CreateDriverRequest;
|
|
5
5
|
use Fleetbase\FleetOps\Http\Requests\UpdateDriverRequest;
|
|
6
6
|
use Fleetbase\FleetOps\Models\Driver;
|
|
7
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
7
8
|
use Fleetbase\FleetOps\Models\Vehicle;
|
|
9
|
+
use Fleetbase\FleetOps\Models\Vendor;
|
|
8
10
|
use Fleetbase\LaravelMysqlSpatial\Types\Point;
|
|
9
11
|
use Fleetbase\Models\Company;
|
|
10
12
|
use Fleetbase\Models\User;
|
|
@@ -29,6 +31,9 @@ class FleetOpsApiDriverControllerProbe extends DriverController
|
|
|
29
31
|
public array $companyCalls = [];
|
|
30
32
|
public array $createdUsers = [];
|
|
31
33
|
public array $uuidLookups = [];
|
|
34
|
+
public array $relationLookups = [];
|
|
35
|
+
public array $relationCompanyScopes = [];
|
|
36
|
+
public array $unresolvable = [];
|
|
32
37
|
public array $pointInputs = [];
|
|
33
38
|
public array $createdDrivers = [];
|
|
34
39
|
public array $resolvedFiles = [];
|
|
@@ -76,6 +81,33 @@ class FleetOpsApiDriverControllerProbe extends DriverController
|
|
|
76
81
|
return $table . '-uuid';
|
|
77
82
|
}
|
|
78
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Stand in for the company-scoped public-id lookup.
|
|
86
|
+
*
|
|
87
|
+
* Anything listed in `$unresolvable` behaves as a cross-company or missing
|
|
88
|
+
* identifier does in production.
|
|
89
|
+
*/
|
|
90
|
+
protected function resolveUuid(string $modelClass, ?string $id, ?string $companyUuid = null): ?string
|
|
91
|
+
{
|
|
92
|
+
if (empty($id)) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
$this->relationLookups[] = [$modelClass, $id];
|
|
97
|
+
$this->relationCompanyScopes[] = $companyUuid;
|
|
98
|
+
|
|
99
|
+
if (in_array($id, $this->unresolvable, true)) {
|
|
100
|
+
throw (new ModelNotFoundException())->setModel($modelClass, $id);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return strtolower(class_basename($modelClass)) . '-uuid';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public function inputForTest(Request $request): array
|
|
107
|
+
{
|
|
108
|
+
return $this->driverInputFromRequest($request);
|
|
109
|
+
}
|
|
110
|
+
|
|
79
111
|
protected function pointFromCoordinates(array $coordinates): Point
|
|
80
112
|
{
|
|
81
113
|
$this->pointInputs[] = $coordinates;
|
|
@@ -343,21 +375,23 @@ test('api driver controller creates drivers with user company assignment and rel
|
|
|
343
375
|
->and($controller->user->assignedRoles)->toBe(['Driver'])
|
|
344
376
|
->and($controller->createdDrivers[0])->toMatchArray([
|
|
345
377
|
'status' => 'available',
|
|
346
|
-
'vehicle_uuid' => '
|
|
347
|
-
'vendor_uuid' => '
|
|
348
|
-
'current_job_uuid' => '
|
|
378
|
+
'vehicle_uuid' => 'vehicle-uuid',
|
|
379
|
+
'vendor_uuid' => 'vendor-uuid',
|
|
380
|
+
'current_job_uuid' => 'order-uuid',
|
|
349
381
|
'online' => 0,
|
|
350
382
|
'user_uuid' => 'user-uuid',
|
|
351
383
|
'company_uuid' => 'company-uuid',
|
|
352
384
|
])
|
|
353
385
|
->and($controller->createdDrivers[0]['location'])->toBeInstanceOf(Point::class)
|
|
354
|
-
->and($controller->
|
|
355
|
-
[
|
|
356
|
-
[
|
|
357
|
-
[
|
|
358
|
-
)
|
|
386
|
+
->and($controller->relationLookups)->toBe([
|
|
387
|
+
[Vehicle::class, 'vehicle_public'],
|
|
388
|
+
[Vendor::class, 'vendor_public'],
|
|
389
|
+
[Order::class, 'order_public'],
|
|
390
|
+
])
|
|
359
391
|
->and($controller->resolvedFiles)->toBe([['file_public', 'uploads/company-uuid/drivers']])
|
|
360
|
-
|
|
392
|
+
// `photo_uuid` is not a column on users; the avatar lives in `avatar_uuid`
|
|
393
|
+
// and the old key was silently dropped by mass assignment.
|
|
394
|
+
->and($controller->user->updates)->toContain(['avatar_uuid' => 'photo-file-uuid'])
|
|
361
395
|
->and($controller->driver->loaded)->toContain(['user', 'vehicle', 'vendor', 'currentJob']);
|
|
362
396
|
});
|
|
363
397
|
|
|
@@ -411,14 +445,14 @@ test('api driver controller updates drivers user details assignments location an
|
|
|
411
445
|
])
|
|
412
446
|
->and($driver->updates[0])->toMatchArray([
|
|
413
447
|
'status' => 'busy',
|
|
414
|
-
'vehicle_uuid' => '
|
|
415
|
-
'vendor_uuid' => '
|
|
416
|
-
'current_job_uuid' => '
|
|
448
|
+
'vehicle_uuid' => 'vehicle-uuid',
|
|
449
|
+
'vendor_uuid' => 'vendor-uuid',
|
|
450
|
+
'current_job_uuid' => 'order-uuid',
|
|
417
451
|
])
|
|
418
452
|
->and($driver->updates[0]['location'])->toBeInstanceOf(Point::class)
|
|
419
453
|
->and($driver->flushedForTest)->toBeTrue()
|
|
420
454
|
->and($controller->resolvedFiles)->toBe([['photo-input', 'uploads/session-company-uuid/drivers']])
|
|
421
|
-
->and($user->updates)->toContain(['
|
|
455
|
+
->and($user->updates)->toContain(['avatar_uuid' => 'photo-file-uuid'])
|
|
422
456
|
->and($driver->loaded)->toContain(['user', 'vehicle', 'vendor', 'currentJob']);
|
|
423
457
|
});
|
|
424
458
|
|
|
@@ -634,3 +668,240 @@ test('api driver controller refuses to set a password through a general update',
|
|
|
634
668
|
->and($user->updates[0])->not->toHaveKey('password')
|
|
635
669
|
->and($user->updates[0])->toHaveKey('name');
|
|
636
670
|
});
|
|
671
|
+
|
|
672
|
+
test('api driver controller accepts every safe driver field the model exposes', function () {
|
|
673
|
+
$payload = [
|
|
674
|
+
// Identity
|
|
675
|
+
'internal_id' => 'DRV-9001', 'drivers_license_number' => 'S1234567A',
|
|
676
|
+
'license_expiry' => '2030-06-30',
|
|
677
|
+
// Operational
|
|
678
|
+
'country' => 'SG', 'currency' => 'SGD', 'city' => 'Singapore', 'online' => true,
|
|
679
|
+
'current_status' => 'on_break', 'status' => 'available',
|
|
680
|
+
'heading' => 180, 'bearing' => 90, 'altitude' => 15, 'speed' => 42,
|
|
681
|
+
// Structured / orchestrator
|
|
682
|
+
'meta' => ['depot' => 'north'], 'skills' => ['hazmat'],
|
|
683
|
+
'max_travel_time' => 28800, 'max_distance' => 250000,
|
|
684
|
+
'time_window_start' => '08:00', 'time_window_end' => '18:00',
|
|
685
|
+
];
|
|
686
|
+
|
|
687
|
+
$controller = new FleetOpsApiDriverControllerProbe();
|
|
688
|
+
$input = $controller->inputForTest(new Request($payload));
|
|
689
|
+
|
|
690
|
+
$missing = array_values(array_diff(array_keys($payload), array_keys($input)));
|
|
691
|
+
|
|
692
|
+
expect($missing)->toBe([])
|
|
693
|
+
->and($input)->toMatchArray($payload);
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
test('api driver controller input excludes authentication tenancy and generated columns', function () {
|
|
697
|
+
// The projection used to be an `except()` blocklist, so anything nobody had
|
|
698
|
+
// thought to name reached Driver::create() intact — including the auth token.
|
|
699
|
+
$controller = new FleetOpsApiDriverControllerProbe();
|
|
700
|
+
|
|
701
|
+
$input = $controller->inputForTest(new Request([
|
|
702
|
+
'internal_id' => 'DRV-1',
|
|
703
|
+
'auth_token' => 'forged',
|
|
704
|
+
'signup_token_used' => true,
|
|
705
|
+
'user_uuid' => 'forged',
|
|
706
|
+
'company_uuid' => 'someone-elses-company',
|
|
707
|
+
'vehicle_uuid' => 'forged',
|
|
708
|
+
'vendor_uuid' => 'forged',
|
|
709
|
+
'current_job_uuid' => 'forged',
|
|
710
|
+
'_key' => 'forged',
|
|
711
|
+
'uuid' => 'forged',
|
|
712
|
+
'public_id' => 'driver_forged',
|
|
713
|
+
'slug' => 'forged',
|
|
714
|
+
'avatar_url' => 'forged',
|
|
715
|
+
]));
|
|
716
|
+
|
|
717
|
+
expect(array_keys($input))->toBe(['internal_id']);
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
test('api driver controller persists meta location and telemetry that the blocklist used to drop', function () {
|
|
721
|
+
// `location`, `heading`, `altitude`, `speed` and `meta` were all on the old
|
|
722
|
+
// `except()` list, so every write silently discarded them — and `meta` could
|
|
723
|
+
// not be mass assigned anyway because the model spelled it `meta,`.
|
|
724
|
+
$controller = new FleetOpsApiDriverControllerProbe();
|
|
725
|
+
|
|
726
|
+
$input = $controller->inputForTest(new Request([
|
|
727
|
+
'meta' => ['badge' => 'A12'],
|
|
728
|
+
'heading' => 270,
|
|
729
|
+
'altitude' => 8,
|
|
730
|
+
'speed' => 55,
|
|
731
|
+
]));
|
|
732
|
+
|
|
733
|
+
expect($input)->toMatchArray([
|
|
734
|
+
'meta' => ['badge' => 'A12'],
|
|
735
|
+
'heading' => 270,
|
|
736
|
+
'altitude' => 8,
|
|
737
|
+
'speed' => 55,
|
|
738
|
+
])->and(in_array('meta', (new Driver())->getFillable(), true))->toBeTrue();
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
test('api driver controller creates an operational driver with no email or phone', function () {
|
|
742
|
+
$controller = new FleetOpsApiDriverControllerProbe();
|
|
743
|
+
|
|
744
|
+
$response = $controller->create(new CreateDriverRequest([
|
|
745
|
+
'name' => 'Yard Driver',
|
|
746
|
+
'internal_id' => 'DRV-7788',
|
|
747
|
+
]));
|
|
748
|
+
|
|
749
|
+
// No invented address, no invented number: the user record simply carries
|
|
750
|
+
// neither, which the users table permits. The driver cannot sign in to
|
|
751
|
+
// Navigator until credentials are supplied.
|
|
752
|
+
expect($response)->toBe(['resource' => 'driver', 'driver' => $controller->driver])
|
|
753
|
+
->and($controller->createdUsers[0])->toMatchArray(['name' => 'Yard Driver'])
|
|
754
|
+
->and($controller->createdUsers[0]['email'] ?? null)->toBeNull()
|
|
755
|
+
->and($controller->createdUsers[0]['phone'] ?? null)->toBeNull()
|
|
756
|
+
->and($controller->createdDrivers[0])->toMatchArray([
|
|
757
|
+
'internal_id' => 'DRV-7788',
|
|
758
|
+
'user_uuid' => 'user-uuid',
|
|
759
|
+
'company_uuid' => 'company-uuid',
|
|
760
|
+
'status' => 'available',
|
|
761
|
+
])
|
|
762
|
+
// The Driver-to-User relationship, organization membership, user type
|
|
763
|
+
// and role are all preserved for a credential-less driver.
|
|
764
|
+
->and($controller->user->assignedCompanies)->toBe(['company-uuid'])
|
|
765
|
+
->and($controller->user->assignedTypes)->toBe(['driver'])
|
|
766
|
+
->and($controller->user->assignedRoles)->toBe(['Driver']);
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
test('api driver controller creates a driver with only one contact method', function () {
|
|
770
|
+
$emailOnly = new FleetOpsApiDriverControllerProbe();
|
|
771
|
+
$emailOnly->create(new CreateDriverRequest([
|
|
772
|
+
'name' => 'Email Only',
|
|
773
|
+
'email' => 'email.only@example.test',
|
|
774
|
+
]));
|
|
775
|
+
|
|
776
|
+
$phoneOnly = new FleetOpsApiDriverControllerProbe();
|
|
777
|
+
$phoneOnly->create(new CreateDriverRequest([
|
|
778
|
+
'name' => 'Phone Only',
|
|
779
|
+
'phone' => '+15550001111',
|
|
780
|
+
]));
|
|
781
|
+
|
|
782
|
+
expect($emailOnly->createdUsers[0])->toMatchArray(['email' => 'email.only@example.test'])
|
|
783
|
+
->and($emailOnly->createdUsers[0]['phone'] ?? null)->toBeNull()
|
|
784
|
+
->and($phoneOnly->createdUsers[0])->toMatchArray(['phone' => '+15550001111'])
|
|
785
|
+
->and($phoneOnly->createdUsers[0]['email'] ?? null)->toBeNull();
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
test('api driver controller rejects a relationship that belongs to another company', function () {
|
|
789
|
+
$controller = new FleetOpsApiDriverControllerProbe();
|
|
790
|
+
$controller->unresolvable = ['vehicle_other_company'];
|
|
791
|
+
|
|
792
|
+
$created = $controller->create(new CreateDriverRequest([
|
|
793
|
+
'name' => 'Driver One',
|
|
794
|
+
'vehicle' => 'vehicle_other_company',
|
|
795
|
+
]));
|
|
796
|
+
|
|
797
|
+
$controller = new FleetOpsApiDriverControllerProbe();
|
|
798
|
+
$controller->unresolvable = ['vendor_other_company'];
|
|
799
|
+
|
|
800
|
+
$updated = $controller->update('driver_public', new UpdateDriverRequest([
|
|
801
|
+
'vendor' => 'vendor_other_company',
|
|
802
|
+
]));
|
|
803
|
+
|
|
804
|
+
expect($created)->toBe([
|
|
805
|
+
'json' => ['error' => 'No vehicle resource found for the identifier provided.'],
|
|
806
|
+
'status' => 404,
|
|
807
|
+
])->and($updated)->toBe([
|
|
808
|
+
'json' => ['error' => 'No vendor resource found for the identifier provided.'],
|
|
809
|
+
'status' => 404,
|
|
810
|
+
]);
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
test('api driver controller clears a relationship when the input is sent empty', function () {
|
|
814
|
+
$controller = new FleetOpsApiDriverControllerProbe();
|
|
815
|
+
|
|
816
|
+
$input = $controller->inputForTest(new Request(['vehicle' => null, 'vendor' => '', 'job' => null]));
|
|
817
|
+
|
|
818
|
+
expect($input)->toMatchArray([
|
|
819
|
+
'vehicle_uuid' => null,
|
|
820
|
+
'vendor_uuid' => null,
|
|
821
|
+
'current_job_uuid' => null,
|
|
822
|
+
])->and($controller->relationLookups)->toBe([]);
|
|
823
|
+
});
|
|
824
|
+
|
|
825
|
+
test('api driver controller resolves driver relationships inside the company the driver is created in', function () {
|
|
826
|
+
// A create request may name a company explicitly, and the relationships must
|
|
827
|
+
// be looked up in that company rather than in whatever the session holds.
|
|
828
|
+
$controller = new FleetOpsApiDriverControllerProbe();
|
|
829
|
+
|
|
830
|
+
$controller->create(new CreateDriverRequest([
|
|
831
|
+
'company' => 'company_public',
|
|
832
|
+
'name' => 'Driver One',
|
|
833
|
+
'vehicle' => 'vehicle_public',
|
|
834
|
+
'vendor' => 'vendor_public',
|
|
835
|
+
]));
|
|
836
|
+
|
|
837
|
+
expect($controller->relationCompanyScopes)->toBe(['company-uuid', 'company-uuid']);
|
|
838
|
+
});
|
|
839
|
+
|
|
840
|
+
test('api driver controller keeps every relationship the base contract returned', function () {
|
|
841
|
+
// The SDK stores what the API returns verbatim, and Navigator interpolates
|
|
842
|
+
// `driver.user` straight into a socket channel name — an object there would
|
|
843
|
+
// subscribe it to `user.[object Object]` and quietly stop delivering
|
|
844
|
+
// messages. These endpoints have always loaded user, vehicle, vendor and
|
|
845
|
+
// currentJob, so they must keep doing it without a `with` parameter.
|
|
846
|
+
$controller = new FleetOpsApiDriverControllerProbe();
|
|
847
|
+
|
|
848
|
+
$controller->create(new CreateDriverRequest([
|
|
849
|
+
'name' => 'Driver One',
|
|
850
|
+
'vehicle' => 'vehicle_public',
|
|
851
|
+
'vendor' => 'vendor_public',
|
|
852
|
+
'job' => 'order_public',
|
|
853
|
+
]));
|
|
854
|
+
|
|
855
|
+
expect($controller->driver->loaded)->toContain(['user', 'vehicle', 'vendor', 'currentJob']);
|
|
856
|
+
|
|
857
|
+
$updateController = new FleetOpsApiDriverControllerProbe();
|
|
858
|
+
$updateController->update('driver_public', new UpdateDriverRequest(['name' => 'Renamed']));
|
|
859
|
+
|
|
860
|
+
expect($updateController->driver->loaded)->toContain(['user', 'vehicle', 'vendor', 'currentJob'])
|
|
861
|
+
->and($updateController->findCalls)->toContain(['driver_public', ['user']]);
|
|
862
|
+
});
|
|
863
|
+
|
|
864
|
+
test('api driver controller copies timezone through to the linked user account', function () {
|
|
865
|
+
// `timezone` is documented and accepted on both create and update, but the
|
|
866
|
+
// update only ever copied name, email and phone — so the request validated,
|
|
867
|
+
// answered 200, and dropped it. The driver has no timezone column; the
|
|
868
|
+
// linked user does.
|
|
869
|
+
$create = new FleetOpsApiDriverControllerProbe();
|
|
870
|
+
$create->create(new CreateDriverRequest([
|
|
871
|
+
'name' => 'Driver One',
|
|
872
|
+
'timezone' => 'Asia/Singapore',
|
|
873
|
+
]));
|
|
874
|
+
|
|
875
|
+
$user = new FleetOpsApiDriverUserFake();
|
|
876
|
+
$user->setRawAttributes(['uuid' => 'user-uuid'], true);
|
|
877
|
+
|
|
878
|
+
$driver = new FleetOpsApiDriverFake();
|
|
879
|
+
$driver->setRawAttributes(['uuid' => 'driver-uuid', 'public_id' => 'driver_public', 'user_uuid' => 'user-uuid'], true);
|
|
880
|
+
$driver->userForTest = $user;
|
|
881
|
+
$driver->setRelation('user', $user);
|
|
882
|
+
|
|
883
|
+
$update = new FleetOpsApiDriverControllerProbe();
|
|
884
|
+
$update->driver = $driver;
|
|
885
|
+
$update->update('driver_public', new UpdateDriverRequest([
|
|
886
|
+
'name' => 'Driver One',
|
|
887
|
+
'timezone' => 'Europe/Amsterdam',
|
|
888
|
+
]));
|
|
889
|
+
|
|
890
|
+
expect($create->createdUsers[0])->toMatchArray(['timezone' => 'Asia/Singapore'])
|
|
891
|
+
->and($user->updates)->toContain([
|
|
892
|
+
'name' => 'Driver One',
|
|
893
|
+
'timezone' => 'Europe/Amsterdam',
|
|
894
|
+
]);
|
|
895
|
+
});
|
|
896
|
+
|
|
897
|
+
test('api driver controller only expands relationships the public contract allows', function () {
|
|
898
|
+
$controller = new FleetOpsApiDriverControllerProbe();
|
|
899
|
+
$request = new CreateDriverRequest(['name' => 'Driver One', 'with' => ['vehicle', 'current_job', 'user', 'company', 'nope']]);
|
|
900
|
+
|
|
901
|
+
$controller->create($request);
|
|
902
|
+
|
|
903
|
+
// `user` and `company` are published as public-id strings. Expanding either
|
|
904
|
+
// would retype a released field, so neither is expandable at all; an unknown
|
|
905
|
+
// name is dropped rather than reaching Eloquent, where it would be a 500.
|
|
906
|
+
expect($request->input('with'))->toBe(['vehicle', 'currentJob']);
|
|
907
|
+
});
|
|
@@ -43,7 +43,7 @@ class FleetOpsApiEntityControllerProbe extends EntityController
|
|
|
43
43
|
return $value === 'contacts' ? 'contact' : null;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
protected function findPayloadByPublicId(string $publicId): ?Payload
|
|
46
|
+
protected function findPayloadByPublicId(?string $publicId): ?Payload
|
|
47
47
|
{
|
|
48
48
|
$this->payload?->setAttribute('lookup_id', $publicId);
|
|
49
49
|
|
|
@@ -26,7 +26,7 @@ class FleetOpsApiEquipmentControllerProbe extends EquipmentController
|
|
|
26
26
|
return $equipment;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
protected function resolveModel(string $modelClass, string $id): Illuminate\Database\Eloquent\Model
|
|
29
|
+
protected function resolveModel(string $modelClass, string $id, ?string $companyUuid = null): Illuminate\Database\Eloquent\Model
|
|
30
30
|
{
|
|
31
31
|
if ($this->equipmentNotFound) {
|
|
32
32
|
throw new ModelNotFoundException();
|
|
@@ -37,7 +37,7 @@ class FleetOpsApiEquipmentControllerProbe extends EquipmentController
|
|
|
37
37
|
return $this->equipment;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
protected function resolveUuid(string $modelClass, ?string $id): ?string
|
|
40
|
+
protected function resolveUuid(string $modelClass, ?string $id, ?string $companyUuid = null): ?string
|
|
41
41
|
{
|
|
42
42
|
$this->resolvedUuids[] = [$modelClass, $id];
|
|
43
43
|
|