HydratorTest   F
last analyzed

Complexity

Total Complexity 82

Size/Duplication

Total Lines 3236
Duplicated Lines 0 %

Importance

Changes 19
Bugs 1 Features 0
Metric Value
eloc 1338
c 19
b 1
f 0
dl 0
loc 3236
rs 0.8
wmc 82

397 Methods

Rating   Name   Duplication   Size   Complexity  
A hp$6 ➔ testHydrateOptionalBooleanProperty() 0 9 1
testHydrateRamseyUuidPropertyWithInvalidValue() 0 11 ?
testHydrateBooleanAssociationArrayAccessPropertyWithNull() 0 11 ?
stringEnumDataProvider() 0 13 ?
A hp$94 ➔ testHydrateBooleanAssociationPropertyWithInvalidValue() 0 11 1
A hp$0 ➔ testStdClassWithArrayProperty() 0 9 1
testHydrateBooleanAssociationArrayAccessPropertyWithInvalidAssociation() 0 11 ?
A hp$77 ➔ testHydrateTypedBooleanArrayAccessPropertyWithInvalidElement() 0 11 1
A hp$23 ➔ testHydrateNullableStringProperty() 0 9 1
testHydrateStringEnumProperty() 0 11 ?
A hp$10 ➔ testHydrateIntegerProperty() 0 9 1
A hp$137 ➔ testAliasedProperty() 0 17 1
A hp$79 ➔ testHydrateTypedOverflowedBooleanArrayAccessProperty() 0 11 1
nonStrictIntegerDataProvider() 0 4 ?
testHydrateArrayAccessProperty() 0 9 ?
testHydrateAnnotatedBooleanArrayAccessProperty() 0 10 ?
A hp$141 ➔ strictIntegerProvider() 0 5 1
A hp$141 ➔ nonStrictBooleanProvider() 0 10 1
A hp$141 ➔ strictNotStringProvider() 0 7 1
testHydrateBooleanArrayPropertyWithEmptyElement() 0 13 ?
A hp$125 ➔ testHydrateSymfonyUuidProperty() 0 9 1
testHydrateBooleanPropertyWithEmptyValue() 0 12 ?
A hp$21 ➔ testHydrateNumericPropertyWithoutValue() 0 12 1
A hp$135 ➔ testStaticalProperty() 0 9 1
A hp$141 ➔ invalidTimestampDataProvider() 0 21 1
testHydrateArrayAccessPropertyWithNull() 0 11 ?
testHydrateOptionalNumericProperty() 0 9 ?
A hp$49 ➔ testHydrateNullableBooleanArrayProperty() 0 10 1
testHydrateBooleanArrayCollectionParameterWithInvalidData() 0 13 ?
A hp$141 ➔ strictIntegerDataProvider() 0 4 2
testHydrateObjectWithNonObjectableJson() 0 9 ?
testHydrateOptionalTimestampProperty() 0 11 ?
A hp$107 ➔ testHydrateOptionalTimezoneProperty() 0 9 2
A hp$81 ➔ testHydrateBooleanAssociationArrayAccessPropertyWithNull() 0 11 1
testHydrateOptionalArrayAccessProperty() 0 9 ?
A hp$5 ➔ testHydrateNullableBooleanProperty() 0 9 1
testHydrateNullableIntegerProperty() 0 9 ?
testHydrateRamseyUuidProperty() 0 9 ?
runTest() 0 76 ?
A hp$141 ➔ nonStrictStringProvider() 0 5 1
testHydrateStringEnumPropertyWithoutValue() 0 13 ?
testHydrateTypedBooleanArrayAccessPropertyWithEmptyElement() 0 11 ?
testHydrateTypedBooleanArrayAccessProperty() 0 8 ?
integerEnumDataProvider() 0 17 ?
testStdClassWithAssociationProperty() 0 9 ?
A hp$17 ➔ testHydrateNullableNumericProperty() 0 9 1
A hp$134 ➔ testHydrateStore() 0 33 1
testTypeFromParameter() 0 93 ?
testHydrateIntegerPropertyWithoutValue() 0 12 ?
A hp$108 ➔ testHydrateTimezonePropertyWithEmptyValue() 0 11 1
A hp$92 ➔ testHydrateOptionalBooleanAssociationProperty() 0 9 1
A hp$141 ➔ nonStrictNotStringProvider() 0 6 1
testHydrateLimitedBooleanArrayProperty() 0 13 ?
A hp$28 ➔ testHydrateIntegerEnumProperty() 0 11 1
A hp$40 ➔ testHydrateStringEnumPropertyWithUnknownValue() 0 14 1
testHydrateBooleanAssociationProperty() 0 9 ?
testAliasedProperty() 0 17 ?
nonStrictNumberDataProvider() 0 4 ?
testUntypedProperty() 0 8 ?
testHydrateOptionalSymfonyUuidProperty() 0 9 ?
testHydrateOptionalArrayProperty() 0 9 ?
testHydrateObjectWithJson() 0 9 ?
strictNullDataProvider() 0 4 ?
testHydrateTimestampPropertyWithoutValue() 0 11 ?
nonStrictNullDataProvider() 0 4 ?
A hp$44 ➔ testHydrateOptionalArrayProperty() 0 9 1
A hp$63 ➔ testHydrateArrayAccessPropertyWithNull() 0 11 1
A hp$4 ➔ testHydrateBooleanProperty() 0 9 1
testHydrateIntegerPropertyWithEmptyValue() 0 12 ?
testHydrateBooleanAssociationArrayAccessPropertyWithEmptyAssociationValue() 0 11 ?
testHydrateTimezonePropertyWithoutValue() 0 11 ?
testHydrateArrayAccessPropertyWithoutValue() 0 11 ?
A hp$67 ➔ testHydrateUnstantiableArrayAccessProperty() 0 8 1
A hp$48 ➔ testHydrateBooleanArrayProperty() 0 10 1
testHydrateTimezonePropertyWithUnknownValue() 0 11 ?
A hp$141 ➔ nonStrictBooleanDataProvider() 0 4 2
testHydrateTypedNullableBooleanArrayAccessProperty() 0 8 ?
A hp$89 ➔ testHydrateUnstantiableAssociationProperty() 0 8 1
myclabsEnumDataProvider() 0 9 ?
assertInvalidValueExceptionPropertyPath() 0 3 ?
A hp$141 ➔ strictNumberDataProvider() 0 4 2
A hp$141 ➔ timestampDataProvider() 0 31 1
invalidTimestampDataProvider() 0 21 ?
A hp$93 ➔ testHydrateBooleanAssociationPropertyWithNull() 0 11 1
A hp$72 ➔ testHydrateAnnotatedLimitedBooleanArrayAccessProperty() 0 13 1
A hp$47 ➔ testHydrateArrayPropertyWithoutValue() 0 11 1
testHydrateStringEnumPropertyWithEmptyValue() 0 13 ?
testHydrateSymfonyUuidPropertyWithEmptyValue() 0 11 ?
A hp$123 ➔ testHydrateRamseyUuidPropertyWithInvalidUuid() 0 11 1
strictIntegerProvider() 0 5 ?
A hp$141 ➔ assertInvalidValueExceptionMessage() 0 3 1
A hp$141 ➔ notNumberDataProvider() 0 4 2
A hp$96 ➔ testHydrateBooleanAssociationPropertyWithEmptyAssociation() 0 11 1
A hp$2 ➔ testStdClassWithAssociationProperty() 0 9 1
A hp$85 ➔ testHydrateBooleanAssociationArrayAccessPropertyWithEmptyAssociationValue() 0 11 1
assertInvalidValueExceptionTranslationDomain() 0 5 ?
A hp$90 ➔ testHydrateBooleanAssociationProperty() 0 9 1
A hp$119 ➔ testHydrateNullableRamseyUuidProperty() 0 9 2
A hp$12 ➔ testHydrateOptionalIntegerProperty() 0 9 1
testHydrateBooleanAssociationArrayProperty() 0 13 ?
A hp$82 ➔ testHydrateBooleanAssociationArrayAccessPropertyWithInvalidValue() 0 11 1
strictBooleanDataProvider() 0 4 ?
A hp$126 ➔ testHydrateNullableSymfonyUuidProperty() 0 9 2
A hp$39 ➔ testHydrateStringEnumPropertyWithInvalidValue() 0 13 1
testHydrateArrayProperty() 0 9 ?
testHydrateIntegerEnumPropertyWithoutValue() 0 13 ?
A hp$134 ➔ testUnknownObject() 0 4 1
testHydrateAnnotatedBooleanArrayAccessPropertyWithInvalidElement() 0 13 ?
A hp$130 ➔ testHydrateSymfonyUuidPropertyWithInvalidUuid() 0 11 1
nonStrictStringProvider() 0 5 ?
nonStrictStringDataProvider() 0 4 ?
A hp$141 ➔ notIntegerProvider() 0 7 1
testHydrateMyclabsEnumPropertyWithEmptyValue() 0 11 ?
testHydrateSymfonyUuidPropertyWithInvalidUuid() 0 11 ?
strictNumberProvider() 0 11 ?
testUnstantiableObject() 0 4 ?
testHydrateAnnotatedNullableBooleanArrayAccessProperty() 0 10 ?
testHydrateBooleanAssociationArrayPropertyWithNull() 0 16 ?
A hp$141 ➔ strictBooleanProvider() 0 4 1
A hp$141 ➔ notArrayDataProvider() 0 4 2
A hp$134 ➔ testUnstantiableObject() 0 4 1
testHydrateNumericPropertyWithInvalidValue() 0 12 ?
A hp$99 ➔ testHydrateNullableTimestampProperty() 0 11 2
testHydrateNullableMyclabsEnumProperty() 0 9 ?
testHydrateTimezonePropertyWithEmptyValue() 0 11 ?
testHydrateTimezonePropertyWithInvalidValue() 0 11 ?
A hp$62 ➔ testHydrateOptionalArrayAccessProperty() 0 9 1
A hp$113 ➔ testHydrateNullableMyclabsEnumProperty() 0 9 1
testHydrateNullableStringEnumProperty() 0 11 ?
A hp$53 ➔ testHydrateBooleanAssociationArrayProperty() 0 13 1
A hp$70 ➔ testHydrateAnnotatedBooleanArrayAccessPropertyWithEmptyElement() 0 13 1
A hp$86 ➔ testHydrateBooleanAssociationArrayAccessPropertyWithInvalidAssociationValue() 0 11 1
testHydrateIntegerEnumPropertyWithEmptyValue() 0 13 ?
testHydrateBooleanAssociationArrayPropertyWithEmptyAssociationValue() 0 16 ?
A hp$14 ➔ testHydrateIntegerPropertyWithInvalidValue() 0 12 1
A hp$34 ➔ testHydrateIntegerEnumPropertyWithoutValue() 0 13 1
notBooleanDataProvider() 0 4 ?
A hp$141 ➔ assertInvalidValueExceptionPropertyPath() 0 3 1
A hp$110 ➔ testHydrateTimezonePropertyWithUnknownValue() 0 11 1
testHydrateOptionalIntegerEnumProperty() 0 11 ?
testHydrateMyclabsEnumPropertyWithUnknownValue() 0 12 ?
A hp$65 ➔ testHydrateArrayAccessPropertyWithoutValue() 0 11 1
testHydrateBooleanProperty() 0 9 ?
strictStringDataProvider() 0 4 ?
notNumberProvider() 0 6 ?
testHydrateTimezoneProperty() 0 9 ?
testHydrateMyclabsEnumPropertyWithoutValue() 0 11 ?
testHydrateNullableSymfonyUuidProperty() 0 9 ?
testHydrateArrayAccessPropertyWithInvalidValue() 0 11 ?
testHydrateBooleanAssociationPropertyWithoutValue() 0 11 ?
testHydrateStringPropertyWithoutValue() 0 12 ?
testHydrateStringEnumPropertyWithInvalidValue() 0 13 ?
nonStrictNullProvider() 0 4 ?
A hp$52 ➔ testHydrateLimitedBooleanArrayProperty() 0 13 1
testHydrateBooleanAssociationArrayPropertyWithInvalidAssociationValue() 0 16 ?
A hp$74 ➔ testHydrateTypedBooleanArrayAccessProperty() 0 8 1
testHydrateOverriddenDateTimeImmutable() 0 12 ?
A hp$104 ➔ testHydrateOverriddenDateTimeImmutable() 0 12 1
nonStrictNumberProvider() 0 30 ?
testSymfonyViolations() 0 18 ?
A hp$141 ➔ nonStrictNotStringDataProvider() 0 4 2
timezoneDataProvider() 0 4 ?
A hp$141 ➔ nonStrictStringDataProvider() 0 4 2
A hp$51 ➔ testHydrateBooleanArrayPropertyWithInvalidElement() 0 13 1
A hp$141 ➔ notIntegerDataProvider() 0 4 2
nonStrictBooleanProvider() 0 10 ?
A hp$78 ➔ testHydrateTypedLimitedBooleanArrayAccessProperty() 0 11 1
A hp$141 ➔ timezoneDataProvider() 0 4 2
testHydrateMyclabsEnumProperty() 0 9 ?
testUnsupportedPropertyType() 0 8 ?
A hp$24 ➔ testHydrateOptionalStringProperty() 0 9 1
testHydrateRamseyUuidPropertyWithEmptyValue() 0 11 ?
testHydrateNullableArrayProperty() 0 9 ?
phpRequired() 0 4 ?
testHydrateAnnotatedOverflowedBooleanArrayAccessProperty() 0 13 ?
strictNumberDataProvider() 0 4 ?
notArrayProvider() 0 7 ?
A hp$141 ➔ strictNullDataProvider() 0 4 2
testHydrateArrayPropertyWithoutValue() 0 11 ?
testHydrateTypedOverflowedBooleanArrayAccessProperty() 0 11 ?
notBooleanProvider() 0 8 ?
testStdClassWithArrayProperty() 0 9 ?
A hp$95 ➔ testHydrateBooleanAssociationPropertyWithoutValue() 0 11 1
A hp$141 ➔ notBooleanDataProvider() 0 4 2
testHydrateNumericProperty() 0 9 ?
A hp$111 ➔ testHydrateTimezonePropertyWithoutValue() 0 11 1
notIntegerProvider() 0 7 ?
A hp$54 ➔ testHydrateBooleanAssociationArrayPropertyWithNull() 0 16 1
A hp$46 ➔ testHydrateArrayPropertyWithInvalidValue() 0 11 1
testHydrateStringProperty() 0 9 ?
testHydrateTimestampPropertyWithInvalidValue() 0 11 ?
A hp$50 ➔ testHydrateBooleanArrayPropertyWithEmptyElement() 0 13 1
A hp$71 ➔ testHydrateAnnotatedBooleanArrayAccessPropertyWithInvalidElement() 0 13 1
A hp$141 ➔ nonStrictNumberDataProvider() 0 4 2
testHydrateSymfonyUuidPropertyWithoutValue() 0 11 ?
A hp$64 ➔ testHydrateArrayAccessPropertyWithInvalidValue() 0 11 1
A hp$37 ➔ testHydrateOptionalStringEnumProperty() 0 11 1
testHydrateNumericPropertyWithEmptyValue() 0 12 ?
A hp$15 ➔ testHydrateIntegerPropertyWithoutValue() 0 12 1
A hp$7 ➔ testHydrateBooleanPropertyWithEmptyValue() 0 12 1
testHydrateNullableTimezoneProperty() 0 9 ?
A hp$141 ➔ strictStringProvider() 0 45 1
A hp$41 ➔ testHydrateStringEnumPropertyWithoutValue() 0 13 1
notIntegerDataProvider() 0 4 ?
A hp$141 ➔ strictNullProvider() 0 3 1
testHydrateBooleanAssociationArrayPropertyWithoutValue() 0 16 ?
testHydrateOptionalBooleanProperty() 0 9 ?
testHydrateStore() 0 33 ?
strictNotStringDataProvider() 0 4 ?
A hp$141 ➔ arrayDataProvider() 0 4 1
testHydrateRamseyUuidPropertyWithoutValue() 0 11 ?
A hp$30 ➔ testHydrateOptionalIntegerEnumProperty() 0 11 1
A hp$31 ➔ testHydrateIntegerEnumPropertyWithEmptyValue() 0 13 1
nonStrictIntegerProvider() 0 6 ?
testHydrateNullableStringProperty() 0 9 ?
A hp$69 ➔ testHydrateAnnotatedNullableBooleanArrayAccessProperty() 0 10 1
A hp$19 ➔ testHydrateNumericPropertyWithEmptyValue() 0 12 1
testHydrateAnnotatedBooleanArrayAccessPropertyWithEmptyElement() 0 13 ?
A hp$128 ➔ testHydrateSymfonyUuidPropertyWithEmptyValue() 0 11 1
A hp$32 ➔ testHydrateIntegerEnumPropertyWithInvalidValue() 0 13 1
A hp$103 ➔ testHydrateTimestampPropertyWithoutValue() 0 11 1
A hp$36 ➔ testHydrateNullableStringEnumProperty() 0 11 1
A hp$141 ➔ assertInvalidValueExceptionErrorCode() 0 3 1
A hp$141 ➔ testSourcelessType() 0 5 1
nonStrictNotStringDataProvider() 0 4 ?
arrayDataProvider() 0 4 ?
A hp$114 ➔ testHydrateOptionalMyclabsEnumProperty() 0 9 1
A hp$57 ➔ testHydrateBooleanAssociationArrayPropertyWithInvalidAssociation() 0 16 1
A hp$16 ➔ testHydrateNumericProperty() 0 9 1
timestampDataProvider() 0 31 ?
A hp$116 ➔ testHydrateMyclabsEnumPropertyWithUnknownValue() 0 12 1
testInvalidObjectExceptionUnsupportedMethodParameterType() 0 19 ?
A hp$42 ➔ testHydrateArrayProperty() 0 9 1
A hp$141 ➔ strictNotStringDataProvider() 0 4 2
A hp$97 ➔ testHydrateBooleanAssociationPropertyWithInvalidAssociationValue() 0 11 1
testHydrateBooleanAssociationArrayAccessPropertyWithInvalidAssociationValue() 0 11 ?
testHydrateOptionalIntegerProperty() 0 9 ?
A hp$29 ➔ testHydrateNullableIntegerEnumProperty() 0 11 1
createHydrator() 0 8 ?
testSourcelessType() 0 5 ?
A hp$45 ➔ testHydrateArrayPropertyWithNull() 0 11 1
A hp$22 ➔ testHydrateStringProperty() 0 9 1
A hp$129 ➔ testHydrateSymfonyUuidPropertyWithInvalidValue() 0 11 1
A hp$141 ➔ integerEnumDataProvider() 0 17 2
testHydrateBooleanAssociationPropertyWithEmptyAssociation() 0 11 ?
testHydrateBooleanArrayCollectionParameterWithValidData() 0 11 ?
A hp$3 ➔ testCreateHydratorWithTypeConverters() 0 23 2
A hp$60 ➔ testHydrateArrayAccessProperty() 0 9 1
strictBooleanProvider() 0 4 ?
testHydrateIntegerPropertyWithInvalidValue() 0 12 ?
testHydrateNullableNumericProperty() 0 9 ?
A hp$11 ➔ testHydrateNullableIntegerProperty() 0 9 1
A hp$138 ➔ testDefaultValuedProperty() 0 11 1
uuidDataProvider() 0 3 ?
strictStringProvider() 0 45 ?
testHydrateStringEnumPropertyWithUnknownValue() 0 14 ?
A hp$83 ➔ testHydrateBooleanAssociationArrayAccessPropertyWithoutValue() 0 11 1
A hp$141 ➔ strictBooleanDataProvider() 0 4 2
C hp$141 ➔ runTest() 0 76 10
A hp$109 ➔ testHydrateTimezonePropertyWithInvalidValue() 0 11 1
A hp$84 ➔ testHydrateBooleanAssociationArrayAccessPropertyWithInvalidAssociation() 0 11 1
testHydrateOptionalStringEnumProperty() 0 11 ?
A hp$118 ➔ testHydrateRamseyUuidProperty() 0 9 1
testHydrateUnstantiableAssociationProperty() 0 8 ?
A hp$141 ➔ assertInvalidValueExceptionCount() 0 3 1
testHydrateTimestampPropertyWithEmptyValue() 0 11 ?
testHydrateNullableArrayAccessProperty() 0 9 ?
testStdClassWithArrayAccessProperty() 0 9 ?
testHydrateOverflowedArrayAccessProperty() 0 11 ?
A hp$38 ➔ testHydrateStringEnumPropertyWithEmptyValue() 0 13 1
A hp$134 ➔ testInvalidObjectExceptionUnsupportedMethodParameterType() 0 19 1
testHydrateNullableRamseyUuidProperty() 0 9 ?
A hp$115 ➔ testHydrateMyclabsEnumPropertyWithEmptyValue() 0 11 1
A hp$75 ➔ testHydrateTypedNullableBooleanArrayAccessProperty() 0 8 1
A hp$35 ➔ testHydrateStringEnumProperty() 0 11 1
A hp$141 ➔ emptyArrayProvider() 0 3 1
A hp$56 ➔ testHydrateBooleanAssociationArrayPropertyWithoutValue() 0 16 1
A hp$141 ➔ phpRequired() 0 4 2
A hp$43 ➔ testHydrateNullableArrayProperty() 0 9 1
testHydrateArrayPropertyWithInvalidValue() 0 11 ?
assertInvalidValueExceptionCount() 0 3 ?
A hp$87 ➔ testHydrateBooleanArrayCollectionParameterWithValidData() 0 11 1
A hp$106 ➔ testHydrateNullableTimezoneProperty() 0 9 2
testHydrateSymfonyUuidProperty() 0 9 ?
testHydrateBooleanPropertyWithoutValue() 0 12 ?
emptyArrayProvider() 0 3 ?
testHydrateAnnotatedLimitedBooleanArrayAccessProperty() 0 13 ?
A hp$105 ➔ testHydrateTimezoneProperty() 0 9 1
A hp$141 ➔ notNumberProvider() 0 6 1
A hp$127 ➔ testHydrateOptionalSymfonyUuidProperty() 0 9 2
A hp$18 ➔ testHydrateOptionalNumericProperty() 0 9 1
A hp$8 ➔ testHydrateBooleanPropertyWithInvalidValue() 0 12 1
testHydrateNullableBooleanProperty() 0 9 ?
testHydrateObjectWithInvalidJson() 0 9 ?
A hp$124 ➔ testHydrateRamseyUuidPropertyWithoutValue() 0 11 1
A hp$66 ➔ testHydrateOverflowedArrayAccessProperty() 0 11 1
testHydrateOptionalTimezoneProperty() 0 9 ?
A hp$141 ➔ strictNumberProvider() 0 11 1
strictIntegerDataProvider() 0 4 ?
testHydrateTypedLimitedBooleanArrayAccessProperty() 0 11 ?
testHydrateIntegerEnumProperty() 0 11 ?
A hp$20 ➔ testHydrateNumericPropertyWithInvalidValue() 0 12 1
strictNullProvider() 0 3 ?
A hp$134 ➔ testInvalidObjectExceptionUnsupportedFunctionParameterType() 0 14 1
A hp$140 ➔ testUnsupportedPropertyType() 0 8 1
testHydrateNullableIntegerEnumProperty() 0 11 ?
A hp$61 ➔ testHydrateNullableArrayAccessProperty() 0 9 1
testHydrateBooleanArrayProperty() 0 10 ?
testHydrateTypedBooleanArrayAccessPropertyWithInvalidElement() 0 11 ?
A hp$141 ➔ myclabsEnumDataProvider() 0 9 1
A hp$117 ➔ testHydrateMyclabsEnumPropertyWithoutValue() 0 11 1
testHydrateBooleanAssociationPropertyWithInvalidAssociationValue() 0 11 ?
testHydrateStringPropertyWithNull() 0 12 ?
nonStrictNotStringProvider() 0 6 ?
A hp$139 ➔ testUntypedProperty() 0 8 1
A hp$141 ➔ nonStrictNumberProvider() 0 30 1
testHydrateBooleanAssociationArrayAccessPropertyWithInvalidValue() 0 11 ?
testHydrateBooleanAssociationArrayPropertyWithInvalidAssociation() 0 16 ?
A hp$13 ➔ testHydrateIntegerPropertyWithEmptyValue() 0 12 1
assertInvalidValueExceptionMessage() 0 3 ?
A hp$141 ➔ assertInvalidValueExceptionTranslationDomain() 0 5 1
A hp$9 ➔ testHydrateBooleanPropertyWithoutValue() 0 12 1
A hp$134 ➔ testHydrateObjectWithNonObjectableJson() 0 9 1
notArrayDataProvider() 0 4 ?
A testIssue25() 0 7 1
testHydrateIntegerEnumPropertyWithInvalidValue() 0 13 ?
A hp$141 ➔ nonStrictIntegerDataProvider() 0 4 2
A hp$100 ➔ testHydrateOptionalTimestampProperty() 0 11 2
testHydrateArrayPropertyWithNull() 0 11 ?
A hp$55 ➔ testHydrateBooleanAssociationArrayPropertyWithInvalidValue() 0 16 1
A hp$101 ➔ testHydrateTimestampPropertyWithEmptyValue() 0 11 1
testHydrateBooleanAssociationPropertyWithNull() 0 11 ?
testHydrateNumericPropertyWithoutValue() 0 12 ?
A hp$121 ➔ testHydrateRamseyUuidPropertyWithEmptyValue() 0 11 1
A hp$88 ➔ testHydrateBooleanArrayCollectionParameterWithInvalidData() 0 13 1
A hp$141 ➔ uuidDataProvider() 0 3 1
A hp$98 ➔ testHydrateTimestampProperty() 0 10 1
A hp$80 ➔ testHydrateBooleanAssociationArrayAccessProperty() 0 8 1
testHydrateOptionalStringProperty() 0 9 ?
testHydrateNullableBooleanAssociationProperty() 0 9 ?
A hp$141 ➔ notBooleanProvider() 0 8 1
testDefaultValuedProperty() 0 11 ?
A hp$58 ➔ testHydrateBooleanAssociationArrayPropertyWithEmptyAssociationValue() 0 16 1
A hp$73 ➔ testHydrateAnnotatedOverflowedBooleanArrayAccessProperty() 0 13 1
A hp$131 ➔ testHydrateSymfonyUuidPropertyWithoutValue() 0 11 1
assertInvalidValueExceptionErrorCode() 0 3 ?
A hp$59 ➔ testHydrateBooleanAssociationArrayPropertyWithInvalidAssociationValue() 0 16 1
A hp$112 ➔ testHydrateMyclabsEnumProperty() 0 9 1
A hp$141 ➔ createHydrator() 0 8 2
A hp$133 ➔ testHydrateObjectWithInvalidJson() 0 9 1
testHydrateIntegerProperty() 0 9 ?
A hp$102 ➔ testHydrateTimestampPropertyWithInvalidValue() 0 11 1
testHydrateBooleanArrayPropertyWithInvalidElement() 0 13 ?
A hp$91 ➔ testHydrateNullableBooleanAssociationProperty() 0 9 1
testHydrateNullableTimestampProperty() 0 11 ?
testUnknownObject() 0 4 ?
A hp$33 ➔ testHydrateIntegerEnumPropertyWithUnknownValue() 0 14 1
B hp$134 ➔ testTypeFromParameter() 0 93 3
A hp$141 ➔ nonStrictNullProvider() 0 4 1
A hp$1 ➔ testStdClassWithArrayAccessProperty() 0 9 1
A hp$132 ➔ testHydrateObjectWithJson() 0 9 1
testHydrateRamseyUuidPropertyWithInvalidUuid() 0 11 ?
A hp$141 ➔ strictStringDataProvider() 0 4 2
testHydrateSymfonyUuidPropertyWithInvalidValue() 0 11 ?
testHydrateBooleanAssociationArrayAccessPropertyWithoutValue() 0 11 ?
strictNotStringProvider() 0 7 ?
A hp$141 ➔ nonStrictNullDataProvider() 0 4 2
testStaticalProperty() 0 9 ?
A hp$25 ➔ testHydrateStringPropertyWithNull() 0 12 1
testHydrateOptionalBooleanAssociationProperty() 0 9 ?
A hp$141 ➔ testSymfonyViolations() 0 18 2
A hp$122 ➔ testHydrateRamseyUuidPropertyWithInvalidValue() 0 11 1
testHydrateBooleanAssociationPropertyWithInvalidValue() 0 11 ?
A hp$68 ➔ testHydrateAnnotatedBooleanArrayAccessProperty() 0 10 1
testInvalidObjectExceptionUnsupportedFunctionParameterType() 0 14 ?
testHydrateStringPropertyWithInvalidValue() 0 12 ?
A hp$141 ➔ nonStrictIntegerProvider() 0 6 1
testHydrateIntegerEnumPropertyWithUnknownValue() 0 14 ?
A hp$120 ➔ testHydrateOptionalRamseyUuidProperty() 0 9 2
testHydrateNullableBooleanArrayProperty() 0 10 ?
testHydrateBooleanAssociationArrayAccessProperty() 0 8 ?
A hp$76 ➔ testHydrateTypedBooleanArrayAccessPropertyWithEmptyElement() 0 11 1
A hp$141 ➔ notArrayProvider() 0 7 1
testHydrateBooleanPropertyWithInvalidValue() 0 12 ?
A hp$136 ➔ testIgnoredProperty() 0 11 1
testHydrateBooleanAssociationArrayPropertyWithInvalidValue() 0 16 ?
testHydrateTimestampProperty() 0 10 ?
testCreateHydratorWithTypeConverters() 0 23 ?
testHydrateOptionalRamseyUuidProperty() 0 9 ?
testIgnoredProperty() 0 11 ?
A hp$27 ➔ testHydrateStringPropertyWithoutValue() 0 12 1
testHydrateOptionalMyclabsEnumProperty() 0 9 ?
A hp$26 ➔ testHydrateStringPropertyWithInvalidValue() 0 12 1
nonStrictBooleanDataProvider() 0 4 ?
notNumberDataProvider() 0 4 ?
A hp$141 ➔ stringEnumDataProvider() 0 13 2
testHydrateUnstantiableArrayAccessProperty() 0 8 ?

