Completed
Push — try/e2e-check-if-chrome-instal... ( 24dbcf...296824 )
by Yaroslav
23:03 queued 13:54
created

WP_Test_Lazy_Images::test_process_image()   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 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3
require __DIR__ . '/../../src/lazy-images.php';
4
5
use Automattic\Jetpack\Jetpack_Lazy_Images;
6
use WorDBless\BaseTestCase;
7
8
/**
9
 * Class WP_Test_Lazy_Images
10
 */
11
class WP_Test_Lazy_Images extends BaseTestCase {
12
	use \Yoast\PHPUnitPolyfills\Polyfills\AssertStringContains;
13
14
	/**
15
	 * Setup.
16
	 *
17
	 * @before
18
	 */
19
	public function set_up() {
20
		add_filter( 'lazyload_images_placeholder_image', array( $this, 'override_image_placeholder' ) );
21
	}
22
23
	/**
24
	 * Data provider for test.
25
	 *
26
	 * @return array
27
	 */
28
	public function get_process_image_test_data() {
29
		return array(
30
			'img_with_no_src'           => array(
31
				array(
32
					'<img id="img" />',
33
					'img',
34
					' id="img"',
35
				),
36
				'<img id="img" />',
37
			),
38
			'img_simple'                => array(
39
				array(
40
					'<img src="image.jpg" />',
41
					'img',
42
					' src="image.jpg"',
43
				),
44
				'<img src="image.jpg" data-lazy-src="http://image.jpg?is-pending-load=1" srcset="placeholder.jpg" class=" jetpack-lazy-image"><noscript><img src="image.jpg" /></noscript>',
45
			),
46
			'img_with_other_attributes' => array(
47
				array(
48
					'<img src="image.jpg" alt="Alt!" />',
49
					'img',
50
					' src="image.jpg" alt="Alt!"',
51
				),
52
				'<img src="image.jpg" alt="Alt!" data-lazy-src="http://image.jpg?is-pending-load=1" srcset="placeholder.jpg" class=" jetpack-lazy-image"><noscript><img src="image.jpg" alt="Alt!" /></noscript>',
53
			),
54
			'img_with_srcset'           => array(
55
				array(
56
					'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" />',
57
					'img',
58
					' src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w"',
59
60
				),
61
				'<img src="image.jpg" data-lazy-srcset="medium.jpg 1000w, large.jpg 2000w" data-lazy-src="http://image.jpg?is-pending-load=1" srcset="placeholder.jpg" class=" jetpack-lazy-image"><noscript><img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" /></noscript>',
62
			),
63
			'img_with_sizes'            => array(
64
				array(
65
					'<img src="image.jpg" sizes="(min-width: 36em) 33.3vw, 100vw" />',
66
					'img',
67
					' src="image.jpg" sizes="(min-width: 36em) 33.3vw, 100vw"',
68
69
				),
70
				'<img src="image.jpg" data-lazy-sizes="(min-width: 36em) 33.3vw, 100vw" data-lazy-src="http://image.jpg?is-pending-load=1" srcset="placeholder.jpg" class=" jetpack-lazy-image"><noscript><img src="image.jpg" sizes="(min-width: 36em) 33.3vw, 100vw" /></noscript>',
71
			),
72
		);
73
	}
74
75
	/**
76
	 * Data provider for test.
77
	 *
78
	 * @return array
79
	 */
80
	public function get_process_image_attributes_data() {
81
		return array(
82
			'img_with_no_src'              => array(
83
				array(
84
					'width'  => 10,
85
					'height' => 10,
86
				),
87
				array(
88
					'width'  => 10,
89
					'height' => 10,
90
				),
91
			),
92
			'img_simple'                   => array(
93
				array(
94
					'src'    => 'image.jpg',
95
					'width'  => 10,
96
					'height' => 10,
97
				),
98
				array(
99
					'src'           => 'image.jpg',
100
					'width'         => 10,
101
					'height'        => 10,
102
					'data-lazy-src' => 'http://image.jpg?is-pending-load=1',
103
					'srcset'        => 'placeholder.jpg',
104
					'class'         => ' jetpack-lazy-image',
105
				),
106
			),
107
			'img_with_srcset'              => array(
108
				array(
109
					'src'    => 'image.jpg',
110
					'width'  => 10,
111
					'height' => 10,
112
					'srcset' => 'medium.jpg 1000w, large.jpg 2000w',
113
				),
114
				array(
115
					'src'              => 'image.jpg',
116
					'width'            => 10,
117
					'height'           => 10,
118
					'data-lazy-srcset' => 'medium.jpg 1000w, large.jpg 2000w',
119
					'data-lazy-src'    => 'http://image.jpg?is-pending-load=1',
120
					'srcset'           => 'placeholder.jpg',
121
					'class'            => ' jetpack-lazy-image',
122
				),
123
			),
124
			'img_with_sizes'               => array(
125
				array(
126
					'src'    => 'image.jpg',
127
					'width'  => 10,
128
					'height' => 10,
129
					'sizes'  => '(min-width: 36em) 33.3vw, 100vw',
130
				),
131
				array(
132
					'src'             => 'image.jpg',
133
					'width'           => 10,
134
					'height'          => 10,
135
					'data-lazy-sizes' => '(min-width: 36em) 33.3vw, 100vw',
136
					'data-lazy-src'   => 'http://image.jpg?is-pending-load=1',
137
					'srcset'          => 'placeholder.jpg',
138
					'class'           => ' jetpack-lazy-image',
139
				),
140
			),
141
			'gazette_theme_featured_image' => array(
142
				array(
143
					'src'    => 'image.jpg',
144
					'width'  => 10,
145
					'height' => 10,
146
					'class'  => 'attachment-gazette-featured-content-thumbnail wp-post-image',
147
				),
148
				// Should be unmodified.
149
				array(
150
					'src'    => 'image.jpg',
151
					'width'  => 10,
152
					'height' => 10,
153
					'class'  => 'attachment-gazette-featured-content-thumbnail wp-post-image',
154
				),
155
			),
156
		);
157
	}
158
159
	/**
160
	 * Test the process image attribute filter.
161
	 */
162
	public function test_process_image_attribute_filter() {
163
		add_filter( 'jetpack_lazy_images_new_attributes', array( $this, 'set_height_attribute' ) );
164
165
		$html = Jetpack_Lazy_Images::process_image(
166
			array(
167
				'<img src="image.jpg" height="100px" />',
168
				'img',
169
				' src="image.jpg" height="100px"',
170
			)
171
		);
172
173
		remove_filter( 'jetpack_lazy_images_new_attributes', array( $this, 'set_height_attribute' ) );
174
175
		$this->assertStringContainsString( 'style="height: 100px;"', $html );
176
	}
177
178
	/**
179
	 * Create a upload
180
	 *
181
	 * @param string  $file File path.
182
	 * @param integer $parent Parent post ID.
183
	 * @return integer
184
	 */
185
	public function create_upload_object( $file, $parent = 0 ) {
186
		$contents = file_get_contents( $file ); //phpcs:ignore
187
		$upload   = wp_upload_bits( basename( $file ), null, $contents );
188
189
		$type = '';
190
		if ( ! empty( $upload['type'] ) ) {
191
			$type = $upload['type'];
192
		} else {
193
			$mime = wp_check_filetype( $upload['file'], null );
194
			if ( $mime ) {
195
				$type = $mime['type'];
196
			}
197
		}
198
199
		$attachment = array(
200
			'post_title'     => basename( $upload['file'] ),
201
			'post_content'   => '',
202
			'post_type'      => 'attachment',
203
			'post_parent'    => $parent,
204
			'post_mime_type' => $type,
205
			'guid'           => $upload['url'],
206
		);
207
208
		// Save the data.
209
210
		$id = wp_insert_attachment( $attachment, $upload['file'], $parent );
211
212
		wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) );
