= 8 */ public function test_object_type_is_narrowed_correctly_for_simple_case(): void { try { $resultFoo = (new MapperBuilder())->mapper()->map(NativeUnionOfObjects::class, [ 'foo' => 'foo', ]); $resultBar = (new MapperBuilder())->mapper()->map(NativeUnionOfObjects::class, [ 'bar' => 'bar', ]); } catch (MappingError $error) { $this->mappingFail($error); } self::assertInstanceOf(\CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SomeFooObject::class, $resultFoo->object); self::assertInstanceOf(\CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SomeBarObject::class, $resultBar->object); } public function test_object_type_is_narrowed_correctly_for_simple_array_case(): void { try { $result = (new MapperBuilder())->mapper()->map(UnionOfFooAndBar::class, [ 'foo' => ['foo' => 'foo'], 'bar' => ['bar' => 'bar'], ]); } catch (MappingError $error) { $this->mappingFail($error); } self::assertInstanceOf(SomeFooObject::class, $result->objects['foo']); self::assertInstanceOf(SomeBarObject::class, $result->objects['bar']); } public function test_objects_sharing_one_property_are_resolved_correctly(): void { try { $result = (new MapperBuilder())->mapper()->map(UnionOfFooAndBarAndFoo::class, [ ['foo' => 'foo'], ['foo' => 'foo', 'bar' => 'bar'], ]); } catch (MappingError $error) { $this->mappingFail($error); } self::assertInstanceOf(SomeFooObject::class, $result->objects[0]); self::assertInstanceOf(SomeFooAndBarObject::class, $result->objects[1]); } /** * * @dataProvider mapping_error_when_cannot_resolve_union_data_provider * * @param class-string $className * @param mixed[] $source */ public function test_mapping_error_when_cannot_resolve_union(string $className, array $source): void { try { (new MapperBuilder())->mapper()->map($className, $source); self::fail('No mapping error when one was expected'); } catch (MappingError $exception) { $error = $exception->node()->children()['objects']->children()[0]->messages()[0]; self::assertSame('1642787246', $error->code()); } } public function mapping_error_when_cannot_resolve_union_data_provider(): iterable { yield [ 'className' => UnionOfFooAndBar::class, 'source' => [['foo' => 'foo', 'bar' => 'bar']], ]; yield [ 'className' => UnionOfFooAndAnotherFoo::class, 'source' => [['foo' => 'foo']], ]; } } // @PHP8.1 Readonly properties final class UnionOfFooAndBar { /** @var array */ public array $objects; } // @PHP8.1 Readonly properties final class UnionOfFooAndAnotherFoo { /** @var array */ public array $objects; } // @PHP8.1 Readonly properties final class UnionOfFooAndBarAndFoo { /** @var array */ public array $objects; } // @PHP8.1 Readonly properties final class SomeFooObject { public string $foo; } // @PHP8.1 Readonly properties final class SomeOtherFooObject { public string $foo; } // @PHP8.1 Readonly properties final class SomeBarObject { public string $bar; } // @PHP8.1 Readonly properties final class SomeFooAndBarObject { public string $foo; public string $bar; }