Completed
Push — master ( 88eef6...81252c )
by Joschi
02:44
created

TestUrl   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 21
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 1
c 3
b 0
f 0
lcom 0
cbo 1
dl 0
loc 21
rs 10
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)
0 ignored issues
show
Coding Style introduced by
Spaces must be used for alignment; tabs are not allowed
Loading history...
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\Kernel\Ports\Kernel;
40
use Apparat\Kernel\Tests\AbstractTest;
41
use Apparat\Object\Domain\Model\Object\Id;
42
use Apparat\Object\Domain\Model\Object\Revision;
43
use Apparat\Object\Domain\Model\Object\Type;
44
use Apparat\Object\Domain\Model\Path\ApparatUrl;
45
use Apparat\Object\Domain\Model\Path\LocalPath;
46
use Apparat\Object\Domain\Model\Path\ObjectUrl;
47
use Apparat\Object\Domain\Model\Path\Url;
48
use Apparat\Object\Domain\Repository\Service;
49
use Apparat\Object\Infrastructure\Repository\FileAdapterStrategy;
50
use Apparat\Object\Ports\Repository;
51
52
/**
53
 * Object URL tests
54
 *
55
 * @package Apparat\Object
56
 * @subpackage ApparatTest
57
 */
58
class UrlTest extends AbstractTest
59
{
60
    /**
61
     * Example query fragment
62
     *
63
     * @var string
64
     */
65
    const QUERY_FRAGMENT = '?param=value#fragment';
66
    /**
67
     * Repository URL
68
     *
69
     * @var string
70
     */
71
    const REPOSITORY_URL = '/repo';
72
    /**
73
     * Example path
74
     *
75
     * @var string
76
     */
77
    const PATH = '/2015/10/01/36704.event/36704-1';
78
    /**
79
     * Example URL
80
     *
81
     * @var string
82
     */
83
    const URL = self::REPOSITORY_URL.self::PATH.self::QUERY_FRAGMENT;
84
    /**
85
     * Example URL
86
     *
87
     * @var string
88
     */
89
    const REMOTE_URL = 'http://apparat:[email protected]:80'.self::PATH.self::QUERY_FRAGMENT;
90
    /**
91
     * Example apparat URL
92
     *
93
     * @var string
94
     */
95
    const APPARAT_URL = 'aprts://apparat:[email protected]:80'.self::PATH.self::QUERY_FRAGMENT;
96
97
    /**
98
     * Setup
99
     */
100
    public static function setUpBeforeClass()
101
    {
102
        // Disable repository auto-connection
103
        Kernel::create(Service::class)->useAutoConnect(false);
104
    }
105
106
    /**
107
     * Test an URL
108
     *
109
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
110
     * @expectedExceptionCode 1451515385
111
     */
112
    public function testInvalidRemoteUrl()
113
    {
114
        new ObjectUrl(self::REMOTE_URL);
115
    }
116
117
    /**
118
     * Test an URL
119
     */
120
    public function testRemoteUrl()
121
    {
122
        $url = new ObjectUrl(self::REMOTE_URL, true);
123
        $this->assertInstanceOf(ObjectUrl::class, $url);
124
        $this->assertEquals(self::REMOTE_URL, strval($url));
125
        $this->assertEquals('http', $url->getScheme());
126
        $this->assertEquals('apparat', $url->getUser());
127
        $this->assertEquals('tools', $url->getPassword());
128
        $this->assertEquals('apparat.tools', $url->getHost());
129
        $this->assertEquals(80, $url->getPort());
130
        $this->assertEquals('', $url->getPath());
131
        $this->assertEquals(['param' => 'value'], $url->getQuery());
132
        $this->assertEquals('fragment', $url->getFragment());
133
        $this->assertInstanceOf(\DateTimeImmutable::class, $url->getCreationDate());
134
        $this->assertEquals('2015-10-01', $url->getCreationDate()->format('Y-m-d'));
135
        $this->assertInstanceOf(Id::class, $url->getId());
136
        $this->assertEquals(new Id(36704), $url->getId());
137
        $this->assertInstanceOf(Type::class, $url->getType());
138
        $this->assertEquals(new Type('event'), $url->getType());
139
        $this->assertInstanceOf(Revision::class, $url->getRevision());
140
        $this->assertEquals(new Revision(1), $url->getRevision());
141
    }
142
143
    /**
144
     * Test a local URL with path prefix
145
     */
146
    public function testLeadedLocalUrl()
147
    {
148
        $pathPrefix = '/prefix/path';
149
        $url = new ObjectUrl($pathPrefix.self::PATH);
150
        $this->assertEquals($pathPrefix, $url->getPath());
151
    }
152
153
    /**
154
     * Test an invalid URL
155
     *
156
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
157
     * @expectedExceptionCode 1449873819
158
     */
159
    public function testInvalidUrl()
160
    {
161
        new ObjectUrl('invalid://');
162
    }
163
164
    /**
165
     * Test an invalid URL path
166
     *
167
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
168
     * @expectedExceptionCode 1449874494
169
     */
170
    public function testInvalidUrlPath()
171
    {
172
        new ObjectUrl('http://invalid~url*path', true);
173
    }
174
175
    /**
176
     * Test the scheme setter
177
     *
178
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
179
     * @expectedExceptionCode 1449924914
180
     */
181
    public function testUrlSchemeSetter()
182
    {
183
        $url = new ObjectUrl(self::URL);
184
        $this->assertEquals(ObjectUrl::SCHEME_HTTPS, $url->setScheme(ObjectUrl::SCHEME_HTTPS)->getScheme());
185
        $url->setScheme('invalid');
186
    }
187
188
    /**
189
     * Test the host setter
190
     *
191
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
192
     * @expectedExceptionCode 1449925567
193
     */
194
    public function testUrlHostSetter()
195
    {
196
        $url = new ObjectUrl(self::URL);
197
        $this->assertEquals('apparat.com', $url->setHost('apparat.com')->getHost());
198
        $url->setHost('_');
199
    }
200
201
    /**
202
     * Test the port setter
203
     *
204
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
205
     * @expectedExceptionCode 1449925885
206
     */
207
    public function testUrlPortSetter()
208
    {
209
        $url = new ObjectUrl(self::URL);
210
        $this->assertEquals(443, $url->setPort(443)->getPort());
211
        $url->setPort(123456789);
212
    }
213
214
    /**
215
     * Test the remaining setter methods
216
     */
217
    public function testUrlSetters()
218
    {
219
        $url = new ObjectUrl(self::URL);
220
        $this->assertEquals('test', $url->setUser('test')->getUser());
221
        $this->assertEquals(null, $url->setUser(null)->getUser());
222
        $this->assertEquals('password', $url->setPassword('password')->getPassword());
223
        $this->assertEquals(null, $url->setPassword(null)->getPassword());
224
        $this->assertEquals('/path/prefix', $url->setPath('/path/prefix')->getPath());
225
        $this->assertEquals(['param2' => 'value2'], $url->setQuery(['param2' => 'value2'])->getQuery());
226
        $this->assertEquals('fragment2', $url->setFragment('fragment2')->getFragment());
227
228
        $this->assertEquals(
229
            '2016-01-01',
230
            $url->setCreationDate(new \DateTimeImmutable('@1451606400'))->getCreationDate()->format('Y-m-d')
231
        );
232
        $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...
233
        $this->assertEquals('article', $url->setType(new Type('article'))->getType()->getType());
234
        $this->assertEquals(
235
            Revision::CURRENT,
236
            $url->setRevision(new Revision(Revision::CURRENT))->getRevision()->getRevision()
237
        );
238
    }
239
240
    /**
241
     * Test the override functionality when getting the URL path
242
     */
243
    public function testUrlPathOverride()
244
    {
245
        $url = new TestObjectUrl(self::URL);
246
        $this->assertEquals(
247
            'https://user:[email protected]:443/path/prefix/2015/10/01/36704.event/36704-2?param2=value2#fragment2',
248
            $url->getUrlOverride()
249
        );
250
    }
251
252
    /**
253
     * Test absolute URL
254
     */
255
    public function testUrlAbsolute()
256
    {
257
        $url = new ObjectUrl(self::REMOTE_URL, true);
258
        $this->assertEquals(true, $url->isAbsolute());
259
    }
260
261
    /**
262
     * Test relative URL
263
     */
264
    public function testUrlReative()
265
    {
266
        $url = new ObjectUrl(self::PATH.self::QUERY_FRAGMENT);
267
        $this->assertEquals(false, $url->isAbsolute());
268
    }
269
270
    /**
271
     * Test URL comparison
272
     */
273
    public function testUrlComparison()
274
    {
275
        $this->assertFalse((new Url('http://example.com'))->matches(new Url('https://example.com')));
276
        $this->assertFalse((new Url('http://[email protected]'))->matches(new Url('http://[email protected]')));
277
        $this->assertFalse(
278
            (new Url('http://user:[email protected]'))->matches(new Url('http://user:[email protected]'))
279
        );
280
        $this->assertFalse((new Url('http://example1.com'))->matches(new Url('http://example2.com')));
281
        $this->assertFalse((new Url('http://example.com:80'))->matches(new Url('http://example.com:443')));
282
        $this->assertFalse((new Url('http://example.com/a'))->matches(new Url('http://example.com/b')));
283
        $this->assertFalse((new Url('http://example.com/?a=1'))->matches(new Url('http://example.com/?a=2')));
284
        $this->assertFalse((new Url('http://example.com/#a'))->matches(new Url('http://example.com/#b')));
285
        $this->assertTrue((new Url(self::REMOTE_URL))->matches(new Url(self::REMOTE_URL)));
286
    }
287
288
    /**
289
     * Test object URL comparison
290
     */
291
    public function testObjectUrlComparison()
292
    {
293
        $this->assertFalse(
294
            (
295
            new ObjectUrl(
296
                'http://example.com/2015/10/01/36704.event/36704-1',
297
                true
298
            )
299
            )->matches(new ObjectUrl('https://example.com/2015/10/01/36704.event/36704-1', true))
300
        );
301
        $this->assertFalse(
302
            (
303
            new ObjectUrl(
304
                'http://example.com/2015/10/01/36704.event/36704-1',
305
                true
306
            )
307
            )->matches(new ObjectUrl('http://example.com/2016/10/01/36704.event/36704-1', true))
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('http://example.com/2015/10/01/36705.event/36705-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/2015/10/01/36704.article/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/36704.event/36704-2', true))
332
        );
333
        $this->assertTrue((new ObjectUrl(self::REMOTE_URL, true))->matches(new ObjectUrl(self::REMOTE_URL, true)));
334
    }