How to fix   Complexity   

Complex Class

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
2
3
declare(strict_types=1);
4
5
namespace Sunrise\Hydrator\Tests;
6
7
use DateTimeImmutable;
8
use DateTimeZone;
9
use Generator;
10
use PHPUnit\Framework\TestCase;
11
use ReflectionClass;
12
use ReflectionFunction;
13
use ReflectionIntersectionType;
0 ignored issues
show
Bug introduced by
The type ReflectionIntersectionType was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use ReflectionMethod;
15
use ReflectionNamedType;
16
use ReflectionParameter;
17
use ReflectionUnionType;
18
use Sunrise\Hydrator\Annotation\Alias;
19
use Sunrise\Hydrator\Annotation\DefaultValue;
20
use Sunrise\Hydrator\Annotation\Ignore;
21
use Sunrise\Hydrator\Annotation\Subtype;
22
use Sunrise\Hydrator\Dictionary\BuiltinType;
23
use Sunrise\Hydrator\Dictionary\ContextKey;
24
use Sunrise\Hydrator\Dictionary\ErrorCode;
25
use Sunrise\Hydrator\Dictionary\TranslationDomain;
26
use Sunrise\Hydrator\Exception\InvalidDataException;
27
use Sunrise\Hydrator\Exception\InvalidObjectException;
28
use Sunrise\Hydrator\Hydrator;
29
use Sunrise\Hydrator\HydratorInterface;
30
use Sunrise\Hydrator\Tests\Fixture\BooleanArrayCollection;
31
use Sunrise\Hydrator\Type;
32
use Sunrise\Hydrator\TypeConverter\TimestampTypeConverter;
33
use Sunrise\Hydrator\TypeConverterInterface;
34
35
use function date;
36
use function get_class;
37
use function join;
38
use function sprintf;
39
use function version_compare;
40
41
use const PHP_VERSION;
42
use const PHP_VERSION_ID;
43
44
class HydratorTest extends TestCase
45
{
46
    private ?int $invalidValueExceptionCount = null;
47
    private array $invalidValueExceptionMessage = [];
48
    private array $invalidValueExceptionPropertyPath = [];
49
    private array $invalidValueExceptionErrorCode = [];
50
    private array $invalidValueExceptionTranslationDomain = [];
51
52
    public function testIssue25(): void
53
    {
54
        $this->assertInvalidValueExceptionCount(1);
55
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
56
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
57
        $this->assertInvalidValueExceptionPropertyPath(0, 'foo');
58
        $this->createHydrator()->hydrate(Fixture\Issue25::class, []);
59
    }
60
61
    public function testStdClassWithArrayProperty(): void
62
    {
63
        $object = new class {
64
            public array $value;
65
        };
66
67
        $this->assertInvalidValueExceptionCount(0);
68
        $this->createHydrator()->hydrate($object, ['value' => (object) ['foo' => 'bar']]);
69
        $this->assertSame(['foo' => 'bar'], $object->value);
70
    }
71
72
    public function testStdClassWithArrayAccessProperty(): void
73
    {
74
        $object = new class {
75
            public Fixture\Collection $value;
76
        };
77
78
        $this->assertInvalidValueExceptionCount(0);
79
        $this->createHydrator()->hydrate($object, ['value' => (object) ['foo' => 'bar']]);
80
        $this->assertSame(['foo' => 'bar'], $object->value->elements);
81
    }
82
83
    public function testStdClassWithAssociationProperty(): void
84
    {
85
        $object = new class {
86
            public Fixture\StringAssociation $value;
87
        };
88
89
        $this->assertInvalidValueExceptionCount(0);
90
        $this->createHydrator()->hydrate($object, ['value' => (object) ['value' => 'foo']]);
91
        $this->assertSame('foo', $object->value->value);
92
    }
93
94
    public function testCreateHydratorWithTypeConverters(): void
95
    {
96
        $object = new class {
97
            public \Closure $foo;
98
        };
99
100
        $typeConverter = $this->createMock(TypeConverterInterface::class);
101
102
        $typeConverter->method('castValue')->willReturnCallback(
103
            static function ($value, Type $type, array $path, array $context): Generator {
0 ignored issues
show
Unused Code introduced by
The parameter $context is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

103
            static function ($value, Type $type, array $path, /** @scrutinizer ignore-unused */ array $context): Generator {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $path is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

103
            static function ($value, Type $type, /** @scrutinizer ignore-unused */ array $path, array $context): Generator {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
104
                if ($type->getName() === \Closure::class) {
105
                    yield static function () use ($value) {
106
                        return $value;
107
                    };
108
                }
109
            }
110
        );
111
112
        $this->createHydrator([], [$typeConverter])->hydrate($object, [
113
            'foo' => 'bar',
114
        ]);
115
116
        $this->assertSame('bar', ($object->foo)());
117
    }
118
119
    /**
120
     * @group boolean
121
     * @dataProvider strictBooleanDataProvider
122
     * @dataProvider nonStrictBooleanDataProvider
123
     */
124
    public function testHydrateBooleanProperty(array $data, bool $expected): void
125
    {
126
        $object = new class {
127
            public bool $value;
128
        };
129
130
        $this->assertInvalidValueExceptionCount(0);
131
        $this->createHydrator()->hydrate($object, $data);
132
        $this->assertSame($expected, $object->value);
133
    }
134
135
    /**
136
     * @group boolean
137
     * @dataProvider strictBooleanDataProvider
138
     * @dataProvider nonStrictBooleanDataProvider
139
     * @dataProvider strictNullDataProvider
140
     * @dataProvider nonStrictNullDataProvider
141
     */
142
    public function testHydrateNullableBooleanProperty(array $data, ?bool $expected): void
143
    {
144
        $object = new class {
145
            public ?bool $value;
146
        };
147
148
        $this->assertInvalidValueExceptionCount(0);
149
        $this->createHydrator()->hydrate($object, $data);
150
        $this->assertSame($expected, $object->value);
151
    }
152
153
    /**
154
     * @group boolean
155
     * @dataProvider strictBooleanDataProvider
156
     * @dataProvider nonStrictBooleanDataProvider
157
     * @dataProvider emptyArrayProvider
158
     */
159
    public function testHydrateOptionalBooleanProperty(array $data, bool $expected = true): void
160
    {
161
        $object = new class {
162
            public bool $value = true;
163
        };
164
165
        $this->assertInvalidValueExceptionCount(0);
166
        $this->createHydrator()->hydrate($object, $data);
167
        $this->assertSame($expected, $object->value);
168
    }
169
170
    /**
171
     * @group boolean
172
     * @dataProvider strictNullDataProvider
173
     * @dataProvider nonStrictNullDataProvider
174
     */
175
    public function testHydrateBooleanPropertyWithEmptyValue(array $data): void
176
    {
177
        $object = new class {
178
            public bool $value;
179
        };
180
181
        $this->assertInvalidValueExceptionCount(1);
182
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
183
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
184
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
185
        $this->assertInvalidValueExceptionTranslationDomain(0, TranslationDomain::HYDRATOR);
186
        $this->createHydrator()->hydrate($object, $data);
187
    }
188
189
    /**
190
     * @group boolean
191
     * @dataProvider notBooleanDataProvider
192
     */
193
    public function testHydrateBooleanPropertyWithInvalidValue(array $data): void
194
    {
195
        $object = new class {
196
            public bool $value;
197
        };
198
199
        $this->assertInvalidValueExceptionCount(1);
200
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type boolean.');
201
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_BOOLEAN);
202
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
203
        $this->assertInvalidValueExceptionTranslationDomain(0, TranslationDomain::HYDRATOR);
204
        $this->createHydrator()->hydrate($object, $data);
205
    }
206
207
    /**
208
     * @group boolean
209
     */
210
    public function testHydrateBooleanPropertyWithoutValue(): void
211
    {
212
        $object = new class {
213
            public bool $value;
214
        };
215
216
        $this->assertInvalidValueExceptionCount(1);
217
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
218
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
219
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
220
        $this->assertInvalidValueExceptionTranslationDomain(0, TranslationDomain::HYDRATOR);
221
        $this->createHydrator()->hydrate($object, []);
222
    }
223
224
    /**
225
     * @group integer
226
     * @dataProvider strictIntegerDataProvider
227
     * @dataProvider nonStrictIntegerDataProvider
228
     */
229
    public function testHydrateIntegerProperty(array $data, int $expected): void
230
    {
231
        $object = new class {
232
            public int $value;
233
        };
234
235
        $this->assertInvalidValueExceptionCount(0);
236
        $this->createHydrator()->hydrate($object, $data);
237
        $this->assertSame($expected, $object->value);
238
    }
239
240
    /**
241
     * @group integer
242
     * @dataProvider strictIntegerDataProvider
243
     * @dataProvider nonStrictIntegerDataProvider
244
     * @dataProvider strictNullDataProvider
245
     * @dataProvider nonStrictNullDataProvider
246
     */
247
    public function testHydrateNullableIntegerProperty(array $data, ?int $expected): void
248
    {
249
        $object = new class {
250
            public ?int $value;
251
        };
252
253
        $this->assertInvalidValueExceptionCount(0);
254
        $this->createHydrator()->hydrate($object, $data);
255
        $this->assertSame($expected, $object->value);
256
    }
257
258
    /**
259
     * @group integer
260
     * @dataProvider strictIntegerDataProvider
261
     * @dataProvider nonStrictIntegerDataProvider
262
     * @dataProvider emptyArrayProvider
263
     */
264
    public function testHydrateOptionalIntegerProperty(array $data, int $expected = 42): void
265
    {
266
        $object = new class {
267
            public int $value = 42;
268
        };
269
270
        $this->assertInvalidValueExceptionCount(0);
271
        $this->createHydrator()->hydrate($object, $data);
272
        $this->assertSame($expected, $object->value);
273
    }
274
275
    /**
276
     * @group integer
277
     * @dataProvider strictNullDataProvider
278
     * @dataProvider nonStrictNullDataProvider
279
     */
280
    public function testHydrateIntegerPropertyWithEmptyValue(array $data): void
281
    {
282
        $object = new class {
283
            public int $value;
284
        };
285
286
        $this->assertInvalidValueExceptionCount(1);
287
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
288
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
289
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
290
        $this->assertInvalidValueExceptionTranslationDomain(0, TranslationDomain::HYDRATOR);
291
        $this->createHydrator()->hydrate($object, $data);
292
    }
293
294
    /**
295
     * @group integer
296
     * @dataProvider notIntegerDataProvider
297
     */
298
    public function testHydrateIntegerPropertyWithInvalidValue(array $data): void
299
    {
300
        $object = new class {
301
            public int $value;
302
        };
303
304
        $this->assertInvalidValueExceptionCount(1);
305
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type integer.');
306
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_INTEGER);
307
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
308
        $this->assertInvalidValueExceptionTranslationDomain(0, TranslationDomain::HYDRATOR);
309
        $this->createHydrator()->hydrate($object, $data);
310
    }
311
312
    /**
313
     * @group integer
314
     */
315
    public function testHydrateIntegerPropertyWithoutValue(): void
316
    {
317
        $object = new class {
318
            public int $value;
319
        };
320
321
        $this->assertInvalidValueExceptionCount(1);
322
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
323
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
324
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
325
        $this->assertInvalidValueExceptionTranslationDomain(0, TranslationDomain::HYDRATOR);
326
        $this->createHydrator()->hydrate($object, []);
327
    }
328
329
    /**
330
     * @group number
331
     * @dataProvider strictNumberDataProvider
332
     * @dataProvider nonStrictNumberDataProvider
333
     */
334
    public function testHydrateNumericProperty(array $data, float $expected): void
335
    {
336
        $object = new class {
337
            public float $value;
338
        };
339
340
        $this->assertInvalidValueExceptionCount(0);
341
        $this->createHydrator()->hydrate($object, $data);
342
        $this->assertSame($expected, $object->value);
343
    }
344
345
    /**
346
     * @group number
347
     * @dataProvider strictNumberDataProvider
348
     * @dataProvider nonStrictNumberDataProvider
349
     * @dataProvider strictNullDataProvider
350
     * @dataProvider nonStrictNullDataProvider
351
     */
352
    public function testHydrateNullableNumericProperty(array $data, ?float $expected): void
353
    {
354
        $object = new class {
355
            public ?float $value;
356
        };
357
358
        $this->assertInvalidValueExceptionCount(0);
359
        $this->createHydrator()->hydrate($object, $data);
360
        $this->assertSame($expected, $object->value);
361
    }
362
363
    /**
364
     * @group number
365
     * @dataProvider strictNumberDataProvider
366
     * @dataProvider nonStrictNumberDataProvider
367
     * @dataProvider emptyArrayProvider
368
     */
369
    public function testHydrateOptionalNumericProperty(array $data, float $expected = 3.14159): void
370
    {
371
        $object = new class {
372
            public float $value = 3.14159;
373
        };
374
375
        $this->assertInvalidValueExceptionCount(0);
376
        $this->createHydrator()->hydrate($object, $data);
377
        $this->assertSame($expected, $object->value);
378
    }
379
380
    /**
381
     * @group number
382
     * @dataProvider strictNullDataProvider
383
     * @dataProvider nonStrictNullDataProvider
384
     */
385
    public function testHydrateNumericPropertyWithEmptyValue(array $data): void
386
    {
387
        $object = new class {
388
            public float $value;
389
        };
390
391
        $this->assertInvalidValueExceptionCount(1);
392
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
393
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
394
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
395
        $this->assertInvalidValueExceptionTranslationDomain(0, TranslationDomain::HYDRATOR);
396
        $this->createHydrator()->hydrate($object, $data);
397
    }
398
399
    /**
400
     * @group number
401
     * @dataProvider notNumberDataProvider
402
     */
403
    public function testHydrateNumericPropertyWithInvalidValue(array $data): void
404
    {
405
        $object = new class {
406
            public float $value;
407
        };
408
409
        $this->assertInvalidValueExceptionCount(1);
410
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type number.');
411
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_NUMBER);
412
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
413
        $this->assertInvalidValueExceptionTranslationDomain(0, TranslationDomain::HYDRATOR);
414
        $this->createHydrator()->hydrate($object, $data);
415
    }
