Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#14)
by Der Mundschenk
02:24
created

DOM_Test   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 437
Duplicated Lines 21.74 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 4
Bugs 0 Features 1
Metric Value
dl 95
loc 437
rs 10
c 4
b 0
f 1
wmc 27
lcom 1
cbo 3

22 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 5 1
A tearDown() 0 2 1
A load_html() 0 3 1
A test_block_tags() 0 19 1
A test_nodelist_to_array() 0 17 2
A provide_get_ancestors_data() 0 5 1
A test_get_ancestors() 0 16 2
A provide_has_class_data() 0 14 1
A test_has_class() 0 12 2
A provide_get_block_parent_data() 0 12 1
A test_get_block_parent() 0 18 3
A test_get_block_parent_name() 8 8 1
A test_get_prev_chr() 13 13 1
A test_get_previous_textnode_null() 0 4 1
A test_get_next_chr() 13 13 1
A test_get_next_textnode_null() 0 4 1
A test_get_first_textnode() 21 21 1
A test_get_first_textnode_null() 0 7 1
A test_get_first_textnode_only_block_level() 9 9 1
A test_get_last_textnode() 22 22 1
A test_get_last_textnode_null() 0 7 1
A test_get_last_textnode_only_block_level() 9 9 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 *  This file is part of PHP-Typography.
4
 *
5
 *  Copyright 2015-2017 Peter Putzer.
6
 *
7
 *  This program is free software; you can redistribute it and/or
8
 *  modify it under the terms of the GNU General Public License
9
 *  as published by the Free Software Foundation; either version 2
10
 *  of the License, or ( at your option ) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, write to the Free Software
19
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
 *
21
 *  @package mundschenk-at/php-typography/tests
22
 *  @license http://www.gnu.org/licenses/gpl-2.0.html
23
 */
24
25
namespace PHP_Typography\Tests;
26
27
use \PHP_Typography\DOM;
28
29
/**
30
 * DOM unit test.
31
 *
32
 * @coversDefaultClass \PHP_Typography\DOM
33
 * @usesDefaultClass \PHP_Typography\DOM
34
 */
