Completed
Push — master ( fb71af...61dfa4 )
by Joschi
06:16
created

UrlTest::testUrlRemote()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 1
eloc 5
nc 1
nop 0
1
<?php
2
3
/**
4
 * apparat-object
5
 *
6
 * @category    Apparat
7
 * @package     Apparat\Object
8
 * @subpackage  Apparat\Object\Infrastructure
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license     http://opensource.org/licenses/MIT The MIT License (MIT)
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Apparat\Object\Tests;
38
39
use Apparat\Object\Domain\Model\Object\Id;
40
use Apparat\Object\Domain\Model\Object\Revision;
41
use Apparat\Object\Domain\Model\Object\Type;
42
use Apparat\Object\Domain\Model\Path\ApparatUrl;
43
use Apparat\Object\Domain\Model\Path\LocalPath;
44
use Apparat\Object\Domain\Model\Path\ObjectUrl;
45
use Apparat\Object\Domain\Model\Path\Url;
46
use Apparat\Object\Domain\Repository\Service;
47
use Apparat\Object\Infrastructure\Repository\FileAdapterStrategy;
48
use Apparat\Object\Ports\Repository;
49
50
/**
51
 * Object URL tests
52
 *
53
 * @package Apparat\Object
54
 * @subpackage ApparatTest
55
 */