416
417
    /**
418
     * @group number
419
     */
420
    public function testHydrateNumericPropertyWithoutValue(): void
421
    {
422
        $object = new class {
423
            public float $value;
424
        };
425
426
        $this->assertInvalidValueExceptionCount(1);
427
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
428
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
429
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
430
        $this->assertInvalidValueExceptionTranslationDomain(0, TranslationDomain::HYDRATOR);
431
        $this->createHydrator()->hydrate($object, []);
432
    }
433
434
    /**
435
     * @group string
436
     * @dataProvider strictStringDataProvider
437
     * @dataProvider nonStrictStringDataProvider
438
     */
439
    public function testHydrateStringProperty(array $data, string $expected): void
440
    {
441
        $object = new class {
442
            public string $value;
443
        };
444
445
        $this->assertInvalidValueExceptionCount(0);
446
        $this->createHydrator()->hydrate($object, $data);
447
        $this->assertSame($expected, $object->value);
448
    }
449
450
    /**
451
     * @group string
452
     * @dataProvider strictStringDataProvider
453
     * @dataProvider nonStrictStringDataProvider
454
     * @dataProvider strictNullDataProvider
455
     */
456
    public function testHydrateNullableStringProperty(array $data, ?string $expected): void
457
    {
458
        $object = new class {
459
            public ?string $value;
460
        };
461
462
        $this->assertInvalidValueExceptionCount(0);
463
        $this->createHydrator()->hydrate($object, $data);
464
        $this->assertSame($expected, $object->value);
465
    }
466
467
    /**
468
     * @group string
469
     * @dataProvider strictStringDataProvider
470
     * @dataProvider nonStrictStringDataProvider
471
     * @dataProvider emptyArrayProvider
472
     */
473
    public function testHydrateOptionalStringProperty(array $data, string $expected = 'default'): void
474
    {
475
        $object = new class {
476
            public string $value = 'default';
477
        };
478
479
        $this->assertInvalidValueExceptionCount(0);
480
        $this->createHydrator()->hydrate($object, $data);
481
        $this->assertSame($expected, $object->value);
482
    }
483
484
    /**
485
     * @group string
486
     * @dataProvider strictNullDataProvider
487
     */
488
    public function testHydrateStringPropertyWithNull(array $data): void
489
    {
490
        $object = new class {
491
            public string $value;
492
        };
493
494
        $this->assertInvalidValueExceptionCount(1);
495
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
496
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
497
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
498
        $this->assertInvalidValueExceptionTranslationDomain(0, TranslationDomain::HYDRATOR);
499
        $this->createHydrator()->hydrate($object, $data);
500
    }
501
502
    /**
503
     * @group string
504
     * @dataProvider nonStrictNotStringDataProvider
505
     */
506
    public function testHydrateStringPropertyWithInvalidValue(array $data): void
507
    {
508
        $object = new class {
509
            public string $value;
510
        };
511
512
        $this->assertInvalidValueExceptionCount(1);
513
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type string.');
514
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_STRING);
515
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
516
        $this->assertInvalidValueExceptionTranslationDomain(0, TranslationDomain::HYDRATOR);
517
        $this->createHydrator()->hydrate($object, $data);
518
    }
519
520
    /**
521
     * @group string
522
     */
523
    public function testHydrateStringPropertyWithoutValue(): void
524
    {
525
        $object = new class {
526
            public string $value;
527
        };
528
529
        $this->assertInvalidValueExceptionCount(1);
530
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
531
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
532
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
533
        $this->assertInvalidValueExceptionTranslationDomain(0, TranslationDomain::HYDRATOR);
534
        $this->createHydrator()->hydrate($object, []);
535
    }
536
537
    /**
538
     * @group enum
539
     * @group integer-enum
540
     * @dataProvider integerEnumDataProvider
541
     */
542
    public function testHydrateIntegerEnumProperty(array $data, $expected): void
543
    {
544
        $this->phpRequired('8.1');
545
546
        $object = new class {
547
            public Fixture\IntegerEnum $value;
548
        };
549
550
        $this->assertInvalidValueExceptionCount(0);
551
        $this->createHydrator()->hydrate($object, $data);
552
        $this->assertSame($expected, $object->value);
553
    }
554
555
    /**
556
     * @group enum
557
     * @group integer-enum
558
     * @dataProvider integerEnumDataProvider
559
     * @dataProvider strictNullDataProvider
560
     * @dataProvider nonStrictNullDataProvider
561
     */
562
    public function testHydrateNullableIntegerEnumProperty(array $data, $expected): void
563
    {
564
        $this->phpRequired('8.1');
565
566
        $object = new class {
567
            public ?Fixture\IntegerEnum $value;
568
        };
569
570
        $this->assertInvalidValueExceptionCount(0);
571
        $this->createHydrator()->hydrate($object, $data);
572
        $this->assertSame($expected, $object->value);
573
    }
574
575
    /**
576
     * @group enum
577
     * @group integer-enum
578
     * @dataProvider integerEnumDataProvider
579
     * @dataProvider emptyArrayProvider
580
     */
581
    public function testHydrateOptionalIntegerEnumProperty(array $data, $expected = null): void
582
    {
583
        $this->phpRequired('8.1');
584
585
        $object = new class {
586
            public ?Fixture\IntegerEnum $value = null;
587
        };
588
589
        $this->assertInvalidValueExceptionCount(0);
590
        $this->createHydrator()->hydrate($object, $data);
591
        $this->assertSame($expected, $object->value);
592
    }
593
594
    /**
595
     * @group enum
596
     * @group integer-enum
597
     * @dataProvider strictNullDataProvider
598
     * @dataProvider nonStrictNullDataProvider
599
     */
600
    public function testHydrateIntegerEnumPropertyWithEmptyValue(array $data): void
601
    {
602
        $this->phpRequired('8.1');
603
604
        $object = new class {
605
            public Fixture\IntegerEnum $value;
606
        };
607
608
        $this->assertInvalidValueExceptionCount(1);
609
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
610
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
611
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
612
        $this->createHydrator()->hydrate($object, $data);
613
    }
614
615
    /**
616
     * @group enum
617
     * @group integer-enum
618
     * @dataProvider notIntegerDataProvider
619
     */
620
    public function testHydrateIntegerEnumPropertyWithInvalidValue(array $data): void
621
    {
622
        $this->phpRequired('8.1');
623
624
        $object = new class {
625
            public Fixture\IntegerEnum $value;
626
        };
627
628
        $this->assertInvalidValueExceptionCount(1);
629
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type integer.');
630
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_INTEGER);
631
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
632
        $this->createHydrator()->hydrate($object, $data);
633
    }
634
635
    /**
636
     * @group enum
637
     * @group integer-enum
638
     */
639
    public function testHydrateIntegerEnumPropertyWithUnknownValue(): void
640
    {
641
        $this->phpRequired('8.1');
642
643
        $object = new class {
644
            public Fixture\IntegerEnum $value;
645
        };
646
647
        $this->assertInvalidValueExceptionCount(1);
648
        // phpcs:ignore Generic.Files.LineLength
649
        $this->assertInvalidValueExceptionMessage(0, 'This value is not a valid choice; expected values: ' . join(', ', Fixture\IntegerEnum::values()) . '.');
650
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::INVALID_CHOICE);
651
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
652
        $this->createHydrator()->hydrate($object, ['value' => 42]);
653
    }
654
655
    /**
656
     * @group enum
657
     * @group integer-enum
658
     */
659
    public function testHydrateIntegerEnumPropertyWithoutValue(): void
660
    {
661
        $this->phpRequired('8.1');
662
663
        $object = new class {
664
            public Fixture\IntegerEnum $value;
665
        };
666
667
        $this->assertInvalidValueExceptionCount(1);
668
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
669
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
670
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
671
        $this->createHydrator()->hydrate($object, []);
672
    }
673
674
    /**
675
     * @group enum
676
     * @group string-enum
677
     * @dataProvider stringEnumDataProvider
678
     */
679
    public function testHydrateStringEnumProperty(array $data, $expected): void
680
    {
681
        $this->phpRequired('8.1');
682
683
        $object = new class {
684
            public Fixture\StringEnum $value;
685
        };
686
687
        $this->assertInvalidValueExceptionCount(0);
688
        $this->createHydrator()->hydrate($object, $data);
689
        $this->assertSame($expected, $object->value);
690
    }
691
692
    /**
693
     * @group enum
694
     * @group string-enum
695
     * @dataProvider stringEnumDataProvider
696
     * @dataProvider strictNullDataProvider
697
     * @dataProvider nonStrictNullDataProvider
698
     */
699
    public function testHydrateNullableStringEnumProperty(array $data, $expected): void
700
    {
701
        $this->phpRequired('8.1');
702
703
        $object = new class {
704
            public ?Fixture\StringEnum $value;
705
        };
706
707
        $this->assertInvalidValueExceptionCount(0);
708
        $this->createHydrator()->hydrate($object, $data);
709
        $this->assertSame($expected, $object->value);
710
    }
711
712
    /**
713
     * @group enum
714
     * @group string-enum
715
     * @dataProvider stringEnumDataProvider
716
     * @dataProvider emptyArrayProvider
717
     */
718
    public function testHydrateOptionalStringEnumProperty(array $data, $expected = null): void
719
    {
720
        $this->phpRequired('8.1');
721
722
        $object = new class {
723
            public ?Fixture\StringEnum $value = null;
724
        };
725
726
        $this->assertInvalidValueExceptionCount(0);
727
        $this->createHydrator()->hydrate($object, $data);
728
        $this->assertSame($expected, $object->value);
729
    }
730
731
    /**
732
     * @group enum
733
     * @group string-enum
734
     * @dataProvider strictNullDataProvider
735
     * @dataProvider nonStrictNullDataProvider
736
     */
737
    public function testHydrateStringEnumPropertyWithEmptyValue(array $data): void
738
    {
739
        $this->phpRequired('8.1');
740
741
        $object = new class {
742
            public Fixture\StringEnum $value;
743
        };
744
745
        $this->assertInvalidValueExceptionCount(1);
746
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
747
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
748
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
749
        $this->createHydrator()->hydrate($object, $data);
750
    }
751
752
    /**
753
     * @group enum
754
     * @group string-enum
755
     * @dataProvider strictNotStringDataProvider
756
     */
757
    public function testHydrateStringEnumPropertyWithInvalidValue(array $data): void
758
    {
759
        $this->phpRequired('8.1');
760
761
        $object = new class {
762
            public Fixture\StringEnum $value;
763
        };
764
765
        $this->assertInvalidValueExceptionCount(1);
766
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type string.');
767
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_STRING);
768
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
769
        $this->createHydrator()->hydrate($object, $data);
770
    }
771
772
    /**
773
     * @group enum
774
     * @group string-enum
775
     */
776
    public function testHydrateStringEnumPropertyWithUnknownValue(): void
777
    {
778
        $this->phpRequired('8.1');
779
780
        $object = new class {
781
            public Fixture\StringEnum $value;
782
        };
783
784
        $this->assertInvalidValueExceptionCount(1);
785
        // phpcs:ignore Generic.Files.LineLength
786
        $this->assertInvalidValueExceptionMessage(0, 'This value is not a valid choice; expected values: ' . join(', ', Fixture\StringEnum::values()) . '.');
787
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::INVALID_CHOICE);
788
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
789
        $this->createHydrator()->hydrate($object, ['value' => 'foo']);
790
    }
791
792
    /**
793
     * @group enum
794
     * @group string-enum
795
     */
796
    public function testHydrateStringEnumPropertyWithoutValue(): void
