Completed
Push — master ( 68c6f3...91ba10 )
by Joschi
02:27
created

UrlTest::testUrlSetters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
dl 0
loc 22
rs 9.2
c 3
b 1
f 0
cc 1
eloc 17
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 path (draft mode)
78
     *
79
     * @var string
80
     */
81
    const DRAFT_PATH = '/2015/10/01/36704.event/36704+';
82
    /**
83
     * Example URL
84
     *
85
     * @var string
86
     */
87
    const URL = self::REPOSITORY_URL.self::PATH.self::QUERY_FRAGMENT;
88
    /**
89
     * Example remote repository URL
90
     *
91
     * @var string
92
     */
93
    const REMOTE_REPOSITORY_URL = 'http://apparat:[email protected]:80';
94
    /**
95
     * Example remote URL
96
     *
97
     * @var string
98
     */
99
    const REMOTE_URL = self::REMOTE_REPOSITORY_URL.self::PATH.self::QUERY_FRAGMENT;
100
    /**
101
     * Example apparat URL
102
     *
103
     * @var string
104
     */
105
    const APPARAT_URL = 'aprts://apparat:[email protected]:80'.self::PATH.self::QUERY_FRAGMENT;
106
107
    /**
108
     * Test an URL
109
     *
110
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
111
     * @expectedExceptionCode 1451515385
112
     */
113
    public function testInvalidRemoteUrl()
114
    {
115
        new ObjectUrl(self::REMOTE_URL);
116
    }
117
118
    /**
119
     * Test an URL
120
     */
121
    public function testRemoteUrl()
122
    {
123
        $url = new ObjectUrl(self::REMOTE_URL, true);
124
        $this->assertInstanceOf(ObjectUrl::class, $url);
125
        $this->assertEquals(self::REMOTE_URL, strval($url));
126
        $this->assertEquals('http', $url->getScheme());
127
        $this->assertEquals('apparat', $url->getUser());
128
        $this->assertEquals('tools', $url->getPassword());
129
        $this->assertEquals('apparat.tools', $url->getHost());
130
        $this->assertEquals(80, $url->getPort());
131
        $this->assertEquals('', $url->getPath());
132
        $this->assertEquals(['param' => 'value'], $url->getQuery());
133
        $this->assertEquals('fragment', $url->getFragment());
134
        $this->assertInstanceOf(\DateTimeImmutable::class, $url->getCreationDate());
135
        $this->assertEquals('2015-10-01', $url->getCreationDate()->format('Y-m-d'));
136
        $this->assertInstanceOf(Id::class, $url->getId());
137
        $this->assertEquals(new Id(36704), $url->getId());
138
        $this->assertInstanceOf(Type::class, $url->getType());
139
        $this->assertEquals(new Type('event'), $url->getType());
140
        $this->assertInstanceOf(Revision::class, $url->getRevision());
141
        $this->assertEquals(new Revision(1), $url->getRevision());
142
        $this->assertEquals(self::REMOTE_REPOSITORY_URL, Service::normalizeRepositoryUrl($url));
143
    }
144
145
    /**
146
     * Test a local URL with path prefix
147
     */
148
    public function testLeadedLocalUrl()
149
    {
150
        $pathPrefix = '/prefix/path';
151
        $url = new ObjectUrl($pathPrefix.self::PATH);
152
        $this->assertEquals($pathPrefix, $url->getPath());
153
        $this->assertEquals(self::PATH, $url->getLocalPath());
154
    }
155
156
    /**
157
     * Test an invalid URL
158
     *
159
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
160
     * @expectedExceptionCode 1449873819
161
     */
162
    public function testInvalidUrl()
163
    {
164
        new ObjectUrl('invalid://');
165
    }
166
167
    /**
168
     * Test an invalid URL path
169
     *
170
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
171
     * @expectedExceptionCode 1449874494
172
     */
173
    public function testInvalidUrlPath()
174
    {
175
        new ObjectUrl('http://invalid~url*path', true);
176
    }
177
178
    /**
179
     * Test the scheme setter
180
     *
181
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
182
     * @expectedExceptionCode 1449924914
183
     */
184
    public function testUrlSchemeSetter()
185
    {
186
        $url = new ObjectUrl(self::URL);
187
        $this->assertEquals(ObjectUrl::SCHEME_HTTPS, $url->setScheme(ObjectUrl::SCHEME_HTTPS)->getScheme());
188
        $url->setScheme('invalid');
189
    }
190
191
    /**
192
     * Test the host setter
193
     *
194
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
195
     * @expectedExceptionCode 1449925567
196
     */
