Completed
Push — 7.5 ( e0ec2c...254eb7 )
by Łukasz
17:27
created

UrlTest::setUp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
namespace eZ\Publish\Core\Repository\Tests\Service\Mock;
8
9
use DateTime;
10
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
11
use eZ\Publish\API\Repository\Values\URL\UsageSearchResult;
12
use eZ\Publish\Core\Base\Exceptions\UnauthorizedException;
13
use eZ\Publish\Core\Repository\Tests\Service\Mock\Base as BaseServiceMockTest;
14
use eZ\Publish\API\Repository\SearchService;
15
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
16
use eZ\Publish\API\Repository\Values\Content\Query\Criterion as ContentCriterion;
17
use eZ\Publish\API\Repository\Values\Content\Query as ContentQuery;
18
use eZ\Publish\API\Repository\Values\Content\Search\SearchResult as ContentSearchResults;
19
use eZ\Publish\API\Repository\Values\URL\SearchResult;
20
use eZ\Publish\API\Repository\Values\URL\URL;
21
use eZ\Publish\API\Repository\Values\URL\URLQuery;
22
use eZ\Publish\API\Repository\Values\URL\URLUpdateStruct;
23
use eZ\Publish\Core\Repository\URLService;
24
use eZ\Publish\SPI\Persistence\URL\URL as SpiUrl;
25
26
class UrlTest extends BaseServiceMockTest
27
{
28
    private const URL_ID = 12;
29
    private const URL_EZ_NO = 'http://ez.no';
30
    private const URL_EZ_COM = 'http://ez.com';
31
32
    /** @var \eZ\Publish\API\Repository\URLService|\PHPUnit\Framework\MockObject\MockObject */
33
    private $urlHandler;
34
35
    /** @var \eZ\Publish\API\Repository\PermissionResolver|\PHPUnit\Framework\MockObject\MockObject */
36
    private $permissionResolver;
37
38
    protected function setUp()
39
    {
40
        parent::setUp();
41
        $this->urlHandler = $this->getPersistenceMockHandler('URL\\Handler');
42
        $this->permissionResolver = $this->getPermissionResolverMock();
43
    }
44
45
    public function testFindUrlsUnauthorized()
46
    {
47
        $this->configureUrlViewPermissionForHasAccess(false);
48
49
        $this->expectException(UnauthorizedException::class);
50
        $this->createUrlService()->findUrls(new URLQuery());
51
    }
52
53
    /**
54
     * @expectedException \eZ\Publish\Core\Base\Exceptions\InvalidArgumentValue
55
     */
56
    public function testFindUrlsNonNumericOffset()
57
    {
58
        $query = new URLQuery();
59
        $query->offset = 'foo';
0 ignored issues
show
Documentation Bug introduced by
The property $offset was declared of type integer, but 'foo' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
60
61
        $this->createUrlService()->findUrls($query);
62
    }
63
64
    /**
65
     * @expectedException \eZ\Publish\Core\Base\Exceptions\InvalidArgumentValue
66
     */
67
    public function testFindUrlsNonNumericLimit()
68
    {
69
        $query = new URLQuery();
70
        $query->limit = 'foo';
0 ignored issues
show
Documentation Bug introduced by
The property $limit was declared of type integer, but 'foo' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
71
72
        $this->createUrlService()->findUrls($query);
73
    }
74
75
    public function testFindUrls()
76
    {
77
        $url = $this->getApiUrl();
78
79
        $this->configureUrlViewPermissionForHasAccess(true);
80
81
        $query = new URLQuery();
82
83
        $results = [
84
            'count' => 1,
85
            'items' => [
86
                new SpiUrl(),
87
            ],
88
        ];
89
90
        $expected = new SearchResult([
91
            'totalCount' => 1,
92
            'items' => [$url],
93
        ]);
94
95
        $this->urlHandler
96
            ->expects($this->once())
97
            ->method('find')
98
            ->with($query)
99
            ->willReturn($results);
100
101
        $this->assertEquals($expected, $this->createUrlService()->findUrls($query));
102
    }
103
104
    /**
105
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
106
     */
107
    public function testUpdateUrlUnauthorized()
108
    {
109
        $url = $this->getApiUrl();
110
111
        $this->configureUrlUpdatePermission($url, false);
112
113
        $this->createUrlService()->updateUrl($url, new URLUpdateStruct());
114
    }
115
116
    /**
117
     * @expectedException \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException
118
     */
119
    public function testUpdateUrlNonUnique()
120
    {
121
        $url = $this->getApiUrl(self::URL_ID, self::URL_EZ_NO);
122
123
        $this->configureUrlUpdatePermission($url, true);
124
125
        $struct = new URLUpdateStruct([
126
            'url' => self::URL_EZ_COM,
127
        ]);
128
129
        $urlService = $this->createUrlService(['isUnique']);
130
        $urlService
131
            ->expects($this->once())
132
            ->method('isUnique')
133
            ->with($url->id, $struct->url)
134
            ->willReturn(false);
135
136
        $urlService->updateUrl($url, $struct);
137
    }
138
139
    public function testUpdateUrl()
140
    {
141
        $apiUrl = $this->getApiUrl(self::URL_ID, self::URL_EZ_NO);
142
        $apiStruct = new URLUpdateStruct([
143
            'url' => self::URL_EZ_COM,
144
            'isValid' => false,
145
            'lastChecked' => new DateTime(),
146
        ]);
147
148
        $this->configurePermissions([
149
            ['url', 'update', $apiUrl, []],
150
            ['url', 'view', $apiUrl, []],
151
            ['url', 'view', new URL(['id' => self::URL_ID, 'url' => self::URL_EZ_COM, 'isValid' => true]), []],
152
        ]);
153
154
        $urlService = $this->createUrlService(['isUnique']);
155
        $urlService
156
            ->expects($this->once())
157
            ->method('isUnique')
158
            ->with($apiUrl->id, $apiStruct->url)
159
            ->willReturn(true);
160
161
        $this->urlHandler
162
            ->expects($this->once())
163
            ->method('updateUrl')
164
            ->willReturnCallback(function ($id, $struct) use ($apiUrl, $apiStruct) {
165
                $this->assertEquals($apiUrl->id, $id);
166
167
                $this->assertEquals($apiStruct->url, $struct->url);
168
                $this->assertEquals(0, $struct->lastChecked);
169
                $this->assertTrue($struct->isValid);
170
            });
171
172
        $this->urlHandler
173
            ->method('loadById')
174
            ->with($apiUrl->id)
175
            ->willReturnOnConsecutiveCalls(
176
                new SpiUrl([
177
                    'id' => $apiUrl->id,
178
                    'url' => $apiUrl->url,
179
                    'isValid' => $apiUrl->isValid,
180
                    'lastChecked' => $apiUrl->lastChecked,
181
                ]),
182
                new SpiUrl([
183
                    'id' => $apiUrl->id,
184
                    'url' => $apiStruct->url,
185
                    'isValid' => true,
186
                    'lastChecked' => 0,
187
                ])
188
            );
189
190
        $this->assertEquals(new URL([
191
            'id' => $apiUrl->id,
192
            'url' => $apiStruct->url,
193
            'isValid' => true,
194
            'lastChecked' => null,
195
        ]), $urlService->updateUrl($apiUrl, $apiStruct));
196
    }
197
198
    public function testUpdateUrlStatus()
199
    {
200
        $apiUrl = $this->getApiUrl(self::URL_ID, self::URL_EZ_NO);
201
        $apiStruct = new URLUpdateStruct([
202
            'isValid' => true,
203
            'lastChecked' => new DateTime('@' . time()),
204
        ]);
205
206
        $urlAfterUpdate = new URL([
207
            'id' => self::URL_ID,
208
            'url' => self::URL_EZ_NO,
209
            'isValid' => true,
210
            'lastChecked' => new DateTime('@' . time()),
211
        ]);
212
213
        $this->configurePermissions([
214
            ['url', 'update', $apiUrl, []],
215
            ['url', 'view', $apiUrl, []],
216
            ['url', 'view', $urlAfterUpdate, []],
217
        ]);
218
219
        $urlService = $this->createUrlService(['isUnique']);
220
        $urlService
221
            ->expects($this->once())
222
            ->method('isUnique')
223
            ->with($apiUrl->id, $apiStruct->url)
224
            ->willReturn(true);
225
226
        $this->urlHandler
227
            ->expects($this->once())
228
            ->method('updateUrl')
229
            ->willReturnCallback(function ($id, $struct) use ($apiUrl, $apiStruct) {
230
                $this->assertEquals($apiUrl->id, $id);
231
232
                $this->assertEquals($apiUrl->url, $struct->url);
233
                $this->assertEquals($apiStruct->lastChecked->getTimestamp(), $struct->lastChecked);
234
                $this->assertTrue($apiStruct->isValid, $struct->isValid);
235
            });
236
237
        $this->urlHandler
238
            ->method('loadById')
239
            ->with($apiUrl->id)
240
            ->willReturnOnConsecutiveCalls(
241
                new SpiUrl([
242
                    'id' => $apiUrl->id,
243
                    'url' => $apiUrl->url,
244
                    'isValid' => $apiUrl->isValid,
245
                    'lastChecked' => $apiUrl->lastChecked,
246
                ]),
247
                new SpiUrl([
248
                    'id' => $apiUrl->id,
249
                    'url' => $apiUrl->url,
250
                    'isValid' => $apiStruct->isValid,
251
                    'lastChecked' => $apiStruct->lastChecked->getTimestamp(),
252
                ])
253
            );
254
255
        $this->assertEquals(new URL([
256
            'id' => $apiUrl->id,
257
            'url' => $apiUrl->url,
258
            'isValid' => $apiStruct->isValid,
259
            'lastChecked' => $apiStruct->lastChecked,
260
        ]), $urlService->updateUrl($apiUrl, $apiStruct));
261
    }
262
263
    /**
264
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
265
     */
266
    public function testLoadByIdUnauthorized()
267
    {
268
        $this->configureUrlViewPermission(
269
            new URL([
270
                'id' => self::URL_ID,
271
            ]),
272
            false
273
        );
274
275
        $this->urlHandler
276
            ->expects($this->once())
277
            ->method('loadById')
278
            ->with(self::URL_ID)
279
            ->willReturn(new SpiUrl([
280
                'id' => self::URL_ID,
281
            ]));
282
283
        $this->createUrlService()->loadById(self::URL_ID);
284
    }
285
286
    public function testLoadById()
287
    {
288
        $url = new URL([
289
            'id' => self::URL_ID,
290
        ]);
291
292
        $this->configureUrlViewPermission($url, true);
293
294
        $this->urlHandler
295
            ->expects($this->once())
296
            ->method('loadById')
297
            ->with(self::URL_ID)
298
            ->willReturn(new SpiUrl([
299
                'id' => self::URL_ID,
300
            ]));
301
302
        $this->assertEquals($url, $this->createUrlService()->loadById(self::URL_ID));
303
    }
304
305
    /**
306
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
307
     */
308
    public function testLoadByUrlUnauthorized()
309
    {
310
        $url = self::URL_EZ_NO;
311
312
        $this->configureUrlViewPermission(
313
            new URL([
314
                'id' => self::URL_ID,
315
            ]),
316
            false
317
        );
318
319
        $this->urlHandler
320
            ->expects($this->once())
321
            ->method('loadByUrl')
322
            ->with($url)
323
            ->willReturn(new SpiUrl([
324
                'id' => self::URL_ID,
325
            ]));
326
327
        $this->createUrlService()->loadByUrl(self::URL_EZ_NO);
328
    }
329
330
    public function testLoadByUrl()
331
    {
332
        $url = self::URL_EZ_NO;
333
334
        $apiUrl = new URL([
335
            'url' => $url,
336
        ]);
337
338
        $this->configureUrlViewPermission($apiUrl, true);
339
340
        $this->urlHandler
341
            ->expects($this->once())
342
            ->method('loadByUrl')
343
            ->with($url)
344
            ->willReturn(new SpiUrl([
345
                'url' => $url,
346
            ]));
347
348
        $this->assertEquals($apiUrl, $this->createUrlService()->loadByUrl($url));
349
    }
350
351
    /**
352
     * @dataProvider dateProviderForFindUsages
353
     */
354
    public function testFindUsages($offset, $limit, ContentQuery $expectedQuery, array $usages)
355
    {
356
        $url = $this->getApiUrl(self::URL_ID, self::URL_EZ_NO);
357
358
        if (!empty($usages)) {
359
            $searchService = $this->createMock(SearchService::class);
360
            $searchService
361
                ->expects($this->once())
362
                ->method('findContentInfo')
363
                ->willReturnCallback(function ($query) use ($expectedQuery, $usages) {
364
                    $this->assertEquals($expectedQuery, $query);
365
366
                    return new ContentSearchResults([
367
                        'searchHits' => array_map(function ($id) {
368
                            return new SearchHit([
369
                                'valueObject' => new ContentInfo([
370
                                    'id' => $id,
371
                                ]),
372
                            ]);
373
                        }, $usages),
374
                        'totalCount' => count($usages),
375
                    ]);
376
                });
377
378
            $this->getRepositoryMock()
379
                ->expects($this->once())
380
                ->method('getSearchService')
381
                ->willReturn($searchService);
382
        }
383
384
        $this->urlHandler
385
            ->expects($this->once())
386
            ->method('findUsages')
387
            ->with($url->id)
388
            ->willReturn($usages);
389
390
        $usageSearchResult = $this->createUrlService()->findUsages($url, $offset, $limit);
391
392
        $this->assertInstanceOf(UsageSearchResult::class, $usageSearchResult);
393
        $this->assertEquals(count($usages), $usageSearchResult->totalCount);
394
        foreach ($usageSearchResult as $contentInfo) {
395
            $this->assertContains($contentInfo->id, $usages);
396
        }
397
    }
398
399
    public function dateProviderForFindUsages()
400
    {
401
        return [
402
            [
403
                10, -1, new ContentQuery([
404
                    'filter' => new ContentCriterion\MatchNone(),
405
                    'offset' => 10,
406
                ]), [],
407
            ],
408
            [
409
                10, -1, new ContentQuery([
410
                    'filter' => new ContentCriterion\LogicalAnd([
411
                        new ContentCriterion\ContentId([1, 2, 3]),
412
                        new ContentCriterion\Visibility(ContentCriterion\Visibility::VISIBLE),
413
                    ]),
414
                    'offset' => 10,
415
                ]), [1, 2, 3],
416
            ],
417
            [
418
                10, 10, new ContentQuery([
419
                    'filter' => new ContentCriterion\LogicalAnd([
420
                        new ContentCriterion\ContentId([1, 2, 3]),
421
                        new ContentCriterion\Visibility(ContentCriterion\Visibility::VISIBLE),
422
                    ]),
423
                    'offset' => 10,
424
                    'limit' => 10,
425
                ]), [1, 2, 3],
426
            ],
427
        ];
428
    }
429
430
    public function testCreateUpdateStruct()
431
    {
432
        $this->assertEquals(new URLUpdateStruct(), $this->createUrlService()->createUpdateStruct());
433
    }
434
435
    protected function configureUrlViewPermissionForHasAccess($hasAccess = false)
436
    {
437
        $this->getRepositoryMock()
438
            ->expects($this->once())
439
            ->method('hasAccess')
440
            ->with('url', 'view')
441
            ->willReturn($hasAccess);
442
    }
443
444
    protected function configureUrlViewPermission($object, $hasAccess = false)
445
    {
446
        $this->permissionResolver
447
            ->expects($this->once())
448
            ->method('canUser')
449
            ->with(
450
                $this->equalTo('url'),
451
                $this->equalTo('view'),
452
                $this->equalTo($object)
453
            )
454
            ->will($this->returnValue($hasAccess));
455
    }
456
457
    protected function configureUrlUpdatePermission($object, $hasAccess = false)
458
    {
459
        $this->permissionResolver
460
            ->expects($this->once())
461
            ->method('canUser')
462
            ->with(
463
                $this->equalTo('url'),
464
                $this->equalTo('update'),
465
                $this->equalTo($object)
466
            )
467
            ->will($this->returnValue($hasAccess));
468
    }
469
470
    protected function configurePermissions(array $permissions)
471
    {
472
        $this->permissionResolver
473
            ->expects($this->exactly(count($permissions)))
474
            ->method('canUser')
475
            ->withConsecutive(...$permissions)
476
            ->willReturn(true);
477
    }
478
479
    /**
480
     * @return \eZ\Publish\API\Repository\URLService|\PHPUnit\Framework\MockObject\MockObject
481
     */
482
    private function createUrlService(array $methods = null)
483
    {
484
        return $this
485
            ->getMockBuilder(URLService::class)
486
            ->setConstructorArgs([$this->getRepositoryMock(), $this->urlHandler, $this->permissionResolver])
487
            ->setMethods($methods)
488
            ->getMock();
489
    }
490
491
    private function getApiUrl($id = null, $url = null)
492
    {
493
        return new URL(['id' => $id, 'url' => $url]);
494
    }
495
}
496