797
    {
798
        $this->phpRequired('8.1');
799
800
        $object = new class {
801
            public Fixture\StringEnum $value;
802
        };
803
804
        $this->assertInvalidValueExceptionCount(1);
805
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
806
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
807
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
808
        $this->createHydrator()->hydrate($object, []);
809
    }
810
811
    /**
812
     * @group array
813
     * @dataProvider arrayDataProvider
814
     */
815
    public function testHydrateArrayProperty(array $data, array $expected): void
816
    {
817
        $object = new class {
818
            public array $value;
819
        };
820
821
        $this->assertInvalidValueExceptionCount(0);
822
        $this->createHydrator()->hydrate($object, $data);
823
        $this->assertSame($expected, $object->value);
824
    }
825
826
    /**
827
     * @group array
828
     * @dataProvider arrayDataProvider
829
     * @dataProvider strictNullDataProvider
830
     */
831
    public function testHydrateNullableArrayProperty(array $data, ?array $expected): void
832
    {
833
        $object = new class {
834
            public ?array $value;
835
        };
836
837
        $this->assertInvalidValueExceptionCount(0);
838
        $this->createHydrator()->hydrate($object, $data);
839
        $this->assertSame($expected, $object->value);
840
    }
841
842
    /**
843
     * @group array
844
     * @dataProvider arrayDataProvider
845
     * @dataProvider emptyArrayProvider
846
     */
847
    public function testHydrateOptionalArrayProperty(array $data, array $expected = []): void
848
    {
849
        $object = new class {
850
            public array $value = [];
851
        };
852
853
        $this->assertInvalidValueExceptionCount(0);
854
        $this->createHydrator()->hydrate($object, $data);
855
        $this->assertSame($expected, $object->value);
856
    }
857
858
    /**
859
     * @group array
860
     * @dataProvider strictNullDataProvider
861
     */
862
    public function testHydrateArrayPropertyWithNull(array $data): void
863
    {
864
        $object = new class {
865
            public array $value;
866
        };
867
868
        $this->assertInvalidValueExceptionCount(1);
869
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
870
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
871
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
872
        $this->createHydrator()->hydrate($object, $data);
873
    }
874
875
    /**
876
     * @group array
877
     * @dataProvider notArrayDataProvider
878
     */
879
    public function testHydrateArrayPropertyWithInvalidValue(array $data): void
880
    {
881
        $object = new class {
882
            public array $value;
883
        };
884
885
        $this->assertInvalidValueExceptionCount(1);
886
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type array.');
887
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_ARRAY);
888
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
889
        $this->createHydrator()->hydrate($object, $data);
890
    }
891
892
    /**
893
     * @group array
894
     */
895
    public function testHydrateArrayPropertyWithoutValue(): void
896
    {
897
        $object = new class {
898
            public array $value;
899
        };
900
901
        $this->assertInvalidValueExceptionCount(1);
902
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
903
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
904
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
905
        $this->createHydrator()->hydrate($object, []);
906
    }
907
908
    /**
909
     * @group array
910
     * @group boolean-array
911
     * @dataProvider strictBooleanProvider
912
     * @dataProvider nonStrictBooleanProvider
913
     */
914
    public function testHydrateBooleanArrayProperty($element, bool $expected): void
915
    {
916
        $object = new class {
917
            /** @Subtype(BuiltinType::BOOL) */
918
            #[Subtype(BuiltinType::BOOL)]
919
            public array $value;
920
        };
921
922
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
923
        $this->assertSame([$expected], $object->value);
924
    }
925
926
    /**
927
     * @group array
928
     * @group boolean-array
929
     * @dataProvider strictBooleanProvider
930
     * @dataProvider nonStrictBooleanProvider
931
     * @dataProvider strictNullProvider
932
     * @dataProvider nonStrictNullProvider
933
     */
934
    public function testHydrateNullableBooleanArrayProperty($element, ?bool $expected): void
935
    {
936
        $object = new class {
937
            /** @Subtype(BuiltinType::BOOL, allowsNull=true) */
938
            #[Subtype(BuiltinType::BOOL, allowsNull: true)]
939
            public array $value;
940
        };
941
942
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
943
        $this->assertSame([$expected], $object->value);
944
    }
945
946
    /**
947
     * @group array
948
     * @group boolean-array
949
     * @dataProvider strictNullProvider
950
     * @dataProvider nonStrictNullProvider
951
     */
952
    public function testHydrateBooleanArrayPropertyWithEmptyElement($element): void
953
    {
954
        $object = new class {
955
            /** @Subtype(BuiltinType::BOOL) */
956
            #[Subtype(BuiltinType::BOOL)]
957
            public array $value;
958
        };
959
960
        $this->assertInvalidValueExceptionCount(1);
961
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
962
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
963
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0');
964
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
965
    }
966
967
    /**
968
     * @group array
969
     * @group boolean-array
970
     * @dataProvider notBooleanProvider
971
     */
972
    public function testHydrateBooleanArrayPropertyWithInvalidElement($element): void
973
    {
974
        $object = new class {
975
            /** @Subtype(BuiltinType::BOOL) */
976
            #[Subtype(BuiltinType::BOOL)]
977
            public array $value;
978
        };
979
980
        $this->assertInvalidValueExceptionCount(1);
981
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type boolean.');
982
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_BOOLEAN);
983
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0');
984
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
985
    }
986
987
    /**
988
     * @group array
989
     * @group boolean-array
990
     * @dataProvider strictBooleanProvider
991
     * @dataProvider nonStrictBooleanProvider
992
     */
993
    public function testHydrateLimitedBooleanArrayProperty($element): void
994
    {
995
        $object = new class {
996
            /** @Subtype(BuiltinType::BOOL, limit=1) */
997
            #[Subtype(BuiltinType::BOOL, limit: 1)]
998
            public array $value;
999
        };
1000
1001
        $this->assertInvalidValueExceptionCount(1);
1002
        $this->assertInvalidValueExceptionMessage(0, 'This value is limited to 1 elements.');
1003
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::ARRAY_OVERFLOW);
1004
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1005
        $this->createHydrator()->hydrate($object, ['value' => [true, $element]]);
1006
    }
1007
1008
    /**
1009
     * @group array
1010
     * @group boolean-association-array
1011
     * @dataProvider strictBooleanDataProvider
1012
     * @dataProvider nonStrictBooleanDataProvider
1013
     */
1014
    public function testHydrateBooleanAssociationArrayProperty(array $data, bool $expected): void
1015
    {
1016
        $object = new class {
1017
            /**
1018
             * @Subtype(\Sunrise\Hydrator\Tests\Fixture\BooleanAssociation::class)
1019
             * @var non-empty-list<Fixture\BooleanAssociation>
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-list<Fixture\BooleanAssociation> at position 0 could not be parsed: Unknown type name 'non-empty-list' at position 0 in non-empty-list<Fixture\BooleanAssociation>.
Loading history...
1020
             */
1021
            #[Subtype(Fixture\BooleanAssociation::class)]
1022
            public array $value;
1023
        };
1024
1025
        $this->createHydrator()->hydrate($object, ['value' => [$data]]);
1026
        $this->assertSame($expected, $object->value[0]->value);
1027
    }
1028
1029
    /**
1030
     * @group array
1031
     * @group boolean-association-array
1032
     * @dataProvider strictNullDataProvider
1033
     */
1034
    public function testHydrateBooleanAssociationArrayPropertyWithNull(array $data): void
1035
    {
1036
        $object = new class {
1037
            /**
1038
             * @Subtype(\Sunrise\Hydrator\Tests\Fixture\BooleanAssociation::class)
1039
             * @var non-empty-list<Fixture\BooleanAssociation>
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-list<Fixture\BooleanAssociation> at position 0 could not be parsed: Unknown type name 'non-empty-list' at position 0 in non-empty-list<Fixture\BooleanAssociation>.
Loading history...
1040
             */
1041
            #[Subtype(Fixture\BooleanAssociation::class)]
1042
            public array $value;
1043
        };
1044
1045
        $this->assertInvalidValueExceptionCount(1);
1046
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
1047
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
1048
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1049
        $this->createHydrator()->hydrate($object, $data);
1050
    }
1051
1052
    /**
1053
     * @group array
1054
     * @group boolean-association-array
1055
     * @dataProvider notArrayDataProvider
1056
     */
1057
    public function testHydrateBooleanAssociationArrayPropertyWithInvalidValue(array $data): void
1058
    {
1059
        $object = new class {
1060
            /**
1061
             * @Subtype(\Sunrise\Hydrator\Tests\Fixture\BooleanAssociation::class)
1062
             * @var non-empty-list<Fixture\BooleanAssociation>
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-list<Fixture\BooleanAssociation> at position 0 could not be parsed: Unknown type name 'non-empty-list' at position 0 in non-empty-list<Fixture\BooleanAssociation>.
Loading history...
1063
             */
1064
            #[Subtype(Fixture\BooleanAssociation::class)]
1065
            public array $value;
1066
        };
1067
1068
        $this->assertInvalidValueExceptionCount(1);
1069
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type array.');
1070
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_ARRAY);
1071
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1072
        $this->createHydrator()->hydrate($object, $data);
1073
    }
1074
1075
    /**
1076
     * @group array
1077
     * @group boolean-association-array
1078
     */
1079
    public function testHydrateBooleanAssociationArrayPropertyWithoutValue(): void
1080
    {
1081
        $object = new class {
1082
            /**
1083
             * @Subtype(\Sunrise\Hydrator\Tests\Fixture\BooleanAssociation::class)
1084
             * @var non-empty-list<Fixture\BooleanAssociation>
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-list<Fixture\BooleanAssociation> at position 0 could not be parsed: Unknown type name 'non-empty-list' at position 0 in non-empty-list<Fixture\BooleanAssociation>.
Loading history...
1085
             */
1086
            #[Subtype(Fixture\BooleanAssociation::class)]
1087
            public array $value;
1088
        };
1089
1090
        $this->assertInvalidValueExceptionCount(1);
1091
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
1092
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
1093
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1094
        $this->createHydrator()->hydrate($object, []);
1095
    }
1096
1097
    /**
1098
     * @group array
1099
     * @group boolean-association-array
1100
     * @dataProvider notArrayProvider
1101
     */
1102
    public function testHydrateBooleanAssociationArrayPropertyWithInvalidAssociation($element): void
1103
    {
1104
        $object = new class {
1105
            /**
1106
             * @Subtype(\Sunrise\Hydrator\Tests\Fixture\BooleanAssociation::class)
1107
             * @var non-empty-list<Fixture\BooleanAssociation>
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-list<Fixture\BooleanAssociation> at position 0 could not be parsed: Unknown type name 'non-empty-list' at position 0 in non-empty-list<Fixture\BooleanAssociation>.
Loading history...
1108
             */
1109
            #[Subtype(Fixture\BooleanAssociation::class)]
1110
            public array $value;
1111
        };
1112
1113
        $this->assertInvalidValueExceptionCount(1);
1114
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type array.');
1115
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_ARRAY);
1116
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0');
1117
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
1118
    }
1119
1120
    /**
1121
     * @group array
1122
     * @group boolean-association-array
1123
     * @dataProvider strictNullDataProvider
1124
     * @dataProvider nonStrictNullDataProvider
1125
     */
1126
    public function testHydrateBooleanAssociationArrayPropertyWithEmptyAssociationValue(array $data): void
1127
    {
1128
        $object = new class {
1129
            /**
1130
             * @Subtype(\Sunrise\Hydrator\Tests\Fixture\BooleanAssociation::class)
1131
             * @var non-empty-list<Fixture\BooleanAssociation>
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-list<Fixture\BooleanAssociation> at position 0 could not be parsed: Unknown type name 'non-empty-list' at position 0 in non-empty-list<Fixture\BooleanAssociation>.
Loading history...
1132
             */
1133
            #[Subtype(Fixture\BooleanAssociation::class)]
1134
            public array $value;
1135
        };
1136
1137
        $this->assertInvalidValueExceptionCount(1);
1138
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
1139
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
1140
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0.value');
1141
        $this->createHydrator()->hydrate($object, ['value' => [$data]]);
1142
    }
1143
1144
    /**
1145
     * @group array
1146
     * @group boolean-association-array
1147
     * @dataProvider notBooleanDataProvider
1148
     */
1149
    public function testHydrateBooleanAssociationArrayPropertyWithInvalidAssociationValue(array $data): void
1150
    {
1151
        $object = new class {
1152
            /**
1153
             * @Subtype(\Sunrise\Hydrator\Tests\Fixture\BooleanAssociation::class)
1154
             * @var non-empty-list<Fixture\BooleanAssociation>
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-list<Fixture\BooleanAssociation> at position 0 could not be parsed: Unknown type name 'non-empty-list' at position 0 in non-empty-list<Fixture\BooleanAssociation>.
Loading history...
1155
             */
1156
            #[Subtype(Fixture\BooleanAssociation::class)]
1157
            public array $value;
1158
        };
1159
1160
        $this->assertInvalidValueExceptionCount(1);
1161
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type boolean.');
1162
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_BOOLEAN);
1163
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0.value');
1164
        $this->createHydrator()->hydrate($object, ['value' => [$data]]);
1165
    }
1166
1167
    /**
1168
     * @group array-access
1169
     * @dataProvider arrayDataProvider
1170
     */
1171
    public function testHydrateArrayAccessProperty(array $data, array $expected): void
1172
    {
1173
        $object = new class {
1174
            public Fixture\Collection $value;
1175
        };
1176
1177
        $this->assertInvalidValueExceptionCount(0);
1178
        $this->createHydrator()->hydrate($object, $data);
1179
        $this->assertSame($expected, $object->value->elements);
1180
    }
1181
1182
    /**
1183
     * @group array-access
1184
     * @dataProvider arrayDataProvider
1185
     * @dataProvider strictNullDataProvider
1186
     */
1187
    public function testHydrateNullableArrayAccessProperty(array $data, ?array $expected): void
1188
    {
1189
        $object = new class {
1190
            public ?Fixture\Collection $value;
1191
        };
1192
1193
        $this->assertInvalidValueExceptionCount(0);
1194
        $this->createHydrator()->hydrate($object, $data);
1195
        $this->assertSame($expected, $object->value->elements ?? null);
1196
    }
1197
1198
    /**
1199
     * @group array-access
1200
     * @dataProvider arrayDataProvider
1201
     * @dataProvider emptyArrayProvider
1202
     */
1203
    public function testHydrateOptionalArrayAccessProperty(array $data, array $expected = []): void
1204
    {
1205
        $object = new class {
1206
            public ?Fixture\Collection $value = null;
1207
        };
1208
1209
        $this->assertInvalidValueExceptionCount(0);
1210
        $this->createHydrator()->hydrate($object, $data);
1211
        $this->assertSame($expected, $object->value->elements ?? []);
1212
    }
1213
1214
    /**
1215
     * @group array-access
1216
     * @dataProvider strictNullDataProvider
1217
     */
1218
    public function testHydrateArrayAccessPropertyWithNull(array $data): void
1219
    {
1220
        $object = new class {
1221
            public Fixture\Collection $value;
1222
        };
1223
1224
        $this->assertInvalidValueExceptionCount(1);
1225
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
1226
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
1227
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1228
        $this->createHydrator()->hydrate($object, $data);
1229
    }
1230
1231
    /**
1232
     * @group array-access
1233
     * @dataProvider notArrayDataProvider
1234
     */
1235
    public function testHydrateArrayAccessPropertyWithInvalidValue(array $data): void
1236
    {
1237
        $object = new class {
1238
            public Fixture\Collection $value;
1239
        };
1240
1241
        $this->assertInvalidValueExceptionCount(1);
1242
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type array.');
1243
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_ARRAY);
1244
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1245
        $this->createHydrator()->hydrate($object, $data);
1246
    }
1247
1248
    /**
1249
     * @group array-access
1250
     */
1251
    public function testHydrateArrayAccessPropertyWithoutValue(): void
1252
    {
1253
        $object = new class {
1254
            public Fixture\Collection $value;
1255
        };
1256
1257
        $this->assertInvalidValueExceptionCount(1);
1258
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
1259
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
1260
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1261
        $this->createHydrator()->hydrate($object, []);
1262
    }
1263
1264
    /**
1265
     * @group array-access
1266
     */
1267
    public function testHydrateOverflowedArrayAccessProperty(): void
1268
    {
1269
        $object = new class {
1270
            public Fixture\LimitedCollection $value;
1271
        };
1272
1273
        $this->assertInvalidValueExceptionCount(1);
1274
        $this->assertInvalidValueExceptionMessage(0, 'This value is limited to 1 elements.');
1275
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::ARRAY_OVERFLOW);
1276
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1277
        $this->createHydrator()->hydrate($object, ['value' => ['foo', 'bar']]);
1278
    }
1279
1280
    /**
1281
     * @group array-access
1282
     */
1283
    public function testHydrateUnstantiableArrayAccessProperty(): void
1284
    {
1285
        $object = new class {
1286
            public Fixture\UnstantiableCollection $value;
1287
        };
1288
1289
        $this->expectException(InvalidObjectException::class);
1290
        $this->createHydrator()->hydrate($object, ['value' => []]);
1291
    }
1292
1293
    /**
1294
     * @group array-access
1295
     * @group annotated-boolean-array-access
1296
     * @dataProvider strictBooleanProvider
1297
     * @dataProvider nonStrictBooleanProvider
1298
     */
1299
    public function testHydrateAnnotatedBooleanArrayAccessProperty($element, bool $expected): void
1300
    {
1301
        $object = new class {
1302
            /** @Subtype(BuiltinType::BOOL) */
1303
            #[Subtype(BuiltinType::BOOL)]
1304
            public Fixture\Collection $value;
1305
        };
1306
1307
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
1308
        $this->assertSame([$expected], $object->value->elements);
1309
    }
1310
1311
    /**
1312
     * @group array-access
1313
     * @group annotated-boolean-array-access
1314
     * @dataProvider strictBooleanProvider
1315
     * @dataProvider nonStrictBooleanProvider
1316
     * @dataProvider strictNullProvider
1317
     * @dataProvider nonStrictNullProvider
1318
     */
1319
    public function testHydrateAnnotatedNullableBooleanArrayAccessProperty($element, ?bool $expected): void
1320
    {
1321
        $object = new class {
1322
            /** @Subtype(BuiltinType::BOOL, allowsNull=true) */
1323
            #[Subtype(BuiltinType::BOOL, allowsNull: true)]
1324
            public Fixture\Collection $value;
1325
        };
1326
1327
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
1328
        $this->assertSame([$expected], $object->value->elements);
1329
    }
1330
1331
    /**
1332
     * @group array-access
1333
     * @group annotated-boolean-array-access
1334
     * @dataProvider strictNullProvider
1335
     * @dataProvider nonStrictNullProvider
1336
     */