197
    public function testUrlHostSetter()
198
    {
199
        $url = new ObjectUrl(self::URL);
200
        $this->assertEquals('apparat.com', $url->setHost('apparat.com')->getHost());
201
        $url->setHost('_');
202
    }
203
204
    /**
205
     * Test the port setter
206
     *
207
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
208
     * @expectedExceptionCode 1449925885
209
     */
210
    public function testUrlPortSetter()
211
    {
212
        $url = new ObjectUrl(self::URL);
213
        $this->assertEquals(443, $url->setPort(443)->getPort());
214
        $url->setPort(123456789);
215
    }
216
217
    /**
218
     * Test the remaining setter methods
219
     */
220
    public function testUrlSetters()
221
    {
222
        $url = new ObjectUrl(self::URL);
223
        $this->assertEquals('test', $url->setUser('test')->getUser());
224
        $this->assertEquals(null, $url->setUser(null)->getUser());
225
        $this->assertEquals('password', $url->setPassword('password')->getPassword());
226
        $this->assertEquals(null, $url->setPassword(null)->getPassword());
227
        $this->assertEquals('/path/prefix', $url->setPath('/path/prefix')->getPath());
228
        $this->assertEquals(['param2' => 'value2'], $url->setQuery(['param2' => 'value2'])->getQuery());
229
        $this->assertEquals('fragment2', $url->setFragment('fragment2')->getFragment());
230
231
        $this->assertEquals(
232
            '2016-01-01',
233
            $url->setCreationDate(new \DateTimeImmutable('@1451606400'))->getCreationDate()->format('Y-m-d')
234
        );
235
        $this->assertEquals(123, $url->setId(new Id(123))->getId()->getId());
236
        $this->assertEquals('article', $url->setType(new Type('article'))->getType()->getType());
237
        $this->assertEquals(
238
            Revision::CURRENT,
239
            $url->setRevision(new Revision(Revision::CURRENT))->getRevision()->getRevision()
240
        );
241
    }
242
243
    /**
244
     * Test the override functionality when getting the URL path
245
     */
246
    public function testUrlPathOverride()
247
    {
248
        $url = new TestObjectUrl(self::URL);
249
        $this->assertEquals(
250
            'https://user:[email protected]:443/path/prefix/2015/10/01/36704.event/36704-2?param2=value2#fragment2',
251
            $url->getUrlOverride()
252
        );
253
    }
254
255
    /**
256
     * Test absolute URL
257
     */
258
    public function testUrlAbsolute()
259
    {
260
        $url = new ObjectUrl(self::REMOTE_URL, true);
261
        $this->assertEquals(true, $url->isAbsolute());
262
        $this->assertEquals(self::REMOTE_REPOSITORY_URL, $url->getRepositoryUrl());
263
    }
264
265
    /**
266
     * Test absolute URL
267
     */
268
    public function testUrlAbsoluteLocal()
269
    {
270
        $url = new ObjectUrl(rtrim(getenv('APPARAT_BASE_URL'), '/').self::REPOSITORY_URL.self::PATH, true);
271
        $this->assertTrue($url->isAbsoluteLocal());
272
    }
273
274
    /**
275
     * Test relative URL
276
     */
277
    public function testUrlRelative()
278
    {
279
        $url = new ObjectUrl(self::PATH.self::QUERY_FRAGMENT);
280
        $this->assertEquals(false, $url->isAbsolute());
281
    }
282
283
    /**
284
     * Test remote URL
285
     */
286
    public function testUrlRemote()
287
    {
288
        $url = new ObjectUrl(self::REMOTE_REPOSITORY_URL.self::REPOSITORY_URL.self::PATH, true);
289
        $this->assertTrue($url->isRemote());
290
        $url = new ObjectUrl(rtrim(getenv('APPARAT_BASE_URL'), '/').self::REPOSITORY_URL.self::PATH, true);
291
        $this->assertFalse($url->isRemote());
292
    }
293
294
    /**
295
     * Test URL comparison
296
     */
297
    public function testUrlComparison()
298
    {
299
        $this->assertFalse((new Url('http://example.com'))->matches(new Url('https://example.com')));
300
        $this->assertFalse((new Url('http://[email protected]'))->matches(new Url('http://[email protected]')));
301
        $this->assertFalse((new Url('http://user:[email protected]'))->matches(
302
            new Url('http://user:[email protected]')
303
        ));
304
        $this->assertFalse((new Url('http://example1.com'))->matches(new Url('http://example2.com')));
305
        $this->assertFalse((new Url('http://example.com:80'))->matches(new Url('http://example.com:443')));
306
        $this->assertFalse((new Url('http://example.com/a'))->matches(new Url('http://example.com/b')));
307
        $this->assertFalse((new Url('http://example.com/?a=1'))->matches(new Url('http://example.com/?a=2')));
308
        $this->assertFalse((new Url('http://example.com/#a'))->matches(new Url('http://example.com/#b')));
309
        $this->assertTrue((new Url(self::REMOTE_URL))->matches(new Url(self::REMOTE_URL)));
310
    }
