'John', 'email' => 'john@test.com']), DocumentMetadata::withTimestamps() ); expect($document->id->toString())->toBe('user_123'); expect($document->entityType->toString())->toBe('user'); expect($document->data->get('name'))->toBe('John'); expect($document->hasMetadata())->toBeTrue(); }); it('can be created with minimal data', function () { $document = new SearchDocument( EntityId::fromString('product_456'), EntityType::product(), DocumentData::fromArray(['title' => 'Test Product']) ); expect($document->id->toString())->toBe('product_456'); expect($document->hasMetadata())->toBeFalse(); }); it('supports immutable metadata updates', function () { $document = new SearchDocument( EntityId::fromString('test_1'), EntityType::fromString('test'), DocumentData::empty() ); $updated = $document->withMetadata('version', '1.0'); expect($document->hasMetadata())->toBeFalse(); // Original unchanged expect($updated->hasMetadata())->toBeTrue(); expect($updated->metadata->get('version'))->toBe('1.0'); }); it('supports immutable data updates', function () { $document = new SearchDocument( EntityId::fromString('test_1'), EntityType::fromString('test'), DocumentData::fromArray(['title' => 'Original']) ); $updated = $document->withDocumentData( DocumentData::fromArray(['title' => 'Updated', 'content' => 'New content']) ); expect($document->data->get('title'))->toBe('Original'); // Original unchanged expect($updated->data->get('title'))->toBe('Updated'); expect($updated->data->get('content'))->toBe('New content'); }); it('supports field-level updates', function () { $document = new SearchDocument( EntityId::fromString('test_1'), EntityType::fromString('test'), DocumentData::fromArray(['title' => 'Original', 'status' => 'draft']) ); $updated = $document->withField('status', 'published'); expect($document->data->get('status'))->toBe('draft'); // Original unchanged expect($updated->data->get('status'))->toBe('published'); expect($updated->data->get('title'))->toBe('Original'); // Other fields preserved }); it('supports field removal', function () { $document = new SearchDocument( EntityId::fromString('test_1'), EntityType::fromString('test'), DocumentData::fromArray(['title' => 'Test', 'temp' => 'remove me']) ); $updated = $document->withoutField('temp'); expect($document->data->has('temp'))->toBeTrue(); // Original unchanged expect($updated->data->has('temp'))->toBeFalse(); expect($updated->data->has('title'))->toBeTrue(); // Other fields preserved }); it('converts to array correctly', function () { $document = new SearchDocument( EntityId::fromString('user_123'), EntityType::user(), DocumentData::fromArray(['name' => 'John']), DocumentMetadata::fromArray(['version' => '1.0']) ); $array = $document->toArray(); expect($array)->toBe([ 'id' => 'user_123', 'entity_type' => 'user', 'data' => ['name' => 'John'], 'metadata' => ['version' => '1.0'], ]); }); it('converts to index array with special fields', function () { $document = new SearchDocument( EntityId::fromString('product_456'), EntityType::product(), DocumentData::fromArray(['title' => 'Test Product', 'price' => 99.99]), DocumentMetadata::fromArray(['version' => '2.0', 'language' => 'en']) ); $indexArray = $document->toIndexArray(); expect($indexArray)->toBe([ 'title' => 'Test Product', 'price' => 99.99, '_id' => 'product_456', '_type' => 'product', '_meta_version' => '2.0', '_meta_language' => 'en', ]); }); it('handles empty metadata correctly', function () { $document = new SearchDocument( EntityId::fromString('test_1'), EntityType::fromString('test'), DocumentData::fromArray(['title' => 'Test']) ); expect($document->hasMetadata())->toBeFalse(); $indexArray = $document->toIndexArray(); expect($indexArray)->toBe([ 'title' => 'Test', '_id' => 'test_1', '_type' => 'test', ]); }); });