Completed
Push — fix/disconnect-user-wpcom ( 8faeaf...290274 )
by
unknown
36:29 queued 25:40
created

ManagerIntegrationTest::tear_down()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase
2
/**
3
 * Connection Manager functionality testing.
4
 *
5
 * @package automattic/jetpack-connection
6
 */
7
8
namespace Automattic\Jetpack\Connection;
9
10
use Automattic\Jetpack\Constants;
11
12
/**
13
 * Connection Manager functionality testing.
14
 */
15
class ManagerIntegrationTest extends \WorDBless\BaseTestCase {
16
17
	/**
18
	 * The connection manager.
19
	 *
20
	 * @var Manager
21
	 */
22
	private $manager;
23
24
	/**
25
	 * Initialize the object before running the test method.
26
	 *
27
	 * @before
28
	 */
29
	public function set_up() {
30
		$this->manager = new Manager();
31
32
		$this->ixr_client = $this->getMockBuilder( '\Jetpack_IXR_Client' )
33
			->setMethods( array( 'isError', 'getResponse' ) )
34
			->getMock();
35
	}
36
37
	/**
38
	 * Clean up the testing environment.
39
	 *
40
	 * @after
41
	 */
42
	public function tear_down() {
43
		unset( $this->ixr_client );
44
	}
45
46
	/**
47
	 * Test the `is_connected' method.
48
	 *
49
	 * @covers Automattic\Jetpack\Connection\Manager::is_connected
50
	 * @dataProvider is_connected_data_provider
51
	 *
52
	 * @param object|boolean $blog_token The blog token. False if the blog token does not exist.
53
	 * @param int|boolean    $blog_id The blog id. False if the blog id does not exist.
54
	 * @param boolean        $expected_output The expected output.
55
	 */
56
	public function test_is_connected( $blog_token, $blog_id, $expected_output ) {
57
		if ( $blog_token ) {
58
			\Jetpack_Options::update_option( 'blog_token', 'asdasd.123123' );
59
		} else {
60
			\Jetpack_Options::delete_option( 'blog_token' );
61
		}
62
63
		if ( $blog_id ) {
64
			\Jetpack_Options::update_option( 'id', $blog_id );
65
		} else {
66
			\Jetpack_Options::delete_option( 'id' );
67
		}
68
69
		$this->assertEquals( $expected_output, $this->manager->is_connected() );
70
	}
71
72
	/**
73
	 * Data provider for test_is_connected.
74
	 *
75
	 * Structure of the test data arrays:
76
	 *     [0] => 'blog_token'      object|boolean The blog token or false if the blog token does not exist.
77
	 *     [1] => 'blog_id'         int|boolean The blog id or false if the blog id does not exist.
78
	 *     [2] => 'expected_output' boolean The expected output of the call to is_connected.
79
	 */
80
	public function is_connected_data_provider() {
81
82
		return array(
83
			'blog token, blog id'       => array( true, 1234, true ),
84
			'blog token, no blog id'    => array( true, false, false ),
85
			'no blog token, blog id'    => array( false, 1234, false ),
86
			'no blog token, no blog id' => array( false, false, false ),
87
		);
88
	}
89
90
	/**
91
	 * Test get_connected_users
92
	 */
93
	public function test_get_connected_users() {
94
		$id_admin = wp_insert_user(
95
			array(
96
				'user_login' => 'admin',
97
				'user_pass'  => 'pass',
98
				'role'       => 'administrator',
99
			)
100
		);
101
102
		$id_author = wp_insert_user(
103
			array(
104
				'user_login' => 'author',
105
				'user_pass'  => 'pass',
106
				'role'       => 'author',
107
			)
108
		);
109
110
		\Jetpack_Options::update_option(
111
			'user_tokens',
112
			array(
113
				$id_admin  => 'asd123',
114
				$id_author => 'asd123',
115
			)
116
		);
117
118
		$all_users = $this->manager->get_connected_users();
119
		$admins    = $this->manager->get_connected_users( 'manage_options' );
120
121
		$this->assertCount( 2, $all_users );
122
		$this->assertCount( 1, $admins );
123
		$this->assertSame( $id_admin, $admins[0]->ID );
124
	}
125
126
	/**
127
	 * Test get_connection_owner and is_owner
128
	 */
129
	public function test_get_connection_owner_and_has_connected_owner() {
130
		$this->assertFalse( $this->manager->get_connection_owner() );
131
		$this->assertFalse( $this->manager->has_connected_owner() );
132
133
		$id_admin = wp_insert_user(
134
			array(
135
				'user_login' => 'admin',
136
				'user_pass'  => 'pass',
137
				'role'       => 'administrator',
138
			)
139
		);
140
141
		$id_author = wp_insert_user(
142
			array(
143
				'user_login' => 'author',
144
				'user_pass'  => 'pass',
145
				'role'       => 'author',
146
			)
147
		);
148
149
		\Jetpack_Options::update_option( 'master_user', $id_admin );
150
151
		// Before tokens are created, no owner is found.
152
		$this->assertFalse( $this->manager->get_connection_owner() );
153
		$this->assertFalse( $this->manager->has_connected_owner() );
154
155
		\Jetpack_Options::update_option(
156
			'user_tokens',
157
			array(
158
				$id_admin  => 'asd.123.' . $id_admin,
159
				$id_author => 'asd.123.' . $id_author,
160
			)
161
		);
162
163
		$owner = $this->manager->get_connection_owner();
164
165
		$this->assertInstanceOf( 'WP_User', $owner );
166
		$this->assertSame( $id_admin, $owner->ID );
167
		$this->assertTrue( $this->manager->has_connected_owner() );
168
	}
169
170
	/**
171
	 * Test has_connected_user and has_connected_admin
172
	 */
173
	public function test_has_connected_user_and_has_connected_admin() {
174
		$this->assertFalse( $this->manager->has_connected_user() );
175
		$this->assertFalse( $this->manager->has_connected_admin() );
176
177
		// Create the user.
178
		$id_author = wp_insert_user(
179
			array(
180
				'user_login' => 'author',
181
				'user_pass'  => 'pass',
182
				'role'       => 'author',
183
			)
184
		);
185
186
		$this->assertFalse( $this->manager->has_connected_user() );
187
		$this->assertFalse( $this->manager->has_connected_admin() );
188
189
		// Connect the user.
190
		\Jetpack_Options::update_option(
191
			'user_tokens',
192
			array(
193
				$id_author => 'asd.123.' . $id_author,
194
			)
195
		);
196
197
		$this->assertTrue( $this->manager->has_connected_user() );
198
		$this->assertFalse( $this->manager->has_connected_admin() );
199
200
		$id_admin = wp_insert_user(
201
			array(
202
				'user_login' => 'admin',
203
				'user_pass'  => 'pass',
204
				'role'       => 'administrator',
205
			)
206
		);
207
208
		\Jetpack_Options::update_option(
209
			'user_tokens',
210
			array(
211
				$id_admin  => 'asd.123.' . $id_admin,
212
				$id_author => 'asd.123.' . $id_author,
213
			)
214
		);
215
216
		$this->assertTrue( $this->manager->has_connected_user() );
217
		$this->assertTrue( $this->manager->has_connected_admin() );
218
219
	}
220
221
	/**
222
	 * Test is_connection_owner
223
	 */
224
	public function test_is_connection_owner() {
225
		$master_user_id = wp_insert_user(
226
			array(
227
				'user_login' => 'sample_user',
228
				'user_pass'  => 'asdqwe',
229
				'role'       => 'administrator',
230
			)
231
		);
232
		$other_user_id  = wp_insert_user(
233
			array(
234
				'user_login' => 'other_user',
235
				'user_pass'  => 'asdqwe',
236
				'role'       => 'administrator',
237
			)
238
		);
239
		\Jetpack_Options::update_option(
240
			'user_tokens',
241
			array(
242
				$master_user_id => 'asd.qwe.' . $master_user_id,
243
			)
244
		);
245
		// No owner and non-logged in user context.
246
		$this->assertFalse( $this->manager->is_connection_owner() );
247
		\Jetpack_Options::update_option( 'master_user', $master_user_id );
248
249
		$this->assertFalse( $this->manager->is_connection_owner() );
250
251
		wp_set_current_user( $master_user_id );
252
		$this->assertTrue( $this->manager->is_connection_owner() );
253
254
		wp_set_current_user( $other_user_id );
255
		$this->assertFalse( $this->manager->is_connection_owner() );
256
257
	}
258
259
	/**
260
	 * Test get_access_token method
261
	 *
262
	 * @dataProvider get_access_token_data_provider
263
	 *
264
	 * @param bool|string $create_blog_token The blog token to be created.
265
	 * @param bool|array  $create_user_tokens The user tokens to be created.
266
	 * @param bool|int    $master_user The ID of the master user to be defined.
267
	 * @param bool|int    $user_id_query The user ID that will be used to fetch the token.
268
	 * @param bool|string $token_key_query The token_key that will be used to fetch the token.
269
	 * @param bool|string $expected_error_code If an error is expected, the error code.
270
	 * @param bool|object $expected_token If success is expected, the expected token object.
271
	 * @return void
272
	 */
273
	public function test_get_access_token( $create_blog_token, $create_user_tokens, $master_user, $user_id_query, $token_key_query, $expected_error_code, $expected_token ) {
274
275
		// Set up.
276
		if ( $create_blog_token ) {
277
			\Jetpack_Options::update_option( 'blog_token', $create_blog_token );
278
			\Jetpack_Options::update_option( 'id', 1234 );
279
		}
280
		if ( $create_user_tokens ) {
281
			\Jetpack_Options::update_option( 'user_tokens', $create_user_tokens );
282
			foreach ( array_keys( $create_user_tokens ) as $uid ) {
283
				wp_insert_user(
284
					array(
285
						'user_login' => 'sample_user' . $uid,
286
						'user_pass'  => 'asdqwe',
287
					)
288
				);
289
			}
290
			if ( $master_user ) {
291
				\Jetpack_Options::update_option( 'master_user', $master_user );
292
			}
293
		}
294
295
		if ( 'CONNECTION_OWNER' === $user_id_query ) {
296
			$user_id_query = true;
297
		}
298
299
		$token = ( new Tokens() )->get_access_token( $user_id_query, $token_key_query, false );
0 ignored issues
show
Bug introduced by
It seems like $token_key_query defined by parameter $token_key_query on line 273 can also be of type boolean; however, Automattic\Jetpack\Conne...ens::get_access_token() does only seem to accept false|string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
Bug introduced by
It seems like $user_id_query can also be of type boolean; however, Automattic\Jetpack\Conne...ens::get_access_token() does only seem to accept false|integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
300
301
		if ( $expected_error_code ) {
302
			$this->assertInstanceOf( 'WP_Error', $token );
303
			$this->assertSame( $expected_error_code, $token->get_error_code() );
304
		} else {
305
			$this->assertEquals( $expected_token, $token );
306
		}
307
	}
308
309
	/**
310
	 * Data provider for test_get_access_token
311
	 *
312
	 * @return array
313
	 */
314
	public function get_access_token_data_provider() {
315
		return array(
316
			'no tokens'                        => array(
317
				false, // blog token.
318
				false, // user tokens.
319
				false, // master_user.
320
				false, // user_id_query.
321
				false, // token_key_query.
322
				'no_possible_tokens', // expected error code.
323
				false, // expected token.
324
			),
325
			'no tokens'                        => array(
326
				false, // blog token.
327
				false, // user tokens.
328
				false, // master_user.
329
				22, // user_id_query.
330
				false, // token_key_query.
331
				'no_user_tokens', // expected error code.
332
				false, // expected token.
333
			),
334
			'no tokens for the user'           => array(
335
				false, // blog token.
336
				array(
337
					11 => 'asd.zxc.11',
338
				), // user tokens.
339
				false, // master_user.
340
				22, // user_id_query.
341
				false, // token_key_query.
342
				'no_token_for_user', // expected error code.
343
				false, // expected token.
344
			),
345
			'malformed user token'             => array(
346
				false, // blog token.
347
				array(
348
					11 => 'asdzxc.11',
349
				), // user tokens.
350
				false, // master_user.
351
				11, // user_id_query.
352
				false, // token_key_query.
353
				'token_malformed', // expected error code.
354
				false, // expected token.
355
			),
356
			'user mismatch'                    => array(
357
				false, // blog token.
358
				array(
359
					11 => 'asd.zxc.22',
360
				), // user tokens.
361
				false, // master_user.
362
				11, // user_id_query.
363
				false, // token_key_query.
364
				'user_id_mismatch', // expected error code.
365
				false, // expected token.
366
			),
367
			'Connection owner not defined'     => array(
368
				false, // blog token.
369
				array(
370
					11 => 'asd.zxc.11',
371
				), // user tokens.
372
				false, // master_user.
373
				'CONNECTION_OWNER', // user_id_query.
374
				false, // token_key_query.
375
				'empty_master_user_option', // expected error code.
376
				false, // expected token.
377
			),
378
			'Connection owner'                 => array(
379
				false, // blog token.
380
				array(
381
					11 => 'asd.zxc.11',
382
				), // user tokens.
383
				11, // master_user.
384
				'CONNECTION_OWNER', // user_id_query.
385
				false, // token_key_query.
386
				false, // expected error code.
387
				(object) array(
388
					'secret'           => 'asd.zxc',
389
					'external_user_id' => 11,
390
				), // expected token.
391
			),
392
			'Find blog token'                  => array(
393
				'asdasd.qweqwe', // blog token.
394
				false, // user tokens.
395
				false, // master_user.
396
				false, // user_id_query.
397
				false, // token_key_query.
398
				false, // expected error code.
399
				(object) array(
400
					'secret'           => 'asdasd.qweqwe',
401
					'external_user_id' => 0,
402
				), // expected token.
403
			),
404
			'Find user token'                  => array(
405
				false, // blog token.
406
				array(
407
					11 => 'qwe.asd.11',
408
					12 => 'asd.zxc.12',
409
				), // user tokens.
410
				false, // master_user.
411
				11, // user_id_query.
412
				false, // token_key_query.
413
				false, // expected error code.
414
				(object) array(
415
					'secret'           => 'qwe.asd',
416
					'external_user_id' => 11,
417
				), // expected token.
418
			),
419
			'Find user token with secret'      => array(
420
				false, // blog token.
421
				array(
422
					11 => 'qwe.asd.11',
423
					12 => 'asd.zxc.12',
424
				), // user tokens.
425
				false, // master_user.
426
				12, // user_id_query.
427
				'asd', // token_key_query.
428
				false, // expected error code.
429
				(object) array(
430
					'secret'           => 'asd.zxc',
431
					'external_user_id' => 12,
432
				), // expected token.
433
			),
434
			'Find blog token with secret'      => array(
435
				'asdasd.qweqwe', // blog token.
436
				false, // user tokens.
437
				false, // master_user.
438
				false, // user_id_query.
439
				'asdasd', // token_key_query.
440
				false, // expected error code.
441
				(object) array(
442
					'secret'           => 'asdasd.qweqwe',
443
					'external_user_id' => 0,
444
				), // expected token.
445
			),
446
			'Dont find user token with secret' => array(
447
				false, // blog token.
448
				array(
449
					11 => 'qwe.asd.11',
450
					12 => 'asd.zxc.12',
451
				), // user tokens.
452
				false, // master_user.
453
				12, // user_id_query.
454
				'qqq', // token_key_query.
455
				'no_valid_user_token', // expected error code.
456
				false, // expected token.
457
			),
458
			'Dont find blog token with secret' => array(
459
				'asdasd.qweqwe', // blog token.
460
				false, // user tokens.
461
				false, // master_user.
462
				false, // user_id_query.
463
				'kaasdas', // token_key_query.
464
				'no_valid_blog_token', // expected error code.
465
				false, // expected token.
466
			),
467
		);
468
	}
469
470
	/**
471
	 * Make sure we don´t change how we return errors
472
	 */
473
	public function test_get_access_token_suppress_errors() {
474
		$this->assertFalse( ( new Tokens() )->get_access_token( 123 ) );
475
		$this->assertInstanceOf( 'WP_Error', ( new Tokens() )->get_access_token( 123, '', false ) );
476
	}
477
478
	/**
479
	 * Test the `is_userless' method.
480
	 *
481
	 * @covers Automattic\Jetpack\Connection\Manager::is_userless
482
	 * @dataProvider data_provider_for_test_is_userless
483
	 *
484
	 * @param boolean $is_connected              If the blog is connected.
485
	 * @param boolean $has_connected_user        If the blog has a connected user.
486
	 * @param boolean $master_user_option_is_set If the master_user option is set.
487
	 * @param boolean $expected                  The expected output.
488
	 */
489
	public function test_is_userless( $is_connected, $has_connected_user, $master_user_option_is_set, $expected ) {
490
		$id_admin = wp_insert_user(
491
			array(
492
				'user_login' => 'admin',
493
				'user_pass'  => 'pass',
494
				'role'       => 'administrator',
495
			)
496
		);
497
498
		if ( $is_connected ) {
499
			\Jetpack_Options::update_option( 'id', 1234 );
500
			\Jetpack_Options::update_option( 'blog_token', 'asdasd.123123' );
501
		} else {
502
			\Jetpack_Options::delete_option( 'blog_token' );
503
			\Jetpack_Options::delete_option( 'id' );
504
		}
505
506
		if ( $has_connected_user ) {
507
			\Jetpack_Options::update_option(
508
				'user_tokens',
509
				array(
510
					$id_admin => 'asd123',
511
				)
512
			);
513
		} else {
514
			\Jetpack_Options::delete_option( 'user_tokens' );
515
		}
516
517
		if ( $master_user_option_is_set ) {
518
			\Jetpack_Options::update_option( 'master_user', $id_admin );
519
		} else {
520
			\Jetpack_Options::delete_option( 'master_user' );
521
		}
522
523
		$this->assertEquals( $expected, $this->manager->is_userless() );
524
	}
525
526
	/**
527
	 * Data provider for test_is_userless.
528
	 *
529
	 * Structure of the test data arrays:
530
	 *     [0] => 'is_connected'              boolean If the blog is connected.
531
	 *     [1] => 'has_connected_user'        boolean If the blog has a connected user.
532
	 *     [2] => 'master_user_option_is_set' boolean If the master_user option is set.
533
	 *     [3] => 'expected'                  boolean The expected output of the call to is_userless.
534
	 */
535
	public function data_provider_for_test_is_userless() {
536
537
		return array(
538
			'connected, has connected_user, master_user option is set'         => array( true, true, true, false ),
539
			'not connected, has connected_user, master_user option is set'     => array( false, true, true, false ),
540
			'connected, no connected_user, master_user option is set'          => array( true, false, true, false ),
541
			'not connected, no connected_user, master_user option is set'      => array( false, false, true, false ),
542
			'not connected, has connected_user, master_user option is not set' => array( false, true, false, false ),
543
			'not connected, no connected_user, master_user option is not set'  => array( false, false, false, false ),
544
			'connected, has connected_user, master_user option is not set'     => array( true, true, false, false ),
545
			'connected, no connected_user, master_user option is not set'      => array( true, false, false, true ),
546
		);
547
	}
548
549
	/**
550
	 * Test the `try_registration()` method.
551
	 *
552
	 * @see Manager::try_registration()
553
	 */
554
	public function test_try_registration() {
555
		add_filter( 'pre_http_request', array( Test_REST_Endpoints::class, 'intercept_register_request' ), 10, 3 );
556
		set_transient( 'jetpack_assumed_site_creation_date', '2021-01-01 01:01:01' );
557
		Constants::$set_constants['JETPACK__API_BASE'] = 'https://jetpack.wordpress.com/jetpack.';
558
559
		$result = $this->manager->try_registration();
560
561
		remove_filter( 'pre_http_request', array( Test_REST_Endpoints::class, 'intercept_register_request' ), 10 );
562
		delete_transient( 'jetpack_assumed_site_creation_date' );
563
564
		static::assertTrue( $result );
565
	}
566
567
	/**
568
	 * Test that User tokens behave according to expectations after attempting to disconnect a user.
569
	 *
570
	 * @covers Automattic\Jetpack\Connection\Manager::disconnect_user
571
	 * @dataProvider get_disconnect_user_outcomes
572
	 *
573
	 * @param bool $remote_response           Response from the unlink_user XML-RPC request.
574
	 * @param int  $expected_user_token_count Number of user tokens left on site after Manager::disconnect_user has completed.
575
	 */
576
	public function test_disconnect_user( $remote_response, $expected_user_token_count ) {
577
		$master_user_id = wp_insert_user(
578
			array(
579
				'user_login' => 'sample_user',
580
				'user_pass'  => 'asdqwe',
581
				'role'       => 'administrator',
582
			)
583
		);
584
		$editor_id      = wp_insert_user(
585
			array(
586
				'user_login' => 'editor',
587
				'user_pass'  => 'pass',
588
				'user_email' => '[email protected]',
589
				'role'       => 'editor',
590
			)
591
		);
592
593
		if ( $remote_response ) {
594
			$callback = 'intercept_disconnect_success';
595
		} else {
596
			$callback = 'intercept_disconnect_failure';
597
		}
598
599
		add_filter(
600
			'pre_http_request',
601
			array(
602
				$this,
603
				$callback,
604
			),
605
			10,
606
			3
607
		);
608
609
		\Jetpack_Options::update_option(
610
			'user_tokens',
611
			array(
612
				$master_user_id => sprintf( '%s.%s.%d', 'masterkey', 'private', $master_user_id ),
613
				$editor_id      => sprintf( '%s.%s.%d', 'editorkey', 'private', $editor_id ),
614
			)
615
		);
616
617
		$this->manager->disconnect_user( $editor_id );
618
619
		remove_filter(
620
			'pre_http_request',
621
			array(
622
				$this,
623
				$callback,
624
			),
625
			10,
626
			3
0 ignored issues
show
Unused Code introduced by
The call to remove_filter() has too many arguments starting with 3.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
627
		);
628
629
		$this->assertCount( $expected_user_token_count, $this->manager->get_connected_users() );
630
	}
631
632
	/**
633
	 * Intercept the disconnect user API request sent to WP.com, and mock success response.
634
	 *
635
	 * @param bool|array $response The existing response.
636
	 * @param array      $args The request arguments.
637
	 * @param string     $url The request URL.
638
	 *
639
	 * @return array
640
	 */
641 View Code Duplication
	public function intercept_disconnect_success( $response, $args, $url ) {
642
		if ( strpos( $url, 'https://jetpack.wordpress.com/xmlrpc.php' ) !== false ) {
643
			$response = array();
644
645
			$response['body'] = '
646
				<methodResponse>
647
					<params>
648
						<param>
649
							<value>1</value>
650
						</param>
651
					</params>
652
				</methodResponse>
653
			';
654
655
			$response['response']['code'] = 200;
656
			return $response;
657
		}
658
659
		return $response;
660
	}
661
662
	/**
663
	 * Intercept the disconnect user API request sent to WP.com, and mock success response.
664
	 *
665
	 * @param bool|array $response The existing response.
666
	 * @param array      $args The request arguments.
667
	 * @param string     $url The request URL.
668
	 *
669
	 * @return array
670
	 */
671 View Code Duplication
	public function intercept_disconnect_failure( $response, $args, $url ) {
672
		if ( strpos( $url, 'https://jetpack.wordpress.com/xmlrpc.php' ) !== false ) {
673
			$response = array();
674
675
			$response['body'] = '
676
				<methodResponse>
677
					<params>
678
						<param>
679
							<value>1</value>
680
						</param>
681
					</params>
682
				</methodResponse>
683
			';
684
685
			$response['response']['code'] = 500;
686
			return $response;
687
		}
688
689
		return $response;
690
	}
691
692
	/**
693
	 * Data for test_disconnect_user
694
	 *
695
	 * @return array
696
	 */
697
	public function get_disconnect_user_outcomes() {
698
		return array(
699
			'success' => array(
700
				true,
701
				1,
702
			),
703
			'failure' => array(
704
				false,
705
				2,
706
			),
707
		);
708
	}
709
}
710