From 97c860704f6be972947f630fb3fadab812a396b2 Mon Sep 17 00:00:00 2001 From: Olli-Antti Kivilahti Date: Mon, 2 Nov 2015 20:25:56 +0200 Subject: [PATCH] Bug 13906 - TestObjectFactory(ies) for Koha objects. Holds test factory for v3.16 --- t/lib/TestObjects/BiblioFactory.pm | 2 + t/lib/TestObjects/HoldFactory.pm | 206 ++++++++++++++++++++++++++++++++++++ t/lib/TestObjects/ItemFactory.pm | 18 ++-- t/lib/TestObjects/ObjectFactory.pm | 6 ++ t/lib/TestObjects/objectFactories.t | 56 ++++++++++ 5 files changed, 279 insertions(+), 9 deletions(-) create mode 100644 t/lib/TestObjects/HoldFactory.pm diff --git a/t/lib/TestObjects/BiblioFactory.pm b/t/lib/TestObjects/BiblioFactory.pm index 11874e7..e981f6d 100644 --- a/t/lib/TestObjects/BiblioFactory.pm +++ b/t/lib/TestObjects/BiblioFactory.pm @@ -41,6 +41,7 @@ sub getObjectType { {'biblio.title' => 'I wish I met your mother', 'biblio.author' => 'Pertti Kurikka', 'biblio.copyrightdate' => '1960', + 'biblio.biblionumber' => 1212, 'biblioitems.isbn' => '9519671580', 'biblioitems.itemtype' => 'BK', }, @@ -71,6 +72,7 @@ sub handleTestObject { ##First see if the given Record already exists in the DB. For testing purposes we use the isbn as the UNIQUE identifier. my $resultset = Koha::Database->new()->schema()->resultset('Biblioitem'); my $existingBiblio = $resultset->search({isbn => $object->{"biblioitems.isbn"}})->next(); + $existingBiblio = $resultset->search({biblionumber => $object->{"biblio.biblionumber"}})->next() unless $existingBiblio; my ($record, $biblionumber, $biblioitemnumber); unless ($existingBiblio) { $record = C4::Biblio::TransformKohaToMarc($object); diff --git a/t/lib/TestObjects/HoldFactory.pm b/t/lib/TestObjects/HoldFactory.pm new file mode 100644 index 0000000..89cb84b --- /dev/null +++ b/t/lib/TestObjects/HoldFactory.pm @@ -0,0 +1,206 @@ +package t::lib::TestObjects::HoldFactory; + +# Copyright KohaSuomi 2015 +# +# 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. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +use Modern::Perl; +use Carp; +use DateTime; + +use C4::Context; +use Koha::Database; +use C4::Circulation; +use C4::Members; +use C4::Items; +use C4::Reserves; +use Koha::Borrowers; +use Koha::Biblios; +use Koha::BiblioItems; +use Koha::Items; +use Koha::Checkouts; + +use t::lib::TestObjects::BorrowerFactory; +use t::lib::TestObjects::ItemFactory; +use t::lib::TestObjects::BiblioFactory; + +use base qw(t::lib::TestObjects::ObjectFactory); + +sub new { + my ($class) = @_; + + my $self = {}; + bless($self, $class); + return $self; +} + +sub getDefaultHashKey { + return ['reservenotes']; +} +sub getObjectType { + return 'HASH'; +} + +=head t::lib::TestObjects::HoldFactory::createTestGroup( $data [, $hashKey], @stashes ) + + my $holds = t::lib::TestObjects::HoldFactory->createTestGroup([ + {#Hold params + }, + {#More hold params + }, + ], undef, $testContext1, $testContext2, $testContext3); + + t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext1); + +@PARAM1, ARRAY of HASHes. + [ { + cardnumber => '167Azava0001', #Borrower's cardnumber + isbn => '971040323123', #ISBN of the Biblio, even if the record normally doesn't have a ISBN, you must mock one on it. + barcode => undef || '911N12032', #Item's barcode, if this is an Item-level hold. + branchcode => 'CPL', + waitingdate => undef || '2015-01-15', #Since when has this hold been waiting for pickup? + }, + { + ... + } + ] +@PARAM2, String, the HASH-element to use as the returning HASHes key. +@PARAM3-5 HASHRef of test contexts. You can save the given objects to multiple + test contexts. Usually one is enough. These test contexts are + used to help tear down DB changes. +@RETURNS HASHRef of $hashKey => HASH-objects representing koha.reserves-table columns + The HASH is keyed with , or the given $hashKey. + Example: { + '11A001-971040323123-43' => {...}, + 'my-nice-hold' => {...}, + ... + } +} +=cut + +sub handleTestObject { + my ($class, $object, $stashes) = @_; + + C4::Reserves::AddReserve($object->{branchcode} || 'CPL', + $object->{borrower}->borrowernumber, + $object->{biblio}->{biblionumber}, + undef, #constraint + undef, #bibitems + undef, #priority + $object->{reservedate}, #resdate + $object->{expirationdate}, #expdate + $object->{reservenotes}, #notes + undef, #title + ($object->{item} ? $object->{item}->itemnumber : undef), #checkitem + undef, #found + ); + my $reserve_id = C4::Reserves::GetReserveId({biblionumber => $object->{biblio}->{biblionumber}, + itemnumber => ($object->{item} ? $object->{item}->itemnumber : undef), + borrowernumber => $object->{borrower}->borrowernumber, + }); + unless ($reserve_id) { + die "HoldFactory->handleTestObject():> Couldn't create a reserve. for isbn => ".$object->{isbn}.", barcode => ".$object->{barcode}. + ", item => ".($object->{barcode} ? $object->{barcode} : '')."\n"; + } + my $hold = C4::Reserves::GetReserve($reserve_id); + foreach my $key (keys $object) { + $hold->{$key} = $object->{$key}; + } + + if ($object->{waitingdate}) { + eval { + C4::Reserves::ModReserveAffect($hold->{item}->itemnumber, $hold->{borrower}->borrowernumber); + + #Modify the waitingdate. An ugly hack for a ugly module. Bear with me my men! + my $dbh = C4::Context->dbh; + my $query = "UPDATE reserves SET waitingdate = ? WHERE reserve_id = ?"; + my $sth = $dbh->prepare($query); + $sth->execute( $hold->{waitingdate}, $hold->{reserve_id} ); + }; + if ($@) { + warn "HoldFactory->handleTestObject():> Error when setting the waitingdate for ".$class->getHashKey($object)."$@"; + } + } + + return $hold; +} + +=head validateAndPopulateDefaultValues +@OVERLOAD + +Validates given Object parameters and makes sure that critical fields are given +and populates defaults for missing values. +=cut + +sub validateAndPopulateDefaultValues { + my ($self, $object, $hashKey, $stashes) = @_; + $self->SUPER::validateAndPopulateDefaultValues($object, $hashKey); + + unless ($object->{cardnumber}) { + croak __PACKAGE__.":> Mandatory parameter 'cardnumber' missing."; + } + unless ($object->{isbn}) { + croak __PACKAGE__.":> Mandatory parameter 'isbn' missing."; + } + + my $borrowers = t::lib::TestObjects::BorrowerFactory->createTestGroup( + {cardnumber => $object->{cardnumber}}, + undef, @$stashes); + my $borrower = $borrowers->{ $object->{cardnumber} }; + $object->{borrower} = $borrower if $borrower; + + my $biblios = t::lib::TestObjects::BiblioFactory->createTestGroup({"biblio.title" => "Test holds' Biblio", + "biblioitems.isbn" => $object->{isbn}}, + undef, @$stashes); + my $biblio = $biblios->{ $object->{isbn} || '971-972-call-me' }; #Get default isbn or the given one + $object->{biblio} = $biblio if $biblio; + + #Get test Item + if ($object->{barcode}) { + my $items = t::lib::TestObjects::ItemFactory->createTestGroup({barcode => $object->{barcode}, isbn => $object->{isbn}}, undef, @$stashes); + my $item = $items->{ $object->{barcode} }; + $object->{item} = $item; + } + + return $object; +} + +=head + + my $objects = createTestGroup(); + ##Do funky stuff + deleteTestGroup($records); + +Removes the given test group from the DB. + +=cut + +sub deleteTestGroup { + my ($self, $objects) = @_; + + #For some reason DBIx cannot delete from OldReserves-table so using DBI and not losing sleep + my $dbh = C4::Context->dbh(); + my $del_old_sth = $dbh->prepare("DELETE FROM old_reserves WHERE reserve_id = ?"); + my $del_sth = $dbh->prepare("DELETE FROM reserves WHERE reserve_id = ?"); + + while( my ($key, $object) = each %$objects) { + $del_sth->execute($object->{reserve_id}); + $del_old_sth->execute($object->{reserve_id}); + } +} + +1; diff --git a/t/lib/TestObjects/ItemFactory.pm b/t/lib/TestObjects/ItemFactory.pm index f75fb97..4481817 100644 --- a/t/lib/TestObjects/ItemFactory.pm +++ b/t/lib/TestObjects/ItemFactory.pm @@ -23,6 +23,7 @@ use Carp; use C4::Items; use Koha::Biblios; +use Koha::BiblioItems; use Koha::Items; use Koha::Checkouts; @@ -64,17 +65,16 @@ sub handleTestObject { #Look for the parent biblio, if we don't find one, create a default one. my ($biblionumber, $biblioitemnumber, $itemnumber); - my $biblio; - $biblio = Koha::Biblios->find({biblionumber => $object->{biblionumber}}) if $object->{biblionumber}; - unless ($biblio) { - my $biblios = t::lib::TestObjects::BiblioFactory->createTestGroup({"biblio.title" => "Test Items' Biblio",}, + my $biblios = t::lib::TestObjects::BiblioFactory->createTestGroup({"biblio.title" => "Test Items' Biblio", + "biblioitems.isbn" => $object->{isbn}, + "biblio.biblionumber" => $object->{biblionumber}}, undef, @$stashes); - $biblio = $biblios->{'971-972-call-me'}; - $object->{biblionumber} = $biblio->{biblionumber}; - } - else { - $object->{biblionumber} = $biblio->biblionumber; + my $biblio; + foreach my $k (keys %$biblios) { + $biblio = $biblios->{$k}; } + $object->{biblionumber} = $biblio->{biblionumber}; + $object->{biblio} = $biblio; #Ok we got a biblio, now we can add an Item for it. First see if the Item already exists. my $item; diff --git a/t/lib/TestObjects/ObjectFactory.pm b/t/lib/TestObjects/ObjectFactory.pm index 791085d..f84a607 100644 --- a/t/lib/TestObjects/ObjectFactory.pm +++ b/t/lib/TestObjects/ObjectFactory.pm @@ -171,6 +171,11 @@ sub tearDownTestContext { t::lib::TestObjects::BorrowerFactory->deleteTestGroup($stash->{borrower}); delete $stash->{borrower}; } + if ($stash->{hold}) { + require t::lib::TestObjects::HoldFactory; + t::lib::TestObjects::HoldFactory->deleteTestGroup($stash->{hold}); + delete $stash->{hold}; + } if ($stash->{letterTemplate}) { require t::lib::TestObjects::LetterTemplateFactory; t::lib::TestObjects::LetterTemplateFactory->deleteTestGroup($stash->{letterTemplate}); @@ -199,6 +204,7 @@ sub getHashKey { my ($class, $object, $primaryKey, $hashKeys) = @_; my @collectedHashKeys; + $hashKeys = $class->getDefaultHashKey unless $hashKeys; $hashKeys = [$hashKeys] unless ref($hashKeys) eq 'ARRAY'; foreach my $hashKey (@$hashKeys) { if (ref($object) eq 'HASH') { diff --git a/t/lib/TestObjects/objectFactories.t b/t/lib/TestObjects/objectFactories.t index d29923a..2c73db3 100644 --- a/t/lib/TestObjects/objectFactories.t +++ b/t/lib/TestObjects/objectFactories.t @@ -49,6 +49,7 @@ use Koha::Serial::Subscription::Frequencies; use Koha::Serial::Subscription::Numberpatterns; use Koha::Serial::Serials; use t::lib::TestObjects::SystemPreferenceFactory; +use t::lib::TestObjects::HoldFactory use C4::Context; use t::lib::TestObjects::MessageQueueFactory; use C4::Letters; @@ -58,6 +59,61 @@ my $testContext = {}; #Gather all created Objects here so we can finally remove +########## HoldFactory subtests ########## +subtest 't::lib::TestObjects::HoldFactory' => \&testHoldFactory; +sub testHoldFactory { + my $subtestContext = {}; + ##Create and Delete using dependencies in the $testContext instantiated in previous subtests. + my $holds = t::lib::TestObjects::HoldFactory->createTestGroup( + {cardnumber => '1A01', + isbn => '971', + barcode => '1N01', + branchcode => 'CPL', + waitingdate => '2015-01-15', + }, + ['cardnumber','isbn','barcode'], $subtestContext); + + is($holds->{'1A01-971-1N01'}->{branchcode}, + 'CPL', + "Hold '1A01-971-1N01' pickup location is 'CPL'."); + is($holds->{'1A01-971-1N01'}->{waitingdate}, + '2015-01-15', + "Hold '1A01-971-1N01' waiting date is '2015-01-15'."); + + #using the default test hold identifier reservenotes to distinguish hard-to-identify holds. + my $holds2 = t::lib::TestObjects::HoldFactory->createTestGroup([ + {cardnumber => '1A01', + isbn => '971', + barcode => '1N02', + branchcode => 'CPL', + reservenotes => 'nice hold', + }, + {cardnumber => '1A01', + barcode => '1N03', + isbn => '971', + branchcode => 'CPL', + reservenotes => 'better hold', + }, + ], undef, $subtestContext); + + is($holds2->{'nice hold'}->{branchcode}, + 'CPL', + "Hold 'nice hold' pickup location is 'CPL'."); + is($holds2->{'nice hold'}->{borrower}->cardnumber, + '1A01', + "Hold 'nice hold' cardnumber is '1A01'."); + is($holds2->{'better hold'}->{isbn}, + '971', + "Hold 'better hold' isbn '971'."); + + t::lib::TestObjects::HoldFactory->deleteTestGroup($subtestContext->{hold}); + + my $holds_deleted = C4::Reserves::GetReservesFromBiblionumber({biblionumber => $holds->{'1A01-971-1N01'}->{biblio}->{biblionumber}}); + ok (not(@$holds_deleted), "Holds deleted"); +}; + + + ########## FileFactory subtests ########## subtest 't::lib::TestObjects::FileFactory' => \&testFileFactory; sub testFileFactory { -- 1.9.1