Completed
Push — master ( 42ada5...e5d943 )
by Joschi
02:42
created

UrlTest::testRemoteUrl()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 1 Features 0
Metric Value
c 5
b 1
f 0
dl 0
loc 25
rs 8.8571
cc 1
eloc 23
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 a remote 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
        $this->assertFalse($url->isDraft());
144
        $this->assertTrue($url->setDraft(true)->isDraft());
145
    }
146
147
    /**
148
     * Test a remote draft URL
149
     */
150
    public function testRemoteDraftUrl() {
151
        $url = new ObjectUrl(self::REMOTE_REPOSITORY_URL.self::DRAFT_PATH, true);
152
        $this->assertInstanceOf(ObjectUrl::class, $url);
153
        $this->assertTrue($url->isDraft());
154
    }
155
156
    /**
157
     * Test a local URL with path prefix
158
     */
159
    public function testLeadedLocalUrl()
160
    {
161
        $pathPrefix = '/prefix/path';
162
        $url = new ObjectUrl($pathPrefix.self::PATH);
163
        $this->assertEquals($pathPrefix, $url->getPath());
164
        $this->assertEquals(self::PATH, $url->getLocalPath());
165
    }
166
167
    /**
168
     * Test an invalid URL
169
     *
170
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
171
     * @expectedExceptionCode 1449873819
172
     */
173
    public function testInvalidUrl()
174
    {
175
        new ObjectUrl('invalid://');
176
    }
177
178
    /**
179
     * Test an invalid URL path
180
     *
181
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
182
     * @expectedExceptionCode 1449874494
183
     */
184
    public function testInvalidUrlPath()
185
    {
186
        new ObjectUrl('http://invalid~url*path', true);
187
    }
188
189
    /**
190
     * Test the scheme setter
191
     *
192
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
193
     * @expectedExceptionCode 1449924914
194
     */
195
    public function testUrlSchemeSetter()
196
    {
197
        $url = new ObjectUrl(self::URL);
198
        $this->assertEquals(ObjectUrl::SCHEME_HTTPS, $url->setScheme(ObjectUrl::SCHEME_HTTPS)->getScheme());
199
        $url->setScheme('invalid');
200
    }
201
202
    /**
203
     * Test the host setter
204
     *
205
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
206
     * @expectedExceptionCode 1449925567
207
     */
208
    public function testUrlHostSetter()
209
    {
210
        $url = new ObjectUrl(self::URL);
211
        $this->assertEquals('apparat.com', $url->setHost('apparat.com')->getHost());
212
        $url->setHost('_');
213
    }
214
215
    /**
216
     * Test the port setter
217
     *
218
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
219
     * @expectedExceptionCode 1449925885
220
     */
221
    public function testUrlPortSetter()
222
    {
223
        $url = new ObjectUrl(self::URL);
224
        $this->assertEquals(443, $url->setPort(443)->getPort());
225
        $url->setPort(123456789);
226
    }
227
228
    /**
229
     * Test the remaining setter methods
230
     */
231
    public function testUrlSetters()
232
    {
233
        $url = new ObjectUrl(self::URL);
234
        $this->assertEquals('test', $url->setUser('test')->getUser());
235
        $this->assertEquals(null, $url->setUser(null)->getUser());
236
        $this->assertEquals('password', $url->setPassword('password')->getPassword());
237
        $this->assertEquals(null, $url->setPassword(null)->getPassword());
238
        $this->assertEquals('/path/prefix', $url->setPath('/path/prefix')->getPath());
239
        $this->assertEquals(['param2' => 'value2'], $url->setQuery(['param2' => 'value2'])->getQuery());
240
        $this->assertEquals('fragment2', $url->setFragment('fragment2')->getFragment());
241
242
        $this->assertEquals(
243
            '2016-01-01',
244
            $url->setCreationDate(new \DateTimeImmutable('@1451606400'))->getCreationDate()->format('Y-m-d')
245
        );
246
        $this->assertEquals(123, $url->setId(new Id(123))->getId()->getId());
247
        $this->assertEquals('article', $url->setType(new Type('article'))->getType()->getType());
248
        $this->assertEquals(
249
            Revision::CURRENT,
250
            $url->setRevision(new Revision(Revision::CURRENT))->getRevision()->getRevision()
251
        );
252
    }
