Parse and validate AT Protocol Lexicons with DTO generation for Laravel
at dev 291 lines 8.8 kB view raw
1<?php 2 3namespace SocialDept\AtpSchema\Tests\Unit\Generator; 4 5use Orchestra\Testbench\TestCase; 6use SocialDept\AtpSchema\Generator\ModelMapper; 7 8class ModelMapperTest extends TestCase 9{ 10 protected ModelMapper $mapper; 11 12 protected function setUp(): void 13 { 14 parent::setUp(); 15 16 $this->mapper = new ModelMapper(); 17 } 18 19 public function test_it_generates_to_model_body_for_simple_properties(): void 20 { 21 $body = $this->mapper->generateToModelBody([ 22 'name' => ['type' => 'string'], 23 'age' => ['type' => 'integer'], 24 ], 'User'); 25 26 $this->assertStringContainsString('return new User([', $body); 27 $this->assertStringContainsString("'name' => \$this->name,", $body); 28 $this->assertStringContainsString("'age' => \$this->age,", $body); 29 } 30 31 public function test_it_generates_from_model_body_for_simple_properties(): void 32 { 33 $body = $this->mapper->generateFromModelBody([ 34 'name' => ['type' => 'string'], 35 'age' => ['type' => 'integer'], 36 ]); 37 38 $this->assertStringContainsString('return new static(', $body); 39 $this->assertStringContainsString('name: $model->name ?? null,', $body); 40 $this->assertStringContainsString('age: $model->age ?? null', $body); 41 } 42 43 public function test_it_handles_datetime_in_to_model(): void 44 { 45 $body = $this->mapper->generateToModelBody([ 46 'createdAt' => [ 47 'type' => 'string', 48 'format' => 'datetime', 49 ], 50 ]); 51 52 $this->assertStringContainsString("\$this->createdAt?->format('Y-m-d H:i:s')", $body); 53 } 54 55 public function test_it_handles_datetime_in_from_model(): void 56 { 57 $body = $this->mapper->generateFromModelBody([ 58 'createdAt' => [ 59 'type' => 'string', 60 'format' => 'datetime', 61 ], 62 ]); 63 64 $this->assertStringContainsString('$model->createdAt ? new \\DateTime($model->createdAt) : null', $body); 65 } 66 67 public function test_it_handles_blob_in_to_model(): void 68 { 69 $body = $this->mapper->generateToModelBody([ 70 'image' => ['type' => 'blob'], 71 ]); 72 73 $this->assertStringContainsString('$this->image?->toArray()', $body); 74 } 75 76 public function test_it_handles_blob_in_from_model(): void 77 { 78 $body = $this->mapper->generateFromModelBody([ 79 'image' => ['type' => 'blob'], 80 ]); 81 82 $this->assertStringContainsString('\\SocialDept\\AtpSchema\\Data\\BlobReference::fromArray', $body); 83 } 84 85 public function test_it_handles_ref_in_to_model(): void 86 { 87 $body = $this->mapper->generateToModelBody([ 88 'author' => [ 89 'type' => 'ref', 90 'ref' => 'app.test.author', 91 ], 92 ]); 93 94 $this->assertStringContainsString('$this->author?->toArray()', $body); 95 } 96 97 public function test_it_handles_ref_in_from_model(): void 98 { 99 $body = $this->mapper->generateFromModelBody([ 100 'author' => [ 101 'type' => 'ref', 102 'ref' => 'app.test.author', 103 ], 104 ]); 105 106 $this->assertStringContainsString('Author::fromArray', $body); 107 } 108 109 public function test_it_handles_array_of_refs_in_to_model(): void 110 { 111 $body = $this->mapper->generateToModelBody([ 112 'posts' => [ 113 'type' => 'array', 114 'items' => [ 115 'type' => 'ref', 116 'ref' => 'app.test.post', 117 ], 118 ], 119 ]); 120 121 $this->assertStringContainsString('array_map(fn ($item) => $item->toArray()', $body); 122 } 123 124 public function test_it_handles_array_of_refs_in_from_model(): void 125 { 126 $body = $this->mapper->generateFromModelBody([ 127 'posts' => [ 128 'type' => 'array', 129 'items' => [ 130 'type' => 'ref', 131 'ref' => 'app.test.post', 132 ], 133 ], 134 ]); 135 136 $this->assertStringContainsString('array_map(fn ($item) => Post::fromArray($item)', $body); 137 } 138 139 public function test_it_handles_array_of_objects(): void 140 { 141 $body = $this->mapper->generateToModelBody([ 142 'settings' => [ 143 'type' => 'array', 144 'items' => [ 145 'type' => 'object', 146 ], 147 ], 148 ]); 149 150 $this->assertStringContainsString('$this->settings ?? []', $body); 151 } 152 153 public function test_it_generates_empty_to_model_for_no_properties(): void 154 { 155 $body = $this->mapper->generateToModelBody([], 'User'); 156 157 $this->assertStringContainsString('return new User();', $body); 158 } 159 160 public function test_it_generates_empty_from_model_for_no_properties(): void 161 { 162 $body = $this->mapper->generateFromModelBody([]); 163 164 $this->assertStringContainsString('return new static();', $body); 165 } 166 167 public function test_it_gets_field_mapping(): void 168 { 169 $mapping = $this->mapper->getFieldMapping([ 170 'userName' => ['type' => 'string'], 171 'emailAddress' => ['type' => 'string'], 172 ]); 173 174 $this->assertSame([ 175 'userName' => 'user_name', 176 'emailAddress' => 'email_address', 177 ], $mapping); 178 } 179 180 public function test_it_checks_if_datetime_needs_transformer(): void 181 { 182 $this->assertTrue($this->mapper->needsTransformer([ 183 'type' => 'string', 184 'format' => 'datetime', 185 ])); 186 } 187 188 public function test_it_checks_if_blob_needs_transformer(): void 189 { 190 $this->assertTrue($this->mapper->needsTransformer(['type' => 'blob'])); 191 } 192 193 public function test_it_checks_if_ref_needs_transformer(): void 194 { 195 $this->assertTrue($this->mapper->needsTransformer(['type' => 'ref'])); 196 } 197 198 public function test_it_checks_if_array_of_refs_needs_transformer(): void 199 { 200 $this->assertTrue($this->mapper->needsTransformer([ 201 'type' => 'array', 202 'items' => ['type' => 'ref'], 203 ])); 204 } 205 206 public function test_it_checks_if_simple_type_needs_transformer(): void 207 { 208 $this->assertFalse($this->mapper->needsTransformer(['type' => 'string'])); 209 $this->assertFalse($this->mapper->needsTransformer(['type' => 'integer'])); 210 } 211 212 public function test_it_gets_datetime_transformer_type(): void 213 { 214 $type = $this->mapper->getTransformerType([ 215 'type' => 'string', 216 'format' => 'datetime', 217 ]); 218 219 $this->assertSame('datetime', $type); 220 } 221 222 public function test_it_gets_blob_transformer_type(): void 223 { 224 $type = $this->mapper->getTransformerType(['type' => 'blob']); 225 226 $this->assertSame('blob', $type); 227 } 228 229 public function test_it_gets_ref_transformer_type(): void 230 { 231 $type = $this->mapper->getTransformerType(['type' => 'ref']); 232 233 $this->assertSame('ref', $type); 234 } 235 236 public function test_it_gets_array_ref_transformer_type(): void 237 { 238 $type = $this->mapper->getTransformerType([ 239 'type' => 'array', 240 'items' => ['type' => 'ref'], 241 ]); 242 243 $this->assertSame('array_ref', $type); 244 } 245 246 public function test_it_gets_array_object_transformer_type(): void 247 { 248 $type = $this->mapper->getTransformerType([ 249 'type' => 'array', 250 'items' => ['type' => 'object'], 251 ]); 252 253 $this->assertSame('array_object', $type); 254 } 255 256 public function test_it_gets_null_transformer_for_simple_types(): void 257 { 258 $this->assertNull($this->mapper->getTransformerType(['type' => 'string'])); 259 $this->assertNull($this->mapper->getTransformerType(['type' => 'integer'])); 260 } 261 262 public function test_it_handles_custom_model_class(): void 263 { 264 $body = $this->mapper->generateToModelBody([ 265 'name' => ['type' => 'string'], 266 ], 'CustomModel'); 267 268 $this->assertStringContainsString('return new CustomModel([', $body); 269 } 270 271 public function test_it_does_not_add_trailing_comma_to_last_property(): void 272 { 273 $body = $this->mapper->generateFromModelBody([ 274 'first' => ['type' => 'string'], 275 'last' => ['type' => 'string'], 276 ]); 277 278 // Should not have comma after last property 279 $lines = explode("\n", $body); 280 $lastPropertyLine = ''; 281 foreach ($lines as $line) { 282 if (str_contains($line, 'last:')) { 283 $lastPropertyLine = $line; 284 285 break; 286 } 287 } 288 289 $this->assertStringNotContainsString(',', rtrim($lastPropertyLine)); 290 } 291}