56
class UrlTest extends AbstractDisabledAutoconnectorTest
57
{
58
    /**
59
     * Example query fragment
60
     *
61
     * @var string
62
     */
63
    const QUERY_FRAGMENT = '?param=value#fragment';
64
    /**
65
     * Repository URL
66
     *
67
     * @var string
68
     */
69
    const REPOSITORY_URL = '/repo';
70
    /**
71
     * Example path
72
     *
73
     * @var string
74
     */
75
    const PATH = '/2015/10/01/36704.event/36704-1';
76
    /**
77
     * Example URL
78
     *
79
     * @var string
80
     */
81
    const URL = self::REPOSITORY_URL.self::PATH.self::QUERY_FRAGMENT;
82
    /**
83
     * Example remote repository URL
84
     *
85
     * @var string
86
     */
87
    const REMOTE_REPOSITORY_URL = 'http://apparat:[email protected]:80';
88
    /**
89
     * Example remote URL
90
     *
91
     * @var string
92
     */
93
    const REMOTE_URL = self::REMOTE_REPOSITORY_URL.self::PATH.self::QUERY_FRAGMENT;
94
    /**
95
     * Example apparat URL
96
     *
97
     * @var string
98
     */
99
    const APPARAT_URL = 'aprts://apparat:[email protected]:80'.self::PATH.self::QUERY_FRAGMENT;
100
101
    /**
102
     * Test an URL
103
     *
104
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
105
     * @expectedExceptionCode 1451515385
106
     */
107
    public function testInvalidRemoteUrl()
108
    {
109
        new ObjectUrl(self::REMOTE_URL);
110
    }
111
112
    /**
113
     * Test an URL
114
     */
115
    public function testRemoteUrl()
116
    {
117
        $url = new ObjectUrl(self::REMOTE_URL, true);
118
        $this->assertInstanceOf(ObjectUrl::class, $url);
119
        $this->assertEquals(self::REMOTE_URL, strval($url));
120
        $this->assertEquals('http', $url->getScheme());
121
        $this->assertEquals('apparat', $url->getUser());
122
        $this->assertEquals('tools', $url->getPassword());
123
        $this->assertEquals('apparat.tools', $url->getHost());
124
        $this->assertEquals(80, $url->getPort());
125
        $this->assertEquals('', $url->getPath());
126
        $this->assertEquals(['param' => 'value'], $url->getQuery());
127
        $this->assertEquals('fragment', $url->getFragment());
128
        $this->assertInstanceOf(\DateTimeImmutable::class, $url->getCreationDate());
129
        $this->assertEquals('2015-10-01', $url->getCreationDate()->format('Y-m-d'));
130
        $this->assertInstanceOf(Id::class, $url->getId());
131
        $this->assertEquals(new Id(36704), $url->getId());
132
        $this->assertInstanceOf(Type::class, $url->getType());
133
        $this->assertEquals(new Type('event'), $url->getType());
134
        $this->assertInstanceOf(Revision::class, $url->getRevision());
135
        $this->assertEquals(new Revision(1), $url->getRevision());
136
        $this->assertEquals(self::REMOTE_REPOSITORY_URL, Service::normalizeRepositoryUrl($url));
137
    }
138
139
    /**
140
     * Test a local URL with path prefix
141
     */
142
    public function testLeadedLocalUrl()
143
    {
144
        $pathPrefix = '/prefix/path';
145
        $url = new ObjectUrl($pathPrefix.self::PATH);
146
        $this->assertEquals($pathPrefix, $url->getPath());
147
        $this->assertEquals(self::PATH, $url->getLocalPath());
148
    }
149
150
    /**
151
     * Test an invalid URL
152
     *
153
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
154
     * @expectedExceptionCode 1449873819
155
     */
156
    public function testInvalidUrl()
157
    {
158
        new ObjectUrl('invalid://');
159
    }
160
161
    /**
162
     * Test an invalid URL path
163
     *
164
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
165
     * @expectedExceptionCode 1449874494
166
     */
167
    public function testInvalidUrlPath()
168
    {
169
        new ObjectUrl('http://invalid~url*path', true);
170
    }
171
172
    /**
173
     * Test the scheme setter
174
     *
175
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
176
     * @expectedExceptionCode 1449924914
177
     */
178
    public function testUrlSchemeSetter()
179
    {
180
        $url = new ObjectUrl(self::URL);
181
        $this->assertEquals(ObjectUrl::SCHEME_HTTPS, $url->setScheme(ObjectUrl::SCHEME_HTTPS)->getScheme());
182
        $url->setScheme('invalid');
183
    }
184
185
    /**
186
     * Test the host setter
187
     *
188
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
189
     * @expectedExceptionCode 1449925567
190
     */
191
    public function testUrlHostSetter()
192
    {
193
        $url = new ObjectUrl(self::URL);
194
        $this->assertEquals('apparat.com', $url->setHost('apparat.com')->getHost());
195
        $url->setHost('_');
196
    }
197
198
    /**
199
     * Test the port setter
200
     *
201
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
202
     * @expectedExceptionCode 1449925885
203
     */
204
    public function testUrlPortSetter()
205
    {
206
        $url = new ObjectUrl(self::URL);
207
        $this->assertEquals(443, $url->setPort(443)->getPort());
208
        $url->setPort(123456789);
209
    }
210
211
    /**
212
     * Test the remaining setter methods
213
     */
214
    public function testUrlSetters()
215
    {
216
        $url = new ObjectUrl(self::URL);
217
        $this->assertEquals('test', $url->setUser('test')->getUser());
218
        $this->assertEquals(null, $url->setUser(null)->getUser());
219
        $this->assertEquals('password', $url->setPassword('password')->getPassword());
220
        $this->assertEquals(null, $url->setPassword(null)->getPassword());
221
        $this->assertEquals('/path/prefix', $url->setPath('/path/prefix')->getPath());
222
        $this->assertEquals(['param2' => 'value2'], $url->setQuery(['param2' => 'value2'])->getQuery());
223
        $this->assertEquals('fragment2', $url->setFragment('fragment2')->getFragment());
224
225
        $this->assertEquals(
226
            '2016-01-01',
227
            $url->setCreationDate(new \DateTimeImmutable('@1451606400'))->getCreationDate()->format('Y-m-d')
228
        );
229
        $this->assertEquals(123, $url->setId(new Id(123))->getId()->getId());
0 ignored issues
show
Bug introduced by
The method getId cannot be called on $url->setId(new \Apparat...bject\Id(123))->getId() (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
230
        $this->assertEquals('article', $url->setType(new Type('article'))->getType()->getType());
231
        $this->assertEquals(
232
            Revision::CURRENT,
233
            $url->setRevision(new Revision(Revision::CURRENT))->getRevision()->getRevision()
234
        );
235
    }
236
237
    /**
238
     * Test the override functionality when getting the URL path
239
     */
240
    public function testUrlPathOverride()
241
    {
242
        $url = new TestObjectUrl(self::URL);
243
        $this->assertEquals(
244
            'https://user:[email protected]:443/path/prefix/2015/10/01/36704.event/36704-2?param2=value2#fragment2',
245
            $url->getUrlOverride()
246
        );
247
    }
248
249
    /**
250
     * Test absolute URL
251
     */
252
    public function testUrlAbsolute()
253
    {
254
        $url = new ObjectUrl(self::REMOTE_URL, true);
255
        $this->assertEquals(true, $url->isAbsolute());
256
        $this->assertEquals(self::REMOTE_REPOSITORY_URL, $url->getRepositoryUrl());
257
    }
258
259
    /**
260
     * Test absolute URL
261
     */
262
    public function testUrlAbsoluteLocal()
263
    {
264
        $url = new ObjectUrl(rtrim(getenv('APPARAT_BASE_URL'), '/').self::REPOSITORY_URL.self::PATH, true);
265
        $this->assertTrue($url->isAbsoluteLocal());
266
    }
267
268
    /**
269
     * Test relative URL
270
     */
271
    public function testUrlRelative()
272
    {
273
        $url = new ObjectUrl(self::PATH.self::QUERY_FRAGMENT);
274
        $this->assertEquals(false, $url->isAbsolute());
275
    }
276
277
    /**
278
     * Test remote URL
279
     */
280
    public function testUrlRemote()
281
    {
282
        $url = new ObjectUrl(self::REMOTE_REPOSITORY_URL.self::REPOSITORY_URL.self::PATH, true);
283
        $this->assertTrue($url->isRemote());
284
        $url = new ObjectUrl(rtrim(getenv('APPARAT_BASE_URL'), '/').self::REPOSITORY_URL.self::PATH, true);
285
        $this->assertFalse($url->isRemote());
286
    }
287
288
    /**
289
     * Test URL comparison
290
     */
291
    public function testUrlComparison()
292
    {
293
        $this->assertFalse((new Url('http://example.com'))->matches(new Url('https://example.com')));
294
        $this->assertFalse((new Url('http://[email protected]'))->matches(new Url('http://[email protected]')));
295
        $this->assertFalse((new Url('http://user:[email protected]'))->matches(new Url('http://user:[email protected]')));
296
        $this->assertFalse((new Url('http://example1.com'))->matches(new Url('http://example2.com')));
297
        $this->assertFalse((new Url('http://example.com:80'))->matches(new Url('http://example.com:443')));
298
        $this->assertFalse((new Url('http://example.com/a'))->matches(new Url('http://example.com/b')));
299
        $this->assertFalse((new Url('http://example.com/?a=1'))->matches(new Url('http://example.com/?a=2')));
300
        $this->assertFalse((new Url('http://example.com/#a'))->matches(new Url('http://example.com/#b')));
301
        $this->assertTrue((new Url(self::REMOTE_URL))->matches(new Url(self::REMOTE_URL)));
302
    }
303
304
    /**
305
     * Test object URL comparison
306
     */
307
    public function testObjectUrlComparison()
308
    {
309
        $this->assertFalse(
310
            (
311
            new ObjectUrl(
312
                'http://example.com/2015/10/01/36704.event/36704-1',
313
                true
314
            )
315
            )->matches(new ObjectUrl('https://example.com/2015/10/01/36704.event/36704-1', true))
316
        );
317
        $this->assertFalse(
318
            (
319
            new ObjectUrl(
320
                'http://example.com/2015/10/01/36704.event/36704-1',
321
                true
322
            )
323
            )->matches(new ObjectUrl('http://example.com/2016/10/01/36704.event/36704-1', true))
324
        );
325
        $this->assertFalse(
326
            (
327
            new ObjectUrl(
328
                'http://example.com/2015/10/01/36704.event/36704-1',
329
                true
330
            )
331
            )->matches(new ObjectUrl('http://example.com/2015/10/01/36705.event/36705-1', true))
332
        );
333
        $this->assertFalse(
334
            (
335
            new ObjectUrl(
336
                'http://example.com/2015/10/01/36704.event/36704-1',
337
                true
338
            )
339
            )->matches(new ObjectUrl('http://example.com/2015/10/01/36704.article/36704-1', true))
340
        );
341
        $this->assertFalse(
342
            (
343
            new ObjectUrl(
344
                'http://example.com/2015/10/01/36704.event/36704-1',
345
                true
346
            )
347
            )->matches(new ObjectUrl('http://example.com/2015/10/01/36704.event/36704-2', true))
348
        );
349
        $this->assertTrue((new ObjectUrl(self::REMOTE_URL, true))->matches(new ObjectUrl(self::REMOTE_URL, true)));
350
    }
351
352
    /**
353
     * Test an invalid apparat URL
354
     *
355
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
356
     * @expectedExceptionCode 1451435429
357
     */
358
    public function testInvalidApparatUrl()
359
    {
360
        new ApparatUrl(self::REMOTE_URL, true);
361
    }
362
363
    /**
364
     * Test an absolute apparat URL
365
     */
366
    public function testAbsoluteApparatUrl()
367
    {
368
        $apparatUrl = new ApparatUrl(self::APPARAT_URL, true);
369
        $this->assertInstanceOf(ApparatUrl::class, $apparatUrl);
370
        $this->assertEquals('https://apparat:[email protected]:80', Service::normalizeRepositoryUrl($apparatUrl));
371
    }
372
373
    /**
374
     * Test an unknown relative apparat URL
375
     *
376
     * @expectedException \Apparat\Object\Domain\Model\Path\ApparatInvalidArgumentException
377
     * @expectedExceptionCode 1452695654
378
     */
379
    public function testUnknownRelativeApparatUrl()
380
    {
381
        new ApparatUrl(self::PATH.self::QUERY_FRAGMENT);
382
    }
383
384
    /**
385
     * Test a relative apparat URL
386
     */
387
    public function testRelativeApparatUrl()
388
    {
389
        Repository::register(
390
            self::REPOSITORY_URL,
391
            [
392
                'type' => FileAdapterStrategy::TYPE,
393
                'root' => __DIR__,
394
            ]
395
        );
396
        $apparatUrl = new ApparatUrl(self::URL);
397
        $this->assertInstanceOf(ApparatUrl::class, $apparatUrl);
398
        $this->assertEquals(self::REPOSITORY_URL, Service::normalizeRepositoryUrl($apparatUrl));
399
    }
400
401
    /**
402
     * Test invalid date precision
403
     *
404
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
405
     * @expectedExceptionCode 1451514114
406
     */
407
    public function testInvalidDatePrecision()
408
    {
409
        new LocalPath(self::PATH, -1);
410
    }
411
412
    /**
413
     * Test arbitrary date precision
414
     */
415
    public function testArbitraryDatePrecision()
416
    {
417
        $path = new LocalPath(self::PATH, true);
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a null|object<Apparat\Obje...odel\Path\TRUE>|integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
418
        $this->assertInstanceOf(LocalPath::class, $path);
419
    }
420
421
    /**
422
     * Test the normalization of an invalid repository URL
423
     *
424
     * @expectedException \Apparat\Object\Domain\Repository\InvalidArgumentException
425
     * @expectedExceptionCode 1453097878
426
     */
427
    public function testInvalidRepositoryUrlNormalization()
428
    {
429
        Service::normalizeRepositoryUrl(new Url(self::REMOTE_REPOSITORY_URL));
430
    }
431
432
    /**
433
     * Test the normalization of a local string repository URL
434
     */
435
    public function testLocalStringUrlNormalization()
436
    {
437
        $this->assertEquals(self::REPOSITORY_URL.self::PATH, Service::normalizeRepositoryUrl(getenv('APPARAT_BASE_URL').self::REPOSITORY_URL.self::PATH));
438
    }
439
}
440