Maintain local ⭤ remote in sync with automatic AT Protocol parity for Laravel (alpha & unstable)
1<?php
2
3namespace SocialDept\AtpParity\Tests\Unit;
4
5use SocialDept\AtpParity\Tests\Fixtures\TestMapper;
6use SocialDept\AtpParity\Tests\Fixtures\TestModel;
7use SocialDept\AtpParity\Tests\Fixtures\TestRecord;
8use SocialDept\AtpParity\Tests\TestCase;
9
10class RecordMapperTest extends TestCase
11{
12 private TestMapper $mapper;
13
14 protected function setUp(): void
15 {
16 parent::setUp();
17 $this->mapper = new TestMapper();
18 }
19
20 public function test_record_class_returns_correct_class(): void
21 {
22 $this->assertSame(TestRecord::class, $this->mapper->recordClass());
23 }
24
25 public function test_model_class_returns_correct_class(): void
26 {
27 $this->assertSame(TestModel::class, $this->mapper->modelClass());
28 }
29
30 public function test_lexicon_returns_record_lexicon(): void
31 {
32 $this->assertSame('app.test.record', $this->mapper->lexicon());
33 }
34
35 public function test_to_model_creates_model_with_attributes(): void
36 {
37 $record = new TestRecord(text: 'Hello world');
38
39 $model = $this->mapper->toModel($record);
40
41 $this->assertInstanceOf(TestModel::class, $model);
42 $this->assertSame('Hello world', $model->content);
43 $this->assertFalse($model->exists);
44 }
45
46 public function test_to_model_applies_meta(): void
47 {
48 $record = new TestRecord(text: 'Test');
49 $meta = [
50 'uri' => 'at://did:plc:test/app.test.record/abc123',
51 'cid' => 'bafyreiabc',
52 ];
53
54 $model = $this->mapper->toModel($record, $meta);
55
56 $this->assertSame('at://did:plc:test/app.test.record/abc123', $model->atp_uri);
57 $this->assertSame('bafyreiabc', $model->atp_cid);
58 }
59
60 public function test_to_record_converts_model_to_record(): void
61 {
62 $model = new TestModel(['content' => 'Test content']);
63
64 $record = $this->mapper->toRecord($model);
65
66 $this->assertInstanceOf(TestRecord::class, $record);
67 $this->assertSame('Test content', $record->text);
68 }
69
70 public function test_update_model_fills_model_without_saving(): void
71 {
72 $model = new TestModel(['content' => 'Original']);
73 $model->save();
74 $originalUpdatedAt = $model->updated_at;
75
76 $record = new TestRecord(text: 'Updated');
77
78 $result = $this->mapper->updateModel($model, $record);
79
80 $this->assertSame($model, $result);
81 $this->assertSame('Updated', $model->content);
82 // Model is filled but not saved
83 $this->assertTrue($model->isDirty('content'));
84 }
85
86 public function test_update_model_applies_meta(): void
87 {
88 $model = new TestModel(['content' => 'Original']);
89 $record = new TestRecord(text: 'Updated');
90 $meta = ['uri' => 'at://test/col/rkey', 'cid' => 'cid123'];
91
92 $this->mapper->updateModel($model, $record, $meta);
93
94 $this->assertSame('at://test/col/rkey', $model->atp_uri);
95 $this->assertSame('cid123', $model->atp_cid);
96 }
97
98 public function test_find_by_uri_returns_model_when_exists(): void
99 {
100 $model = TestModel::create([
101 'content' => 'Test',
102 'atp_uri' => 'at://did:plc:test/app.test.record/abc',
103 ]);
104
105 $found = $this->mapper->findByUri('at://did:plc:test/app.test.record/abc');
106
107 $this->assertNotNull($found);
108 $this->assertSame($model->id, $found->id);
109 }
110
111 public function test_find_by_uri_returns_null_when_not_exists(): void
112 {
113 $found = $this->mapper->findByUri('at://nonexistent/col/rkey');
114
115 $this->assertNull($found);
116 }
117
118 public function test_upsert_creates_new_model_when_uri_not_found(): void
119 {
120 $record = new TestRecord(text: 'New record');
121 $meta = [
122 'uri' => 'at://did:plc:test/app.test.record/new123',
123 'cid' => 'bafyrei123',
124 ];
125
126 $model = $this->mapper->upsert($record, $meta);
127
128 $this->assertTrue($model->exists);
129 $this->assertSame('New record', $model->content);
130 $this->assertSame('at://did:plc:test/app.test.record/new123', $model->atp_uri);
131 }
132
133 public function test_upsert_updates_existing_model_when_uri_found(): void
134 {
135 $existing = TestModel::create([
136 'content' => 'Original',
137 'atp_uri' => 'at://did:plc:test/app.test.record/exists',
138 'atp_cid' => 'old_cid',
139 ]);
140
141 $record = new TestRecord(text: 'Updated content');
142 $meta = [
143 'uri' => 'at://did:plc:test/app.test.record/exists',
144 'cid' => 'new_cid',
145 ];
146
147 $model = $this->mapper->upsert($record, $meta);
148
149 $this->assertSame($existing->id, $model->id);
150 $this->assertSame('Updated content', $model->content);
151 $this->assertSame('new_cid', $model->atp_cid);
152 }
153
154 public function test_upsert_without_uri_creates_new_model(): void
155 {
156 $record = new TestRecord(text: 'No URI');
157
158 $model = $this->mapper->upsert($record, []);
159
160 $this->assertTrue($model->exists);
161 $this->assertSame('No URI', $model->content);
162 $this->assertNull($model->atp_uri);
163 }
164
165 public function test_delete_by_uri_deletes_model_when_exists(): void
166 {
167 TestModel::create([
168 'content' => 'To delete',
169 'atp_uri' => 'at://did:plc:test/app.test.record/todelete',
170 ]);
171
172 $result = $this->mapper->deleteByUri('at://did:plc:test/app.test.record/todelete');
173
174 $this->assertTrue($result);
175 $this->assertNull($this->mapper->findByUri('at://did:plc:test/app.test.record/todelete'));
176 }
177
178 public function test_delete_by_uri_returns_false_when_not_exists(): void
179 {
180 $result = $this->mapper->deleteByUri('at://nonexistent/col/rkey');
181
182 $this->assertFalse($result);
183 }
184}