Completed
Pull Request — master (#8)
by Laurens
02:34
created

GeoLocationPerformanceReportTest   B

Complexity

Total Complexity 15

Size/Duplication

Total Lines 324
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 16

Importance

Changes 6
Bugs 1 Features 0
Metric Value
wmc 15
c 6
b 1
f 0
lcom 1
cbo 16
dl 0
loc 324
rs 8.4614

15 Methods

Rating   Name   Duplication   Size   Complexity  
A testGetRequest() 0 19 1
A testSetAggregation() 0 16 1
B testGeoLocationPerformanceReportMoveFile() 0 31 1
A testGeoLocationPerformanceReportTimeoutException() 0 20 1
A testGeoLocationPerformanceReportRequestErrorException() 0 13 1
B testPollGenerateReportSoapException() 0 31 1
B getClientProxyMock() 0 33 1
A getRequestNewAccessTokenMock() 0 10 1
B getFileHelperMock() 0 29 1
A getCsvHelperMock() 0 17 1
A getTimeHelperMock() 0 7 1
A getApiClient() 0 7 1
A generateSoapFault() 0 14 1
A getFilesystemMock() 0 4 1
A getFileHelper() 0 4 1
1
<?php
2
namespace Tests\Werkspot\BingAdsApiBundle\Api\Report;
3
4
use BingAds\Bulk\ReportTimePeriod;
5
use BingAds\Proxy\ClientProxy;
6
use BingAds\Reporting\AccountThroughAdGroupReportScope;
7
use BingAds\Reporting\GeoLocationPerformanceReportRequest;
8
use BingAds\Reporting\NonHourlyReportAggregation;
9
use BingAds\Reporting\ReportFormat;
10
use BingAds\Reporting\ReportTime;
11
use GuzzleHttp\Client as GuzzleClient;
12
use Mockery;
13
use PHPUnit_Framework_TestCase;
14
use SoapFault;
15
use stdClass;
16
use Symfony\Component\Filesystem\Filesystem;
17
use Symfony\Component\Finder\Finder;
18
use Werkspot\BingAdsApiBundle\Api\Client;
19
use Werkspot\BingAdsApiBundle\Api\Exceptions;
20
use Werkspot\BingAdsApiBundle\Api\Helper;
21
use Werkspot\BingAdsApiBundle\Api\Report\GeoLocationPerformanceReport;
22
use Werkspot\BingAdsApiBundle\Guzzle\OauthTokenService;
23
use Werkspot\BingAdsApiBundle\Model\AccessToken;
24
use Werkspot\BingAdsApiBundle\Model\ApiDetails;
25
26
class GeoLocationPerformanceReportTest extends PHPUnit_Framework_TestCase
27
{
28
    const YESTERDAY = 'Yesterday';
29
    const ACCESS_TOKEN = '2ec09aeccaf634d982eec793037e37fe';
30
    const REFRESH_TOKEN = '0c59f7e609b0cc467067e39d523116ce';
31
32
    const CACHE_DIR = '/tmp';
33
34
    const CSV_REPORT_PATH = 'report.csv';
35
36
    private static $LINES_IN_REPORT = ['something', 'else'];
37
38
    public function testGetRequest()
39
    {
40
        $expected = new GeoLocationPerformanceReportRequest();
41
        $expected->Format = ReportFormat::Csv;
42
        $expected->ReportName = GeoLocationPerformanceReport::NAME;
43
        $expected->ReturnOnlyCompleteData = true;
44
        $expected->Aggregation = NonHourlyReportAggregation::Daily;
45
        $expected->Scope = new AccountThroughAdGroupReportScope();
46
        $expected->Time = new ReportTime();
47
        $expected->Time->PredefinedTime = self::YESTERDAY;
48
        $expected->Columns = [];
49
50
        $report = new GeoLocationPerformanceReport();
51
        $report->setTimePeriod(self::YESTERDAY);
52
        $report->setColumns([]);
53
        $result = $report->getRequest();
54
55
        $this->assertEquals($expected, $result);
56
    }
57
58
    public function testSetAggregation()
59
    {
60
        $report = new GeoLocationPerformanceReport();
61
62
        $report->setTimePeriod(self::YESTERDAY);
63
        $report->setColumns([]);
64
        $result = $report->getRequest();
65
        $this->assertEquals(NonHourlyReportAggregation::Daily, $result->Aggregation);
66
67
        $report->setAggregation(NonHourlyReportAggregation::Monthly);
68
        $report->setTimePeriod(self::YESTERDAY);
69
        $report->setColumns([]);
70
        $result = $report->getRequest();
71
72
        $this->assertEquals(NonHourlyReportAggregation::Monthly, $result->Aggregation);
73
    }
74
75
    public function testGeoLocationPerformanceReportMoveFile()
76
    {
77
        $fileLocation = 'test.csv';
78
79
        $fileHelperMock = $this->getFileHelperMock();
80
        $fileHelperMock->shouldReceive('moveFirstFile')
81
            ->with([self::CSV_REPORT_PATH], $fileLocation)
82
            ->andReturn(self::CSV_REPORT_PATH)
83
            ->once();
84
85
        $fileSystem = $this->getFilesystemMock();
86
        $fileSystem
87
            ->shouldReceive('exists')
88
            ->with(self::CACHE_DIR . '/' . Client::CACHE_SUBDIRECTORY)
89
            ->andReturn(true)
90
            ->once();
91
92
        $apiClient = $this->getApiClient(
93
            $this->getRequestNewAccessTokenMock(),
94
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
95
            $this->getClientProxyMock(),
96
            $fileHelperMock,
97
            $this->getCsvHelperMock(),
98
            $this->getTimeHelperMock(),
99
            $fileSystem
100
        );
101
102
        $this->assertEquals('refreshToken', $apiClient->getRefreshToken());
103
        $apiClient->getReport('GeoLocationPerformanceReport', ['TimePeriod', 'AccountName', 'AdGroupId'], ReportTimePeriod::LastWeek, $fileLocation);
104
        $this->assertEquals(self::REFRESH_TOKEN, $apiClient->getRefreshToken());
105
    }
106
107
    /**
108
     * @expectedException \Werkspot\BingAdsApiBundle\Api\Exceptions\RequestTimeoutException
109
     */
110
    public function testGeoLocationPerformanceReportTimeoutException()
111
    {
112
        $fileSystem = $this->getFilesystemMock();
113
        $fileSystem
114
            ->shouldReceive('exists')
115
            ->with(self::CACHE_DIR . '/' . Client::CACHE_SUBDIRECTORY)
116
            ->andReturn(true)
117
            ->once();
118
119
        $apiClient = $this->getApiClient(
120
            $this->getRequestNewAccessTokenMock(),
121
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
122
            $this->getClientProxyMock('Pending'),
123
            $this->getFileHelper(),
124
            new Helper\Csv(),
125
            $this->getTimeHelperMock(),
126
            $fileSystem
127
        );
128
        $apiClient->getReport('GeoLocationPerformanceReport', ['TimePeriod', 'AccountName', 'AdGroupId'], ReportTimePeriod::LastMonth, self::CSV_REPORT_PATH);
129
    }
130
131
    /**
132
     * @expectedException \Werkspot\BingAdsApiBundle\Api\Exceptions\ReportRequestErrorException
133
     */
134
    public function testGeoLocationPerformanceReportRequestErrorException()
135
    {
136
        $apiClient = $this->getApiClient(
137
            $this->getRequestNewAccessTokenMock(),
138
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
139
            $this->getClientProxyMock('Error'),
140
            $this->getFileHelper(),
141
            new Helper\Csv(),
142
            $this->getTimeHelperMock(),
143
            new Filesystem()
144
        );
145
        $apiClient->getReport('GeoLocationPerformanceReport', ['TimePeriod', 'AccountName', 'AdGroupId'], ReportTimePeriod::LastMonth, self::CSV_REPORT_PATH);
146
    }
147
148
    public function testPollGenerateReportSoapException()
149
    {
150
        $clientProxyMock = Mockery::mock(ClientProxy::class);
151
        $clientProxyMock->ReportRequestId = 'reportID';
152
        $clientProxyMock
153
            ->shouldReceive('ConstructWithCredentials')
154
            ->andReturnSelf()
155
            ->once()
156
            ->shouldReceive('GetNamespace')
157
            ->once()
158
            ->andReturn('Namespace')
159
            ->shouldReceive('GetService')
160
            ->twice()
161
            ->andReturnSelf()
162
            ->shouldReceive('SubmitGenerateReport')
163
            ->once()
164
            ->andReturnSelf()
165
            ->shouldReceive('PollGenerateReport')
166
            ->andThrow($this->generateSoapFault(0));
167
        $this->expectException(Exceptions\SoapInternalErrorException::class);
168
        $apiClient = $this->getApiClient(
169
            $this->getRequestNewAccessTokenMock(),
170
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
171
            $clientProxyMock,
172
            $this->getFileHelper(),
173
            new Helper\Csv(),
174
            $this->getTimeHelperMock(),
175
            new Filesystem()
176
        );
177
        $apiClient->getReport('GeoLocationPerformanceReport', ['TimePeriod', 'AccountName', 'AdGroupId'], ReportTimePeriod::LastMonth, self::CSV_REPORT_PATH);
178
    }
179
    /**
180
     * @return Mockery\MockInterface|ClientProxy
181
     */
182
    private function getClientProxyMock($reportStatus = 'Success')
183
    {
184
        $clientProxyMock = Mockery::mock(ClientProxy::class);
185
        $clientProxyMock
186
            ->shouldReceive('ConstructWithCredentials')
187
            ->andReturnSelf()
188
            ->once()
189
190
            ->shouldReceive('GetNamespace')
191
            ->between(1, 48)
192
            ->andReturn('Namespace')
193
194
            ->shouldReceive('GetService')
195
            ->between(2, 49)
196
            ->andReturnSelf()
197
198
            ->shouldReceive('SubmitGenerateReport')
199
            ->between(1, 48)
200
            ->andReturnSelf()
201
202
            ->shouldReceive('PollGenerateReport')
203
            ->between(1, 48)
204
            ->andReturnSelf();
205
206
        $status = new \stdClass();
207
        $status->Status = $reportStatus;
208
        $status->ReportDownloadUrl = 'http://example.com/download.zip';
209
210
        $clientProxyMock->ReportRequestId = 'reportID';
211
        $clientProxyMock->ReportRequestStatus = $status;
212
213
        return $clientProxyMock;
214
    }
215
216
    /**
217
     * @return Mockery\MockInterface|OauthTokenService
218
     */
219
    private function getRequestNewAccessTokenMock()
220
    {
221
        $oauthTokenServiceMock = Mockery::mock(OauthTokenService::class);
222
        $oauthTokenServiceMock
223
            ->shouldReceive('refreshToken')
224
            ->with('clientId', 'clientSecret', 'redirectUri', AccessToken::class)
225
            ->andReturn(new AccessToken(self::ACCESS_TOKEN, self::REFRESH_TOKEN));
226
227
        return $oauthTokenServiceMock;
228
    }
229
230
    /**
231
     * @return Mockery\MockInterface|Helper\File
232
     */
233
    private function getFileHelperMock()
234
    {
235
        $zipHelperMock = Mockery::mock(Helper\File::class);
236
        $zipHelperMock
237
            ->shouldReceive('copyFile')
238
            ->andReturn('/tmp/report.zip')
239
            ->once()
240
241
            ->shouldReceive('unZip')
242
            ->with('/tmp/report.zip')
243
            ->andReturn([self::CSV_REPORT_PATH])
244
            ->once()
245
246
            ->shouldReceive('isHealthyZipFile')
247
            ->with('/tmp/report.zip')
248
            ->andReturn(true)
249
            ->once()
250
251
            ->shouldReceive('readFileLinesIntoArray')
252
            ->with(self::CSV_REPORT_PATH)
253
            ->andReturn(self::$LINES_IN_REPORT)
254
            ->once()
255
256
            ->shouldReceive('writeLinesToFile')
257
            ->with(self::$LINES_IN_REPORT, self::CSV_REPORT_PATH)
258
            ->once();
259
260
        return $zipHelperMock;
261
    }
262
263
    /**
264
     * @return Mockery\MockInterface|Helper\Csv
265
     */
266
    private function getCsvHelperMock()
267
    {
268
        $lines = self::$LINES_IN_REPORT;
269
        $csvHelperMock = Mockery::mock(Helper\Csv::class);
270
        $csvHelperMock
271
            ->shouldReceive('removeHeaders')
272
            ->andReturn($lines)
273
            ->once()
274
            ->shouldReceive('removeLastLines')
275
            ->andReturn($lines)
276
            ->once()
277
            ->shouldReceive('convertDateMDYtoYMD')
278
            ->andReturn($lines)
279
            ->once();
280
281
        return $csvHelperMock;
282
    }
283
284
    /**
285
     * @return Mockery\MockInterface|Helper\Time
286
     */
287
    private function getTimeHelperMock()
288
    {
289
        $timeHelperMock = Mockery::mock(Helper\Time::class);
290
        $timeHelperMock->shouldReceive('sleep')->andReturnNull();
291
292
        return $timeHelperMock;
293
    }
294
295
    /**
296
     * @param OauthTokenService $requestNewAccessToken
297
     * @param ApiDetails $apiDetails
298
     * @param ClientProxy $clientProxy
299
     * @param Helper\File $fileHelper
300
     * @param Helper\Csv $csvHelper
301
     * @param Helper\Time $timeHelper
302
     * @param Filesystem $fileSystem
303
     *
304
     * @return Client
305
     */
306
    private function getApiClient(OauthTokenService $requestNewAccessToken, ApiDetails $apiDetails, ClientProxy $clientProxy, Helper\File $fileHelper, Helper\Csv $csvHelper, Helper\Time $timeHelper, Filesystem $fileSystem)
307
    {
308
        $apiClient = new Client($requestNewAccessToken, $apiDetails, $clientProxy, $fileHelper, $csvHelper, $timeHelper, $fileSystem);
309
        $apiClient->setConfig(['cache_dir' => self::CACHE_DIR]);
310
311
        return $apiClient;
312
    }
313
314
    /**
315
     * @param $code
316
     *
317
     * @return SoapFault
318
     */
319
    private function generateSoapFault($code)
320
    {
321
        $message = "an error message {$code}";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $code instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
322
        $error = new stdClass();
323
        $error->Code = $code;
324
        $error->Message = $message;
325
        $exception = new SoapFault('Server', '');
326
        $exception->detail = new stdClass();
327
        $exception->detail->AdApiFaultDetail = new stdClass();
328
        $exception->detail->AdApiFaultDetail->Errors = new stdClass();
329
        $exception->detail->AdApiFaultDetail->Errors->AdApiError = [$error];
330
331
        return $exception;
332
    }
333
334
    /**
335
     * @return Mockery\MockInterface|Filesystem
336
     */
337
    private function getFilesystemMock()
338
    {
339
        return Mockery::mock(Filesystem::class);
340
    }
341
342
    /**
343
     * @return Helper\File
344
     */
345
    private function getFileHelper()
346
    {
347
        return  new Helper\File(new GuzzleClient(), new Filesystem(), new Finder());
348
    }
349
}
350