Skip to content

Commit 3589bd7

Browse files
Add tests for picture
1 parent 1131414 commit 3589bd7

File tree

2 files changed

+132
-7
lines changed

2 files changed

+132
-7
lines changed

src/class-tiny-picture.php

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
class Tiny_Picture {
2222

2323

24+
2425
public function __construct() {
2526
$this->init();
2627
}
@@ -90,6 +91,7 @@ private function filter_images( $content ) {
9091

9192
class Tiny_Picture_Element {
9293

94+
9395
/**
9496
* The raw HTML img element as a string
9597
* @var string
@@ -153,30 +155,43 @@ private function get_image_srcsets() {
153155
return $result;
154156
}
155157

156-
private function get_formatted_source( $imgsrcs, $format ) {
157-
$upload_dir = wp_upload_dir();
158+
private function get_local_path( $url ) {
159+
$wp_upload_dir = wp_upload_dir();
160+
$local_path = parse_url( $url, PHP_URL_PATH );
161+
$format_path = str_replace( $wp_upload_dir['baseurl'], $wp_upload_dir['basedir'], $local_path );
162+
return $format_path;
163+
}
158164

159-
$formatted_src_set = array();
165+
private function get_formatted_source( $imgsrcs, $format ) {
166+
$formatted_src_set = array();
160167
foreach ( $imgsrcs as $imgsrc ) {
161168
$format_url = Tiny_Helpers::replace_file_extension( $format, $imgsrc['path'] );
162-
$format_path = str_replace( $upload_dir['baseurl'], $upload_dir['basedir'], $format_url );
163-
if ( file_exists( $format_path ) ) {
169+
$local_path = $this->get_local_path( $format_url );
170+
$exists_local = file_exists( $local_path );
171+
if ( $exists_local ) {
164172
$formatted_src_set[] = $format_url . ' ' . $imgsrc['size'];
165173
}
166174
}
167175

168176
if ( empty( $formatted_src_set ) ) {
169-
// no avif sources found
177+
// no alternative sources found
170178
return '';
171179
}
172180

173181
$source_set = implode( ', ', $formatted_src_set );
174-
return '<source type="' . $format . '" srcset="' . $source_set . '">';
182+
$trimmed_source_set = trim( $source_set );
183+
return '<source type="' . $format . '" srcset="' . $trimmed_source_set . '">';
175184
}
176185

177186
public function get_picture_element() {
178187
$srcsets = $this->get_image_srcsets();
179188

189+
$avif = $this->get_formatted_source( $srcsets, 'image/avif' );
190+
$webp = $this->get_formatted_source( $srcsets, 'image/webp' );
191+
if ( empty( $avif ) && empty( $webp ) ) {
192+
return $this->img_element;
193+
}
194+
180195
$picture = '<picture>';
181196
$picture .= $this->get_formatted_source( $srcsets, 'image/avif' );
182197
$picture .= $this->get_formatted_source( $srcsets, 'image/webp' );

test/unit/TinyPictureTest.php

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?php
2+
3+
require_once dirname(__FILE__) . '/TinyTestCase.php';
4+
5+
class Tiny_Picture_Test extends Tiny_TestCase
6+
{
7+
public function set_up()
8+
{
9+
parent::set_up();
10+
}
11+
12+
/**
13+
* img tags with a absolute url should be processed correctly
14+
*/
15+
public function test_replace_image_with_absolute_url_with_picture_tag()
16+
{
17+
$this->wp->createImage(37857, '2025/01', 'test.avif');
18+
19+
$tiny_picture = new Tiny_Picture();
20+
$output = $tiny_picture->replace_img_with_picture_tag('<img src="https://www.tinifytest.com/wp-content/uploads/2025/01/test.png">');
21+
$expected_output = '<picture><source type="image/avif" srcset="https://www.tinifytest.com/wp-content/uploads/2025/01/test.avif"><img src="https://www.tinifytest.com/wp-content/uploads/2025/01/test.png"></picture>';
22+
$this->assertEquals($expected_output, $output);
23+
}
24+
25+
/**
26+
* img tags with a relative url should be processed correctly
27+
*/
28+
public function test_replace_image_with_relative_url_with_picture_tag()
29+
{
30+
$this->wp->createImage(37857, '2025/01', 'test.webp');
31+
32+
$tiny_picture = new Tiny_Picture();
33+
$output = $tiny_picture->replace_img_with_picture_tag('<img src="/wp-content/uploads/2025/01/test.png">');
34+
$expected_output = '<picture><source type="image/webp" srcset="/wp-content/uploads/2025/01/test.webp"><img src="/wp-content/uploads/2025/01/test.png"></picture>';
35+
$this->assertEquals($expected_output, $output);
36+
}
37+
38+
/**
39+
* HTML containing a picture element with a img tag nested within,
40+
* should not be replaced
41+
*/
42+
public function test_will_not_replace_images_within_picture_tag()
43+
{
44+
$tiny_picture = new Tiny_Picture();
45+
$current_picture = '<picture><source type="image/webp" srcset="/wp-content/uploads/2025/01/test.webp"><img src="/wp-content/uploads/2025/01/test.png"></picture>';
46+
$output = $tiny_picture->replace_img_with_picture_tag($current_picture);
47+
$this->assertEquals($current_picture, $output);
48+
}
49+
50+
public function test_img_with_no_alternate_format_should_not_change()
51+
{
52+
$tiny_picture = new Tiny_Picture();
53+
$output = $tiny_picture->replace_img_with_picture_tag('<img src="/wp-content/uploads/2025/01/missing.png">');
54+
$expected_output = '<img src="/wp-content/uploads/2025/01/missing.png">';
55+
$this->assertEquals($expected_output, $output);
56+
}
57+
58+
public function test_img_with_query_string_keeps_query()
59+
{
60+
$this->wp->createImage(37857, '2025/01', 'test.avif');
61+
62+
$tiny_picture = new Tiny_Picture();
63+
$output = $tiny_picture->replace_img_with_picture_tag('<img src="/wp-content/uploads/2025/01/test.png?ver=123">');
64+
$expected_output = '<picture><source type="image/avif" srcset="/wp-content/uploads/2025/01/test.avif"><img src="/wp-content/uploads/2025/01/test.png?ver=123"></picture>';
65+
$this->assertEquals($expected_output, $output);
66+
}
67+
68+
public function test_multiple_img_tags()
69+
{
70+
$this->wp->createImage(1000, '2025/01', 'first.webp');
71+
$this->wp->createImage(1000, '2025/01', 'second.webp');
72+
73+
$tiny_picture = new Tiny_Picture();
74+
$input = '<img src="/wp-content/uploads/2025/01/first.png"><p>Hello</p><img src="/wp-content/uploads/2025/01/second.png">';
75+
$expected = '<picture><source type="image/webp" srcset="/wp-content/uploads/2025/01/first.webp"><img src="/wp-content/uploads/2025/01/first.png"></picture><p>Hello</p><picture><source type="image/webp" srcset="/wp-content/uploads/2025/01/second.webp"><img src="/wp-content/uploads/2025/01/second.png"></picture>';
76+
77+
$this->assertEquals($expected, $tiny_picture->replace_img_with_picture_tag($input));
78+
}
79+
80+
public function test_img_with_additional_attributes()
81+
{
82+
$this->wp->createImage(1000, '2025/01', 'test.webp');
83+
84+
$tiny_picture = new Tiny_Picture();
85+
$input = '<img src="/wp-content/uploads/2025/01/test.png" class="lazy" alt="Test" loading="lazy">';
86+
$expected = '<picture><source type="image/webp" srcset="/wp-content/uploads/2025/01/test.webp"><img src="/wp-content/uploads/2025/01/test.png" class="lazy" alt="Test" loading="lazy"></picture>';
87+
$this->assertEquals($expected, $tiny_picture->replace_img_with_picture_tag($input));
88+
}
89+
90+
public function test_uppercase_img_tag_is_handled()
91+
{
92+
$this->wp->createImage(37857, '2025/01', 'test.webp');
93+
94+
$tiny_picture = new Tiny_Picture();
95+
$input = '<IMG SRC="/wp-content/uploads/2025/01/test.png">';
96+
$expected = '<picture><source type="image/webp" srcset="/wp-content/uploads/2025/01/test.webp"><IMG SRC="/wp-content/uploads/2025/01/test.png"></picture>';
97+
$this->assertEquals($expected, $tiny_picture->replace_img_with_picture_tag($input));
98+
}
99+
100+
public function test_img_inside_anchor_is_wrapped()
101+
{
102+
$this->wp->createImage(1000, '2025/01', 'test.webp');
103+
104+
$tiny_picture = new Tiny_Picture();
105+
$input = '<a href="/something"><img src="/wp-content/uploads/2025/01/test.png"></a>';
106+
$expected = '<a href="/something"><picture><source type="image/webp" srcset="/wp-content/uploads/2025/01/test.webp"><img src="/wp-content/uploads/2025/01/test.png"></picture></a>';
107+
108+
$this->assertEquals($expected, $tiny_picture->replace_img_with_picture_tag($input));
109+
}
110+
}

0 commit comments

Comments
 (0)