213
214
		return $id;
215
	}
216
217
	/**
218
	 * Test that the wp_get_attachment_image function output gets the lazy treatment.
219
	 */
220
	public function test_wp_get_attachment_image_gets_lazy_treatment() {
221
222
		// @todo Remove when WordPress 5.6 is the minimum supported version.
223
		if ( ! function_exists( 'is_gd_image' ) && version_compare( PHP_VERSION, '8.0', '>=' ) ) {
224
			$editor = wp_get_image_editor( __DIR__ . '/wp-logo.jpg' );
225
			if ( is_wp_error( $editor ) ) {
226
				$this->markTestSkipped( 'WordPress <5.6 does not properly support the ext-gd in PHP 8.0+' );
227
			}
228
		}
229
230
		$attachment_id = $this->create_upload_object( __DIR__ . '/wp-logo.jpg', 0 );
231
		add_filter( 'wp_get_attachment_image_attributes', array( 'Automattic\\Jetpack\\Jetpack_Lazy_Images', 'process_image_attributes' ), PHP_INT_MAX );
232
		$image = wp_get_attachment_image( $attachment_id );
233
		remove_filter( 'wp_get_attachment_image_attributes', array( 'Automattic\\Jetpack\\Jetpack_Lazy_Images', 'process_image_attributes' ), PHP_INT_MAX );
234
235
		$this->assertStringContainsString( 'srcset="placeholder.jpg"', $image );
236
		$this->assertStringContainsString(
237
			sprintf( 'data-lazy-srcset="%s"', wp_get_attachment_image_srcset( $attachment_id, 'thumbnail' ) ),
238
			$image
239
		);
240
		// phpcs:enable
241
	}
