From d7808795650bdef6b6adcc0079373f70b07ad4ea Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Tue, 12 Jul 2022 16:22:46 +0100 Subject: [PATCH] Bug 31086: (QA follow-up) Add unit tests This patch adds the unit tests for the change to Koha::Hold::store. We test for and catch the exception introduced for both the create and update cases. Signed-off-by: Martin Renvoize Signed-off-by: Tomas Cohen Arazi (cherry picked from commit f0685f0f4053da428ab13d9f3991790fb71b7e55) Signed-off-by: Lucas Gass (cherry picked from commit bc95ffa3e3f97738f54ce56e2af0422bfc05bc57) Signed-off-by: Arthur Suzuki --- t/db_dependent/Koha/Hold.t | 271 ++++++++++++++++++++++++++++++++++++- 1 file changed, 270 insertions(+), 1 deletion(-) diff --git a/t/db_dependent/Koha/Hold.t b/t/db_dependent/Koha/Hold.t index addf0e4ae4..cee2180594 100755 --- a/t/db_dependent/Koha/Hold.t +++ b/t/db_dependent/Koha/Hold.t @@ -19,7 +19,7 @@ use Modern::Perl; -use Test::More tests => 3; +use Test::More tests => 4; use Test::Exception; use Test::MockModule; @@ -31,6 +31,275 @@ use Koha::Libraries; my $schema = Koha::Database->new->schema; my $builder = t::lib::TestBuilder->new; +subtest 'store() tests' => sub { + plan tests => 2; + + $schema->storage->txn_begin; + + my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); + my $item = $builder->build_sample_item; + throws_ok { + Koha::Hold->new( + { + borrowernumber => $patron->borrowernumber, + biblionumber => $item->biblionumber, + priority => 1, + itemnumber => $item->itemnumber, + } + )->store + } + 'Koha::Exceptions::Hold::MissingPickupLocation', + 'Exception thrown because branchcode was not passed'; + + my $hold = $builder->build_object( { class => 'Koha::Holds' } ); + throws_ok { + $hold->branchcode(undef)->store; + } + 'Koha::Exceptions::Hold::MissingPickupLocation', + 'Exception thrown if one tries to set branchcode to null'; + + $schema->storage->txn_rollback; +}; + +subtest 'fill() tests' => sub { + + plan tests => 13; + + $schema->storage->txn_begin; + + my $fee = 15; + + my $category = $builder->build_object( + { + class => 'Koha::Patron::Categories', + value => { reservefee => $fee } + } + ); + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { categorycode => $category->id } + } + ); + my $manager = $builder->build_object( { class => 'Koha::Patrons' } ); + + my $title = 'Do what you want'; + my $biblio = $builder->build_sample_biblio( { title => $title } ); + my $item = $builder->build_sample_item( { biblionumber => $biblio->id } ); + my $hold = $builder->build_object( + { + class => 'Koha::Holds', + value => { + biblionumber => $biblio->id, + borrowernumber => $patron->id, + itemnumber => $item->id, + priority => 10, + } + } + ); + + t::lib::Mocks::mock_preference( 'HoldFeeMode', 'any_time_is_collected' ); + t::lib::Mocks::mock_preference( 'HoldsLog', 1 ); + t::lib::Mocks::mock_userenv( + { patron => $manager, branchcode => $manager->branchcode } ); + + my $interface = 'api'; + C4::Context->interface($interface); + + my $ret = $hold->fill; + + is( ref($ret), 'Koha::Hold', '->fill returns the object type' ); + is( $ret->id, $hold->id, '->fill returns the object' ); + + is( Koha::Holds->find($hold->id), undef, 'Hold no longer current' ); + my $old_hold = Koha::Old::Holds->find( $hold->id ); + + is( $old_hold->id, $hold->id, 'reserve_id retained' ); + is( $old_hold->priority, 0, 'priority set to 0' ); + is( $old_hold->found, 'F', 'found set to F' ); + + subtest 'fee applied tests' => sub { + + plan tests => 9; + + my $account = $patron->account; + is( $account->balance, $fee, 'Charge applied correctly' ); + + my $debits = $account->outstanding_debits; + is( $debits->count, 1, 'Only one fee charged' ); + + my $fee_debit = $debits->next; + is( $fee_debit->amount * 1, $fee, 'Fee amount stored correctly' ); + is( $fee_debit->description, $title, + 'Fee description stored correctly' ); + is( $fee_debit->manager_id, $manager->id, + 'Fee manager_id stored correctly' ); + is( $fee_debit->branchcode, $manager->branchcode, + 'Fee branchcode stored correctly' ); + is( $fee_debit->interface, $interface, + 'Fee interface stored correctly' ); + is( $fee_debit->debit_type_code, + 'RESERVE', 'Fee debit_type_code stored correctly' ); + is( $fee_debit->itemnumber, $item->id, + 'Fee itemnumber stored correctly' ); + }; + + my $logs = Koha::ActionLogs->search( + { + action => 'FILL', + module => 'HOLDS', + object => $hold->id + } + ); + + is( $logs->count, 1, '1 log line added' ); + + # Set HoldFeeMode to something other than any_time_is_collected + t::lib::Mocks::mock_preference( 'HoldFeeMode', 'not_always' ); + # Disable logging + t::lib::Mocks::mock_preference( 'HoldsLog', 0 ); + + $hold = $builder->build_object( + { + class => 'Koha::Holds', + value => { + biblionumber => $biblio->id, + borrowernumber => $patron->id, + itemnumber => $item->id, + priority => 10, + } + } + ); + + $hold->fill; + + my $account = $patron->account; + is( $account->balance, $fee, 'No new charge applied' ); + + my $debits = $account->outstanding_debits; + is( $debits->count, 1, 'Only one fee charged, because of HoldFeeMode' ); + + $logs = Koha::ActionLogs->search( + { + action => 'FILL', + module => 'HOLDS', + object => $hold->id + } + ); + + is( $logs->count, 0, 'HoldsLog disabled, no logs added' ); + + subtest 'anonymization behavior tests' => sub { + + plan tests => 5; + + # reduce the tests noise + t::lib::Mocks::mock_preference( 'HoldsLog', 0 ); + t::lib::Mocks::mock_preference( 'HoldFeeMode', 'not_always' ); + # unset AnonymousPatron + t::lib::Mocks::mock_preference( 'AnonymousPatron', undef ); + + # 0 == keep forever + $patron->privacy(0)->store; + my $hold = $builder->build_object( + { + class => 'Koha::Holds', + value => { borrowernumber => $patron->id, found => undef } + } + ); + $hold->fill(); + is( Koha::Old::Holds->find( $hold->id )->borrowernumber, + $patron->borrowernumber, 'Patron link is kept' ); + + # 1 == "default", meaning it is not protected from removal + $patron->privacy(1)->store; + $hold = $builder->build_object( + { + class => 'Koha::Holds', + value => { borrowernumber => $patron->id, found => undef } + } + ); + $hold->fill(); + is( Koha::Old::Holds->find( $hold->id )->borrowernumber, + $patron->borrowernumber, 'Patron link is kept' ); + + # 2 == delete immediately + $patron->privacy(2)->store; + $hold = $builder->build_object( + { + class => 'Koha::Holds', + value => { borrowernumber => $patron->id, found => undef } + } + ); + + throws_ok + { $hold->fill(); } + 'Koha::Exception', + 'AnonymousPatron not set, exception thrown'; + + $hold->discard_changes; # refresh from DB + + ok( !$hold->is_found, 'Hold is not filled' ); + + my $anonymous_patron = $builder->build_object({ class => 'Koha::Patrons' }); + t::lib::Mocks::mock_preference( 'AnonymousPatron', $anonymous_patron->id ); + + $hold = $builder->build_object( + { + class => 'Koha::Holds', + value => { borrowernumber => $patron->id, found => undef } + } + ); + $hold->fill(); + is( + Koha::Old::Holds->find( $hold->id )->borrowernumber, + $anonymous_patron->id, + 'Patron link is set to the configured anonymous patron immediately' + ); + }; + + subtest 'holds_queue update tests' => sub { + + plan tests => 1; + + my $biblio = $builder->build_sample_biblio; + + my $mock = Test::MockModule->new('Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue'); + $mock->mock( 'enqueue', sub { + my ( $self, $args ) = @_; + is_deeply( + $args->{biblio_ids}, + [ $biblio->id ], + '->fill triggers a holds queue update for the related biblio' + ); + } ); + + t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 1 ); + + $builder->build_object( + { + class => 'Koha::Holds', + value => { + biblionumber => $biblio->id, + } + } + )->fill; + + t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 0 ); + # this call shouldn't add a new test + $builder->build_object( + { + class => 'Koha::Holds', + value => { + biblionumber => $biblio->id, + } + } + )->fill; + }; + + $schema->storage->txn_rollback; +}; + subtest 'patron() tests' => sub { plan tests => 2; -- 2.20.1