createDepartment([ 'name' => 'Scanner Department ' . uniqid('', false), ]); $session = api_fixtures()->createUserSession([ 'add_department_lane', 'add_number_plate_scanner', 'edit_number_plate_scanner', ]); $laneName = 'Lane ' . uniqid('', false); $laneResponse = api_client()->post('/department/lanes', [ 'department' => $department['id'], 'name' => $laneName, ], $session['headers']); $laneResponse ->assertStatus(200) ->assertEnvelope() ->assertSuccess(); $lane = api_test_runtime()->queryOne( "SELECT id FROM department_lanes WHERE department = " . (int)$department['id'] . " AND name = '" . api_test_runtime()->db()->real_escape_string($laneName) . "'" . ' ORDER BY id DESC LIMIT 1' ); expect($lane)->not->toBeNull(); $laneId = (int)($lane['id'] ?? 0); expect($laneId)->toBeGreaterThan(0); api_fixtures()->cleanupDeleteById('department_lanes', $laneId); $scannerName = 'Scanner ' . uniqid('', false); $createResponse = api_client()->post('/numberplatescanners', [ 'department_id' => $department['id'], 'name' => $scannerName, 'notes' => 'Original notes', ], $session['headers']); $createResponse ->assertStatus(200) ->assertEnvelope() ->assertSuccess() ->assertMessage('Number plate scanner added'); $createdScanner = api_test_runtime()->queryOne( "SELECT id FROM plate_scanners WHERE department_id = " . (int)$department['id'] . " AND name = '" . api_test_runtime()->db()->real_escape_string($scannerName) . "'" . ' ORDER BY id DESC LIMIT 1' ); expect($createdScanner)->not->toBeNull(); $scannerId = (int)($createdScanner['id'] ?? 0); expect($scannerId)->toBeGreaterThan(0); api_fixtures()->cleanupDeleteById('plate_scanners', $scannerId); $redis = api_test_runtime()->redis(); expect($redis)->not->toBeNull(); $cacheKeys = [ "obj_prop:plate_scanners:{$scannerId}:lane_id" => '___NULL___', "obj_prop:plate_scanners:{$scannerId}:name" => $scannerName, "obj_prop:plate_scanners:{$scannerId}:notes" => 'Original notes', ]; foreach ($cacheKeys as $cacheKey => $value) { $redis->set($cacheKey, $value); } $updateResponse = api_client()->put('/numberplatescanners', [ 'id' => $scannerId, 'department_id' => $department['id'], 'lane_id' => $laneId, 'name' => 'Updated scanner', 'notes' => 'Updated notes', ], $session['headers']); $updateResponse ->assertStatus(200) ->assertEnvelope() ->assertSuccess() ->assertMessage('Number plate scanner edited'); $redis->del(array_keys($cacheKeys)); $updatedScanner = $updateResponse->data()['scanner'] ?? null; expect($updatedScanner)->toBeArray(); expect($updatedScanner['id'] ?? null)->toBe($scannerId); expect($updatedScanner['department_id'] ?? null)->toBe($department['id']); expect($updatedScanner['lane_id'] ?? null)->toBe($laneId); expect($updatedScanner['name'] ?? null)->toBe('Updated scanner'); expect($updatedScanner['notes'] ?? null)->toBe('Updated notes'); $row = api_fixtures()->fetchRowById('plate_scanners', $scannerId); expect($row)->not->toBeNull(); expect((int)($row['lane_id'] ?? 0))->toBe($laneId); expect($row['name'] ?? null)->toBe('Updated scanner'); expect($row['notes'] ?? null)->toBe('Updated notes'); }); it('rejects plate scanner edits when the permission is missing', function (): void { api_test_covers('PUT /numberplatescanners', 'auth'); $session = api_fixtures()->createUserSession([]); $response = api_client()->put('/numberplatescanners', [ 'id' => 1, 'department_id' => 1, 'name' => 'No permission', 'notes' => 'Should fail', ], $session['headers']); $response ->assertStatus(403) ->assertEnvelope() ->assertSuccess(false) ->assertMissingPermissions(['edit_number_plate_scanner']); });