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

testPollGenerateReportSoapException()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 30
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 30
rs 8.8571
cc 1
eloc 27
nc 1
nop 0
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;
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
        $report->setTimePeriod(self::YESTERDAY);
56
        $report->setColumns([]);
57
        $result = $report->getRequest();
58
        $this->assertEquals(NonHourlyReportAggregation::Daily, $result->Aggregation);
59
60
        $report->setAggregation(NonHourlyReportAggregation::Monthly);
61
        $report->setTimePeriod(self::YESTERDAY);
62
        $report->setColumns([]);
63
        $result = $report->getRequest();
64
65
        $this->assertEquals(NonHourlyReportAggregation::Monthly, $result->Aggregation);
66
    }
67
68
    public function testGeoLocationPerformanceReportReturnsArrayWithCsv()
69
    {
70
        $apiClient = $this->getApiClient(
71
            $this->getRequestNewAccessTokenMock(),
72
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
73
            $this->getClientProxyMock(),
74
            $this->getFileHelperMock(),
75
            $this->getCsvHelperMock(),
76
            $this->getTimeHelperMock()
77
        );
78
        $result = $apiClient->get(['TimePeriod', 'AccountName', 'AdGroupId'], 'GeoLocationPerformanceReport', ReportTimePeriod::LastWeek);
79
        $this->assertEquals([ASSETS_DIR . 'report.csv'], $result);
80
    }
81
82
    public function testGeoLocationPerformanceReportMoveFile()
83
    {
84
        $apiClient = $this->getApiClient(
85
            $this->getRequestNewAccessTokenMock(),
86
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
87
            $this->getClientProxyMock(),
88
            $this->getFileHelperMock(),
89
            $this->getCsvHelperMock(),
90
            $this->getTimeHelperMock()
91
        );
92
        $result = $apiClient->get(['TimePeriod', 'AccountName', 'AdGroupId'], 'GeoLocationPerformanceReport', ReportTimePeriod::LastWeek, ASSETS_DIR . 'test.csv');
93
        $this->assertEquals(ASSETS_DIR . 'test.csv', $result);
94
95
        //--Move File back
96
        $fileSystem = new Filesystem();
97
        $fileSystem->rename(ASSETS_DIR . 'test.csv', ASSETS_DIR . 'report.csv');
98
    }
99
100
    public function testGetRefreshToken()
101
    {
102
        $apiClient = $this->getApiClient(
103
            $this->getRequestNewAccessTokenMock(),
104
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
105
            $this->getClientProxyMock(),
106
            $this->getFileHelperMock(),
107
            $this->getCsvHelperMock(),
108
            $this->getTimeHelperMock()
109
        );
110
111
        $this->assertEquals('refreshToken', $apiClient->getRefreshToken());
112
113
        $apiClient->get(['TimePeriod', 'AccountName', 'AdGroupId'], 'GeoLocationPerformanceReport', ReportTimePeriod::LastWeek);
114
        $this->assertEquals(self::REFRESH_TOKEN, $apiClient->getRefreshToken());
115
    }
116
117
    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...
118
    {
119
        $this->expectException(Exceptions\RequestTimeoutException::class);
120
        $apiClient = $this->getApiClient(
121
            $this->getRequestNewAccessTokenMock(),
122
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
123
            $this->getClientProxyMock('Pending'),
124
            new Helper\File(),
125
            new Helper\Csv(),
126
            $this->getTimeHelperMock()
127
        );
128
        $apiClient->get(['TimePeriod', 'AccountName', 'AdGroupId'], 'GeoLocationPerformanceReport');
129
    }
130
131
    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...
132
    {
133
        $this->expectException(Exceptions\ReportRequestErrorException::class);
134
        $apiClient = $this->getApiClient(
135
            $this->getRequestNewAccessTokenMock(),
136
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
137
            $this->getClientProxyMock('Error'),
138
            new Helper\File(),
139
            new Helper\Csv(),
140
            $this->getTimeHelperMock()
141
        );
142
        $apiClient->get(['TimePeriod', 'AccountName', 'AdGroupId'], 'GeoLocationPerformanceReport');
143
    }
144
145
    public function testPollGenerateReportSoapException()
146
    {
147
        $clientProxyMock = Mockery::mock(ClientProxy::class);
148
        $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...
149
        $clientProxyMock
150
            ->shouldReceive('ConstructWithCredentials')
151
            ->andReturnSelf()
152
            ->once()
153
            ->shouldReceive('GetNamespace')
154
            ->once()
155
            ->andReturn('Namespace')
156
            ->shouldReceive('GetService')
157
            ->twice()
158
            ->andReturnSelf()
159
            ->shouldReceive('SubmitGenerateReport')
160
            ->once()
161
            ->andReturnSelf()
162
            ->shouldReceive('PollGenerateReport')
163
            ->andThrow($this->generateSoapFault(0));
164
        $this->expectException(Exceptions\SoapInternalErrorException::class);
165
        $apiClient = $this->getApiClient(
166
            $this->getRequestNewAccessTokenMock(),
167
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
168
            $clientProxyMock,
169
            new Helper\File(),
170
            new Helper\Csv(),
171
            $this->getTimeHelperMock()
172
        );
173
        $apiClient->get(['TimePeriod', 'AccountName', 'AdGroupId'], 'GeoLocationPerformanceReport');
174
    }