35
class DOM_Test extends PHP_Typography_Testcase {
36
37
	/**
38
	 * HTML parser.
39
	 *
40
	 * @var \Masterminds\HTML5
41
	 */
42
	private $parser;
43
44
	/**
45
	 * Sets up the fixture, for example, opens a network connection.
46
	 * This method is called before a test is executed.
47
	 */
48
	protected function setUp() { // @codingStandardsIgnoreLine
49
		$this->parser = new \Masterminds\HTML5( [
50
			'disable_html_ns' => true,
51
		] );
52
	}
53
54
	/**
55
	 * Tears down the fixture, for example, closes a network connection.
56
	 * This method is called after a test is executed.
57
	 */
58
	protected function tearDown() { // @codingStandardsIgnoreLine
59
	}
60
61
	/**
62
	 * Load given HTML document.
63
	 *
64
	 * @param  string $html An HTML document.
65
	 *
66
	 * @return \DOMDocument
67
	 */
68
	protected function load_html( $html ) {
69
		return $this->parser->loadHTML( $html );
70
	}
71
72
	/**
73
	 * Test block_tags.
74
	 *
75
	 * @covers ::block_tags
76
	 */
77
	public function test_block_tags() {
78
		$block_tags = DOM::block_tags( true );
79
		$this->assertInternalType( 'array', $block_tags );
80
81
		$tag_names = array_keys( $block_tags );
82
		$this->assertContainsOnly( 'string', $tag_names );
83
84
		// Our "custom" block tags.
85
		$this->assertContains( 'dt', $tag_names );
86
		$this->assertContains( 'li', $tag_names );
87
		$this->assertContains( 'td', $tag_names );
88
89
		// Some block tags native to HTML5-PHP.
90
		$this->assertContains( 'p', $tag_names );
91
		$this->assertContains( 'div', $tag_names );
92
93
		// Non-block tags.
94
		$this->assertNotContains( 'img', $tag_names );
95
	}
96
97
	/**
98
	 * Test nodelist_to_array.
99
	 *
100
	 * @covers ::nodelist_to_array
101
	 */
102
	public function test_nodelist_to_array() {
103
		$parser = new \Masterminds\HTML5( [
104
			'disable_html_ns' => true,
105
		] );
106
		$dom = $parser->loadHTML( '<body><p>blabla</p><ul><li>foo</li><li>bar</li></ul></body>' );
107
		$xpath = new \DOMXPath( $dom );
108
109
		$node_list = $xpath->query( '//*' );
110
		$node_array = DOM::nodelist_to_array( $node_list );
111
112
		$this->assertGreaterThan( 1, $node_list->length );
113
		$this->assertSame( $node_list->length, count( $node_array ) );
114
		foreach ( $node_list as $node ) {
115
			$this->assertArrayHasKey( spl_object_hash( $node ), $node_array );
116
			$this->assertSame( $node, $node_array[ spl_object_hash( $node ) ] );
117
		}
118
	}
119
120
	/**
121
	 * Provide data for testing get_ancestors.
122
	 *
123
	 * @return array
124
	 */
125
	public function provide_get_ancestors_data() {
126
		return [
127
			[ '<div class="ancestor"><p class="ancestor">bar <span id="origin">foo</span></p></div><p>foo <span>bar</span></p>', '//*[@id="origin"]' ],
128
		];
129
	}
130
131
	/**
132
	 * Test get_ancestors.
133
	 *
134
	 * @covers ::get_ancestors
135
	 *
136
	 * @uses ::nodelist_to_array
137
	 *
138
	 * @dataProvider provide_get_ancestors_data
139
	 *
140
	 * @param  string $html        HTML input.
141
	 * @param  string $xpath_query XPath query.
142
	 */
143
	public function test_get_ancestors( $html, $xpath_query ) {
144
		$parser = new \Masterminds\HTML5( [
145
			'disable_html_ns' => true,
146
		] );
147
		$dom = $parser->loadHTML( '<body>' . $html . '</body>' );
148
		$xpath = new \DOMXPath( $dom );
149
150
		$origin = $xpath->query( $xpath_query )->item( 0 );
151
		$ancestor_array = DOM::get_ancestors( $origin );
152
		$ancestor_array_xpath = DOM::nodelist_to_array( $xpath->query( 'ancestor::*', $origin ) );
153
154
		$this->assertSame( count( $ancestor_array ), count( $ancestor_array_xpath ) );
155
		foreach ( $ancestor_array as $ancestor ) {
156
			$this->assertContains( $ancestor, $ancestor_array_xpath );
157
		}
158
	}
159
160
	/**
161
	 * Provide data for testing has_class.
162
	 *
163
	 * @return array
164
	 */
165
	public function provide_has_class_data() {
166
		return [
167
			[ '<span class="foo bar"></span>', '//span', 'bar', true ],
168
			[ '<span class="foo bar"></span>', '//span', 'foo', true ],
169
			[ '<span class="foo bar"></span>', '//span', 'foobar', false ],
170
			[ '<span class="foo bar"></span>', '//span', [ 'foo' ], true ],
171
			[ '<span class="foo bar"></span>', '//span', [ 'foo', 'bar' ], true ],
172
			[ '<span class="foo bar"></span>', '//span', '', false ],
173
			[ '<span class="foo bar"></span>', '//span', [], false ],
174
			[ '<span class="foo bar"></span>', '//span', [ '' ], false ],
175
			[ '<span class="foo bar">something</span>', '//span/text()', 'bar', true ],
176
			[ '<span>something</span>', '//span', 'foo', false ],
177
		];
178
	}
179
180
	/**
181
	 * Test has_class.
182
	 *
183
	 * @covers ::has_class
184
	 *
185
	 * @dataProvider provide_has_class_data
186
	 *
187
	 * @param  string $html        HTML input.
188
	 * @param  string $xpath_query XPath query.
189
	 * @param  array  $classnames  Array of classnames.
190
	 * @param  bool   $result      Expected result.
191
	 */
192
	public function test_has_class( $html, $xpath_query, $classnames, $result ) {
193
		$parser = new \Masterminds\HTML5( [
194
			'disable_html_ns' => true,
195
		] );
196
		$dom = $parser->loadHTML( '<body>' . $html . '</body>' );
197
		$xpath = new \DOMXPath( $dom );
198
199
		$nodes = $xpath->query( $xpath_query );
200
		foreach ( $nodes as $node ) {
201
			$this->assertSame( $result, DOM::has_class( $node, $classnames ) );
202
		}
203
	}
204
205
	/**
206
	 * Provides data for testing get_block_parent.
207
	 *
208
	 * @return array
209
	 */
210
	public function provide_get_block_parent_data() {
211
		return [
212
			[ "//*[@id='foo']",          "//*[@id='para']",  'p',    '<div id="outer"><p id="para"><span>A</span><span id="foo">new hope.</span></p><span><span id="bar">blabla</span></span></div>' ],
213
			[ "//*[@id='para']//text()", "//*[@id='para']",  'p',    '<div id="outer"><p id="para"><span>A</span><span id="foo">new hope.</span></p><span><span id="bar">blabla</span></span></div>' ],
214
			[ "//*[@id='para']",         "//*[@id='outer']", 'div',  '<div id="outer"><p id="para"><span>A</span><span id="foo">new hope.</span></p><span><span id="bar">blabla</span></span></div>' ],
215
			[ "//*[@id='bar']",          "//*[@id='outer']", 'div',  '<div id="outer"><p id="para"><span>A</span><span id="foo">new hope.</span></p><span><span id="bar">blabla</span></span></div>' ],
216
			[ "//*[@id='bar']//text()",  "//*[@id='outer']", 'div',  '<div id="outer"><p id="para"><span>A</span><span id="foo">new hope.</span></p><span><span id="bar">blabla</span></span></div>' ],
217
			[ "//*[@id='foo']//text()",  "//*[@id='para']",  'p',    '<div id="outer"><p id="para"><span>A</span><span id="foo">new hope.</span></p><span><span id="bar">blabla</span></span></div>' ],
218
			[ "//*[@id='outer']",        '//html',           'html', '<div id="outer"><p id="para"><span>A</span><span id="foo">new hope.</span></p><span><span id="bar">blabla</span></span></div>' ],
219
			[ '//html',                  null,               '',     '<div id="outer"><p id="para"><span>A</span><span id="foo">new hope.</span></p><span><span id="bar">blabla</span></span></div>' ],
220
		];
221
	}
222
223
	/**
224
	 * Test get_block_parent.
225
	 *
226
	 * @covers ::get_block_parent
227
	 *
228
	 * @dataProvider provide_get_block_parent_data
229
	 *
230
	 * @param string $input_xpath  Input element/node.
231
	 * @param string $parent_xpath Expected result element.
232
	 * @param string $parent_tag   Parent tag name.
233
	 * @param string $html         HTML code.
234
	 */
235
	public function test_get_block_parent( $input_xpath, $parent_xpath, $parent_tag, $html ) {
236
		$doc = $this->load_html( $html );
237
		$xpath = new \DOMXPath( $doc );
238
239
		$input_node  = $xpath->query( $input_xpath )->item( 0 ); // really only one.
240
241
		if ( ! empty( $parent_xpath ) ) {
242
			$parent_node = $xpath->query( $parent_xpath )->item( 0 ); // really only one.
243
		} else {
244
			$parent_node = null;
245
		}
246
247
		$this->assertSame( $parent_node, DOM::get_block_parent( $input_node ) );
248
249
		if ( ! empty( $parent_tag ) ) {
250
			$this->assertSame( $parent_tag, $parent_node->tagName );
0 ignored issues
show
Bug introduced by
The property tagName does not seem to exist in DOMNode.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
251
		}
252
	}
253
254
	/**
255
	 * Test get_block_parent_name.
256
	 *
257
	 * @covers ::get_block_parent_name
258
	 *
259
	 * @uses ::get_block_parent
260
	 *
261
	 * @dataProvider provide_get_block_parent_data
262
	 *
263
	 * @param string $input_xpath  Input element/node.
264
	 * @param string $parent_xpath Ignored.
265
	 * @param string $parent_tag   Parent tag name.
266
	 * @param string $html         HTML code.
267
	 */
268 View Code Duplication
	public function test_get_block_parent_name( $input_xpath, $parent_xpath, $parent_tag, $html ) {
0 ignored issues
show
Unused Code introduced by
The parameter $parent_xpath is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
269
		$doc = $this->load_html( $html );
270
		$xpath = new \DOMXPath( $doc );
271
272
		$input_node  = $xpath->query( $input_xpath )->item( 0 ); // really only one.
273
274
		$this->assertSame( $parent_tag, DOM::get_block_parent_name( $input_node ) );
275
	}
276
277
	/**
278
	 * Test get_prev_chr.
279
	 *
280
	 * @covers ::get_prev_chr
281
	 * @covers ::get_adjacent_chr
282
	 * @covers ::get_previous_textnode
283
	 * @covers ::get_adjacent_textnode
284
	 *
285
	 * @uses ::get_last_textnode
286
	 * @uses ::get_edge_textnode
287
	 * @uses PHP_Typography\Strings::functions
288
	 */
289 View Code Duplication
	public function test_get_prev_chr() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
290
		$html = '<p><span>A</span><span id="foo">new hope.</span></p><p><span id="bar">The empire</span> strikes back.</p<';
291
		$doc = $this->load_html( $html );
292
		$xpath = new \DOMXPath( $doc );
293
294
		$textnodes = $xpath->query( "//*[@id='foo']/text()" ); // really only one.
295
		$prev_char = DOM::get_prev_chr( $textnodes->item( 0 ) );
296
		$this->assertSame( 'A', $prev_char );
297
298
		$textnodes = $xpath->query( "//*[@id='bar']/text()" ); // really only one.
299
		$prev_char = DOM::get_prev_chr( $textnodes->item( 0 ) );
300
		$this->assertSame( '', $prev_char );
301
	}
