1<?php
2
3namespace spec\Prophecy\Doubler;
4
5use PhpSpec\ObjectBehavior;
6use Prophecy\Doubler\ClassPatch\ClassPatchInterface;
7use Prophecy\Doubler\Generator\ClassCreator;
8use Prophecy\Doubler\Generator\ClassMirror;
9use Prophecy\Doubler\Generator\Node\ClassNode;
10use Prophecy\Doubler\NameGenerator;
11
12class DoublerSpec extends ObjectBehavior
13{
14    function let(ClassMirror $mirror, ClassCreator $creator, NameGenerator $namer)
15    {
16        $this->beConstructedWith($mirror, $creator, $namer);
17    }
18
19    function it_does_not_have_patches_by_default()
20    {
21        $this->getClassPatches()->shouldHaveCount(0);
22    }
23
24    function its_registerClassPatch_adds_a_patch_to_the_doubler(ClassPatchInterface $patch)
25    {
26        $this->registerClassPatch($patch);
27        $this->getClassPatches()->shouldReturn(array($patch));
28    }
29
30    function its_getClassPatches_sorts_patches_by_priority(
31        ClassPatchInterface $alt1,
32        ClassPatchInterface $alt2,
33        ClassPatchInterface $alt3,
34        ClassPatchInterface $alt4
35    ) {
36        $alt1->getPriority()->willReturn(2);
37        $alt2->getPriority()->willReturn(50);
38        $alt3->getPriority()->willReturn(10);
39        $alt4->getPriority()->willReturn(0);
40
41        $this->registerClassPatch($alt1);
42        $this->registerClassPatch($alt2);
43        $this->registerClassPatch($alt3);
44        $this->registerClassPatch($alt4);
45
46        $this->getClassPatches()->shouldReturn(array($alt2, $alt3, $alt1, $alt4));
47    }
48
49    function its_double_mirrors_alterates_and_instantiates_provided_class(
50        $mirror,
51        $creator,
52        $namer,
53        ClassPatchInterface $alt1,
54        ClassPatchInterface $alt2,
55        \ReflectionClass $class,
56        \ReflectionClass $interface1,
57        \ReflectionClass $interface2,
58        ClassNode $node
59    ) {
60        $mirror->reflect($class, array($interface1, $interface2))->willReturn($node);
61        $alt1->supports($node)->willReturn(true);
62        $alt2->supports($node)->willReturn(false);
63        $alt1->getPriority()->willReturn(1);
64        $alt2->getPriority()->willReturn(2);
65        $namer->name($class, array($interface1, $interface2))->willReturn('SplStack');
66        $class->getName()->willReturn('stdClass');
67        $interface1->getName()->willReturn('ArrayAccess');
68        $interface2->getName()->willReturn('Iterator');
69
70        $alt1->apply($node)->shouldBeCalled();
71        $alt2->apply($node)->shouldNotBeCalled();
72        $creator->create('SplStack', $node)->shouldBeCalled();
73
74        $this->registerClassPatch($alt1);
75        $this->registerClassPatch($alt2);
76
77        $this->double($class, array($interface1, $interface2))
78            ->shouldReturnAnInstanceOf('SplStack');
79    }
80
81    function it_double_instantiates_a_class_with_constructor_argument(
82        $mirror,
83        \ReflectionClass $class,
84        ClassNode $node,
85        $namer
86    ) {
87        $class->getName()->willReturn('ReflectionClass');
88        $mirror->reflect($class, array())->willReturn($node);
89        $namer->name($class, array())->willReturn('ReflectionClass');
90
91        $double = $this->double($class, array(), array('stdClass'));
92        $double->shouldBeAnInstanceOf('ReflectionClass');
93        $double->getName()->shouldReturn('stdClass');
94    }
95
96    function it_can_instantiate_class_with_final_constructor(
97        $mirror,
98        \ReflectionClass $class,
99        ClassNode $node,
100        $namer
101    ) {
102        $class->getName()->willReturn('spec\Prophecy\Doubler\WithFinalConstructor');
103        $mirror->reflect($class, array())->willReturn($node);
104        $namer->name($class, array())->willReturn('spec\Prophecy\Doubler\WithFinalConstructor');
105
106        $double = $this->double($class, array());
107
108        $double->shouldBeAnInstanceOf('spec\Prophecy\Doubler\WithFinalConstructor');
109    }
110}
111
112class WithFinalConstructor
113{
114    final public function __construct() {}
115}
116