Completed
Pull Request — master (#4)
by Laurens
03:17
created

getClientProxyMock()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 29
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 29
rs 8.8571
cc 1
eloc 24
nc 1
nop 1
1
<?php
2
3
namespace Tests\Werkspot\BingAdsApiBundle\Tests\Api\Report;
4
5
use BingAds\Bulk\ReportTimePeriod;
6
use BingAds\Proxy\ClientProxy;
7
use BingAds\Reporting\AccountThroughAdGroupReportScope;
8
use BingAds\Reporting\GeoLocationPerformanceReportRequest;
9
use BingAds\Reporting\NonHourlyReportAggregation;
10
use BingAds\Reporting\ReportFormat;
11
use BingAds\Reporting\ReportTime;
12
use Mockery;
13
use PHPUnit_Framework_TestCase;
14
use Symfony\Component\Filesystem\Filesystem;
15
use stdClass;
16
use SoapFault;
17
use Werkspot\BingAdsApiBundle\Api\Client;
18
use Werkspot\BingAdsApiBundle\Api\Exceptions;
19
use Werkspot\BingAdsApiBundle\Api\Helper;
20
use Werkspot\BingAdsApiBundle\Api\Report\GeoLocationPerformanceReport;
21
use Werkspot\BingAdsApiBundle\Guzzle\OauthTokenService;
22
use Werkspot\BingAdsApiBundle\Model\AccessToken;
23
use Werkspot\BingAdsApiBundle\Model\ApiDetails;
24
25
class GeoLocationPerformanceReportTest extends PHPUnit_Framework_TestCase
26
{
27
    const YESTERDAY = 'Yesterday';
28
    const ACCESS_TOKEN = '2ec09aeccaf634d982eec793037e37fe';
29
    const REFRESH_TOKEN = '0c59f7e609b0cc467067e39d523116ce';
30
31
    public function testGetRequest()
32
    {
33
        $expected = new GeoLocationPerformanceReportRequest();
34
        $expected->Format = ReportFormat::Csv;
35
        $expected->ReportName = GeoLocationPerformanceReport::NAME;
36
        $expected->ReturnOnlyCompleteData = true;
37
        $expected->Aggregation = NonHourlyReportAggregation::Daily;
38
        $expected->Scope = new AccountThroughAdGroupReportScope();
39
        $expected->Time = new ReportTime();
40
        $expected->Time->PredefinedTime = self::YESTERDAY;
1 ignored issue
show
Documentation Bug introduced by
It seems like self::YESTERDAY of type string is incompatible with the declared type object<BingAds\Reporting\ReportTimePeriod> of property $PredefinedTime.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
41
        $expected->Columns = [];
42
43
        $report = new GeoLocationPerformanceReport();
44
        $report->setTimePeriod(self::YESTERDAY);
45
        $report->setColumns([]);
46
        $result = $report->getRequest();
47
48
        $this->assertEquals($expected, $result);
49
    }
50
51
    public function testSetAggregation()
52
    {
53
        $report = new GeoLocationPerformanceReport();
54
55
        $result = $report->getRequest([], self::YESTERDAY);
0 ignored issues
show
Unused Code introduced by
The call to GeoLocationPerformanceReport::getRequest() has too many arguments starting with array().

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
56
        $this->assertEquals(NonHourlyReportAggregation::Daily, $result->Aggregation);
57
58
        $report->setAggregation(NonHourlyReportAggregation::Monthly);
59
        $result = $report->getRequest([], self::YESTERDAY);
0 ignored issues
show
Unused Code introduced by
The call to GeoLocationPerformanceReport::getRequest() has too many arguments starting with array().

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
60
61
        $this->assertEquals(NonHourlyReportAggregation::Monthly, $result->Aggregation);
62
    }
63
64
    public function testGeoLocationPerformanceReportReturnsArrayWithCsv()
65
    {
66
        $apiClient = $this->getApiClient(
67
            $this->getRequestNewAccessTokenMock(),
68
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
69
            $this->getClientProxyMock(),
70
            $this->getFileHelperMock(),
71
            $this->getCsvHelperMock(),
72
            $this->getTimeHelperMock()
73
        );
74
        $result = $apiClient->get(['TimePeriod', 'AccountName', 'AdGroupId'], 'GeoLocationPerformanceReport', ReportTimePeriod::LastWeek);
75
        $this->assertEquals([ASSETS_DIR . 'report.csv'], $result);
76
    }
77
78
    public function testGeoLocationPerformanceReportMoveFile()
79
    {
80
        $apiClient = $this->getApiClient(
81
            $this->getRequestNewAccessTokenMock(),
82
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
83
            $this->getClientProxyMock(),
84
            $this->getFileHelperMock(),
85
            $this->getCsvHelperMock(),
86
            $this->getTimeHelperMock()
87
        );
88
        $result = $apiClient->get(['TimePeriod', 'AccountName', 'AdGroupId'], 'GeoLocationPerformanceReport', ReportTimePeriod::LastWeek, ASSETS_DIR . 'test.csv');
89
        $this->assertEquals(ASSETS_DIR . 'test.csv', $result);
90
91
        //--Move File back
92
        $fileSystem = new Filesystem();
93
        $fileSystem->rename(ASSETS_DIR . 'test.csv', ASSETS_DIR . 'report.csv');
94
    }
95
96
    public function testGetRefreshToken()
97
    {
98
        $apiClient = $this->getApiClient(
99
            $this->getRequestNewAccessTokenMock(),
100
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
101
            $this->getClientProxyMock(),
102
            $this->getFileHelperMock(),
103
            $this->getCsvHelperMock(),
104
            $this->getTimeHelperMock()
105
        );
106
107
        $this->assertEquals('refreshToken', $apiClient->getRefreshToken());
108
109
        $apiClient->get(['TimePeriod', 'AccountName', 'AdGroupId'], 'GeoLocationPerformanceReport', ReportTimePeriod::LastWeek);
110
        $this->assertEquals(self::REFRESH_TOKEN, $apiClient->getRefreshToken());
111
    }
112
113 View Code Duplication
    public function testGeoLocationPerformanceReportTimeoutException()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
114
    {
115
        $this->expectException(Exceptions\RequestTimeoutException::class);
116
        $apiClient = $this->getApiClient(
117
            $this->getRequestNewAccessTokenMock(),
118
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
119
            $this->getClientProxyMock('Pending'),
120
            new Helper\File(),
121
            new Helper\Csv(),
122
            $this->getTimeHelperMock()
123
        );
124
        $apiClient->get(['TimePeriod', 'AccountName', 'AdGroupId'], 'GeoLocationPerformanceReport');
125
    }
126
127 View Code Duplication
    public function testGeoLocationPerformanceReportRequestErrorException()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
128
    {
129
        $this->expectException(Exceptions\ReportRequestErrorException::class);
130
        $apiClient = $this->getApiClient(
131
            $this->getRequestNewAccessTokenMock(),
132
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
133
            $this->getClientProxyMock('Error'),
134
            new Helper\File(),
135
            new Helper\Csv(),
136
            $this->getTimeHelperMock()
137
        );
138
        $apiClient->get(['TimePeriod', 'AccountName', 'AdGroupId'], 'GeoLocationPerformanceReport');
139
    }
140
141
    public function testPollGenerateReportSoapException()
142
    {
143
        $clientProxyMock = Mockery::mock(ClientProxy::class);
144
        $clientProxyMock->ReportRequestId = 'reportID';
1 ignored issue
show
Bug introduced by
Accessing ReportRequestId on the interface Mockery\MockInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
145
        $clientProxyMock
1 ignored issue
show
Bug introduced by
The method shouldReceive() does not seem to exist on object<Mockery\Expectation>.

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...
146
            ->shouldReceive('ConstructWithCredentials')
147
            ->andReturnSelf()
148
            ->once()
149
            ->shouldReceive('GetNamespace')
150
            ->once()
151
            ->andReturn('Namespace')
152
            ->shouldReceive('GetService')
153
            ->twice()
154
            ->andReturnSelf()
155
            ->shouldReceive('SubmitGenerateReport')
156
            ->once()
157
            ->andReturnSelf()
158
            ->shouldReceive('PollGenerateReport')
159
            ->andThrow($this->generateSoapFault(0));
160
        $this->expectException(Exceptions\SoapInternalErrorException::class);
161
        $apiClient = $this->getApiClient(
162
            $this->getRequestNewAccessTokenMock(),
163
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
164
            $clientProxyMock,
165
            new Helper\File(),
166
            new Helper\Csv(),
167
            $this->getTimeHelperMock()
168
        );
169
        $apiClient->get(['TimePeriod', 'AccountName', 'AdGroupId'], 'GeoLocationPerformanceReport');
170
    }
171
    /**
172
     * @return Mockery\MockInterface
173
     */
174
    private function getClientProxyMock($reportStatus = 'Success')
175
    {
176
        $clientProxyMock = Mockery::mock(ClientProxy::class);
177
        $clientProxyMock
1 ignored issue
show
Bug introduced by
The method shouldReceive() does not seem to exist on object<Mockery\Expectation>.

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...
178
            ->shouldReceive('ConstructWithCredentials')
179
            ->andReturnSelf()
180
            ->once()
181
            ->shouldReceive('GetNamespace')
182
            ->between(1, 48)
183
            ->andReturn('Namespace')
184
            ->shouldReceive('GetService')
185
            ->between(2, 49)
186
            ->andReturnSelf()
187
            ->shouldReceive('SubmitGenerateReport')
188
            ->between(1, 48)
189
            ->andReturnSelf()
190
            ->shouldReceive('PollGenerateReport')
191
            ->between(1, 48)
192
            ->andReturnSelf();
193
194
        $status = new \stdClass();
195
        $status->Status = $reportStatus;
196
        $status->ReportDownloadUrl = 'http://example.com/download.zip';
197
198
        $clientProxyMock->ReportRequestId = 'reportID';
1 ignored issue
show
Bug introduced by
Accessing ReportRequestId on the interface Mockery\MockInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
199
        $clientProxyMock->ReportRequestStatus = $status;
1 ignored issue
show
Bug introduced by
Accessing ReportRequestStatus on the interface Mockery\MockInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
200
201
        return $clientProxyMock;
202
    }
203
204
    /**
205
     * @return Mockery\MockInterface
206
     */
207 View Code Duplication
    private function getRequestNewAccessTokenMock()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
208
    {
209
        $requestNewAccessTokenMock = Mockery::mock(OauthTokenService::class);
210
        $requestNewAccessTokenMock
211
            ->shouldReceive('refreshToken')
212
            ->with('clientId', 'clientSecret', 'redirectUri', AccessToken::class)
213
            ->once()
214
            ->andReturn(new AccessToken(self::ACCESS_TOKEN, self::REFRESH_TOKEN));
215
216
        return $requestNewAccessTokenMock;
217
    }
218
219
    /**
220
     * @return Mockery\MockInterface
221
     */
222
    private function getFileHelperMock()
223
    {
224
        $zipHelperMock = Mockery::mock(Helper\File::class);
225
        $zipHelperMock
1 ignored issue
show
Bug introduced by
The method shouldReceive() does not seem to exist on object<Mockery\Expectation>.

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...
226
            ->shouldReceive('getFile')
227
            ->andReturn('/tmp/report.zip')
228
            ->once()
229
            ->shouldReceive('unZip')
230
            ->with('/tmp/report.zip')
231
            ->andReturn([ASSETS_DIR . 'report.csv'])
232
            ->once();
233
234
        return $zipHelperMock;
235
    }
236
237
    /**
238
     * @return Mockery\MockInterface
239
     */
240
    private function getCsvHelperMock()
241
    {
242
        $lines = file(ASSETS_DIR . 'report.csv');
243
        $csvHelperMock = Mockery::mock(Helper\Csv::class);
244
        $csvHelperMock
1 ignored issue
show
Bug introduced by
The method shouldReceive() does not seem to exist on object<Mockery\Expectation>.

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...
245
            ->shouldReceive('removeHeaders')
246
            ->andReturn($lines)
247
            ->once()
248
            ->shouldReceive('removeLastLines')
249
            ->andReturn($lines)
250
            ->once()
251
            ->shouldReceive('convertDateMDYtoYMD')
252
            ->andReturn($lines)
253
            ->once();
254
255
        return $csvHelperMock;
256
    }
257
258
    private function getTimeHelperMock()
259
    {
260
        $timeHelperMock = Mockery::mock(Helper\Time::class);
261
        $timeHelperMock->shouldReceive('sleep')->andReturnNull();
262
263
        return $timeHelperMock;
264
    }
265
266
    /**
267
     * @param OauthTokenService $requestNewAccessToken
268
     * @param ClientProxy $clientProxy
269
     * @param Helper\File $fileHelper
270
     * @param Helper\Csv $csvHelper
271
     * @param Helper\Time $timeHelper
272
     *
273
     * @return Client
274
     */
275 View Code Duplication
    private function getApiClient(OauthTokenService $requestNewAccessToken, ApiDetails $apiDetails, ClientProxy $clientProxy, Helper\File $fileHelper, Helper\Csv $csvHelper, Helper\Time $timeHelper)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
276
    {
277
        $apiClient = new Client($requestNewAccessToken, $apiDetails, $clientProxy, $fileHelper, $csvHelper, $timeHelper);
278
        $apiClient->setConfig(['cache_dir' => '/tmp']);
279
280
        return $apiClient;
281
    }
282
283
    /**
284
     * @param $code
285
     * @return SoapFault
286
     */
287 View Code Duplication
    private function generateSoapFault($code)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
288
    {
289
        $message = "an error message {$code}";
290
        $error = new stdClass();
291
        $error->Code = $code;
292
        $error->Message = $message;
293
        $exception = new SoapFault('Server', '');
294
        $exception->detail = new stdClass();
1 ignored issue
show
Bug introduced by
The property detail does not seem to exist in SoapFault.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
295
        $exception->detail->AdApiFaultDetail = new stdClass();
296
        $exception->detail->AdApiFaultDetail->Errors = new stdClass();
297
        $exception->detail->AdApiFaultDetail->Errors->AdApiError = [$error];
298
299
        return $exception;
300
    }
301
}
302