<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[51997] trunk/tests/phpunit/tests/admin: Tests: Split `WP_Posts_List_Table` and `WP_Comments_List_Table` tests into two separate files for clarity.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/51997">51997</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/51997","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>SergeyBiryukov</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2021-11-03 00:48:42 +0000 (Wed, 03 Nov 2021)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Tests: Split `WP_Posts_List_Table` and `WP_Comments_List_Table` tests into two separate files for clarity.

These were previously combined in the `includesListTable.php` file. Since the tests were specific neither to the `_get_list_table()` function nor the parent `WP_List_Table` class, the naming was confusing, which should now be resolved.

Follow-up to <a href="https://core.trac.wordpress.org/changeset/31730">[31730]</a>, <a href="https://core.trac.wordpress.org/changeset/38854">[38854]</a>, <a href="https://core.trac.wordpress.org/changeset/40297">[40297]</a>, <a href="https://core.trac.wordpress.org/changeset/48151">[48151]</a>, <a href="https://core.trac.wordpress.org/changeset/48521">[48521]</a>, <a href="https://core.trac.wordpress.org/changeset/49190">[49190]</a>, <a href="https://core.trac.wordpress.org/changeset/51993">[51993]</a>.

See <a href="https://core.trac.wordpress.org/ticket/53363">#53363</a>.</pre>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestsadminwpCommentsListTablephp">trunk/tests/phpunit/tests/admin/wpCommentsListTable.php</a></li>
<li><a href="#trunktestsphpunittestsadminwpPostsListTablephp">trunk/tests/phpunit/tests/admin/wpPostsListTable.php</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestsadminincludesListTablephp">trunk/tests/phpunit/tests/admin/includesListTable.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunktestsphpunittestsadminincludesListTablephp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/admin/includesListTable.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/admin/includesListTable.php     2021-11-02 23:18:46 UTC (rev 51996)
+++ trunk/tests/phpunit/tests/admin/includesListTable.php       2021-11-03 00:48:42 UTC (rev 51997)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,514 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-/**
- * @group admin
- */
-class Tests_Admin_IncludesListTable extends WP_UnitTestCase {
-       protected static $top           = array();
-       protected static $children      = array();
-       protected static $grandchildren = array();
-       protected static $post_ids      = array();
-
-       /**
-        * @var WP_Posts_List_Table
-        */
-       protected $table;
-
-       function set_up() {
-               parent::set_up();
-               $this->table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => 'edit-page' ) );
-       }
-
-       public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
-               // Note that our top/children/grandchildren arrays are 1-indexed.
-
-               // Create top-level pages.
-               $num_posts = 5;
-               foreach ( range( 1, $num_posts ) as $i ) {
-                       $p = $factory->post->create_and_get(
-                               array(
-                                       'post_type'  => 'page',
-                                       'post_title' => sprintf( 'Top Level Page %d', $i ),
-                               )
-                       );
-
-                       self::$top[ $i ]  = $p;
-                       self::$post_ids[] = $p->ID;
-               }
-
-               // Create child pages.
-               $num_children = 3;
-               foreach ( self::$top as $top => $top_page ) {
-                       foreach ( range( 1, $num_children ) as $i ) {
-                               $p = $factory->post->create_and_get(
-                                       array(
-                                               'post_type'   => 'page',
-                                               'post_parent' => $top_page->ID,
-                                               'post_title'  => sprintf( 'Child %d', $i ),
-                                       )
-                               );
-
-                               self::$children[ $top ][ $i ] = $p;
-                               self::$post_ids[]             = $p->ID;
-                       }
-               }
-
-               // Create grand-child pages for the third and fourth top-level pages.
-               $num_grandchildren = 3;
-               foreach ( range( 3, 4 ) as $top ) {
-                       foreach ( self::$children[ $top ] as $child => $child_page ) {
-                               foreach ( range( 1, $num_grandchildren ) as $i ) {
-                                       $p = $factory->post->create_and_get(
-                                               array(
-                                                       'post_type'   => 'page',
-                                                       'post_parent' => $child_page->ID,
-                                                       'post_title'  => sprintf( 'Grandchild %d', $i ),
-                                               )
-                                       );
-
-                                       self::$grandchildren[ $top ][ $child ][ $i ] = $p;
-                                       self::$post_ids[]                            = $p->ID;
-                               }
-                       }
-               }
-       }
-
-       /**
-        * @ticket 15459
-        *
-        * @covers WP_Posts_List_Table::display_rows
-        * @covers WP_Posts_List_Table::set_hierarchical_display
-        */
-       function test_list_hierarchical_pages_first_page() {
-               $this->_test_list_hierarchical_page(
-                       array(
-                               'paged'          => 1,
-                               'posts_per_page' => 2,
-                       ),
-                       array(
-                               self::$top[1]->ID,
-                               self::$children[1][1]->ID,
-                       )
-               );
-       }
-
-       /**
-        * @ticket 15459
-        *
-        * @covers WP_Posts_List_Table::display_rows
-        * @covers WP_Posts_List_Table::set_hierarchical_display
-        */
-       function test_list_hierarchical_pages_second_page() {
-               $this->_test_list_hierarchical_page(
-                       array(
-                               'paged'          => 2,
-                               'posts_per_page' => 2,
-                       ),
-                       array(
-                               self::$top[1]->ID,
-                               self::$children[1][2]->ID,
-                               self::$children[1][3]->ID,
-                       )
-               );
-       }
-
-       /**
-        * @ticket 15459
-        *
-        * @covers WP_Posts_List_Table::display_rows
-        * @covers WP_Posts_List_Table::set_hierarchical_display
-        */
-       function test_search_hierarchical_pages_first_page() {
-               $this->_test_list_hierarchical_page(
-                       array(
-                               'paged'          => 1,
-                               'posts_per_page' => 2,
-                               's'              => 'Child',
-                       ),
-                       array(
-                               self::$children[1][1]->ID,
-                               self::$children[1][2]->ID,
-                       )
-               );
-       }
-
-       /**
-        * @ticket 15459
-        *
-        * @covers WP_Posts_List_Table::display_rows
-        * @covers WP_Posts_List_Table::set_hierarchical_display
-        */
-       function test_search_hierarchical_pages_second_page() {
-               $this->_test_list_hierarchical_page(
-                       array(
-                               'paged'          => 2,
-                               'posts_per_page' => 2,
-                               's'              => 'Top',
-                       ),
-                       array(
-                               self::$top[3]->ID,
-                               self::$top[4]->ID,
-                       )
-               );
-       }
-
-       /**
-        * @ticket 15459
-        *
-        * @covers WP_Posts_List_Table::display_rows
-        * @covers WP_Posts_List_Table::set_hierarchical_display
-        */
-       function test_grandchildren_hierarchical_pages_first_page() {
-               // Page 6 is the first page with grandchildren.
-               $this->_test_list_hierarchical_page(
-                       array(
-                               'paged'          => 6,
-                               'posts_per_page' => 2,
-                       ),
-                       array(
-                               self::$top[3]->ID,
-                               self::$children[3][1]->ID,
-                               self::$grandchildren[3][1][1]->ID,
-                               self::$grandchildren[3][1][2]->ID,
-                       )
-               );
-       }
-
-       /**
-        * @ticket 15459
-        *
-        * @covers WP_Posts_List_Table::display_rows
-        * @covers WP_Posts_List_Table::set_hierarchical_display
-        */
-       function test_grandchildren_hierarchical_pages_second_page() {
-               // Page 7 is the second page with grandchildren.
-               $this->_test_list_hierarchical_page(
-                       array(
-                               'paged'          => 7,
-                               'posts_per_page' => 2,
-                       ),
-                       array(
-                               self::$top[3]->ID,
-                               self::$children[3][1]->ID,
-                               self::$grandchildren[3][1][3]->ID,
-                               self::$children[3][2]->ID,
-                       )
-               );
-       }
-
-       /**
-        * Helper function to test the output of a page which uses `WP_Posts_List_Table`.
-        *
-        * @param array $args         Query args for the list of pages.
-        * @param array $expected_ids Expected IDs of pages returned.
-        */
-       protected function _test_list_hierarchical_page( array $args, array $expected_ids ) {
-               if ( PHP_VERSION_ID >= 80100 ) {
-                       /*
-                        * For the time being, ignoring PHP 8.1 "null to non-nullable" deprecations coming in
-                        * via hooked in filter functions until a more structural solution to the
-                        * "missing input validation" conundrum has been architected and implemented.
-                        */
-                       $this->expectDeprecation();
-                       $this->expectDeprecationMessageMatches( '`Passing null to parameter \#[0-9]+ \(\$[^\)]+\) of type [^ ]+ is deprecated`' );
-               }
-
-               $matches = array();
-
-               $_REQUEST['paged']   = $args['paged'];
-               $GLOBALS['per_page'] = $args['posts_per_page'];
-
-               $args = array_merge(
-                       array(
-                               'post_type' => 'page',
-                       ),
-                       $args
-               );
-
-               // Mimic the behaviour of `wp_edit_posts_query()`:
-               if ( ! isset( $args['orderby'] ) ) {
-                       $args['orderby']                = 'menu_order title';
-                       $args['order']                  = 'asc';
-                       $args['posts_per_page']         = -1;
-                       $args['posts_per_archive_page'] = -1;
-               }
-
-               // Effectively ignore the output until retrieving it later via `getActualOutput()`.
-               $this->expectOutputRegex( '`.`' );
-
-               $pages = new WP_Query( $args );
-
-               $this->table->set_hierarchical_display( true );
-               $this->table->display_rows( $pages->posts );
-               $output = $this->getActualOutput();
-
-               // Clean up.
-               unset( $_REQUEST['paged'] );
-               unset( $GLOBALS['per_page'] );
-
-               preg_match_all( '|<tr[^>]*>|', $output, $matches );
-
-               $this->assertCount( count( $expected_ids ), array_keys( $matches[0] ) );
-
-               foreach ( $expected_ids as $id ) {
-                       $this->assertStringContainsString( sprintf( 'id="post-%d"', $id ), $output );
-               }
-       }
-
-       /**
-        * @ticket 37407
-        *
-        * @covers WP_Posts_List_Table::extra_tablenav
-        */
-       function test_filter_button_should_not_be_shown_if_there_are_no_posts() {
-               // Set post type to a non-existent one.
-               $this->table->screen->post_type = 'foo';
-
-               ob_start();
-               $this->table->extra_tablenav( 'top' );
-               $output = ob_get_clean();
-
-               $this->assertStringNotContainsString( 'id="post-query-submit"', $output );
-       }
-
-       /**
-        * @ticket 37407
-        *
-        * @covers WP_Posts_List_Table::extra_tablenav
-        */
-       function test_months_dropdown_should_not_be_shown_if_there_are_no_posts() {
-               // Set post type to a non-existent one.
-               $this->table->screen->post_type = 'foo';
-
-               ob_start();
-               $this->table->extra_tablenav( 'top' );
-               $output = ob_get_clean();
-
-               $this->assertStringNotContainsString( 'id="filter-by-date"', $output );
-       }
-
-       /**
-        * @ticket 37407
-        *
-        * @covers WP_Posts_List_Table::extra_tablenav
-        */
-       function test_category_dropdown_should_not_be_shown_if_there_are_no_posts() {
-               // Set post type to a non-existent one.
-               $this->table->screen->post_type = 'foo';
-
-               ob_start();
-               $this->table->extra_tablenav( 'top' );
-               $output = ob_get_clean();
-
-               $this->assertStringNotContainsString( 'id="cat"', $output );
-       }
-
-       /**
-        * @ticket 38341
-        *
-        * @covers WP_Posts_List_Table::extra_tablenav
-        */
-       public function test_empty_trash_button_should_not_be_shown_if_there_are_no_posts() {
-               // Set post type to a non-existent one.
-               $this->table->screen->post_type = 'foo';
-
-               ob_start();
-               $this->table->extra_tablenav( 'top' );
-               $output = ob_get_clean();
-
-               $this->assertStringNotContainsString( 'id="delete_all"', $output );
-       }
-
-       /**
-        * @ticket 40188
-        *
-        * @covers WP_Posts_List_Table::extra_tablenav
-        */
-       public function test_filter_button_should_not_be_shown_if_there_are_no_comments() {
-               $table = _get_list_table( 'WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
-
-               ob_start();
-               $table->extra_tablenav( 'top' );
-               $output = ob_get_clean();
-
-               $this->assertStringNotContainsString( 'id="post-query-submit"', $output );
-       }
-
-       /**
-        * @ticket 40188
-        *
-        * @covers WP_Posts_List_Table::extra_tablenav
-        */
-       public function test_filter_button_should_be_shown_if_there_are_comments() {
-               $post_id    = self::factory()->post->create();
-               $comment_id = self::factory()->comment->create(
-                       array(
-                               'comment_post_ID'  => $post_id,
-                               'comment_approved' => '1',
-                       )
-               );
-
-               $table = _get_list_table( 'WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
-               $table->prepare_items();
-
-               ob_start();
-               $table->extra_tablenav( 'top' );
-               $output = ob_get_clean();
-
-               $this->assertStringContainsString( 'id="post-query-submit"', $output );
-       }
-
-       /**
-        * @ticket 40188
-        *
-        * @covers WP_Posts_List_Table::extra_tablenav
-        */
-       public function test_filter_comment_type_dropdown_should_be_shown_if_there_are_comments() {
-               $post_id    = self::factory()->post->create();
-               $comment_id = self::factory()->comment->create(
-                       array(
-                               'comment_post_ID'  => $post_id,
-                               'comment_approved' => '1',
-                       )
-               );
-
-               $table = _get_list_table( 'WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
-               $table->prepare_items();
-
-               ob_start();
-               $table->extra_tablenav( 'top' );
-               $output = ob_get_clean();
-
-               $this->assertStringContainsString( 'id="filter-by-comment-type"', $output );
-               $this->assertStringContainsString( "<option value='comment'>", $output );
-       }
-
-       /**
-        * @ticket 38341
-        *
-        * @covers WP_Posts_List_Table::extra_tablenav
-        */
-       public function test_empty_trash_button_should_not_be_shown_if_there_are_no_comments() {
-               $table = _get_list_table( 'WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
-
-               ob_start();
-               $table->extra_tablenav( 'top' );
-               $output = ob_get_clean();
-
-               $this->assertStringNotContainsString( 'id="delete_all"', $output );
-       }
-
-       /**
-        * @ticket 19278
-        *
-        * @covers WP_Posts_List_Table::bulk_actions
-        */
-       public function test_bulk_action_menu_supports_options_and_optgroups() {
-               $table = _get_list_table( 'WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
-
-               add_filter(
-                       'bulk_actions-edit-comments',
-                       static function() {
-                               return array(
-                                       'delete'       => 'Delete',
-                                       'Change State' => array(
-                                               'feature' => 'Featured',
-                                               'sale'    => 'On Sale',
-                                       ),
-                               );
-                       }
-               );
-
-               ob_start();
-               $table->bulk_actions();
-               $output = ob_get_clean();
-
-               $expected = <<<'OPTIONS'
-<option value="delete">Delete</option>
-       <optgroup label="Change State">
-               <option value="feature">Featured</option>
-               <option value="sale">On Sale</option>
-       </optgroup>
-OPTIONS;
-               $expected = str_replace( "\r\n", "\n", $expected );
-
-               $this->assertStringContainsString( $expected, $output );
-       }
-
-       /**
-        * @ticket 45089
-        *
-        * @covers WP_Posts_List_Table::print_column_headers
-        */
-       public function test_sortable_columns() {
-               require_once ABSPATH . 'wp-admin/includes/class-wp-comments-list-table.php';
-
-               $override_sortable_columns = array(
-                       'author'   => array( 'comment_author', true ),
-                       'response' => 'comment_post_ID',
-                       'date'     => array( 'comment_date', 'dEsC' ), // The ordering support should be case-insensitive.
-               );
-
-               // Stub the get_sortable_columns() method.
-               $object = $this->getMockBuilder( 'WP_Comments_List_Table' )
-                       ->setConstructorArgs( array( array( 'screen' => 'edit-comments' ) ) )
-                       ->setMethods( array( 'get_sortable_columns' ) )
-                       ->getMock();
-
-               // Change the null return value of the stubbed get_sortable_columns() method.
-               $object->method( 'get_sortable_columns' )
-                       ->willReturn( $override_sortable_columns );
-
-               $output = get_echo( array( $object, 'print_column_headers' ) );
-
-               $this->assertStringContainsString( '?orderby=comment_author&#038;order=desc', $output, 'Mismatch of the default link ordering for comment author column. Should be desc.' );
-               $this->assertStringContainsString( 'column-author sortable asc', $output, 'Mismatch of CSS classes for the comment author column.' );
-
-               $this->assertStringContainsString( '?orderby=comment_post_ID&#038;order=asc', $output, 'Mismatch of the default link ordering for comment response column. Should be asc.' );
-               $this->assertStringContainsString( 'column-response sortable desc', $output, 'Mismatch of CSS classes for the comment post ID column.' );
-
-               $this->assertStringContainsString( '?orderby=comment_date&#038;order=desc', $output, 'Mismatch of the default link ordering for comment date column. Should be asc.' );
-               $this->assertStringContainsString( 'column-date sortable asc', $output, 'Mismatch of CSS classes for the comment date column.' );
-       }
-
-       /**
-        * @ticket 45089
-        *
-        * @covers WP_Posts_List_Table::print_column_headers
-        */
-       public function test_sortable_columns_with_current_ordering() {
-               require_once ABSPATH . 'wp-admin/includes/class-wp-comments-list-table.php';
-
-               $override_sortable_columns = array(
-                       'author'   => array( 'comment_author', false ),
-                       'response' => 'comment_post_ID',
-                       'date'     => array( 'comment_date', 'asc' ), // We will override this with current ordering.
-               );
-
-               // Current ordering.
-               $_GET['orderby'] = 'comment_date';
-               $_GET['order']   = 'desc';
-
-               // Stub the get_sortable_columns() method.
-               $object = $this->getMockBuilder( 'WP_Comments_List_Table' )
-                       ->setConstructorArgs( array( array( 'screen' => 'edit-comments' ) ) )
-                       ->setMethods( array( 'get_sortable_columns' ) )
-                       ->getMock();
-
-               // Change the null return value of the stubbed get_sortable_columns() method.
-               $object->method( 'get_sortable_columns' )
-                       ->willReturn( $override_sortable_columns );
-
-               $output = get_echo( array( $object, 'print_column_headers' ) );
-
-               $this->assertStringContainsString( '?orderby=comment_author&#038;order=asc', $output, 'Mismatch of the default link ordering for comment author column. Should be asc.' );
-               $this->assertStringContainsString( 'column-author sortable desc', $output, 'Mismatch of CSS classes for the comment author column.' );
-
-               $this->assertStringContainsString( '?orderby=comment_post_ID&#038;order=asc', $output, 'Mismatch of the default link ordering for comment response column. Should be asc.' );
-               $this->assertStringContainsString( 'column-response sortable desc', $output, 'Mismatch of CSS classes for the comment post ID column.' );
-
-               $this->assertStringContainsString( '?orderby=comment_date&#038;order=asc', $output, 'Mismatch of the current link ordering for comment date column. Should be asc.' );
-               $this->assertStringContainsString( 'column-date sorted desc', $output, 'Mismatch of CSS classes for the comment date column.' );
-       }
-
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsadminwpCommentsListTablephpfromrev51995trunktestsphpunittestsadminincludesListTablephp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/admin/wpCommentsListTable.php (from rev 51995, trunk/tests/phpunit/tests/admin/includesListTable.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/admin/wpCommentsListTable.php                           (rev 0)
+++ trunk/tests/phpunit/tests/admin/wpCommentsListTable.php     2021-11-03 00:48:42 UTC (rev 51997)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,198 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * @group admin
+ */
+class Tests_Admin_wpCommentsListTable extends WP_UnitTestCase {
+
+       /**
+        * @var WP_Comments_List_Table
+        */
+       protected $table;
+
+       function set_up() {
+               parent::set_up();
+               $this->table = _get_list_table( 'WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
+       }
+
+       /**
+        * @ticket 40188
+        *
+        * @covers WP_Posts_List_Table::extra_tablenav
+        */
+       public function test_filter_button_should_not_be_shown_if_there_are_no_comments() {
+               ob_start();
+               $this->table->extra_tablenav( 'top' );
+               $output = ob_get_clean();
+
+               $this->assertStringNotContainsString( 'id="post-query-submit"', $output );
+       }
+
+       /**
+        * @ticket 40188
+        *
+        * @covers WP_Posts_List_Table::extra_tablenav
+        */
+       public function test_filter_button_should_be_shown_if_there_are_comments() {
+               $post_id    = self::factory()->post->create();
+               $comment_id = self::factory()->comment->create(
+                       array(
+                               'comment_post_ID'  => $post_id,
+                               'comment_approved' => '1',
+                       )
+               );
+
+               $this->table->prepare_items();
+
+               ob_start();
+               $this->table->extra_tablenav( 'top' );
+               $output = ob_get_clean();
+
+               $this->assertStringContainsString( 'id="post-query-submit"', $output );
+       }
+
+       /**
+        * @ticket 40188
+        *
+        * @covers WP_Posts_List_Table::extra_tablenav
+        */
+       public function test_filter_comment_type_dropdown_should_be_shown_if_there_are_comments() {
+               $post_id    = self::factory()->post->create();
+               $comment_id = self::factory()->comment->create(
+                       array(
+                               'comment_post_ID'  => $post_id,
+                               'comment_approved' => '1',
+                       )
+               );
+
+               $this->table->prepare_items();
+
+               ob_start();
+               $this->table->extra_tablenav( 'top' );
+               $output = ob_get_clean();
+
+               $this->assertStringContainsString( 'id="filter-by-comment-type"', $output );
+               $this->assertStringContainsString( "<option value='comment'>", $output );
+       }
+
+       /**
+        * @ticket 38341
+        *
+        * @covers WP_Posts_List_Table::extra_tablenav
+        */
+       public function test_empty_trash_button_should_not_be_shown_if_there_are_no_comments() {
+               ob_start();
+               $this->table->extra_tablenav( 'top' );
+               $output = ob_get_clean();
+
+               $this->assertStringNotContainsString( 'id="delete_all"', $output );
+       }
+
+       /**
+        * @ticket 19278
+        *
+        * @covers WP_Posts_List_Table::bulk_actions
+        */
+       public function test_bulk_action_menu_supports_options_and_optgroups() {
+               add_filter(
+                       'bulk_actions-edit-comments',
+                       static function() {
+                               return array(
+                                       'delete'       => 'Delete',
+                                       'Change State' => array(
+                                               'feature' => 'Featured',
+                                               'sale'    => 'On Sale',
+                                       ),
+                               );
+                       }
+               );
+
+               ob_start();
+               $this->table->bulk_actions();
+               $output = ob_get_clean();
+
+               $expected = <<<'OPTIONS'
+<option value="delete">Delete</option>
+       <optgroup label="Change State">
+               <option value="feature">Featured</option>
+               <option value="sale">On Sale</option>
+       </optgroup>
+OPTIONS;
+               $expected = str_replace( "\r\n", "\n", $expected );
+
+               $this->assertStringContainsString( $expected, $output );
+       }
+
+       /**
+        * @ticket 45089
+        *
+        * @covers WP_Posts_List_Table::print_column_headers
+        */
+       public function test_sortable_columns() {
+               $override_sortable_columns = array(
+                       'author'   => array( 'comment_author', true ),
+                       'response' => 'comment_post_ID',
+                       'date'     => array( 'comment_date', 'dEsC' ), // The ordering support should be case-insensitive.
+               );
+
+               // Stub the get_sortable_columns() method.
+               $object = $this->getMockBuilder( 'WP_Comments_List_Table' )
+                       ->setConstructorArgs( array( array( 'screen' => 'edit-comments' ) ) )
+                       ->setMethods( array( 'get_sortable_columns' ) )
+                       ->getMock();
+
+               // Change the null return value of the stubbed get_sortable_columns() method.
+               $object->method( 'get_sortable_columns' )
+                       ->willReturn( $override_sortable_columns );
+
+               $output = get_echo( array( $object, 'print_column_headers' ) );
+
+               $this->assertStringContainsString( '?orderby=comment_author&#038;order=desc', $output, 'Mismatch of the default link ordering for comment author column. Should be desc.' );
+               $this->assertStringContainsString( 'column-author sortable asc', $output, 'Mismatch of CSS classes for the comment author column.' );
+
+               $this->assertStringContainsString( '?orderby=comment_post_ID&#038;order=asc', $output, 'Mismatch of the default link ordering for comment response column. Should be asc.' );
+               $this->assertStringContainsString( 'column-response sortable desc', $output, 'Mismatch of CSS classes for the comment post ID column.' );
+
+               $this->assertStringContainsString( '?orderby=comment_date&#038;order=desc', $output, 'Mismatch of the default link ordering for comment date column. Should be asc.' );
+               $this->assertStringContainsString( 'column-date sortable asc', $output, 'Mismatch of CSS classes for the comment date column.' );
+       }
+
+       /**
+        * @ticket 45089
+        *
+        * @covers WP_Posts_List_Table::print_column_headers
+        */
+       public function test_sortable_columns_with_current_ordering() {
+               $override_sortable_columns = array(
+                       'author'   => array( 'comment_author', false ),
+                       'response' => 'comment_post_ID',
+                       'date'     => array( 'comment_date', 'asc' ), // We will override this with current ordering.
+               );
+
+               // Current ordering.
+               $_GET['orderby'] = 'comment_date';
+               $_GET['order']   = 'desc';
+
+               // Stub the get_sortable_columns() method.
+               $object = $this->getMockBuilder( 'WP_Comments_List_Table' )
+                       ->setConstructorArgs( array( array( 'screen' => 'edit-comments' ) ) )
+                       ->setMethods( array( 'get_sortable_columns' ) )
+                       ->getMock();
+
+               // Change the null return value of the stubbed get_sortable_columns() method.
+               $object->method( 'get_sortable_columns' )
+                       ->willReturn( $override_sortable_columns );
+
+               $output = get_echo( array( $object, 'print_column_headers' ) );
+
+               $this->assertStringContainsString( '?orderby=comment_author&#038;order=asc', $output, 'Mismatch of the default link ordering for comment author column. Should be asc.' );
+               $this->assertStringContainsString( 'column-author sortable desc', $output, 'Mismatch of CSS classes for the comment author column.' );
+
+               $this->assertStringContainsString( '?orderby=comment_post_ID&#038;order=asc', $output, 'Mismatch of the default link ordering for comment response column. Should be asc.' );
+               $this->assertStringContainsString( 'column-response sortable desc', $output, 'Mismatch of CSS classes for the comment post ID column.' );
+
+               $this->assertStringContainsString( '?orderby=comment_date&#038;order=asc', $output, 'Mismatch of the current link ordering for comment date column. Should be asc.' );
+               $this->assertStringContainsString( 'column-date sorted desc', $output, 'Mismatch of CSS classes for the comment date column.' );
+       }
+
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsadminwpPostsListTablephpfromrev51996trunktestsphpunittestsadminincludesListTablephp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/admin/wpPostsListTable.php (from rev 51996, trunk/tests/phpunit/tests/admin/includesListTable.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/admin/wpPostsListTable.php                              (rev 0)
+++ trunk/tests/phpunit/tests/admin/wpPostsListTable.php        2021-11-03 00:48:42 UTC (rev 51997)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,322 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * @group admin
+ */
+class Tests_Admin_wpPostsListTable extends WP_UnitTestCase {
+       protected static $top           = array();
+       protected static $children      = array();
+       protected static $grandchildren = array();
+       protected static $post_ids      = array();
+
+       /**
+        * @var WP_Posts_List_Table
+        */
+       protected $table;
+
+       function set_up() {
+               parent::set_up();
+               $this->table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => 'edit-page' ) );
+       }
+
+       public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
+               // Note that our top/children/grandchildren arrays are 1-indexed.
+
+               // Create top-level pages.
+               $num_posts = 5;
+               foreach ( range( 1, $num_posts ) as $i ) {
+                       $p = $factory->post->create_and_get(
+                               array(
+                                       'post_type'  => 'page',
+                                       'post_title' => sprintf( 'Top Level Page %d', $i ),
+                               )
+                       );
+
+                       self::$top[ $i ]  = $p;
+                       self::$post_ids[] = $p->ID;
+               }
+
+               // Create child pages.
+               $num_children = 3;
+               foreach ( self::$top as $top => $top_page ) {
+                       foreach ( range( 1, $num_children ) as $i ) {
+                               $p = $factory->post->create_and_get(
+                                       array(
+                                               'post_type'   => 'page',
+                                               'post_parent' => $top_page->ID,
+                                               'post_title'  => sprintf( 'Child %d', $i ),
+                                       )
+                               );
+
+                               self::$children[ $top ][ $i ] = $p;
+                               self::$post_ids[]             = $p->ID;
+                       }
+               }
+
+               // Create grand-child pages for the third and fourth top-level pages.
+               $num_grandchildren = 3;
+               foreach ( range( 3, 4 ) as $top ) {
+                       foreach ( self::$children[ $top ] as $child => $child_page ) {
+                               foreach ( range( 1, $num_grandchildren ) as $i ) {
+                                       $p = $factory->post->create_and_get(
+                                               array(
+                                                       'post_type'   => 'page',
+                                                       'post_parent' => $child_page->ID,
+                                                       'post_title'  => sprintf( 'Grandchild %d', $i ),
+                                               )
+                                       );
+
+                                       self::$grandchildren[ $top ][ $child ][ $i ] = $p;
+                                       self::$post_ids[]                            = $p->ID;
+                               }
+                       }
+               }
+       }
+
+       /**
+        * @ticket 15459
+        *
+        * @covers WP_Posts_List_Table::display_rows
+        * @covers WP_Posts_List_Table::set_hierarchical_display
+        */
+       function test_list_hierarchical_pages_first_page() {
+               $this->_test_list_hierarchical_page(
+                       array(
+                               'paged'          => 1,
+                               'posts_per_page' => 2,
+                       ),
+                       array(
+                               self::$top[1]->ID,
+                               self::$children[1][1]->ID,
+                       )
+               );
+       }
+
+       /**
+        * @ticket 15459
+        *
+        * @covers WP_Posts_List_Table::display_rows
+        * @covers WP_Posts_List_Table::set_hierarchical_display
+        */
+       function test_list_hierarchical_pages_second_page() {
+               $this->_test_list_hierarchical_page(
+                       array(
+                               'paged'          => 2,
+                               'posts_per_page' => 2,
+                       ),
+                       array(
+                               self::$top[1]->ID,
+                               self::$children[1][2]->ID,
+                               self::$children[1][3]->ID,
+                       )
+               );
+       }
+
+       /**
+        * @ticket 15459
+        *
+        * @covers WP_Posts_List_Table::display_rows
+        * @covers WP_Posts_List_Table::set_hierarchical_display
+        */
+       function test_search_hierarchical_pages_first_page() {
+               $this->_test_list_hierarchical_page(
+                       array(
+                               'paged'          => 1,
+                               'posts_per_page' => 2,
+                               's'              => 'Child',
+                       ),
+                       array(
+                               self::$children[1][1]->ID,
+                               self::$children[1][2]->ID,
+                       )
+               );
+       }
+
+       /**
+        * @ticket 15459
+        *
+        * @covers WP_Posts_List_Table::display_rows
+        * @covers WP_Posts_List_Table::set_hierarchical_display
+        */
+       function test_search_hierarchical_pages_second_page() {
+               $this->_test_list_hierarchical_page(
+                       array(
+                               'paged'          => 2,
+                               'posts_per_page' => 2,
+                               's'              => 'Top',
+                       ),
+                       array(
+                               self::$top[3]->ID,
+                               self::$top[4]->ID,
+                       )
+               );
+       }
+
+       /**
+        * @ticket 15459
+        *
+        * @covers WP_Posts_List_Table::display_rows
+        * @covers WP_Posts_List_Table::set_hierarchical_display
+        */
+       function test_grandchildren_hierarchical_pages_first_page() {
+               // Page 6 is the first page with grandchildren.
+               $this->_test_list_hierarchical_page(
+                       array(
+                               'paged'          => 6,
+                               'posts_per_page' => 2,
+                       ),
+                       array(
+                               self::$top[3]->ID,
+                               self::$children[3][1]->ID,
+                               self::$grandchildren[3][1][1]->ID,
+                               self::$grandchildren[3][1][2]->ID,
+                       )
+               );
+       }
+
+       /**
+        * @ticket 15459
+        *
+        * @covers WP_Posts_List_Table::display_rows
+        * @covers WP_Posts_List_Table::set_hierarchical_display
+        */
+       function test_grandchildren_hierarchical_pages_second_page() {
+               // Page 7 is the second page with grandchildren.
+               $this->_test_list_hierarchical_page(
+                       array(
+                               'paged'          => 7,
+                               'posts_per_page' => 2,
+                       ),
+                       array(
+                               self::$top[3]->ID,
+                               self::$children[3][1]->ID,
+                               self::$grandchildren[3][1][3]->ID,
+                               self::$children[3][2]->ID,
+                       )
+               );
+       }
+
+       /**
+        * Helper function to test the output of a page which uses `WP_Posts_List_Table`.
+        *
+        * @param array $args         Query args for the list of pages.
+        * @param array $expected_ids Expected IDs of pages returned.
+        */
+       protected function _test_list_hierarchical_page( array $args, array $expected_ids ) {
+               if ( PHP_VERSION_ID >= 80100 ) {
+                       /*
+                        * For the time being, ignoring PHP 8.1 "null to non-nullable" deprecations coming in
+                        * via hooked in filter functions until a more structural solution to the
+                        * "missing input validation" conundrum has been architected and implemented.
+                        */
+                       $this->expectDeprecation();
+                       $this->expectDeprecationMessageMatches( '`Passing null to parameter \#[0-9]+ \(\$[^\)]+\) of type [^ ]+ is deprecated`' );
+               }
+
+               $matches = array();
+
+               $_REQUEST['paged']   = $args['paged'];
+               $GLOBALS['per_page'] = $args['posts_per_page'];
+
+               $args = array_merge(
+                       array(
+                               'post_type' => 'page',
+                       ),
+                       $args
+               );
+
+               // Mimic the behaviour of `wp_edit_posts_query()`:
+               if ( ! isset( $args['orderby'] ) ) {
+                       $args['orderby']                = 'menu_order title';
+                       $args['order']                  = 'asc';
+                       $args['posts_per_page']         = -1;
+                       $args['posts_per_archive_page'] = -1;
+               }
+
+               // Effectively ignore the output until retrieving it later via `getActualOutput()`.
+               $this->expectOutputRegex( '`.`' );
+
+               $pages = new WP_Query( $args );
+
+               $this->table->set_hierarchical_display( true );
+               $this->table->display_rows( $pages->posts );
+               $output = $this->getActualOutput();
+
+               // Clean up.
+               unset( $_REQUEST['paged'] );
+               unset( $GLOBALS['per_page'] );
+
+               preg_match_all( '|<tr[^>]*>|', $output, $matches );
+
+               $this->assertCount( count( $expected_ids ), array_keys( $matches[0] ) );
+
+               foreach ( $expected_ids as $id ) {
+                       $this->assertStringContainsString( sprintf( 'id="post-%d"', $id ), $output );
+               }
+       }
+
+       /**
+        * @ticket 37407
+        *
+        * @covers WP_Posts_List_Table::extra_tablenav
+        */
+       function test_filter_button_should_not_be_shown_if_there_are_no_posts() {
+               // Set post type to a non-existent one.
+               $this->table->screen->post_type = 'foo';
+
+               ob_start();
+               $this->table->extra_tablenav( 'top' );
+               $output = ob_get_clean();
+
+               $this->assertStringNotContainsString( 'id="post-query-submit"', $output );
+       }
+
+       /**
+        * @ticket 37407
+        *
+        * @covers WP_Posts_List_Table::extra_tablenav
+        */
+       function test_months_dropdown_should_not_be_shown_if_there_are_no_posts() {
+               // Set post type to a non-existent one.
+               $this->table->screen->post_type = 'foo';
+
+               ob_start();
+               $this->table->extra_tablenav( 'top' );
+               $output = ob_get_clean();
+
+               $this->assertStringNotContainsString( 'id="filter-by-date"', $output );
+       }
+
+       /**
+        * @ticket 37407
+        *
+        * @covers WP_Posts_List_Table::extra_tablenav
+        */
+       function test_category_dropdown_should_not_be_shown_if_there_are_no_posts() {
+               // Set post type to a non-existent one.
+               $this->table->screen->post_type = 'foo';
+
+               ob_start();
+               $this->table->extra_tablenav( 'top' );
+               $output = ob_get_clean();
+
+               $this->assertStringNotContainsString( 'id="cat"', $output );
+       }
+
+       /**
+        * @ticket 38341
+        *
+        * @covers WP_Posts_List_Table::extra_tablenav
+        */
+       public function test_empty_trash_button_should_not_be_shown_if_there_are_no_posts() {
+               // Set post type to a non-existent one.
+               $this->table->screen->post_type = 'foo';
+
+               ob_start();
+               $this->table->extra_tablenav( 'top' );
+               $output = ob_get_clean();
+
+               $this->assertStringNotContainsString( 'id="delete_all"', $output );
+       }
+
+}
</ins></span></pre>
</div>
</div>

</body>
</html>