1337
    public function testHydrateAnnotatedBooleanArrayAccessPropertyWithEmptyElement($element): void
1338
    {
1339
        $object = new class {
1340
            /** @Subtype(BuiltinType::BOOL) */
1341
            #[Subtype(BuiltinType::BOOL)]
1342
            public Fixture\Collection $value;
1343
        };
1344
1345
        $this->assertInvalidValueExceptionCount(1);
1346
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
1347
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
1348
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0');
1349
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
1350
    }
1351
1352
    /**
1353
     * @group array-access
1354
     * @group annotated-boolean-array-access
1355
     * @dataProvider notBooleanProvider
1356
     */
1357
    public function testHydrateAnnotatedBooleanArrayAccessPropertyWithInvalidElement($element): void
1358
    {
1359
        $object = new class {
1360
            /** @Subtype(BuiltinType::BOOL) */
1361
            #[Subtype(BuiltinType::BOOL)]
1362
            public Fixture\Collection $value;
1363
        };
1364
1365
        $this->assertInvalidValueExceptionCount(1);
1366
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type boolean.');
1367
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_BOOLEAN);
1368
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0');
1369
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
1370
    }
1371
1372
    /**
1373
     * @group array-access
1374
     * @group annotated-boolean-array-access
1375
     * @dataProvider strictBooleanProvider
1376
     * @dataProvider nonStrictBooleanProvider
1377
     */
1378
    public function testHydrateAnnotatedLimitedBooleanArrayAccessProperty($element): void
1379
    {
1380
        $object = new class {
1381
            /** @Subtype(BuiltinType::BOOL, limit=1) */
1382
            #[Subtype(BuiltinType::BOOL, limit: 1)]
1383
            public Fixture\Collection $value;
1384
        };
1385
1386
        $this->assertInvalidValueExceptionCount(1);
1387
        $this->assertInvalidValueExceptionMessage(0, 'This value is limited to 1 elements.');
1388
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::ARRAY_OVERFLOW);
1389
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1390
        $this->createHydrator()->hydrate($object, ['value' => [true, $element]]);
1391
    }
1392
1393
    /**
1394
     * @group array-access
1395
     * @group annotated-boolean-array-access
1396
     * @dataProvider strictBooleanProvider
1397
     * @dataProvider nonStrictBooleanProvider
1398
     */
1399
    public function testHydrateAnnotatedOverflowedBooleanArrayAccessProperty($element): void
1400
    {
1401
        $object = new class {
1402
            /** @Subtype(BuiltinType::BOOL) */
1403
            #[Subtype(BuiltinType::BOOL)]
1404
            public Fixture\LimitedCollection $value;
1405
        };
1406
1407
        $this->assertInvalidValueExceptionCount(1);
1408
        $this->assertInvalidValueExceptionMessage(0, 'This value is limited to 1 elements.');
1409
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::ARRAY_OVERFLOW);
1410
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1411
        $this->createHydrator()->hydrate($object, ['value' => [true, $element]]);
1412
    }
1413
1414
    /**
1415
     * @group array-access
1416
     * @group typed-boolean-array-access
1417
     * @dataProvider strictBooleanProvider
1418
     * @dataProvider nonStrictBooleanProvider
1419
     */
1420
    public function testHydrateTypedBooleanArrayAccessProperty($element, bool $expected): void
1421
    {
1422
        $object = new class {
1423
            public Fixture\BooleanCollection $value;
1424
        };
1425
1426
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
1427
        $this->assertSame([$expected], $object->value->elements);
1428
    }
1429
1430
    /**
1431
     * @group array-access
1432
     * @group typed-boolean-array-access
1433
     * @dataProvider strictBooleanProvider
1434
     * @dataProvider nonStrictBooleanProvider
1435
     * @dataProvider strictNullProvider
1436
     * @dataProvider nonStrictNullProvider
1437
     */
1438
    public function testHydrateTypedNullableBooleanArrayAccessProperty($element, ?bool $expected): void
1439
    {
1440
        $object = new class {
1441
            public Fixture\NullableBooleanCollection $value;
1442
        };
1443
1444
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
1445
        $this->assertSame([$expected], $object->value->elements);
1446
    }
1447
1448
    /**
1449
     * @group array-access
1450
     * @group typed-boolean-array-access
1451
     * @dataProvider strictNullProvider
1452
     * @dataProvider nonStrictNullProvider
1453
     */
1454
    public function testHydrateTypedBooleanArrayAccessPropertyWithEmptyElement($element): void
1455
    {
1456
        $object = new class {
1457
            public Fixture\BooleanCollection $value;
1458
        };
1459
1460
        $this->assertInvalidValueExceptionCount(1);
1461
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
1462
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
1463
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0');
1464
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
1465
    }
1466
1467
    /**
1468
     * @group array-access
1469
     * @group typed-boolean-array-access
1470
     * @dataProvider notBooleanProvider
1471
     */
1472
    public function testHydrateTypedBooleanArrayAccessPropertyWithInvalidElement($element): void
1473
    {
1474
        $object = new class {
1475
            public Fixture\BooleanCollection $value;
1476
        };
1477
1478
        $this->assertInvalidValueExceptionCount(1);
1479
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type boolean.');
1480
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_BOOLEAN);
1481
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0');
1482
        $this->createHydrator()->hydrate($object, ['value' => [$element]]);
1483
    }
1484
1485
    /**
1486
     * @group array-access
1487
     * @group typed-boolean-array-access
1488
     * @dataProvider strictBooleanProvider
1489
     * @dataProvider nonStrictBooleanProvider
1490
     */
1491
    public function testHydrateTypedLimitedBooleanArrayAccessProperty($element): void
1492
    {
1493
        $object = new class {
1494
            public Fixture\LimitedCollection $value;
1495
        };
1496
1497
        $this->assertInvalidValueExceptionCount(1);
1498
        $this->assertInvalidValueExceptionMessage(0, 'This value is limited to 1 elements.');
1499
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::ARRAY_OVERFLOW);
1500
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1501
        $this->createHydrator()->hydrate($object, ['value' => [true, $element]]);
1502
    }
1503
1504
    /**
1505
     * @group array-access
1506
     * @group typed-boolean-array-access
1507
     * @dataProvider strictBooleanProvider
1508
     * @dataProvider nonStrictBooleanProvider
1509
     */
1510
    public function testHydrateTypedOverflowedBooleanArrayAccessProperty($element): void
1511
    {
1512
        $object = new class {
1513
            public Fixture\LimitedBooleanCollection $value;
1514
        };
1515
1516
        $this->assertInvalidValueExceptionCount(1);
1517
        $this->assertInvalidValueExceptionMessage(0, 'This value is limited to 1 elements.');
1518
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::ARRAY_OVERFLOW);
1519
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1520
        $this->createHydrator()->hydrate($object, ['value' => [true, $element]]);
1521
    }
1522
1523
    /**
1524
     * @group array-access
1525
     * @group boolean-association-array-access
1526
     * @dataProvider strictBooleanDataProvider
1527
     * @dataProvider nonStrictBooleanDataProvider
1528
     */
1529
    public function testHydrateBooleanAssociationArrayAccessProperty(array $data, bool $expected): void
1530
    {
1531
        $object = new class {
1532
            public Fixture\BooleanAssociationCollection $value;
1533
        };
1534
1535
        $this->createHydrator()->hydrate($object, ['value' => [$data]]);
1536
        $this->assertSame($expected, $object->value[0]->value);
1537
    }
1538
1539
    /**
1540
     * @group array-access
1541
     * @group boolean-association-array-access
1542
     * @dataProvider strictNullDataProvider
1543
     */
1544
    public function testHydrateBooleanAssociationArrayAccessPropertyWithNull(array $data): void
1545
    {
1546
        $object = new class {
1547
            public Fixture\BooleanAssociationCollection $value;
1548
        };
1549
1550
        $this->assertInvalidValueExceptionCount(1);
1551
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
1552
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
1553
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1554
        $this->createHydrator()->hydrate($object, $data);
1555
    }
1556
1557
    /**
1558
     * @group array-access
1559
     * @group boolean-association-array-access
1560
     * @dataProvider notArrayDataProvider
1561
     */
1562
    public function testHydrateBooleanAssociationArrayAccessPropertyWithInvalidValue(array $data): void
1563
    {
1564
        $object = new class {
1565
            public Fixture\BooleanAssociationCollection $value;
1566
        };
1567
1568
        $this->assertInvalidValueExceptionCount(1);
1569
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type array.');
1570
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_ARRAY);
1571
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1572
        $this->createHydrator()->hydrate($object, $data);
1573
    }
1574
1575
    /**
1576
     * @group array-access
1577
     * @group boolean-association-array-access
1578
     */
1579
    public function testHydrateBooleanAssociationArrayAccessPropertyWithoutValue(): void
1580
    {
1581
        $object = new class {
1582
            public Fixture\BooleanAssociationCollection $value;
1583
        };
1584
1585
        $this->assertInvalidValueExceptionCount(1);
1586
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
1587
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
1588
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1589
        $this->createHydrator()->hydrate($object, []);
1590
    }
1591
1592
    /**
1593
     * @group array-access
1594
     * @group boolean-association-array-access
1595
     * @dataProvider notArrayProvider
1596
     */
1597
    public function testHydrateBooleanAssociationArrayAccessPropertyWithInvalidAssociation($actual): void
1598
    {
1599
        $object = new class {
1600
            public Fixture\BooleanAssociationCollection $value;
1601
        };
1602
1603
        $this->assertInvalidValueExceptionCount(1);
1604
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type array.');
1605
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_ARRAY);
1606
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0');
1607
        $this->createHydrator()->hydrate($object, ['value' => [$actual]]);
1608
    }
1609
1610
    /**
1611
     * @group array-access
1612
     * @group boolean-association-array-access
1613
     * @dataProvider strictNullDataProvider
1614
     * @dataProvider nonStrictNullDataProvider
1615
     */
1616
    public function testHydrateBooleanAssociationArrayAccessPropertyWithEmptyAssociationValue(array $data): void
1617
    {
1618
        $object = new class {
1619
            public Fixture\BooleanAssociationCollection $value;
1620
        };
1621
1622
        $this->assertInvalidValueExceptionCount(1);
1623
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
1624
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
1625
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0.value');
1626
        $this->createHydrator()->hydrate($object, ['value' => [$data]]);
1627
    }
1628
1629
    /**
1630
     * @group array-access
1631
     * @group boolean-association-array-access
1632
     * @dataProvider notBooleanDataProvider
1633
     */
1634
    public function testHydrateBooleanAssociationArrayAccessPropertyWithInvalidAssociationValue(array $data): void
1635
    {
1636
        $object = new class {
1637
            public Fixture\BooleanAssociationCollection $value;
1638
        };
1639
1640
        $this->assertInvalidValueExceptionCount(1);
1641
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type boolean.');
1642
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_BOOLEAN);
1643
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0.value');
1644
        $this->createHydrator()->hydrate($object, ['value' => [$data]]);
1645
    }
1646
1647
    /**
1648
     * @group array-access
1649
     */
1650
    public function testHydrateBooleanArrayCollectionParameterWithValidData(): void
1651
    {
1652
        $this->phpRequired('8.0');
1653
1654
        $object = new class {
1655
            public BooleanArrayCollection $value;
1656
        };
1657
1658
        $this->assertInvalidValueExceptionCount(0);
1659
        $this->createHydrator()->hydrate($object, ['value' => [[true]]]);
1660
        $this->assertSame([[true]], (array) $object->value);
1661
    }
1662
1663
    /**
1664
     * @group array-access
1665
     */
1666
    public function testHydrateBooleanArrayCollectionParameterWithInvalidData(): void
1667
    {
1668
        $this->phpRequired('8.0');
1669
1670
        $object = new class {
1671
            public BooleanArrayCollection $value;
1672
        };
1673
1674
        $this->assertInvalidValueExceptionCount(1);
1675
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type boolean.');
1676
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_BOOLEAN);
1677
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.0.0');
1678
        $this->createHydrator()->hydrate($object, ['value' => [['foo']]]);
1679
    }
1680
1681
    /**
1682
     * @group association
1683
     */
1684
    public function testHydrateUnstantiableAssociationProperty(): void
1685
    {
1686
        $object = new class {
1687
            public Fixture\UnstantiableObject $value;
1688
        };
1689
1690
        $this->expectException(InvalidObjectException::class);
1691
        $this->createHydrator()->hydrate($object, ['value' => 'foo']);
1692
    }
1693
1694
    /**
1695
     * @group association
1696
     * @group boolean-association
1697
     * @dataProvider strictBooleanDataProvider
1698
     * @dataProvider nonStrictBooleanDataProvider
1699
     */
1700
    public function testHydrateBooleanAssociationProperty(array $data, bool $expected): void
1701
    {
1702
        $object = new class {
1703
            public Fixture\BooleanAssociation $value;
1704
        };
1705
1706
        $this->assertInvalidValueExceptionCount(0);
1707
        $this->createHydrator()->hydrate($object, ['value' => $data]);
1708
        $this->assertSame($expected, $object->value->value);
1709
    }
1710
1711
    /**
1712
     * @group association
1713
     * @group boolean-association
1714
     */
1715
    public function testHydrateNullableBooleanAssociationProperty(): void
1716
    {
1717
        $object = new class {
1718
            public ?Fixture\BooleanAssociation $value;
1719
        };
1720
1721
        $this->assertInvalidValueExceptionCount(0);
1722
        $this->createHydrator()->hydrate($object, ['value' => null]);
1723
        $this->assertNull($object->value);
1724
    }
1725
1726
    /**
1727
     * @group association
1728
     * @group boolean-association
1729
     */
1730
    public function testHydrateOptionalBooleanAssociationProperty(): void
1731
    {
1732
        $object = new class {
1733
            public ?Fixture\BooleanAssociation $value = null;
1734
        };
1735
1736
        $this->assertInvalidValueExceptionCount(0);
1737
        $this->createHydrator()->hydrate($object, []);
1738
        $this->assertNull($object->value);
1739
    }
1740
1741
    /**
1742
     * @group association
1743
     * @group boolean-association
1744
     */
1745
    public function testHydrateBooleanAssociationPropertyWithNull(): void
1746
    {
1747
        $object = new class {
1748
            public Fixture\BooleanAssociation $value;
1749
        };
1750
1751
        $this->assertInvalidValueExceptionCount(1);
1752
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
1753
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
1754
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1755
        $this->createHydrator()->hydrate($object, ['value' => null]);
1756
    }
1757
1758
    /**
1759
     * @group association
1760
     * @group boolean-association
1761
     * @dataProvider notArrayDataProvider
1762
     */
1763
    public function testHydrateBooleanAssociationPropertyWithInvalidValue(array $data): void
1764
    {
1765
        $object = new class {
1766
            public Fixture\BooleanAssociation $value;
1767
        };
1768
1769
        $this->assertInvalidValueExceptionCount(1);
1770
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type array.');
1771
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_ARRAY);
1772
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1773
        $this->createHydrator()->hydrate($object, $data);
1774
    }
1775
1776
    /**
1777
     * @group association
1778
     * @group boolean-association
1779
     */
1780
    public function testHydrateBooleanAssociationPropertyWithoutValue(): void
1781
    {
1782
        $object = new class {
1783
            public Fixture\BooleanAssociation $value;
1784
        };
1785
1786
        $this->assertInvalidValueExceptionCount(1);
1787
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
1788
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
1789
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1790
        $this->createHydrator()->hydrate($object, []);
1791
    }
1792
1793
    /**
1794
     * @group association
1795
     * @group boolean-association
1796
     */
1797
    public function testHydrateBooleanAssociationPropertyWithEmptyAssociation(): void
1798
    {
1799
        $object = new class {
1800
            public Fixture\BooleanAssociation $value;
1801
        };
1802
1803
        $this->assertInvalidValueExceptionCount(1);
1804
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
1805
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
1806
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.value');
1807
        $this->createHydrator()->hydrate($object, ['value' => []]);
1808
    }
1809
1810
    /**
1811
     * @group association
1812
     * @group boolean-association
1813
     * @dataProvider notBooleanDataProvider
1814
     */
1815
    public function testHydrateBooleanAssociationPropertyWithInvalidAssociationValue(array $data): void
1816
    {
1817
        $object = new class {
1818
            public Fixture\BooleanAssociation $value;
1819
        };
1820
1821
        $this->assertInvalidValueExceptionCount(1);
1822
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type boolean.');
1823
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_BOOLEAN);
1824
        $this->assertInvalidValueExceptionPropertyPath(0, 'value.value');
1825
        $this->createHydrator()->hydrate($object, ['value' => $data]);
1826
    }
1827
1828
    /**
1829
     * @group timestamp
1830
     * @dataProvider timestampDataProvider
1831
     */
1832
    // phpcs:ignore Generic.Files.LineLength
1833
    public function testHydrateTimestampProperty(array $data, string $expected, ?string $format = null, ?string $timezone = null): void
1834
    {
1835
        $object = new class {
1836
            public DateTimeImmutable $value;
1837
        };
1838
1839
        $this->assertInvalidValueExceptionCount(0);
1840
        // phpcs:ignore Generic.Files.LineLength
1841
        $this->createHydrator([ContextKey::TIMESTAMP_FORMAT => $format, ContextKey::TIMEZONE => $timezone])->hydrate($object, $data);
1842
        $this->assertSame($expected, $object->value->format($format ?? TimestampTypeConverter::DEFAULT_FORMAT));
1843
    }
1844
1845
    /**
1846
     * @group timestamp
1847
     * @dataProvider timestampDataProvider
1848
     * @dataProvider strictNullDataProvider
1849
     * @dataProvider nonStrictNullDataProvider
1850
     */
1851
    // phpcs:ignore Generic.Files.LineLength
1852
    public function testHydrateNullableTimestampProperty(array $data, ?string $expected, ?string $format = null, ?string $timezone = null): void
1853
    {
1854
        $object = new class {
1855
            public ?DateTimeImmutable $value;
1856
        };
1857
1858
        $this->assertInvalidValueExceptionCount(0);
1859
        // phpcs:ignore Generic.Files.LineLength
1860
        $this->createHydrator([ContextKey::TIMESTAMP_FORMAT => $format, ContextKey::TIMEZONE => $timezone])->hydrate($object, $data);
1861
        // phpcs:ignore Generic.Files.LineLength
1862
        $this->assertSame($expected, isset($object->value) ? $object->value->format($format ?? TimestampTypeConverter::DEFAULT_FORMAT) : null);
0 ignored issues
show
Bug introduced by
The method format() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1862
        $this->assertSame($expected, isset($object->value) ? $object->value->/** @scrutinizer ignore-call */ format($format ?? TimestampTypeConverter::DEFAULT_FORMAT) : null);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1863
    }
