public function testCanDenormalizeCompleteSpecs()
{
$fixture = new FakeFixture();
$specs = ['__construct' => $construct = ['<latitude()>'], 'username' => '<name()>', 'name' => 'bob', '__calls' => [['setLocation' => $setLocationArgs = ['<latitude()>', '<longitude()>']]]];
$flagParserProphecy = $this->prophesize(FlagParserInterface::class);
$flagParserProphecy->parse('username')->willReturn($usernameFlags = new FlagBag('parsed_username'));
$flagParserProphecy->parse('name')->willReturn($nameFlags = new FlagBag('parsed_name'));
/** @var FlagParserInterface $flagParser */
$flagParser = $flagParserProphecy->reveal();
$constructorDenormalizerProphecy = $this->prophesize(ConstructorDenormalizerInterface::class);
$constructorDenormalizerProphecy->denormalize($fixture, $flagParser, $construct)->willReturn($constructor = new FakeMethodCall());
/** @var ConstructorDenormalizerInterface $constructorDenormalizer */
$constructorDenormalizer = $constructorDenormalizerProphecy->reveal();
$propertyDenormalizerProphecy = $this->prophesize(PropertyDenormalizerInterface::class);
$propertyDenormalizerProphecy->denormalize($fixture, 'parsed_username', '<name()>', $usernameFlags)->willReturn($usernameProp = new Property('username', '<name()>'));
$propertyDenormalizerProphecy->denormalize($fixture, 'parsed_name', 'bob', $nameFlags)->willReturn($nameProp = new Property('name', 'bob'));
/** @var PropertyDenormalizerInterface $propertyDenormalizer */
$propertyDenormalizer = $propertyDenormalizerProphecy->reveal();
$callsDenormalizerProphecy = $this->prophesize(CallsDenormalizerInterface::class);
$callsDenormalizerProphecy->denormalize($fixture, $flagParser, 'setLocation', $setLocationArgs)->willReturn($call = new NoMethodCall());
/** @var CallsDenormalizerInterface $callsDenormalizer */
$callsDenormalizer = $callsDenormalizerProphecy->reveal();
$expected = new SpecificationBag($constructor, (new PropertyBag())->with($usernameProp)->with($nameProp), (new MethodCallBag())->with($call));
$denormalizer = new SimpleSpecificationsDenormalizer($constructorDenormalizer, $propertyDenormalizer, $callsDenormalizer);
$actual = $denormalizer->denormalize(new FakeFixture(), $flagParser, $specs);
$this->assertEquals($expected, $actual);
$flagParserProphecy->parse(Argument::any())->shouldHaveBeenCalledTimes(2);
$constructorDenormalizerProphecy->denormalize(Argument::cetera())->shouldHaveBeenCalledTimes(1);
$propertyDenormalizerProphecy->denormalize(Argument::cetera())->shouldHaveBeenCalledTimes(2);
$callsDenormalizerProphecy->denormalize(Argument::cetera())->shouldHaveBeenCalledTimes(1);
}