Completed
Push — try/search-config-via-wpadmin ( cb094f...014825 )
by
unknown
74:32 queued 64:33
created

Test_Admin_Menu::test_add_stats_menu()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Tests for Admin_Menu class.
4
 *
5
 * @package automattic/jetpack
6
 */
7
8
use Automattic\Jetpack\Dashboard_Customizations\Admin_Menu;
9
use Automattic\Jetpack\Dashboard_Customizations\Base_Admin_Menu;
10
use Automattic\Jetpack\Status;
11
12
require_jetpack_file( 'modules/masterbar/admin-menu/class-admin-menu.php' );
13
require_jetpack_file( 'tests/php/modules/masterbar/data/admin-menu.php' );
14
15
/**
16
 * Class Test_Admin_Menu
17
 *
18
 * @coversDefaultClass Automattic\Jetpack\Dashboard_Customizations\Admin_Menu
19
 */
20
class Test_Admin_Menu extends WP_UnitTestCase {
21
22
	/**
23
	 * Menu data fixture.
24
	 *
25
	 * @var array
26
	 */
27
	public static $menu_data;
28
29
	/**
30
	 * Submenu data fixture.
31
	 *
32
	 * @var array
33
	 */
34
	public static $submenu_data;
35
36
	/**
37
	 * Test domain.
38
	 *
39
	 * @var string
40
	 */
41
	public static $domain;
42
43
	/**
44
	 * Admin menu instance.
45
	 *
46
	 * @var Admin_Menu
47
	 */
48
	public static $admin_menu;
49
50
	/**
51
	 * Mock user ID.
52
	 *
53
	 * @var int
54
	 */
55
	private static $user_id = 0;
56
57
	/**
58
	 * Create shared fixtures.
59
	 *
60
	 * @param WP_UnitTest_Factory $factory Fixture factory.
61
	 */
62 View Code Duplication
	public static function wpSetUpBeforeClass( $factory ) {
63
		static::$domain       = ( new Status() )->get_site_suffix();
64
		static::$user_id      = $factory->user->create( array( 'role' => 'administrator' ) );
0 ignored issues
show
Bug introduced by
Since $user_id is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $user_id to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
65
		static::$menu_data    = get_menu_fixture();
66
		static::$submenu_data = get_submenu_fixture();
67
	}
68
69
	/**
70
	 * Set up data.
71
	 */
72 View Code Duplication
	public function setUp() {
73
		parent::setUp();
74
		global $menu, $submenu;
75
76
		// Initialize in setUp so it registers hooks for every test.
77
		static::$admin_menu = Admin_Menu::get_instance();
78
79
		$menu    = static::$menu_data;
80
		$submenu = static::$submenu_data;
81
82
		wp_set_current_user( static::$user_id );
0 ignored issues
show
Bug introduced by
Since $user_id is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $user_id to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
83
	}
84
85
	/**
86
	 * Test_Admin_Menu.
87
	 *
88
	 * @covers ::reregister_menu_items
89
	 */
90
	public function test_admin_menu_output() {
91
		global $menu, $submenu;
92
93
		static::$admin_menu->reregister_menu_items();
94
95
		$this->assertSame(
96
			array_keys( $menu ),
97
			array( 2, '3.86682', 4, 5, 10, 15, 20, 25, 30, 50, 51, 59, 60, 61, 65, 70, 75, 80 ),
98
			'Admin menu should not have unexpected top menu items.'
99
		);
100
101
		$this->assertEquals( static::$submenu_data[''], $submenu[''], 'Submenu items without parent should stay the same.' );
102
	}
103
104
	/**
105
	 * Shim wpcomsh fallback site icon.
106
	 *
107
	 * @return string
108
	 */
109
	public function wpcomsh_site_icon_url() {
110
		return 'https://s0.wp.com/i/webclip.png';
111
	}
112
113
	/**
114
	 * Custom site icon.
115
	 *
116
	 * @return string
117
	 */
118
	public function custom_site_icon_url() {
119
		return 'https://s0.wp.com/i/jetpack.png';
120
	}
121
122
	/**
123
	 * Tests add_my_home_menu
124
	 *
125
	 * @covers ::add_my_home_menu
126
	 */
127
	public function test_add_my_home_menu() {
128
		global $menu, $submenu;
129
130
		static::$admin_menu->add_my_home_menu();
131
132
		// Has My Home submenu item when there are other submenu items.
133
		$this->assertSame( 'https://wordpress.com/home/' . static::$domain, array_shift( $submenu['index.php'] )[2] );
134
135
		// Reset data.
136
		$menu    = static::$menu_data;
137
		$submenu = static::$submenu_data;
138
139
		// Has no ny Home submenu when there are no other submenus.
140
		$submenu['index.php'] = array(
141
			0 => array( 'Home', 'read', 'index.php' ),
142
		);
143
144
		static::$admin_menu->add_my_home_menu();
145
146
		$this->assertSame( 'https://wordpress.com/home/' . static::$domain, $menu[2][2] );
147
		$this->assertSame( Base_Admin_Menu::HIDE_CSS_CLASS, $submenu['index.php'][0][4] );
148
	}
149
150
	/**
151
	 * Tests add_upsell_nudge
152
	 *
153
	 * @covers ::add_upsell_nudge
154
	 */
155
	public function test_add_upsell_nudge() {
156
		global $menu;
157
		$nudge = array(
158
			'content' => 'Free domain with an <a href="somehref">annual plan</a>',
159
			'cta'     => '<b>Upgrade</b>',
160
			'link'    => '/plans/example.com?addDomainFlow=true',
161
		);
162
		static::$admin_menu->add_upsell_nudge( $nudge );
0 ignored issues
show
Documentation introduced by
$nudge is of type array<string,string,{"co...ring","link":"string"}>, but the function expects a object.

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...
163
164
		$markup = '
165
<div class="upsell_banner">
166
	<div class="banner__info">
167
		<div class="banner__title">Free domain with an annual plan</div>
168
	</div>
169
	<div class="banner__action">
170
		<button type="button" class="button">Upgrade</button>
171
	</div>
172
</div>';
173
		$link   = 'https://wordpress.com/plans/example.com?addDomainFlow=true';
174
175
		$this->assertSame( $markup, $menu[1][0] );
176
		$this->assertSame( $link, $menu[1][2] );
177
	}
178
179
	/**
180
	 * Tests add_stats_menu
181
	 *
182
	 * @covers ::add_stats_menu
183
	 */
184
	public function test_add_stats_menu() {
185
		global $menu;
186
187
		static::$admin_menu->add_stats_menu();
188
189
		$this->assertSame( 'https://wordpress.com/stats/day/' . static::$domain, $menu['3.86682'][2] );
190
	}
191
192
	/**
193
	 * Tests add_upgrades_menu
194
	 *
195
	 * @covers ::add_upgrades_menu
196
	 */
197 View Code Duplication
	public function test_add_upgrades_menu() {
198
		global $submenu;
199
200
		static::$admin_menu->add_upgrades_menu( 'Test Plan' );
201
202
		$this->assertSame( 'Upgrades<span class="inline-text" style="display:none">Test Plan</span>', $submenu['paid-upgrades.php'][0][0] );
203
		$this->assertSame( 'https://wordpress.com/plans/my-plan/' . static::$domain, $submenu['paid-upgrades.php'][1][2] );
204
		$this->assertSame( 'https://wordpress.com/purchases/subscriptions/' . static::$domain, $submenu['paid-upgrades.php'][2][2] );
205
	}
206
207
	/**
208
	 * Tests add_posts_menu
209
	 *
210
	 * @covers ::add_posts_menu
211
	 */
212 View Code Duplication
	public function test_add_posts_menu() {
213
		global $submenu;
214
215
		static::$admin_menu->add_posts_menu();
216
217
		$this->assertSame( 'https://wordpress.com/posts/' . static::$domain, $submenu['edit.php'][0][2] );
218
		$this->assertSame( 'https://wordpress.com/post/' . static::$domain, $submenu['edit.php'][1][2] );
219
	}
220
221
	/**
222
	 * Tests add_media_menu
223
	 *
224
	 * @covers ::add_media_menu
225
	 */
226 View Code Duplication
	public function test_add_media_menu() {
227
		global $menu, $submenu;
228
229
		static::$admin_menu->add_media_menu();
230
231
		$this->assertSame( 'https://wordpress.com/media/' . static::$domain, $menu[10][2] );
232
		$this->assertFalse( static::$admin_menu->has_visible_items( $submenu['upload.php'] ) );
233
	}
234
235
	/**
236
	 * Tests add_page_menu
237
	 *
238
	 * @covers ::add_page_menu
239
	 */
240 View Code Duplication
	public function test_add_page_menu() {
241
		global $submenu;
242
243
		static::$admin_menu->add_page_menu();
244
245
		$this->assertSame( 'https://wordpress.com/pages/' . static::$domain, $submenu['edit.php?post_type=page'][0][2] );
246
		$this->assertSame( 'https://wordpress.com/page/' . static::$domain, $submenu['edit.php?post_type=page'][1][2] );
247
	}
248
249
	/**
250
	 * Tests add_custom_post_type_menu
251
	 *
252
	 * @covers ::add_custom_post_type_menu
253
	 */
254
	public function test_add_custom_post_type_menu() {
255
		global $menu, $submenu;
256
257
		// Don't show post types that don't want to be shown.
258
		get_post_type_object( 'revision' );
259
		static::$admin_menu->add_custom_post_type_menu( 'revision' );
260
261
		$last_item = array_pop( $menu );
262
		$this->assertNotSame( 'https://wordpress.com/types/revision/' . static::$domain, $last_item[2] );
263
264
		register_post_type(
265
			'custom_test_type',
266
			array(
267
				'label'         => 'Custom Test Types',
268
				'show_ui'       => true,
269
				'menu_position' => 2020,
270
			)
271
		);
272
273
		static::$admin_menu->add_custom_post_type_menu( 'custom_test_type' );
274
275
		// Clean up.
276
		unregister_post_type( 'custom_test_type' );
277
278
		$this->assertSame( 'https://wordpress.com/types/custom_test_type/' . static::$domain, array_shift( $submenu['edit.php?post_type=custom_test_type'] )[2] );
279
		$this->assertSame( 'https://wordpress.com/edit/custom_test_type/' . static::$domain, array_shift( $submenu['edit.php?post_type=custom_test_type'] )[2] );
280
	}
281
282
	/**
283
	 * Tests add_comments_menu
284
	 *
285
	 * @covers ::add_comments_menu
286
	 */
287 View Code Duplication
	public function test_add_comments_menu() {
288
		global $menu, $submenu;
289
290
		static::$admin_menu->add_comments_menu();
291
292
		$this->assertSame( 'https://wordpress.com/comments/all/' . static::$domain, $menu[25][2] );
293
		$this->assertFalse( self::$admin_menu->has_visible_items( $submenu['edit-comments.php'] ) );
294
	}
295
296
	/**
297
	 * Tests add_appearance_menu
298
	 *
299
	 * @covers ::add_appearance_menu
300
	 */
301
	public function test_add_appearance_menu() {
302
		global $submenu;
303
304
		static::$admin_menu->add_appearance_menu();
305
306
		$this->assertSame( 'https://wordpress.com/themes/' . static::$domain, array_shift( $submenu['themes.php'] )[2] );
307
		$this->assertSame( 'https://wordpress.com/customize/' . static::$domain, array_shift( $submenu['themes.php'] )[2] );
308
		$this->assertSame( 'https://wordpress.com/customize/' . static::$domain . '?autofocus%5Bpanel%5D=nav_menus', array_shift( $submenu['themes.php'] )[2] );
309
		$this->assertSame( 'https://wordpress.com/customize/' . static::$domain . '?autofocus%5Bpanel%5D=widgets', array_shift( $submenu['themes.php'] )[2] );
310
	}
311
312
	/**
313
	 * Tests add_plugins_menu
314
	 *
315
	 * @covers ::add_plugins_menu
316
	 */
317
	public function test_add_plugins_menu() {
318
		global $menu, $submenu;
319
320
		static::$admin_menu->add_plugins_menu();
321
322
		$this->assertSame( 'https://wordpress.com/plugins/' . static::$domain, $menu[65][2] );
323
		$this->assertFalse( self::$admin_menu->has_visible_items( $submenu['plugins.php'] ) );
324
325
		// Reset.
326
		$menu    = static::$menu_data;
327
		$submenu = static::$submenu_data;
328
329
		// Check submenu are kept when using WP Admin links.
330
		static::$admin_menu->add_plugins_menu( true );
331
		$this->assertNotEmpty( $submenu['plugins.php'] );
332
	}
333
334
	/**
335
	 * Tests add_users_menu
336
	 *
337
	 * @covers ::add_users_menu
338
	 */
339
	public function test_add_users_menu() {
340
		global $menu, $submenu;
341
342
		// Current user can't list users.
343
		wp_set_current_user( $this->factory->user->create( array( 'role' => 'editor' ) ) );
344
		$menu    = array(
345
			70 => array(
346
				'Profile',
347
				'read',
348
				'profile.php',
349
				'',
350
				'menu-top menu-icon-users',
351
				'menu-users',
352
				'dashicons-admin-users',
353
			),
354
		);
355
		$submenu = array(
356
			'profile.php' => array(
357
				0 => array( 'Profile', 'read', 'profile.php' ),
358
			),
359
		);
360
361
		static::$admin_menu->add_users_menu();
362
363
		$this->assertSame( 'https://wordpress.com/me', $submenu['profile.php'][0][2] );
364
		$this->assertSame( 'https://wordpress.com/me/account', $submenu['profile.php'][2][2] );
365
366
		// Reset.
367
		wp_set_current_user( static::$user_id );
0 ignored issues
show
Bug introduced by
Since $user_id is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $user_id to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
368
		$menu    = static::$menu_data;
369
		$submenu = static::$submenu_data;
370
371
		// On multisite the administrator is not allowed to create users.
372
		grant_super_admin( self::$user_id );
373
		static::$admin_menu->add_users_menu();
374
375
		$this->assertSame( 'https://wordpress.com/people/team/' . static::$domain, $submenu['users.php'][0][2] );
376
		$this->assertSame( 'https://wordpress.com/people/new/' . static::$domain, $submenu['users.php'][1][2] );
377
		$this->assertSame( 'https://wordpress.com/me', $submenu['users.php'][2][2] );
378
		$this->assertSame( 'https://wordpress.com/me/account', $submenu['users.php'][6][2] );
379
	}
380
381
	/**
382
	 * Tests add_tools_menu
383
	 *
384
	 * @covers ::add_tools_menu
385
	 */
386
	public function test_add_tools_menu() {
387
		global $submenu;
388
389
		static::$admin_menu->add_tools_menu();
390
391
		$this->assertSame( 'https://wordpress.com/marketing/tools/' . static::$domain, $submenu['tools.php'][0][2] );
392
		$this->assertSame( 'https://wordpress.com/earn/' . static::$domain, $submenu['tools.php'][1][2] );
393
		$this->assertSame( 'https://wordpress.com/import/' . static::$domain, $submenu['tools.php'][3][2] );
394
		$this->assertSame( 'https://wordpress.com/export/' . static::$domain, $submenu['tools.php'][4][2] );
395
	}
396
397
	/**
398
	 * Tests add_options_menu
399
	 *
400
	 * @covers ::add_options_menu
401
	 */
402 View Code Duplication
	public function test_add_options_menu() {
403
		global $submenu;
404
405
		static::$admin_menu->add_options_menu();
406
407
		$this->assertSame( 'https://wordpress.com/settings/general/' . static::$domain, array_shift( $submenu['options-general.php'] )[2] );
408
		$this->assertSame( 'options-general.php', $submenu['options-general.php'][1][2] );
409
	}
410
411
	/**
412
	 * Tests add_jetpack_menu
413
	 * §
414
	 *
415
	 * @covers ::add_jetpack_menu
416
	 */
417 View Code Duplication
	public function test_add_jetpack_menu() {
418
		global $submenu;
419
420
		static::$admin_menu->add_jetpack_menu();
421
422
		$this->assertSame( 'https://wordpress.com/activity-log/' . static::$domain, $submenu['jetpack'][3][2] );
423
		$this->assertSame( 'https://wordpress.com/backup/' . static::$domain, $submenu['jetpack'][4][2] );
424
		$this->assertSame( 'https://wordpress.com/jetpack-search/' . static::$domain, $submenu['jetpack'][5][2] );
425
	}
426
427
	/**
428
	 * Tests add_gutenberg_menus
429
	 *
430
	 * @covers ::add_gutenberg_menus
431
	 */
432
	public function test_add_gutenberg_menus() {
433
		global $menu;
434
		static::$admin_menu->add_gutenberg_menus( false );
435
436
		// FSE is no longer where it was put by default.
437
		$this->assertArrayNotHasKey( 100, $menu );
438
		$this->assertArrayHasKey( 61, $menu );
439
440
		$fse_link = 'https://wordpress.com/site-editor/' . static::$domain;
441
		$fse_menu = array(
442
			'Site Editor',
443
			'edit_theme_options',
444
			$fse_link,
445
			'Site Editor',
446
			'menu-top toplevel_page_' . $fse_link,
447
			'toplevel_page_' . $fse_link,
448
			'dashicons-layout',
449
		);
450
		$this->assertSame( $menu[61], $fse_menu );
451
	}
452
453
	/**
454
	 * Check if the hidden menus are at the end of the submenu.
455
	 */
456
	public function test_if_the_hidden_menus_are_at_the_end_of_submenu() {
457
		global $submenu;
458
459
		$submenu = array(
460
			'options-general.php' => array(
461
				array( '', 'read', 'test-slug', '', '' ),
462
				array( '', 'read', 'test-slug', '', Base_Admin_Menu::HIDE_CSS_CLASS ),
463
				array( '', 'read', 'test-slug', '', '' ),
464
				array( '', 'read', 'test-slug', '' ),
465
				array( '', 'read', 'test-slug', '', Base_Admin_Menu::HIDE_CSS_CLASS ),
466
				array( '', 'read', 'test-slug', '', '' ),
467
			),
468
		);
469
470
		static::$admin_menu->sort_hidden_submenus();
471
		$this->assertNotEquals( Base_Admin_Menu::HIDE_CSS_CLASS, $submenu['options-general.php'][0][4] );
472
		$this->assertNotEquals( Base_Admin_Menu::HIDE_CSS_CLASS, $submenu['options-general.php'][2][4] );
473
474
		$this->assertEquals( $submenu['options-general.php'][3], array( '', 'read', 'test-slug', '' ) );
475
476
		$this->assertNotEquals( Base_Admin_Menu::HIDE_CSS_CLASS, $submenu['options-general.php'][5][4] );
477
478
		$this->assertEquals( Base_Admin_Menu::HIDE_CSS_CLASS, $submenu['options-general.php'][6][4] );
479
		$this->assertEquals( Base_Admin_Menu::HIDE_CSS_CLASS, $submenu['options-general.php'][7][4] );
480
481
		$submenu = self::$submenu_data;
482
	}
483
484
	/**
485
	 * Check if the parent menu is hidden when the submenus are hidden.
486
	 *
487
	 * @dataProvider hide_menu_based_on_submenu_provider
488
	 *
489
	 * @param array $menu_items The mock menu array.
490
	 * @param array $submenu_items The mock submenu array.
491
	 * @param array $expected The expected result.
492
	 */
493
	public function test_if_it_hides_menu_based_on_submenu( $menu_items, $submenu_items, $expected ) {
494
		global $submenu, $menu;
495
496
		$menu    = $menu_items;
497
		$submenu = $submenu_items;
498
499
		static::$admin_menu->hide_parent_of_hidden_submenus();
500
501
		$this->assertEquals( $expected, $menu[0] );
502
503
		// reset the menu arrays.
504
		$menu    = self::$menu_data;
505
		$submenu = self::$submenu_data;
506
	}
507
508
	/**
509
	 * The data provider for test_if_it_hides_menu_based_on_submenu.
510
	 *
511
	 * @return array
512
	 */
513
	public function hide_menu_based_on_submenu_provider() {
514
		return array(
515
			array(
516
				array(
517
					array( '', 'non-existing-capability', 'test-slug', '', '' ),
518
				),
519
				array(
520
					'test-slug' => array(
521
						array(
522
							'test',
523
							'',
524
							'',
525
							'',
526
							Base_Admin_Menu::HIDE_CSS_CLASS,
527
						),
528
					),
529
				),
530
				array( '', 'non-existing-capability', 'test-slug', '', Base_Admin_Menu::HIDE_CSS_CLASS ),
531
			),
532
			array(
533
				array(
534
					array( '', 'read', 'test-slug', '', '' ),
535
				),
536
				array(
537
					'test-slug' => array(
538
						array(
539
							'test',
540
							'',
541
							'test-slug',
542
							'',
543
							Base_Admin_Menu::HIDE_CSS_CLASS,
544
						),
545
					),
546
				),
547
				array( '', 'read', 'test-slug', '', Base_Admin_Menu::HIDE_CSS_CLASS ),
548
			),
549
		);
550
	}
551
}
552