1864
1865
    /**
1866
     * @group timestamp
1867
     * @dataProvider timestampDataProvider
1868
     * @dataProvider emptyArrayProvider
1869
     */
1870
    // phpcs:ignore Generic.Files.LineLength
1871
    public function testHydrateOptionalTimestampProperty(array $data, ?string $expected = null, ?string $format = null, ?string $timezone = null): void
1872
    {
1873
        $object = new class {
1874
            public ?DateTimeImmutable $value = null;
1875
        };
1876
1877
        $this->assertInvalidValueExceptionCount(0);
1878
        // phpcs:ignore Generic.Files.LineLength
1879
        $this->createHydrator([ContextKey::TIMESTAMP_FORMAT => $format, ContextKey::TIMEZONE => $timezone])->hydrate($object, $data);
1880
        // phpcs:ignore Generic.Files.LineLength
1881
        $this->assertSame($expected, isset($object->value) ? $object->value->format($format ?? TimestampTypeConverter::DEFAULT_FORMAT) : null);
1882
    }
1883
1884
    /**
1885
     * @group timestamp
1886
     * @dataProvider strictNullDataProvider
1887
     * @dataProvider nonStrictNullDataProvider
1888
     */
1889
    public function testHydrateTimestampPropertyWithEmptyValue(array $data): void
1890
    {
1891
        $object = new class {
1892
            public DateTimeImmutable $value;
1893
        };
1894
1895
        $this->assertInvalidValueExceptionCount(1);
1896
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
1897
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
1898
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1899
        $this->createHydrator()->hydrate($object, $data);
1900
    }
1901
1902
    /**
1903
     * @group timestamp
1904
     * @dataProvider invalidTimestampDataProvider
1905
     */
1906
    // phpcs:ignore Generic.Files.LineLength
1907
    public function testHydrateTimestampPropertyWithInvalidValue(array $data, ?string $format, string $errorCode, string $errorMessage): void
1908
    {
1909
        $object = new class {
1910
            public DateTimeImmutable $value;
1911
        };
1912
1913
        $this->assertInvalidValueExceptionCount(1);
1914
        $this->assertInvalidValueExceptionMessage(0, $errorMessage);
1915
        $this->assertInvalidValueExceptionErrorCode(0, $errorCode);
1916
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1917
        $this->createHydrator([ContextKey::TIMESTAMP_FORMAT => $format])->hydrate($object, $data);
1918
    }
1919
1920
    /**
1921
     * @group timestamp
1922
     */
1923
    public function testHydrateTimestampPropertyWithoutValue(): void
1924
    {
1925
        $object = new class {
1926
            public DateTimeImmutable $value;
1927
        };
1928
1929
        $this->assertInvalidValueExceptionCount(1);
1930
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
1931
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
1932
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
1933
        $this->createHydrator()->hydrate($object, []);
1934
    }
1935
1936
    /**
1937
     * @group timestamp
1938
     * @dataProvider timestampDataProvider
1939
     */
1940
    // phpcs:ignore Generic.Files.LineLength
1941
    public function testHydrateOverriddenDateTimeImmutable(array $data, string $expected, ?string $format = null, ?string $timezone = null): void
1942
    {
1943
        $this->phpRequired('8.0');
1944
1945
        $object = new class {
1946
            public Fixture\OverriddenDateTimeImmutable $value;
1947
        };
1948
1949
        $this->assertInvalidValueExceptionCount(0);
1950
        // phpcs:ignore Generic.Files.LineLength
1951
        $this->createHydrator([ContextKey::TIMESTAMP_FORMAT => $format, ContextKey::TIMEZONE => $timezone])->hydrate($object, $data);
1952
        $this->assertSame($expected, $object->value->format($format ?? TimestampTypeConverter::DEFAULT_FORMAT));
1953
    }
1954
1955
    /**
1956
     * @group timezone
1957
     * @dataProvider timezoneDataProvider
1958
     */
1959
    public function testHydrateTimezoneProperty(array $data, string $expected): void
1960
    {
1961
        $object = new class {
1962
            public DateTimeZone $value;
1963
        };
1964
1965
        $this->assertInvalidValueExceptionCount(0);
1966
        $this->createHydrator()->hydrate($object, $data);
1967
        $this->assertSame($expected, $object->value->getName());
1968
    }
1969
1970
    /**
1971
     * @group timezone
1972
     * @dataProvider timezoneDataProvider
1973
     * @dataProvider strictNullDataProvider
1974
     * @dataProvider nonStrictNullDataProvider
1975
     */
1976
    public function testHydrateNullableTimezoneProperty(array $data, ?string $expected): void
1977
    {
1978
        $object = new class {
1979
            public ?DateTimeZone $value;
1980
        };
1981
1982
        $this->assertInvalidValueExceptionCount(0);
1983
        $this->createHydrator()->hydrate($object, $data);
1984
        $this->assertSame($expected, isset($object->value) ? $object->value->getName() : null);
1985
    }
1986
1987
    /**
1988
     * @group timezone
1989
     * @dataProvider timezoneDataProvider
1990
     * @dataProvider emptyArrayProvider
1991
     */
1992
    public function testHydrateOptionalTimezoneProperty(array $data, ?string $expected = null): void
1993
    {
1994
        $object = new class {
1995
            public ?DateTimeZone $value = null;
1996
        };
1997
1998
        $this->assertInvalidValueExceptionCount(0);
1999
        $this->createHydrator()->hydrate($object, $data);
2000
        $this->assertSame($expected, isset($object->value) ? $object->value->getName() : null);
2001
    }
2002
2003
    /**
2004
     * @group timezone
2005
     * @dataProvider strictNullDataProvider
2006
     * @dataProvider nonStrictNullDataProvider
2007
     */
2008
    public function testHydrateTimezonePropertyWithEmptyValue(array $data): void
2009
    {
2010
        $object = new class {
2011
            public DateTimeZone $value;
2012
        };
2013
2014
        $this->assertInvalidValueExceptionCount(1);
2015
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
2016
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
2017
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2018
        $this->createHydrator()->hydrate($object, $data);
2019
    }
2020
2021
    /**
2022
     * @group timezone
2023
     * @dataProvider strictNotStringDataProvider
2024
     */
2025
    public function testHydrateTimezonePropertyWithInvalidValue(array $data): void
2026
    {
2027
        $object = new class {
2028
            public DateTimeZone $value;
2029
        };
2030
2031
        $this->assertInvalidValueExceptionCount(1);
2032
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type string.');
2033
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_STRING);
2034
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2035
        $this->createHydrator()->hydrate($object, $data);
2036
    }
2037
2038
    /**
2039
     * @group timezone
2040
     */
2041
    public function testHydrateTimezonePropertyWithUnknownValue(): void
2042
    {
2043
        $object = new class {
2044
            public DateTimeZone $value;
2045
        };
2046
2047
        $this->assertInvalidValueExceptionCount(1);
2048
        $this->assertInvalidValueExceptionMessage(0, 'This value is not a valid timezone.');
2049
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::INVALID_TIMEZONE);
2050
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2051
        $this->createHydrator()->hydrate($object, ['value' => 'Jupiter/Europa']);
2052
    }
2053
2054
    /**
2055
     * @group timezone
2056
     */
2057
    public function testHydrateTimezonePropertyWithoutValue(): void
2058
    {
2059
        $object = new class {
2060
            public DateTimeZone $value;
2061
        };
2062
2063
        $this->assertInvalidValueExceptionCount(1);
2064
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
2065
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
2066
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2067
        $this->createHydrator()->hydrate($object, []);
2068
    }
2069
2070
    /**
2071
     * @group myclabs-enum
2072
     * @dataProvider myclabsEnumDataProvider
2073
     */
2074
    public function testHydrateMyclabsEnumProperty(array $data, $expected): void
2075
    {
2076
        $object = new class {
2077
            public Fixture\MyclabsEnum $value;
2078
        };
2079
2080
        $this->assertInvalidValueExceptionCount(0);
2081
        $this->createHydrator()->hydrate($object, $data);
2082
        $this->assertEquals($expected, $object->value);
2083
    }
2084
2085
    /**
2086
     * @group myclabs-enum
2087
     * @dataProvider myclabsEnumDataProvider
2088
     * @dataProvider strictNullDataProvider
2089
     * @dataProvider nonStrictNullDataProvider
2090
     */
2091
    public function testHydrateNullableMyclabsEnumProperty(array $data, $expected): void
2092
    {
2093
        $object = new class {
2094
            public ?Fixture\MyclabsEnum $value;
2095
        };
2096
2097
        $this->assertInvalidValueExceptionCount(0);
2098
        $this->createHydrator()->hydrate($object, $data);
2099
        $this->assertEquals($expected, $object->value);
2100
    }
2101
2102
    /**
2103
     * @group myclabs-enum
2104
     * @dataProvider myclabsEnumDataProvider
2105
     * @dataProvider emptyArrayProvider
2106
     */
2107
    public function testHydrateOptionalMyclabsEnumProperty(array $data, $expected = null): void
2108
    {
2109
        $object = new class {
2110
            public ?Fixture\MyclabsEnum $value = null;
2111
        };
2112
2113
        $this->assertInvalidValueExceptionCount(0);
2114
        $this->createHydrator()->hydrate($object, $data);
2115
        $this->assertEquals($expected, $object->value);
2116
    }
2117
2118
    /**
2119
     * @group myclabs-enum
2120
     * @dataProvider strictNullDataProvider
2121
     * @dataProvider nonStrictNullDataProvider
2122
     */
2123
    public function testHydrateMyclabsEnumPropertyWithEmptyValue(array $data): void
2124
    {
2125
        $object = new class {
2126
            public Fixture\MyclabsEnum $value;
2127
        };
2128
2129
        $this->assertInvalidValueExceptionCount(1);
2130
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
2131
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
2132
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2133
        $this->createHydrator()->hydrate($object, $data);
2134
    }
2135
2136
    /**
2137
     * @group myclabs-enum
2138
     */
2139
    public function testHydrateMyclabsEnumPropertyWithUnknownValue(): void
2140
    {
2141
        $object = new class {
2142
            public Fixture\MyclabsEnum $value;
2143
        };
2144
2145
        $this->assertInvalidValueExceptionCount(1);
2146
        // phpcs:ignore Generic.Files.LineLength
2147
        $this->assertInvalidValueExceptionMessage(0, 'This value is not a valid choice; expected values: ' . join(', ', Fixture\MyclabsEnum::toArray()) . '.');
2148
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::INVALID_CHOICE);
2149
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2150
        $this->createHydrator()->hydrate($object, ['value' => 'foo']);
2151
    }
2152
2153
    /**
2154
     * @group myclabs-enum
2155
     */
2156
    public function testHydrateMyclabsEnumPropertyWithoutValue(): void
2157
    {
2158
        $object = new class {
2159
            public Fixture\MyclabsEnum $value;
2160
        };
2161
2162
        $this->assertInvalidValueExceptionCount(1);
2163
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
2164
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
2165
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2166
        $this->createHydrator()->hydrate($object, []);
2167
    }
2168
2169
    /**
2170
     * @group ramsey-uuid
2171
     * @dataProvider uuidDataProvider
2172
     */
2173
    public function testHydrateRamseyUuidProperty(array $data, string $expected): void
2174
    {
2175
        $object = new class {
2176
            public \Ramsey\Uuid\UuidInterface $value;
2177
        };
2178
2179
        $this->assertInvalidValueExceptionCount(0);
2180
        $this->createHydrator()->hydrate($object, $data);
2181
        $this->assertSame($expected, $object->value->toString());
2182
    }
2183
2184
    /**
2185
     * @group ramsey-uuid
2186
     * @dataProvider uuidDataProvider
2187
     * @dataProvider strictNullDataProvider
2188
     * @dataProvider nonStrictNullDataProvider
2189
     */
2190
    public function testHydrateNullableRamseyUuidProperty(array $data, ?string $expected): void
2191
    {
2192
        $object = new class {
2193
            public ?\Ramsey\Uuid\UuidInterface $value;
2194
        };
2195
2196
        $this->assertInvalidValueExceptionCount(0);
2197
        $this->createHydrator()->hydrate($object, $data);
2198
        $this->assertSame($expected, isset($object->value) ? $object->value->toString() : null);
2199
    }
2200
2201
    /**
2202
     * @group ramsey-uuid
2203
     * @dataProvider uuidDataProvider
2204
     * @dataProvider emptyArrayProvider
2205
     */
2206
    public function testHydrateOptionalRamseyUuidProperty(array $data, ?string $expected = null): void
2207
    {
2208
        $object = new class {
2209
            public ?\Ramsey\Uuid\UuidInterface $value = null;
2210
        };
2211
2212
        $this->assertInvalidValueExceptionCount(0);
2213
        $this->createHydrator()->hydrate($object, $data);
2214
        $this->assertSame($expected, isset($object->value) ? $object->value->toString() : null);
2215
    }
2216
2217
    /**
2218
     * @group ramsey-uuid
2219
     * @dataProvider strictNullDataProvider
2220
     * @dataProvider nonStrictNullDataProvider
2221
     */
2222
    public function testHydrateRamseyUuidPropertyWithEmptyValue(array $data): void
2223
    {
2224
        $object = new class {
2225
            public \Ramsey\Uuid\UuidInterface $value;
2226
        };
2227
2228
        $this->assertInvalidValueExceptionCount(1);
2229
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
2230
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
2231
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2232
        $this->createHydrator()->hydrate($object, $data);
2233
    }
2234
2235
    /**
2236
     * @group ramsey-uuid
2237
     * @dataProvider strictNotStringDataProvider
2238
     */
2239
    public function testHydrateRamseyUuidPropertyWithInvalidValue(array $data): void
2240
    {
2241
        $object = new class {
2242
            public \Ramsey\Uuid\UuidInterface $value;
2243
        };
2244
2245
        $this->assertInvalidValueExceptionCount(1);
2246
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type string.');
2247
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_STRING);
2248
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2249
        $this->createHydrator()->hydrate($object, $data);
2250
    }
2251
2252
    /**
2253
     * @group ramsey-uuid
2254
     */
2255
    public function testHydrateRamseyUuidPropertyWithInvalidUuid(): void
2256
    {
2257
        $object = new class {
2258
            public \Ramsey\Uuid\UuidInterface $value;
2259
        };
2260
2261
        $this->assertInvalidValueExceptionCount(1);
2262
        $this->assertInvalidValueExceptionMessage(0, 'This value is not a valid UID.');
2263
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::INVALID_UID);
2264
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2265
        $this->createHydrator()->hydrate($object, ['value' => 'foo']);
2266
    }
2267
2268
    /**
2269
     * @group ramsey-uuid
2270
     */
2271
    public function testHydrateRamseyUuidPropertyWithoutValue(): void
2272
    {
2273
        $object = new class {
2274
            public \Ramsey\Uuid\UuidInterface $value;
2275
        };
2276
2277
        $this->assertInvalidValueExceptionCount(1);
2278
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
2279
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
2280
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2281
        $this->createHydrator()->hydrate($object, []);
2282
    }
2283
2284
    /**
2285
     * @group symfony-uuid
2286
     * @dataProvider uuidDataProvider
2287
     */
2288
    public function testHydrateSymfonyUuidProperty(array $data, string $expected): void
2289
    {
2290
        $object = new class {
2291
            public \Symfony\Component\Uid\UuidV4 $value;
2292
        };
2293
2294
        $this->assertInvalidValueExceptionCount(0);
2295
        $this->createHydrator()->hydrate($object, $data);
2296
        $this->assertSame($expected, $object->value->toRfc4122());
2297
    }
2298
2299
    /**
2300
     * @group symfony-uuid
2301
     * @dataProvider uuidDataProvider
2302
     * @dataProvider strictNullDataProvider
2303
     * @dataProvider nonStrictNullDataProvider
2304
     */
2305
    public function testHydrateNullableSymfonyUuidProperty(array $data, ?string $expected): void
2306
    {
2307
        $object = new class {
2308
            public ?\Symfony\Component\Uid\UuidV4 $value;
2309
        };
2310
2311
        $this->assertInvalidValueExceptionCount(0);
2312
        $this->createHydrator()->hydrate($object, $data);
2313
        $this->assertSame($expected, isset($object->value) ? $object->value->toRfc4122() : null);
2314
    }
2315
2316
    /**
2317
     * @group symfony-uuid
2318
     * @dataProvider uuidDataProvider
2319
     * @dataProvider emptyArrayProvider
2320
     */
2321
    public function testHydrateOptionalSymfonyUuidProperty(array $data, ?string $expected = null): void
2322
    {
2323
        $object = new class {
2324
            public ?\Symfony\Component\Uid\UuidV4 $value = null;
2325
        };
2326
2327
        $this->assertInvalidValueExceptionCount(0);
2328
        $this->createHydrator()->hydrate($object, $data);
2329
        $this->assertSame($expected, isset($object->value) ? $object->value->toRfc4122() : null);
2330
    }
2331
2332
    /**
2333
     * @group symfony-uuid
2334
     * @dataProvider strictNullDataProvider
2335
     * @dataProvider nonStrictNullDataProvider
2336
     */
2337
    public function testHydrateSymfonyUuidPropertyWithEmptyValue(array $data): void
2338
    {
2339
        $object = new class {
2340
            public \Symfony\Component\Uid\UuidV4 $value;
2341
        };
2342
2343
        $this->assertInvalidValueExceptionCount(1);
2344
        $this->assertInvalidValueExceptionMessage(0, 'This value must not be empty.');
2345
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_NOT_BE_EMPTY);
2346
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2347
        $this->createHydrator()->hydrate($object, $data);
2348
    }
2349
2350
    /**
2351
     * @group symfony-uuid
2352
     * @dataProvider strictNotStringDataProvider
2353
     */
2354
    public function testHydrateSymfonyUuidPropertyWithInvalidValue(array $data): void
2355
    {
2356
        $object = new class {
2357
            public \Symfony\Component\Uid\UuidV4 $value;
2358
        };
2359
2360
        $this->assertInvalidValueExceptionCount(1);
2361
        $this->assertInvalidValueExceptionMessage(0, 'This value must be of type string.');
2362
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_STRING);
2363
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2364
        $this->createHydrator()->hydrate($object, $data);
2365
    }
2366
2367
    /**
2368
     * @group symfony-uuid
2369
     */
2370
    public function testHydrateSymfonyUuidPropertyWithInvalidUuid(): void
