'abc123', 'csrf' => 'xyz789', 'refreshed_at' => '2026-05-11T10:00:00Z', ]), ); $factoryMock = Mockery::mock(ProcessFactory::class); /** @var ProcessFactory $factoryMock */ $factoryMock->shouldReceive('create')->andReturn($stubHandle); $bridge = new PlaywrightBridge($factoryMock); $result = $bridge->refreshSession( login: 'test_login', password: 'test_password', url: 'https://crm.bp-gr.ru' ); // Credentials must come through stdin, not argv (avoid leak in ps output) $capturedInput = json_decode($stubHandle->capturedInput, true); expect($capturedInput)->toBeArray() ->and($capturedInput['login'])->toBe('test_login') ->and($capturedInput['password'])->toBe('test_password') ->and($capturedInput['url'])->toBe('https://crm.bp-gr.ru'); expect($stubHandle->capturedTimeout)->toBe(75); expect($result)->toHaveKeys(['phpsessid', 'csrf', 'refreshed_at']) ->and($result['phpsessid'])->toBe('abc123') ->and($result['csrf'])->toBe('xyz789'); }); test('PlaywrightBridge throws SupplierAuthException on non-zero exit', function () { $stubHandle = new StubPlaywrightProcessHandle( successful: false, errorOutput: '{"error":"login rejected"}', exitCode: 1, ); $factoryMock = Mockery::mock(ProcessFactory::class); $factoryMock->shouldReceive('create')->andReturn($stubHandle); $bridge = new PlaywrightBridge($factoryMock); expect(fn () => $bridge->refreshSession('bad', 'bad', 'https://crm.bp-gr.ru')) ->toThrow(SupplierAuthException::class); }); test('PlaywrightBridge throws SupplierAuthException on invalid stdout JSON', function () { $stubHandle = new StubPlaywrightProcessHandle( successful: true, output: 'not valid json{', ); $factoryMock = Mockery::mock(ProcessFactory::class); $factoryMock->shouldReceive('create')->andReturn($stubHandle); $bridge = new PlaywrightBridge($factoryMock); expect(fn () => $bridge->refreshSession('a', 'b', 'https://crm.bp-gr.ru')) ->toThrow(SupplierAuthException::class); }); test('PlaywrightBridge throws SupplierAuthException on missing keys in stdout', function () { $stubHandle = new StubPlaywrightProcessHandle( successful: true, output: json_encode(['phpsessid' => 'a']), // no csrf ); $factoryMock = Mockery::mock(ProcessFactory::class); $factoryMock->shouldReceive('create')->andReturn($stubHandle); $bridge = new PlaywrightBridge($factoryMock); expect(fn () => $bridge->refreshSession('a', 'b', 'https://crm.bp-gr.ru')) ->toThrow(SupplierAuthException::class); });