302
303
	/**
304
	 * Test get_previous_textnode.
305
	 *
306
	 * @covers ::get_previous_textnode
307
	 * @covers ::get_adjacent_textnode
308
	 */
309
	public function test_get_previous_textnode_null() {
310
		$node = DOM::get_previous_textnode( null );
311
		$this->assertNull( $node );
312
	}
313
314
	/**
315
	 * Test get_next_chr.
316
	 *
317
	 * @covers ::get_next_chr
318
	 * @covers ::get_adjacent_chr
319
	 * @covers ::get_next_textnode
320
	 * @covers ::get_adjacent_textnode
321
	 *
322
	 * @uses ::get_first_textnode
323
	 * @uses ::get_edge_textnode
324
	 * @uses PHP_Typography\Strings::functions
325
	 */
326 View Code Duplication
	public function test_get_next_chr() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
327
		$html = '<p><span id="foo">A</span><span id="bar">new hope.</span></p><p><span>The empire</span> strikes back.</p<';
328
		$doc = $this->load_html( $html );
329
		$xpath = new \DOMXPath( $doc );
330
331
		$textnodes = $xpath->query( "//*[@id='foo']/text()" ); // really only one.
332
		$prev_char = DOM::get_next_chr( $textnodes->item( 0 ) );
333
		$this->assertSame( 'n', $prev_char );
