From 5e89be73ba75975a82e22189a07f4be499feff62 Mon Sep 17 00:00:00 2001 From: Laura_Escamilla Date: Mon, 9 Jun 2025 13:26:36 +0000 Subject: [PATCH] Bug 39427: Split the argument for both name fields to be searched and added regex for spacing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug 39427: Unit tests To test: 1. Ensure that the virtual shelves system preference is enabled 2. Create one or two lists using a patron that has both a first and last name. You don’t have to add items to the list, the list itself is enough. 3. Under the Owner column in the Lists table, search using the patron’s first name. Note that the name is properly filtered. 4. Next, try to search by the last name. It is also properly filtered. 5. Now search using both the first name and the last name together. Note that the results come up empty. 6. Apply the patch. 7. Repeat steps 3–5. Note that the patron shows in the results with just the first name, the last name, and the full name.
7.1. Additionally, try searching with extra spaces (e.g., ' Firstname Surname ' or 'Firstname Surname'). Confirm that results are still correctly shown. 8. Run t/db_dependent/Virtualshelves.t 9. Sign off and have a great day! :D --- C4/Utils/DataTables/VirtualShelves.pm | 15 ++++++- t/db_dependent/Virtualshelves.t | 65 +++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/C4/Utils/DataTables/VirtualShelves.pm b/C4/Utils/DataTables/VirtualShelves.pm index 4b578e4f70..5c5ee3611a 100644 --- a/C4/Utils/DataTables/VirtualShelves.pm +++ b/C4/Utils/DataTables/VirtualShelves.pm @@ -63,8 +63,19 @@ sub search { push @args, "%$shelfname%"; } if ( defined $owner and $owner ne '' ) { - push @where_strs, '( bo.firstname LIKE ? OR bo.surname LIKE ? )'; - push @args, "%$owner%", "%$owner%"; + $owner =~ s/^\s+|\s+$//g; # Trim leading/trailing spaces + $owner =~ s/\s+/ /g; # Collapse multiple internal spaces to one + my @name_parts = split ' ', $owner; + + if ( @name_parts == 2 ) { + push @where_strs, '( bo.firstname LIKE ? AND bo.surname LIKE ? )'; + push @args, "%$name_parts[0]%", "%$name_parts[1]%"; + + } else { + + push @where_strs, '(bo.firstname LIKE ? OR bo.surname LIKE ?)'; + push @args, "%$owner%", "%$owner%"; + } } if ( defined $sortby and $sortby ne '' ) { push @where_strs, 'sortfield = ?'; diff --git a/t/db_dependent/Virtualshelves.t b/t/db_dependent/Virtualshelves.t index 10182dfbc5..bfff2dff26 100755 --- a/t/db_dependent/Virtualshelves.t +++ b/t/db_dependent/Virtualshelves.t @@ -129,6 +129,71 @@ subtest 'CRUD' => sub { teardown(); }; +subtest 'Owner filter logic' => sub { + plan tests => 16; + + my ( @where_strs, @args ); + + my $test_logic = sub { + my ($owner) = @_; + @where_strs = (); + @args = (); + + if ( defined $owner and $owner ne '' ) { + $owner =~ s/^\s+|\s+$//g; # Trim leading/trailing spaces + $owner =~ s/\s+/ /g; # Normalize internal whitespace + + return ( [], [] ) if $owner eq ''; + + my @name_parts = split ' ', $owner; + + if ( @name_parts == 2 ) { + push @where_strs, '( bo.firstname LIKE ? AND bo.surname LIKE ? )'; + push @args, "%$name_parts[0]%", "%$name_parts[1]%"; + } else { + push @where_strs, '(bo.firstname LIKE ? OR bo.surname LIKE ?)'; + push @args, "%$owner%", "%$owner%"; + } + } + + return ( \@where_strs, \@args ); + }; + + my ( $where, $args ); + + ( $where, $args ) = $test_logic->(undef); + is_deeply( $where, [], 'No where clause when owner is undef' ); + is_deeply( $args, [], 'No args when owner is undef' ); + + ( $where, $args ) = $test_logic->(''); + is_deeply( $where, [], 'No where clause when owner is empty' ); + is_deeply( $args, [], 'No args when owner is empty' ); + + ( $where, $args ) = $test_logic->('John Smith'); + is_deeply( $where, ['( bo.firstname LIKE ? AND bo.surname LIKE ? )'], 'AND clause for two name parts' ); + is_deeply( $args, [ '%John%', '%Smith%' ], 'Args match both names' ); + + ( $where, $args ) = $test_logic->(' John Smith '); + is_deeply( $where, ['( bo.firstname LIKE ? AND bo.surname LIKE ? )'], 'Trimmed whitespace around two name parts' ); + is_deeply( $args, [ '%John%', '%Smith%' ], 'Args match trimmed names' ); + + ( $where, $args ) = $test_logic->('John Smith'); + is_deeply( $where, ['( bo.firstname LIKE ? AND bo.surname LIKE ? )'], 'Normalized internal whitespace' ); + is_deeply( $args, [ '%John%', '%Smith%' ], 'Args match normalized names' ); + + ( $where, $args ) = $test_logic->('John '); + is_deeply( $where, ['(bo.firstname LIKE ? OR bo.surname LIKE ?)'], 'Single name with trailing space' ); + is_deeply( $args, [ '%John%', '%John%' ], 'Args match single name trimmed' ); + + ( $where, $args ) = $test_logic->(' '); + is_deeply( $where, [], 'No where clause when owner is only whitespace' ); + is_deeply( $args, [], 'No args when owner is only whitespace' ); + + ( $where, $args ) = $test_logic->(' John '); + is_deeply( $where, ['(bo.firstname LIKE ? OR bo.surname LIKE ?)'], 'Single name with leading/trailing spaces' ); + is_deeply( $args, [ '%John%', '%John%' ], 'Args match cleaned single name' ); +}; + subtest 'Sharing' => sub { plan tests => 21; my $patron_wants_to_share = $builder->build( -- 2.39.5