WP User Query fails when searching meta queries and search columns

Combining a meta query with a search for a keyword will return posts which match both the search query and the result of the meta query (even if you’re using relation => OR in the meta query).

This answer covers a way to achieve your expected outcome for posts, which – you need to modify the query before it fetches the result. That will need to be modified to be used with a WP User Query however. I’ve made an attempt at a solution that searches for the search term in the user_nicename, user_email and your meta fields – untested, so might need tweaking.

add_action( 'pre_user_query', 'user_meta_OR_search');
function user_meta_OR_search($q){
    if ($search = $q->get('_meta_or_search')){
        add_filter( 'get_meta_sql', function( $sql ) use ( $search ){
            global $wpdb;

            // Only run once:
            static $nr = 0; 
            if( 0 != $nr++ ) return $sql;

            // Modify WHERE part:
            $where = sprintf(
                " AND ( %s OR %s OR %s ) ",
                $wpdb->prepare( "{$wpdb->users}.user_nicename like '%%%s%%'", $search),
                $wpdb->prepare( "{$wpdb->users}.user_email like '%%%s%%'", $search),
                mb_substr( $sql['where'], 5, mb_strlen( $sql['where'] ) )
            );

            $sql['where'] = $where;

            return $sql;
        });
    }
}

// Then, where you do the searching:
$search_term = "test";

$args = array(
    'fields' => ['ID'],
    'count_total' => true,
    'order' => 'ASC',   
    'orderby' => 'display_name',
    '_meta_or_search' => '*'.esc_attr( $search_term ).'*',
    "meta_query" => array(
        'relation' => 'OR',
        array(
            'key'     => 'first_name',
            'value'   => $search_term,
            'compare' => 'LIKE'
        ),
        array(
            'key'     => 'last_name',
            'value'   => $search_term,
            'compare' => 'LIKE'
              ),
        array(
            'key' => 'description',
            'value' => $search_term ,
            'compare' => 'LIKE'
        )
    )
);

$the_query = new WP_User_Query($args);

Another solution is to use two queries – one which does a general search using s and one searching using meta_query:

$args1 = array (
    'fields' => ['ID'],
    'count_total' => true,
    'order' => 'ASC',   
    'orderby' => 'display_name',
    'search' => '*'.esc_attr( $search_term ).'*'
);

$wp_user_query1 = new WP_User_Query($args1);
$args2 = array (
    'fields' => ['ID'],
    'count_total' => true,
    'order' => 'ASC',   
    'orderby' => 'display_name',
    'meta_query' => array(
        'relation' => 'OR',
        array(
            'key'     => 'first_name',
            'value'   => $search_term,
            'compare' => 'LIKE'
        ),
        array(
            'key'     => 'last_name',
            'value'   => $search_term,
            'compare' => 'LIKE'
        ),
        array(
            'key' => 'description',
            'value' => $search_term ,
            'compare' => 'LIKE'
        )
    )
);
$wp_user_query2 = new WP_User_Query($args2);

$result = new WP_User_Query();
$result->results = array_unique( array_merge( $wp_user_query1->results, $wp_user_query2->results ), SORT_REGULAR );
$result->post_count = count( $result->results );

This will merge the results of the two queries into a third query containing the final search results. I haven’t tested this, so it might need some tweaking!