Maintain local ⭤ remote in sync with automatic AT Protocol parity for Laravel (alpha & unstable)
at dev 118 lines 3.8 kB view raw
1<?php 2 3namespace SocialDept\AtpParity\Tests\Unit\Sync; 4 5use Carbon\Carbon; 6use SocialDept\AtpParity\Sync\ConflictDetector; 7use SocialDept\AtpParity\Tests\Fixtures\SyncableModel; 8use SocialDept\AtpParity\Tests\Fixtures\TestModel; 9use SocialDept\AtpParity\Tests\Fixtures\TestRecord; 10use SocialDept\AtpParity\Tests\TestCase; 11 12class ConflictDetectorTest extends TestCase 13{ 14 private ConflictDetector $detector; 15 16 protected function setUp(): void 17 { 18 parent::setUp(); 19 $this->detector = new ConflictDetector(); 20 } 21 22 public function test_no_conflict_when_cid_matches(): void 23 { 24 $model = new TestModel([ 25 'atp_cid' => 'samecid123', 26 'atp_synced_at' => Carbon::parse('2024-01-15 12:00:00'), 27 'updated_at' => Carbon::parse('2024-01-15 13:00:00'), // local changes 28 ]); 29 $record = new TestRecord(text: 'Remote content'); 30 31 $hasConflict = $this->detector->hasConflict($model, $record, 'samecid123'); 32 33 $this->assertFalse($hasConflict); 34 } 35 36 public function test_no_conflict_when_no_local_changes(): void 37 { 38 $model = new TestModel([ 39 'atp_cid' => 'oldcid', 40 'atp_synced_at' => Carbon::parse('2024-01-15 13:00:00'), 41 'updated_at' => Carbon::parse('2024-01-15 12:00:00'), // updated before sync 42 ]); 43 $record = new TestRecord(text: 'Remote content'); 44 45 $hasConflict = $this->detector->hasConflict($model, $record, 'newcid'); 46 47 $this->assertFalse($hasConflict); 48 } 49 50 public function test_conflict_when_cid_differs_and_local_changes(): void 51 { 52 $model = new TestModel([ 53 'atp_cid' => 'oldcid', 54 'atp_synced_at' => Carbon::parse('2024-01-15 12:00:00'), 55 'updated_at' => Carbon::parse('2024-01-15 13:00:00'), // local changes 56 ]); 57 $record = new TestRecord(text: 'Remote content'); 58 59 $hasConflict = $this->detector->hasConflict($model, $record, 'newcid'); 60 61 $this->assertTrue($hasConflict); 62 } 63 64 public function test_conflict_when_never_synced(): void 65 { 66 $model = new TestModel([ 67 'atp_cid' => 'cid', 68 // No atp_synced_at means never synced, which implies local changes 69 ]); 70 $record = new TestRecord(text: 'Remote'); 71 72 $hasConflict = $this->detector->hasConflict($model, $record, 'differentcid'); 73 74 $this->assertTrue($hasConflict); 75 } 76 77 public function test_uses_syncs_with_atp_trait_method(): void 78 { 79 $model = new SyncableModel([ 80 'atp_cid' => 'oldcid', 81 'atp_synced_at' => Carbon::parse('2024-01-15 12:00:00'), 82 'updated_at' => Carbon::parse('2024-01-15 13:00:00'), 83 ]); 84 $record = new TestRecord(text: 'Remote'); 85 86 $hasConflict = $this->detector->hasConflict($model, $record, 'newcid'); 87 88 $this->assertTrue($hasConflict); 89 } 90 91 public function test_no_conflict_when_synced_after_update_with_trait(): void 92 { 93 $model = new SyncableModel([ 94 'atp_cid' => 'oldcid', 95 'updated_at' => Carbon::parse('2024-01-15 12:00:00'), 96 'atp_synced_at' => Carbon::parse('2024-01-15 13:00:00'), 97 ]); 98 $record = new TestRecord(text: 'Remote'); 99 100 $hasConflict = $this->detector->hasConflict($model, $record, 'newcid'); 101 102 $this->assertFalse($hasConflict); 103 } 104 105 public function test_no_conflict_without_updated_at(): void 106 { 107 $model = new TestModel([ 108 'atp_cid' => 'cid', 109 'atp_synced_at' => Carbon::now(), 110 // No updated_at 111 ]); 112 $record = new TestRecord(text: 'Remote'); 113 114 $hasConflict = $this->detector->hasConflict($model, $record, 'newcid'); 115 116 $this->assertFalse($hasConflict); 117 } 118}