311
312
    /**
313
     * Test object URL comparison
314
     */
315
    public function testObjectUrlComparison()
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('https://example.com/2015/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/2016/10/01/36704.event/36704-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/36705.event/36705-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.article/36704-1', true))
348
        );
349
        $this->assertFalse(
350
            (
351
            new ObjectUrl(
352
                'http://example.com/2015/10/01/36704.event/36704-1',
353
                true
354
            )
355
            )->matches(new ObjectUrl('http://example.com/2015/10/01/36704.event/36704-2', true))
356
        );
357
        $this->assertTrue((new ObjectUrl(self::REMOTE_URL, true))->matches(new ObjectUrl(self::REMOTE_URL, true)));
358
    }
359
360
    /**
361
     * Test an invalid apparat URL
362
     *
363
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
364
     * @expectedExceptionCode 1451435429
365
     */
366
    public function testInvalidApparatUrl()
367
    {
368
        new ApparatUrl(self::REMOTE_URL, true);
369
    }
370
371
    /**
372
     * Test an absolute apparat URL
373
     */
374
    public function testAbsoluteApparatUrl()
375
    {
376
        $apparatUrl = new ApparatUrl(self::APPARAT_URL, true);
377
        $this->assertInstanceOf(ApparatUrl::class, $apparatUrl);
378
        $this->assertEquals('https://apparat:[email protected]:80', Service::normalizeRepositoryUrl($apparatUrl));
379
    }
380
381
    /**
382
     * Test an unknown relative apparat URL
383
     *
384
     * @expectedException \Apparat\Object\Domain\Model\Path\ApparatInvalidArgumentException
385
     * @expectedExceptionCode 1452695654
386
     */
387
    public function testUnknownRelativeApparatUrl()
388
    {
389
        new ApparatUrl(self::PATH.self::QUERY_FRAGMENT);
390
    }
391
392
    /**
393
     * Test a relative apparat URL
394
     */
395
    public function testRelativeApparatUrl()
396
    {
397
        Repository::register(
398
            self::REPOSITORY_URL,
399
            [
400
                'type' => FileAdapterStrategy::TYPE,
401
                'root' => __DIR__,
402
            ]
403
        );
404
        $apparatUrl = new ApparatUrl(self::URL);
405
        $this->assertInstanceOf(ApparatUrl::class, $apparatUrl);
406
        $this->assertEquals(self::REPOSITORY_URL, Service::normalizeRepositoryUrl($apparatUrl));
407
    }
408
409
    /**
410
     * Test invalid date precision
411
     *
412
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
413
     * @expectedExceptionCode 1451514114
414
     */
415
    public function testInvalidDatePrecision()
416
    {
417
        new LocalPath(self::PATH, -1);
418
    }
419
420
    /**
421
     * Test arbitrary date precision
422
     */
423
    public function testArbitraryDatePrecision()
424
    {
425
        $path = new LocalPath(self::PATH, true);
426
        $this->assertInstanceOf(LocalPath::class, $path);
427
    }
428
429
    /**
430
     * Test draft path
431
     */
432
    public function testDraftPath() {
433
        $path = new LocalPath(self::DRAFT_PATH);
434
        $this->assertInstanceOf(LocalPath::class, $path);
435
        $this->assertTrue($path->isDraft());
436
    }
437
438
    /**
439
     * Test the normalization of an invalid repository URL
440
     *
441
     * @expectedException \Apparat\Object\Domain\Repository\InvalidArgumentException
442
     * @expectedExceptionCode 1453097878
443
     */
444
    public function testInvalidRepositoryUrlNormalization()
445
    {
446
        Service::normalizeRepositoryUrl(new Url(self::REMOTE_REPOSITORY_URL));
447
    }
448
449
    /**
450
     * Test the normalization of a local string repository URL
451
     */
452
    public function testLocalStringUrlNormalization()
453
    {
454
        $this->assertEquals(
455
            self::REPOSITORY_URL.self::PATH,
456
            Service::normalizeRepositoryUrl(getenv('APPARAT_BASE_URL').self::REPOSITORY_URL.self::PATH)
457
        );
458
    }
459
}
460