242
243
	/**
244
	 * Test that the wp_get_attachment_image function output does not get the lazy treatment when lazy images feature is skipped.
245
	 */
246
	public function test_wp_get_attachment_image_does_not_get_lazy_treatment_when_skip_lazy_added() {
247
		$attachment_id = $this->create_upload_object( __DIR__ . '/wp-logo.jpg', 0 );
248
		$instance      = Jetpack_Lazy_Images::instance();
249
250
		$instance->setup_filters();
251
		add_filter( 'wp_get_attachment_image_attributes', array( $this, 'add_skip_lazy_class_to_attributes' ) );
252
		$image = wp_get_attachment_image( $attachment_id );
253
		remove_filter( 'wp_get_attachment_image_attributes', array( $this, 'add_skip_lazy_class_to_attributes' ) );
254
		$instance->remove_filters();
255
256
		$this->assertStringNotContainsString( 'srcset="placeholder.jpg"', $image );
257
	}
258
259
	/**
260
	 * Test the process_image method.
261
	 *
262
	 * @param array  $image_parts   Image parts.
263
	 * @param string $expected_html Expected HTML.
264
	 *
265
	 * @dataProvider get_process_image_test_data
266
	 */
267
	public function test_process_image( $image_parts, $expected_html ) {
268
		$actual_html = Jetpack_Lazy_Images::process_image( $image_parts );
269
270
		$this->assertEquals( $expected_html, $actual_html );
271
	}
272
273
	/**
274
	 * Test the add_image_placeholders method.
275
	 */
276
	public function test_add_image_placeholders() {
277
		$this->assertSame( $this->get_output_content(), Jetpack_Lazy_Images::instance()->add_image_placeholders( $this->get_input_content() ) );
278
	}
279
280
	/**
281
	 * Test the process_image_attributes method.
282
	 *
283
	 * @param array $input           Input attributes.
284
	 * @param array $expected_output Expected output.
285
	 *
286
	 * @dataProvider get_process_image_attributes_data
287
	 */
288
	public function test_process_image_attributes( $input, $expected_output ) {
289
		$this->assertSame( Jetpack_Lazy_Images::process_image_attributes( $input ), $expected_output );
290
	}
291
292
	/**
293
	 * Test that images with classes are not processed.
294
	 *
295
	 * @param string $input       Input content.
296
	 * @param bool   $should_skip Whether or not it lazy images treatment should be skipped.
297
	 *
298
	 * @dataProvider get_dont_process_images_with_classes_data
299
	 */
300 View Code Duplication
	public function test_dont_process_images_with_classes( $input, $should_skip = true ) {
301
		$instance = Jetpack_Lazy_Images::instance();
302
		$output   = $instance->add_image_placeholders( $input );
303
304
		if ( $should_skip ) {
305
			$this->assertStringNotContainsString( 'srcset="placeholder.jpg"', $output );
306
		} else {
307
			$this->assertStringContainsString( 'srcset="placeholder.jpg"', $output );
308
		}
309
	}
310
311
	/**
312
	 * Data provider for test.
313
	 *
314
	 * @return array
315
	 */
316
	public function get_dont_process_images_with_classes_data() {
317
		return array(
318
			'skip_lazy'                    => array(
319
				'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" class="skip-lazy"/>',
320
			),
321
			'gazette_theme_featured_image' => array(
322
				'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" class="attachment-gazette-featured-content-thumbnail wp-post-image"/>',
323
			),
324
			'does_not-skip'                => array(
325
				'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" class="wp-post-image"/>',
326
				false,
327
			),
328
		);
329
	}
