@@ -33,12 +33,12 @@ class Test_Move extends \WP_UnitTestCase {
3333 private $ user_id_2 ;
3434
3535 /**
36- * Setup the test.
36+ * Set up the test.
3737 */
3838 public function setUp (): void {
3939 parent ::setUp ();
40- $ this ->user_id = $ this -> factory ->user ->create ();
41- $ this ->user_id_2 = $ this -> factory ->user ->create ();
40+ $ this ->user_id = self :: factory () ->user ->create ();
41+ $ this ->user_id_2 = self :: factory () ->user ->create ();
4242 }
4343
4444 /**
@@ -125,7 +125,7 @@ public function test_handle_move_with_target_and_origin() {
125125
126126 \wp_delete_post ( $ updated_follower ->ID );
127127
128- \remove_filter ( 'pre_http_request ' , $ filter, 10 );
128+ \remove_filter ( 'pre_http_request ' , $ filter );
129129 }
130130
131131 /**
@@ -232,6 +232,85 @@ public function test_handle_move_without_target_or_origin() {
232232 $ test_follower ->delete ();
233233 }
234234
235+ /**
236+ * Test the handle_move method when target exists but origin does not.
237+ *
238+ * This tests the scenario where the new profile is already followed,
239+ * but the old profile is not. In this case, no action should be taken.
240+ */
241+ public function test_handle_move_with_existing_target_but_missing_origin () {
242+ $ target = 'https://example.com/new-profile ' ;
243+ $ origin = 'https://example.com/old-profile ' ;
244+
245+ // Create only the target follower, not the origin.
246+ $ target_follower = new Actor ();
247+ $ target_follower ->set_inbox ( 'https://example.com/new-profile/inbox ' );
248+ $ target_follower ->set_type ( 'Person ' );
249+ $ target_follower ->set_id ( $ target );
250+ $ target_follower ->set_url ( $ target );
251+ $ target_id = Remote_Actors::upsert ( $ target_follower );
252+
253+ // Add user ID to target.
254+ \add_post_meta ( $ target_id , Followers::FOLLOWER_META_KEY , $ this ->user_id );
255+
256+ $ filter = function ( $ preempt , $ args , $ url ) use ( $ target , $ origin ) {
257+ if ( $ url === $ target ) {
258+ return array (
259+ 'body ' => \wp_json_encode (
260+ array (
261+ 'type ' => 'Person ' ,
262+ 'id ' => $ target ,
263+ 'url ' => $ target ,
264+ 'name ' => 'New Profile ' ,
265+ 'inbox ' => 'https://example.com/new-profile/inbox ' ,
266+ 'also_known_as ' => array ( $ origin ),
267+ )
268+ ),
269+ 'response ' => array ( 'code ' => 200 ),
270+ );
271+ }
272+ if ( $ url === $ origin ) {
273+ return array (
274+ 'body ' => \wp_json_encode (
275+ array (
276+ 'type ' => 'Person ' ,
277+ 'id ' => $ origin ,
278+ 'url ' => $ origin ,
279+ 'name ' => 'Old Profile ' ,
280+ 'inbox ' => 'https://example.com/old-profile/inbox ' ,
281+ 'movedTo ' => $ target ,
282+ )
283+ ),
284+ 'response ' => array ( 'code ' => 200 ),
285+ );
286+ }
287+ return $ preempt ;
288+ };
289+
290+ // Mock the HTTP request.
291+ \add_filter ( 'pre_http_request ' , $ filter , 10 , 3 );
292+
293+ $ activity = array (
294+ 'type ' => 'Move ' ,
295+ 'actor ' => $ origin ,
296+ 'object ' => $ target ,
297+ );
298+
299+ Move::handle_move ( $ activity , 1 );
300+
301+ // Verify that the target still exists with the same followers.
302+ $ target_users = \get_post_meta ( $ target_id , Followers::FOLLOWER_META_KEY , false );
303+ $ this ->assertContains ( (string ) $ this ->user_id , $ target_users );
304+ $ this ->assertCount ( 1 , $ target_users );
305+
306+ // Verify that no origin follower was created.
307+ $ this ->assertWPError ( Remote_Actors::get_by_uri ( $ origin ) );
308+
309+ // Cleanup.
310+ \wp_delete_post ( $ target_id );
311+ \remove_filter ( 'pre_http_request ' , $ filter );
312+ }
313+
235314 /**
236315 * Test the handle_move method with an existing target and origin.
237316 */
0 commit comments