GraphTest::testIsStrict()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * phpDocumentor
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * @link      http://phpdoc.org
12
 */
13
14
namespace phpDocumentor\GraphViz\Test;
15
16
use InvalidArgumentException;
17
use Mockery as m;
18
use phpDocumentor\GraphViz\AttributeNotFound;
19
use phpDocumentor\GraphViz\Edge;
20
use phpDocumentor\GraphViz\Exception;
21
use phpDocumentor\GraphViz\Graph;
22
use phpDocumentor\GraphViz\Node;
23
use PHPUnit\Framework\TestCase;
24
use RuntimeException;
25
use function is_readable;
26
use function preg_replace;
27
use function sys_get_temp_dir;
28
use function tempnam;
29
use const PHP_EOL;
30
31
/**
32
 * Test for the the class representing a GraphViz graph.
33
 */
34
class GraphTest extends TestCase
35
{
36
    /** @var Graph */
37
    protected $fixture;
38
39
    /**
40
     * Sets up the fixture, for example, opens a network connection.
41
     * This method is called before a test is executed.
42
     */
43
    protected function setUp() : void
44
    {
45
        $this->fixture = new Graph();
46
    }
47
48
    /**
49
     * Tears down the fixture, for example, closes a network connection.
50
     * This method is called after a test is executed.
51
     */
52
    protected function tearDown() : void
53
    {
54
        m::close();
55
    }
56
57
    /**
58
     * @covers \phpDocumentor\GraphViz\Graph::create
59
     */
60
    public function testCreate() : void
61
    {
62
        $fixture = Graph::create();
63
        $this->assertInstanceOf(
64
            Graph::class,
65
            $fixture
66
        );
67
        $this->assertSame(
68
            'G',
69
            $fixture->getName()
70
        );
71
        $this->assertSame(
72
            'digraph',
73
            $fixture->getType()
74
        );
75
76
        $fixture = Graph::create('MyName', false);
77
        $this->assertSame(
78
            'MyName',
79
            $fixture->getName()
80
        );
81
        $this->assertSame(
82
            'graph',
83
            $fixture->getType()
84
        );
85
    }
86
87
    /**
88
     * @covers \phpDocumentor\GraphViz\Graph::setName
89
     */
90
    public function testSetName() : void
91
    {
92
        $this->assertSame(
93
            $this->fixture,
94
            $this->fixture->setName('otherName'),
95
            'Expecting a fluent interface'
96
        );
97
    }
98
99
    /**
100
     * @covers \phpDocumentor\GraphViz\Graph::getName
101
     */
102
    public function testGetName() : void
103
    {
104
        $this->assertSame(
105
            $this->fixture->getName(),
106
            'G',
107
            'Expecting the name to match the initial state'
108
        );
109
        $this->fixture->setName('otherName');
110
        $this->assertSame(
111
            $this->fixture->getName(),
112
            'otherName',
113
            'Expecting the name to contain the new value'
114
        );
115
    }
116
117
    /**
118
     * @covers \phpDocumentor\GraphViz\Graph::setType
119
     */
120
    public function testSetType() : void
121
    {
122
        $this->assertSame(
123
            $this->fixture,
124
            $this->fixture->setType('digraph'),
125
            'Expecting a fluent interface'
126
        );
127
        $this->assertSame(
128
            $this->fixture,
129
            $this->fixture->setType('graph'),
130
            'Expecting a fluent interface'
131
        );
132
        $this->assertSame(
133
            $this->fixture,
134
            $this->fixture->setType('subgraph'),
135
            'Expecting a fluent interface'
136
        );
137
    }
138
139
    /**
140
     * @covers \phpDocumentor\GraphViz\Graph::setType
141
     */
142
    public function testSetTypeException() : void
143
    {
144
        $this->expectException(InvalidArgumentException::class);
145
        $this->fixture->setType('fakegraphg');
146
    }
147
148
    /**
149
     * @covers \phpDocumentor\GraphViz\Graph::getType
150
     */
151
    public function testGetType() : void
152
    {
153
        $this->assertSame(
154
            $this->fixture->getType(),
155
            'digraph'
156
        );
157
        $this->fixture->setType('graph');
158
        $this->assertSame(
159
            $this->fixture->getType(),
160
            'graph'
161
        );
162
    }
163
164
    public function testSetStrict() : void
165
    {
166
        $this->assertSame(
167
            $this->fixture,
168
            $this->fixture->setStrict(true),
169
            'Expecting a fluent interface'
170
        );
171
        $this->assertSame(
172
            $this->fixture,
173
            $this->fixture->setStrict(false),
174
            'Expecting a fluent interface'
175
        );
176
    }
177
178
    public function testIsStrict() : void
179
    {
180
        $this->assertSame(
181
            $this->fixture->isStrict(),
182
            false
183
        );
184
        $this->fixture->setStrict(true);
185
        $this->assertSame(
186
            $this->fixture->isStrict(),
187
            true
188
        );
189
    }
190
191
    public function testSetPath() : void
192
    {
193
        $this->assertSame(
194
            $this->fixture,
195
            $this->fixture->setPath(__DIR__),
196
            'Expecting a fluent interface'
197
        );
198
    }
199
200
    /**
201
     * @covers \phpDocumentor\GraphViz\Graph::__call
202
     * @covers \phpDocumentor\GraphViz\Graph::getAttribute
203
     * @covers \phpDocumentor\GraphViz\Graph::setAttribute
204
     */
205
    public function test__call() : void
206
    {
207
        $this->assertNull($this->fixture->MyMethod());
0 ignored issues
show
Documentation Bug introduced by
The method MyMethod does not exist on object<phpDocumentor\GraphViz\Graph>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
208
        $this->assertSame($this->fixture, $this->fixture->setBgColor('black'));
0 ignored issues
show
Documentation Bug introduced by
The method setBgColor does not exist on object<phpDocumentor\GraphViz\Graph>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
209
        $this->assertSame('black', $this->fixture->getBgColor()->getValue());
0 ignored issues
show
Documentation Bug introduced by
The method getBgColor does not exist on object<phpDocumentor\GraphViz\Graph>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
210
    }
211
212
    /**
213
     * @covers \phpDocumentor\GraphViz\Graph::getAttribute
214
     * @covers \phpDocumentor\GraphViz\AttributeNotFound::__construct
215
     */
216
    public function testGetNonExistingAttributeThrowsAttributeNotFound() : void
217
    {
218
        $this->expectException(AttributeNotFound::class);
219
        $this->expectExceptionMessage('Attribute with name "notexisting" was not found');
220
221
        $this->fixture->getNotExisting();
0 ignored issues
show
Documentation Bug introduced by
The method getNotExisting does not exist on object<phpDocumentor\GraphViz\Graph>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
222
    }
223
224
    /**
225
     * @covers \phpDocumentor\GraphViz\Graph::addGraph
226
     */
227
    public function testAddGraph() : void
228
    {
229
        $mock = m::mock(Graph::class);
230
        $mock->expects('setType');
231
        $mock->expects('getName');
232
233
        $this->assertSame(
234
            $this->fixture,
235
            $this->fixture->addGraph($mock)
0 ignored issues
show
Documentation introduced by
$mock is of type object<Mockery\LegacyMockInterface>, but the function expects a object<self>.

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...
236
        );
237
    }
238
239
    /**
240
     * @covers \phpDocumentor\GraphViz\Graph::hasGraph
241
     */
242
    public function testHasGraph() : void
243
    {
244
        $mock = m::mock(Graph::class);
245
        $mock->expects('getName')->andReturn('MyName');
246
        $mock->expects('setType');
247
248
        $this->assertFalse($this->fixture->hasGraph('MyName'));
249
        $this->fixture->addGraph($mock);
0 ignored issues
show
Documentation introduced by
$mock is of type object<Mockery\LegacyMockInterface>, but the function expects a object<self>.

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...
250
        $this->assertTrue($this->fixture->hasGraph('MyName'));
251
    }
252
253
    /**
254
     * @covers \phpDocumentor\GraphViz\Graph::getGraph
255
     */
256
    public function testGetGraph() : void
257
    {
258
        $mock = m::mock(Graph::class);
259
        $mock->expects('setType');
260
        $mock->expects('getName')->andReturn('MyName');
261
262
        $this->fixture->addGraph($mock);
0 ignored issues
show
Documentation introduced by
$mock is of type object<Mockery\LegacyMockInterface>, but the function expects a object<self>.

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...
263
        $this->assertSame(
264
            $mock,
265
            $this->fixture->getGraph('MyName')
266
        );
267
    }
268
269
    /**
270
     * @covers \phpDocumentor\GraphViz\Graph::setNode
271
     */
272
    public function testSetNode() : void
273
    {
274
        $mock = m::mock(Node::class);
275
        $mock->expects('getName')->andReturn('MyName');
276
277
        $this->assertSame(
278
            $this->fixture,
279
            $this->fixture->setNode($mock)
0 ignored issues
show
Documentation introduced by
$mock is of type object<Mockery\LegacyMockInterface>, but the function expects a object<phpDocumentor\GraphViz\Node>.

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...
280
        );
281
    }
282
283
    /**
284
     * @covers \phpDocumentor\GraphViz\Graph::findNode
285
     */
286
    public function testFindNode() : void
287
    {
288
        $this->assertNull($this->fixture->findNode('MyNode'));
289
290
        $mock = m::mock(Node::class);
291
        $mock->expects('getName')->andReturn('MyName');
292
293
        $this->fixture->setNode($mock);
0 ignored issues
show
Documentation introduced by
$mock is of type object<Mockery\LegacyMockInterface>, but the function expects a object<phpDocumentor\GraphViz\Node>.

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...
294
        $this->assertSame(
295
            $mock,
296
            $this->fixture->findNode('MyName')
297
        );
298
299
        $subGraph = Graph::create();
300
        $mock2    = m::mock(Node::class);
301
        $mock2->expects('getName')->andReturn('MyName2');
302
303
        $subGraph->setNode($mock2);
304
305
        $this->fixture->addGraph($subGraph);
306
        $this->assertSame(
307
            $mock2,
308
            $this->fixture->findNode('MyName2')
309
        );
310
    }
311
312
    /**
313
     * @covers \phpDocumentor\GraphViz\Graph::__set
314
     */
315
    public function test__set() : void
316
    {
317
        $mock = m::mock(Node::class);
318
319
        $this->fixture->__set('myNode', $mock);
0 ignored issues
show
Documentation introduced by
$mock is of type object<Mockery\LegacyMockInterface>, but the function expects a object<phpDocumentor\GraphViz\Node>.

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...
320
321
        self::assertSame($mock, $this->fixture->myNode);
0 ignored issues
show
Documentation introduced by
The property myNode does not exist on object<phpDocumentor\GraphViz\Graph>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
322
    }
323
324
    /**
325
     * @covers \phpDocumentor\GraphViz\Graph::__get
326
     */
327
    public function test__get() : void
328
    {
329
        $mock = m::mock(Node::class);
330
331
        $this->fixture->myNode = $mock;
0 ignored issues
show
Documentation introduced by
The property myNode does not exist on object<phpDocumentor\GraphViz\Graph>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
332
        $this->assertSame(
333
            $mock,
334
            $this->fixture->myNode
0 ignored issues
show
Documentation introduced by
The property myNode does not exist on object<phpDocumentor\GraphViz\Graph>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
335
        );
336
    }
337
338
    /**
339
     * @covers \phpDocumentor\GraphViz\Graph::link
340
     */
341
    public function testLink() : void
342
    {
343
        $mock = m::mock(Edge::class);
344
345
        $this->assertSame(
346
            $this->fixture,
347
            $this->fixture->link($mock)
0 ignored issues
show
Documentation introduced by
$mock is of type object<Mockery\LegacyMockInterface>, but the function expects a object<phpDocumentor\GraphViz\Edge>.

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...
348
        );
349
    }
350
351
    /**
352
     * @covers \phpDocumentor\GraphViz\Graph::export
353
     */
354
    public function testExportException() : void
355
    {
356
        $graph    = Graph::create('My First Graph');
357
        $filename = tempnam(sys_get_temp_dir(), 'tst');
358
359
        if ($filename === false) {
360
            $this->assertFalse('Failed to create destination file');
361
362
            return;
363
        }
364
365
        $this->expectException(Exception::class);
366
        $graph->export('fpd', $filename);
367
    }
368
369
    /**
370
     * @covers \phpDocumentor\GraphViz\Graph::export
371
     */
372
    public function testExport() : void
373
    {
374
        $graph    = Graph::create('My First Graph');
375
        $filename = tempnam(sys_get_temp_dir(), 'tst');
376
377
        if ($filename === false) {
378
            $this->assertFalse('Failed to create destination file');
379
380
            return;
381
        }
382
383
        $this->assertSame(
384
            $graph,
385
            $graph->export('pdf', $filename)
386
        );
387
        $this->assertTrue(is_readable($filename));
388
    }
389
390
    /**
391
     * @covers \phpDocumentor\GraphViz\Graph::__toString
392
     */
393
    public function test__toString() : void
394
    {
395
        $graph = Graph::create('My First Graph');
396
        $this->assertSame(
397
            $this->normalizeLineEndings((string) $graph),
398
            $this->normalizeLineEndings(('digraph "My First Graph" {' . PHP_EOL . PHP_EOL . '}'))
399
        );
400
401
        $graph->setLabel('PigeonPost');
402
        $this->assertSame(
403
            $this->normalizeLineEndings((string) $graph),
404
            $this->normalizeLineEndings(('digraph "My First Graph" {' . PHP_EOL . 'label="PigeonPost"' . PHP_EOL . '}'))
405
        );
406
407
        $graph->setStrict(true);
408
        $this->assertSame(
409
            $this->normalizeLineEndings((string) $graph),
410
            $this->normalizeLineEndings(
411
                ('strict digraph "My First Graph" {' . PHP_EOL . 'label="PigeonPost"' . PHP_EOL . '}')
412
            )
413
        );
414
    }
415
416
    /**
417
     * Help avoid issue of "#Warning: Strings contain different line endings!" on Windows.
418
     */
419
    private function normalizeLineEndings(string $string) : string
420
    {
421
        $result = preg_replace('~\R~u', "\r\n", $string);
422
        if ($result === null) {
423
            throw new RuntimeException('Normalize line endings failed');
424
        }
425
426
        return $result;
427
    }
428
}
429