- Timestamp:
- 03/02/2025 10:05:08 PM (3 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tests/phpunit/tests/rest-api/rest-posts-controller.php
r59801 r59899 275 275 276 276 /** 277 * @ticket 56481 278 */ 279 public function test_get_items_with_head_request_should_not_prepare_post_data() { 280 $request = new WP_REST_Request( 'HEAD', '/wp/v2/posts' ); 281 282 $hook_name = 'rest_prepare_post'; 283 $filter = new MockAction(); 284 $callback = array( $filter, 'filter' ); 285 286 add_filter( $hook_name, $callback ); 287 $response = rest_get_server()->dispatch( $request ); 288 remove_filter( $hook_name, $callback ); 289 290 $this->assertNotWPError( $response ); 291 $response = rest_ensure_response( $response ); 292 293 $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' ); 294 295 $headers = $response->get_headers(); 296 $this->assertSame( 0, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' ); 297 $this->assertArrayHasKey( 'Link', $headers, 'The "Link" header should be present in the response.' ); 298 $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' ); 299 } 300 301 /** 277 302 * A valid query that returns 0 results should return an empty JSON list. 303 * In case of a HEAD request, the response should not contain a body. 278 304 * 305 * @dataProvider data_readable_http_methods 279 306 * @link https://github.com/WP-API/WP-API/issues/862 280 */ 281 public function test_get_items_empty_query() { 282 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); 307 * @ticket 56481 308 * 309 * @covers WP_REST_Posts_Controller::get_items 310 * 311 * @param string $method The HTTP method to use. 312 */ 313 public function test_get_items_empty_query( $method ) { 314 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 283 315 $request->set_query_params( 284 316 array( … … 288 320 $response = rest_get_server()->dispatch( $request ); 289 321 290 $this->assertEmpty( $response->get_data() ); 291 $this->assertSame( 200, $response->get_status() ); 292 } 293 294 public function test_get_items_author_query() { 322 if ( $request->is_method( 'HEAD' ) ) { 323 $this->assertNull( $response->get_data(), 'Failed asserting that response data is null for HEAD request.' ); 324 } else { 325 $this->assertSame( array(), $response->get_data(), 'Failed asserting that response data is an empty array for GET request.' ); 326 } 327 328 $headers = $response->get_headers(); 329 $this->assertSame( 0, $headers['X-WP-Total'], 'Failed asserting that X-WP-Total header is 0.' ); 330 $this->assertSame( 0, $headers['X-WP-TotalPages'], 'Failed asserting that X-WP-TotalPages header is 0.' ); 331 } 332 333 /** 334 * @dataProvider data_readable_http_methods 335 * @ticket 56481 336 * 337 * @param string $method The HTTP method to use. 338 */ 339 public function test_get_items_author_query( $method ) { 295 340 self::factory()->post->create( array( 'post_author' => self::$editor_id ) ); 296 341 self::factory()->post->create( array( 'post_author' => self::$author_id ) ); … … 299 344 300 345 // All posts in the database. 301 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );346 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 302 347 $request->set_param( 'per_page', self::$per_page ); 303 348 $response = rest_get_server()->dispatch( $request ); 304 349 $this->assertSame( 200, $response->get_status() ); 305 $this->assertCount( $total_posts, $response->get_data() ); 350 if ( $request->is_method( 'get' ) ) { 351 $this->assertCount( $total_posts, $response->get_data() ); 352 353 } else { 354 $this->assertNull( $response->get_data(), 'Failed asserting that response data is null for HEAD request.' ); 355 $headers = $response->get_headers(); 356 $this->assertSame( $total_posts, $headers['X-WP-Total'] ); 357 } 306 358 307 359 // Limit to editor and author. 308 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );360 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 309 361 $request->set_param( 'author', array( self::$editor_id, self::$author_id ) ); 310 362 $response = rest_get_server()->dispatch( $request ); 311 363 $this->assertSame( 200, $response->get_status() ); 312 364 $data = $response->get_data(); 313 $this->assertCount( 2, $data ); 314 $this->assertSameSets( array( self::$editor_id, self::$author_id ), wp_list_pluck( $data, 'author' ) ); 365 if ( $request->is_method( 'get' ) ) { 366 $this->assertCount( 2, $data ); 367 $this->assertSameSets( array( self::$editor_id, self::$author_id ), wp_list_pluck( $data, 'author' ) ); 368 } else { 369 $this->assertNull( $data, 'Failed asserting that response data is null for HEAD request.' ); 370 $headers = $response->get_headers(); 371 $this->assertSame( 2, $headers['X-WP-Total'], 'Failed asserting that X-WP-Total header is 2.' ); 372 } 315 373 316 374 // Limit to editor. 317 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );375 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 318 376 $request->set_param( 'author', self::$editor_id ); 319 377 $response = rest_get_server()->dispatch( $request ); 320 378 $this->assertSame( 200, $response->get_status() ); 321 379 $data = $response->get_data(); 322 $this->assertCount( 1, $data ); 323 $this->assertSame( self::$editor_id, $data[0]['author'] ); 324 } 325 326 public function test_get_items_author_exclude_query() { 380 if ( $request->is_method( 'get' ) ) { 381 $this->assertCount( 1, $data ); 382 $this->assertSame( self::$editor_id, $data[0]['author'] ); 383 } else { 384 $this->assertNull( $data, 'Failed asserting that response data is null for HEAD request.' ); 385 $headers = $response->get_headers(); 386 $this->assertSame( 1, $headers['X-WP-Total'], 'Failed asserting that X-WP-Total header is 1.' ); 387 } 388 } 389 390 /** 391 * @dataProvider data_readable_http_methods 392 * @ticket 56481 393 * 394 * @param string $method The HTTP method to use. 395 */ 396 public function test_get_items_author_exclude_query( $method ) { 327 397 self::factory()->post->create( array( 'post_author' => self::$editor_id ) ); 328 398 self::factory()->post->create( array( 'post_author' => self::$author_id ) ); … … 331 401 332 402 // All posts in the database. 333 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );403 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 334 404 $request->set_param( 'per_page', self::$per_page ); 335 405 $response = rest_get_server()->dispatch( $request ); 336 406 $this->assertSame( 200, $response->get_status() ); 337 $this->assertCount( $total_posts, $response->get_data() ); 407 if ( $request->is_method( 'get' ) ) { 408 $this->assertCount( $total_posts, $response->get_data() ); 409 } else { 410 $this->assertNull( $response->get_data(), 'Failed asserting that response data is null for HEAD request.' ); 411 $headers = $response->get_headers(); 412 $this->assertSame( $total_posts, $headers['X-WP-Total'], 'Failed asserting that the number of posts is correct.' ); 413 } 338 414 339 415 // Exclude editor and author. 340 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );416 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 341 417 $request->set_param( 'per_page', self::$per_page ); 342 418 $request->set_param( 'author_exclude', array( self::$editor_id, self::$author_id ) ); … … 344 420 $this->assertSame( 200, $response->get_status() ); 345 421 $data = $response->get_data(); 346 $this->assertCount( $total_posts - 2, $data ); 347 $this->assertNotEquals( self::$editor_id, $data[0]['author'] ); 348 $this->assertNotEquals( self::$author_id, $data[0]['author'] ); 422 if ( $request->is_method( 'get' ) ) { 423 $this->assertCount( $total_posts - 2, $data ); 424 $this->assertNotEquals( self::$editor_id, $data[0]['author'] ); 425 $this->assertNotEquals( self::$author_id, $data[0]['author'] ); 426 } else { 427 $this->assertNull( $response->get_data(), 'Failed asserting that response data is null for HEAD request.' ); 428 $headers = $response->get_headers(); 429 $this->assertSame( $total_posts - 2, $headers['X-WP-Total'], 'Failed asserting that the number of posts is correct.' ); 430 } 349 431 350 432 // Exclude editor. 351 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );433 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 352 434 $request->set_param( 'per_page', self::$per_page ); 353 435 $request->set_param( 'author_exclude', self::$editor_id ); … … 355 437 $this->assertSame( 200, $response->get_status() ); 356 438 $data = $response->get_data(); 357 $this->assertCount( $total_posts - 1, $data ); 358 $this->assertNotEquals( self::$editor_id, $data[0]['author'] ); 359 $this->assertNotEquals( self::$editor_id, $data[1]['author'] ); 439 if ( $request->is_method( 'get' ) ) { 440 $this->assertCount( $total_posts - 1, $data ); 441 $this->assertNotEquals( self::$editor_id, $data[0]['author'] ); 442 $this->assertNotEquals( self::$editor_id, $data[1]['author'] ); 443 } else { 444 $this->assertNull( $response->get_data(), 'Failed asserting that response data is null for HEAD request.' ); 445 $headers = $response->get_headers(); 446 $this->assertSame( $total_posts - 1, $headers['X-WP-Total'], 'Failed asserting that the number of posts is correct.' ); 447 } 360 448 361 449 // Invalid 'author_exclude' should error. 362 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );450 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 363 451 $request->set_param( 'author_exclude', 'invalid' ); 364 452 $response = rest_get_server()->dispatch( $request ); … … 366 454 } 367 455 368 public function test_get_items_include_query() { 456 /** 457 * @dataProvider data_readable_http_methods 458 * @ticket 56481 459 * 460 * @param string $method The HTTP method to use. 461 */ 462 public function test_get_items_include_query( $method ) { 369 463 $id1 = self::factory()->post->create( 370 464 array( … … 380 474 ); 381 475 382 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );476 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 383 477 384 478 // Order defaults to date descending. … … 386 480 $response = rest_get_server()->dispatch( $request ); 387 481 $data = $response->get_data(); 388 $this->assertCount( 2, $data ); 389 $this->assertSame( $id2, $data[0]['id'] ); 482 if ( $request->is_method( 'get' ) ) { 483 $this->assertCount( 2, $data ); 484 $this->assertSame( $id2, $data[0]['id'] ); 485 } else { 486 $this->assertNull( $data, 'Failed asserting that response data is null for HEAD request.' ); 487 $headers = $response->get_headers(); 488 $this->assertSame( 2, $headers['X-WP-Total'], 'Failed asserting that the number of posts is correct.' ); 489 } 490 390 491 $this->assertPostsOrderedBy( '{posts}.post_date DESC' ); 391 492 … … 394 495 $response = rest_get_server()->dispatch( $request ); 395 496 $data = $response->get_data(); 396 $this->assertCount( 2, $data ); 397 $this->assertSame( $id1, $data[0]['id'] ); 497 if ( $request->is_method( 'get' ) ) { 498 $this->assertCount( 2, $data ); 499 $this->assertSame( $id1, $data[0]['id'] ); 500 } else { 501 $this->assertNull( $data, 'Failed asserting that response data is null for HEAD request.' ); 502 $headers = $response->get_headers(); 503 $this->assertSame( 2, $headers['X-WP-Total'], 'Failed asserting that the number of posts is correct.' ); 504 } 505 398 506 $this->assertPostsOrderedBy( "FIELD({posts}.ID,$id1,$id2)" ); 399 507 400 508 // Invalid 'include' should error. 401 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );509 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 402 510 $request->set_param( 'include', 'invalid' ); 403 511 $response = rest_get_server()->dispatch( $request ); … … 1730 1838 } 1731 1839 1732 public function test_get_items_pagination_headers() { 1840 /** 1841 * @dataProvider data_readable_http_methods 1842 * @ticket 56481 1843 * 1844 * @param string $method HTTP method to use. 1845 */ 1846 public function test_get_items_pagination_headers( $method ) { 1733 1847 $total_posts = self::$total_posts; 1734 1848 $total_pages = (int) ceil( $total_posts / 10 ); 1735 1849 1736 1850 // Start of the index. 1737 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );1851 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 1738 1852 $response = rest_get_server()->dispatch( $request ); 1739 1853 $headers = $response->get_headers(); … … 1753 1867 ++$total_posts; 1754 1868 ++$total_pages; 1755 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );1869 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 1756 1870 $request->set_param( 'page', 3 ); 1757 1871 $response = rest_get_server()->dispatch( $request ); … … 1775 1889 1776 1890 // Last page. 1777 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );1891 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 1778 1892 $request->set_param( 'page', $total_pages ); 1779 1893 $response = rest_get_server()->dispatch( $request ); … … 1791 1905 1792 1906 // Out of bounds. 1793 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );1907 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 1794 1908 $request->set_param( 'page', 100 ); 1795 1909 $response = rest_get_server()->dispatch( $request ); … … 1799 1913 // With query params. 1800 1914 $total_pages = (int) ceil( $total_posts / 5 ); 1801 $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );1915 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 1802 1916 $request->set_query_params( 1803 1917 array( … … 1826 1940 ); 1827 1941 $this->assertStringContainsString( '<' . $next_link . '>; rel="next"', $headers['Link'] ); 1942 } 1943 1944 /** 1945 * Data provider intended to provide HTTP method names for testing GET and HEAD requests. 1946 * 1947 * @return array 1948 */ 1949 public static function data_readable_http_methods() { 1950 return array( 1951 'GET request' => array( 'GET' ), 1952 'HEAD request' => array( 'HEAD' ), 1953 ); 1954 } 1955 1956 /** 1957 * @dataProvider data_readable_http_methods 1958 * @ticket 56481 1959 * 1960 * @param string $method HTTP method to use. 1961 */ 1962 public function test_get_items_only_fetches_ids_for_head_requests( $method ) { 1963 $is_head_request = 'HEAD' === $method; 1964 $request = new WP_REST_Request( $method, '/wp/v2/posts' ); 1965 1966 $filter = new MockAction(); 1967 1968 add_filter( 'posts_pre_query', array( $filter, 'filter' ), 10, 2 ); 1969 1970 $response = rest_get_server()->dispatch( $request ); 1971 1972 $this->assertSame( 200, $response->get_status() ); 1973 if ( $is_head_request ) { 1974 $this->assertEmpty( $response->get_data() ); 1975 } else { 1976 $this->assertNotEmpty( $response->get_data() ); 1977 } 1978 1979 $args = $filter->get_args(); 1980 $this->assertTrue( isset( $args[0][1] ), 'Query parameters were not captured.' ); 1981 $this->assertInstanceOf( WP_Query::class, $args[0][1], 'Query parameters were not captured.' ); 1982 1983 /** @var WP_Query $query */ 1984 $query = $args[0][1]; 1985 1986 if ( $is_head_request ) { 1987 $this->assertArrayHasKey( 'fields', $query->query, 'The fields parameter is not set in the query vars.' ); 1988 $this->assertSame( 'ids', $query->query['fields'], 'The query must fetch only post IDs.' ); 1989 $this->assertArrayHasKey( 'fields', $query->query_vars, 'The fields parameter is not set in the query vars.' ); 1990 $this->assertSame( 'ids', $query->query_vars['fields'], 'The query must fetch only post IDs.' ); 1991 $this->assertArrayHasKey( 'update_post_term_cache', $query->query_vars, 'The "update_post_term_cache" parameter is missing in the query vars.' ); 1992 $this->assertFalse( $query->query_vars['update_post_term_cache'], 'The "update_post_term_cache" parameter must be false for HEAD requests.' ); 1993 $this->assertArrayHasKey( 'update_post_meta_cache', $query->query_vars, 'The "update_post_meta_cache" parameter is missing in the query vars.' ); 1994 $this->assertFalse( $query->query_vars['update_post_meta_cache'], 'The "update_post_meta_cache" parameter must be false for HEAD requests.' ); 1995 } else { 1996 $this->assertTrue( ! array_key_exists( 'fields', $query->query ) || 'ids' !== $query->query['fields'], 'The fields parameter should not be forced to "ids" for non-HEAD requests.' ); 1997 $this->assertTrue( ! array_key_exists( 'fields', $query->query_vars ) || 'ids' !== $query->query_vars['fields'], 'The fields parameter should not be forced to "ids" for non-HEAD requests.' ); 1998 $this->assertArrayHasKey( 'update_post_term_cache', $query->query_vars, 'The "update_post_term_cache" parameter is missing in the query vars.' ); 1999 $this->assertTrue( $query->query_vars['update_post_term_cache'], 'The "update_post_term_cache" parameter must be true for non-HEAD requests.' ); 2000 $this->assertArrayHasKey( 'update_post_meta_cache', $query->query_vars, 'The "update_post_meta_cache" parameter is missing in the query vars.' ); 2001 $this->assertTrue( $query->query_vars['update_post_meta_cache'], 'The "update_post_meta_cache" parameter must be true for non-HEAD requests.' ); 2002 } 2003 2004 if ( ! $is_head_request ) { 2005 return; 2006 } 2007 2008 global $wpdb; 2009 $posts_table = preg_quote( $wpdb->posts, '/' ); 2010 $pattern = '/^SELECT\s+SQL_CALC_FOUND_ROWS\s+' . $posts_table . '\.ID\s+FROM\s+' . $posts_table . '\s+WHERE/i'; 2011 2012 // Assert that the SQL query only fetches the ID column. 2013 $this->assertMatchesRegularExpression( $pattern, $query->request, 'The SQL query does not match the expected string.' ); 1828 2014 } 1829 2015 … … 1972 2158 1973 2159 $this->check_get_post_response( $response, 'view' ); 2160 } 2161 2162 /** 2163 * @dataProvider data_readable_http_methods 2164 * @ticket 56481 2165 * 2166 * @param string $method The HTTP method to use. 2167 */ 2168 public function test_get_item_should_allow_adding_headers_via_filter( $method ) { 2169 $request = new WP_REST_Request( $method, sprintf( '/wp/v2/posts/%d', self::$post_id ) ); 2170 2171 $hook_name = 'rest_prepare_' . get_post_type( self::$post_id ); 2172 $filter = new MockAction(); 2173 $callback = array( $filter, 'filter' ); 2174 add_filter( $hook_name, $callback ); 2175 $header_filter = new class() { 2176 public static function add_custom_header( $response ) { 2177 $response->header( 'X-Test-Header', 'Test' ); 2178 2179 return $response; 2180 } 2181 }; 2182 add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) ); 2183 $response = rest_get_server()->dispatch( $request ); 2184 remove_filter( $hook_name, $callback ); 2185 remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) ); 2186 2187 $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' ); 2188 $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was not called when it should be for GET/HEAD requests.' ); 2189 $headers = $response->get_headers(); 2190 $this->assertArrayHasKey( 'Link', $headers, 'The "Link" header should be present in the response.' ); 2191 $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' ); 2192 $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' ); 2193 if ( 'HEAD' !== $method ) { 2194 return null; 2195 } 2196 $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' ); 1974 2197 } 1975 2198
Note: See TracChangeset
for help on using the changeset viewer.