253
254
    /**
255
     * Test the override functionality when getting the URL path
256
     */
257
    public function testUrlPathOverride()
258
    {
259
        $url = new TestObjectUrl(self::URL);
260
        $this->assertEquals(
261
            'https://user:[email protected]:443/path/prefix/2015/10/01/36704.event/36704-2?param2=value2#fragment2',
262
            $url->getUrlOverride()
263
        );
264
    }
265
266
    /**
267
     * Test absolute URL
268
     */
269
    public function testUrlAbsolute()
270
    {
271
        $url = new ObjectUrl(self::REMOTE_URL, true);
272
        $this->assertEquals(true, $url->isAbsolute());
273
        $this->assertEquals(self::REMOTE_REPOSITORY_URL, $url->getRepositoryUrl());
274
    }
275
276
    /**
277
     * Test absolute URL
278
     */
279
    public function testUrlAbsoluteLocal()
280
    {
281
        $url = new ObjectUrl(rtrim(getenv('APPARAT_BASE_URL'), '/').self::REPOSITORY_URL.self::PATH, true);
282
        $this->assertTrue($url->isAbsoluteLocal());
283
    }
284
285
    /**
286
     * Test relative URL
287
     */
288
    public function testUrlRelative()
289
    {
290
        $url = new ObjectUrl(self::PATH.self::QUERY_FRAGMENT);
291
        $this->assertEquals(false, $url->isAbsolute());
292
    }
293
294
    /**
295
     * Test remote URL
296
     */
297
    public function testUrlRemote()
298
    {
299
        $url = new ObjectUrl(self::REMOTE_REPOSITORY_URL.self::REPOSITORY_URL.self::PATH, true);
300
        $this->assertTrue($url->isRemote());
301
        $url = new ObjectUrl(rtrim(getenv('APPARAT_BASE_URL'), '/').self::REPOSITORY_URL.self::PATH, true);
302
        $this->assertFalse($url->isRemote());
303
    }
304
305
    /**
306
     * Test URL comparison
307
     */
308
    public function testUrlComparison()
309
    {
310
        $this->assertFalse((new Url('http://example.com'))->matches(new Url('https://example.com')));
311
        $this->assertFalse((new Url('http://[email protected]'))->matches(new Url('http://[email protected]')));
312
        $this->assertFalse((new Url('http://user:[email protected]'))->matches(
313
            new Url('http://user:[email protected]')
314
        ));
315
        $this->assertFalse((new Url('http://example1.com'))->matches(new Url('http://example2.com')));
316
        $this->assertFalse((new Url('http://example.com:80'))->matches(new Url('http://example.com:443')));
317
        $this->assertFalse((new Url('http://example.com/a'))->matches(new Url('http://example.com/b')));
318
        $this->assertFalse((new Url('http://example.com/?a=1'))->matches(new Url('http://example.com/?a=2')));
319
        $this->assertFalse((new Url('http://example.com/#a'))->matches(new Url('http://example.com/#b')));
320
        $this->assertTrue((new Url(self::REMOTE_URL))->matches(new Url(self::REMOTE_URL)));
321
    }
322
323
    /**
324
     * Test object URL comparison
325
     */
326
    public function testObjectUrlComparison()
327
    {
328
        $this->assertFalse(
329
            (
330
            new ObjectUrl(
331
                'http://example.com/2015/10/01/36704.event/36704-1',
332
                true
333
            )
334
            )->matches(new ObjectUrl('https://example.com/2015/10/01/36704.event/36704-1', true))
335
        );
336
        $this->assertFalse(
337
            (
338
            new ObjectUrl(
339
                'http://example.com/2015/10/01/36704.event/36704-1',
340
                true
341
            )
342
            )->matches(new ObjectUrl('http://example.com/2016/10/01/36704.event/36704-1', true))
343
        );
344
        $this->assertFalse(
345
            (
346
            new ObjectUrl(
347
                'http://example.com/2015/10/01/36704.event/36704-1',
348
                true
349
            )
350
            )->matches(new ObjectUrl('http://example.com/2015/10/01/36705.event/36705-1', true))
351
        );
352
        $this->assertFalse(
353
            (
354
            new ObjectUrl(
355
                'http://example.com/2015/10/01/36704.event/36704-1',
356
                true
357
            )
358
            )->matches(new ObjectUrl('http://example.com/2015/10/01/36704.article/36704-1', true))
359
        );
360
        $this->assertFalse(
361
            (
362
            new ObjectUrl(
363
                'http://example.com/2015/10/01/36704.event/36704-1',
364
                true
365
            )
366
            )->matches(new ObjectUrl('http://example.com/2015/10/01/36704.event/36704-2', true))
367
        );
368
        $this->assertTrue((new ObjectUrl(self::REMOTE_URL, true))->matches(new ObjectUrl(self::REMOTE_URL, true)));
369
    }
