Completed
Push — update/conversation-remove-par... ( 498b22...5ced53 )
by
unknown
18:38 queued 07:08
created

Test_WPcom_Admin_Menu::test_add_tools_menu()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15

Duplication

Lines 15
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 15
loc 15
rs 9.7666
c 0
b 0
f 0
1
<?php
2
/**
3
 * Tests for WPcom_Admin_Menu class.
4
 *
5
 * @package automattic/jetpack
6
 */
7
8
use Automattic\Jetpack\Dashboard_Customizations\WPcom_Admin_Menu;
9
use Automattic\Jetpack\Status;
10
11
require_jetpack_file( 'modules/masterbar/admin-menu/class-wpcom-admin-menu.php' );
12
require_jetpack_file( 'tests/php/modules/masterbar/data/admin-menu.php' );
13
14
/**
15
 * Class Test_WPcom_Admin_Menu.
16
 *
17
 * @coversDefaultClass Automattic\Jetpack\Dashboard_Customizations\WPcom_Admin_Menu
18
 */
19
class Test_WPcom_Admin_Menu extends WP_UnitTestCase {
20
21
	/**
22
	 * Menu data fixture.
23
	 *
24
	 * @var array
25
	 */
26
	public static $menu_data;
27
28
	/**
29
	 * Submenu data fixture.
30
	 *
31
	 * @var array
32
	 */
33
	public static $submenu_data;
34
35
	/**
36
	 * Test domain.
37
	 *
38
	 * @var string
39
	 */
40
	public static $domain;
41
42
	/**
43
	 * Whether this testsuite is run on WP.com.
44
	 *
45
	 * @var bool
46
	 */
47
	public static $is_wpcom;
48
49
	/**
50
	 * Admin menu instance.
51
	 *
52
	 * @var WPcom_Admin_Menu
53
	 */
54
	public static $admin_menu;
55
56
	/**
57
	 * Mock user ID.
58
	 *
59
	 * @var int
60
	 */
61
	private static $user_id = 0;
62
63
	/**
64
	 * Create shared fixtures.
65
	 *
66
	 * @param WP_UnitTest_Factory $factory Fixture factory.
67
	 */
68 View Code Duplication
	public static function wpSetUpBeforeClass( $factory ) {
69
		static::$domain       = ( new Status() )->get_site_suffix();
70
		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...
71
		static::$menu_data    = get_menu_fixture();
72
		static::$submenu_data = get_submenu_fixture();
73
	}
74
75
	/**
76
	 * Set up data.
77
	 */
78 View Code Duplication
	public function setUp() {
79
		parent::setUp();
80
		global $menu, $submenu;
81
82
		// Initialize in setUp so it registers hooks for every test.
83
		static::$admin_menu = WPcom_Admin_Menu::get_instance();
84
85
		$menu    = static::$menu_data;
86
		$submenu = static::$submenu_data;
87
88
		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...
89
	}
90
91
	/**
92
	 * Test get_instance.
93
	 *
94
	 * @covers ::get_instance
95
	 * @covers ::__construct
96
	 */
97 View Code Duplication
	public function test_get_instance() {
98
		$instance = WPcom_Admin_Menu::get_instance();
99
100
		$this->assertInstanceOf( WPcom_Admin_Menu::class, $instance );
101
		$this->assertSame( $instance, static::$admin_menu );
102
103
		$this->assertSame( 99999, has_action( 'admin_menu', array( $instance, 'reregister_menu_items' ) ) );
104
		$this->assertSame( 10, has_action( 'admin_enqueue_scripts', array( $instance, 'enqueue_scripts' ) ) );
105
	}
106
107
	/**
108
	 * Tests add_browse_sites_link.
109
	 *
110
	 * @covers ::add_browse_sites_link
111
	 */
112
	public function test_add_browse_sites_link() {
113
		if ( ! function_exists( 'add_user_to_blog' ) ) {
114
			$this->markTestSkipped( 'Only used on multisite' );
115
		}
116
		global $menu;
117
118
		// No output when user has just one site.
119
		static::$admin_menu->add_browse_sites_link();
120
		$this->assertArrayNotHasKey( 0, $menu );
121
122
		// Give user a second site.
123
		$blog_id = $this->factory->blog->create();
124
		add_user_to_blog( $blog_id, get_current_user_id(), 'editor' );
125
126
		static::$admin_menu->add_browse_sites_link();
127
128
		$browse_sites_menu_item = array(
129
			'Browse sites',
130
			'read',
131
			'https://wordpress.com/home',
132
			'site-switcher',
133
			'menu-top toplevel_page_https://wordpress.com/home',
134
			'toplevel_page_https://wordpress.com/home',
135
			'dashicons-arrow-left-alt2',
136
		);
137
		$this->assertSame( $menu[0], $browse_sites_menu_item );
138
139
		remove_user_from_blog( get_current_user_id(), $blog_id );
140
	}
141
142
	/**
143
	 * Tests add_new_site_link.
144
	 *
145
	 * @covers ::add_new_site_link
146
	 */
147
	public function test_add_new_site_link() {
148
		global $menu;
149
150
		static::$admin_menu->add_new_site_link();
151
152
		$new_site_menu_item = array(
153
			'Add new site',
154
			'read',
155
			'https://wordpress.com/start?ref=calypso-sidebar',
156
			'Add new site',
157
			'menu-top toplevel_page_https://wordpress.com/start?ref=calypso-sidebar',
158
			'toplevel_page_https://wordpress.com/start?ref=calypso-sidebar',
159
			'dashicons-plus-alt',
160
		);
161
		$this->assertSame( $menu[1002], $new_site_menu_item ); // 1001 is the separator position, 1002 is the link position
162
	}
163
164
	/**
165
	 * Tests add_site_card_menu
166
	 *
167
	 * @covers ::add_site_card_menu
168
	 */
169
	public function test_add_site_card_menu() {
170
		global $menu;
171
172
		if ( ! static::$is_wpcom ) {
173
			$this->markTestSkipped( 'Only used on WP.com.' );
174
		}
175
176
		static::$admin_menu->add_site_card_menu();
177
178
		$home_url            = home_url();
179
		$site_card_menu_item = array(
180
			// phpcs:ignore Squiz.Strings.DoubleQuoteUsage.NotRequired
181
			'
182
<div class="site__info">
183
	<div class="site__title">' . get_option( 'blogname' ) . '</div>
184
	<div class="site__domain">' . static::$domain . "</div>\n\t</div>",
185
			'read',
186
			$home_url,
187
			'site-card',
188
			'menu-top toplevel_page_' . $home_url,
189
			'toplevel_page_' . $home_url,
190
			'data:image/svg+xml,%3Csvg%20class%3D%22gridicon%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ctitle%3EGlobe%3C%2Ftitle%3E%3Crect%20fill-opacity%3D%220%22%20x%3D%220%22%20width%3D%2224%22%20height%3D%2224%22%2F%3E%3Cg%3E%3Cpath%20fill%3D%22%23fff%22%20d%3D%22M12%202C6.477%202%202%206.477%202%2012s4.477%2010%2010%2010%2010-4.477%2010-10S17.523%202%2012%202zm0%2018l2-2%201-1v-2h-2v-1l-1-1H9v3l2%202v1.93c-3.94-.494-7-3.858-7-7.93l1%201h2v-2h2l3-3V6h-2L9%205v-.41C9.927%204.21%2010.94%204%2012%204s2.073.212%203%20.59V6l-1%201v2l1%201%203.13-3.13c.752.897%201.304%201.964%201.606%203.13H18l-2%202v2l1%201h2l.286.286C18.03%2018.06%2015.24%2020%2012%2020z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E',
191
		);
192
193
		$this->assertEquals( $menu[1], $site_card_menu_item );
194
	}
195
196
	/**
197
	 * Tests set_site_card_menu_class
198
	 *
199
	 * @covers ::set_site_card_menu_class
200
	 */
201
	public function test_set_site_card_menu_class() {
202
		global $menu;
203
204
		if ( ! static::$is_wpcom ) {
205
			$this->markTestSkipped( 'Only used on WP.com.' );
206
		}
207
208
		static::$admin_menu->add_site_card_menu();
209
210
		$menu = static::$admin_menu->set_site_card_menu_class( $menu );
211
		$this->assertNotContains( 'has-site-icon', $menu[1][4] );
212
213
		// Atomic fallback site icon counts as no site icon.
214
		add_filter( 'get_site_icon_url', array( $this, 'wpcomsh_site_icon_url' ) );
215
		$menu = static::$admin_menu->set_site_card_menu_class( $menu );
216
		remove_filter( 'get_site_icon_url', array( $this, 'wpcomsh_site_icon_url' ) );
217
		$this->assertNotContains( 'has-site-icon', $menu[1][4] );
218
219
		// Custom site icon triggers CSS class.
220
		add_filter( 'get_site_icon_url', array( $this, 'custom_site_icon_url' ) );
221
		$menu = static::$admin_menu->set_site_card_menu_class( $menu );
222
		remove_filter( 'get_site_icon_url', array( $this, 'custom_site_icon_url' ) );
223
		$this->assertContains( 'has-site-icon', $menu[1][4] );
224
	}
225
226
	/**
227
	 * Shim wpcomsh fallback site icon.
228
	 *
229
	 * @return string
230
	 */
231
	public function wpcomsh_site_icon_url() {
232
		return 'https://s0.wp.com/i/webclip.png';
233
	}
234
235
	/**
236
	 * Custom site icon.
237
	 *
238
	 * @return string
239
	 */
240
	public function custom_site_icon_url() {
241
		return 'https://s0.wp.com/i/jetpack.png';
242
	}
243
244
	/**
245
	 * Tests add_upgrades_menu
246
	 *
247
	 * @covers ::add_upgrades_menu
248
	 */
249
	public function test_add_wpcom_upgrades_menu() {
250
		global $submenu;
251
252
		static::$admin_menu->add_upgrades_menu();
253
254
		$domains_submenu_item = array(
255
			'Domains',
256
			'manage_options',
257
			'https://wordpress.com/domains/manage/' . static::$domain,
258
			'Domains',
259
		);
260
		$this->assertContains( $domains_submenu_item, $submenu[ 'https://wordpress.com/plans/' . static::$domain ] );
261
	}
262
263
	/**
264
	 * Tests add_users_menu
265
	 *
266
	 * @covers ::add_users_menu
267
	 */
268
	public function test_add_users_menu() {
269
		global $menu, $submenu;
270
271
		// Current user can't list users.
272
		wp_set_current_user( $this->factory->user->create( array( 'role' => 'editor' ) ) );
273
		$menu = array();
274
275
		static::$admin_menu->add_users_menu( false );
276
277
		$profile_menu_item = array(
278
			'My Profile',
279
			'read',
280
			'https://wordpress.com/me',
281
			'My Profile',
282
			'menu-top toplevel_page_https://wordpress.com/me',
283
			'toplevel_page_https://wordpress.com/me',
284
			'dashicons-admin-users',
285
		);
286
		$this->assertSame( $menu[70], $profile_menu_item );
287
288
		$account_submenu_item = array(
289
			'Account Settings',
290
			'read',
291
			'https://wordpress.com/me/account',
292
			'Account Settings',
293
		);
294
		$this->assertContains( $account_submenu_item, $submenu['https://wordpress.com/me'] );
295
		$this->assertArrayNotHasKey( 'profile.php', $submenu );
296
297
		// Reset.
298
		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...
299
		$menu = static::$menu_data;
300
301
		static::$admin_menu->add_users_menu( false );
302
303
		$slug = 'https://wordpress.com/people/team/' . static::$domain;
304
305
		$users_menu_item = array(
306
			'Users',
307
			'list_users',
308
			$slug,
309
			'Users',
310
			'menu-top toplevel_page_' . $slug,
311
			'toplevel_page_' . $slug,
312
			'dashicons-admin-users',
313
		);
314
		$this->assertSame( $menu[70], $users_menu_item );
315
		$this->assertEmpty( $submenu['users.php'] );
316
317
		$all_people_submenu_item = array(
318
			'All People',
319
			'list_users',
320
			$slug,
321
			'All People',
322
		);
323
		$this->assertContains( $all_people_submenu_item, $submenu[ $slug ] );
324
325
		$add_new_submenu_item = array(
326
			'Add New',
327
			'promote_users',
328
			'https://wordpress.com/people/new/' . static::$domain,
329
			'Add New',
330
		);
331
		$this->assertContains( $add_new_submenu_item, $submenu[ $slug ] );
332
333
		$profile_submenu_item = array(
334
			'My Profile',
335
			'read',
336
			'https://wordpress.com/me',
337
			'My Profile',
338
		);
339
		$this->assertContains( $profile_submenu_item, $submenu[ $slug ] );
340
341
		$account_submenu_item = array(
342
			'Account Settings',
343
			'read',
344
			'https://wordpress.com/me/account',
345
			'Account Settings',
346
		);
347
		$this->assertContains( $account_submenu_item, $submenu[ $slug ] );
348
	}
349
350
	/**
351
	 * Tests add_tools_menu
352
	 *
353
	 * @covers ::add_tools_menu
354
	 */
355 View Code Duplication
	public function test_add_tools_menu() {
356
		global $submenu;
357
358
		$slug = 'https://wordpress.com/marketing/tools/' . static::$domain;
359
		static::$admin_menu->add_tools_menu( false, true );
360
361
		// Check Export menu item always links to Calypso.
362
		$export_submenu_item = array(
363
			'Export',
364
			'export',
365
			'https://wordpress.com/export/' . static::$domain,
366
			'Export',
367
		);
368
		$this->assertContains( $export_submenu_item, $submenu[ $slug ] );
369
	}
370
371
	/**
372
	 * Tests add_options_menu
373
	 *
374
	 * @covers ::add_options_menu
375
	 */
376
	public function test_add_options_menu() {
377
		global $submenu;
378
379
		$slug = 'https://wordpress.com/settings/general/' . static::$domain;
380
		static::$admin_menu->add_options_menu( false );
381
382
		$this->assertContains( 'Hosting Configuration', $submenu[ $slug ][6] );
383
384
		$sharing_submenu_item = array(
385
			'Sharing',
386
			'publish_posts',
387
			'https://wordpress.com/marketing/sharing-buttons/' . static::$domain,
388
			'Sharing Settings',
389
		);
390
		$this->assertContains( $sharing_submenu_item, $submenu[ $slug ] );
391
	}
392
393
	/**
394
	 * Tests add_appearance_menu
395
	 *
396
	 * @covers ::add_appearance_menu
397
	 */
398 View Code Duplication
	public function test_add_appearance_menu() {
399
		global $submenu;
400
401
		$slug = 'https://wordpress.com/themes/' . static::$domain;
402
		static::$admin_menu->add_appearance_menu( false );
403
404
		// Check Customize menu always links to WP.com.
405
		$customize_submenu_item = array(
406
			'Customize',
407
			'customize',
408
			'https://wordpress.com/customize/' . static::$domain,
409
			'Customize',
410
		);
411
		$this->assertContains( $customize_submenu_item, $submenu[ $slug ] );
412
	}
413
}
414