| Total Complexity | 58 |
| Total Lines | 1721 |
| Duplicated Lines | 0 % |
| Changes | 8 | ||
| Bugs | 0 | Features | 0 |
Complex classes like HydratorTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use HydratorTest, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 76 | class HydratorTest extends TestCase |
||
| 77 | { |
||
| 78 | private ?int $invalidValueExceptionCount = null; |
||
| 79 | private array $invalidValueExceptionMessage = []; |
||
| 80 | private array $invalidValueExceptionPropertyPath = []; |
||
| 81 | private array $invalidValueExceptionErrorCode = []; |
||
| 82 | |||
| 83 | /** |
||
| 84 | * @group boolean |
||
| 85 | * @dataProvider strictBooleanDataProvider |
||
| 86 | * @dataProvider nonStrictBooleanDataProvider |
||
| 87 | */ |
||
| 88 | public function testHydrateBooleanProperty(array $data, bool $expected): void |
||
| 89 | { |
||
| 90 | $this->assertInvalidValueExceptionCount(0); |
||
| 91 | $object = $this->createHydrator()->hydrate(ObjectWithBoolean::class, $data); |
||
| 92 | $this->assertSame($expected, $object->value); |
||
| 93 | } |
||
| 94 | |||
| 95 | /** |
||
| 96 | * @group boolean |
||
| 97 | * @dataProvider strictBooleanDataProvider |
||
| 98 | * @dataProvider nonStrictBooleanDataProvider |
||
| 99 | * @dataProvider strictNullDataProvider |
||
| 100 | * @dataProvider nonStrictNullDataProvider |
||
| 101 | */ |
||
| 102 | public function testHydrateNullableBooleanProperty(array $data, ?bool $expected): void |
||
| 103 | { |
||
| 104 | $this->assertInvalidValueExceptionCount(0); |
||
| 105 | $object = $this->createHydrator()->hydrate(ObjectWithNullableBoolean::class, $data); |
||
| 106 | $this->assertSame($expected, $object->value); |
||
| 107 | } |
||
| 108 | |||
| 109 | /** |
||
| 110 | * @group boolean |
||
| 111 | * @dataProvider strictBooleanDataProvider |
||
| 112 | * @dataProvider nonStrictBooleanDataProvider |
||
| 113 | * @dataProvider emptyDataProvider |
||
| 114 | */ |
||
| 115 | public function testHydrateOptionalBooleanProperty(array $data, bool $expected = true): void |
||
| 116 | { |
||
| 117 | $this->assertInvalidValueExceptionCount(0); |
||
| 118 | $object = $this->createHydrator()->hydrate(ObjectWithOptionalBoolean::class, $data); |
||
| 119 | $this->assertSame($expected, $object->value); |
||
| 120 | } |
||
| 121 | |||
| 122 | /** |
||
| 123 | * @group boolean |
||
| 124 | * @dataProvider strictNullDataProvider |
||
| 125 | * @dataProvider nonStrictNullDataProvider |
||
| 126 | */ |
||
| 127 | public function testHydrateNonNullableBooleanPropertyWithNull(array $data): void |
||
| 128 | { |
||
| 129 | $this->assertInvalidValueExceptionCount(1); |
||
| 130 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 131 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 132 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 133 | $this->createHydrator()->hydrate(ObjectWithBoolean::class, $data); |
||
| 134 | } |
||
| 135 | |||
| 136 | /** |
||
| 137 | * @group boolean |
||
| 138 | * @dataProvider notBooleanDataProvider |
||
| 139 | */ |
||
| 140 | public function testHydrateBooleanPropertyWithNonBooleanValue(array $data): void |
||
| 141 | { |
||
| 142 | $this->assertInvalidValueExceptionCount(1); |
||
| 143 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type boolean.'); |
||
| 144 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_BOOLEAN); |
||
| 145 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 146 | $this->createHydrator()->hydrate(ObjectWithBoolean::class, $data); |
||
| 147 | } |
||
| 148 | |||
| 149 | /** |
||
| 150 | * @group boolean |
||
| 151 | */ |
||
| 152 | public function testHydrateRequiredBooleanPropertyWithoutValue(): void |
||
| 153 | { |
||
| 154 | $this->assertInvalidValueExceptionCount(1); |
||
| 155 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 156 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 157 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 158 | $this->createHydrator()->hydrate(ObjectWithBoolean::class, []); |
||
| 159 | } |
||
| 160 | |||
| 161 | /** |
||
| 162 | * @group integer |
||
| 163 | * @dataProvider strictIntegerDataProvider |
||
| 164 | * @dataProvider nonStrictIntegerDataProvider |
||
| 165 | */ |
||
| 166 | public function testHydrateIntegerProperty(array $data, int $expected): void |
||
| 167 | { |
||
| 168 | $this->assertInvalidValueExceptionCount(0); |
||
| 169 | $object = $this->createHydrator()->hydrate(ObjectWithInteger::class, $data); |
||
| 170 | $this->assertSame($expected, $object->value); |
||
| 171 | } |
||
| 172 | |||
| 173 | /** |
||
| 174 | * @group integer |
||
| 175 | * @dataProvider strictIntegerDataProvider |
||
| 176 | * @dataProvider nonStrictIntegerDataProvider |
||
| 177 | * @dataProvider strictNullDataProvider |
||
| 178 | * @dataProvider nonStrictNullDataProvider |
||
| 179 | */ |
||
| 180 | public function testHydrateNullableIntegerProperty(array $data, ?int $expected): void |
||
| 181 | { |
||
| 182 | $this->assertInvalidValueExceptionCount(0); |
||
| 183 | $object = $this->createHydrator()->hydrate(ObjectWithNullableInteger::class, $data); |
||
| 184 | $this->assertSame($expected, $object->value); |
||
| 185 | } |
||
| 186 | |||
| 187 | /** |
||
| 188 | * @group integer |
||
| 189 | * @dataProvider strictIntegerDataProvider |
||
| 190 | * @dataProvider nonStrictIntegerDataProvider |
||
| 191 | * @dataProvider emptyDataProvider |
||
| 192 | */ |
||
| 193 | public function testHydrateOptionalIntegerProperty(array $data, int $expected = 42): void |
||
| 194 | { |
||
| 195 | $this->assertInvalidValueExceptionCount(0); |
||
| 196 | $object = $this->createHydrator()->hydrate(ObjectWithOptionalInteger::class, $data); |
||
| 197 | $this->assertSame($expected, $object->value); |
||
| 198 | } |
||
| 199 | |||
| 200 | /** |
||
| 201 | * @group integer |
||
| 202 | * @dataProvider strictNullDataProvider |
||
| 203 | * @dataProvider nonStrictNullDataProvider |
||
| 204 | */ |
||
| 205 | public function testHydrateNonNullableIntegerPropertyWithNull(array $data): void |
||
| 206 | { |
||
| 207 | $this->assertInvalidValueExceptionCount(1); |
||
| 208 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 209 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 210 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 211 | $this->createHydrator()->hydrate(ObjectWithInteger::class, $data); |
||
| 212 | } |
||
| 213 | |||
| 214 | /** |
||
| 215 | * @group integer |
||
| 216 | * @dataProvider notIntegerDataProvider |
||
| 217 | */ |
||
| 218 | public function testHydrateIntegerPropertyWithNotInteger(array $data): void |
||
| 219 | { |
||
| 220 | $this->assertInvalidValueExceptionCount(1); |
||
| 221 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type integer.'); |
||
| 222 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_INTEGER); |
||
| 223 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 224 | $this->createHydrator()->hydrate(ObjectWithInteger::class, $data); |
||
| 225 | } |
||
| 226 | |||
| 227 | /** |
||
| 228 | * @group integer |
||
| 229 | */ |
||
| 230 | public function testHydrateRequiredIntegerPropertyWithoutValue(): void |
||
| 231 | { |
||
| 232 | $this->assertInvalidValueExceptionCount(1); |
||
| 233 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 234 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 235 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 236 | $this->createHydrator()->hydrate(ObjectWithInteger::class, []); |
||
| 237 | } |
||
| 238 | |||
| 239 | /** |
||
| 240 | * @group number |
||
| 241 | * @dataProvider strictNumberDataProvider |
||
| 242 | * @dataProvider nonStrictNumberDataProvider |
||
| 243 | */ |
||
| 244 | public function testHydrateNumericProperty(array $data, float $expected): void |
||
| 245 | { |
||
| 246 | $this->assertInvalidValueExceptionCount(0); |
||
| 247 | $object = $this->createHydrator()->hydrate(ObjectWithNumber::class, $data); |
||
| 248 | $this->assertSame($expected, $object->value); |
||
| 249 | } |
||
| 250 | |||
| 251 | /** |
||
| 252 | * @group number |
||
| 253 | * @dataProvider strictNumberDataProvider |
||
| 254 | * @dataProvider nonStrictNumberDataProvider |
||
| 255 | * @dataProvider strictNullDataProvider |
||
| 256 | * @dataProvider nonStrictNullDataProvider |
||
| 257 | */ |
||
| 258 | public function testHydrateNullableNumericProperty(array $data, ?float $expected): void |
||
| 259 | { |
||
| 260 | $this->assertInvalidValueExceptionCount(0); |
||
| 261 | $object = $this->createHydrator()->hydrate(ObjectWithNullableNumber::class, $data); |
||
| 262 | $this->assertSame($expected, $object->value); |
||
| 263 | } |
||
| 264 | |||
| 265 | /** |
||
| 266 | * @group number |
||
| 267 | * @dataProvider strictNumberDataProvider |
||
| 268 | * @dataProvider nonStrictNumberDataProvider |
||
| 269 | * @dataProvider emptyDataProvider |
||
| 270 | */ |
||
| 271 | public function testHydrateOptionalNumericProperty(array $data, float $expected = 3.14159): void |
||
| 272 | { |
||
| 273 | $this->assertInvalidValueExceptionCount(0); |
||
| 274 | $object = $this->createHydrator()->hydrate(ObjectWithOptionalNumber::class, $data); |
||
| 275 | $this->assertSame($expected, $object->value); |
||
| 276 | } |
||
| 277 | |||
| 278 | /** |
||
| 279 | * @group number |
||
| 280 | * @dataProvider strictNullDataProvider |
||
| 281 | * @dataProvider nonStrictNullDataProvider |
||
| 282 | */ |
||
| 283 | public function testHydrateNonNullableNumericPropertyWithNull(array $data): void |
||
| 284 | { |
||
| 285 | $this->assertInvalidValueExceptionCount(1); |
||
| 286 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 287 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 288 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 289 | $this->createHydrator()->hydrate(ObjectWithNumber::class, $data); |
||
| 290 | } |
||
| 291 | |||
| 292 | /** |
||
| 293 | * @group number |
||
| 294 | * @dataProvider notNumberDataProvider |
||
| 295 | */ |
||
| 296 | public function testHydrateNumericPropertyWithNotNumber(array $data): void |
||
| 297 | { |
||
| 298 | $this->assertInvalidValueExceptionCount(1); |
||
| 299 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type number.'); |
||
| 300 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_NUMBER); |
||
| 301 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 302 | $this->createHydrator()->hydrate(ObjectWithNumber::class, $data); |
||
| 303 | } |
||
| 304 | |||
| 305 | /** |
||
| 306 | * @group number |
||
| 307 | */ |
||
| 308 | public function testHydrateRequiredNumericPropertyWithoutValue(): void |
||
| 309 | { |
||
| 310 | $this->assertInvalidValueExceptionCount(1); |
||
| 311 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 312 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 313 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 314 | $this->createHydrator()->hydrate(ObjectWithNumber::class, []); |
||
| 315 | } |
||
| 316 | |||
| 317 | /** |
||
| 318 | * @group string |
||
| 319 | * @dataProvider stringDataProvider |
||
| 320 | */ |
||
| 321 | public function testHydrateStringProperty(array $data, string $expected): void |
||
| 322 | { |
||
| 323 | $this->assertInvalidValueExceptionCount(0); |
||
| 324 | $object = $this->createHydrator()->hydrate(ObjectWithString::class, $data); |
||
| 325 | $this->assertSame($expected, $object->value); |
||
| 326 | } |
||
| 327 | |||
| 328 | /** |
||
| 329 | * @group string |
||
| 330 | * @dataProvider stringDataProvider |
||
| 331 | * @dataProvider strictNullDataProvider |
||
| 332 | */ |
||
| 333 | public function testHydrateNullableStringProperty(array $data, ?string $expected): void |
||
| 334 | { |
||
| 335 | $this->assertInvalidValueExceptionCount(0); |
||
| 336 | $object = $this->createHydrator()->hydrate(ObjectWithNullableString::class, $data); |
||
| 337 | $this->assertSame($expected, $object->value); |
||
| 338 | } |
||
| 339 | |||
| 340 | /** |
||
| 341 | * @group string |
||
| 342 | * @dataProvider stringDataProvider |
||
| 343 | * @dataProvider emptyDataProvider |
||
| 344 | */ |
||
| 345 | public function testHydrateOptionalStringProperty(array $data, string $expected = 'default'): void |
||
| 346 | { |
||
| 347 | $this->assertInvalidValueExceptionCount(0); |
||
| 348 | $object = $this->createHydrator()->hydrate(ObjectWithOptionalString::class, $data); |
||
| 349 | $this->assertSame($expected, $object->value); |
||
| 350 | } |
||
| 351 | |||
| 352 | /** |
||
| 353 | * @group string |
||
| 354 | * @dataProvider strictNullDataProvider |
||
| 355 | */ |
||
| 356 | public function testHydrateNonNullableStringPropertyWithNull(array $data): void |
||
| 357 | { |
||
| 358 | $this->assertInvalidValueExceptionCount(1); |
||
| 359 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 360 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 361 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 362 | $this->createHydrator()->hydrate(ObjectWithString::class, $data); |
||
| 363 | } |
||
| 364 | |||
| 365 | /** |
||
| 366 | * @group string |
||
| 367 | * @dataProvider notStringDataProvider |
||
| 368 | */ |
||
| 369 | public function testHydrateStringPropertyWithNotString(array $data): void |
||
| 370 | { |
||
| 371 | $this->assertInvalidValueExceptionCount(1); |
||
| 372 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type string.'); |
||
| 373 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_STRING); |
||
| 374 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 375 | $this->createHydrator()->hydrate(ObjectWithString::class, $data); |
||
| 376 | } |
||
| 377 | |||
| 378 | /** |
||
| 379 | * @group string |
||
| 380 | */ |
||
| 381 | public function testHydrateRequiredStringPropertyWithoutValue(): void |
||
| 382 | { |
||
| 383 | $this->assertInvalidValueExceptionCount(1); |
||
| 384 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 385 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 386 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 387 | $this->createHydrator()->hydrate(ObjectWithString::class, []); |
||
| 388 | } |
||
| 389 | |||
| 390 | /** |
||
| 391 | * @group array |
||
| 392 | * @dataProvider arrayDataProvider |
||
| 393 | */ |
||
| 394 | public function testHydrateArrayProperty(array $data, array $expected): void |
||
| 395 | { |
||
| 396 | $this->assertInvalidValueExceptionCount(0); |
||
| 397 | $object = $this->createHydrator()->hydrate(ObjectWithArray::class, $data); |
||
| 398 | $this->assertSame($expected, $object->value); |
||
| 399 | } |
||
| 400 | |||
| 401 | /** |
||
| 402 | * @group array |
||
| 403 | * @dataProvider arrayDataProvider |
||
| 404 | * @dataProvider strictNullDataProvider |
||
| 405 | */ |
||
| 406 | public function testHydrateNullableArrayProperty(array $data, ?array $expected): void |
||
| 407 | { |
||
| 408 | $this->assertInvalidValueExceptionCount(0); |
||
| 409 | $object = $this->createHydrator()->hydrate(ObjectWithNullableArray::class, $data); |
||
| 410 | $this->assertSame($expected, $object->value); |
||
| 411 | } |
||
| 412 | |||
| 413 | /** |
||
| 414 | * @group array |
||
| 415 | * @dataProvider arrayDataProvider |
||
| 416 | * @dataProvider emptyDataProvider |
||
| 417 | */ |
||
| 418 | public function testHydrateOptionalArrayProperty(array $data, array $expected = []): void |
||
| 419 | { |
||
| 420 | $this->assertInvalidValueExceptionCount(0); |
||
| 421 | $object = $this->createHydrator()->hydrate(ObjectWithOptionalArray::class, $data); |
||
| 422 | $this->assertSame($expected, $object->value); |
||
| 423 | } |
||
| 424 | |||
| 425 | /** |
||
| 426 | * @group array |
||
| 427 | * @dataProvider strictNullDataProvider |
||
| 428 | */ |
||
| 429 | public function testHydrateNonNullableArrayPropertyWithNull(array $data): void |
||
| 430 | { |
||
| 431 | $this->assertInvalidValueExceptionCount(1); |
||
| 432 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 433 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 434 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 435 | $this->createHydrator()->hydrate(ObjectWithArray::class, $data); |
||
| 436 | } |
||
| 437 | |||
| 438 | /** |
||
| 439 | * @group array |
||
| 440 | * @dataProvider notArrayDataProvider |
||
| 441 | */ |
||
| 442 | public function testHydrateArrayPropertyWithNotArray(array $data): void |
||
| 443 | { |
||
| 444 | $this->assertInvalidValueExceptionCount(1); |
||
| 445 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type array.'); |
||
| 446 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_ARRAY); |
||
| 447 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 448 | $this->createHydrator()->hydrate(ObjectWithArray::class, $data); |
||
| 449 | } |
||
| 450 | |||
| 451 | /** |
||
| 452 | * @group array |
||
| 453 | */ |
||
| 454 | public function testHydrateRequiredArrayPropertyWithoutValue(): void |
||
| 455 | { |
||
| 456 | $this->assertInvalidValueExceptionCount(1); |
||
| 457 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 458 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 459 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 460 | $this->createHydrator()->hydrate(ObjectWithArray::class, []); |
||
| 461 | } |
||
| 462 | |||
| 463 | /** |
||
| 464 | * @group datetimeTimestamp |
||
| 465 | * @dataProvider timestampDataProvider |
||
| 466 | */ |
||
| 467 | public function testHydrateTimestampProperty(array $data, string $expected, string $format): void |
||
| 468 | { |
||
| 469 | $this->assertInvalidValueExceptionCount(0); |
||
| 470 | $object = $this->createHydrator()->hydrate(ObjectWithTimestamp::class, $data); |
||
| 471 | $this->assertSame($expected, $object->value->format($format)); |
||
| 472 | } |
||
| 473 | |||
| 474 | /** |
||
| 475 | * @group datetimeTimestamp |
||
| 476 | * @dataProvider timestampDataProvider |
||
| 477 | * @dataProvider strictNullDataProvider |
||
| 478 | * @dataProvider nonStrictNullDataProvider |
||
| 479 | */ |
||
| 480 | // phpcs:ignore Generic.Files.LineLength |
||
| 481 | public function testHydrateNullableTimestampProperty(array $data, ?string $expected = null, ?string $format = null): void |
||
| 482 | { |
||
| 483 | $this->assertInvalidValueExceptionCount(0); |
||
| 484 | $object = $this->createHydrator()->hydrate(ObjectWithNullableTimestamp::class, $data); |
||
| 485 | $this->assertSame($expected, isset($object->value, $format) ? $object->value->format($format) : null); |
||
| 486 | } |
||
| 487 | |||
| 488 | /** |
||
| 489 | * @group datetimeTimestamp |
||
| 490 | * @dataProvider timestampDataProvider |
||
| 491 | * @dataProvider emptyDataProvider |
||
| 492 | */ |
||
| 493 | // phpcs:ignore Generic.Files.LineLength |
||
| 494 | public function testHydrateOptionalTimestampProperty(array $data, ?string $expected = null, ?string $format = null): void |
||
| 495 | { |
||
| 496 | $this->assertInvalidValueExceptionCount(0); |
||
| 497 | $object = $this->createHydrator()->hydrate(ObjectWithOptionalTimestamp::class, $data); |
||
| 498 | $this->assertSame($expected, isset($object->value, $format) ? $object->value->format($format) : null); |
||
| 499 | } |
||
| 500 | |||
| 501 | /** |
||
| 502 | * @group datetimeTimestamp |
||
| 503 | * @dataProvider strictNullDataProvider |
||
| 504 | * @dataProvider nonStrictNullDataProvider |
||
| 505 | */ |
||
| 506 | public function testHydrateNonNullableTimestampPropertyWithNull(array $data): void |
||
| 507 | { |
||
| 508 | $this->assertInvalidValueExceptionCount(1); |
||
| 509 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 510 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 511 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 512 | $this->createHydrator()->hydrate(ObjectWithTimestamp::class, $data); |
||
| 513 | } |
||
| 514 | |||
| 515 | /** |
||
| 516 | * @group datetimeTimestamp |
||
| 517 | * @dataProvider notStringDataProvider |
||
| 518 | */ |
||
| 519 | public function testHydrateTimestampPropertyWithNotString(array $data): void |
||
| 520 | { |
||
| 521 | $this->assertInvalidValueExceptionCount(1); |
||
| 522 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type string.'); |
||
| 523 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_STRING); |
||
| 524 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 525 | $this->createHydrator()->hydrate(ObjectWithTimestamp::class, $data); |
||
| 526 | } |
||
| 527 | |||
| 528 | /** |
||
| 529 | * @group datetimeTimestamp |
||
| 530 | * @dataProvider invalidTimestampDataProvider |
||
| 531 | */ |
||
| 532 | public function testHydrateTimestampPropertyWithInvalidTimestamp(array $data): void |
||
| 533 | { |
||
| 534 | $this->assertInvalidValueExceptionCount(1); |
||
| 535 | $message = sprintf('This value is not a valid timestamp, expected format: %s.', ObjectWithTimestamp::FORMAT); |
||
| 536 | $this->assertInvalidValueExceptionMessage(0, $message); |
||
| 537 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::INVALID_TIMESTAMP); |
||
| 538 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 539 | $this->createHydrator()->hydrate(ObjectWithTimestamp::class, $data); |
||
| 540 | } |
||
| 541 | |||
| 542 | /** |
||
| 543 | * @group datetimeTimestamp |
||
| 544 | */ |
||
| 545 | public function testHydrateRequiredTimestampPropertyWithoutValue(): void |
||
| 546 | { |
||
| 547 | $this->assertInvalidValueExceptionCount(1); |
||
| 548 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 549 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 550 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 551 | $this->createHydrator()->hydrate(ObjectWithTimestamp::class, []); |
||
| 552 | } |
||
| 553 | |||
| 554 | /** |
||
| 555 | * @group datetimeTimestamp |
||
| 556 | * @dataProvider timestampDataProvider |
||
| 557 | */ |
||
| 558 | public function testHydrateUnformattedTimestampProperty(array $data): void |
||
| 559 | { |
||
| 560 | $this->expectException(UnsupportedPropertyTypeException::class); |
||
| 561 | $this->expectExceptionMessage(sprintf( |
||
| 562 | 'The property %1$s.%2$s must contain the attribute %3$s, ' . |
||
| 563 | 'for example: #[\%3$s(\DateTimeInterface::DATE_RFC3339)].', |
||
| 564 | ObjectWithUnformattedTimestampProperty::class, |
||
| 565 | 'value', |
||
| 566 | Format::class, |
||
| 567 | )); |
||
| 568 | |||
| 569 | $this->createHydrator()->hydrate(ObjectWithUnformattedTimestampProperty::class, $data); |
||
| 570 | } |
||
| 571 | |||
| 572 | /** |
||
| 573 | * @group unixTimestamp |
||
| 574 | * @dataProvider strictUnixTimeStampDataProvider |
||
| 575 | * @dataProvider nonStrictUnixTimeStampDataProvider |
||
| 576 | */ |
||
| 577 | public function testHydrateUnixTimeStampProperty(array $data, string $expected, string $format): void |
||
| 578 | { |
||
| 579 | $this->assertInvalidValueExceptionCount(0); |
||
| 580 | $object = $this->createHydrator()->hydrate(ObjectWithUnixTimeStamp::class, $data); |
||
| 581 | $this->assertSame($expected, $object->value->format($format)); |
||
| 582 | } |
||
| 583 | |||
| 584 | /** |
||
| 585 | * @group unixTimestamp |
||
| 586 | * @dataProvider strictUnixTimeStampDataProvider |
||
| 587 | * @dataProvider nonStrictUnixTimeStampDataProvider |
||
| 588 | * @dataProvider strictNullDataProvider |
||
| 589 | * @dataProvider nonStrictNullDataProvider |
||
| 590 | */ |
||
| 591 | // phpcs:ignore Generic.Files.LineLength |
||
| 592 | public function testHydrateNullableUnixTimeStampProperty(array $data, ?string $expected = null, ?string $format = null): void |
||
| 593 | { |
||
| 594 | $this->assertInvalidValueExceptionCount(0); |
||
| 595 | $object = $this->createHydrator()->hydrate(ObjectWithNullableUnixTimeStamp::class, $data); |
||
| 596 | $this->assertSame($expected, isset($object->value, $format) ? $object->value->format($format) : null); |
||
| 597 | } |
||
| 598 | |||
| 599 | /** |
||
| 600 | * @group unixTimestamp |
||
| 601 | * @dataProvider strictUnixTimeStampDataProvider |
||
| 602 | * @dataProvider nonStrictUnixTimeStampDataProvider |
||
| 603 | * @dataProvider emptyDataProvider |
||
| 604 | */ |
||
| 605 | // phpcs:ignore Generic.Files.LineLength |
||
| 606 | public function testHydrateOptionalUnixTimeStampProperty(array $data, ?string $expected = null, ?string $format = null): void |
||
| 607 | { |
||
| 608 | $this->assertInvalidValueExceptionCount(0); |
||
| 609 | $object = $this->createHydrator()->hydrate(ObjectWithOptionalUnixTimeStamp::class, $data); |
||
| 610 | $this->assertSame($expected, isset($object->value, $format) ? $object->value->format($format) : null); |
||
| 611 | } |
||
| 612 | |||
| 613 | /** |
||
| 614 | * @group unixTimestamp |
||
| 615 | * @dataProvider strictNullDataProvider |
||
| 616 | * @dataProvider nonStrictNullDataProvider |
||
| 617 | */ |
||
| 618 | public function testHydrateNonNullableUnixTimeStampPropertyWithNull(array $data): void |
||
| 619 | { |
||
| 620 | $this->assertInvalidValueExceptionCount(1); |
||
| 621 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 622 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 623 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 624 | $this->createHydrator()->hydrate(ObjectWithUnixTimeStamp::class, $data); |
||
| 625 | } |
||
| 626 | |||
| 627 | /** |
||
| 628 | * @group unixTimestamp |
||
| 629 | * @dataProvider notIntegerDataProvider |
||
| 630 | */ |
||
| 631 | public function testHydrateUnixTimeStampPropertyWithNotInteger(array $data): void |
||
| 632 | { |
||
| 633 | $this->assertInvalidValueExceptionCount(1); |
||
| 634 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type integer.'); |
||
| 635 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_INTEGER); |
||
| 636 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 637 | $this->createHydrator()->hydrate(ObjectWithUnixTimeStamp::class, $data); |
||
| 638 | } |
||
| 639 | |||
| 640 | /** |
||
| 641 | * @group unixTimestamp |
||
| 642 | */ |
||
| 643 | public function testHydrateRequiredUnixTimeStampPropertyWithoutValue(): void |
||
| 644 | { |
||
| 645 | $this->assertInvalidValueExceptionCount(1); |
||
| 646 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 647 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 648 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 649 | $this->createHydrator()->hydrate(ObjectWithUnixTimeStamp::class, []); |
||
| 650 | } |
||
| 651 | |||
| 652 | /** |
||
| 653 | * @group integerEnumeration |
||
| 654 | * @dataProvider strictIntegerEnumerationDataProvider |
||
| 655 | * @dataProvider nonStrictIntegerEnumerationDataProvider |
||
| 656 | * @param IntegerEnum $expected |
||
| 657 | */ |
||
| 658 | public function testHydrateIntegerEnumerationProperty(array $data, $expected): void |
||
| 659 | { |
||
| 660 | $this->phpRequired('8.1'); |
||
| 661 | $this->assertInvalidValueExceptionCount(0); |
||
| 662 | $object = $this->createHydrator()->hydrate(ObjectWithIntegerEnum::class, $data); |
||
| 663 | $this->assertSame($expected, $object->value); |
||
| 664 | } |
||
| 665 | |||
| 666 | /** |
||
| 667 | * @group integerEnumeration |
||
| 668 | * @dataProvider strictIntegerEnumerationDataProvider |
||
| 669 | * @dataProvider nonStrictIntegerEnumerationDataProvider |
||
| 670 | * @dataProvider strictNullDataProvider |
||
| 671 | * @dataProvider nonStrictNullDataProvider |
||
| 672 | * @param IntegerEnum|null $expected |
||
| 673 | */ |
||
| 674 | public function testHydrateNullableIntegerEnumerationProperty(array $data, $expected): void |
||
| 675 | { |
||
| 676 | $this->phpRequired('8.1'); |
||
| 677 | $this->assertInvalidValueExceptionCount(0); |
||
| 678 | $object = $this->createHydrator()->hydrate(ObjectWithNullableIntegerEnum::class, $data); |
||
| 679 | $this->assertSame($expected, $object->value); |
||
| 680 | } |
||
| 681 | |||
| 682 | /** |
||
| 683 | * @group integerEnumeration |
||
| 684 | * @dataProvider strictIntegerEnumerationDataProvider |
||
| 685 | * @dataProvider nonStrictIntegerEnumerationDataProvider |
||
| 686 | * @dataProvider emptyDataProvider |
||
| 687 | * @param IntegerEnum|null $expected |
||
| 688 | */ |
||
| 689 | // phpcs:ignore Generic.Files.LineLength |
||
| 690 | public function testHydrateOptionalIntegerEnumerationProperty(array $data, $expected = null): void |
||
| 691 | { |
||
| 692 | $this->phpRequired('8.1'); |
||
| 693 | $this->assertInvalidValueExceptionCount(0); |
||
| 694 | $object = $this->createHydrator()->hydrate(ObjectWithOptionalIntegerEnum::class, $data); |
||
| 695 | $this->assertSame($expected ?? IntegerEnum::FOO, $object->value); |
||
| 696 | } |
||
| 697 | |||
| 698 | /** |
||
| 699 | * @group integerEnumeration |
||
| 700 | * @dataProvider strictNullDataProvider |
||
| 701 | * @dataProvider nonStrictNullDataProvider |
||
| 702 | */ |
||
| 703 | public function testHydrateNonNullableIntegerEnumerationPropertyWithNull(array $data): void |
||
| 704 | { |
||
| 705 | $this->phpRequired('8.1'); |
||
| 706 | $this->assertInvalidValueExceptionCount(1); |
||
| 707 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 708 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 709 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 710 | $this->createHydrator()->hydrate(ObjectWithIntegerEnum::class, $data); |
||
| 711 | } |
||
| 712 | |||
| 713 | /** |
||
| 714 | * @group integerEnumeration |
||
| 715 | * @dataProvider notIntegerDataProvider |
||
| 716 | */ |
||
| 717 | public function testHydrateIntegerEnumerationPropertyWithNotInteger(array $data): void |
||
| 718 | { |
||
| 719 | $this->phpRequired('8.1'); |
||
| 720 | $this->assertInvalidValueExceptionCount(1); |
||
| 721 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type integer.'); |
||
| 722 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_INTEGER); |
||
| 723 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 724 | $this->createHydrator()->hydrate(ObjectWithIntegerEnum::class, $data); |
||
| 725 | } |
||
| 726 | |||
| 727 | /** |
||
| 728 | * @group integerEnumeration |
||
| 729 | */ |
||
| 730 | public function testHydrateRequiredIntegerEnumerationPropertyWithoutValue(): void |
||
| 731 | { |
||
| 732 | $this->assertInvalidValueExceptionCount(1); |
||
| 733 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 734 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 735 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 736 | $this->createHydrator()->hydrate(ObjectWithIntegerEnum::class, []); |
||
| 737 | } |
||
| 738 | |||
| 739 | /** |
||
| 740 | * @group stringEnumeration |
||
| 741 | */ |
||
| 742 | public function testHydrateIntegerEnumerationPropertyWithInvalidChoice(): void |
||
| 743 | { |
||
| 744 | $this->phpRequired('8.1'); |
||
| 745 | $this->assertInvalidValueExceptionCount(1); |
||
| 746 | // phpcs:ignore Generic.Files.LineLength |
||
| 747 | $this->assertInvalidValueExceptionMessage(0, 'This value is not a valid choice, expected choices: 1, 2, 3.'); |
||
| 748 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::INVALID_CHOICE); |
||
| 749 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 750 | $this->createHydrator()->hydrate(ObjectWithIntegerEnum::class, ['value' => 42]); |
||
| 751 | } |
||
| 752 | |||
| 753 | /** |
||
| 754 | * @group stringEnumeration |
||
| 755 | * @dataProvider stringEnumerationDataProvider |
||
| 756 | * @param StringEnum $expected |
||
| 757 | */ |
||
| 758 | public function testHydrateStringEnumerationProperty(array $data, $expected): void |
||
| 759 | { |
||
| 760 | $this->phpRequired('8.1'); |
||
| 761 | $this->assertInvalidValueExceptionCount(0); |
||
| 762 | $object = $this->createHydrator()->hydrate(ObjectWithStringEnum::class, $data); |
||
| 763 | $this->assertSame($expected, $object->value); |
||
| 764 | } |
||
| 765 | |||
| 766 | /** |
||
| 767 | * @group stringEnumeration |
||
| 768 | * @dataProvider stringEnumerationDataProvider |
||
| 769 | * @dataProvider strictNullDataProvider |
||
| 770 | * @dataProvider nonStrictNullDataProvider |
||
| 771 | * @param StringEnum|null $expected |
||
| 772 | */ |
||
| 773 | public function testHydrateNullableStringEnumerationProperty(array $data, $expected): void |
||
| 774 | { |
||
| 775 | $this->phpRequired('8.1'); |
||
| 776 | $this->assertInvalidValueExceptionCount(0); |
||
| 777 | $object = $this->createHydrator()->hydrate(ObjectWithNullableStringEnum::class, $data); |
||
| 778 | $this->assertSame($expected, $object->value); |
||
| 779 | } |
||
| 780 | |||
| 781 | /** |
||
| 782 | * @group stringEnumeration |
||
| 783 | * @dataProvider stringEnumerationDataProvider |
||
| 784 | * @dataProvider emptyDataProvider |
||
| 785 | * @param StringEnum|null $expected |
||
| 786 | */ |
||
| 787 | // phpcs:ignore Generic.Files.LineLength |
||
| 788 | public function testHydrateOptionalStringEnumerationProperty(array $data, $expected = null): void |
||
| 789 | { |
||
| 790 | $this->phpRequired('8.1'); |
||
| 791 | $this->assertInvalidValueExceptionCount(0); |
||
| 792 | $object = $this->createHydrator()->hydrate(ObjectWithOptionalStringEnum::class, $data); |
||
| 793 | $this->assertSame($expected ?? StringEnum::FOO, $object->value); |
||
| 794 | } |
||
| 795 | |||
| 796 | /** |
||
| 797 | * @group stringEnumeration |
||
| 798 | * @dataProvider strictNullDataProvider |
||
| 799 | * @dataProvider nonStrictNullDataProvider |
||
| 800 | */ |
||
| 801 | public function testHydrateNonNullableStringEnumerationPropertyWithNull(array $data): void |
||
| 802 | { |
||
| 803 | $this->phpRequired('8.1'); |
||
| 804 | $this->assertInvalidValueExceptionCount(1); |
||
| 805 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 806 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 807 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 808 | $this->createHydrator()->hydrate(ObjectWithStringEnum::class, $data); |
||
| 809 | } |
||
| 810 | |||
| 811 | /** |
||
| 812 | * @group stringEnumeration |
||
| 813 | * @dataProvider notStringDataProvider |
||
| 814 | */ |
||
| 815 | public function testHydrateStringEnumerationPropertyWithNotInteger(array $data): void |
||
| 816 | { |
||
| 817 | $this->phpRequired('8.1'); |
||
| 818 | $this->assertInvalidValueExceptionCount(1); |
||
| 819 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type string.'); |
||
| 820 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_STRING); |
||
| 821 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 822 | $this->createHydrator()->hydrate(ObjectWithStringEnum::class, $data); |
||
| 823 | } |
||
| 824 | |||
| 825 | /** |
||
| 826 | * @group stringEnumeration |
||
| 827 | */ |
||
| 828 | public function testHydrateStringEnumerationPropertyWithInvalidChoice(): void |
||
| 829 | { |
||
| 830 | $this->phpRequired('8.1'); |
||
| 831 | $this->assertInvalidValueExceptionCount(1); |
||
| 832 | // phpcs:ignore Generic.Files.LineLength |
||
| 833 | $this->assertInvalidValueExceptionMessage(0, 'This value is not a valid choice, expected choices: foo, bar, baz.'); |
||
| 834 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::INVALID_CHOICE); |
||
| 835 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 836 | $this->createHydrator()->hydrate(ObjectWithStringEnum::class, ['value' => 'unknown']); |
||
| 837 | } |
||
| 838 | |||
| 839 | /** |
||
| 840 | * @group stringEnumeration |
||
| 841 | */ |
||
| 842 | public function testHydrateRequiredStringEnumerationPropertyWithoutValue(): void |
||
| 843 | { |
||
| 844 | $this->assertInvalidValueExceptionCount(1); |
||
| 845 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 846 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 847 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 848 | $this->createHydrator()->hydrate(ObjectWithStringEnum::class, []); |
||
| 849 | } |
||
| 850 | |||
| 851 | /** |
||
| 852 | * @group relationship |
||
| 853 | * @dataProvider stringDataProvider |
||
| 854 | */ |
||
| 855 | public function testHydrateRelationshipProperty(array $data, string $expected): void |
||
| 856 | { |
||
| 857 | $this->assertInvalidValueExceptionCount(0); |
||
| 858 | $object = $this->createHydrator()->hydrate(ObjectWithRelationship::class, ['value' => $data]); |
||
| 859 | $this->assertSame($expected, $object->value->value); |
||
| 860 | } |
||
| 861 | |||
| 862 | /** |
||
| 863 | * @group relationship |
||
| 864 | * @dataProvider strictNullDataProvider |
||
| 865 | */ |
||
| 866 | public function testHydrateNullableRelationshipProperty(array $data): void |
||
| 867 | { |
||
| 868 | $this->assertInvalidValueExceptionCount(0); |
||
| 869 | $object = $this->createHydrator()->hydrate(ObjectWithNullableRelationship::class, $data); |
||
| 870 | $this->assertNull($object->value); |
||
| 871 | } |
||
| 872 | |||
| 873 | /** |
||
| 874 | * @group relationship |
||
| 875 | * @dataProvider emptyDataProvider |
||
| 876 | */ |
||
| 877 | public function testHydrateOptionalRelationshipProperty(array $data): void |
||
| 878 | { |
||
| 879 | $this->assertInvalidValueExceptionCount(0); |
||
| 880 | $object = $this->createHydrator()->hydrate(ObjectWithOptionalRelationship::class, $data); |
||
| 881 | $this->assertNull($object->value); |
||
| 882 | } |
||
| 883 | |||
| 884 | /** |
||
| 885 | * @group relationship |
||
| 886 | * @dataProvider strictNullDataProvider |
||
| 887 | */ |
||
| 888 | public function testHydrateNonNullableRelationshipPropertyWithNull(array $data): void |
||
| 889 | { |
||
| 890 | $this->assertInvalidValueExceptionCount(1); |
||
| 891 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 892 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 893 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 894 | $this->createHydrator()->hydrate(ObjectWithRelationship::class, $data); |
||
| 895 | } |
||
| 896 | |||
| 897 | /** |
||
| 898 | * @group relationship |
||
| 899 | * @dataProvider notArrayDataProvider |
||
| 900 | */ |
||
| 901 | public function testHydrateRelationshipPropertyWithNotArray(array $data): void |
||
| 902 | { |
||
| 903 | $this->assertInvalidValueExceptionCount(1); |
||
| 904 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type array.'); |
||
| 905 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_ARRAY); |
||
| 906 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 907 | $this->createHydrator()->hydrate(ObjectWithRelationship::class, $data); |
||
| 908 | } |
||
| 909 | |||
| 910 | /** |
||
| 911 | * @group relationship |
||
| 912 | */ |
||
| 913 | public function testHydrateRequiredRelationshipPropertyWithoutValue(): void |
||
| 914 | { |
||
| 915 | $this->assertInvalidValueExceptionCount(1); |
||
| 916 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 917 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 918 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 919 | $this->createHydrator()->hydrate(ObjectWithRelationship::class, []); |
||
| 920 | } |
||
| 921 | |||
| 922 | /** |
||
| 923 | * @group relationship |
||
| 924 | * @dataProvider stringDataProvider |
||
| 925 | */ |
||
| 926 | public function testHydrateRelationshipWithStringProperty(array $data, string $expected): void |
||
| 927 | { |
||
| 928 | $this->assertInvalidValueExceptionCount(0); |
||
| 929 | $object = $this->createHydrator()->hydrate(ObjectWithRelationshipWithString::class, ['value' => $data]); |
||
| 930 | $this->assertSame($expected, $object->value->value); |
||
| 931 | } |
||
| 932 | |||
| 933 | /** |
||
| 934 | * @group relationship |
||
| 935 | * @dataProvider stringDataProvider |
||
| 936 | * @dataProvider strictNullDataProvider |
||
| 937 | */ |
||
| 938 | public function testHydrateRelationshipWithNullableStringProperty(array $data, ?string $expected): void |
||
| 939 | { |
||
| 940 | $this->assertInvalidValueExceptionCount(0); |
||
| 941 | $object = $this->createHydrator()->hydrate(ObjectWithRelationshipWithNullableString::class, ['value' => $data]); |
||
| 942 | $this->assertSame($expected, $object->value->value); |
||
| 943 | } |
||
| 944 | |||
| 945 | /** |
||
| 946 | * @group relationship |
||
| 947 | * @dataProvider stringDataProvider |
||
| 948 | * @dataProvider emptyDataProvider |
||
| 949 | */ |
||
| 950 | public function testHydrateRelationshipWithOptionalStringProperty(array $data, string $expected = 'default'): void |
||
| 951 | { |
||
| 952 | $this->assertInvalidValueExceptionCount(0); |
||
| 953 | $object = $this->createHydrator()->hydrate(ObjectWithRelationshipWithOptionalString::class, ['value' => $data]); |
||
| 954 | $this->assertSame($expected, $object->value->value); |
||
| 955 | } |
||
| 956 | |||
| 957 | /** |
||
| 958 | * @group relationship |
||
| 959 | * @dataProvider strictNullDataProvider |
||
| 960 | */ |
||
| 961 | public function testHydrateRelationshipWithNonNullablePropertyWithNull(array $data): void |
||
| 962 | { |
||
| 963 | $this->assertInvalidValueExceptionCount(1); |
||
| 964 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 965 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 966 | $this->assertInvalidValueExceptionPropertyPath(0, 'value.value'); |
||
| 967 | $this->createHydrator()->hydrate(ObjectWithRelationshipWithString::class, ['value' => $data]); |
||
| 968 | } |
||
| 969 | |||
| 970 | /** |
||
| 971 | * @group relationship |
||
| 972 | * @dataProvider notStringDataProvider |
||
| 973 | */ |
||
| 974 | public function testHydrateRelationshipWithStringPropertyWithNotString(array $data): void |
||
| 975 | { |
||
| 976 | $this->assertInvalidValueExceptionCount(1); |
||
| 977 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type string.'); |
||
| 978 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_STRING); |
||
| 979 | $this->assertInvalidValueExceptionPropertyPath(0, 'value.value'); |
||
| 980 | $this->createHydrator()->hydrate(ObjectWithRelationshipWithString::class, ['value' => $data]); |
||
| 981 | } |
||
| 982 | |||
| 983 | /** |
||
| 984 | * @group relationship |
||
| 985 | */ |
||
| 986 | public function testHydrateRelationshipWithRequiredStringPropertyWithoutValue(): void |
||
| 987 | { |
||
| 988 | $this->assertInvalidValueExceptionCount(1); |
||
| 989 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 990 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 991 | $this->assertInvalidValueExceptionPropertyPath(0, 'value.value'); |
||
| 992 | $this->createHydrator()->hydrate(ObjectWithRelationshipWithString::class, ['value' => []]); |
||
| 993 | } |
||
| 994 | |||
| 995 | /** |
||
| 996 | * @group relationship |
||
| 997 | */ |
||
| 998 | public function testHydrateUnstantiableRelationshipProperty(): void |
||
| 999 | { |
||
| 1000 | $this->expectException(UnsupportedPropertyTypeException::class); |
||
| 1001 | $this->expectExceptionMessage(sprintf( |
||
| 1002 | 'The property %s.%s refers to a non-instantiable class %s.', |
||
| 1003 | ObjectWithUnstantiableRelationship::class, |
||
| 1004 | 'value', |
||
| 1005 | UnstantiableObject::class, |
||
| 1006 | )); |
||
| 1007 | |||
| 1008 | $this->createHydrator()->hydrate(ObjectWithUnstantiableRelationship::class, ['value' => []]); |
||
| 1009 | } |
||
| 1010 | |||
| 1011 | /** |
||
| 1012 | * @group relationships |
||
| 1013 | */ |
||
| 1014 | public function testHydrateRelationshipsProperty(): void |
||
| 1015 | { |
||
| 1016 | $data = ['value' => [['value' => ['value' => 'foo']], ['value' => ['value' => 'bar']]]]; |
||
| 1017 | |||
| 1018 | $this->assertInvalidValueExceptionCount(0); |
||
| 1019 | $object = $this->createHydrator()->hydrate(ObjectWithRelationships::class, $data); |
||
| 1020 | $this->assertCount(2, $object->value); |
||
| 1021 | $this->assertArrayHasKey(0, $object->value); |
||
| 1022 | $this->assertSame($data['value'][0]['value']['value'], $object->value[0]->value->value); |
||
| 1023 | $this->assertArrayHasKey(1, $object->value); |
||
| 1024 | $this->assertSame($data['value'][1]['value']['value'], $object->value[1]->value->value); |
||
| 1025 | } |
||
| 1026 | |||
| 1027 | /** |
||
| 1028 | * @group relationships |
||
| 1029 | * @dataProvider strictNullDataProvider |
||
| 1030 | */ |
||
| 1031 | public function testHydrateNullableRelationshipsProperty(array $data): void |
||
| 1032 | { |
||
| 1033 | $this->assertInvalidValueExceptionCount(0); |
||
| 1034 | $object = $this->createHydrator()->hydrate(ObjectWithNullableRelationships::class, $data); |
||
| 1035 | $this->assertNull($object->value); |
||
| 1036 | } |
||
| 1037 | |||
| 1038 | /** |
||
| 1039 | * @group relationships |
||
| 1040 | * @dataProvider emptyDataProvider |
||
| 1041 | */ |
||
| 1042 | public function testHydrateOptionalRelationshipsProperty(array $data): void |
||
| 1043 | { |
||
| 1044 | $this->assertInvalidValueExceptionCount(0); |
||
| 1045 | $object = $this->createHydrator()->hydrate(ObjectWithOptionalRelationships::class, $data); |
||
| 1046 | $this->assertSame([], $object->value); |
||
| 1047 | } |
||
| 1048 | |||
| 1049 | /** |
||
| 1050 | * @group relationships |
||
| 1051 | * @dataProvider strictNullDataProvider |
||
| 1052 | */ |
||
| 1053 | public function testHydrateNonNullableRelationshipsPropertyWithNull(array $data): void |
||
| 1054 | { |
||
| 1055 | $this->assertInvalidValueExceptionCount(1); |
||
| 1056 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 1057 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 1058 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 1059 | $this->createHydrator()->hydrate(ObjectWithRelationships::class, $data); |
||
| 1060 | } |
||
| 1061 | |||
| 1062 | /** |
||
| 1063 | * @group relationships |
||
| 1064 | * @dataProvider notArrayDataProvider |
||
| 1065 | */ |
||
| 1066 | public function testHydrateRelationshipsPropertyWithNotArray(array $data): void |
||
| 1067 | { |
||
| 1068 | $this->assertInvalidValueExceptionCount(1); |
||
| 1069 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type array.'); |
||
| 1070 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_ARRAY); |
||
| 1071 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 1072 | $this->createHydrator()->hydrate(ObjectWithRelationships::class, $data); |
||
| 1073 | } |
||
| 1074 | |||
| 1075 | /** |
||
| 1076 | * @group relationships |
||
| 1077 | */ |
||
| 1078 | public function testHydrateRequiredRelationshipsPropertyWithoutValue(): void |
||
| 1079 | { |
||
| 1080 | $this->assertInvalidValueExceptionCount(1); |
||
| 1081 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 1082 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 1083 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 1084 | $this->createHydrator()->hydrate(ObjectWithRelationships::class, []); |
||
| 1085 | } |
||
| 1086 | |||
| 1087 | /** |
||
| 1088 | * @group relationships |
||
| 1089 | * @dataProvider strictNullDataProvider |
||
| 1090 | */ |
||
| 1091 | public function testHydrateRelationshipsPropertyWithNullsForNonNullableValues(array $data): void |
||
| 1092 | { |
||
| 1093 | $this->assertInvalidValueExceptionCount(1); |
||
| 1094 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 1095 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 1096 | $this->assertInvalidValueExceptionPropertyPath(0, 'value.0.value.value'); |
||
| 1097 | $this->createHydrator()->hydrate(ObjectWithRelationships::class, ['value' => [['value' => $data]]]); |
||
| 1098 | } |
||
| 1099 | |||
| 1100 | /** |
||
| 1101 | * @group relationships |
||
| 1102 | * @dataProvider notStringDataProvider |
||
| 1103 | */ |
||
| 1104 | public function testHydrateRelationshipsPropertyWithNotStringForStringValue(array $data): void |
||
| 1105 | { |
||
| 1106 | $this->assertInvalidValueExceptionCount(1); |
||
| 1107 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type string.'); |
||
| 1108 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_STRING); |
||
| 1109 | $this->assertInvalidValueExceptionPropertyPath(0, 'value.0.value.value'); |
||
| 1110 | $this->createHydrator()->hydrate(ObjectWithRelationships::class, ['value' => [['value' => $data]]]); |
||
| 1111 | } |
||
| 1112 | |||
| 1113 | /** |
||
| 1114 | * @group relationships |
||
| 1115 | */ |
||
| 1116 | public function testHydrateRelationshipsPropertyWithoutValueForRequiredValue(): void |
||
| 1117 | { |
||
| 1118 | $this->assertInvalidValueExceptionCount(1); |
||
| 1119 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 1120 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 1121 | $this->assertInvalidValueExceptionPropertyPath(0, 'value.0.value.value'); |
||
| 1122 | $this->createHydrator()->hydrate(ObjectWithRelationships::class, ['value' => [['value' => []]]]); |
||
| 1123 | } |
||
| 1124 | |||
| 1125 | /** |
||
| 1126 | * @group relationships |
||
| 1127 | */ |
||
| 1128 | public function testHydrateRelationshipsPropertyWithNotArrayForRelation(): void |
||
| 1129 | { |
||
| 1130 | $this->assertInvalidValueExceptionCount(1); |
||
| 1131 | $this->assertInvalidValueExceptionMessage(0, 'This value should be of type array.'); |
||
| 1132 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_ARRAY); |
||
| 1133 | $this->assertInvalidValueExceptionPropertyPath(0, 'value.0'); |
||
| 1134 | $this->createHydrator()->hydrate(ObjectWithRelationships::class, ['value' => [null]]); |
||
| 1135 | } |
||
| 1136 | |||
| 1137 | /** |
||
| 1138 | * @group relationships |
||
| 1139 | */ |
||
| 1140 | public function testSeveralErrorsWhenHydratingRelationshipsProperty(): void |
||
| 1141 | { |
||
| 1142 | $this->assertInvalidValueExceptionCount(3); |
||
| 1143 | $this->assertInvalidValueExceptionMessage(0, 'This value should not be empty.'); |
||
| 1144 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_NOT_BE_EMPTY); |
||
| 1145 | $this->assertInvalidValueExceptionPropertyPath(0, 'value.0.value.value'); |
||
| 1146 | $this->assertInvalidValueExceptionMessage(1, 'This value should be of type string.'); |
||
| 1147 | $this->assertInvalidValueExceptionErrorCode(1, ErrorCode::VALUE_SHOULD_BE_STRING); |
||
| 1148 | $this->assertInvalidValueExceptionPropertyPath(1, 'value.1.value.value'); |
||
| 1149 | $this->assertInvalidValueExceptionMessage(2, 'This value should be provided.'); |
||
| 1150 | $this->assertInvalidValueExceptionErrorCode(2, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 1151 | $this->assertInvalidValueExceptionPropertyPath(2, 'value.2.value.value'); |
||
| 1152 | $this->createHydrator()->hydrate(ObjectWithRelationships::class, ['value' => [ |
||
| 1153 | ['value' => ['value' => null]], |
||
| 1154 | ['value' => ['value' => []]], |
||
| 1155 | ['value' => []] |
||
| 1156 | ]]); |
||
| 1157 | } |
||
| 1158 | |||
| 1159 | /** |
||
| 1160 | * @group relationships |
||
| 1161 | */ |
||
| 1162 | public function testHydrateLimitedRelationshipsProperty(): void |
||
| 1163 | { |
||
| 1164 | $this->assertInvalidValueExceptionCount(1); |
||
| 1165 | $this->assertInvalidValueExceptionMessage(0, 'This element is redundant, limit: 1.'); |
||
| 1166 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::REDUNDANT_ELEMENT); |
||
| 1167 | $this->assertInvalidValueExceptionPropertyPath(0, 'value.1'); |
||
| 1168 | $this->createHydrator()->hydrate(ObjectWithRelationshipsWithLimit::class, ['value' => [ |
||
| 1169 | ['value' => 'foo'], |
||
| 1170 | ['value' => 'bar'], |
||
| 1171 | ]]); |
||
| 1172 | } |
||
| 1173 | |||
| 1174 | /** |
||
| 1175 | * @group relationships |
||
| 1176 | */ |
||
| 1177 | public function testHydrateRelationshipsPropertyWithUnstantiableObject(): void |
||
| 1178 | { |
||
| 1179 | $this->expectException(UnsupportedPropertyTypeException::class); |
||
| 1180 | $this->expectExceptionMessage(sprintf( |
||
| 1181 | 'The property %s.%s refers to a non-instantiable class %s.', |
||
| 1182 | ObjectWithRelationshipsWithUnstantiableObject::class, |
||
| 1183 | 'value', |
||
| 1184 | UnstantiableObject::class, |
||
| 1185 | )); |
||
| 1186 | |||
| 1187 | $this->createHydrator()->hydrate( |
||
| 1188 | ObjectWithRelationshipsWithUnstantiableObject::class, |
||
| 1189 | ['value' => [['value' => []]]], |
||
| 1190 | ); |
||
| 1191 | } |
||
| 1192 | |||
| 1193 | /** |
||
| 1194 | * @group json |
||
| 1195 | */ |
||
| 1196 | public function testHydrateObjectWithJson(): void |
||
| 1197 | { |
||
| 1198 | $this->assertInvalidValueExceptionCount(0); |
||
| 1199 | $object = $this->createHydrator()->hydrateWithJson(ObjectWithString::class, '{"value": "foo"}'); |
||
| 1200 | $this->assertSame('foo', $object->value); |
||
| 1201 | } |
||
| 1202 | |||
| 1203 | /** |
||
| 1204 | * @group json |
||
| 1205 | */ |
||
| 1206 | public function testHydrateObjectWithInvalidJson(): void |
||
| 1207 | { |
||
| 1208 | $this->expectException(InvalidDataException::class); |
||
| 1209 | $this->expectExceptionMessage('Invalid JSON: Maximum stack depth exceeded'); |
||
| 1210 | $this->createHydrator()->hydrateWithJson(ObjectWithString::class, '[]', 0, 1); |
||
| 1211 | } |
||
| 1212 | |||
| 1213 | /** |
||
| 1214 | * @group json |
||
| 1215 | */ |
||
| 1216 | public function testHydrateObjectWithNonObjectableJson(): void |
||
| 1217 | { |
||
| 1218 | $this->expectException(InvalidDataException::class); |
||
| 1219 | $this->expectExceptionMessage('JSON must be an object.'); |
||
| 1220 | $this->createHydrator()->hydrateWithJson(ObjectWithString::class, 'null'); |
||
| 1221 | } |
||
| 1222 | |||
| 1223 | public function testInstantedObject(): void |
||
| 1224 | { |
||
| 1225 | $object = new class { |
||
| 1226 | public string $value; |
||
| 1227 | }; |
||
| 1228 | |||
| 1229 | $this->assertInvalidValueExceptionCount(0); |
||
| 1230 | $this->createHydrator()->hydrate($object, ['value' => 'foo']); |
||
| 1231 | $this->assertSame('foo', $object->value); |
||
| 1232 | } |
||
| 1233 | |||
| 1234 | public function testUnstantiableObject(): void |
||
| 1235 | { |
||
| 1236 | $this->expectException(UninitializableObjectException::class); |
||
| 1237 | $this->expectExceptionMessage(sprintf( |
||
| 1238 | 'The class %s cannot be hydrated because it is an uninstantiable class.', |
||
| 1239 | UnstantiableObject::class, |
||
| 1240 | )); |
||
| 1241 | |||
| 1242 | $this->createHydrator()->hydrate(UnstantiableObject::class, []); |
||
| 1243 | } |
||
| 1244 | |||
| 1245 | public function testStaticalProperty(): void |
||
| 1246 | { |
||
| 1247 | $this->assertInvalidValueExceptionCount(0); |
||
| 1248 | $this->createHydrator()->hydrate(ObjectWithStaticalProperty::class, ['value' => 'foo']); |
||
| 1249 | $this->assertNotSame('foo', ObjectWithStaticalProperty::$value); |
||
| 1250 | } |
||
| 1251 | |||
| 1252 | public function testIgnoredProperty(): void |
||
| 1253 | { |
||
| 1254 | $this->assertInvalidValueExceptionCount(0); |
||
| 1255 | $object = $this->createHydrator()->hydrate(ObjectWithIgnoredProperty::class, ['value' => 'foo']); |
||
| 1256 | $this->assertNotSame('foo', $object->value); |
||
| 1257 | } |
||
| 1258 | |||
| 1259 | public function testUnsupportedPropertyType(): void |
||
| 1260 | { |
||
| 1261 | $this->expectException(UnsupportedPropertyTypeException::class); |
||
| 1262 | $this->expectExceptionMessage(sprintf( |
||
| 1263 | 'The property %s.%s contains an unsupported type %s.', |
||
| 1264 | ObjectWithUnsupportedProperty::class, |
||
| 1265 | 'value', |
||
| 1266 | 'iterable', |
||
| 1267 | )); |
||
| 1268 | |||
| 1269 | $this->createHydrator()->hydrate(ObjectWithUnsupportedProperty::class, ['value' => []]); |
||
| 1270 | } |
||
| 1271 | |||
| 1272 | public function testUnsupportedPropertyTypeNotation(): void |
||
| 1273 | { |
||
| 1274 | $this->phpRequired('8.0'); |
||
| 1275 | |||
| 1276 | $this->expectException(UnsupportedPropertyTypeException::class); |
||
| 1277 | $this->expectExceptionMessage(sprintf( |
||
| 1278 | 'The property %s.%s contains an unsupported type %s.', |
||
| 1279 | ObjectWithUnsupportedPropertyNotation::class, |
||
| 1280 | 'value', |
||
| 1281 | 'int|float', |
||
| 1282 | )); |
||
| 1283 | |||
| 1284 | $this->createHydrator()->hydrate(ObjectWithUnsupportedPropertyNotation::class, ['value' => []]); |
||
| 1285 | } |
||
| 1286 | |||
| 1287 | public function testUntypedProperty(): void |
||
| 1288 | { |
||
| 1289 | $this->expectException(UntypedPropertyException::class); |
||
| 1290 | $this->expectExceptionMessage(sprintf( |
||
| 1291 | 'The property %s.%s is not typed.', |
||
| 1292 | ObjectWithUntypedProperty::class, |
||
| 1293 | 'value', |
||
| 1294 | )); |
||
| 1295 | |||
| 1296 | $this->createHydrator()->hydrate(ObjectWithUntypedProperty::class, ['value' => []]); |
||
| 1297 | } |
||
| 1298 | |||
| 1299 | public function testAnnotatedAlias(): void |
||
| 1300 | { |
||
| 1301 | /** @var Hydrator $hydrator */ |
||
| 1302 | $hydrator = $this->createHydrator(); |
||
| 1303 | $hydrator->useDefaultAnnotationReader(); |
||
| 1304 | |||
| 1305 | $this->assertInvalidValueExceptionCount(0); |
||
| 1306 | $object = $hydrator->hydrate(ObjectWithAnnotatedAlias::class, ['non-normalized-value' => 'foo']); |
||
| 1307 | $this->assertSame('foo', $object->value); |
||
| 1308 | |||
| 1309 | $this->assertInvalidValueExceptionCount(1); |
||
| 1310 | $hydrator->hydrate(ObjectWithAnnotatedAlias::class, ['value' => 'foo']); |
||
| 1311 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 1312 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 1313 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 1314 | } |
||
| 1315 | |||
| 1316 | public function testAttributedAlias(): void |
||
| 1317 | { |
||
| 1318 | $this->phpRequired('8.0'); |
||
| 1319 | |||
| 1320 | /** @var Hydrator $hydrator */ |
||
| 1321 | $hydrator = $this->createHydrator(); |
||
| 1322 | |||
| 1323 | $this->assertInvalidValueExceptionCount(0); |
||
| 1324 | $object = $hydrator->hydrate(ObjectWithAttributedAlias::class, ['non-normalized-value' => 'foo']); |
||
| 1325 | $this->assertSame('foo', $object->value); |
||
| 1326 | |||
| 1327 | $this->assertInvalidValueExceptionCount(1); |
||
| 1328 | $hydrator->hydrate(ObjectWithAttributedAlias::class, ['value' => 'foo']); |
||
| 1329 | $this->assertInvalidValueExceptionMessage(0, 'This value should be provided.'); |
||
| 1330 | $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::VALUE_SHOULD_BE_PROVIDED); |
||
| 1331 | $this->assertInvalidValueExceptionPropertyPath(0, 'value'); |
||
| 1332 | } |
||
| 1333 | |||
| 1334 | public function testAnnotationReader(): void |
||
| 1335 | { |
||
| 1336 | /** @var Hydrator $hydrator */ |
||
| 1337 | $hydrator = $this->createHydrator(); |
||
| 1338 | |||
| 1339 | $hydrator->setAnnotationReader(null); |
||
| 1340 | $this->assertNull($hydrator->getAnnotationReader()); |
||
|
|
|||
| 1341 | |||
| 1342 | $reader = $this->createMock(Reader::class); |
||
| 1343 | $hydrator->setAnnotationReader($reader); |
||
| 1344 | $this->assertSame($reader, $hydrator->getAnnotationReader()); |
||
| 1345 | |||
| 1346 | $hydrator->setAnnotationReader(null); |
||
| 1347 | $this->assertNull($hydrator->getAnnotationReader()); |
||
| 1348 | } |
||
| 1349 | |||
| 1350 | public function testHydrateStore(): void |
||
| 1351 | { |
||
| 1352 | $this->phpRequired('8.1'); |
||
| 1353 | |||
| 1354 | $sold = Status::SOLD; |
||
| 1355 | |||
| 1356 | $data = []; |
||
| 1357 | $data['name'] = 'Some product'; |
||
| 1358 | $data['category']['name'] = 'Some category'; |
||
| 1359 | $data['tags'][]['name'] = 'foo'; |
||
| 1360 | $data['tags'][]['name'] = 'bar'; |
||
| 1361 | $data['status'] = $sold->value; |
||
| 1362 | $data['createdAt'] = '2000-01-01 00:00:00'; |
||
| 1363 | |||
| 1364 | $this->assertInvalidValueExceptionCount(0); |
||
| 1365 | $product = $this->createHydrator()->hydrate(Product::class, $data); |
||
| 1366 | $this->assertSame('Some product', $product->name); |
||
| 1367 | $this->assertSame('Some category', $product->category->name); |
||
| 1368 | $this->assertCount(2, $product->tags); |
||
| 1369 | $this->assertArrayHasKey(0, $product->tags); |
||
| 1370 | $this->assertSame('foo', $product->tags[0]->name); |
||
| 1371 | $this->assertArrayHasKey(1, $product->tags); |
||
| 1372 | $this->assertSame('bar', $product->tags[1]->name); |
||
| 1373 | $this->assertSame(Status::SOLD, $product->status); |
||
| 1374 | $this->assertSame('2000-01-01 00:00:00', $product->createdAt->format('Y-m-d H:i:s')); |
||
| 1375 | |||
| 1376 | unset($data['createdAt']); |
||
| 1377 | $this->assertInvalidValueExceptionCount(0); |
||
| 1378 | $product = $this->createHydrator()->hydrate(Product::class, $data); |
||
| 1379 | $this->assertSame('2020-01-01 12:00:00', $product->createdAt->format('Y-m-d H:i:s')); |
||
| 1380 | } |
||
| 1381 | |||
| 1382 | public function testSymfonyViolations(): void |
||
| 1383 | { |
||
| 1384 | $violations = null; |
||
| 1385 | try { |
||
| 1386 | $this->createHydrator()->hydrate(ObjectWithString::class, []); |
||
| 1387 | } catch (InvalidDataException $e) { |
||
| 1388 | $violations = $e->getViolations(); |
||
| 1389 | } |
||
| 1390 | |||
| 1391 | $this->assertNotNull($violations); |
||
| 1392 | $this->assertCount(1, $violations); |
||
| 1393 | $this->assertTrue($violations->has(0)); |
||
| 1394 | $this->assertSame(ErrorCode::VALUE_SHOULD_BE_PROVIDED, $violations->get(0)->getCode()); |
||
| 1395 | $this->assertSame('This value should be provided.', $violations->get(0)->getMessage()); |
||
| 1396 | $this->assertSame('value', $violations->get(0)->getPropertyPath()); |
||
| 1397 | } |
||
| 1398 | |||
| 1399 | public function emptyDataProvider(): array |
||
| 1400 | { |
||
| 1401 | return [ |
||
| 1402 | [[]], |
||
| 1403 | ]; |
||
| 1404 | } |
||
| 1405 | |||
| 1406 | public function strictNullDataProvider(): array |
||
| 1407 | { |
||
| 1408 | return [ |
||
| 1409 | [['value' => null], null], |
||
| 1410 | ]; |
||
| 1411 | } |
||
| 1412 | |||
| 1413 | public function nonStrictNullDataProvider(): array |
||
| 1414 | { |
||
| 1415 | return [ |
||
| 1416 | [['value' => ''], null], |
||
| 1417 | [['value' => ' '], null], |
||
| 1418 | ]; |
||
| 1419 | } |
||
| 1420 | |||
| 1421 | public function strictBooleanDataProvider(): array |
||
| 1422 | { |
||
| 1423 | return [ |
||
| 1424 | [['value' => true], true], |
||
| 1425 | [['value' => false], false], |
||
| 1426 | ]; |
||
| 1427 | } |
||
| 1428 | |||
| 1429 | public function nonStrictBooleanDataProvider(): array |
||
| 1430 | { |
||
| 1431 | return [ |
||
| 1432 | [['value' => '1'], true], |
||
| 1433 | [['value' => '0'], false], |
||
| 1434 | [['value' => 'true'], true], |
||
| 1435 | [['value' => 'false'], false], |
||
| 1436 | [['value' => 'yes'], true], |
||
| 1437 | [['value' => 'no'], false], |
||
| 1438 | [['value' => 'on'], true], |
||
| 1439 | [['value' => 'off'], false], |
||
| 1440 | ]; |
||
| 1441 | } |
||
| 1442 | |||
| 1443 | public function notBooleanDataProvider(): array |
||
| 1444 | { |
||
| 1445 | return [ |
||
| 1446 | [['value' => 0]], |
||
| 1447 | [['value' => 1]], |
||
| 1448 | [['value' => 42]], |
||
| 1449 | [['value' => 3.14159]], |
||
| 1450 | [['value' => 'foo']], |
||
| 1451 | [['value' => []]], |
||
| 1452 | ]; |
||
| 1453 | } |
||
| 1454 | |||
| 1455 | public function strictIntegerDataProvider(): array |
||
| 1456 | { |
||
| 1457 | return [ |
||
| 1458 | [['value' => -1], -1], |
||
| 1459 | [['value' => 0], 0], |
||
| 1460 | [['value' => 1], 1], |
||
| 1461 | ]; |
||
| 1462 | } |
||
| 1463 | |||
| 1464 | public function nonStrictIntegerDataProvider(): array |
||
| 1465 | { |
||
| 1466 | return [ |
||
| 1467 | [['value' => '-1'], -1], |
||
| 1468 | [['value' => '0'], 0], |
||
| 1469 | [['value' => '+1'], 1], |
||
| 1470 | ]; |
||
| 1471 | } |
||
| 1472 | |||
| 1473 | public function notIntegerDataProvider(): array |
||
| 1474 | { |
||
| 1475 | return [ |
||
| 1476 | [['value' => true]], |
||
| 1477 | [['value' => false]], |
||
| 1478 | [['value' => 3.14159]], |
||
| 1479 | [['value' => 'foo']], |
||
| 1480 | [['value' => []]], |
||
| 1481 | ]; |
||
| 1482 | } |
||
| 1483 | |||
| 1484 | public function strictNumberDataProvider(): array |
||
| 1485 | { |
||
| 1486 | return [ |
||
| 1487 | [['value' => -1], -1.], |
||
| 1488 | [['value' => 0], 0.], |
||
| 1489 | [['value' => 1], 1.], |
||
| 1490 | [['value' => -1.], -1.], |
||
| 1491 | [['value' => 0.], 0.], |
||
| 1492 | [['value' => 1.], 1.], |
||
| 1493 | [['value' => -.1], -.1], |
||
| 1494 | [['value' => .0], .0], |
||
| 1495 | [['value' => .1], .1], |
||
| 1496 | ]; |
||
| 1497 | } |
||
| 1498 | |||
| 1499 | public function nonStrictNumberDataProvider(): array |
||
| 1500 | { |
||
| 1501 | return [ |
||
| 1502 | [['value' => '-1'], -1.], |
||
| 1503 | [['value' => '0'], 0.], |
||
| 1504 | [['value' => '+1'], 1.], |
||
| 1505 | [['value' => '-1.'], -1.], |
||
| 1506 | [['value' => '0.'], 0.], |
||
| 1507 | [['value' => '+1.'], 1.], |
||
| 1508 | [['value' => '-.1'], -.1], |
||
| 1509 | [['value' => '.0'], .0], |
||
| 1510 | [['value' => '+.1'], .1], |
||
| 1511 | [['value' => '-1.0'], -1.], |
||
| 1512 | [['value' => '0.0'], 0.], |
||
| 1513 | [['value' => '+1.0'], 1.], |
||
| 1514 | [['value' => '1e-1'], .1], |
||
| 1515 | [['value' => '1e1'], 10.], |
||
| 1516 | [['value' => '1e+1'], 10.], |
||
| 1517 | [['value' => '1.e-1'], .1], |
||
| 1518 | [['value' => '1.e1'], 10.], |
||
| 1519 | [['value' => '1.e+1'], 10.], |
||
| 1520 | [['value' => '.1e-1'], .01], |
||
| 1521 | [['value' => '.1e1'], 1.], |
||
| 1522 | [['value' => '.1e+1'], 1.], |
||
| 1523 | [['value' => '1.0e-1'], .1], |
||
| 1524 | [['value' => '1.0e1'], 10.], |
||
| 1525 | [['value' => '1.0e+1'], 10.], |
||
| 1526 | ]; |
||
| 1527 | } |
||
| 1528 | |||
| 1529 | public function notNumberDataProvider(): array |
||
| 1530 | { |
||
| 1531 | return [ |
||
| 1532 | [['value' => true]], |
||
| 1533 | [['value' => false]], |
||
| 1534 | [['value' => 'foo']], |
||
| 1535 | [['value' => []]], |
||
| 1536 | ]; |
||
| 1537 | } |
||
| 1538 | |||
| 1539 | public function stringDataProvider(): array |
||
| 1540 | { |
||
| 1541 | return [ |
||
| 1542 | [['value' => 'foo'], 'foo'], |
||
| 1543 | |||
| 1544 | // Should not be cast to a null |
||
| 1545 | [['value' => ''], ''], |
||
| 1546 | [['value' => ' '], ' '], |
||
| 1547 | |||
| 1548 | // Should not be cast to a boolean type |
||
| 1549 | [['value' => '1'], '1'], |
||
| 1550 | [['value' => '0'], '0'], |
||
| 1551 | [['value' => 'true'], 'true'], |
||
| 1552 | [['value' => 'false'], 'false'], |
||
| 1553 | [['value' => 'yes'], 'yes'], |
||
| 1554 | [['value' => 'no'], 'no'], |
||
| 1555 | [['value' => 'on'], 'on'], |
||
| 1556 | [['value' => 'off'], 'off'], |
||
| 1557 | |||
| 1558 | // Should not be cast to a number |
||
| 1559 | [['value' => '42'], '42'], |
||
| 1560 | [['value' => '3.14159'], '3.14159'], |
||
| 1561 | ]; |
||
| 1562 | } |
||
| 1563 | |||
| 1564 | public function notStringDataProvider(): array |
||
| 1565 | { |
||
| 1566 | return [ |
||
| 1567 | [['value' => true]], |
||
| 1568 | [['value' => false]], |
||
| 1569 | [['value' => 42]], |
||
| 1570 | [['value' => 3.14159]], |
||
| 1571 | [['value' => []]], |
||
| 1572 | ]; |
||
| 1573 | } |
||
| 1574 | |||
| 1575 | public function arrayDataProvider(): array |
||
| 1576 | { |
||
| 1577 | return [ |
||
| 1578 | [['value' => ['foo']], ['foo']] |
||
| 1579 | ]; |
||
| 1580 | } |
||
| 1581 | |||
| 1582 | public function notArrayDataProvider(): array |
||
| 1583 | { |
||
| 1584 | return [ |
||
| 1585 | [['value' => true]], |
||
| 1586 | [['value' => false]], |
||
| 1587 | [['value' => 42]], |
||
| 1588 | [['value' => 3.14159]], |
||
| 1589 | [['value' => 'foo']], |
||
| 1590 | ]; |
||
| 1591 | } |
||
| 1592 | |||
| 1593 | public function timestampDataProvider(): array |
||
| 1594 | { |
||
| 1595 | return [ |
||
| 1596 | [['value' => '1970-01-01 00:00:00'], '1970-01-01 00:00:00', 'Y-m-d H:i:s'], |
||
| 1597 | ]; |
||
| 1598 | } |
||
| 1599 | |||
| 1600 | public function invalidTimestampDataProvider(): array |
||
| 1601 | { |
||
| 1602 | return [ |
||
| 1603 | [['value' => 'Tue, 06 Jun 23 16:50:23']], |
||
| 1604 | ]; |
||
| 1605 | } |
||
| 1606 | |||
| 1607 | public function notTimestampDataProvider(): array |
||
| 1608 | { |
||
| 1609 | return [ |
||
| 1610 | [['value' => true]], |
||
| 1611 | [['value' => false]], |
||
| 1612 | [['value' => 42]], |
||
| 1613 | [['value' => 3.14159]], |
||
| 1614 | [['value' => []]], |
||
| 1615 | ]; |
||
| 1616 | } |
||
| 1617 | |||
| 1618 | public function strictUnixTimeStampDataProvider(): array |
||
| 1619 | { |
||
| 1620 | return [ |
||
| 1621 | [['value' => -1], '1969-12-31 23:59:59', 'Y-m-d H:i:s'], |
||
| 1622 | [['value' => 0], '1970-01-01 00:00:00', 'Y-m-d H:i:s'], |
||
| 1623 | [['value' => 1], '1970-01-01 00:00:01', 'Y-m-d H:i:s'], |
||
| 1624 | ]; |
||
| 1625 | } |
||
| 1626 | |||
| 1627 | public function nonStrictUnixTimeStampDataProvider(): array |
||
| 1628 | { |
||
| 1629 | return [ |
||
| 1630 | [['value' => '-1'], '1969-12-31 23:59:59', 'Y-m-d H:i:s'], |
||
| 1631 | [['value' => '0'], '1970-01-01 00:00:00', 'Y-m-d H:i:s'], |
||
| 1632 | [['value' => '1'], '1970-01-01 00:00:01', 'Y-m-d H:i:s'], |
||
| 1633 | ]; |
||
| 1634 | } |
||
| 1635 | |||
| 1636 | public function notUnixTimeStampDataProvider(): array |
||
| 1637 | { |
||
| 1638 | return [ |
||
| 1639 | [['value' => true]], |
||
| 1640 | [['value' => false]], |
||
| 1641 | [['value' => 'foo']], |
||
| 1642 | [['value' => []]], |
||
| 1643 | ]; |
||
| 1644 | } |
||
| 1645 | |||
| 1646 | public function strictIntegerEnumerationDataProvider(): array |
||
| 1647 | { |
||
| 1648 | if (PHP_VERSION_ID < 80100) { |
||
| 1649 | return [[[], null]]; |
||
| 1650 | } |
||
| 1651 | |||
| 1652 | $foo = IntegerEnum::FOO; |
||
| 1653 | $bar = IntegerEnum::BAR; |
||
| 1654 | $baz = IntegerEnum::BAZ; |
||
| 1655 | |||
| 1656 | return [ |
||
| 1657 | [['value' => $foo->value], $foo], |
||
| 1658 | [['value' => $bar->value], $bar], |
||
| 1659 | [['value' => $baz->value], $baz], |
||
| 1660 | ]; |
||
| 1661 | } |
||
| 1662 | |||
| 1663 | public function nonStrictIntegerEnumerationDataProvider(): array |
||
| 1664 | { |
||
| 1665 | if (PHP_VERSION_ID < 80100) { |
||
| 1666 | return [[[], null]]; |
||
| 1667 | } |
||
| 1668 | |||
| 1669 | $foo = IntegerEnum::FOO; |
||
| 1670 | $bar = IntegerEnum::BAR; |
||
| 1671 | $baz = IntegerEnum::BAZ; |
||
| 1672 | |||
| 1673 | return [ |
||
| 1674 | [['value' => (string) $foo->value], $foo], |
||
| 1675 | [['value' => (string) $bar->value], $bar], |
||
| 1676 | [['value' => (string) $baz->value], $baz], |
||
| 1677 | ]; |
||
| 1678 | } |
||
| 1679 | |||
| 1680 | public function stringEnumerationDataProvider(): array |
||
| 1681 | { |
||
| 1682 | if (PHP_VERSION_ID < 80100) { |
||
| 1683 | return [[[], null]]; |
||
| 1684 | } |
||
| 1685 | |||
| 1686 | $foo = StringEnum::FOO; |
||
| 1687 | $bar = StringEnum::BAR; |
||
| 1688 | $baz = StringEnum::BAZ; |
||
| 1689 | |||
| 1690 | return [ |
||
| 1691 | [['value' => $foo->value], $foo], |
||
| 1692 | [['value' => $bar->value], $bar], |
||
| 1693 | [['value' => $baz->value], $baz], |
||
| 1694 | ]; |
||
| 1695 | } |
||
| 1696 | |||
| 1697 | private function createHydrator(): HydratorInterface |
||
| 1705 | } |
||
| 1706 | |||
| 1707 | private function phpRequired(string $version): void |
||
| 1708 | { |
||
| 1709 | if (version_compare(PHP_VERSION, $version, '<')) { |
||
| 1710 | $this->markTestSkipped(sprintf('PHP %s is required.', $version)); |
||
| 1711 | } |
||
| 1712 | } |
||
| 1713 | |||
| 1714 | private function assertInvalidValueExceptionCount(int $expectedCount): void |
||
| 1717 | } |
||
| 1718 | |||
| 1719 | private function assertInvalidValueExceptionMessage(int $exceptionIndex, string $expectedMessage): void |
||
| 1720 | { |
||
| 1721 | $this->invalidValueExceptionMessage[] = [$exceptionIndex, $expectedMessage]; |
||
| 1722 | } |
||
| 1723 | |||
| 1724 | private function assertInvalidValueExceptionPropertyPath(int $exceptionIndex, string $expectedPropertyPath): void |
||
| 1725 | { |
||
| 1726 | $this->invalidValueExceptionPropertyPath[] = [$exceptionIndex, $expectedPropertyPath]; |
||
| 1727 | } |
||
| 1728 | |||
| 1729 | private function assertInvalidValueExceptionErrorCode(int $exceptionIndex, string $expectedErrorCode): void |
||
| 1730 | { |
||
| 1731 | $this->invalidValueExceptionErrorCode[] = [$exceptionIndex, $expectedErrorCode]; |
||
| 1732 | } |
||
| 1733 | |||
| 1734 | protected function runTest(): void |
||
| 1797 | } |
||
| 1798 | } |
||
| 1799 | } |
||
| 1800 | } |
||
| 1801 |
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.