From 4d8169332446aa7d7372a65da7360f69025595b1 Mon Sep 17 00:00:00 2001 From: Janusz Kaczmarek Date: Tue, 1 Apr 2025 11:20:13 +0000 Subject: [PATCH] Bug 39503: Unit tests NB, some previous test had to be adjusted to make it posible to call search_auth_compat in _search and properly interpret its results. Signed-off-by: Roman Dolny Signed-off-by: Martin Renvoize --- t/db_dependent/Heading.t | 97 ++++++++++++++----- .../Koha/SearchEngine/Elasticsearch.t | 56 ++++++++++- 2 files changed, 125 insertions(+), 28 deletions(-) diff --git a/t/db_dependent/Heading.t b/t/db_dependent/Heading.t index 9e0cd90e3b2..8ff1ab260dd 100755 --- a/t/db_dependent/Heading.t +++ b/t/db_dependent/Heading.t @@ -73,7 +73,7 @@ subtest "UNIMARC tests" => sub { subtest "_search tests" => sub { - plan tests => 10; + plan tests => 11; t::lib::Mocks::mock_preference( 'marcflavour', 'MARC21' ); t::lib::Mocks::mock_preference( 'SearchEngine', 'Elasticsearch' ); @@ -184,48 +184,93 @@ subtest "_search tests" => sub { "Search formed as expected for a non-subject field with double punctuation, period+comma " ); + # Special case where thesaurus defined in subfield 2 should also match record with no thesaurus + # In the ES index an auth rec. without 040 $f, so 'z' from 008/11 is present in subject-heading-thesaurus + my $expected_authid = 12345; $search->mock( 'search_auth_compat', sub { my $self = shift; my $search_query = shift; - if ( scalar @{ $search_query->{query}->{bool}->{must} } == 2 - && $search_query->{query}->{bool}->{must}[1]->{term}->{'subject-heading-thesaurus.ci_raw'} eq - 'special_sauce' ) - { - return; + if ( scalar @{ $search_query->{query}->{bool}->{must} } == 2 ) { + if ( $search_query->{query}->{bool}->{must}[1]->{term}->{'subject-heading-thesaurus.ci_raw'} eq + 'special_sauce' ) + { + # no record with 'special_sauce' + return ( [], 0 ); + } elsif ( + $search_query->{query}->{bool}->{must}[1]->{term}->{'subject-heading-thesaurus.ci_raw'} eq 'z' ) + { + # for 'notdefined' we return the only record with 008/11 = 'z' + return ( [ { authid => $expected_authid } ], 1 ); + } else { + + # other cases - nothing + return ( [], 0 ); + } + } elsif ( scalar @{ $search_query->{query}->{bool}->{must} } == 1 ) { + return ['no thesaurus checking at all']; } - return ( $search_query, 1 ); } ); - - # Special case where thesaurus defined in subfield 2 should also match record with no thesaurus $field = MARC::Field->new( '650', ' ', '7', a => 'Uncles', x => 'Fiction', 2 => 'special_sauce' ); $heading = C4::Heading->new_from_field($field); - ($search_query) = $heading->_search('match-heading'); - $terms = $search_query->{query}->{bool}->{must}; - $expected_terms = [ - { term => { 'match-heading.ci_raw' => 'Uncles generalsubdiv Fiction' } }, - { term => { 'subject-heading-thesaurus.ci_raw' => 'z' } }, - ]; + my ($matched_auths) = $heading->_search('match-heading'); + my $expected_result = [ { authid => $expected_authid } ]; is_deeply( - $terms, $expected_terms, - "When thesaurus in subfield 2, and nothing is found, we should search again for notdefined (008_11 = z) " + $matched_auths, $expected_result, + "When thesaurus in subfield 2, we should search again for notdefined (008_11 = z) and get a result" ); - t::lib::Mocks::mock_preference( 'LinkerConsiderThesaurus', '0' ); + # In the ES index an auth rec. with 040 $f 'special_sauce', so 'z' from 008/11 not present in subject-heading-thesaurus + $search->mock( + 'search_auth_compat', + sub { + my $self = shift; + my $search_query = shift; + if ( scalar @{ $search_query->{query}->{bool}->{must} } == 2 ) { + if ( $search_query->{query}->{bool}->{must}[1]->{term}->{'subject-heading-thesaurus.ci_raw'} eq + 'special_sauce' ) + { + # no record with 'special_sauce' + return ( [ { authid => $expected_authid } ], 1 ); + } elsif ( + $search_query->{query}->{bool}->{must}[1]->{term}->{'subject-heading-thesaurus.ci_raw'} eq 'z' ) + { + # for 'notdefined' we return the only record with 008/11 = 'z' + return ( [], 0 ); + } else { + + # other cases - nothing + return ( [], 0 ); + } + } elsif ( scalar @{ $search_query->{query}->{bool}->{must} } == 1 ) { + return ['no thesaurus checking at all']; + } + } + ); - $search_query = undef; - ($search_query) = $heading->_search('match-heading'); - $terms = $search_query->{query}->{bool}->{must}; - $expected_terms = [ - { term => { 'match-heading.ci_raw' => 'Uncles generalsubdiv Fiction' } }, - ]; + # Special case continued: but it should not match an authority record with a different thesaurus + # defined in 040 $f + $field = MARC::Field->new( '650', ' ', '7', a => 'Uncles', x => 'Fiction', 2 => 'special_sauce_2' ); + $heading = C4::Heading->new_from_field($field); + + ($matched_auths) = $heading->_search('match-heading'); + $expected_result = []; is_deeply( - $terms, $expected_terms, - "When thesaurus in subfield 2, and nothing is found, we don't search again if LinkerConsiderThesaurusDisabled" + $matched_auths, $expected_result, + 'When thesaurus in subfield 2, and nothing is found, we search again for notdefined (008_11 = z), and get no results because 040 $f with different value exists in the auth rec.' ); + # When LinkerConsiderThesaurus off, no attantion is being paid on the thesaurus + t::lib::Mocks::mock_preference( 'LinkerConsiderThesaurus', '0' ); + + ($matched_auths) = $heading->_search('match-heading'); + $expected_result = ['no thesaurus checking at all']; + is_deeply( + $matched_auths, $expected_result, + "When thesaurus in subfield 2, and nothing is found, we don't search again if LinkerConsiderThesaurus disabled" + ); }; subtest "authorities exact match tests" => sub { diff --git a/t/db_dependent/Koha/SearchEngine/Elasticsearch.t b/t/db_dependent/Koha/SearchEngine/Elasticsearch.t index 8ee3ae0541b..2e4b3402ec6 100755 --- a/t/db_dependent/Koha/SearchEngine/Elasticsearch.t +++ b/t/db_dependent/Koha/SearchEngine/Elasticsearch.t @@ -967,7 +967,7 @@ subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents_array () t subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () authority tests' => sub { - plan tests => 5; + plan tests => 9; t::lib::Mocks::mock_preference( 'marcflavour', 'MARC21' ); t::lib::Mocks::mock_preference( 'ElasticsearchMARCFormat', 'base64ISO2709' ); @@ -996,6 +996,26 @@ subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () authori sort => 0, marc_type => 'marc21', marc_field => '185v', + }, + { + name => 'subject-heading-thesaurus', + type => 'string', + facet => 0, + suggestible => 0, + searchable => 1, + sort => 0, + marc_type => 'marc21', + marc_field => '008_/11', + }, + { + name => 'subject-heading-thesaurus', + type => 'string', + facet => 0, + suggestible => 0, + searchable => 1, + sort => 0, + marc_type => 'marc21', + marc_field => '040f', } ); @@ -1041,7 +1061,20 @@ subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () authori $marc_record_3->append_fields( MARC::Field->new( '185', '', '', v => 'Formsubdiv' ), ); - my $records = [ $marc_record_1, $marc_record_2, $marc_record_3 ]; + + my $marc_record_4 = MARC::Record->new(); + $marc_record_4->append_fields( + MARC::Field->new( '008', ' ' x 11 . 'z' . ' ' x 28 ), + MARC::Field->new( '040', ' ', ' ', f => 'special_sauce' ), + MARC::Field->new( '150', ' ', ' ', a => 'Philosophy' ), + ); + + my $marc_record_5 = MARC::Record->new(); + $marc_record_5->append_fields( + MARC::Field->new( '008', ' ' x 11 . 'z' . ' ' x 28 ), + MARC::Field->new( '150', ' ', ' ', a => 'Philosophy' ), + ); + my $records = [ $marc_record_1, $marc_record_2, $marc_record_3, $marc_record_4, $marc_record_5 ]; $see->get_elasticsearch_mappings(); #sort_fields will call this and use the actual db values unless we call it first @@ -1068,6 +1101,25 @@ subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () authori $docs->[2]->{'match'}, "Third record heading should contain the subfield" ); + is( + scalar( @{ $docs->[3]->{'subject-heading-thesaurus'} } ), + 1, + "Only one subject-heading-thesaurus element for a record with 040 \$f" + ); + is_deeply( + $docs->[3]->{'subject-heading-thesaurus'}->[0], + 'special_sauce', + "Fourth record's subject-heading-thesaurus taken from 040 \$f" + ); + is( + scalar( @{ $docs->[4]->{'subject-heading-thesaurus'} } ), + 1, + "Just one subject-heading-thesaurus element for a record with 008/11 = 'z' and without 040 \$f" + ); + is_deeply( + $docs->[4]->{'subject-heading-thesaurus'}->[0], + 'z', "Fifth record's subject-heading-thesaurus taken from 008/11" + ); }; -- 2.49.0