172 lines
6.0 KiB
PHP
172 lines
6.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
usesApiSuite();
|
|
|
|
it('serves whole-department expected relay states and records successful physical completion only', function (): void {
|
|
$scenario = api_fixtures()->createSelfServeScenario([
|
|
'department' => [
|
|
'name' => 'Edge Expected State Department',
|
|
],
|
|
'relay_ids' => [
|
|
'entry' => 'expected-entry',
|
|
'exit' => 'expected-exit',
|
|
'machine' => 'expected-machine',
|
|
'program_picker' => 'expected-program',
|
|
'cleaner' => 'expected-cleaner',
|
|
],
|
|
]);
|
|
$departmentId = (int)$scenario['department']['id'];
|
|
$laneId = (int)$scenario['lane']['id'];
|
|
api_fixtures()->setDepartmentShellyTransportMode($departmentId, 'gateway');
|
|
$session = api_fixtures()->createEdgeOperatorSession($departmentId, [
|
|
'modules_selfserve_lane_relay_machine_status_set',
|
|
'modules_selfserve_lane_relay_machine_cleaner_status_set',
|
|
]);
|
|
$gateway = api_fixtures()->createClaimedEdgeGateway([
|
|
'department_id' => $departmentId,
|
|
'label' => 'Expected State Gateway',
|
|
]);
|
|
|
|
$relayIps = [
|
|
'expected-entry' => '10.41.0.11',
|
|
'expected-exit' => '10.41.0.12',
|
|
'expected-machine' => '10.41.0.13',
|
|
'expected-program' => '10.41.0.14',
|
|
'expected-cleaner' => '10.41.0.15',
|
|
];
|
|
foreach ($relayIps as $relayId => $ip) {
|
|
api_fixtures()->createEdgeRelayBinding([
|
|
'gateway_id' => (int)$gateway['id'],
|
|
'department_id' => $departmentId,
|
|
'relay_id' => $relayId,
|
|
'device_id' => 'device-' . $relayId,
|
|
'local_ip' => $ip,
|
|
'metadata' => [
|
|
'device_type' => 'SHELLY_SWITCH',
|
|
],
|
|
]);
|
|
}
|
|
|
|
$queueResponse = api_client()->post('/modules/self-serve/lane/hardware/batch/set', [
|
|
'lane_id' => $laneId,
|
|
'transport' => 'gateway',
|
|
'commands' => [
|
|
['target' => 'MACHINE', 'on' => true],
|
|
['target' => 'CLEANER', 'on' => false],
|
|
],
|
|
], $session['headers']);
|
|
|
|
$queueResponse
|
|
->assertStatus(202)
|
|
->assertEnvelope()
|
|
->assertSuccess();
|
|
|
|
$expectedResponse = api_client()->post('/edge-agent/gateways/' . (int)$gateway['id'] . '/expected-relay-states', [
|
|
'agent_token' => (string)$gateway['agent_token'],
|
|
'wait_seconds' => 0,
|
|
]);
|
|
|
|
$expectedResponse
|
|
->assertStatus(200)
|
|
->assertEnvelope()
|
|
->assertSuccess();
|
|
|
|
$lanes = $expectedResponse->data()['lanes'] ?? [];
|
|
expect($lanes)->toHaveKey((string)$laneId);
|
|
$laneStates = $lanes[(string)$laneId];
|
|
|
|
expect(array_keys($laneStates))->toBe([
|
|
'ENTRANCE_GATE',
|
|
'EXIT_GATE',
|
|
'MACHINE',
|
|
'PROGRAM_PICKER',
|
|
'CLEANER',
|
|
])
|
|
->and($laneStates['MACHINE']['device'])->toBe([
|
|
'ip' => '10.41.0.13',
|
|
'id' => 'device-expected-machine',
|
|
'type' => 'SHELLY_SWITCH',
|
|
])
|
|
->and($laneStates['MACHINE']['state'])->toBeTrue()
|
|
->and($laneStates['MACHINE']['completed'])->toBeNull()
|
|
->and($laneStates['CLEANER']['state'])->toBeFalse()
|
|
->and($laneStates['CLEANER']['completed'])->toBeNull()
|
|
->and($laneStates['ENTRANCE_GATE']['completed'])->not->toBeNull();
|
|
expect($expectedResponse->data())->toHaveKey('CLEANER')
|
|
->and($expectedResponse->data()['MACHINE']['device'] ?? null)->toBe($laneStates['MACHINE']['device'])
|
|
->and($expectedResponse->data()['CLEANER']['completed'])->toBeNull();
|
|
|
|
$machineUpdated = (string)$laneStates['MACHINE']['updated'];
|
|
$cleanerUpdated = (string)$laneStates['CLEANER']['updated'];
|
|
|
|
$resultResponse = api_client()->post('/edge-agent/gateways/' . (int)$gateway['id'] . '/relay-state-results', [
|
|
'agent_token' => (string)$gateway['agent_token'],
|
|
'results' => [
|
|
[
|
|
'lane_id' => $laneId,
|
|
'role' => 'MACHINE',
|
|
'state' => true,
|
|
'updated' => $machineUpdated,
|
|
'ok' => true,
|
|
'completed' => '2026-07-01T09:10:00+00:00',
|
|
],
|
|
[
|
|
'lane_id' => $laneId,
|
|
'role' => 'CLEANER',
|
|
'state' => false,
|
|
'updated' => $cleanerUpdated,
|
|
'ok' => false,
|
|
'skipped' => true,
|
|
'error' => 'Relay offline',
|
|
],
|
|
],
|
|
]);
|
|
|
|
$resultResponse
|
|
->assertStatus(200)
|
|
->assertEnvelope()
|
|
->assertSuccess();
|
|
|
|
expect($resultResponse->data()['summary'] ?? [])
|
|
->toHaveKey('completed', 1)
|
|
->toHaveKey('skipped', 1)
|
|
->toHaveKey('failed', 0);
|
|
|
|
$afterResult = api_client()->post('/edge-agent/gateways/' . (int)$gateway['id'] . '/expected-relay-states', [
|
|
'agent_token' => (string)$gateway['agent_token'],
|
|
'wait_seconds' => 0,
|
|
]);
|
|
|
|
$afterResult
|
|
->assertStatus(200)
|
|
->assertEnvelope()
|
|
->assertSuccess();
|
|
|
|
$afterLaneStates = $afterResult->data()['lanes'][(string)$laneId] ?? [];
|
|
expect($afterLaneStates['MACHINE']['completed'] ?? null)->not->toBeNull()
|
|
->and($afterLaneStates['CLEANER']['completed'] ?? null)->toBeNull()
|
|
->and($afterLaneStates['CLEANER']['last_error'] ?? null)->toBe('Relay offline');
|
|
|
|
$staleResponse = api_client()->post('/edge-agent/gateways/' . (int)$gateway['id'] . '/relay-state-results', [
|
|
'agent_token' => (string)$gateway['agent_token'],
|
|
'results' => [[
|
|
'lane_id' => $laneId,
|
|
'role' => 'CLEANER',
|
|
'state' => false,
|
|
'updated' => '2000-01-01 00:00:00',
|
|
'ok' => true,
|
|
'completed' => '2026-07-01T09:11:00+00:00',
|
|
]],
|
|
]);
|
|
|
|
$staleResponse
|
|
->assertStatus(200)
|
|
->assertEnvelope()
|
|
->assertSuccess();
|
|
|
|
expect($staleResponse->data()['summary']['stale'] ?? null)->toBe(1)
|
|
->and($staleResponse->data()['rejected'][0]['reason'] ?? null)->toBe('STALE_STATE');
|
|
});
|