'counter:demo', 'method' => 'increment', 'params' => ['amount' => 5], 'fragments' => ['counter-display'], 'operationId' => 'op-1', ]; $operation = BatchOperation::fromArray($data); expect($operation->componentId)->toBe('counter:demo'); expect($operation->method)->toBe('increment'); expect($operation->params)->toBe(['amount' => 5]); expect($operation->fragments)->toBe(['counter-display']); expect($operation->operationId)->toBe('op-1'); }); it('creates minimal operation', function () { $operation = new BatchOperation( componentId: 'stats:user', method: 'refresh' ); expect($operation->componentId)->toBe('stats:user'); expect($operation->method)->toBe('refresh'); expect($operation->params)->toBe([]); expect($operation->fragments)->toBeNull(); expect($operation->operationId)->toBeNull(); }); it('throws on empty component id', function () { expect(fn () => new BatchOperation('', 'method')) ->toThrow(InvalidArgumentException::class, 'Component ID cannot be empty'); }); it('throws on empty method', function () { expect(fn () => new BatchOperation('counter:demo', '')) ->toThrow(InvalidArgumentException::class, 'Method cannot be empty'); }); it('converts params to ActionParameters', function () { $operation = new BatchOperation( componentId: 'counter:demo', method: 'increment', params: ['amount' => 5, 'step' => 2] ); $actionParams = $operation->getActionParameters(); expect($actionParams)->toBeInstanceOf(ActionParameters::class); expect($actionParams->toArray())->toBe(['amount' => 5, 'step' => 2]); }); it('checks if has fragments', function () { $withFragments = new BatchOperation('counter:demo', 'increment', fragments: ['display']); expect($withFragments->hasFragments())->toBeTrue(); $withoutFragments = new BatchOperation('counter:demo', 'increment'); expect($withoutFragments->hasFragments())->toBeFalse(); $emptyFragments = new BatchOperation('counter:demo', 'increment', fragments: []); expect($emptyFragments->hasFragments())->toBeFalse(); }); it('gets fragments', function () { $operation = new BatchOperation( componentId: 'counter:demo', method: 'increment', fragments: ['counter-display', 'counter-controls'] ); expect($operation->getFragments())->toBe(['counter-display', 'counter-controls']); }); it('converts to array', function () { $operation = new BatchOperation( componentId: 'counter:demo', method: 'increment', params: ['amount' => 5], fragments: ['display'], operationId: 'op-1' ); $array = $operation->toArray(); expect($array)->toBe([ 'componentId' => 'counter:demo', 'method' => 'increment', 'params' => ['amount' => 5], 'fragments' => ['display'], 'operationId' => 'op-1', ]); }); });