330
331
	/**
332
	 * Test that images with the skip lazy data attribute are skipped.
333
	 *
334
	 * @param string $input       Input content.
335
	 * @param bool   $should_skip Whether or not it lazy images treatment should be skipped.
336
	 *
337
	 * @dataProvider get_dont_process_images_with_skip_lazy_data_attribute_data
338
	 */
339 View Code Duplication
	public function test_dont_process_images_with_skip_lazy_data_attribute( $input, $should_skip = true ) {
340
		$instance = Jetpack_Lazy_Images::instance();
341
		$output   = $instance->add_image_placeholders( $input );
342
343
		if ( $should_skip ) {
344
			$this->assertStringNotContainsString( 'srcset="placeholder.jpg"', $output );
345
		} else {
346
			$this->assertStringContainsString( 'srcset="placeholder.jpg"', $output );
347
		}
348
	}
349
350
	/**
351
	 * Data provider for test.
352
	 *
353
	 * @return array
354
	 */
355
	public function get_dont_process_images_with_skip_lazy_data_attribute_data() {
356
		return array(
357
			'skip_lazy_attr_only' => array(
358
				'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" data-skip-lazy/>',
359
			),
360
			'skip-lazy-attr-true' => array(
361
				'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" data-skip-lazy="true"/>',
362
			),
363
			'skip-lazy-attr-1'    => array(
364
				'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" data-skip-lazy="1"/>',
365
			),
366
		);
367
	}
368
369
	/**
370
	 * Test that images with the blocked class should be skipped
371
	 *
372
	 * @param bool   $expected Expected result.
373
	 * @param string $input  A string of space-separated classes.
374
	 * @param bool   $empty_blocked_classes Empty block classes.
375
	 *
376
	 * @dataProvider get_should_skip_image_with_blocked_class_data
377
	 */
378
	public function test_should_skip_image_with_blocked_class( $expected, $input, $empty_blocked_classes = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
379
		$this->assertSame( $expected, Jetpack_Lazy_Images::should_skip_image_with_blocked_class( $input ) );
380
	}
381
382
	/**
383
	 * Data provider for test.
384
	 *
385
	 * @return array
386
	 */
387
	public function get_should_skip_image_with_blocked_class_data() {
388
		return array(
389
			'wp-post-image'   => array(
390
				false,
391
				'wp-post-image',
392
			),
393
			'skip-lazy'       => array(
394
				true,
395
				'wp-post-image skip-lazy',
396
			),
397
			'gazette-feature' => array(
398
				true,
399
				'wp-post-image attachment-gazette-featured-content-thumbnail',
400
			),
401
		);
402
	}
403
404
	/**
405
	 * Test that images with filtered empty blocklist should be skipped.
406
	 *
407
	 * @param string $classes A string of space-separated classes. TODO: Check type.
408
	 *
409
	 * @dataProvider get_should_skip_image_with_filtered_empty_blocked_data
410
	 */
411
	public function test_should_skip_image_with_filtered_empty_blocklist( $classes ) {
412
		$filter_callbacks = array(
413
			'__return_empty_string',
414
			'__return_empty_array',
415
		);
416
417
		foreach ( $filter_callbacks as $callback ) {
418
			add_filter( 'jetpack_lazy_images_blocked_classes', $callback );
419
			$this->assertSame( false, Jetpack_Lazy_Images::should_skip_image_with_blocked_class( $classes ) );
420
			remove_filter( 'jetpack_lazy_images_blocked_classes', $callback );
421
		}
422
	}
423
424
	/**
425
	 * Data provider for test.
426
	 *
427
	 * @return array
428
	 */
429
	public function get_should_skip_image_with_filtered_empty_blocked_data() {
430
		return array(
431
			'wp-post-image'   => array(
432
				'wp-post-image',
433
			),
434
			'skip-lazy'       => array(
435
				'wp-post-image skip-lazy',
436
			),
437
			'gazette-feature' => array(
438
				'wp-post-image attachment-gazette-featured-content-thumbnail',
439
			),
440
		);
441
	}
