Completed
Push — try/package-button-block ( 063e81 )
by
unknown
110:43 queued 103:17
created

WP_Test_Jetpack_Gutenberg::provider_invalid_urls()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
class WP_Test_Jetpack_Gutenberg extends WP_UnitTestCase {
4
5
	public $master_user_id = false;
6
7
	public function setUp() {
8
		parent::setUp();
9
		if ( ! function_exists( 'register_block_type' ) ) {
10
			$this->markTestSkipped( 'register_block_type not available' );
11
			return;
12
		}
13
14
		if ( ! class_exists( 'WP_Block_Type_Registry' ) ) {
15
			$this->markTestSkipped( 'WP_Block_Type_Registry not available' );
16
			return;
17
		}
18
		// Create a user and set it up as current.
19
		$this->master_user_id = $this->factory->user->create( array( 'user_login' => 'current_master' ) );
20
		// Mock a connection
21
		Jetpack_Options::update_option( 'master_user', $this->master_user_id );
22
		Jetpack_Options::update_option( 'user_tokens', array( $this->master_user_id => "honey.badger.$this->master_user_id" ) );
23
24
		add_filter( 'jetpack_set_available_extensions', array( __CLASS__, 'get_extensions_whitelist' ) );
25
		delete_option( 'jetpack_excluded_extensions' );
26
27
		// These action causing issues in tests in WPCOM context. Since we are not using any real block here,
28
		// and we are testing block availability with block stubs - we are safe to remove these actions for these tests.
29
		remove_all_actions( 'jetpack_register_gutenberg_extensions' );
30
		Jetpack_Gutenberg::init();
31
	}
32
33
	public function tearDown() {
34
		parent::tearDown();
35
36
		Jetpack_Gutenberg::reset();
37
		remove_filter( 'jetpack_set_available_extensions', array( __CLASS__, 'get_extensions_whitelist' ) );
38
39
		if ( $this->master_user_id ) {
40
			Jetpack_Options::delete_option( array( 'master_user', 'user_tokens' ) );
41
			wp_delete_user( $this->master_user_id );
42
		}
43
44
		if ( class_exists( 'WP_Block_Type_Registry' ) ) {
45
			$blocks = WP_Block_Type_Registry::get_instance()->get_all_registered();
46
			foreach ( $blocks as $block_name => $block ) {
47
				if ( wp_startswith( $block_name, 'jetpack/' ) ) {
48
					unregister_block_type( $block_name );
49
				}
50
			}
51
		}
52
	}
53
54
	public static function get_extensions_whitelist() {
55
		return array(
56
			// Our "Blocks" :)
57
			'apple',
58
			'banana',
59
			'coconut',
60
			'grape',
61
			// Our "Plugins" :)
62
			'onion',
63
			'potato',
64
			'tomato'
65
		);
66
	}
67
68
	/**
69
	 * This test will throw an exception/fail if blocks register twice upon repeat calls to get_availability()
70
	 */
71
	function test_does_calling_get_availability_twice_result_in_notice() {
72
		add_action( 'jetpack_register_gutenberg_extensions', array( $this, 'register_block') );
73
		Jetpack_Gutenberg::get_availability();
74
		Jetpack_Gutenberg::get_availability();
75
		$result = remove_action( 'jetpack_register_gutenberg_extensions', array( $this, 'register_block') );
76
		$this->assertTrue( $result );
77
	}
78
79
	function register_block() {
80
		jetpack_register_block( 'jetpack/apple' );
81
	}
82
83
	function test_registered_block_is_available() {
84
		jetpack_register_block( 'jetpack/apple' );
85
		$availability = Jetpack_Gutenberg::get_availability();
86
		$this->assertTrue( $availability['apple']['available'] );
87
	}
88
89 View Code Duplication
	function test_registered_block_is_not_available() {
90
		Jetpack_Gutenberg::set_extension_unavailable( 'jetpack/banana', 'bar' );
91
		$availability = Jetpack_Gutenberg::get_availability();
92
		$this->assertFalse( $availability['banana']['available'], 'banana is available!' );
93
		$this->assertEquals( $availability['banana']['unavailable_reason'], 'bar', 'unavailable_reason is not "bar"' );
94
	}
95
96
	function test_registered_block_is_not_available_when_not_defined_in_whitelist() {
97
		jetpack_register_block( 'jetpack/durian' );
98
		$availability = Jetpack_Gutenberg::get_availability();
99
		$this->assertArrayNotHasKey( 'durian', $availability, 'durian is available!' );
100
	}
101
102 View Code Duplication
	function test_block_is_not_available_when_not_registered_returns_missing_module() {
103
		$availability = Jetpack_Gutenberg::get_availability();
104
105
		// 'unavailable_reason' should be 'missing_module' if the block wasn't registered
106
		$this->assertFalse( $availability['grape']['available'], 'Availability is not false exists' );
107
		$this->assertEquals( $availability['grape']['unavailable_reason'], 'missing_module', 'unavailable_reason is not "missing_module"'  );
108
	}
109
110
	// Plugins
111
	function test_registered_plugin_is_available() {
112
		Jetpack_Gutenberg::set_extension_available( 'jetpack/onion' );
113
		$availability = Jetpack_Gutenberg::get_availability();
114
		$this->assertTrue( $availability['onion']['available'] );
115
	}
116
117 View Code Duplication
	function test_registered_plugin_is_not_available() {
118
		Jetpack_Gutenberg::set_extension_unavailable( 'jetpack/potato', 'bar' );
119
		$availability = Jetpack_Gutenberg::get_availability();
120
		$this->assertFalse( $availability['potato']['available'], 'potato is available!' );
121
		$this->assertEquals( $availability['potato']['unavailable_reason'], 'bar', 'unavailable_reason is not "bar"' );
122
	}
123
124
	function test_registered_plugin_is_not_available_when_not_defined_in_whitelist() {
125
		Jetpack_Gutenberg::set_extension_available( 'jetpack/parsnip' );
126
		$availability = Jetpack_Gutenberg::get_availability();
127
		$this->assertArrayNotHasKey( 'parsnip', $availability, 'parsnip is available!' );
128
129
	}
130
131 View Code Duplication
	function test_plugin_is_not_available_when_not_registered_returns_missing_module() {
132
		$availability = Jetpack_Gutenberg::get_availability();
133
134
		// 'unavailable_reason' should be 'missing_module' if the block wasn't registered
135
		$this->assertFalse( $availability['tomato']['available'], 'Availability is not false exists' );
136
		$this->assertEquals( $availability['tomato']['unavailable_reason'], 'missing_module', 'unavailable_reason is not "missing_module"'  );
137
	}
138
139
	function test_get_available_extensions() {
140
		$extensions = Jetpack_Gutenberg::get_available_extensions( $this->get_extensions_whitelist() );
141
		$this->assertInternalType( 'array', $extensions );
142
		$this->assertNotEmpty( $extensions );
143
		$this->assertContains( 'onion', $extensions );
144
145
		update_option( 'jetpack_excluded_extensions', array( 'onion' ) );
146
147
		$extensions = Jetpack_Gutenberg::get_available_extensions( $this->get_extensions_whitelist() );
148
		$this->assertInternalType( 'array', $extensions );
149
		$this->assertNotEmpty( $extensions );
150
		$this->assertNotContains( 'onion', $extensions );
151
	}
152
153
	function test_returns_false_if_core_wp_version_less_than_minimum() {
154
		$version_gated = Jetpack_Gutenberg::is_gutenberg_version_available(
155
			array(
156
				'wp'        => '999999',
157
				'gutenberg' => '999999',
158
			),
159
			'gated_block'
160
		);
161
		$this->assertEquals( false, $version_gated );
162
	}
163
164
	/**
165
	 * Tests whether the environment has the minimum Gutenberg/WordPress installation needed by a block
166
	 */
167
	public function test_returns_true_if_gutenberg_or_core_wp_version_greater_or_equal_to_minimum() {
168
		$version_gated = Jetpack_Gutenberg::is_gutenberg_version_available(
169
			array(
170
				'wp'        => '1',
171
				'gutenberg' => '1',
172
			),
173
			'ungated_block'
174
		);
175
		$this->assertEquals( true, $version_gated );
176
	}
177
178
	/**
179
	 * Test that known invalid urls are normalized during validation.
180
	 *
181
	 * @dataProvider provider_invalid_urls
182
	 *
183
	 * @param string $url               Original URL.
184
	 * @param string $validated_url     Expected URL after validation.
185
	 */
186
	public function test_validate_normalizes_invalid_domain_url( $url, $validated_url ) {
187
		$allowed_hosts = array( 'calendar.google.com' );
188
189
		$url = Jetpack_Gutenberg::validate_block_embed_url( $url, $allowed_hosts );
190
191
		$this->assertEquals( $validated_url, $url );
192
	}
193
194
	/**
195
	 * Provides Original URL and Expected Validated URL values.
196
	 *
197
	 * @return array Array of Test Data
198
	 */
199
	public function provider_invalid_urls() {
200
		return array(
201
			array(
202
				'https://calendar.google.com#@evil.com',
203
				'https://calendar.google.com/#%40evil.com',
204
			),
205
			array(
206
				'https://[email protected]:[email protected]',
207
				'https://calendar.google.com/',
208
			),
209
			array(
210
				'https://[email protected] @calendar.google.com',
211
				'https://calendar.google.com/',
212
			),
213
			array(
214
				'https://calendar.google.com/\xFF\x2E\xFF\x2E/passwd',
215
				'https://calendar.google.com/\xFF\x2E\xFF\x2E/passwd',
216
			),
217
		);
218
	}
219
220
	/**
221
	 * Tests whether a third-party domain can be used in a block.
222
	 */
223 View Code Duplication
	public function test_validate_block_embed_third_party_url() {
224
		$url           = 'https://example.org';
225
		$allowed_hosts = array( 'wordpress.com' );
226
227
		$validated_url = Jetpack_Gutenberg::validate_block_embed_url( $url, $allowed_hosts );
228
229
		$this->assertFalse( $validated_url );
230
	}
231
232
	/**
233
	 * Tests whether a random string (not a URL) can be used in a block.
234
	 */
235
	public function test_validate_block_embed_string() {
236
		$url           = 'apple';
237
		$allowed_hosts = array( 'wordpress.com' );
238
239
		$validated_url = Jetpack_Gutenberg::validate_block_embed_url( $url, $allowed_hosts );
240
241
		$this->assertFalse( $validated_url );
242
	}
243
244
	/**
245
	 * Tests whether a schemeless URL can be used in a block.
246
	 */
247 View Code Duplication
	public function test_validate_block_embed_scheme() {
248
		$url           = 'wordpress.com';
249
		$allowed_hosts = array( 'wordpress.com' );
250
251
		$validated_url = Jetpack_Gutenberg::validate_block_embed_url( $url, $allowed_hosts );
252
253
		$this->assertFalse( $validated_url );
254
	}
255
256
	/**
257
	 * Tests whether a URL belonging to a whitelisted list can be used in a block.
258
	 */
259 View Code Duplication
	public function test_validate_block_embed_url() {
260
		$url           = 'https://wordpress.com/tos/';
261
		$allowed_hosts = array( 'wordpress.com' );
262
263
		$validated_url = Jetpack_Gutenberg::validate_block_embed_url( $url, $allowed_hosts );
264
265
		$this->assertEquals( $url, $validated_url );
266
	}
267
268
	/**
269
	 * Tests whether a URL matches a specific regex.
270
	 */
271 View Code Duplication
	public function test_validate_block_embed_regex() {
272
		$url     = 'https://wordpress.com/tos/';
273
		$allowed = array( '#^https?:\/\/(www.)?wordpress\.com(\/)?([^\/]+)?(\/)?$#' );
274
275
		$validated_url = Jetpack_Gutenberg::validate_block_embed_url( $url, $allowed, true );
276
277
		$this->assertEquals( $url, $validated_url );
278
	}
279
280
	/**
281
	 * Tests whether a URL does not match a specific regex.
282
	 */
283 View Code Duplication
	public function test_validate_block_embed_regex_mismatch() {
284
		$url     = 'https://www.facebook.com/WordPresscom/';
285
		$allowed = array( '#^https?:\/\/(www.)?wordpress\.com(\/)?([^\/]+)?(\/)?$#' );
286
287
		$validated_url = Jetpack_Gutenberg::validate_block_embed_url( $url, $allowed, true );
288
289
		$this->assertFalse( $validated_url );
290
	}
291
}
292