2371
    {
2372
        $object = new class {
2373
            public \Symfony\Component\Uid\UuidV4 $value;
2374
        };
2375
2376
        $this->assertInvalidValueExceptionCount(1);
2377
        $this->assertInvalidValueExceptionMessage(0, 'This value is not a valid UID.');
2378
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::INVALID_UID);
2379
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2380
        $this->createHydrator()->hydrate($object, ['value' => 'foo']);
2381
    }
2382
2383
    /**
2384
     * @group symfony-uuid
2385
     */
2386
    public function testHydrateSymfonyUuidPropertyWithoutValue(): void
2387
    {
2388
        $object = new class {
2389
            public \Symfony\Component\Uid\UuidV4 $value;
2390
        };
2391
2392
        $this->assertInvalidValueExceptionCount(1);
2393
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
2394
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
2395
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2396
        $this->createHydrator()->hydrate($object, []);
2397
    }
2398
2399
    /**
2400
     * @group json
2401
     */
2402
    public function testHydrateObjectWithJson(): void
2403
    {
2404
        $object = new class {
2405
            public string $value;
2406
        };
2407
2408
        $this->assertInvalidValueExceptionCount(0);
2409
        $this->createHydrator()->hydrateWithJson($object, '{"value": "foo"}');
2410
        $this->assertSame('foo', $object->value);
2411
    }
2412
2413
    /**
2414
     * @group json
2415
     */
2416
    public function testHydrateObjectWithInvalidJson(): void
2417
    {
2418
        $object = new class {
2419
            public string $value;
2420
        };
2421
2422
        $this->expectException(InvalidDataException::class);
2423
        $this->expectExceptionMessageMatches('/^The JSON is invalid and couldn‘t be decoded due to: .+$/');
2424
        $this->createHydrator()->hydrateWithJson($object, '[[]]', 0, 1);
2425
    }
2426
2427
    /**
2428
     * @group json
2429
     */
2430
    public function testHydrateObjectWithNonObjectableJson(): void
2431
    {
2432
        $object = new class {
2433
            public string $value;
2434
        };
2435
2436
        $this->expectException(InvalidDataException::class);
2437
        $this->expectExceptionMessage('The JSON must be in the form of an array or an object.');
2438
        $this->createHydrator()->hydrateWithJson($object, 'null');
2439
    }
2440
2441
    public function testInvalidObjectExceptionUnsupportedMethodParameterType(): void
2442
    {
2443
        $class = $this->createMock(ReflectionClass::class);
2444
        $class->method('getName')->willReturn('foo');
2445
2446
        $method = $this->createMock(ReflectionMethod::class);
2447
        $method->method('getDeclaringClass')->willReturn($class);
2448
        $method->method('getName')->willReturn('bar');
2449
2450
        $parameter = $this->createMock(ReflectionParameter::class);
2451
        $parameter->method('getDeclaringClass')->willReturn($class);
2452
        $parameter->method('getDeclaringFunction')->willReturn($method);
2453
        $parameter->method('getName')->willReturn('baz');
2454
2455
        $type = new Type($parameter, 'mixed', false);
2456
2457
        $e = InvalidObjectException::unsupportedParameterType($type, $parameter);
2458
        // phpcs:ignore Generic.Files.LineLength
2459
        $this->assertSame('The parameter {foo::bar($baz[0])} is associated with an unsupported type {mixed}.', $e->getMessage());
2460
    }
2461
2462
    public function testInvalidObjectExceptionUnsupportedFunctionParameterType(): void
2463
    {
2464
        $function = $this->createMock(ReflectionFunction::class);
2465
        $function->method('getName')->willReturn('foo');
2466
2467
        $parameter = $this->createMock(ReflectionParameter::class);
2468
        $parameter->method('getDeclaringFunction')->willReturn($function);
2469
        $parameter->method('getName')->willReturn('bar');
2470
2471
        $type = new Type($parameter, 'mixed', false);
2472
2473
        $e = InvalidObjectException::unsupportedParameterType($type, $parameter);
2474
        // phpcs:ignore Generic.Files.LineLength
2475
        $this->assertSame('The parameter {foo($bar[0])} is associated with an unsupported type {mixed}.', $e->getMessage());
2476
    }
2477
2478
    public function testTypeFromParameter(): void
2479
    {
2480
        $parameter = $this->createMock(ReflectionParameter::class);
2481
        $parameter->method('getType')->willReturn(null);
2482
        $type = Type::fromParameter($parameter);
2483
        $this->assertSame(BuiltinType::MIXED, $type->getName());
2484
        $this->assertTrue($type->allowsNull());
2485
2486
        $namedType = $this->createMock(ReflectionNamedType::class);
2487
        $namedType->method('getName')->willReturn('foo');
2488
        $namedType->method('allowsNull')->willReturn(false);
2489
        $parameter = $this->createMock(ReflectionParameter::class);
2490
        $parameter->method('getType')->willReturn($namedType);
2491
        $type = Type::fromParameter($parameter);
2492
        $this->assertSame('foo', $type->getName());
2493
        $this->assertFalse($type->allowsNull());
2494
2495
        $namedType = $this->createMock(ReflectionNamedType::class);
2496
        $namedType->method('getName')->willReturn('foo');
2497
        $namedType->method('allowsNull')->willReturn(true);
2498
        $parameter = $this->createMock(ReflectionParameter::class);
2499
        $parameter->method('getType')->willReturn($namedType);
2500
        $type = Type::fromParameter($parameter);
2501
        $this->assertSame('foo', $type->getName());
2502
        $this->assertTrue($type->allowsNull());
2503
2504
        if (PHP_VERSION_ID < 80000) {
2505
            return;
2506
        }
2507
2508
        $namedTypes = [];
2509
        $namedTypes[0] = $this->createMock(ReflectionNamedType::class);
2510
        $namedTypes[0]->method('getName')->willReturn('foo');
2511
        $namedTypes[1] = $this->createMock(ReflectionNamedType::class);
2512
        $namedTypes[1]->method('getName')->willReturn('bar');
2513
        $unionType = $this->createMock(ReflectionUnionType::class);
2514
        $unionType->method('getTypes')->willReturn($namedTypes);
2515
        $unionType->method('allowsNull')->willReturn(false);
2516
        $unionType->method('__toString')->willReturn('foo|bar');
2517
        $parameter = $this->createMock(ReflectionParameter::class);
2518
        $parameter->method('getType')->willReturn($unionType);
2519
        $type = Type::fromParameter($parameter);
2520
        $this->assertSame('foo|bar', $type->getName());
2521
        $this->assertFalse($type->allowsNull());
2522
2523
        $namedTypes = [];
2524
        $namedTypes[0] = $this->createMock(ReflectionNamedType::class);
2525
        $namedTypes[0]->method('getName')->willReturn('foo');
2526
        $namedTypes[1] = $this->createMock(ReflectionNamedType::class);
2527
        $namedTypes[1]->method('getName')->willReturn('bar');
2528
        $unionType = $this->createMock(ReflectionUnionType::class);
2529
        $unionType->method('getTypes')->willReturn($namedTypes);
2530
        $unionType->method('allowsNull')->willReturn(true);
2531
        $unionType->method('__toString')->willReturn('foo|bar|null');
2532
        $parameter = $this->createMock(ReflectionParameter::class);
2533
        $parameter->method('getType')->willReturn($unionType);
2534
        $type = Type::fromParameter($parameter);
2535
        $this->assertSame('foo|bar|null', $type->getName());
2536
        $this->assertTrue($type->allowsNull());
2537
2538
        if (PHP_VERSION_ID < 80100) {
2539
            return;
2540
        }
2541
2542
        $namedTypes = [];
2543
        $namedTypes[0] = $this->createMock(ReflectionNamedType::class);
2544
        $namedTypes[0]->method('getName')->willReturn('foo');
2545
        $namedTypes[1] = $this->createMock(ReflectionNamedType::class);
2546
        $namedTypes[1]->method('getName')->willReturn('bar');
2547
        $intersectionType = $this->createMock(ReflectionIntersectionType::class);
2548
        $intersectionType->method('getTypes')->willReturn($namedTypes);
2549
        $intersectionType->method('allowsNull')->willReturn(false);
2550
        $intersectionType->method('__toString')->willReturn('foo&bar');
2551
        $parameter = $this->createMock(ReflectionParameter::class);
2552
        $parameter->method('getType')->willReturn($intersectionType);
2553
        $type = Type::fromParameter($parameter);
2554
        $this->assertSame('foo&bar', $type->getName());
2555
        $this->assertFalse($type->allowsNull());
2556
2557
        $namedTypes = [];
2558
        $namedTypes[0] = $this->createMock(ReflectionNamedType::class);
2559
        $namedTypes[0]->method('getName')->willReturn('foo');
2560
        $namedTypes[1] = $this->createMock(ReflectionNamedType::class);
2561
        $namedTypes[1]->method('getName')->willReturn('bar');
2562
        $intersectionType = $this->createMock(ReflectionIntersectionType::class);
2563
        $intersectionType->method('getTypes')->willReturn($namedTypes);
2564
        $intersectionType->method('allowsNull')->willReturn(true);
2565
        $intersectionType->method('__toString')->willReturn('(foo&bar)|null');
2566
        $parameter = $this->createMock(ReflectionParameter::class);
2567
        $parameter->method('getType')->willReturn($intersectionType);
2568
        $type = Type::fromParameter($parameter);
2569
        $this->assertSame('(foo&bar)|null', $type->getName());
2570
        $this->assertTrue($type->allowsNull());
2571
    }
2572
2573
    public function testHydrateStore(): void
2574
    {
2575
        $this->phpRequired('8.1');
2576
2577
        $sold = Fixture\Store\Status::SOLD;
2578
2579
        $data = [
2580
            'name' => 'Pear',
2581
            'category' => [
2582
                'name' => 'Vegetables',
2583
            ],
2584
            'tags' => [
2585
                [
2586
                    'name' => 'foo',
2587
                ],
2588
                [
2589
                    'name' => 'bar',
2590
                ],
2591
            ],
2592
            'status' => $sold->value,
2593
        ];
2594
2595
        $this->assertInvalidValueExceptionCount(0);
2596
        $product = $this->createHydrator()->hydrate(Fixture\Store\Product::class, $data);
2597
        $this->assertSame('Pear', $product->name);
2598
        $this->assertSame('Vegetables', $product->category->name);
2599
        $this->assertCount(2, $product->tags);
2600
        $this->assertArrayHasKey(0, $product->tags);
2601
        $this->assertSame('foo', $product->tags[0]->name);
2602
        $this->assertArrayHasKey(1, $product->tags);
2603
        $this->assertSame('bar', $product->tags[1]->name);
2604
        $this->assertSame($sold, $product->status);
2605
        $this->assertSame('2020-01-01 12:00:00', $product->createdAt->format('Y-m-d H:i:s'));
2606
    }
2607
2608
    public function testUnknownObject(): void
2609
    {
2610
        $this->expectException(InvalidObjectException::class);
2611
        $this->createHydrator()->hydrate(\Unknown::class, []);
0 ignored issues
show
Bug introduced by
The type Unknown was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
2612
    }
2613
2614
    public function testUnstantiableObject(): void
2615
    {
2616
        $this->expectException(InvalidObjectException::class);
2617
        $this->createHydrator()->hydrate(Fixture\UnstantiableObject::class, []);
2618
    }
2619
2620
    public function testStaticalProperty(): void
2621
    {
2622
        $object = new class {
2623
            public static string $value = 'foo';
2624
        };
2625
2626
        $this->assertInvalidValueExceptionCount(0);
2627
        $this->createHydrator()->hydrate($object, ['value' => 'bar']);
2628
        $this->assertSame('foo', $object::$value);
2629
    }
2630
2631
    public function testIgnoredProperty(): void
2632
    {
2633
        $object = new class {
2634
            /** @Ignore() */
2635
            #[Ignore]
2636
            public string $value = 'foo';
2637
        };
2638
2639
        $this->assertInvalidValueExceptionCount(0);
2640
        $this->createHydrator()->hydrate($object, ['value' => 'bar']);
2641
        $this->assertSame('foo', $object->value);
2642
    }
2643
2644
    public function testAliasedProperty(): void
2645
    {
2646
        $proto = new class {
2647
            /** @Alias("alias") */
2648
            #[Alias('alias')]
2649
            public string $value;
2650
        };
2651
2652
        $this->assertInvalidValueExceptionCount(0);
2653
        $object = $this->createHydrator()->hydrate(get_class($proto), ['alias' => 'foo']);
2654
        $this->assertSame('foo', $object->value);
2655
2656
        $this->assertInvalidValueExceptionCount(1);
2657
        $this->createHydrator()->hydrate(get_class($proto), ['value' => 'foo']);
2658
        $this->assertInvalidValueExceptionMessage(0, 'This value must be provided.');
2659
        $this->assertInvalidValueExceptionErrorCode(0, ErrorCode::MUST_BE_PROVIDED);
2660
        $this->assertInvalidValueExceptionPropertyPath(0, 'value');
2661
    }
2662
2663
    public function testDefaultValuedProperty(): void
2664
    {
2665
        $object = new class {
2666
            /** @DefaultValue("foo") */
2667
            #[DefaultValue('foo')]
2668
            public string $value;
2669
        };
2670
2671
        $this->assertInvalidValueExceptionCount(0);
2672
        $this->createHydrator()->hydrate($object, []);
2673
        $this->assertSame('foo', $object->value);
2674
    }
2675
2676
    public function testUntypedProperty(): void
2677
    {
2678
        $object = new class {
2679
            public $value;
2680
        };
2681
2682
        $this->createHydrator()->hydrate($object, ['value' => 'foo']);
2683
        $this->assertSame('foo', $object->value);
2684
    }
2685
2686
    public function testUnsupportedPropertyType(): void
2687
    {
2688
        $object = new class {
2689
            public balalaika $value;
0 ignored issues
show
Bug introduced by
The type Sunrise\Hydrator\Tests\balalaika was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
2690
        };
2691
2692
        $this->expectException(InvalidObjectException::class);
2693
        $this->createHydrator()->hydrate($object, ['value' => 'foo']);
2694
    }
2695
2696
    public function testSymfonyViolations(): void
2697
    {
2698
        $violations = null;
2699
2700
        try {
2701
            $this->createHydrator()->hydrate(new class {
2702
                public string $value;
2703
            }, []);
2704
        } catch (InvalidDataException $e) {
2705
            $violations = $e->getViolations();
2706
        }
2707
2708
        $this->assertNotNull($violations);
2709
        $this->assertCount(1, $violations);
2710
        $this->assertTrue($violations->has(0));
2711
        $this->assertSame(ErrorCode::MUST_BE_PROVIDED, $violations->get(0)->getCode());
2712
        $this->assertSame('This value must be provided.', $violations->get(0)->getMessage());
2713
        $this->assertSame('value', $violations->get(0)->getPropertyPath());
2714
    }
2715
2716
    /**
2717
     * @dataProvider strictBooleanProvider
2718
     * @dataProvider nonStrictBooleanProvider
2719
     */
2720
    public function testSourcelessType($element, bool $expected): void
2721
    {
2722
        $type = Type::fromName(BuiltinType::BOOL);
2723
2724
        $this->assertSame($expected, $this->createHydrator()->castValue($element, $type));
2725
    }
2726
2727
    public function strictNullProvider(): Generator
2728
    {
2729
        yield [null, null];
2730
    }
2731
2732
    public function nonStrictNullProvider(): Generator
2733
    {
2734
        yield ['', null];
2735
        yield [' ', null];
2736
    }
2737
2738
    public function strictBooleanProvider(): Generator
2739
    {
2740
        yield [true, true];
2741
        yield [false, false];
2742
    }
2743
2744
    public function nonStrictBooleanProvider(): Generator
2745
    {
2746
        yield ['1', true];
2747
        yield ['0', false];
2748
        yield ['true', true];
2749
        yield ['false', false];
2750
        yield ['yes', true];
2751
        yield ['no', false];
2752
        yield ['on', true];
2753
        yield ['off', false];
2754
    }
2755
2756
    public function notBooleanProvider(): Generator
2757
    {
2758
        yield [0];
2759
        yield [1];
2760
        yield [42];
2761
        yield [3.14159];
2762
        yield ['foo'];
2763
        yield [[]];
2764
    }
2765
2766
    public function strictIntegerProvider(): Generator
2767
    {
2768
        yield [-1, -1];
2769
        yield [0, 0];
2770
        yield [1, 1];
2771
    }
2772
2773
    public function nonStrictIntegerProvider(): Generator
2774
    {
2775
        yield ['-1', -1];
2776
        yield ['0', 0];
2777
        yield ['1', 1];
2778
        yield ['+1', 1];
2779
    }
2780
2781
    public function notIntegerProvider(): Generator
2782
    {
2783
        yield [true];
2784
        yield [false];
2785
        yield [3.14159];
2786
        yield ['foo'];
2787
        yield [[]];
2788
    }
2789
2790
    public function strictNumberProvider(): Generator
2791
    {
2792
        yield [-1, -1.];
2793
        yield [0, 0.];
2794
        yield [1, 1.];
2795
        yield [-1., -1.];
2796
        yield [0., 0.];
2797
        yield [1., 1.];
2798
        yield [-.1, -.1];
2799
        yield [.0, .0];
2800
        yield [.1, .1];
2801
    }
2802
2803
    public function nonStrictNumberProvider(): Generator
2804
    {
2805
        yield ['-1', -1.];
2806
        yield ['0', 0.];
2807
        yield ['1', 1.];
2808
        yield ['+1', 1.];
2809
        yield ['-1.', -1.];
2810
        yield ['0.', 0.];
2811
        yield ['1.', 1.];
2812
        yield ['+1.', 1.];
2813
        yield ['-.1', -.1];
2814
        yield ['.0', .0];
2815
        yield ['.1', .1];
2816
        yield ['+.1', .1];
2817
        yield ['-1.0', -1.];
2818
        yield ['0.0', 0.];
2819
        yield ['1.0', 1.];
2820
        yield ['+1.0', 1.];
2821
        yield ['1e-1', .1];
2822
        yield ['1e1', 10.];
2823
        yield ['1e+1', 10.];
2824
        yield ['1.e-1', .1];
2825
        yield ['1.e1', 10.];
2826
        yield ['1.e+1', 10.];
2827
        yield ['.1e-1', .01];
2828
        yield ['.1e1', 1.];
2829
        yield ['.1e+1', 1.];
2830
        yield ['1.0e-1', .1];
2831
        yield ['1.0e1', 10.];
2832
        yield ['1.0e+1', 10.];
2833
    }
2834
2835
    public function notNumberProvider(): Generator
2836
    {
2837
        yield [true];
2838
        yield [false];
2839
        yield ['foo'];
2840
        yield [[]];
2841
    }