370
371
    /**
372
     * Test an invalid apparat URL
373
     *
374
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
375
     * @expectedExceptionCode 1451435429
376
     */
377
    public function testInvalidApparatUrl()
378
    {
379
        new ApparatUrl(self::REMOTE_URL, true);
380
    }
381
382
    /**
383
     * Test an absolute apparat URL
384
     */
385
    public function testAbsoluteApparatUrl()
386
    {
387
        $apparatUrl = new ApparatUrl(self::APPARAT_URL, true);
388
        $this->assertInstanceOf(ApparatUrl::class, $apparatUrl);
389
        $this->assertEquals('https://apparat:[email protected]:80', Service::normalizeRepositoryUrl($apparatUrl));
390
    }
391
392
    /**
393
     * Test an unknown relative apparat URL
394
     *
395
     * @expectedException \Apparat\Object\Domain\Model\Path\ApparatInvalidArgumentException
396
     * @expectedExceptionCode 1452695654
397
     */
398
    public function testUnknownRelativeApparatUrl()
399
    {
400
        new ApparatUrl(self::PATH.self::QUERY_FRAGMENT);
401
    }
402
403
    /**
404
     * Test a relative apparat URL
405
     */
406
    public function testRelativeApparatUrl()
407
    {
408
        Repository::register(
409
            self::REPOSITORY_URL,
410
            [
411
                'type' => FileAdapterStrategy::TYPE,
412
                'root' => __DIR__,
413
            ]
414
        );
415
        $apparatUrl = new ApparatUrl(self::URL);
416
        $this->assertInstanceOf(ApparatUrl::class, $apparatUrl);
417
        $this->assertEquals(self::REPOSITORY_URL, Service::normalizeRepositoryUrl($apparatUrl));
418
    }
419
420
    /**
421
     * Test invalid date precision
422
     *
423
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
424
     * @expectedExceptionCode 1451514114
425
     */
426
    public function testInvalidDatePrecision()
427
    {
428
        new LocalPath(self::PATH, -1);
429
    }
430
431
    /**
432
     * Test arbitrary date precision
433
     */
434
    public function testArbitraryDatePrecision()
435
    {
436
        $path = new LocalPath(self::PATH, true);
437
        $this->assertInstanceOf(LocalPath::class, $path);
438
    }
439
440
    /**
441
     * Test draft path
442
     */
443
    public function testDraftPath() {
444
        $path = new LocalPath(self::DRAFT_PATH);
445
        $this->assertInstanceOf(LocalPath::class, $path);
446
        $this->assertTrue($path->isDraft());
447
    }
448
449
    /**
450
     * Test the normalization of an invalid repository URL
451
     *
452
     * @expectedException \Apparat\Object\Domain\Repository\InvalidArgumentException
453
     * @expectedExceptionCode 1453097878
454
     */
455
    public function testInvalidRepositoryUrlNormalization()
456
    {
457
        Service::normalizeRepositoryUrl(new Url(self::REMOTE_REPOSITORY_URL));
458
    }
459
460
    /**
461
     * Test the normalization of a local string repository URL
462
     */
463
    public function testLocalStringUrlNormalization()
464
    {
465
        $this->assertEquals(
466
            self::REPOSITORY_URL.self::PATH,
467
            Service::normalizeRepositoryUrl(getenv('APPARAT_BASE_URL').self::REPOSITORY_URL.self::PATH)
468
        );
469
    }
470
}
471