Skip to content

Commit a36103c

Browse files
author
Paul Bearne
committed
Add AJAX image cropping tests and update MIME type handling
Introduced detailed PHPUnit tests for AJAX image cropping preview functionality. Made `get_mime_type` a public method and adjusted MIME type handling in `stream_preview_image` for better compatibility with image editors. These changes ensure more robustness in image handling and testing.
1 parent c697356 commit a36103c

File tree

3 files changed

+201
-2
lines changed

3 files changed

+201
-2
lines changed

src/wp-admin/includes/image-edit.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,12 @@ function stream_preview_image( $post_id ) {
787787
return false;
788788
}
789789

790-
return wp_stream_image( $img, $post->post_mime_type, $post_id );
790+
$mime_type = $post->post_mime_type;
791+
if ( method_exists( $img, 'get_mime_type' ) ) {
792+
$mime_type = $img->get_mime_type();
793+
}
794+
795+
return wp_stream_image( $img, $mime_type, $post_id );
791796
}
792797

793798
/**

src/wp-includes/class-wp-image-editor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ protected function make_image( $filename, $callback, $arguments ) {
611611
* @param string $extension
612612
* @return string|false
613613
*/
614-
protected static function get_mime_type( $extension = null ) {
614+
public static function get_mime_type( $extension = null ) {
615615
if ( ! $extension ) {
616616
return false;
617617
}
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
<?php
2+
3+
/**
4+
* Admin Ajax functions to be tested.
5+
*/
6+
require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
7+
require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
8+
require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
9+
10+
/**
11+
* Class for testing ajax crop image functionality.
12+
*
13+
*
14+
* @covers ::wp_ajax_crop_image
15+
*/
16+
class Tests_Ajax_WpAjaxImgeditPreview extends WP_Ajax_UnitTestCase {
17+
18+
/**
19+
* @var WP_Post|null
20+
*/
21+
private $attachment;
22+
23+
/**
24+
* @var WP_Post|null
25+
*/
26+
private $cropped_attachment;
27+
28+
protected static $attachment_id;
29+
30+
public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
31+
require_once ABSPATH . 'wp-admin/includes/image-edit.php';
32+
self::$attachment_id = $factory->attachment->create_upload_object( DIR_TESTDATA . '/images/test-image.jpg' );
33+
}
34+
35+
public static function wpTearDownAfterClass() {
36+
wp_delete_attachment( self::$attachment_id, true );
37+
}
38+
39+
public function set_up() {
40+
parent::set_up();
41+
42+
// Become an administrator.
43+
$this->_setRole( 'administrator' );
44+
}
45+
46+
public function tear_down() {
47+
if ( $this->attachment instanceof WP_Post ) {
48+
wp_delete_attachment( $this->attachment->ID, true );
49+
}
50+
51+
if ( $this->cropped_attachment instanceof WP_Post ) {
52+
wp_delete_attachment( $this->cropped_attachment->ID, true );
53+
}
54+
$this->attachment = null;
55+
$this->cropped_attachment = null;
56+
57+
parent::tear_down();
58+
}
59+
60+
/**
61+
* Tests that attachment properties are copied over to the cropped image.
62+
*
63+
* @group ajax
64+
*
65+
* @ticket 37750
66+
*/
67+
public function test_stream_preview_image() {
68+
$this->attachment = $this->make_attachment( true );
69+
$this->prepare_post( $this->attachment );
70+
$this->_setRole( 'editor' );
71+
72+
$_GET = wp_parse_args(
73+
array(
74+
'action' => 'imgedit-preview',
75+
'_ajax_nonce' => wp_create_nonce( 'image_editor-' . $this->attachment->ID ),
76+
'postid' => $this->attachment->ID,
77+
'rand' => random_int( 1, 1000 ),
78+
)
79+
);
80+
81+
try {
82+
$this->_handleAjax( 'imgedit-preview' );
83+
} catch ( WPAjaxDieContinueException $e ) {
84+
}
85+
86+
$this->assertStringStartsWith( "\xFF\xD8", $this->_last_response );
87+
}
88+
89+
/**
90+
* Test stream_preview_image function with non-image attachment.
91+
*/
92+
public function test_stream_preview_image_non_image() {
93+
$attachment_id = self::factory()->attachment->create_upload_object( DIR_TESTDATA . '/functions/dummy.txt' );
94+
95+
$result = stream_preview_image( $attachment_id );
96+
97+
$this->assertFalse( $result );
98+
99+
wp_delete_attachment( $attachment_id, true );
100+
}
101+
102+
103+
/**
104+
* Test stream_preview_image function with invalid post ID.
105+
*/
106+
public function test_stream_preview_image_invalid_id() {
107+
$result = stream_preview_image( 0 );
108+
109+
$this->assertFalse( $result );
110+
}
111+
112+
/**
113+
* Creates an attachment.
114+
*
115+
* @return WP_Post
116+
*/
117+
private function make_attachment( $with_metadata = true ) {
118+
$uniq_id = uniqid( 'crop-image-ajax-action-test-' );
119+
120+
$test_file = DIR_TESTDATA . '/images/test-image.jpg';
121+
$upload_directory = wp_upload_dir();
122+
$uploaded_file = $upload_directory['path'] . '/' . $uniq_id . '.jpg';
123+
$filesystem = new WP_Filesystem_Direct( true );
124+
$filesystem->copy( $test_file, $uploaded_file );
125+
126+
$attachment_data = array(
127+
'file' => $uploaded_file,
128+
'type' => 'image/jpg',
129+
'url' => 'http://localhost/foo.jpg',
130+
);
131+
132+
$attachment_id = $this->_make_attachment( $attachment_data );
133+
$post_data = array(
134+
'ID' => $attachment_id,
135+
'post_title' => $with_metadata ? 'Title ' . $uniq_id : '',
136+
'post_content' => $with_metadata ? 'Description ' . $uniq_id : '',
137+
'context' => 'custom-logo',
138+
'post_excerpt' => $with_metadata ? 'Caption ' . $uniq_id : '',
139+
);
140+
141+
// Update the post because _make_attachment method doesn't support these arguments.
142+
wp_update_post( $post_data );
143+
144+
if ( $with_metadata ) {
145+
update_post_meta( $attachment_id, '_wp_attachment_image_alt', wp_slash( 'Alt ' . $uniq_id ) );
146+
}
147+
148+
return get_post( $attachment_id );
149+
}
150+
//
151+
// /**
152+
// * @param array $response Response to validate.
153+
// */
154+
// private function validate_response( $response ) {
155+
// $this->assertArrayHasKey( 'success', $response, 'Response array must contain "success" key.' );
156+
// $this->assertArrayHasKey( 'data', $response, 'Response array must contain "data" key.' );
157+
// $this->assertNotEmpty( $response['data']['id'], 'Response array must contain "ID" value of the post entity.' );
158+
// }
159+
//
160+
/**
161+
* Prepares $_POST for crop-image ajax action.
162+
*
163+
* @param WP_Post $attachment
164+
*/
165+
private function prepare_post( WP_Post $attachment ) {
166+
$_POST = array(
167+
'wp_customize' => 'on',
168+
'nonce' => wp_create_nonce( 'image_editor-' . $attachment->ID ),
169+
'id' => $attachment->ID,
170+
'context' => 'custom_logo',
171+
'cropDetails' =>
172+
array(
173+
'x1' => '0',
174+
'y1' => '0',
175+
'x2' => '100',
176+
'y2' => '100',
177+
'width' => '100',
178+
'height' => '100',
179+
'dst_width' => '100',
180+
'dst_height' => '100',
181+
),
182+
'action' => 'crop-image',
183+
);
184+
}
185+
//
186+
// /**
187+
// * @param WP_Post $attachment
188+
// *
189+
// * @return string
190+
// */
191+
// private function get_attachment_filename( WP_Post $attachment ) {
192+
// return wp_basename( wp_get_attachment_url( $attachment->ID ) );
193+
// }
194+
}

0 commit comments

Comments
 (0)