175
    /**
176
     * @return Mockery\MockInterface
177
     */
178
    private function getClientProxyMock($reportStatus = 'Success')
179
    {
180
        $clientProxyMock = Mockery::mock(ClientProxy::class);
181
        $clientProxyMock
182
            ->shouldReceive('ConstructWithCredentials')
183
            ->andReturnSelf()
184
            ->once()
185
            ->shouldReceive('GetNamespace')
186
            ->between(1, 48)
187
            ->andReturn('Namespace')
188
            ->shouldReceive('GetService')
189
            ->between(2, 49)
190
            ->andReturnSelf()
191
            ->shouldReceive('SubmitGenerateReport')
192
            ->between(1, 48)
193
            ->andReturnSelf()
194
            ->shouldReceive('PollGenerateReport')
195
            ->between(1, 48)
196
            ->andReturnSelf();
197
198
        $status = new \stdClass();
199
        $status->Status = $reportStatus;
200
        $status->ReportDownloadUrl = 'http://example.com/download.zip';
201
202
        $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...
203
        $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...
204
205
        return $clientProxyMock;
206
    }
207
208
    /**
209
     * @return Mockery\MockInterface
210
     */
211 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...
212
    {
213
        $oauthTokenServiceMock = Mockery::mock(OauthTokenService::class);
214
        $oauthTokenServiceMock
215
            ->shouldReceive('refreshToken')
216
            ->with('clientId', 'clientSecret', 'redirectUri', AccessToken::class)
217
            ->once()
218
            ->andReturn(new AccessToken(self::ACCESS_TOKEN, self::REFRESH_TOKEN));
219
220
        return $oauthTokenServiceMock;
221
    }
222
223
    /**
224
     * @return Mockery\MockInterface
225
     */
226
    private function getFileHelperMock()
227
    {
228
        $zipHelperMock = Mockery::mock(Helper\File::class);
229
        $zipHelperMock
230
            ->shouldReceive('getFile')
231
            ->andReturn('/tmp/report.zip')
232
            ->once()
233
            ->shouldReceive('unZip')
234
            ->with('/tmp/report.zip')
235
            ->andReturn([ASSETS_DIR . 'report.csv'])
236
            ->once();
237
238
        return $zipHelperMock;
239
    }
240
241
    /**
242
     * @return Mockery\MockInterface
243
     */
244
    private function getCsvHelperMock()
245
    {
246
        $lines = file(ASSETS_DIR . 'report.csv');
247
        $csvHelperMock = Mockery::mock(Helper\Csv::class);
248
        $csvHelperMock
249
            ->shouldReceive('removeHeaders')
250
            ->andReturn($lines)
251
            ->once()
252
            ->shouldReceive('removeLastLines')
253
            ->andReturn($lines)
254
            ->once()
255
            ->shouldReceive('convertDateMDYtoYMD')
256
            ->andReturn($lines)
257
            ->once();
258
259
        return $csvHelperMock;
260
    }
261
262
    private function getTimeHelperMock()
263
    {
264
        $timeHelperMock = Mockery::mock(Helper\Time::class);
265
        $timeHelperMock->shouldReceive('sleep')->andReturnNull();
266
267
        return $timeHelperMock;
268
    }
269
270
    /**
271
     * @param OauthTokenService $requestNewAccessToken
272
     * @param ClientProxy $clientProxy
273
     * @param Helper\File $fileHelper
274
     * @param Helper\Csv $csvHelper
275
     * @param Helper\Time $timeHelper
276
     *
277
     * @return Client
278
     */
279 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...
280
    {
281
        $apiClient = new Client($requestNewAccessToken, $apiDetails, $clientProxy, $fileHelper, $csvHelper, $timeHelper);
282
        $apiClient->setConfig(['cache_dir' => '/tmp']);
283
284
        return $apiClient;
285
    }
286
287
    /**
288
     * @param $code
289
     * @return SoapFault
290
     */
291 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...
292
    {
293
        $message = "an error message {$code}";
294
        $error = new stdClass();
295
        $error->Code = $code;
296
        $error->Message = $message;
297
        $exception = new SoapFault('Server', '');
298
        $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...
299
        $exception->detail->AdApiFaultDetail = new stdClass();
300
        $exception->detail->AdApiFaultDetail->Errors = new stdClass();
301
        $exception->detail->AdApiFaultDetail->Errors->AdApiError = [$error];
302
303
        return $exception;
304
    }
305
}
306