Completed
Push — add/private-site-mode ( 81d3a8...c37ff2 )
by
unknown
25:46 queued 11:45
created

WP_Test_Jetpack::wpSetupBeforeClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
4
use Automattic\Jetpack\Constants;
5
use Automattic\Jetpack\Assets;
6
use Automattic\Jetpack\Partner;
7
use Automattic\Jetpack\Status;
8
9
// Extend with a public constructor so that can be mocked in tests
10
class MockJetpack extends Jetpack {
11
12
	/**
13
	 * Holds the singleton instance of this class
14
	 *
15
	 * @var MockJetpack
16
	 */
17
	public static $instance = false;
18
19
	/**
20
	 * We are redefining this to overcome the lack of late static binding in the parent Jetpack class.
21
	 *
22
	 * @static
23
	 */
24
	public static function init() {
25
		if ( ! self::$instance ) {
26
			self::$instance = new self();
27
		}
28
29
		return self::$instance;
30
	}
31
32
	public function __construct() {
33
		$this->connection_manager = new Connection_Manager();
34
	}
35
}
36
37
class MockJetpack_XMLRPC_Server extends Jetpack_XMLRPC_Server {
38
	private $mockLoginUser = false;
39
40
	public function __construct( $user ) {
41
		$this->mockLoginUser = $user;
42
	}
43
44
	public function login() {
45
		return $this->mockLoginUser;
46
	}
47
}
48
49
class WP_Test_Jetpack extends WP_UnitTestCase {
50
	static $admin_id = 0;
51
52
	static $activated_modules = array();
53
	static $deactivated_modules = array();
54
55
	public static function wpSetupBeforeClass() {
56
		self::$admin_id = self::factory()->user->create( array(
57
			'role' => 'administrator',
58
		) );
59
	}
60
61
	public function tearDown() {
62
		parent::tearDown();
63
		Constants::clear_constants();
64
	}
65
66
	/**
67
	 * Make sure that MockJetpack creates separate instances of `Jetpack` and `Automattic\Jetpack\Connection\Manager`.
68
	 */
69
	public function test_static_binding() {
70
		$this->assertNotEquals( spl_object_hash( MockJetpack::init() ), spl_object_hash( Jetpack::init() ) );
71
		$this->assertNotEquals( spl_object_hash( MockJetpack::connection() ), spl_object_hash( Jetpack::connection() ) );
72
	}
73
74
	/**
75
	 * @author blobaugh
76
	 * @covers Jetpack::init
77
	 * @since 2.3.3
78
	 */
79
	public function test_init() {
80
		$this->assertInstanceOf( 'Jetpack', Jetpack::init() );
81
	}
82
83
	/**
84
	 * @author enkrates
85
	 * @covers Jetpack::sort_modules
86
	 * @since 3.2
87
	 */
88
	public function test_sort_modules_with_equal_sort_values() {
89
90
		$first_file  = array( 'sort' => 5 );
91
		$second_file = array( 'sort' => 5 );
92
93
		$sort_value = Jetpack::sort_modules( $first_file, $second_file );
94
95
		$this->assertEquals( 0, $sort_value );
96
	}
97
98
	/**
99
	 * @author enkrates
100
	 * @covers Jetpack::sort_modules
101
	 * @since 3.2
102
	 */
103
	public function test_sort_modules_with_different_sort_values() {
104
105
		$first_file  = array( 'sort' => 10 );
106
		$second_file = array( 'sort' => 5 );
107
108
		$sort_value = Jetpack::sort_modules( $first_file, $second_file );
109
		$reversed_sort_value = Jetpack::sort_modules( $second_file, $first_file );
110
111
		$this->assertEquals( 1, $sort_value );
112
		$this->assertEquals( -1, $reversed_sort_value );
113
	}
114
115
	/**
116
	 * @author georgestephanis
117
	 * @covers Jetpack::absolutize_css_urls
118
	 */
119
	public function test_absolutize_css_urls_properly_handles_use_cases() {
120
121
		$css = <<<CSS
122
.test-it {
123
	background: url(same-dir.png);
124
	background: url('same-dir.png');
125
	background: url("same-dir.png");
126
	background: url( same-dir.png );
127
	background: url( 'same-dir.png' );
128
	background: url( "same-dir.png" );
129
	background: url(		same-dir.png		);
130
	background: url(		'same-dir.png'	);
131
	background: url(		"same-dir.png"	);
132
	background: url(./same-dir.png);
133
	background: url(down/down-dir.png);
134
	background: url(../up-dir.png);
135
	background: url(../../up-2-dirs.png);
136
	background: url(/at-root.png);
137
	background: url(//other-domain.com/root.png);
138
	background: url(https://other-domain.com/root.png);
139
	background: url(data:image/gif;base64,eh129ehiuehjdhsa==);
140
}
141
CSS;
142
143
		$expected = <<<EXPECTED
144
.test-it {
145
	background: url("http://example.com/dir1/dir2/same-dir.png");
146
	background: url("http://example.com/dir1/dir2/same-dir.png");
147
	background: url("http://example.com/dir1/dir2/same-dir.png");
148
	background: url("http://example.com/dir1/dir2/same-dir.png");
149
	background: url("http://example.com/dir1/dir2/same-dir.png");
150
	background: url("http://example.com/dir1/dir2/same-dir.png");
151
	background: url("http://example.com/dir1/dir2/same-dir.png");
152
	background: url("http://example.com/dir1/dir2/same-dir.png");
153
	background: url("http://example.com/dir1/dir2/same-dir.png");
154
	background: url("http://example.com/dir1/dir2/./same-dir.png");
155
	background: url("http://example.com/dir1/dir2/down/down-dir.png");
156
	background: url("http://example.com/dir1/dir2/../up-dir.png");
157
	background: url("http://example.com/dir1/dir2/../../up-2-dirs.png");
158
	background: url("http://example.com/at-root.png");
159
	background: url(//other-domain.com/root.png);
160
	background: url(https://other-domain.com/root.png);
161
	background: url(data:image/gif;base64,eh129ehiuehjdhsa==);
162
}
163
EXPECTED;
164
165
		$result = Jetpack::absolutize_css_urls( $css, 'http://example.com/dir1/dir2/style.css' );
166
		$this->assertEquals( $expected, $result );
167
168
	}
169
170
	/*
171
	 * @author tonykova
172
	 * @covers Jetpack::implode_frontend_css
173
	 */
174
	public function test_implode_frontend_css_enqueues_bundle_file_handle() {
175
		global $wp_styles;
176
		$wp_styles = new WP_styles();
177
178
		add_filter( 'jetpack_implode_frontend_css', '__return_true' );
179
180
		if ( ! file_exists( plugins_url( 'jetpack-carousel.css', __FILE__ ) ) ) {
181
			$this->markTestSkipped( 'Required CSS file not found.' );
182
		}
183
184
		// Enqueue some script on the $to_dequeue list
185
		$style_handle = 'jetpack-carousel';
186
		wp_enqueue_style( 'jetpack-carousel', plugins_url( 'jetpack-carousel.css', __FILE__ ) );
187
188
		Jetpack::init()->implode_frontend_css( true );
189
190
		$seen_bundle = false;
191
		foreach ( $wp_styles->registered as $handle => $handle_obj ) {
192
			if ( $style_handle === $handle ) {
193
				$expected = ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ? "<!-- `{$style_handle}` is included in the concatenated jetpack.css -->\r\n" : '';
194
				$this->assertEquals( $expected, get_echo( array( $wp_styles, 'do_item' ), array( $handle ) ) );
195
			} elseif ( 'jetpack_css' === $handle ) {
196
				$seen_bundle = true;
197
			}
198
		}
199
200
		$this->assertTrue( $seen_bundle );
201
	}
202
203
	/**
204
	 * @author tonykova
205
	 * @covers Jetpack::implode_frontend_css
206
	 * @since 3.2.0
207
	 */
208
	public function test_implode_frontend_css_does_not_enqueue_bundle_when_disabled_through_filter() {
209
		global $wp_styles;
210
		$wp_styles = new WP_styles();
211
212
		add_filter( 'jetpack_implode_frontend_css', '__return_false' );
213
214
		// Enqueue some script on the $to_dequeue list
215
		$style_handle = 'jetpack-carousel';
0 ignored issues
show
Unused Code introduced by
$style_handle is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
216
		wp_enqueue_style( 'jetpack-carousel', plugins_url( 'jetpack-carousel.css', __FILE__ ) );
217
218
		Jetpack::init()->implode_frontend_css();
219
220
		$seen_orig = false;
221
		foreach ( $wp_styles->registered as $handle => $handle_obj ) {
222
			$this->assertNotEquals( 'jetpack_css', $handle );
223
			if ( 'jetpack-carousel' === $handle ) {
224
				$seen_orig = true;
225
			}
226
		}
227
228
		$this->assertTrue( $seen_orig );
229
	}
230
231 View Code Duplication
	public function test_activating_deactivating_modules_fires_actions() {
232
		self::reset_tracking_of_module_activation();
233
234
		add_action( 'jetpack_activate_module', array( __CLASS__, 'track_activated_modules' ) );
235
		add_action( 'jetpack_deactivate_module', array( __CLASS__, 'track_deactivated_modules' ) );
236
237
		Jetpack::update_active_modules( array( 'stats' ) );
238
		Jetpack::update_active_modules( array( 'stats' ) );
239
		Jetpack::update_active_modules( array( 'json-api' ) );
240
		Jetpack::update_active_modules( array( 'json-api' ) );
241
242
		$this->assertEquals( self::$activated_modules, array( 'stats', 'json-api' ) );
243
		$this->assertEquals(  self::$deactivated_modules, array( 'stats' ) );
244
245
		remove_action( 'jetpack_activate_module', array( __CLASS__, 'track_activated_modules' ) );
246
		remove_action( 'jetpack_deactivate_module', array( __CLASS__, 'track_deactivated_modules' ) );
247
	}
248
249 View Code Duplication
	public function test_activating_deactivating_modules_fires_specific_actions() {
250
		self::reset_tracking_of_module_activation();
251
		add_action( 'jetpack_activate_module_stats', array( __CLASS__, 'track_activated_modules' ) );
252
		add_action( 'jetpack_deactivate_module_stats', array( __CLASS__, 'track_deactivated_modules' ) );
253
254
		Jetpack::update_active_modules( array( 'stats' ) );
255
		Jetpack::update_active_modules( array( 'stats' ) );
256
		Jetpack::update_active_modules( array( 'json-api' ) );
257
		Jetpack::update_active_modules( array( 'json-api' ) );
258
259
		$this->assertEquals( self::$activated_modules, array( 'stats' ) );
260
		$this->assertEquals(  self::$deactivated_modules, array( 'stats' ) );
261
262
		remove_action( 'jetpack_activate_module_stats', array( __CLASS__, 'track_activated_modules' ) );
263
		remove_action( 'jetpack_deactivate_module_stats', array( __CLASS__, 'track_deactivated_modules' ) );
264
	}
265
266
	public function test_active_modules_filter_restores_state() {
267
		self::reset_tracking_of_module_activation();
268
269
		add_action( 'jetpack_activate_module', array( __CLASS__, 'track_activated_modules' ) );
270
		add_action( 'jetpack_deactivate_module', array( __CLASS__, 'track_deactivated_modules' ) );
271
		add_filter( 'jetpack_active_modules', array( __CLASS__, 'e2e_test_filter' ) );
272
273
		Jetpack::update_active_modules( array( 'monitor' ) );
274
		$this->assertEquals( self::$activated_modules, array( 'monitor' ) );
275
		$this->assertEquals(  self::$deactivated_modules, array() );
276
277
		// Simce we override the 'monitor' module, verify it does not appear in get_active_modules().
278
		$active_modules = Jetpack::get_active_modules();
279
		$this->assertEquals(  $active_modules, array() );
280
281
		// Verify that activating a new module does not deactivate 'monitor' module.
282
		Jetpack::update_active_modules( array( 'stats' ) );
283
		$this->assertEquals( self::$activated_modules, array( 'monitor', 'stats') );
284
		$this->assertEquals(  self::$deactivated_modules, array() );
285
286
		remove_filter( 'jetpack_active_modules', array( __CLASS__, 'e2e_test_filter' ) );
287
288
		// With the module override filter removed, verify that monitor module appears in get_active_modules().
289
		$active_modules = Jetpack::get_active_modules();
290
		$this->assertEquals(  $active_modules, array( 'monitor', 'stats' ) );
291
	}
292
293
	 // This filter overrides the 'monitor' module.
294
	public static function e2e_test_filter( $modules ) {
295
		$disabled_modules = array( 'monitor' );
296
297
		foreach ( $disabled_modules as $module_slug ) {
298
			$found = array_search( $module_slug, $modules );
299
			if ( false !== $found ) {
300
				unset( $modules[ $found ] );
301
			}
302
		}
303
304
		return $modules;
305
	}
306
307
	public function test_get_other_linked_admins_one_admin_returns_false() {
308
		delete_transient( 'jetpack_other_linked_admins' );
309
		$other_admins = Jetpack::get_other_linked_admins();
310
		$this->assertFalse( $other_admins );
311
		$this->assertEquals( 0, get_transient( 'jetpack_other_linked_admins' ) );
312
	}
313
314
	public function test_get_other_linked_admins_more_than_one_not_false() {
315
		delete_transient( 'jetpack_other_linked_admins' );
316
		$master_user = $this->factory->user->create( array( 'role' => 'administrator' ) );
317
		$connected_admin = $this->factory->user->create( array( 'role' => 'administrator' ) );
318
319
		Jetpack_Options::update_option( 'master_user', $master_user );
320
		Jetpack_Options::update_option( 'user_tokens', array(
321
			$connected_admin => 'apple.a.' . $connected_admin,
322
			$master_user     => 'kiwi.a.' . $master_user
323
		) );
324
325
		$other_admins = Jetpack::get_other_linked_admins();
326
		$this->assertInternalType( 'int', $other_admins );
327
		$this->assertInternalType( 'int', get_transient( 'jetpack_other_linked_admins' ) );
328
	}
329
330 View Code Duplication
	public function test_promoting_admin_clears_other_linked_admins_transient() {
331
		set_transient( 'jetpack_other_linked_admins', 2, HOUR_IN_SECONDS );
332
		$editor_user = $this->factory->user->create( array( 'role' => 'editor' ) );
333
		wp_update_user( array( 'ID' => $editor_user, 'role' => 'administrator' ) );
334
335
		$this->assertFalse( get_transient( 'jetpack_other_linked_admins' ) );
336
	}
337
338 View Code Duplication
	public function test_demoting_admin_clear_other_linked_admins_transiet() {
339
		set_transient( 'jetpack_other_linked_admins', 2, HOUR_IN_SECONDS );
340
		$admin_user = $this->factory->user->create( array( 'role' => 'administrator' ) );
341
		wp_update_user( array( 'ID' => $admin_user, 'role' => 'editor' ) );
342
343
		$this->assertFalse( get_transient( 'jetpack_other_linked_admins' ) );
344
	}
345
346 View Code Duplication
	public function test_null_old_roles_clears_linked_admins_transient() {
347
		set_transient( 'jetpack_other_linked_admins', 2, HOUR_IN_SECONDS );
348
		$admin_user = $this->factory->user->create( array( 'role' => 'administrator' ) );
349
		wp_update_user( array( 'ID' => $admin_user, 'role' => 'editor' ) );
350
351
		/** This action is documented in wp-includes/class-wp-user.php */
352
		do_action( 'set_user_role', $admin_user, 'contributor' );
353
354
		$this->assertFalse( get_transient( 'jetpack_other_linked_admins' ) );
355
	}
356
357
	function test_changing_non_admin_roles_does_not_clear_other_linked_admins_transient() {
358
		set_transient( 'jetpack_other_linked_admins', 2, HOUR_IN_SECONDS );
359
		$user_id = $this->factory->user->create( array( 'role' => 'subscriber' ) );
360
361
		foreach ( array( 'contributor', 'author', 'editor' ) as $role ) {
362
			wp_update_user( array( 'ID' => $user_id, 'role' => $role) );
363
		}
364
365
		$this->assertEquals( 2, get_transient( 'jetpack_other_linked_admins' ) );
366
	}
367
368
	function test_other_linked_admins_transient_set_to_zero_returns_false() {
369
		set_transient( 'jetpack_other_linked_admins', 0, HOUR_IN_SECONDS );
370
		$this->assertFalse( Jetpack::get_other_linked_admins() );
371
	}
372
373
	function test_idc_optin_default() {
374
		if ( is_multisite() ) {
375
			$this->assertFalse( Jetpack::sync_idc_optin() );
376
		} else {
377
			$this->assertTrue( Jetpack::sync_idc_optin() );
378
		}
379
	}
380
381
	function test_idc_optin_filter_overrides_development_version() {
382
		add_filter( 'jetpack_development_version', '__return_true' );
383
		add_filter( 'jetpack_sync_idc_optin', '__return_false' );
384
		$this->assertFalse( Jetpack::sync_idc_optin() );
385
		remove_filter( 'jetpack_development_version', '__return_true' );
386
		remove_filter( 'jetpack_sync_idc_optin', '__return_false' );
387
	}
388
389
	function test_idc_optin_casts_to_bool() {
390
		add_filter( 'jetpack_sync_idc_optin', array( $this, 'return_string_1' ) );
391
		$this->assertTrue( Jetpack::sync_idc_optin() );
392
		remove_filter( 'jetpack_sync_idc_optin', array( $this, 'return_string_1' ) );
393
	}
394
395
	function test_idc_optin_true_when_constant_true() {
396
		Constants::set_constant( 'JETPACK_SYNC_IDC_OPTIN', true );
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a string.

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...
397
		$this->assertTrue( Jetpack::sync_idc_optin() );
398
	}
399
400
	function test_idc_optin_false_when_constant_false() {
401
		Constants::set_constant( 'JETPACK_SYNC_IDC_OPTIN', false );
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

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...
402
		$this->assertFalse( Jetpack::sync_idc_optin() );
403
	}
404
405
	function test_idc_optin_filter_overrides_constant() {
406
		Constants::set_constant( 'JETPACK_SYNC_IDC_OPTIN', true );
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a string.

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...
407
		add_filter( 'jetpack_sync_idc_optin', '__return_false' );
408
		$this->assertFalse( Jetpack::sync_idc_optin() );
409
		remove_filter( 'jetpack_sync_idc_optin', '__return_false' );
410
	}
411
412
	function test_sync_error_idc_validation_returns_false_if_no_option() {
413
		Jetpack_Options::delete_option( 'sync_error_idc' );
414
		$this->assertFalse( Jetpack::validate_sync_error_idc_option() );
415
	}
416
417
	function test_sync_error_idc_validation_returns_true_when_option_matches_expected() {
418
		add_filter( 'jetpack_sync_idc_optin', '__return_true' );
419
		Jetpack_Options::update_option( 'sync_error_idc', Jetpack::get_sync_error_idc_option() );
420
		$this->assertTrue( Jetpack::validate_sync_error_idc_option() );
421
		Jetpack_Options::delete_option( 'sync_error_idc' );
422
		remove_filter( 'jetpack_sync_idc_optin', '__return_true' );
423
	}
424
425
	/**
426
	 * Verify that validate_sync_error returns false if wpcom_ is set and matches expected.
427
	 */
428 View Code Duplication
	public function test_sync_error_idc_validation_returns_false_when_wpcom_option_matches_expected() {
429
		add_filter( 'jetpack_sync_idc_optin', '__return_true' );
430
		$option                  = Jetpack::get_sync_error_idc_option();
431
		$option['wpcom_home']    = $option['home'];
432
		$option['wpcom_siteurl'] = $option['siteurl'];
433
		Jetpack_Options::update_option( 'sync_error_idc', $option );
434
		$this->assertFalse( Jetpack::validate_sync_error_idc_option() );
435
436
		// Verify the migrate_for_idc is set.
437
		$this->assertTrue( Jetpack_Options::get_option( 'migrate_for_idc' ) );
438
439
		Jetpack_Options::delete_option( 'sync_error_idc' );
440
		Jetpack_Options::delete_option( 'migrate_for_idc' );
441
		remove_filter( 'jetpack_sync_idc_optin', '__return_true' );
442
	}
443
444
	/**
445
	 * Verify that validate_sync_error returns true if wpcom_ is set and does not match.
446
	 */
447 View Code Duplication
	public function test_sync_error_idc_validation_returns_true_when_wpcom_option_does_not_match_expected() {
448
		add_filter( 'jetpack_sync_idc_optin', '__return_true' );
449
		$option                  = Jetpack::get_sync_error_idc_option();
450
		$option['wpcom_home']    = $option['home'];
451
		$option['wpcom_siteurl'] = 'coolrunnings.test';
452
		Jetpack_Options::update_option( 'sync_error_idc', $option );
453
		$this->assertTrue( Jetpack::validate_sync_error_idc_option() );
454
455
		// Verify the migrate_for_idc is not set.
456
		$this->assertNotTrue( Jetpack_Options::get_option( 'migrate_for_idc' ) );
457
458
		Jetpack_Options::delete_option( 'sync_error_idc' );
459
		Jetpack_Options::delete_option( 'migrate_for_idc' );
460
		remove_filter( 'jetpack_sync_idc_optin', '__return_true' );
461
	}
462
463
	function test_sync_error_idc_validation_cleans_up_when_validation_fails() {
464
		Jetpack_Options::update_option( 'sync_error_idc', array(
465
			'home'    => 'coolsite.com/',
466
			'siteurl' => 'coolsite.com/wp/',
467
		) );
468
469
		$this->assertFalse( Jetpack::validate_sync_error_idc_option() );
470
		$this->assertFalse( Jetpack_Options::get_option( 'sync_error_idc' ) );
471
	}
472
473 View Code Duplication
	function test_sync_error_idc_validation_cleans_up_when_part_of_validation_fails() {
474
		$test = Jetpack::get_sync_error_idc_option();
475
		$test['siteurl'] = 'coolsite.com/wp/';
476
		Jetpack_Options::update_option( 'sync_error_idc', $test );
477
478
		$this->assertFalse( Jetpack::validate_sync_error_idc_option() );
479
		$this->assertFalse( Jetpack_Options::get_option( 'sync_error_idc' ) );
480
	}
481
482
	function test_sync_error_idc_validation_returns_false_and_cleans_up_when_opted_out() {
483
		Jetpack_Options::update_option( 'sync_error_idc', Jetpack::get_sync_error_idc_option() );
484
		Constants::set_constant( 'JETPACK_SYNC_IDC_OPTIN', false );
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

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...
485
486
		$this->assertFalse( Jetpack::validate_sync_error_idc_option() );
487
		$this->assertFalse( Jetpack_Options::get_option( 'sync_error_idc' ) );
488
	}
489
490
	function test_is_staging_site_true_when_sync_error_idc_is_valid() {
491
		add_filter( 'jetpack_sync_error_idc_validation', '__return_true' );
492
		$this->assertTrue( ( new Status() )->is_staging_site() );
493
		remove_filter( 'jetpack_sync_error_idc_validation', '__return_false' );
494
	}
495
496
	function test_is_dev_version_true_with_alpha() {
497
		Constants::set_constant( 'JETPACK__VERSION', '4.3.1-alpha' );
498
		$this->assertTrue( Jetpack::is_development_version() );
499
	}
500
501
	function test_is_dev_version_true_with_beta() {
502
		Constants::set_constant( 'JETPACK__VERSION', '4.3-beta2' );
503
		$this->assertTrue( Jetpack::is_development_version() );
504
	}
505
506
	function test_is_dev_version_true_with_rc() {
507
		Constants::set_constant( 'JETPACK__VERSION', '4.3-rc2' );
508
		$this->assertTrue( Jetpack::is_development_version() );
509
	}
510
511
	function test_is_dev_version_false_with_number_dot_number() {
512
		Constants::set_constant( 'JETPACK__VERSION', '4.3' );
513
		$this->assertFalse( Jetpack::is_development_version() );
514
	}
515
516
	function test_is_dev_version_false_with_number_dot_number_dot_number() {
517
		Constants::set_constant( 'JETPACK__VERSION', '4.3.1' );
518
		$this->assertFalse( Jetpack::is_development_version() );
519
	}
520
521
	/**
522
	 * Tests is_offline_mode filter.
523
	 *
524
	 * @covers \Automattic\Jetpack\Status::is_offline_mode
525
	 */
526
	public function test_is_offline_mode_filter() {
527
		add_filter( 'jetpack_offline_mode', '__return_true' );
528
		$this->assertTrue( ( new Status() )->is_offline_mode() );
529
		remove_filter( 'jetpack_offline_mode', '__return_true' );
530
	}
531
532
	/**
533
	 * Tests is_offline_mode filter's bool type casting.
534
	 *
535
	 * @covers \Automattic\Jetpack\Status::is_offline_mode
536
	 */
537
	public function test_is_offline_mode_bool() {
538
		add_filter( 'jetpack_offline_mode', '__return_zero' );
539
		$this->assertFalse( ( new Status() )->is_offline_mode() );
540
		remove_filter( 'jetpack_offline_mode', '__return_zero' );
541
	}
542
543 View Code Duplication
	function test_get_sync_idc_option_sanitizes_out_www_and_protocol() {
544
		$original_home    = get_option( 'home' );
545
		$original_siteurl = get_option( 'siteurl' );
546
547
		update_option( 'home', 'http://www.coolsite.com' );
548
		update_option( 'siteurl', 'http://www.coolsite.com/wp' );
549
550
		$expected = array(
551
			'home' => 'coolsite.com/',
552
			'siteurl' => 'coolsite.com/wp/'
553
		);
554
555
		$this->assertSame( $expected, Jetpack::get_sync_error_idc_option() );
556
557
		// Cleanup
558
		update_option( 'home', $original_home );
559
		update_option( 'siteurl', $original_siteurl );
560
	}
561
562 View Code Duplication
	function test_get_sync_idc_option_with_ip_address_in_option() {
563
		$original_home    = get_option( 'home' );
564
		$original_siteurl = get_option( 'siteurl' );
565
566
		update_option( 'home', 'http://72.182.131.109/~wordpress' );
567
		update_option( 'siteurl', 'http://72.182.131.109/~wordpress/wp' );
568
569
		$expected = array(
570
			'home' => '72.182.131.109/~wordpress/',
571
			'siteurl' => '72.182.131.109/~wordpress/wp/'
572
		);
573
574
		$this->assertSame( $expected, Jetpack::get_sync_error_idc_option() );
575
576
		// Cleanup
577
		update_option( 'home', $original_home );
578
		update_option( 'siteurl', $original_siteurl );
579
	}
580
581 View Code Duplication
	function test_normalize_url_protocol_agnostic_strips_protocol_and_www_for_subdir_subdomain() {
582
		$url = 'https://www.subdomain.myfaketestsite.com/what';
583
		$url_normalized = Jetpack::normalize_url_protocol_agnostic( $url );
584
		$this->assertTrue( 'subdomain.myfaketestsite.com/what/' === $url_normalized );
585
586
		$url = 'http://subdomain.myfaketestsite.com';
587
		$url_normalized = Jetpack::normalize_url_protocol_agnostic( $url );
588
		$this->assertTrue( 'subdomain.myfaketestsite.com/' === $url_normalized );
589
590
		$url = 'www.subdomain.myfaketestsite.com';
591
		$url_normalized = Jetpack::normalize_url_protocol_agnostic( $url );
592
		$this->assertTrue( 'subdomain.myfaketestsite.com/' === $url_normalized );
593
	}
594
595 View Code Duplication
	function test_normalize_url_protocol_agnostic_strips_protocol_and_www_for_normal_urls() {
596
		$url = 'https://www.myfaketestsite.com';
597
		$url_normalized = Jetpack::normalize_url_protocol_agnostic( $url );
598
		$this->assertTrue( 'myfaketestsite.com/' === $url_normalized );
599
600
		$url = 'www.myfaketestsite.com';
601
		$url_normalized = Jetpack::normalize_url_protocol_agnostic( $url );
602
		$this->assertTrue( 'myfaketestsite.com/' === $url_normalized );
603
604
		$url = 'myfaketestsite.com';
605
		$url_normalized = Jetpack::normalize_url_protocol_agnostic( $url );
606
		$this->assertTrue( 'myfaketestsite.com/' === $url_normalized );
607
	}
608
609
	function test_normalize_url_protocol_agnostic_strips_protocol_for_ip() {
610
		$url = 'http://123.456.789.0';
611
		$url_normalized = Jetpack::normalize_url_protocol_agnostic( $url );
612
		$this->assertTrue( '123.456.789.0/' === $url_normalized );
613
614
		$url = '123.456.789.0';
615
		$url_normalized = Jetpack::normalize_url_protocol_agnostic( $url );
616
		$this->assertTrue( '123.456.789.0/' === $url_normalized );
617
	}
618
619
	/**
620
	 * Parse the referer on plugin activation and record the activation source
621
	 * - featured plugins page
622
	 * - popular plugins page
623
	 * - search (with query)
624
	 * - plugins list
625
	 * - other
626
	 */
627
	function test_get_activation_source() {
628
		$plugins_url = admin_url( 'plugins.php' );
629
		$plugin_install_url = admin_url( 'plugin-install.php' );
630
		$unknown_url = admin_url( 'unknown.php' );
631
632
		$this->assertEquals( array( 'list', null ), Jetpack::get_activation_source( $plugins_url . '?plugin_status=all&paged=1&s' ) );
633
		$this->assertEquals( array( 'featured', null ), Jetpack::get_activation_source( $plugin_install_url ) );
634
		$this->assertEquals( array( 'popular', null ), Jetpack::get_activation_source( $plugin_install_url . '?tab=popular' ) );
635
		$this->assertEquals( array( 'recommended', null ), Jetpack::get_activation_source( $plugin_install_url . '?tab=recommended' ) );
636
		$this->assertEquals( array( 'favorites', null ), Jetpack::get_activation_source( $plugin_install_url . '?tab=favorites' ) );
637
		$this->assertEquals( array( 'search-term', 'jetpack' ), Jetpack::get_activation_source( $plugin_install_url . '?s=jetpack&tab=search&type=term' ) );
638
		$this->assertEquals( array( 'search-author', 'foo' ), Jetpack::get_activation_source( $plugin_install_url . '?s=foo&tab=search&type=author' ) );
639
		$this->assertEquals( array( 'search-tag', 'social' ), Jetpack::get_activation_source( $plugin_install_url . '?s=social&tab=search&type=tag' ) );
640
		$this->assertEquals( array( 'unknown', null ), Jetpack::get_activation_source( $unknown_url ) );
641
	}
642
643
	/**
644
	 * @author tyxla
645
	 * @covers Jetpack::get_assumed_site_creation_date()
646
	 */
647 View Code Duplication
	function test_get_assumed_site_creation_date_user_earliest() {
648
		$user_id = $this->factory->user->create( array(
649
			'role'            => 'administrator',
650
			'user_registered' => '1990-01-01 00:00:00',
651
		) );
652
		$post_id = $this->factory->post->create( array(
653
			'post_date' => '1995-01-01 00:00:00',
654
		) );
655
656
		$jetpack = new MockJetpack();
657
		$this->assertEquals( '1990-01-01 00:00:00', $jetpack::connection()->get_assumed_site_creation_date() );
658
659
		wp_delete_user( $user_id );
660
		wp_delete_post( $post_id, true );
661
	}
662
663
	/**
664
	 * @author tyxla
665
	 * @covers Jetpack::get_assumed_site_creation_date()
666
	 */
667 View Code Duplication
	function test_get_assumed_site_creation_date_post_earliest() {
668
		$user_id = $this->factory->user->create( array(
669
			'role'            => 'administrator',
670
			'user_registered' => '1994-01-01 00:00:00',
671
		) );
672
		$post_id = $this->factory->post->create( array(
673
			'post_date' => '1991-01-01 00:00:00',
674
		) );
675
676
		$jetpack = new MockJetpack();
677
		$this->assertEquals( '1991-01-01 00:00:00', $jetpack::connection()->get_assumed_site_creation_date() );
678
679
		wp_delete_user( $user_id );
680
		wp_delete_post( $post_id, true );
681
	}
682
683
	/**
684
	 * @author tyxla
685
	 * @covers Jetpack::get_assumed_site_creation_date()
686
	 */
687 View Code Duplication
	function test_get_assumed_site_creation_date_only_admins() {
688
		$admin_id = $this->factory->user->create( array(
689
			'role'            => 'administrator',
690
			'user_registered' => '1994-01-01 00:00:00',
691
		) );
692
		$editor_id = $this->factory->user->create( array(
693
			'role'            => 'editor',
694
			'user_registered' => '1992-01-01 00:00:00',
695
		) );
696
697
		$jetpack = new MockJetpack();
698
		$this->assertEquals( '1994-01-01 00:00:00', $jetpack::connection()->get_assumed_site_creation_date() );
699
700
		wp_delete_user( $admin_id );
701
		wp_delete_user( $editor_id );
702
	}
703
704
	/**
705
	 * @author ebinnion
706
	 * @dataProvider get_file_url_for_environment_data_provider
707
	 */
708
	function test_get_file_url_for_environment( $min_path, $non_min_path, $is_script_debug, $expected, $not_expected ) {
709
		Constants::set_constant( 'SCRIPT_DEBUG', $is_script_debug );
710
		$file_url = Jetpack::get_file_url_for_environment( $min_path, $non_min_path );
711
712
		$this->assertContains( $$expected, $file_url );
713
		$this->assertNotContains( $$not_expected, $file_url );
714
	}
715
716 View Code Duplication
	function get_file_url_for_environment_data_provider() {
717
		return array(
718
			'script-debug-true' => array(
719
				'_inc/build/shortcodes/js/recipes.js',
720
				'modules/shortcodes/js/recipes.js',
721
				true,
722
				'non_min_path',
723
				'min_path'
724
			),
725
			'script-debug-false' => array(
726
				'_inc/build/shortcodes/js/recipes.js',
727
				'modules/shortcodes/js/recipes.js',
728
				false,
729
				'min_path',
730
				'non_min_path'
731
			),
732
		);
733
	}
734
735
	/**
736
	 * @dataProvider get_content_width_data
737
	 */
738
	public function test_get_content_width( $expected, $content_width ) {
739
		$GLOBALS['content_width'] = $content_width;
740
		$this->assertSame( $expected, Jetpack::get_content_width() );
741
	}
742
743
	public function get_content_width_data() {
744
		return array(
745
			'zero' => array(
746
				0,
747
				0,
748
			),
749
			'int' => array(
750
				100,
751
				100,
752
			),
753
			'numeric_string' => array(
754
				'100',
755
				'100',
756
			),
757
			'non_numeric_string' => array(
758
				false,
759
				'meh'
760
			),
761
			'content_width_not_set' => array(
762
				false,
763
				null,
764
			),
765
		);
766
	}
767
768
	/**
769
	 * Return a Cyrillic salt.
770
	 *
771
	 * @param string $password String to add salt to.
772
	 * @return string
773
	 */
774
	public static function cyrillic_salt( $password ) {
775
		return 'ленка' . $password . 'пенка';
776
	}
777
778
	/**
779
	 * Return a Kanji salt.
780
	 *
781
	 * @param string $password String to add salt to.
782
	 * @return string
783
	 */
784
	public static function kanji_salt( $password ) {
785
		return '強熊' . $password . '清珠';
786
	}
787
788
	/**
789
	 * Filter to increase a string length.
790
	 *
791
	 * @param string $password String to expand.
792
	 * @return string
793
	 */
794
	public static function multiply_filter( $password ) {
795
		for ( $i = 0; $i < 10; $i++ ) {
796
			$password .= $password;
797
		}
798
		return $password;
799
	}
800
801
	/**
802
	 * Return string '1'.
803
	 *
804
	 * @return string
805
	 */
806
	public function return_string_1() {
807
		return '1';
808
	}
809
810
	/**
811
	 * Reset tracking of module activation.
812
	 */
813
	public static function reset_tracking_of_module_activation() {
814
		self::$activated_modules   = array();
815
		self::$deactivated_modules = array();
816
	}
817
818
	/**
819
	 * Track activated modules.
820
	 *
821
	 * @param mixed $module Module.
822
	 */
823
	public static function track_activated_modules( $module ) {
824
		self::$activated_modules[] = $module;
825
	}
826
827
	/**
828
	 * Track deactivated modules.
829
	 *
830
	 * @param mixed $module Module.
831
	 */
832
	public static function track_deactivated_modules( $module ) {
833
		self::$deactivated_modules[] = $module;
834
	}
835
836
	/**
837
	 * Mocked `setup_xmlrpc_handlers`.
838
	 *
839
	 * @param array         $request_params Incoming request parameters.
840
	 * @param bool          $is_active Whether the connection is currently active.
841
	 * @param bool          $is_signed Whether the signature check has been successful.
842
	 * @param WP_User|false $user User for the mocked Jetpack_XMLRPC_Server.
843
	 * @return bool
844
	 */
845
	private function mocked_setup_xmlrpc_handlers( $request_params, $is_active, $is_signed, $user = false ) {
846
		$GLOBALS['HTTP_RAW_POST_DATA'] = '';
847
848
		Constants::set_constant( 'XMLRPC_REQUEST', true );
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a string.

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...
849
850
		$jetpack       = new MockJetpack();
851
		$xmlrpc_server = new MockJetpack_XMLRPC_Server( $user );
852
		return $jetpack::connection()->setup_xmlrpc_handlers( $request_params, $is_active, $is_signed, $xmlrpc_server );
853
	}
854
855
	/**
856
	 * Asserts that:
857
	 *   - all of the required xmlrpc methods are in the actual method list.
858
	 *   - all of the actual xmlrpc methods are in the required or allowed lists.
859
	 *
860
	 * @param string[] $required List of XML-RPC methods that must be contained in $actual.
861
	 * @param string[] $allowed  Additional list of XML-RPC methods that may be contained in $actual.
862
	 *                           Useful for listing methods that are added by modules that may or may
863
	 *                           not be active during the test run.
864
	 * @param string[] $actual   The list of XML-RPC methods.
865
	 */
866
	private function assertXMLRPCMethodsComply( $required, $allowed, $actual ) {
867
		$this->assertEquals( array(), array_diff( $required, $actual ) );
868
		$this->assertEquals( array(), array_diff( $actual, $required, $allowed ) );
869
	}
870
871
	/**
872
	 * Tests the setup of the xmlrpc methods when the site is active, the request is signed, and without a user.
873
	 *
874
	 * @group xmlrpc
875
	 */
876
	public function test_classic_xmlrpc_when_active_and_signed_with_no_user() {
877
		$this->mocked_setup_xmlrpc_handlers( array( 'for' => 'jetpack' ), true, true );
878
879
		$methods = apply_filters( 'xmlrpc_methods', array( 'test.test' => '__return_true' ) );
880
881
		$required = array(
882
			'jetpack.verifyAction',
883
			'jetpack.getUser',
884
			'jetpack.remoteRegister',
885
			'jetpack.remoteProvision',
886
			'jetpack.jsonAPI',
887
			'jetpack.idcUrlValidation',
888
			'jetpack.unlinkUser',
889
			'jetpack.testConnection',
890
			'jetpack.featuresAvailable',
891
			'jetpack.featuresEnabled',
892
			'jetpack.disconnectBlog',
893
		);
894
895
		$allowed = array(
896
			'jetpack.getHeartbeatData',
897
			'jetpack.syncObject',
898
			'jetpack.updatePublicizeConnections',
899
			'jetpack.getBlog',
900
		);
901
902
		$this->assertXMLRPCMethodsComply( $required, $allowed, array_keys( $methods ) );
903
	}
904
905
	/**
906
	 * Tests the setup of the xmlrpc methods when the site is active, the request is signed, and with a user.
907
	 *
908
	 * @group xmlrpc
909
	 */
910
	public function test_classic_xmlrpc_when_active_and_signed_with_user() {
911
		$this->mocked_setup_xmlrpc_handlers( array( 'for' => 'jetpack' ), true, true, get_user_by( 'ID', self::$admin_id ) );
912
913
		$methods = apply_filters( 'xmlrpc_methods', array( 'test.test' => '__return_true' ) );
914
915
		$required = array(
916
			'jetpack.verifyAction',
917
			'jetpack.getUser',
918
			'jetpack.remoteRegister',
919
			'jetpack.remoteProvision',
920
			'jetpack.jsonAPI',
921
922
			'jetpack.testAPIUserCode',
923
			'jetpack.disconnectBlog',
924
			'jetpack.unlinkUser',
925
			'jetpack.idcUrlValidation',
926
			'jetpack.testConnection',
927
			'jetpack.featuresAvailable',
928
			'jetpack.featuresEnabled',
929
930
			'jetpack.syncObject',
931
		);
932
933
		// It's OK if these module-added methods are present (module active in tests).
934
		// It's OK if they are not (module inactive in tests).
935
		$allowed = array(
936
			'jetpack.subscriptions.subscribe',
937
			'jetpack.updatePublicizeConnections',
938
			'jetpack.getHeartbeatData',
939
		);
940
941
		$this->assertXMLRPCMethodsComply( $required, $allowed, array_keys( $methods ) );
942
	}
943
944
	/**
945
	 * Tests the setup of the xmlrpc methods when the site is active, the request is signed, with a user,
946
	 * and with edit methods enabled.
947
	 *
948
	 * @group xmlrpc
949
	 */
950
	public function test_classic_xmlrpc_when_active_and_signed_with_user_with_edit() {
951
		$this->mocked_setup_xmlrpc_handlers(
952
			array( 'for' => 'jetpack' ),
953
			true,
954
			true,
955
			get_user_by( 'ID', self::$admin_id )
956
		);
957
958
		$methods = apply_filters(
959
			'xmlrpc_methods',
960
			array(
961
				'test.test'                 => '__return_true',
962
				'metaWeblog.editPost'       => '__return_true',
963
				'metaWeblog.newMediaObject' => '__return_true',
964
			)
965
		);
966
967
		$required = array(
968
			'jetpack.verifyAction',
969
			'jetpack.getUser',
970
			'jetpack.remoteRegister',
971
			'jetpack.remoteProvision',
972
			'jetpack.jsonAPI',
973
974
			'jetpack.testAPIUserCode',
975
			'jetpack.disconnectBlog',
976
			'jetpack.unlinkUser',
977
			'jetpack.idcUrlValidation',
978
			'jetpack.testConnection',
979
			'jetpack.featuresAvailable',
980
			'jetpack.featuresEnabled',
981
982
			'metaWeblog.newMediaObject',
983
			'jetpack.updateAttachmentParent',
984
985
			'jetpack.syncObject',
986
		);
987
988
		// It's OK if these module-added methods are present (module active in tests).
989
		// It's OK if they are not (module inactive in tests).
990
		$allowed = array(
991
			'jetpack.subscriptions.subscribe',
992
			'jetpack.updatePublicizeConnections',
993
			'jetpack.getHeartbeatData',
994
		);
995
996
		$this->assertXMLRPCMethodsComply( $required, $allowed, array_keys( $methods ) );
997
	}
998
999
	/**
1000
	 * Tests the setup of the xmlrpc methods when the site is active and the request is not signed.
1001
	 *
1002
	 * @group xmlrpc
1003
	 */
1004
	public function test_classic_xmlrpc_when_active_and_not_signed() {
1005
		$this->mocked_setup_xmlrpc_handlers( array( 'for' => 'jetpack' ), true, false );
1006
1007
		$methods = apply_filters( 'xmlrpc_methods', array( 'test.test' => '__return_true' ) );
1008
1009
		$required = array(
1010
			'jetpack.remoteAuthorize',
1011
		);
1012
1013
		// Nothing else is allowed.
1014
		$allowed = array();
1015
1016
		$this->assertXMLRPCMethodsComply( $required, $allowed, array_keys( $methods ) );
1017
	}
1018
1019
	/**
1020
	 * Tests the setup of the xmlrpc methods when the site is not active and the request is not signed.
1021
	 *
1022
	 * @group xmlrpc
1023
	 */
1024 View Code Duplication
	public function test_classic_xmlrpc_when_not_active_and_not_signed() {
1025
		$this->mocked_setup_xmlrpc_handlers( array( 'for' => 'jetpack' ), false, false );
1026
1027
		$methods = apply_filters( 'xmlrpc_methods', array( 'test.test' => '__return_true' ) );
1028
1029
		$required = array(
1030
			'jetpack.remoteAuthorize',
1031
			'jetpack.remoteRegister',
1032
1033
			'jetpack.verifyRegistration',
1034
		);
1035
1036
		// Nothing else is allowed.
1037
		$allowed = array();
1038
1039
		$this->assertXMLRPCMethodsComply( $required, $allowed, array_keys( $methods ) );
1040
	}
1041
1042
	/**
1043
	 * Tests the setup of the xmlrpc methods when the site is not active and the request is signed.
1044
	 *
1045
	 * @group xmlrpc
1046
	 */
1047 View Code Duplication
	public function test_classic_xmlrpc_when_not_active_and_signed() {
1048
		$this->mocked_setup_xmlrpc_handlers( array( 'for' => 'jetpack' ), false, true );
1049
1050
		$methods = apply_filters( 'xmlrpc_methods', array( 'test.test' => '__return_true' ) );
1051
1052
		$required = array(
1053
			'jetpack.remoteRegister',
1054
			'jetpack.remoteProvision',
1055
			'jetpack.remoteConnect',
1056
			'jetpack.getUser',
1057
		);
1058
1059
		// Nothing else is allowed.
1060
		$allowed = array();
1061
1062
		$this->assertXMLRPCMethodsComply( $required, $allowed, array_keys( $methods ) );
1063
	}
1064
1065
	/**
1066
	 * Test "wp_getOptions_hook_in_place".
1067
	 *
1068
	 * @see https://github.com/Automattic/jetpack/pull/13514
1069
	 *
1070
	 * @group xmlrpc
1071
	 */
1072
	public function test_wp_getOptions_hook_in_place() {
1073
		$options = apply_filters( 'xmlrpc_blog_options', array() );
1074
1075
		$this->assertArrayHasKey( 'jetpack_version', $options );
1076
	}
1077
1078
	/**
1079
	 * Tests if Partner codes are added to the connect url.
1080
	 *
1081
	 * @dataProvider partner_code_provider
1082
	 *
1083
	 * @param string $code_type Partner code type.
1084
	 * @param string $option_name Option and filter name.
1085
	 * @param string $query_string_name Query string variable name.
1086
	 */
1087
	public function test_partner_codes_are_added_to_authorize_url( $code_type, $option_name, $query_string_name ) {
1088
		$test_code = 'abc-123';
1089
		Partner::init();
1090
		add_filter(
1091
			$option_name,
1092
			function () use ( $test_code ) {
1093
				return $test_code;
1094
			}
1095
		);
1096
		$jetpack = \Jetpack::init();
1097
		$url     = $jetpack->build_authorize_url();
1098
1099
		$parsed_vars = array();
1100
		parse_str( wp_parse_url( $url, PHP_URL_QUERY ), $parsed_vars );
1101
1102
		$this->assertArrayHasKey( $query_string_name, $parsed_vars );
1103
		$this->assertSame( $test_code, $parsed_vars[ $query_string_name ] );
1104
	}
1105
1106
	/**
1107
	 * Provides code for test_partner_codes_are_added_to_authorize_url.
1108
	 *
1109
	 * @return array
1110
	 */
1111 View Code Duplication
	public function partner_code_provider() {
1112
		return array(
1113
			'subsidiary_code' =>
1114
				array(
1115
					Partner::SUBSIDIARY_CODE,            // Code type.
1116
					'jetpack_partner_subsidiary_id',     // filter/option key.
1117
					'subsidiaryId',                      // Query string parameter.
1118
				),
1119
			'affiliate_code'  =>
1120
				array(
1121
					Partner::AFFILIATE_CODE,
1122
					'jetpack_affiliate_code',
1123
					'aff',
1124
				),
1125
		);
1126
	}
1127
1128
	/**
1129
	 * Tests login URL only adds redirect param when redirect param is in original request.
1130
	 *
1131
	 * @since 8.4.0
1132
	 * @return void
1133
	 */
1134
	public function test_login_url_add_redirect() {
1135
		$login_url = wp_login_url( '/wp-admin' );
1136
		$this->assertFalse( strpos( $login_url, Jetpack::$jetpack_redirect_login ) );
1137
1138
		$login_url = wp_login_url( '/wp-admin?' . Jetpack::$jetpack_redirect_login . '=true' );
1139
		parse_str( wp_parse_url( $login_url, PHP_URL_QUERY ), $login_parts );
1140
		$this->assertArraySubset( array( Jetpack::$jetpack_redirect_login => 'true' ), $login_parts, true );
1141
	}
1142
1143
	/**
1144
	 * Tests login redirect sending users to Calypso when redirect param is set.
1145
	 *
1146
	 * @since 8.4.0
1147
	 * @return void
1148
	 */
1149
	public function test_login_init_redirect() {
1150
		tests_add_filter(
1151
			'wp_redirect',
1152
			function ( $location ) {
1153
				$expected_location = add_query_arg(
1154
					array(
1155
						'forceInstall' => 1,
1156
						'url'          => rawurlencode( get_site_url() ),
1157
					),
1158
					'https://wordpress.com/jetpack/connect'
1159
				);
1160
				$this->assertEquals( $location, $expected_location );
1161
				throw new Exception(); // Cause an exception, as we don't want to run exit.
1162
			}
1163
		);
1164
1165
		// Remove core filters that add headers.
1166
		remove_filter( 'login_init', 'wp_admin_headers' );
1167
		remove_filter( 'login_init', 'send_frame_options_header' );
1168
1169
		// Run it once and no exception is thrown.
1170
		do_action( 'login_init' );
1171
1172
		$this->expectException( Exception::class );
1173
		$_GET[ Jetpack::$jetpack_redirect_login ] = 'true';
1174
		do_action( 'login_init' ); // Now expect an exception.
1175
	}
1176
1177
	/**
1178
	 * Tests getting the correct Calypso host.
1179
	 *
1180
	 * @since 8.4.0
1181
	 * @return void
1182
	 */
1183
	public function test_get_calypso_host() {
1184
		// No env.
1185
		$this->assertEquals( 'https://wordpress.com/', Jetpack::get_calypso_host() );
1186
1187
		$_GET['calypso_env'] = 'development';
1188
		$this->assertEquals( 'http://calypso.localhost:3000/', Jetpack::get_calypso_host() );
1189
1190
		$_GET['calypso_env'] = 'wpcalypso';
1191
		$this->assertEquals( 'https://wpcalypso.wordpress.com/', Jetpack::get_calypso_host() );
1192
1193
		$_GET['calypso_env'] = 'horizon';
1194
		$this->assertEquals( 'https://horizon.wordpress.com/', Jetpack::get_calypso_host() );
1195
1196
		$_GET['calypso_env'] = 'stage';
1197
		$this->assertEquals( 'https://wordpress.com/', Jetpack::get_calypso_host() );
1198
1199
		$_GET['calypso_env'] = 'production';
1200
		$this->assertEquals( 'https://wordpress.com/', Jetpack::get_calypso_host() );
1201
	}
1202
1203
	/**
1204
	 * Tests the Jetpack::should_set_cookie() method.
1205
	 *
1206
	 * @param string  $key The state key test value.
1207
	 * @param string  $set_screen The $current_screen->base test value.
1208
	 * @param boolean $expected_output The expected output of Jetpack::should_set_cookie().
1209
	 *
1210
	 * @covers Jetpack::should_set_cookie
1211
	 * @dataProvider should_set_cookie_provider
1212
	 */
1213
	public function test_should_set_cookie( $key, $set_screen, $expected_output ) {
1214
		global $current_screen;
1215
		$old_current_screen   = $current_screen;
1216
		$current_screen       = new stdClass();
1217
		$current_screen->base = $set_screen;
1218
1219
		$this->assertEquals( $expected_output, Jetpack::should_set_cookie( $key ) );
1220
		$current_screen = $old_current_screen;
1221
	}
1222
1223
	/**
1224
	 * The data provider for test_should_set_cookie(). Provides an array of
1225
	 * test data. Each data set is an array with the structure:
1226
	 *     [0] => The state key test value.
1227
	 *     [1] => The $current_screen->base test value.
1228
	 *     [2] => The expected output of Jetpack::should_set_cookie().
1229
	 */
1230
	public function should_set_cookie_provider() {
1231
		return array(
1232
			array( 'display_update_modal', 'toplevel_page_jetpack', false ),
1233
			array( 'display_update_modal', 'test_page', true ),
1234
			array( 'display_update_modal', null, true ),
1235
			array( 'message', 'toplevel_page_jetpack', true ),
1236
			array( 'message', 'test_page', true ),
1237
			array( 'message', null, true ),
1238
		);
1239
	}
1240
1241
	/**
1242
	 * Testing that a deprecated action triggers Jetpack functionality.
1243
	 *
1244
	 * Using the `jetpack_updated_theme` action for the sake of testing.
1245
	 *
1246
	 * @expectedDeprecated jetpack_updated_theme
1247
	 */
1248
	public function test_deprecated_action_fires() {
1249
		add_action( 'jetpack_updated_theme', '__return_false' );
1250
		Jetpack::init()->deprecated_hooks();
1251
		remove_action( 'jetpack_updated_theme', '__return_false' );
1252
	}
1253
1254
	/**
1255
	 * Testing that a deprecated filter triggers Jetpack functionality.
1256
	 *
1257
	 * Using the `jetpack_bail_on_shortcode` filter for the sake of testing.
1258
	 *
1259
	 * @expectedDeprecated jetpack_bail_on_shortcode
1260
	 */
1261
	public function test_deprecated_filter_fires() {
1262
		add_filter( 'jetpack_bail_on_shortcode', '__return_false' );
1263
		Jetpack::init()->deprecated_hooks();
1264
		remove_filter( 'jetpack_bail_on_shortcode', '__return_false' );
1265
	}
1266
} // end class
1267