334
335
		$textnodes = $xpath->query( "//*[@id='bar']/text()" ); // really only one.
336
		$prev_char = DOM::get_next_chr( $textnodes->item( 0 ) );
337
		$this->assertSame( '', $prev_char );
338
	}
339
340
	/**
341
	 * Test get_next_textnode.
342
	 *
343
	 * @covers ::get_next_textnode
344
	 * @covers ::get_adjacent_textnode
345
	 */
346
	public function test_get_next_textnode_null() {
347
		$node = DOM::get_next_textnode( null );
348
		$this->assertNull( $node );
349
	}
350
351
352
	/**
353
	 * Test get_first_textnode.
354
	 *
355
	 * @covers ::get_first_textnode
356
	 * @covers ::get_edge_textnode
357
	 */
358 View Code Duplication
	public function test_get_first_textnode() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
359
		$html = '<p><span id="foo">A</span><span id="bar">new hope.</span></p>';
360
		$doc = $this->load_html( $html );
361
		$xpath = new \DOMXPath( $doc );
362
363
		$textnodes = $xpath->query( "//*[@id='foo']/text()" ); // really only one.
364
		$node = DOM::get_first_textnode( $textnodes->item( 0 ) );
365
		$this->assertSame( 'A', $node->nodeValue );
366
367
		$textnodes = $xpath->query( "//*[@id='foo']" ); // really only one.
368
		$node = DOM::get_first_textnode( $textnodes->item( 0 ) );
369
		$this->assertSame( 'A', $node->nodeValue );
370
371
		$textnodes = $xpath->query( "//*[@id='bar']" ); // really only one.
