Completed
Push — master ( 3624f7...34c464 )
by Winfred
15s
created

GeoLocationPerformanceReportTest   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 282
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 14

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 15
c 1
b 0
f 0
lcom 1
cbo 14
dl 0
loc 282
rs 10
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
        $apiClient = $this->getApiClient(
86
            $this->getRequestNewAccessTokenMock(),
87
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
88
            $this->getClientProxyMock(),
89
            $fileHelperMock,
90
            $this->getCsvHelperMock(),
91
            $this->getTimeHelperMock()
92
        );
93
94
        $this->assertEquals('refreshToken', $apiClient->getRefreshToken());
95
        $apiClient->getReport('GeoLocationPerformanceReport', ['TimePeriod', 'AccountName', 'AdGroupId'], ReportTimePeriod::LastWeek, $fileLocation);
96
        $this->assertEquals(self::REFRESH_TOKEN, $apiClient->getRefreshToken());
97
    }
98
99
    /**
100
     * @expectedException \Werkspot\BingAdsApiBundle\Api\Exceptions\RequestTimeoutException
101
     */
102
    public function testGeoLocationPerformanceReportTimeoutException()
103
    {
104
        $apiClient = $this->getApiClient(
105
            $this->getRequestNewAccessTokenMock(),
106
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
107
            $this->getClientProxyMock('Pending'),
108
            $this->getFileHelper(),
109
            new Helper\Csv(),
110
            $this->getTimeHelperMock()
111
        );
112
        $apiClient->getReport('GeoLocationPerformanceReport', ['TimePeriod', 'AccountName', 'AdGroupId'], ReportTimePeriod::LastMonth, self::CSV_REPORT_PATH);
113
    }
114
115
    /**
116
     * @expectedException \Werkspot\BingAdsApiBundle\Api\Exceptions\ReportRequestErrorException
117
     */
118
    public function testGeoLocationPerformanceReportRequestErrorException()
119
    {
120
        $apiClient = $this->getApiClient(
121
            $this->getRequestNewAccessTokenMock(),
122
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
123
            $this->getClientProxyMock('Error'),
124
            $this->getFileHelper(),
125
            new Helper\Csv(),
126
            $this->getTimeHelperMock()
127
        );
128
        $apiClient->getReport('GeoLocationPerformanceReport', ['TimePeriod', 'AccountName', 'AdGroupId'], ReportTimePeriod::LastMonth, self::CSV_REPORT_PATH);
129
    }
130
131
    public function testClearCache()
132
    {
133
        $fileHelperMock = Mockery::mock(Helper\File::class);
134
        $fileHelperMock
135
            ->shouldReceive('clearCache')
136
            ->with(null)
137
            ->once()
138
139
            ->shouldReceive('clearCache')
140
            ->withAnyArgs()
141
            ->once();
142
        $apiClient = $this->getApiClient(
143
            $this->getRequestNewAccessTokenMock(),
144
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
145
            new ClientProxy('example.com'),
146
            $fileHelperMock,
147
            new Helper\Csv(),
148
            new Helper\Time()
149
        );
150
        $apiClient->clearCache();
151
        $apiClient->clearCache(true);
152
    }
153
154
    /**
155
     * @dataProvider getReportNameData
156
     *
157
     * @expectedException \Werkspot\BingAdsApiBundle\Api\Exceptions\InvalidReportNameException
158
     */
159
    public function testThrowsExceptionOnEmptyReportName($name)
160
    {
161
        $apiClient = $this->getApiClient(
162
            $this->getRequestNewAccessTokenMock(),
163
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
164
            new ClientProxy('example.com'),
165
            $this->getFileHelper(),
166
            new Helper\Csv(),
167
            new Helper\Time()
168
        );
169
        $apiClient->getReport($name, [], ReportTimePeriod::LastMonth, self::CSV_REPORT_PATH);
170
    }
171
172
    public function getReportNameData()
173
    {
174
        return [
175
            'Empty string' => [''],
176
            'NULL' => [null],
177
        ];
178
    }
179
180
    public function testPollGenerateReportSoapException()
181
    {
182
        $clientProxyMock = Mockery::mock(ClientProxy::class);
183
        $clientProxyMock->ReportRequestId = 'reportID';
184
        $clientProxyMock
185
            ->shouldReceive('ConstructWithCredentials')
186
            ->andReturnSelf()
187
            ->once()
188
            ->shouldReceive('GetNamespace')
189
            ->once()
190
            ->andReturn('Namespace')
191
            ->shouldReceive('GetService')
192
            ->twice()
193
            ->andReturnSelf()
194
            ->shouldReceive('SubmitGenerateReport')
195
            ->once()
196
            ->andReturnSelf()
197
            ->shouldReceive('PollGenerateReport')
198
            ->andThrow($this->generateSoapFault(0));
199
        $this->expectException(Exceptions\SoapInternalErrorException::class);
200
        $apiClient = $this->getApiClient(
201
            $this->getRequestNewAccessTokenMock(),
202
            new ApiDetails('refreshToken', 'clientId', 'clientSecret', 'redirectUri', 'devToken'),
203
            $clientProxyMock,
204
            $this->getFileHelper(),
205
            new Helper\Csv(),
206
            $this->getTimeHelperMock()
207
        );
208
        $apiClient->getReport('GeoLocationPerformanceReport', ['TimePeriod', 'AccountName', 'AdGroupId'], ReportTimePeriod::LastMonth, self::CSV_REPORT_PATH);
209
    }
210
    /**
211
     * @return Mockery\MockInterface|ClientProxy
212
     */
213
    private function getClientProxyMock($reportStatus = 'Success')
