#!/usr/bin/perl
+
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
#
-#testing C4 matcher
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
-use strict;
-use warnings;
-use Test::More tests => 10;
+use Test::More;
use Test::MockModule;
+use Test::Warn;
+
+use MARC::Record;
+
+use Module::Load::Conditional qw/check_install/;
BEGIN {
- use_ok('C4::Matcher');
+ if ( check_install( module => 'Test::DBIx::Class' ) ) {
+ plan tests => 13;
+ } else {
+ plan skip_all => "Need Test::DBIx::Class"
+ }
}
-my $module = new Test::MockModule('C4::Context');
-$module->mock(
- '_new_dbh',
- sub {
- my $dbh = DBI->connect( 'DBI:Mock:', '', '' )
- || die "Cannot create handle: $DBI::errstr\n";
- return $dbh;
- }
-);
-my $matcher = [
- [ 'matcher_id', 'code', 'description', 'record_type', 'threshold' ],
- [ 1, 'ISBN', 'ISBN', 'red', 1 ],
- [ 2, 'ISSN', 'ISSN', 'blue', 0 ]
-];
-my $dbh = C4::Context->dbh();
+use Test::DBIx::Class;
-$dbh->{mock_add_resultset} = $matcher;
+my $db = Test::MockModule->new('Koha::Database');
+$db->mock( _new_schema => sub { return Schema(); } );
+
+use_ok('C4::Matcher', qw( GetMatcherList GetMatcherId ));
+
+fixtures_ok [
+ MarcMatcher => [
+ [ 'matcher_id', 'code', 'description', 'record_type', 'threshold' ],
+ [ 1, 'ISBN', 'ISBN', 'red', 1 ],
+ [ 2, 'ISSN', 'ISSN', 'blue', 0 ]
+ ],
+], 'add fixtures';
my @matchers = C4::Matcher::GetMatcherList();
is( $matchers[1]->{'matcher_id'}, 2, 'Second matcher_id value is 2' );
-$dbh->{mock_add_resultset} = $matcher;
-
my $matcher_id = C4::Matcher::GetMatcherId('ISBN');
is( $matcher_id, 1, 'testing getmatcherid' );
$testmatcher->description('match on ISSN');
is( $testmatcher->description(), 'match on ISSN', 'testing code accessor' );
+
+subtest '_get_match_keys() tests' => sub {
+
+ plan tests => 21;
+
+ my $matchpoint = get_title_matchpoint({
+ length => 0,
+ norms => [ 'legacy_default' ],
+ offset => 0
+ });
+
+ my $record = MARC::Record->new();
+ $record->append_fields(
+ MARC::Field->new('020', '1', ' ',
+ a => '978-1451697216 (alk. paper)'),
+ MARC::Field->new('020', '1', ' ',
+ a => '145169721X (alk. paper)'),
+ MARC::Field->new('020', '1', ' ',
+ a => '1NOTISBN3'),
+ MARC::Field->new('100', '1', ' ',
+ a => 'King, Stephen',
+ d => 'd1947-'),
+ MARC::Field->new('245', ' ', ' ',
+ a => ' .; thE t[]:,aliS(m)/An\'"',
+ c => 'Stephen King, Peter Straub.' ),
+ MARC::Field->new('700', ' ', ' ',
+ a => 'Straub, Peter',
+ d => '1943-')
+ );
+
+ my @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+
+ is( $keys[0], 'THE TALISMAN STEPHEN KING PETER STRAUB',
+ 'Match key correctly calculated with no $norms');
+
+ $matchpoint = get_title_matchpoint({
+ length => 9,
+ norms => [ 'legacy_default' ],
+ offset => 0
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], 'THE',
+ 'Match key correctly calculated with length 9');
+
+ $matchpoint = get_title_matchpoint({
+ length => 9,
+ norms => [ 'legacy_default' ],
+ offset => 1
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], 'THE T',
+ 'Match key correctly calculated with length 9 and offset 1');
+
+ $matchpoint = get_title_matchpoint({
+ length => 9,
+ norms => [ 'legacy_default' ],
+ offset => 2
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], 'THE T',
+ 'Match key correctly calculated with length 9 and offset 2, should not remove space');
+
+ $matchpoint = get_authors_matchpoint({
+ length => 0,
+ norms => [ 'legacy_default' ],
+ offset => 0
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], 'STRAUB PETER KING STEPHEN',
+ 'Match key correctly calculated with multiple components');
+
+ $matchpoint = get_authors_matchpoint({
+ length => 9,
+ norms => [ 'legacy_default' ],
+ offset => 0
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], 'STRAUB P KING STE',
+ 'Match key correctly calculated with multiple components, length 9');
+
+ $matchpoint = get_authors_matchpoint({
+ length => 10,
+ norms => [ 'legacy_default' ],
+ offset => 0
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], 'STRAUB PE KING STEP',
+ 'Match key correctly calculated with multiple components, length 10');
+
+ $matchpoint = get_authors_matchpoint({
+ length => 10,
+ norms => [ 'legacy_default' ],
+ offset => 2
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], 'RAUB PETE NG STEPHE',
+ 'Match key correctly calculated with multiple components, length 10, offset 1');
+
+ $matchpoint = get_title_matchpoint({
+ length => 0,
+ norms => [ 'none', 'none' ],
+ offset => 0
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], ' .; thE t[]:,aliS(m)/An\'" Stephen King, Peter Straub.',
+ 'Match key intact if \'none\' specified, length 0 and offset 0' );
+
+ $matchpoint = get_authors_matchpoint({
+ length => 0,
+ norms => [ 'upper_case' ],
+ offset => 0
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], 'STRAUB, PETER KING, STEPHEN',
+ 'Match key correctly calculated with multiple components, \'upper_case\' norm');
+
+ $matchpoint = get_authors_matchpoint({
+ length => 0,
+ norms => [ 'lower_case' ],
+ offset => 0
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], 'straub, peter king, stephen',
+ 'Match key correctly calculated with multiple components, \'lower_case\' norm');
+
+ $matchpoint = get_authors_matchpoint({
+ length => 0,
+ norms => [ 'remove_spaces' ],
+ offset => 0
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], 'Straub,Peter King,Stephen',
+ 'Match key correctly calculated with multiple components, \'remove_spaces\' norm');
+
+ $matchpoint = get_authors_matchpoint({
+ length => 0,
+ norms => [ 'remove_spaces', 'lower_case' ],
+ offset => 0
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], 'straub,peter king,stephen',
+ 'Match key correctly calculated with multiple components, \'remove_spaces\' and \'lower_case\' norm');
+
+ my $norm = 'unknown_norm';
+ $matchpoint = get_title_matchpoint({
+ length => 0,
+ norms => [ $norm ],
+ offset => 0
+ });
+ warning_is
+ { @keys = C4::Matcher::_get_match_keys( $record, $matchpoint ) }
+ qq{Invalid normalization routine required ($norm)},
+ 'Passing an invalid normalization routine name raises a warning';
+
+ is( $keys[0], ' .; thE t[]:,aliS(m)/An\'" Stephen King, Peter Straub.',
+ 'Match key intact if invalid normalization routine specified' );
+
+ $matchpoint = get_title_matchpoint({
+ length => 0,
+ norms => [ $norm, 'upper_case' ],
+ offset => 0
+ });
+ warning_is
+ { @keys = C4::Matcher::_get_match_keys( $record, $matchpoint ) }
+ qq{Invalid normalization routine required ($norm)},
+ 'Passing an invalid normalization routine name raises a warning';
+
+ is( $keys[0], ' .; THE T[]:,ALIS(M)/AN\'" STEPHEN KING, PETER STRAUB.',
+ 'Match key correctly normalized if invalid normalization routine specified' );
+
+ $matchpoint = get_isbn_matchpoint({
+ length => 0,
+ norms => [ 'ISBN' ],
+ offset => 0
+ });
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], '9781451697216',
+ 'Match key correctly calculated as ISBN13 when ISBN normalizer used');
+ is( $keys[1], '9781451697216',
+ 'Match key correctly calculated as ISBN13 when ISBN normalizer used');
+ is( $keys[2], '1NOTISBN3',
+ 'Match key passed through if not an isbn when ISBN normalizer used');
+
+ $matchpoint = get_title_matchpoint({
+ length => 0,
+ offset => 0
+ });
+ delete $matchpoint->{component}->{subfields};
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], ' .; thE t[]:,aliS(m)/An\'" Stephen King, Peter Straub.', "Match key correctly returns whole field if no subfields specified" )
+};
+
+subtest '_get_match_keys() leader tests' => sub {
+ plan tests => 2;
+ my $record = MARC::Record->new();
+ my $matchpoint = get_leader_matchpoint({
+ length => 1,
+ offset => 6,
+ });
+
+ my @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], ' ', 'Match key correctly calculated as " " from LDR6 when no leader available');
+
+ $record->leader('01344cam a22003014a 4500');
+
+ @keys = C4::Matcher::_get_match_keys( $record, $matchpoint );
+ is( $keys[0], 'a', 'Match key correctly calculated as "a" from LDR6');
+};
+
+sub get_title_matchpoint {
+
+ my $params = shift;
+
+ my $length = $params->{length} // 0;
+ my $norms = $params->{norms} // [];
+ my $offset = $params->{offset} // 0;
+
+ my $matchpoint = {
+ components => [
+ {
+ length => $length,
+ norms => $norms,
+ offset => $offset,
+ subfields =>
+ {
+ a => 1,
+ c => 1
+ },
+ tag => '245'
+ }
+ ],
+ index => "title",
+ score => 1000
+ };
+
+ return $matchpoint;
+}
+
+sub get_authors_matchpoint {
+
+ my $params = shift;
+
+ my $length = $params->{length} // 0;
+ my $norms = $params->{norms} // [];
+ my $offset = $params->{offset} // 0;
+
+ my $matchpoint = {
+ components => [
+ {
+ length => $length,
+ norms => $norms,
+ offset => $offset,
+ subfields =>
+ {
+ a => 1
+ },
+ tag => '700'
+ },
+ {
+ length => $length,
+ norms => $norms,
+ offset => $offset,
+ subfields =>
+ {
+ a => 1
+ },
+ tag => '100'
+ }
+ ],
+ index => "author",
+ score => 1000
+ };
+
+ return $matchpoint;
+}
+
+sub get_isbn_matchpoint {
+
+ my $params = shift;
+
+ my $length = $params->{length} // 0;
+ my $norms = $params->{norms} // [];
+ my $offset = $params->{offset} // 0;
+
+ my $matchpoint = {
+ components => [
+ {
+ length => $length,
+ norms => $norms,
+ offset => $offset,
+ subfields =>
+ {
+ a => 1
+ },
+ tag => '020'
+ },
+ ],
+ index => "isbn",
+ score => 1000
+ };
+
+ return $matchpoint;
+}
+
+sub get_leader_matchpoint {
+ my $params = shift;
+ my $length = $params->{length} // 0;
+ my $norms = $params->{norms} // [];
+ my $offset = $params->{offset} // 0;
+
+ my $matchpoint = {
+ components => [
+ {
+ length => $length,
+ norms => $norms,
+ offset => $offset,
+ tag => 'LDR'
+ },
+ ],
+ };
+
+ return $matchpoint;
+}