1<?php
2
3namespace spec\Prophecy\Call;
4
5use PhpSpec\ObjectBehavior;
6use Prophecy\Promise\PromiseInterface;
7use Prophecy\Prophecy\MethodProphecy;
8use Prophecy\Prophecy\ObjectProphecy;
9use Prophecy\Argument\ArgumentsWildcard;
10
11class CallCenterSpec extends ObjectBehavior
12{
13    function let(ObjectProphecy $objectProphecy)
14    {
15    }
16
17    function it_records_calls_made_through_makeCall_method(ObjectProphecy $objectProphecy, ArgumentsWildcard $wildcard)
18    {
19        $wildcard->scoreArguments(array(5, 2, 3))->willReturn(10);
20        $objectProphecy->getMethodProphecies()->willReturn(array());
21
22        $this->makeCall($objectProphecy, 'setValues', array(5, 2, 3));
23
24        $calls = $this->findCalls('setValues', $wildcard);
25        $calls->shouldHaveCount(1);
26
27        $calls[0]->shouldBeAnInstanceOf('Prophecy\Call\Call');
28        $calls[0]->getMethodName()->shouldReturn('setValues');
29        $calls[0]->getArguments()->shouldReturn(array(5, 2, 3));
30        $calls[0]->getReturnValue()->shouldReturn(null);
31    }
32
33    function it_returns_null_for_any_call_through_makeCall_if_no_method_prophecies_added(
34        $objectProphecy
35    )
36    {
37        $objectProphecy->getMethodProphecies()->willReturn(array());
38
39        $this->makeCall($objectProphecy, 'setValues', array(5, 2, 3))->shouldReturn(null);
40    }
41
42    function it_executes_promise_of_method_prophecy_that_matches_signature_passed_to_makeCall(
43        $objectProphecy,
44        MethodProphecy $method1,
45        MethodProphecy $method2,
46        MethodProphecy $method3,
47        ArgumentsWildcard $arguments1,
48        ArgumentsWildcard $arguments2,
49        ArgumentsWildcard $arguments3,
50        PromiseInterface $promise
51    ) {
52        $method1->hasReturnVoid()->willReturn(false);
53        $method1->getMethodName()->willReturn('getName');
54        $method1->getArgumentsWildcard()->willReturn($arguments1);
55        $arguments1->scoreArguments(array('world', 'everything'))->willReturn(false);
56
57        $method2->hasReturnVoid()->willReturn(false);
58        $method2->getMethodName()->willReturn('setTitle');
59        $method2->getArgumentsWildcard()->willReturn($arguments2);
60        $arguments2->scoreArguments(array('world', 'everything'))->willReturn(false);
61
62        $method3->hasReturnVoid()->willReturn(false);
63        $method3->getMethodName()->willReturn('getName');
64        $method3->getArgumentsWildcard()->willReturn($arguments3);
65        $method3->getPromise()->willReturn($promise);
66        $arguments3->scoreArguments(array('world', 'everything'))->willReturn(200);
67
68        $objectProphecy->getMethodProphecies()->willReturn(array(
69            'method1' => array($method1),
70            'method2' => array($method2, $method3)
71        ));
72        $objectProphecy->getMethodProphecies('getName')->willReturn(array($method1, $method3));
73        $objectProphecy->reveal()->willReturn(new \stdClass());
74
75        $promise->execute(array('world', 'everything'), $objectProphecy->getWrappedObject(), $method3)->willReturn(42);
76
77        $this->makeCall($objectProphecy, 'getName', array('world', 'everything'))->shouldReturn(42);
78
79        $calls = $this->findCalls('getName', $arguments3);
80        $calls->shouldHaveCount(1);
81        $calls[0]->getReturnValue()->shouldReturn(42);
82    }
83
84    function it_executes_promise_of_method_prophecy_that_matches_with_highest_score_to_makeCall(
85        $objectProphecy,
86        MethodProphecy $method1,
87        MethodProphecy $method2,
88        MethodProphecy $method3,
89        ArgumentsWildcard $arguments1,
90        ArgumentsWildcard $arguments2,
91        ArgumentsWildcard $arguments3,
92        PromiseInterface $promise
93    ) {
94        $method1->hasReturnVoid()->willReturn(false);
95        $method1->getMethodName()->willReturn('getName');
96        $method1->getArgumentsWildcard()->willReturn($arguments1);
97        $arguments1->scoreArguments(array('world', 'everything'))->willReturn(50);
98
99        $method2->hasReturnVoid()->willReturn(false);
100        $method2->getMethodName()->willReturn('getName');
101        $method2->getArgumentsWildcard()->willReturn($arguments2);
102        $method2->getPromise()->willReturn($promise);
103        $arguments2->scoreArguments(array('world', 'everything'))->willReturn(300);
104
105        $method3->hasReturnVoid()->willReturn(false);
106        $method3->getMethodName()->willReturn('getName');
107        $method3->getArgumentsWildcard()->willReturn($arguments3);
108        $arguments3->scoreArguments(array('world', 'everything'))->willReturn(200);
109
110        $objectProphecy->getMethodProphecies()->willReturn(array(
111            'method1' => array($method1),
112            'method2' => array($method2, $method3)
113        ));
114        $objectProphecy->getMethodProphecies('getName')->willReturn(array(
115            $method1, $method2, $method3
116        ));
117        $objectProphecy->reveal()->willReturn(new \stdClass());
118
119        $promise->execute(array('world', 'everything'), $objectProphecy->getWrappedObject(), $method2)
120            ->willReturn('second');
121
122        $this->makeCall($objectProphecy, 'getName', array('world', 'everything'))
123            ->shouldReturn('second');
124    }
125
126    function it_throws_exception_if_call_does_not_match_any_of_defined_method_prophecies(
127        $objectProphecy,
128        MethodProphecy $method,
129        ArgumentsWildcard $arguments
130    ) {
131        $method->getMethodName()->willReturn('getName');
132        $method->getArgumentsWildcard()->willReturn($arguments);
133        $arguments->scoreArguments(array('world', 'everything'))->willReturn(false);
134        $arguments->__toString()->willReturn('arg1, arg2');
135
136        $objectProphecy->getMethodProphecies()->willReturn(array('method1' => array($method)));
137        $objectProphecy->getMethodProphecies('getName')->willReturn(array($method));
138
139        $this->shouldThrow('Prophecy\Exception\Call\UnexpectedCallException')
140            ->duringMakeCall($objectProphecy, 'getName', array('world', 'everything'));
141    }
142
143    function it_returns_null_if_method_prophecy_that_matches_makeCall_arguments_has_no_promise(
144        $objectProphecy,
145        MethodProphecy $method,
146        ArgumentsWildcard $arguments
147    ) {
148        $method->hasReturnVoid()->willReturn(false);
149        $method->getMethodName()->willReturn('getName');
150        $method->getArgumentsWildcard()->willReturn($arguments);
151        $method->getPromise()->willReturn(null);
152        $arguments->scoreArguments(array('world', 'everything'))->willReturn(100);
153
154        $objectProphecy->getMethodProphecies()->willReturn(array($method));
155        $objectProphecy->getMethodProphecies('getName')->willReturn(array($method));
156
157        $this->makeCall($objectProphecy, 'getName', array('world', 'everything'))
158            ->shouldReturn(null);
159    }
160
161    function it_finds_recorded_calls_by_a_method_name_and_arguments_wildcard(
162        $objectProphecy,
163        ArgumentsWildcard $wildcard
164    ) {
165        $objectProphecy->getMethodProphecies()->willReturn(array());
166
167        $this->makeCall($objectProphecy, 'getName', array('world'));
168        $this->makeCall($objectProphecy, 'getName', array('everything'));
169        $this->makeCall($objectProphecy, 'setName', array(42));
170
171        $wildcard->scoreArguments(array('world'))->willReturn(false);
172        $wildcard->scoreArguments(array('everything'))->willReturn(10);
173
174        $calls = $this->findCalls('getName', $wildcard);
175
176        $calls->shouldHaveCount(1);
177        $calls[0]->getMethodName()->shouldReturn('getName');
178        $calls[0]->getArguments()->shouldReturn(array('everything'));
179    }
180}
181