Completed
Push — ezp_30827 ( c6ab75...809fcf )
by
unknown
14:52
created

UrlTest   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 464
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Importance

Changes 0
Metric Value
dl 0
loc 464
rs 10
c 0
b 0
f 0
wmc 24
lcom 1
cbo 13

22 Methods

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