From e74339ed60674870cda36f80226d6bf221192de7 Mon Sep 17 00:00:00 2001 From: noruzzamans Date: Fri, 9 Oct 2026 12:15:33 +0600 Subject: [PATCH 1/6] test: cover the admin bar, active-posts widget and Users list edge paths --- plugins/presence-api/tests/test-admin-bar.php | 60 +++++++++++++++++++ plugins/presence-api/tests/test-user-list.php | 2 + .../widgets/test-widget-active-posts.php | 11 ++++ 3 files changed, 73 insertions(+) diff --git a/plugins/presence-api/tests/test-admin-bar.php b/plugins/presence-api/tests/test-admin-bar.php index ea11e3f9..34b4dd97 100644 --- a/plugins/presence-api/tests/test-admin-bar.php +++ b/plugins/presence-api/tests/test-admin-bar.php @@ -10,6 +10,8 @@ * @covers ::wp_presence_admin_bar_assets * @covers ::wp_presence_admin_bar_node_markup * @covers ::wp_presence_admin_bar_heartbeat_received + * @covers ::wp_presence_refresh_screen_token + * @covers ::wp_presence_get_entry_screen * @covers ::wp_presence_screen_object_id * @covers ::wp_presence_get_user_color * @covers ::wp_presence_online_users_url @@ -320,6 +322,8 @@ public function test_a_crowded_screen_names_only_a_few() { public function test_someone_editing_a_post_links_to_it() { $this->put_editor_on_post( self::$post_id ); + wp_set_presence( wp_presence_post_room( self::$post_id ), 'editor-' . self::$editor_id, array(), array( 'user_id' => self::$editor_id ) ); + wp_set_presence( 'postType/bad', 'bad-' . self::$editor_id, array(), array( 'user_id' => self::$editor_id ) ); wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) ); $place = $this->place_of( $this->render_nodes(), self::$editor_id ); @@ -477,6 +481,43 @@ public function test_readers_of_another_page_are_not_on_this_page() { $this->assertSame( 'presence-elsewhere', $nodes[ 'presence-user-' . $there ]->parent ); } + public function test_people_on_the_front_end_link_to_posts_you_can_read() { + set_current_screen( 'dashboard' ); + $published_id = self::factory()->post->create( + array( + 'post_title' => 'Public Post', + 'post_status' => 'publish', + ) + ); + $on_home = $this->put_user_on_screen( 'front', array( 'title' => 'Home' ) ); + $on_published = $this->put_user_on_screen( + 'front', + array( + 'title' => 'Public Post', + 'post_id' => $published_id, + ) + ); + $on_draft = $this->put_user_on_screen( + 'front', + array( + 'title' => 'Secret Draft', + 'post_id' => self::$post_id, + ) + ); + + wp_set_current_user( self::factory()->user->create( array( 'role' => 'contributor' ) ) ); + $this->let_current_user_list_users(); + $nodes = $this->render_nodes(); + + $this->assertArrayNotHasKey( 'presence-user-' . $on_published, $nodes ); + $this->assertSame( get_permalink( $published_id ), $nodes['presence-place-0']->href ); + $this->assertStringContainsString( '>Public Post', $nodes['presence-place-0']->title ); + $this->assertSame( 'Home', $this->place_of( $nodes, $on_home )->title ); + $this->assertFalse( $this->place_of( $nodes, $on_home )->href ); + $this->assertSame( esc_html( get_userdata( $on_draft )->display_name ), $nodes[ 'presence-user-' . $on_draft ]->title ); + $this->assertFalse( $nodes[ 'presence-user-' . $on_draft ]->href ); + } + public function test_rows_are_not_links() { $this->view_admin_page( 'upload.php', 'upload' ); $user_id = $this->put_user_on_screen( 'upload' ); @@ -783,5 +824,24 @@ static function ( $is_agent, $user_id ) use ( $agent_id ) { $title = $nodes[ 'presence-user-' . $agent_id ]->title; $this->assertStringContainsString( $agent->display_name, $title ); $this->assertStringContainsString( 'presence-agent-badge', $title ); + + wp_remove_presence( wp_presence_post_room( self::$post_id ), 'agent-' . $agent_id ); + wp_set_presence( + 'admin/online', + 'agent-screen-' . $agent_id, + array( + 'screen' => 'users', + 'title' => 'Users', + ), + array( 'user_id' => $agent_id ) + ); + $nodes = $this->render_nodes(); + $this->assertSame( $agent->display_name . ' (agent)', $nodes['presence-place-0']->meta['title'] ); + } + + public function test_node_markup_is_empty_for_a_user_without_edit_posts() { + wp_set_current_user( self::factory()->user->create( array( 'role' => 'subscriber' ) ) ); + + $this->assertSame( '', wp_presence_admin_bar_node_markup( 'dashboard' ) ); } } diff --git a/plugins/presence-api/tests/test-user-list.php b/plugins/presence-api/tests/test-user-list.php index c2a5fb56..e441e4de 100644 --- a/plugins/presence-api/tests/test-user-list.php +++ b/plugins/presence-api/tests/test-user-list.php @@ -189,10 +189,12 @@ public function test_every_users_view_gets_a_fresh_online_count() { $this->assertSame( '(1)', wp_presence_users_online_count_heartbeat_received( array(), $ask, 'users' )['presence-fragments']['users-online-count'] ); $this->assertSame( array(), wp_presence_users_online_count_heartbeat_received( array(), $ask, 'users-network' ) ); + $this->assertSame( array(), wp_presence_users_online_count_heartbeat_received( array(), array(), 'users' ) ); } public function test_the_online_view_needs_its_nonce() { $this->assertSame( array(), $this->tick_online_view( 'invalid' ) ); + $this->assertSame( array(), wp_presence_users_list_heartbeat_received( array(), array(), 'users' ) ); } /** diff --git a/plugins/presence-api/tests/widgets/test-widget-active-posts.php b/plugins/presence-api/tests/widgets/test-widget-active-posts.php index 281905e8..3550390d 100644 --- a/plugins/presence-api/tests/widgets/test-widget-active-posts.php +++ b/plugins/presence-api/tests/widgets/test-widget-active-posts.php @@ -107,6 +107,14 @@ public function test_heartbeat_received_ignores_without_ping() { $this->assertArrayNotHasKey( 'presence-fragments', $response ); $this->assertArrayHasKey( 'existing', $response ); + + wp_set_current_user( self::factory()->user->create( array( 'role' => 'subscriber' ) ) ); + $unauthorised = WP_Presence_Widget_Active_Posts::heartbeat_received( + array(), + array( 'presence-fragments' => array( 'active-posts' => true ) ), + 'dashboard' + ); + $this->assertSame( array(), $unauthorised ); } /** @@ -174,6 +182,9 @@ public function test_excludes_non_post_rooms() { wp_set_current_user( self::$editor_id ); wp_set_presence( 'admin/online', 'user-' . self::$editor_id, array(), array( 'user_id' => self::$editor_id ) ); + wp_set_presence( wp_presence_post_room( self::$post_id ), 'deleted-user', array(), array( 'user_id' => 999901 ) ); + wp_set_presence( 'postType/bad', 'bad-room', array(), array( 'user_id' => self::$editor_id ) ); + wp_set_presence( 'postType/attachment:' . self::$post_id, 'attachment-room', array(), array( 'user_id' => self::$editor_id ) ); $posts = $this->active_posts(); From 3ad73448d6c27aa0260a7cf9ed02d702e9d10878 Mon Sep 17 00:00:00 2001 From: noruzzamans Date: Sun, 11 Oct 2026 15:36:48 +0600 Subject: [PATCH 2/6] test: isolate edge-path assertions into dedicated test methods --- plugins/presence-api/tests/test-admin-bar.php | 19 ++++++- plugins/presence-api/tests/test-user-list.php | 9 +++- .../widgets/test-widget-active-posts.php | 49 ++++++++++++++++++- 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/plugins/presence-api/tests/test-admin-bar.php b/plugins/presence-api/tests/test-admin-bar.php index 34b4dd97..7d3b00a7 100644 --- a/plugins/presence-api/tests/test-admin-bar.php +++ b/plugins/presence-api/tests/test-admin-bar.php @@ -322,9 +322,26 @@ public function test_a_crowded_screen_names_only_a_few() { public function test_someone_editing_a_post_links_to_it() { $this->put_editor_on_post( self::$post_id ); - wp_set_presence( wp_presence_post_room( self::$post_id ), 'editor-' . self::$editor_id, array(), array( 'user_id' => self::$editor_id ) ); + + wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) ); + $place = $this->place_of( $this->render_nodes(), self::$editor_id ); + + $this->assertSame( get_edit_post_link( self::$post_id, 'raw' ), $place->href ); + $this->assertSame( 'Secret Draft', $place->title ); + } + + public function test_unparseable_post_room_is_skipped_and_first_post_room_wins() { + $this->put_editor_on_post( self::$post_id ); wp_set_presence( 'postType/bad', 'bad-' . self::$editor_id, array(), array( 'user_id' => self::$editor_id ) ); + $second_post_id = self::factory()->post->create( + array( + 'post_title' => 'Second Post', + 'post_status' => 'draft', + ) + ); + wp_set_presence( wp_presence_post_room( $second_post_id ), 'second-' . self::$editor_id, array(), array( 'user_id' => self::$editor_id ) ); + wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) ); $place = $this->place_of( $this->render_nodes(), self::$editor_id ); diff --git a/plugins/presence-api/tests/test-user-list.php b/plugins/presence-api/tests/test-user-list.php index e441e4de..170e5f62 100644 --- a/plugins/presence-api/tests/test-user-list.php +++ b/plugins/presence-api/tests/test-user-list.php @@ -189,11 +189,18 @@ public function test_every_users_view_gets_a_fresh_online_count() { $this->assertSame( '(1)', wp_presence_users_online_count_heartbeat_received( array(), $ask, 'users' )['presence-fragments']['users-online-count'] ); $this->assertSame( array(), wp_presence_users_online_count_heartbeat_received( array(), $ask, 'users-network' ) ); - $this->assertSame( array(), wp_presence_users_online_count_heartbeat_received( array(), array(), 'users' ) ); } public function test_the_online_view_needs_its_nonce() { $this->assertSame( array(), $this->tick_online_view( 'invalid' ) ); + } + + /** + * @covers ::wp_presence_users_online_count_heartbeat_received + * @covers ::wp_presence_users_list_heartbeat_received + */ + public function test_heartbeat_received_returns_empty_without_fragment_request() { + $this->assertSame( array(), wp_presence_users_online_count_heartbeat_received( array(), array(), 'users' ) ); $this->assertSame( array(), wp_presence_users_list_heartbeat_received( array(), array(), 'users' ) ); } diff --git a/plugins/presence-api/tests/widgets/test-widget-active-posts.php b/plugins/presence-api/tests/widgets/test-widget-active-posts.php index 3550390d..fb8ea5cc 100644 --- a/plugins/presence-api/tests/widgets/test-widget-active-posts.php +++ b/plugins/presence-api/tests/widgets/test-widget-active-posts.php @@ -107,7 +107,12 @@ public function test_heartbeat_received_ignores_without_ping() { $this->assertArrayNotHasKey( 'presence-fragments', $response ); $this->assertArrayHasKey( 'existing', $response ); + } + /** + * @covers WP_Presence_Widget_Active_Posts::heartbeat_received + */ + public function test_heartbeat_received_ignores_unauthorised_user() { wp_set_current_user( self::factory()->user->create( array( 'role' => 'subscriber' ) ) ); $unauthorised = WP_Presence_Widget_Active_Posts::heartbeat_received( array(), @@ -182,15 +187,55 @@ public function test_excludes_non_post_rooms() { wp_set_current_user( self::$editor_id ); wp_set_presence( 'admin/online', 'user-' . self::$editor_id, array(), array( 'user_id' => self::$editor_id ) ); - wp_set_presence( wp_presence_post_room( self::$post_id ), 'deleted-user', array(), array( 'user_id' => 999901 ) ); wp_set_presence( 'postType/bad', 'bad-room', array(), array( 'user_id' => self::$editor_id ) ); - wp_set_presence( 'postType/attachment:' . self::$post_id, 'attachment-room', array(), array( 'user_id' => self::$editor_id ) ); $posts = $this->active_posts(); $this->assertCount( 0, $posts ); } + /** + * @covers WP_Presence_Widget_Active_Posts::build_active_posts_data + */ + public function test_active_posts_skips_users_that_no_longer_exist() { + wp_set_current_user( self::$editor_id ); + + wp_set_presence( wp_presence_post_room( self::$post_id ), 'deleted-user', array(), array( 'user_id' => 999901 ) ); + + $posts = $this->active_posts(); + + $this->assertCount( 0, $posts ); + } + + /** + * @covers WP_Presence_Widget_Active_Posts::build_active_posts_data + */ + public function test_active_posts_excludes_posts_without_presence_support() { + register_post_type( + 'no_presence_support', + array( + 'public' => true, + 'supports' => array( 'title', 'editor' ), + ) + ); + $post_id = self::factory()->post->create( + array( + 'post_type' => 'no_presence_support', + 'post_status' => 'publish', + 'post_author' => self::$editor_id, + ) + ); + wp_set_current_user( self::$editor_id ); + + $room = 'postType/no_presence_support:' . $post_id; + wp_set_presence( $room, 'user-' . self::$editor_id, array(), array( 'user_id' => self::$editor_id ) ); + + $posts = $this->active_posts(); + $this->assertCount( 0, $posts ); + + _unregister_post_type( 'no_presence_support' ); + } + /** * A contributor has `edit_posts`, which is all the widget itself requires, * but cannot edit someone else's post and must not learn it is being From 5cf46f642f217a439f3f1aa8842f862511ec84e7 Mon Sep 17 00:00:00 2001 From: noruzzamans Date: Sun, 11 Oct 2026 15:40:59 +0600 Subject: [PATCH 3/6] test: fix typo in unparsable test method name --- plugins/presence-api/tests/test-admin-bar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/presence-api/tests/test-admin-bar.php b/plugins/presence-api/tests/test-admin-bar.php index 7d3b00a7..3bda0735 100644 --- a/plugins/presence-api/tests/test-admin-bar.php +++ b/plugins/presence-api/tests/test-admin-bar.php @@ -330,7 +330,7 @@ public function test_someone_editing_a_post_links_to_it() { $this->assertSame( 'Secret Draft', $place->title ); } - public function test_unparseable_post_room_is_skipped_and_first_post_room_wins() { + public function test_unparsable_post_room_is_skipped_and_first_post_room_wins() { $this->put_editor_on_post( self::$post_id ); wp_set_presence( 'postType/bad', 'bad-' . self::$editor_id, array(), array( 'user_id' => self::$editor_id ) ); From e0b90a91c05d676960854e04e02bfea4b90b1b68 Mon Sep 17 00:00:00 2001 From: noruzzamans Date: Sun, 11 Oct 2026 15:46:29 +0600 Subject: [PATCH 4/6] test: ensure dummy post type explicitly lacks presence support --- .../presence-api/tests/widgets/test-widget-active-posts.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/presence-api/tests/widgets/test-widget-active-posts.php b/plugins/presence-api/tests/widgets/test-widget-active-posts.php index fb8ea5cc..9a65b1d3 100644 --- a/plugins/presence-api/tests/widgets/test-widget-active-posts.php +++ b/plugins/presence-api/tests/widgets/test-widget-active-posts.php @@ -215,9 +215,11 @@ public function test_active_posts_excludes_posts_without_presence_support() { 'no_presence_support', array( 'public' => true, - 'supports' => array( 'title', 'editor' ), + 'supports' => array( 'title' ), ) ); + remove_post_type_support( 'no_presence_support', 'presence' ); + $post_id = self::factory()->post->create( array( 'post_type' => 'no_presence_support', @@ -234,6 +236,7 @@ public function test_active_posts_excludes_posts_without_presence_support() { $this->assertCount( 0, $posts ); _unregister_post_type( 'no_presence_support' ); + wp_presence_forget_post_type( 'no_presence_support' ); } /** From 99ba54cbbdc57287af04e8c048d0b5a75357656d Mon Sep 17 00:00:00 2001 From: noruzzamans Date: Tue, 13 Oct 2026 08:41:58 +0600 Subject: [PATCH 5/6] test: tighten edge-path assertions per maintainer review --- plugins/presence-api/tests/test-admin-bar.php | 11 +++++++++-- plugins/presence-api/tests/test-user-list.php | 2 ++ .../tests/widgets/test-widget-active-posts.php | 13 ------------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/plugins/presence-api/tests/test-admin-bar.php b/plugins/presence-api/tests/test-admin-bar.php index 92531252..69854687 100644 --- a/plugins/presence-api/tests/test-admin-bar.php +++ b/plugins/presence-api/tests/test-admin-bar.php @@ -332,7 +332,6 @@ public function test_someone_editing_a_post_links_to_it() { public function test_unparsable_post_room_is_skipped_and_first_post_room_wins() { $this->put_editor_on_post( self::$post_id ); - wp_set_presence( 'postType/bad', 'bad-' . self::$editor_id, array(), array( 'user_id' => self::$editor_id ) ); $second_post_id = self::factory()->post->create( array( @@ -342,11 +341,19 @@ public function test_unparsable_post_room_is_skipped_and_first_post_room_wins() ); wp_set_presence( wp_presence_post_room( $second_post_id ), 'second-' . self::$editor_id, array(), array( 'user_id' => self::$editor_id ) ); + $other_user_id = $this->put_user_on_screen( 'edit-comments', array( 'title' => 'Comments' ) ); + wp_set_presence( 'postType/bad', 'bad-' . $other_user_id, array(), array( 'user_id' => $other_user_id ) ); + wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) ); - $place = $this->place_of( $this->render_nodes(), self::$editor_id ); + $nodes = $this->render_nodes(); + $place = $this->place_of( $nodes, self::$editor_id ); $this->assertSame( get_edit_post_link( self::$post_id, 'raw' ), $place->href ); $this->assertSame( 'Secret Draft', $place->title ); + + $other_place = $this->place_of( $nodes, $other_user_id ); + $this->assertSame( admin_url( 'edit-comments.php' ), $other_place->href ); + $this->assertSame( 'Comments', $other_place->title ); } public function test_someone_editing_a_template_in_the_site_editor_links_to_it() { diff --git a/plugins/presence-api/tests/test-user-list.php b/plugins/presence-api/tests/test-user-list.php index 170e5f62..efd16575 100644 --- a/plugins/presence-api/tests/test-user-list.php +++ b/plugins/presence-api/tests/test-user-list.php @@ -200,6 +200,8 @@ public function test_the_online_view_needs_its_nonce() { * @covers ::wp_presence_users_list_heartbeat_received */ public function test_heartbeat_received_returns_empty_without_fragment_request() { + wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) ); + $this->assertSame( array(), wp_presence_users_online_count_heartbeat_received( array(), array(), 'users' ) ); $this->assertSame( array(), wp_presence_users_list_heartbeat_received( array(), array(), 'users' ) ); } diff --git a/plugins/presence-api/tests/widgets/test-widget-active-posts.php b/plugins/presence-api/tests/widgets/test-widget-active-posts.php index 9a65b1d3..07bad5db 100644 --- a/plugins/presence-api/tests/widgets/test-widget-active-posts.php +++ b/plugins/presence-api/tests/widgets/test-widget-active-posts.php @@ -109,19 +109,6 @@ public function test_heartbeat_received_ignores_without_ping() { $this->assertArrayHasKey( 'existing', $response ); } - /** - * @covers WP_Presence_Widget_Active_Posts::heartbeat_received - */ - public function test_heartbeat_received_ignores_unauthorised_user() { - wp_set_current_user( self::factory()->user->create( array( 'role' => 'subscriber' ) ) ); - $unauthorised = WP_Presence_Widget_Active_Posts::heartbeat_received( - array(), - array( 'presence-fragments' => array( 'active-posts' => true ) ), - 'dashboard' - ); - $this->assertSame( array(), $unauthorised ); - } - /** * @covers WP_Presence_Widget_Active_Posts::build_active_posts_data */ From 5c79e8f092941b9e5adf610c7779429fefa6746f Mon Sep 17 00:00:00 2001 From: noruzzamans Date: Tue, 13 Oct 2026 08:57:09 +0600 Subject: [PATCH 6/6] test: isolate unparsable post room to dedicated user --- plugins/presence-api/tests/test-admin-bar.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/plugins/presence-api/tests/test-admin-bar.php b/plugins/presence-api/tests/test-admin-bar.php index 69854687..19950664 100644 --- a/plugins/presence-api/tests/test-admin-bar.php +++ b/plugins/presence-api/tests/test-admin-bar.php @@ -341,19 +341,14 @@ public function test_unparsable_post_room_is_skipped_and_first_post_room_wins() ); wp_set_presence( wp_presence_post_room( $second_post_id ), 'second-' . self::$editor_id, array(), array( 'user_id' => self::$editor_id ) ); - $other_user_id = $this->put_user_on_screen( 'edit-comments', array( 'title' => 'Comments' ) ); - wp_set_presence( 'postType/bad', 'bad-' . $other_user_id, array(), array( 'user_id' => $other_user_id ) ); + $second_user_id = self::factory()->user->create( array( 'role' => 'editor' ) ); + wp_set_presence( 'postType/bad', 'bad-' . $second_user_id, array(), array( 'user_id' => $second_user_id ) ); wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) ); - $nodes = $this->render_nodes(); + $place = $this->place_of( $this->render_nodes(), self::$editor_id ); - $place = $this->place_of( $nodes, self::$editor_id ); $this->assertSame( get_edit_post_link( self::$post_id, 'raw' ), $place->href ); $this->assertSame( 'Secret Draft', $place->title ); - - $other_place = $this->place_of( $nodes, $other_user_id ); - $this->assertSame( admin_url( 'edit-comments.php' ), $other_place->href ); - $this->assertSame( 'Comments', $other_place->title ); } public function test_someone_editing_a_template_in_the_site_editor_links_to_it() {