372
		$node = DOM::get_first_textnode( $textnodes->item( 0 ) );
373
		$this->assertSame( 'new hope.', $node->nodeValue );
374
375
		$textnodes = $xpath->query( '//p' ); // really only one.
376
		$node = DOM::get_first_textnode( $textnodes->item( 0 ) );
377
		$this->assertSame( 'A', $node->nodeValue );
378
	}
379
380
	/**
381
	 * Test get_first_textnode.
382
	 *
383
	 * @covers ::get_first_textnode
384
	 * @covers ::get_edge_textnode
385
	 */
386
	public function test_get_first_textnode_null() {
387
		// Passing null returns null.
388
		$this->assertNull( DOM::get_first_textnode( null ) );
389
390
		// Passing a DOMNode that is not a DOMElement or a DOMText returns null as well.
391
		$this->assertNull( DOM::get_first_textnode( new \DOMDocument() ) );
392
	}
393
394
	/**
395
	 * Test get_first_textnode.
396
	 *
397
	 * @covers ::get_first_textnode
398
	 * @covers ::get_edge_textnode
399
	 */
400 View Code Duplication
	public function test_get_first_textnode_only_block_level() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
401
		$html = '<div><div id="foo">No</div><div id="bar">hope</div></div>';
402
		$doc = $this->load_html( $html );
403
		$xpath = new \DOMXPath( $doc );
404
405
		$textnodes = $xpath->query( '//div' ); // really only one.
406
		$node = DOM::get_first_textnode( $textnodes->item( 0 ) );
407
		$this->assertNull( $node );
408
	}
409
410
	/**
411
	 * Test get_last_textnode.
412
	 *
413
	 * @covers ::get_last_textnode
414
	 * @covers ::get_edge_textnode
415
	 *
416
	 * @uses ::get_first_textnode
417
	 */
418 View Code Duplication
	public function test_get_last_textnode() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
419
420
		$html = '<p><span id="foo">A</span><span id="bar">new hope.</span> Really.</p>';
421
		$doc = $this->load_html( $html );
422
		$xpath = new \DOMXPath( $doc );
423
424
		$textnodes = $xpath->query( "//*[@id='foo']/text()" ); // really only one.
425
		$node = DOM::get_last_textnode( $textnodes->item( 0 ) );
426
		$this->assertSame( 'A', $node->nodeValue );
427
428
		$textnodes = $xpath->query( "//*[@id='foo']" ); // really only one.
429
		$node = DOM::get_last_textnode( $textnodes->item( 0 ) );
430
		$this->assertSame( 'A', $node->nodeValue );
431
432
		$textnodes = $xpath->query( "//*[@id='bar']" ); // really only one.
433
		$node = DOM::get_first_textnode( $textnodes->item( 0 ) );
434
		$this->assertSame( 'new hope.', $node->nodeValue );
435
436
		$textnodes = $xpath->query( '//p' ); // really only one.
437
		$node = DOM::get_last_textnode( $textnodes->item( 0 ) );
438
		$this->assertSame( ' Really.', $node->nodeValue );
439
	}
440
441
	/**
442
	 * Test get_last_textnode.
443
	 *
444
	 * @covers ::get_last_textnode
445
	 * @covers ::get_edge_textnode
446
	 */
447
	public function test_get_last_textnode_null() {
448
		// Passing null returns null.
449
		$this->assertNull( DOM::get_last_textnode( null ) );
450
451
		// Passing a DOMNode that is not a DOMElement or a DOMText returns null as well.
452
		$this->assertNull( DOM::get_last_textnode( new \DOMDocument() ) );
453
	}
454
455
456
	/**
457
	 * Test get_last_textnode.
458
	 *
459
	 * @covers ::get_last_textnode
460
	 * @covers ::get_edge_textnode
461
	 */
462 View Code Duplication
	public function test_get_last_textnode_only_block_level() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
463
		$html = '<div><div id="foo">No</div><div id="bar">hope</div></div>';
464
		$doc = $this->load_html( $html );
465
		$xpath = new \DOMXPath( $doc );
466
467
		$textnodes = $xpath->query( '//div' ); // really only one.
468
		$node = DOM::get_last_textnode( $textnodes->item( 0 ) );
469
		$this->assertNull( $node );
470
	}
471
}
472