335
336
    /**
337
     * Test an invalid apparat URL
338
     *
339
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
340
     * @expectedExceptionCode 1451435429
341
     */
342
    public function testInvalidApparatUrl()
343
    {
344
        new ApparatUrl(self::REMOTE_URL, true);
345
    }
346
347
    /**
348
     * Test an absolute apparat URL
349
     */
350
    public function testAbsoluteApparatUrl()
351
    {
352
        $apparatUrl = new ApparatUrl(self::APPARAT_URL, true);
353
        $this->assertInstanceOf(ApparatUrl::class, $apparatUrl);
354
    }
355
356
    /**
357
     * Test an unknown relative apparat URL
358
     *
359
     * @expectedException \Apparat\Object\Domain\Model\Path\ApparatInvalidArgumentException
360
     * @expectedExceptionCode 1452695654
361
     */
362
    public function testUnknownRelativeApparatUrl()
363
    {
364
        new ApparatUrl(self::PATH.self::QUERY_FRAGMENT);
365
    }
366
367
    /**
368
     * Test a relative apparat URL
369
     */
370
    public function testRelativeApparatUrl()
371
    {
372
        Repository::register(
373
            self::REPOSITORY_URL,
374
            [
375
                'type' => FileAdapterStrategy::TYPE,
376
                'root' => __DIR__,
377
            ]
378
        );
379
        $apparatUrl = new ApparatUrl(self::URL);
380
        $this->assertInstanceOf(ApparatUrl::class, $apparatUrl);
381
    }
382
383
    /**
384
     * Test invalid date precision
385
     *
386
     * @expectedException \Apparat\Object\Domain\Model\Path\InvalidArgumentException
387
     * @expectedExceptionCode 1451514114
388
     */
389
    public function testInvalidDatePrecision()
390
    {
391
        new LocalPath(self::PATH, -1);
392
    }
393
394
    /**
395
     * Test arbitrary date precision
396
     */
397
    public function testArbitraryDatePrecision()
398
    {
399
        $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...
400
        $this->assertInstanceOf(LocalPath::class, $path);
401
    }
402
}
403