2842
2843
    public function strictStringProvider(): Generator
2844
    {
2845
        yield ['foo', 'foo'];
2846
2847
        // Must not be cast to a null
2848
        yield ['', ''];
2849
        yield [' ', ' '];
2850
2851
        // Must not be cast to a boolean
2852
        yield ['true', 'true'];
2853
        yield ['false', 'false'];
2854
        yield ['yes', 'yes'];
2855
        yield ['no', 'no'];
2856
        yield ['on', 'on'];
2857
        yield ['off', 'off'];
2858
2859
        // Must not be cast to a number
2860
        yield ['-1', '-1'];
2861
        yield ['0', '0'];
2862
        yield ['1', '1'];
2863
        yield ['+1', '+1'];
2864
        yield ['-1.', '-1.'];
2865
        yield ['0.', '0.'];
2866
        yield ['1.', '1.'];
2867
        yield ['+1.', '+1.'];
2868
        yield ['-.1', '-.1'];
2869
        yield ['.0', '.0'];
2870
        yield ['.1', '.1'];
2871
        yield ['+.1', '+.1'];
2872
        yield ['-1.0', '-1.0'];
2873
        yield ['0.0', '0.0'];
2874
        yield ['1.0', '1.0'];
2875
        yield ['+1.0', '+1.0'];
2876
        yield ['1e-1', '1e-1'];
2877
        yield ['1e1', '1e1'];
2878
        yield ['1e+1', '1e+1'];
2879
        yield ['1.e-1', '1.e-1'];
2880
        yield ['1.e1', '1.e1'];
2881
        yield ['1.e+1', '1.e+1'];
2882
        yield ['.1e-1', '.1e-1'];
2883
        yield ['.1e1', '.1e1'];
2884
        yield ['.1e+1', '.1e+1'];
2885
        yield ['1.0e-1', '1.0e-1'];
2886
        yield ['1.0e1', '1.0e1'];
2887
        yield ['1.0e+1', '1.0e+1'];
2888
    }
2889
2890
    public function nonStrictStringProvider(): Generator
2891
    {
2892
        yield [-1, '-1'];
2893
        yield [0, '0'];
2894
        yield [1, '1'];
2895
    }
2896
2897
    public function strictNotStringProvider(): Generator
2898
    {
2899
        yield [true];
2900
        yield [false];
2901
        yield [42];
2902
        yield [3.14159];
2903
        yield [[]];
2904
    }
2905
2906
    public function nonStrictNotStringProvider(): Generator
2907
    {
2908
        yield [true];
2909
        yield [false];
2910
        yield [3.14159];
2911
        yield [[]];
2912
    }
2913
2914
    public function emptyArrayProvider(): Generator
2915
    {
2916
        yield [[]];
2917
    }
2918
2919
    public function notArrayProvider(): Generator
2920
    {
2921
        yield [true];
2922
        yield [false];
2923
        yield [42];
2924
        yield [3.14159];
2925
        yield ['foo'];
2926
    }
2927
2928
    public function strictNullDataProvider(): Generator
2929
    {
2930
        foreach ($this->strictNullProvider() as [$actual, $expected]) {
2931
            yield [['value' => $actual], $expected];
2932
        }
2933
    }
2934
2935
    public function nonStrictNullDataProvider(): Generator
2936
    {
2937
        foreach ($this->nonStrictNullProvider() as [$actual, $expected]) {
2938
            yield [['value' => $actual], $expected];
2939
        }
2940
    }
2941
2942
    public function strictBooleanDataProvider(): Generator
2943
    {
2944
        foreach ($this->strictBooleanProvider() as [$actual, $expected]) {
2945
            yield [['value' => $actual], $expected];
2946
        }
2947
    }
2948
2949
    public function nonStrictBooleanDataProvider(): Generator
2950
    {
2951
        foreach ($this->nonStrictBooleanProvider() as [$actual, $expected]) {
2952
            yield [['value' => $actual], $expected];
2953
        }
2954
    }
2955
2956
    public function notBooleanDataProvider(): Generator
2957
    {
2958
        foreach ($this->notBooleanProvider() as [$actual]) {
2959
            yield [['value' => $actual]];
2960
        }
2961
    }
2962
2963
    public function strictIntegerDataProvider(): Generator
2964
    {
2965
        foreach ($this->strictIntegerProvider() as [$actual, $expected]) {
2966
            yield [['value' => $actual], $expected];
2967
        }
2968
    }
2969
2970
    public function nonStrictIntegerDataProvider(): Generator
2971
    {
2972
        foreach ($this->nonStrictIntegerProvider() as [$actual, $expected]) {
2973
            yield [['value' => $actual], $expected];
2974
        }
2975
    }
2976
2977
    public function notIntegerDataProvider(): Generator
2978
    {
2979
        foreach ($this->notIntegerProvider() as [$actual]) {
2980
            yield [['value' => $actual]];
2981
        }
2982
    }
2983
2984
    public function strictNumberDataProvider(): Generator
2985
    {
2986
        foreach ($this->strictNumberProvider() as [$actual, $expected]) {
2987
            yield [['value' => $actual], $expected];
2988
        }
2989
    }
2990
2991
    public function nonStrictNumberDataProvider(): Generator
2992
    {
2993
        foreach ($this->nonStrictNumberProvider() as [$actual, $expected]) {
2994
            yield [['value' => $actual], $expected];
2995
        }
2996
    }
2997
2998
    public function notNumberDataProvider(): Generator
2999
    {
3000
        foreach ($this->notNumberProvider() as [$actual]) {
3001
            yield [['value' => $actual]];
3002
        }
3003
    }
3004
3005
    public function strictStringDataProvider(): Generator
3006
    {
3007
        foreach ($this->strictStringProvider() as [$actual, $expected]) {
3008
            yield [['value' => $actual], $expected];
3009
        }
3010
    }
3011
3012
    public function nonStrictStringDataProvider(): Generator
3013
    {
3014
        foreach ($this->nonStrictStringProvider() as [$actual, $expected]) {
3015
            yield [['value' => $actual], $expected];
3016
        }
3017
    }
3018
3019
    public function strictNotStringDataProvider(): Generator
3020
    {
3021
        foreach ($this->strictNotStringProvider() as [$actual]) {
3022
            yield [['value' => $actual]];
3023
        }
3024
    }
3025
3026
    public function nonStrictNotStringDataProvider(): Generator
3027
    {
3028
        foreach ($this->nonStrictNotStringProvider() as [$actual]) {
3029
            yield [['value' => $actual]];
3030
        }
3031
    }
3032
3033
    public function integerEnumDataProvider(): Generator
3034
    {
3035
        if (PHP_VERSION_ID < 80100) {
3036
            return [[[], null]];
3037
        }
3038
3039
        $foo = Fixture\IntegerEnum::FOO;
3040
        $bar = Fixture\IntegerEnum::BAR;
3041
        $baz = Fixture\IntegerEnum::BAZ;
3042
3043
        yield [['value' => $foo->value], $foo];
3044
        yield [['value' => $bar->value], $bar];
3045
        yield [['value' => $baz->value], $baz];
3046
3047
        yield [['value' => (string) $foo->value], $foo];
3048
        yield [['value' => (string) $bar->value], $bar];
3049
        yield [['value' => (string) $baz->value], $baz];
3050
    }
3051
3052
    public function stringEnumDataProvider(): Generator
3053
    {
3054
        if (PHP_VERSION_ID < 80100) {
3055
            return [[[], null]];
3056
        }
3057
3058
        $foo = Fixture\StringEnum::FOO;
3059
        $bar = Fixture\StringEnum::BAR;
3060
        $baz = Fixture\StringEnum::BAZ;
3061
3062
        yield [['value' => $foo->value], $foo];
3063
        yield [['value' => $bar->value], $bar];
3064
        yield [['value' => $baz->value], $baz];
3065
    }
3066
3067
    public function myclabsEnumDataProvider(): Generator
3068
    {
3069
        $foo = Fixture\MyclabsEnum::FOO();
0 ignored issues
show
Bug introduced by
The method FOO() does not exist on Sunrise\Hydrator\Tests\Fixture\MyclabsEnum. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

3069
        /** @scrutinizer ignore-call */ 
3070
        $foo = Fixture\MyclabsEnum::FOO();
Loading history...
3070
        $bar = Fixture\MyclabsEnum::BAR();
0 ignored issues
show
Bug introduced by
The method BAR() does not exist on Sunrise\Hydrator\Tests\Fixture\MyclabsEnum. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

3070
        /** @scrutinizer ignore-call */ 
3071
        $bar = Fixture\MyclabsEnum::BAR();
Loading history...
3071
        $baz = Fixture\MyclabsEnum::BAZ();
0 ignored issues
show
Bug introduced by
The method BAZ() does not exist on Sunrise\Hydrator\Tests\Fixture\MyclabsEnum. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

3071
        /** @scrutinizer ignore-call */ 
3072
        $baz = Fixture\MyclabsEnum::BAZ();
Loading history...
3072
3073
        yield [['value' => $foo->getValue()], $foo];
3074
        yield [['value' => $bar->getValue()], $bar];
3075
        yield [['value' => $baz->getValue()], $baz];
3076
    }
3077
3078
    public function arrayDataProvider(): Generator
3079
    {
3080
        yield [['value' => []], []];
3081
        yield [['value' => ['foo']], ['foo']];
3082
    }
3083
3084
    public function notArrayDataProvider(): Generator
3085
    {
3086
        foreach ($this->notArrayProvider() as [$actual]) {
3087
            yield [['value' => $actual]];
3088
        }
3089
    }
3090
3091
    public function timestampDataProvider(): Generator
3092
    {
3093
        // default formatted timestamp
3094
        $timestamp = date(TimestampTypeConverter::DEFAULT_FORMAT);
3095
3096
        yield [['value' => $timestamp], $timestamp];
3097
        yield [['value' => $timestamp], $timestamp, TimestampTypeConverter::DEFAULT_FORMAT];
3098
3099
        yield [['value' => '700101'], '700101', 'ymd'];
3100
        yield [['value' => '000000'], '000000', 'His'];
3101
3102
        yield [['value' => '-1'], '-1', 'U'];
3103
        yield [['value' => '0'], '0', 'U'];
3104
        yield [['value' => '1'], '1', 'U'];
3105
        yield [['value' => '+1'], '1', 'U'];
3106
3107
        // Must be converted to a string...
3108
        yield [['value' => -1], '-1', 'U'];
3109
        yield [['value' => 0], '0', 'U'];
3110
        yield [['value' => 1], '1', 'U'];
3111
3112
        // The timezone must be applied...
3113
        yield [['value' => '00:00:00'], '00:00:00', 'H:i:s', 'Europe/Kiev'];
3114
3115
        // ISO 8601
3116
        yield [['value' => '00:00:00.123456'], '00:00:00.123456', 'H:i:s.u'];
3117
        yield [['value' => '00:00:00.123456+00:00'], '00:00:00.123456+00:00', 'H:i:s.uP'];
3118
        yield [['value' => 'Monday 00:00:00.123456'], 'Monday 00:00:00.123456', 'l H:i:s.u'];
3119
        yield [['value' => '00:00:00.1234567890'], '00:00:00.123456', 'H:i:s.u'];
3120
        yield [['value' => '00:00:00.1234567890+00:00'], '00:00:00.123456+00:00', 'H:i:s.uP'];
3121
        yield [['value' => 'Monday 00:00:00.1234567890'], 'Monday 00:00:00.123456', 'l H:i:s.u'];
3122
    }
3123
3124
    public function invalidTimestampDataProvider(): Generator
3125
    {
3126
        yield [
3127
            ['value' => '01/01/1970 00:00:00'],
3128
            'Y-m-d H:i:s',
3129
            ErrorCode::INVALID_TIMESTAMP,
3130
            'This value is not a valid timestamp; expected format: Y-m-d H:i:s.',
3131
        ];
3132
3133
        yield [
3134
            ['value' => '1970-01-01 00:00:00'],
3135
            'U',
3136
            ErrorCode::MUST_BE_INTEGER,
3137
            'This value must be of type integer.',
3138
        ];
3139
3140
        yield [
3141
            ['value' => 0],
3142
            'Y',
3143
            ErrorCode::MUST_BE_STRING,
3144
            'This value must be of type string.',
3145
        ];
3146
    }
3147
3148
    public function timezoneDataProvider(): Generator
3149
    {
3150
        foreach (DateTimeZone::listIdentifiers() as $timezone) {
3151
            yield [['value' => $timezone], $timezone];
3152
        }
3153
    }
3154
3155
    public function uuidDataProvider(): Generator
3156
    {
3157
        yield [['value' => '207ddb61-c300-4368-9f26-33d0a99eac00'], '207ddb61-c300-4368-9f26-33d0a99eac00'];
3158
    }
3159
3160
    private function createHydrator(array $context = [], array $typeConverters = []): HydratorInterface
3161
    {
3162
        $hydrator = new Hydrator($context, $typeConverters);
3163
        if (PHP_VERSION_ID < 80000) {
3164
            $hydrator->useDefaultAnnotationReader();
0 ignored issues
show
Deprecated Code introduced by
The function Sunrise\Hydrator\Hydrato...faultAnnotationReader() has been deprecated: 3.2.0 Use the {@see setAnnotationReader()} method with the {@see DoctrineAnnotationReader::default()} attribute. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

3164
            /** @scrutinizer ignore-deprecated */ $hydrator->useDefaultAnnotationReader();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
3165
        }
3166
3167
        return $hydrator;
3168
    }
3169
3170
    private function phpRequired(string $version): void
3171
    {
3172
        if (version_compare(PHP_VERSION, $version, '<')) {
3173
            $this->markTestSkipped(sprintf('PHP %s is required.', $version));
3174
        }
3175
    }
3176
3177
    private function assertInvalidValueExceptionCount(int $expectedCount): void
3178
    {
3179
        $this->invalidValueExceptionCount = $expectedCount;
3180
    }
3181
3182
    private function assertInvalidValueExceptionMessage(int $exceptionIndex, string $expectedMessage): void
3183
    {
3184
        $this->invalidValueExceptionMessage[] = [$exceptionIndex, $expectedMessage];
3185
    }
3186
3187
    private function assertInvalidValueExceptionPropertyPath(int $exceptionIndex, string $expectedPropertyPath): void
3188
    {
3189
        $this->invalidValueExceptionPropertyPath[] = [$exceptionIndex, $expectedPropertyPath];
3190
    }
3191
3192
    private function assertInvalidValueExceptionErrorCode(int $exceptionIndex, string $expectedErrorCode): void
3193
    {
3194
        $this->invalidValueExceptionErrorCode[] = [$exceptionIndex, $expectedErrorCode];
3195
    }
3196
3197
    private function assertInvalidValueExceptionTranslationDomain(
3198
        int $exceptionIndex,
3199
        string $expectedTranslationDomain
3200
    ): void {
3201
        $this->invalidValueExceptionTranslationDomain[] = [$exceptionIndex, $expectedTranslationDomain];
3202
    }
3203
3204
    protected function runTest(): void
3205
    {
3206
        $invalidDataExceptionHandled = false;
3207
3208
        try {
3209
            parent::runTest();
3210
        } catch (InvalidDataException $invalidDataException) {
3211
            $invalidDataExceptionMessages = [];
3212
            foreach ($invalidDataException->getExceptions() as $invalidValueException) {
3213
                $invalidDataExceptionMessages[] = sprintf(
3214
                    '[%s] %s',
3215
                    $invalidValueException->getPropertyPath(),
3216
                    $invalidValueException->getMessage(),
3217
                );
3218
            }
3219
3220
            if (isset($this->invalidValueExceptionCount)) {
3221
                $invalidDataExceptionHandled = true;
3222
                $this->assertCount(
3223
                    $this->invalidValueExceptionCount,
0 ignored issues
show
Bug introduced by
It seems like $this->invalidValueExceptionCount can also be of type null; however, parameter $expectedCount of PHPUnit\Framework\Assert::assertCount() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3223
                    /** @scrutinizer ignore-type */ $this->invalidValueExceptionCount,
Loading history...
3224
                    $invalidDataException->getExceptions(),
3225
                    \join(\PHP_EOL, $invalidDataExceptionMessages),
3226
                );
3227
            }
3228
3229
            foreach ($this->invalidValueExceptionMessage as [$index, $invalidValueExceptionMessage]) {
3230
                $invalidDataExceptionHandled = true;
3231
                $this->assertArrayHasKey($index, $invalidDataException->getExceptions());
3232
                $this->assertSame(
3233
                    $invalidValueExceptionMessage,
3234
                    $invalidDataException->getExceptions()[$index]->getMessage(),
3235
                );
3236
            }
3237
3238
            foreach ($this->invalidValueExceptionPropertyPath as [$index, $invalidValueExceptionPropertyPath]) {
3239
                $invalidDataExceptionHandled = true;
3240
                $this->assertArrayHasKey($index, $invalidDataException->getExceptions());
3241
                $this->assertSame(
3242
                    $invalidValueExceptionPropertyPath,
3243
                    $invalidDataException->getExceptions()[$index]->getPropertyPath(),
3244
                );
3245
            }
3246
3247
            foreach ($this->invalidValueExceptionErrorCode as [$index, $invalidValueExceptionErrorCode]) {
3248
                $invalidDataExceptionHandled = true;
3249
                $this->assertArrayHasKey($index, $invalidDataException->getExceptions());
3250
                $this->assertSame(
3251
                    $invalidValueExceptionErrorCode,
3252
                    $invalidDataException->getExceptions()[$index]->getErrorCode(),
3253
                );
3254
            }
3255
3256
            foreach ($this->invalidValueExceptionTranslationDomain as [
3257
                $index,
3258
                $invalidValueExceptionTranslationDomain,
3259
            ]) {
3260
                $invalidDataExceptionHandled = true;
3261
                $this->assertArrayHasKey($index, $invalidDataException->getExceptions());
3262
                $this->assertSame(
3263
                    $invalidValueExceptionTranslationDomain,
3264
                    $invalidDataException->getExceptions()[$index]->getTranslationDomain(),
3265
                );
3266
            }
3267
3268
            if (!$invalidDataExceptionHandled) {
3269
                throw $invalidDataException;
3270
            }
3271
        } finally {
3272
            $this->invalidValueExceptionCount = null;
3273
            $this->invalidValueExceptionMessage = [];
3274
            $this->invalidValueExceptionPropertyPath = [];
3275
            $this->invalidValueExceptionErrorCode = [];
3276
            $this->invalidValueExceptionTranslationDomain = [];
3277
3278
            if ($invalidDataExceptionHandled) {
3279
                $this->assertTrue(true);
3280
            }
3281
        }
3282
    }
3283
}
3284