storePair(); $GLOBALS['wpcs_current_user_can']['manage_options'] = true; $GLOBALS['wpcs_nonce_valid']['wpcs_test_connection']['wpcs_connection_nonce'] = true; $_POST['pair_index'] = '0'; $this->controller()->handleTest(); self::assertStringContainsString( 'wpcs_connection_ok=1', $GLOBALS['wpcs_redirect_location'] ); self::assertSame( 'GET', $GLOBALS['wpcs_last_http_request']['method'] ); self::assertSame( 'https://destination.test/wp-json/wp-content-sync/v1/status', $GLOBALS['wpcs_last_http_request']['url'] ); } public function test_it_rejects_users_without_manage_options(): void { $GLOBALS['wpcs_current_user_can']['manage_options'] = false; $this->expectException( \RuntimeException::class ); $this->expectExceptionMessage( 'You do not have permission to test WP Content Sync connections.' ); $this->controller()->handleTest(); } public function test_it_rejects_invalid_nonces(): void { $GLOBALS['wpcs_nonce_valid']['wpcs_test_connection']['wpcs_connection_nonce'] = false; $this->expectException( \RuntimeException::class ); $this->expectExceptionMessage( 'The connection test request could not be verified.' ); $this->controller()->handleTest(); } public function test_it_redirects_failures_without_leaking_application_passwords(): void { $this->storePair(); $GLOBALS['wpcs_current_user_can']['manage_options'] = true; $GLOBALS['wpcs_nonce_valid']['wpcs_test_connection']['wpcs_connection_nonce'] = true; $GLOBALS['wpcs_http_response'] = array( 'response' => array( 'code' => 401 ), 'body' => '{"message":"Unauthorized"}', ); $_POST['pair_index'] = '0'; $this->controller()->handleTest(); self::assertStringContainsString( 'wpcs_connection_error=', $GLOBALS['wpcs_redirect_location'] ); self::assertStringNotContainsString( 'app-pass', $GLOBALS['wpcs_redirect_location'] ); self::assertStringNotContainsString( 'app-pass', wp_json_encode( $GLOBALS['wpcs_test_options'][ OptionLogger::OPTION_NAME ] ) ); } private function controller(): ConnectionTestController { return new ConnectionTestController( new SettingsRepository(), new RestTransportClient(), new OptionLogger() ); } private function storePair(): void { update_option( SettingsRepository::OPTION_NAME, array( 'sync_pairs' => array( array( 'name' => 'Staging', 'source_url' => 'https://source.test', 'destination_url' => 'https://destination.test', 'username' => 'codex', 'application_password' => 'app-pass', ), ), ), false ); } }