442
443
	/**
444
	 * Test that Jetpack lazy images skip image with attributes filter.
445
	 *
446
	 * @param string $filter_name filter name.
447
	 *
448
	 * @dataProvider get_skip_image_with_attributes_data
449
	 */
450
	public function test_jetpack_lazy_images_skip_image_with_attributes_filter( $filter_name ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
451
		$instance = Jetpack_Lazy_Images::instance();
452
		$src      = '<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" class="wp-post-image"/>';
453
454
		$this->assertStringContainsString( 'srcset="placeholder.jpg"', $instance->add_image_placeholders( $src ) );
455
456
		add_filter( 'jetpack_lazy_images_skip_image_with_attributes', '__return_true' );
457
		$this->assertStringNotContainsString( 'srcset="placeholder.jpg"', $instance->add_image_placeholders( $src ) );
458
		remove_filter( 'jetpack_lazy_images_skip_image_with_attributes', '__return_true' );
459
460
		add_filter( 'jetpack_lazy_images_skip_image_with_attributes', array( $this, 'skip_if_srcset' ), 10, 2 );
461
		$this->assertStringNotContainsString( 'srcset="placeholder.jpg"', $instance->add_image_placeholders( $src ) );
462
		$this->assertStringContainsString( 'srcset="placeholder.jpg"', $instance->add_image_placeholders( '<img src="image.jpg" />' ) );
463
		remove_filter( 'jetpack_lazy_images_skip_image_with_attributes', array( $this, 'skip_if_srcset' ), 10, 2 );
0 ignored issues
show
Unused Code introduced by
The call to remove_filter() has too many arguments starting with 2.

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...
464
	}
465
466
	/**
467
	 * Data provider for test.
468
	 *
469
	 * @return array
470
	 */
471
	public function get_skip_image_with_attributes_data() {
472
		return array(
473
			'deprecated_filter_name_with_typo' => array(
474
				'jetpack_lazy_images_skip_image_with_atttributes',
475
			),
476
			'correct_filter_name'              => array(
477
				'jetpack_lazy_images_skip_image_with_attributes',
478
			),
479
		);
480
	}
481
482
	/*
483
	 * Helpers
484
	 */
485
486
	/**
487
	 * Override image placeholder.
488
	 *
489
	 * @return string
490
	 */
491
	public function override_image_placeholder() {
492
		return 'placeholder.jpg';
493
	}
494
495
	/**
496
	 * Set height attribute.
497
	 *
498
	 * @param array $attributes Attributes.
499
	 *
500
	 * @return array
501
	 */
502
	public function set_height_attribute( $attributes ) {
503
		if ( ! empty( $attributes['height'] ) ) {
504
			$attributes['style'] = sprintf( 'height: %dpx;', $attributes['height'] );
505
			unset( $attributes['height'] );
506
		}
507
		return $attributes;
508
	}
509
510
	/**
511
	 * Get input content.
512
	 *
513
	 * @return string
514
	 */
515 View Code Duplication
	public function get_input_content() {
516
		ob_start();
517
518
		require_once __DIR__ . '/pre-image-placeholder-content.html';
519
520
		$contents = trim( ob_get_contents() );
521
		ob_end_clean();
522
523
		return trim( $contents );
524
	}
525
526
	/**
527
	 * Get output content.
528
	 *
529
	 * @return string
530
	 */
531 View Code Duplication
	public function get_output_content() {
532
		ob_start();
533
534
		require_once __DIR__ . '/post-image-placeholder-content.html';
535
536
		$contents = trim( ob_get_contents() );
537
		ob_end_clean();
538
539
		return trim( $contents );
540
	}
541
542
	/**
543
	 * Check is the srcset attribute it set.
544
	 *
545
	 * @param bool  $should_skip Whether or not it lazy images treatment should be skipped.
546
	 * @param array $attributes  Attributes.
547
	 *
548
	 * @return bool
549
	 */
550
	public function skip_if_srcset( $should_skip, $attributes ) {
551
		return isset( $attributes['srcset'] );
552
	}
553
554
	/**
555
	 * Add skip lazy class to attributes.
556
	 *
557
	 * @param array $attributes attributes.
558
	 *
559
	 * @return mixed
560
	 */
561
	public function add_skip_lazy_class_to_attributes( $attributes ) {
562
		$attributes['class'] .= ' skip-lazy';
563
		return $attributes;
564
	}
565
}
566