214
    {
215
        $clientProxyMock = Mockery::mock(ClientProxy::class);
216
        $clientProxyMock
217
            ->shouldReceive('ConstructWithCredentials')
218
            ->andReturnSelf()
219
            ->once()
220
221
            ->shouldReceive('GetNamespace')
222
            ->between(1, 48)
223
            ->andReturn('Namespace')
224
225
            ->shouldReceive('GetService')
226
            ->between(2, 49)
227
            ->andReturnSelf()
228
229
            ->shouldReceive('SubmitGenerateReport')
230
            ->between(1, 48)
231
            ->andReturnSelf()
232
233
            ->shouldReceive('PollGenerateReport')
234
            ->between(1, 48)
235
            ->andReturnSelf();
236
237
        $status = new \stdClass();
238
        $status->Status = $reportStatus;
239
        $status->ReportDownloadUrl = 'http://example.com/download.zip';
240
241
        $clientProxyMock->ReportRequestId = 'reportID';
242
        $clientProxyMock->ReportRequestStatus = $status;
243
244
        return $clientProxyMock;
245
    }
246
247
    /**
248
     * @return Mockery\MockInterface|OauthTokenService
249
     */
250
    private function getRequestNewAccessTokenMock()
251
    {
252
        $oauthTokenServiceMock = Mockery::mock(OauthTokenService::class);
253
        $oauthTokenServiceMock
254
            ->shouldReceive('refreshToken')
255
            ->with('clientId', 'clientSecret', 'redirectUri', AccessToken::class)
256
            ->andReturn(new AccessToken(self::ACCESS_TOKEN, self::REFRESH_TOKEN));
257
258
        return $oauthTokenServiceMock;
259
    }
260
261
    /**
262
     * @return Mockery\MockInterface|Helper\File
263
     */
264
    private function getFileHelperMock()
265
    {
266
        $zipHelperMock = Mockery::mock(Helper\File::class);
267
        $zipHelperMock
268
            ->shouldReceive('createDirIfNotExists')
269
            ->once()
270
271
            ->shouldReceive('copyFile')
272
            ->andReturn('/tmp/report.zip')
273
            ->once()
274
275
            ->shouldReceive('unZip')
276
            ->with('/tmp/report.zip')
277
            ->andReturn([self::CSV_REPORT_PATH])
278
            ->once()
279
280
            ->shouldReceive('isHealthyZipFile')
281
            ->with('/tmp/report.zip')
282
            ->andReturn(true)
283
            ->once()
284
285
            ->shouldReceive('readFileLinesIntoArray')
286
            ->with(self::CSV_REPORT_PATH)
287
            ->andReturn(self::$LINES_IN_REPORT)
288
            ->once()
289
290
            ->shouldReceive('writeLinesToFile')
291
            ->with(self::$LINES_IN_REPORT, self::CSV_REPORT_PATH)
292
            ->once();
293
294
        return $zipHelperMock;
295
    }
296
297
    /**
298
     * @return Mockery\MockInterface|Helper\Csv
299
     */
300
    private function getCsvHelperMock()
301
    {
302
        $lines = self::$LINES_IN_REPORT;
303
        $csvHelperMock = Mockery::mock(Helper\Csv::class);
304
        $csvHelperMock
305
            ->shouldReceive('removeHeaders')
306
            ->andReturn($lines)
307
            ->once()
308
            ->shouldReceive('removeLastLines')
309
            ->andReturn($lines)
310
            ->once()
311
            ->shouldReceive('convertDateMDYtoYMD')
312
            ->andReturn($lines)
313
            ->once();
314
315
        return $csvHelperMock;
316
    }
317
318
    /**
319
     * @return Mockery\MockInterface|Helper\Time
320
     */
321
    private function getTimeHelperMock()
322
    {
323
        $timeHelperMock = Mockery::mock(Helper\Time::class);
324
        $timeHelperMock->shouldReceive('sleep')->andReturnNull();
325
326
        return $timeHelperMock;
327
    }
328
329
    /**
330
     * @param OauthTokenService $requestNewAccessToken
331
     * @param ApiDetails $apiDetails
332
     * @param ClientProxy $clientProxy
333
     * @param Helper\File $fileHelper
334
     * @param Helper\Csv $csvHelper
335
     * @param Helper\Time $timeHelper
336
     *
337
     * @return Client
338
     */
339
    private function getApiClient(OauthTokenService $requestNewAccessToken, ApiDetails $apiDetails, ClientProxy $clientProxy, Helper\File $fileHelper, Helper\Csv $csvHelper, Helper\Time $timeHelper)
340
    {
341
        $apiClient = new Client($requestNewAccessToken, $apiDetails, $clientProxy, $fileHelper, $csvHelper, $timeHelper);
342
        $apiClient->setConfig(['cache_dir' => self::CACHE_DIR]);
343
344
        return $apiClient;
345
    }
346
347
    /**
348
     * @param $code
349
     *
350
     * @return SoapFault
351
     */
352
    private function generateSoapFault($code)
353
    {
354
        $message = "an error message {$code}";
355
        $error = new stdClass();
356
        $error->Code = $code;
357
        $error->Message = $message;
358
        $exception = new SoapFault('Server', '');
359
        $exception->detail = new stdClass();
360
        $exception->detail->AdApiFaultDetail = new stdClass();
361
        $exception->detail->AdApiFaultDetail->Errors = new stdClass();
362
        $exception->detail->AdApiFaultDetail->Errors->AdApiError = [$error];
363
364
        return $exception;
365
    }
366
367
    /**
368
     * @return Helper\File
369
     */
370
    private function getFileHelper()
371
    {
372
        return  new Helper\File(new GuzzleClient(), new Filesystem(), new Finder());
373
    }
374
}
375