Maintain local ⭤ remote in sync with automatic AT Protocol parity for Laravel (alpha & unstable)
at dev 169 lines 5.5 kB view raw
1<?php 2 3namespace SocialDept\AtpParity\Tests\Unit\Import; 4 5use Illuminate\Support\Facades\Event; 6use Mockery; 7use SocialDept\AtpParity\Events\ImportCompleted; 8use SocialDept\AtpParity\Events\ImportFailed; 9use SocialDept\AtpParity\Events\ImportProgress; 10use SocialDept\AtpParity\Events\ImportStarted; 11use SocialDept\AtpParity\Import\ImportService; 12use SocialDept\AtpParity\Import\ImportState; 13use SocialDept\AtpParity\MapperRegistry; 14use SocialDept\AtpParity\Tests\Fixtures\TestMapper; 15use SocialDept\AtpParity\Tests\Fixtures\TestModel; 16use SocialDept\AtpParity\Tests\TestCase; 17use SocialDept\AtpResolver\Facades\Resolver; 18 19class ImportServiceTest extends TestCase 20{ 21 private ImportService $service; 22 23 private MapperRegistry $registry; 24 25 protected function setUp(): void 26 { 27 parent::setUp(); 28 29 $this->registry = new MapperRegistry(); 30 $this->registry->register(new TestMapper()); 31 32 $this->service = new ImportService($this->registry); 33 34 Event::fake(); 35 } 36 37 public function test_import_user_collection_returns_failed_when_no_mapper(): void 38 { 39 $this->app->forgetInstance(MapperRegistry::class); 40 $emptyRegistry = new MapperRegistry(); 41 $service = new ImportService($emptyRegistry); 42 43 $result = $service->importUserCollection('did:plc:test', 'unknown.collection'); 44 45 $this->assertTrue($result->isFailed()); 46 $this->assertStringContainsString('No mapper registered', $result->error); 47 } 48 49 public function test_import_user_collection_fails_when_pds_not_resolved(): void 50 { 51 Resolver::shouldReceive('resolvePds') 52 ->with('did:plc:test') 53 ->andReturnNull(); 54 55 $result = $this->service->importUserCollection('did:plc:test', 'app.test.record'); 56 57 $this->assertTrue($result->isFailed()); 58 $this->assertStringContainsString('Could not resolve PDS', $result->error); 59 Event::assertDispatched(ImportFailed::class); 60 } 61 62 /** 63 * @group integration 64 */ 65 public function test_import_user_collection_imports_records(): void 66 { 67 $this->markTestSkipped('Requires integration test with real or mock ATP client - AtpClient has typed properties that prevent mocking'); 68 } 69 70 /** 71 * @group integration 72 */ 73 public function test_import_dispatches_events(): void 74 { 75 $this->markTestSkipped('Requires integration test with real or mock ATP client - AtpClient has typed properties that prevent mocking'); 76 } 77 78 /** 79 * @group integration 80 */ 81 public function test_import_calls_progress_callback(): void 82 { 83 $this->markTestSkipped('Requires integration test with real or mock ATP client - AtpClient has typed properties that prevent mocking'); 84 } 85 86 /** 87 * @group integration 88 */ 89 public function test_import_user_imports_multiple_collections(): void 90 { 91 $this->markTestSkipped('Requires integration test with real or mock ATP client - AtpClient has typed properties that prevent mocking'); 92 } 93 94 public function test_get_status_returns_import_state(): void 95 { 96 ImportState::create([ 97 'did' => 'did:plc:test', 98 'collection' => 'app.test.record', 99 'status' => 'completed', 100 'records_synced' => 50, 101 ]); 102 103 $state = $this->service->getStatus('did:plc:test', 'app.test.record'); 104 105 $this->assertNotNull($state); 106 $this->assertSame('completed', $state->status); 107 $this->assertSame(50, $state->records_synced); 108 } 109 110 public function test_get_status_returns_null_when_not_found(): void 111 { 112 $state = $this->service->getStatus('did:plc:unknown', 'unknown'); 113 114 $this->assertNull($state); 115 } 116 117 public function test_is_imported_returns_true_when_completed(): void 118 { 119 ImportState::create([ 120 'did' => 'did:plc:test', 121 'collection' => 'app.test.record', 122 'status' => 'completed', 123 ]); 124 125 $this->assertTrue($this->service->isImported('did:plc:test', 'app.test.record')); 126 } 127 128 public function test_is_imported_returns_false_when_not_started(): void 129 { 130 $this->assertFalse($this->service->isImported('did:plc:test', 'app.test.record')); 131 } 132 133 public function test_reset_deletes_import_state(): void 134 { 135 ImportState::create([ 136 'did' => 'did:plc:test', 137 'collection' => 'app.test.record', 138 'status' => 'completed', 139 ]); 140 141 $this->service->reset('did:plc:test', 'app.test.record'); 142 143 $this->assertNull($this->service->getStatus('did:plc:test', 'app.test.record')); 144 } 145 146 public function test_import_skips_already_completed(): void 147 { 148 ImportState::create([ 149 'did' => 'did:plc:test', 150 'collection' => 'app.test.record', 151 'status' => 'completed', 152 'records_synced' => 100, 153 ]); 154 155 // No mocking needed - should return cached result 156 $result = $this->service->importUserCollection('did:plc:test', 'app.test.record'); 157 158 $this->assertTrue($result->completed); 159 $this->assertSame(100, $result->recordsSynced); 160 } 161 162 /** 163 * @group integration 164 */ 165 public function test_import_handles_record_failures_gracefully(): void 166 { 167 $this->markTestSkipped('Requires integration test with real or mock ATP client - AtpClient has typed properties that prevent mocking'); 168 } 169}