1
|
|
|
<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase |
2
|
|
|
/** |
3
|
|
|
* Tokens functionality testing. |
4
|
|
|
* |
5
|
|
|
* @package automattic/jetpack-connection |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace Automattic\Jetpack\Connection; |
9
|
|
|
|
10
|
|
|
use Automattic\Jetpack\Constants; |
11
|
|
|
use PHPUnit\Framework\TestCase; |
12
|
|
|
use Requests_Utility_CaseInsensitiveDictionary; |
13
|
|
|
use WP_Error; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Tokens functionality testing. |
17
|
|
|
*/ |
18
|
|
|
class TokensTest extends TestCase { |
19
|
|
|
/** |
20
|
|
|
* Initialize the object before running the test method. |
21
|
|
|
* |
22
|
|
|
* @before |
23
|
|
|
*/ |
24
|
|
|
public function set_up() { |
25
|
|
|
$this->tokens = $this->getMockBuilder( 'Automattic\Jetpack\Connection\Tokens' ) |
26
|
|
|
->setMethods( array( 'get_access_token' ) ) |
27
|
|
|
->getMock(); |
28
|
|
|
} |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Clean up the testing environment. |
32
|
|
|
* |
33
|
|
|
* @after |
34
|
|
|
*/ |
35
|
|
|
public function tear_down() { |
36
|
|
|
remove_all_filters( 'jetpack_options' ); |
37
|
|
|
unset( $this->tokens ); |
38
|
|
|
Constants::clear_constants(); |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Test the `validate` functionality when the site is not registered. |
43
|
|
|
* |
44
|
|
|
* @covers Automattic\Jetpack\Connection\Tokens::validate |
45
|
|
|
*/ |
46
|
|
|
public function test_validate_when_site_is_not_registered() { |
47
|
|
|
$expected = new WP_Error( 'site_not_registered', 'Site not registered.' ); |
|
|
|
|
48
|
|
|
$this->assertEquals( $expected, $this->tokens->validate() ); |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Test the `validate` functionality when the current user is not connnected, aka user token is missing. |
53
|
|
|
* |
54
|
|
|
* @covers Automattic\Jetpack\Connection\Tokens::validate |
55
|
|
|
*/ |
56
|
|
|
public function test_validate_with_missing_user_token() { |
57
|
|
|
add_filter( |
58
|
|
|
'jetpack_options', |
59
|
|
|
function ( $value, $name ) { |
60
|
|
|
return 'id' === $name ? 123 : $value; |
61
|
|
|
}, |
62
|
|
|
10, |
63
|
|
|
2 |
64
|
|
|
); |
65
|
|
|
$blog_token = (object) array( |
66
|
|
|
'secret' => 'abcd.1234', |
67
|
|
|
'external_user_id' => null, |
68
|
|
|
); |
69
|
|
|
|
70
|
|
|
$user_token = false; |
71
|
|
|
|
72
|
|
|
$this->tokens->expects( $this->exactly( 2 ) ) |
73
|
|
|
->method( 'get_access_token' ) |
74
|
|
|
->will( $this->onConsecutiveCalls( $blog_token, $user_token ) ); |
75
|
|
|
$this->assertFalse( $this->tokens->validate() ); |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* Test the `validate` functionality when the remote request to the `jetpack-token-health` endpoint fails. |
80
|
|
|
* |
81
|
|
|
* @covers Automattic\Jetpack\Connection\Tokens::validate |
82
|
|
|
*/ |
83
|
|
|
public function test_validate_with_failed_remote_request() { |
84
|
|
|
add_filter( |
85
|
|
|
'jetpack_options', |
86
|
|
|
function ( $value, $name ) { |
87
|
|
|
return 'id' === $name ? 123 : $value; |
88
|
|
|
}, |
89
|
|
|
10, |
90
|
|
|
2 |
91
|
|
|
); |
92
|
|
|
add_filter( 'pre_http_request', array( $this, 'intercept_jetpack_token_health_request_failed' ), 10, 3 ); |
93
|
|
|
$blog_token = (object) array( |
94
|
|
|
'secret' => 'abcd.1234', |
95
|
|
|
'external_user_id' => null, |
96
|
|
|
); |
97
|
|
|
|
98
|
|
|
$user_token = (object) array( |
99
|
|
|
'secret' => 'abcd.4321', |
100
|
|
|
'external_user_id' => 1, |
101
|
|
|
); |
102
|
|
|
|
103
|
|
|
$this->tokens->expects( $this->exactly( 2 ) ) |
104
|
|
|
->method( 'get_access_token' ) |
105
|
|
|
->will( $this->onConsecutiveCalls( $blog_token, $user_token ) ); |
106
|
|
|
|
107
|
|
|
$this->assertFalse( $this->tokens->validate() ); |
108
|
|
|
|
109
|
|
|
remove_filter( 'pre_http_request', array( $this, 'intercept_jetpack_token_health_request_failed' ), 10 ); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Test the `validate` functionality when the remote request to the `jetpack-token-health` endpoint succeeds. |
114
|
|
|
* |
115
|
|
|
* @covers Automattic\Jetpack\Connection\Tokens::validate |
116
|
|
|
*/ |
117
|
|
|
public function test_validate() { |
118
|
|
|
add_filter( |
119
|
|
|
'jetpack_options', |
120
|
|
|
function ( $value, $name ) { |
121
|
|
|
return 'id' === $name ? 123 : $value; |
122
|
|
|
}, |
123
|
|
|
10, |
124
|
|
|
2 |
125
|
|
|
); |
126
|
|
|
add_filter( 'pre_http_request', array( $this, 'intercept_jetpack_token_health_request_success' ), 10, 3 ); |
127
|
|
|
$blog_token = (object) array( |
128
|
|
|
'secret' => 'abcd.1234', |
129
|
|
|
'external_user_id' => null, |
130
|
|
|
); |
131
|
|
|
|
132
|
|
|
$user_token = (object) array( |
133
|
|
|
'secret' => 'abcd.4321', |
134
|
|
|
'external_user_id' => 1, |
135
|
|
|
); |
136
|
|
|
|
137
|
|
|
$this->tokens->expects( $this->exactly( 2 ) ) |
138
|
|
|
->method( 'get_access_token' ) |
139
|
|
|
->will( $this->onConsecutiveCalls( $blog_token, $user_token ) ); |
140
|
|
|
|
141
|
|
|
$expected = array( |
142
|
|
|
'blog_token' => array( |
143
|
|
|
'is_healthy' => true, |
144
|
|
|
), |
145
|
|
|
'user_token' => array( |
146
|
|
|
'is_healthy' => true, |
147
|
|
|
'is_master_user' => true, |
148
|
|
|
), |
149
|
|
|
); |
150
|
|
|
$this->assertSame( $expected, $this->tokens->validate() ); |
151
|
|
|
|
152
|
|
|
remove_filter( 'pre_http_request', array( $this, 'intercept_jetpack_token_health_request_success' ), 10 ); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
/** |
156
|
|
|
* Test the `get_signed_token` functionality. |
157
|
|
|
* |
158
|
|
|
* @covers Automattic\Jetpack\Connection\Tokens::get_signed_token |
159
|
|
|
*/ |
160
|
|
View Code Duplication |
public function test_get_signed_token() { |
161
|
|
|
$access_token = (object) array( |
162
|
|
|
'external_user_id' => 1, |
163
|
|
|
); |
164
|
|
|
|
165
|
|
|
// Missing secret. |
166
|
|
|
$invalid_token_error = new WP_Error( 'invalid_token' ); |
|
|
|
|
167
|
|
|
$this->assertEquals( $invalid_token_error, ( new Tokens() )->get_signed_token( $access_token ) ); |
168
|
|
|
// Secret is null. |
169
|
|
|
$access_token->secret = null; |
170
|
|
|
$this->assertEquals( $invalid_token_error, ( new Tokens() )->get_signed_token( $access_token ) ); |
171
|
|
|
// Secret is empty. |
172
|
|
|
$access_token->secret = ''; |
173
|
|
|
$this->assertEquals( $invalid_token_error, ( new Tokens() )->get_signed_token( $access_token ) ); |
174
|
|
|
// Valid secret. |
175
|
|
|
$access_token->secret = 'abcd.1234'; |
176
|
|
|
|
177
|
|
|
$signed_token = ( new Tokens() )->get_signed_token( $access_token ); |
178
|
|
|
$this->assertTrue( strpos( $signed_token, 'token' ) !== false ); |
179
|
|
|
$this->assertTrue( strpos( $signed_token, 'timestamp' ) !== false ); |
180
|
|
|
$this->assertTrue( strpos( $signed_token, 'nonce' ) !== false ); |
181
|
|
|
$this->assertTrue( strpos( $signed_token, 'signature' ) !== false ); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Intercept the `jetpack-token-health` API request sent to WP.com, and mock failed response. |
186
|
|
|
* |
187
|
|
|
* @param bool|array $response The existing response. |
188
|
|
|
* @param array $args The request arguments. |
189
|
|
|
* @param string $url The request URL. |
190
|
|
|
* |
191
|
|
|
* @return array |
192
|
|
|
*/ |
193
|
|
View Code Duplication |
public function intercept_jetpack_token_health_request_failed( $response, $args, $url ) { |
194
|
|
|
if ( false === strpos( $url, 'jetpack-token-health' ) ) { |
195
|
|
|
return $response; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
return array( |
199
|
|
|
'headers' => new Requests_Utility_CaseInsensitiveDictionary( array( 'content-type' => 'application/json' ) ), |
200
|
|
|
'body' => wp_json_encode( array( 'dummy_error' => true ) ), |
201
|
|
|
'response' => array( |
202
|
|
|
'code' => 500, |
203
|
|
|
'message' => 'failed', |
204
|
|
|
), |
205
|
|
|
); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* Intercept the `jetpack-token-health` API request sent to WP.com, and mock successful response. |
210
|
|
|
* |
211
|
|
|
* @param bool|array $response The existing response. |
212
|
|
|
* @param array $args The request arguments. |
213
|
|
|
* @param string $url The request URL. |
214
|
|
|
* |
215
|
|
|
* @return array |
216
|
|
|
*/ |
217
|
|
|
public function intercept_jetpack_token_health_request_success( $response, $args, $url ) { |
218
|
|
|
if ( false === strpos( $url, 'jetpack-token-health' ) ) { |
219
|
|
|
return $response; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
$body = array( |
223
|
|
|
'blog_token' => array( |
224
|
|
|
'is_healthy' => true, |
225
|
|
|
), |
226
|
|
|
'user_token' => array( |
227
|
|
|
'is_healthy' => true, |
228
|
|
|
'is_master_user' => true, |
229
|
|
|
), |
230
|
|
|
); |
231
|
|
|
|
232
|
|
|
return array( |
233
|
|
|
'headers' => new Requests_Utility_CaseInsensitiveDictionary( array( 'content-type' => 'application/json' ) ), |
234
|
|
|
'body' => wp_json_encode( $body ), |
235
|
|
|
'response' => array( |
236
|
|
|
'code' => 200, |
237
|
|
|
'message' => 'OK', |
238
|
|
|
), |
239
|
|
|
); |
240
|
|
|
} |
241
|
|
|
} |
242
|
|
|
|
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.