Main Koha release repository https://koha-community.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

596 lines
22 KiB

  1. #!/usr/bin/perl
  2. # Copyright 2019 Koha Development team
  3. #
  4. # This file is part of Koha
  5. #
  6. # Koha is free software; you can redistribute it and/or modify it
  7. # under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # Koha is distributed in the hope that it will be useful, but
  12. # WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with Koha; if not, see <http://www.gnu.org/licenses>.
  18. use Modern::Perl;
  19. use Test::More tests => 7;
  20. use C4::Biblio;
  21. use C4::Circulation;
  22. use Koha::Items;
  23. use Koha::Database;
  24. use Koha::Old::Items;
  25. use List::MoreUtils qw(all);
  26. use t::lib::TestBuilder;
  27. use t::lib::Mocks;
  28. my $schema = Koha::Database->new->schema;
  29. my $builder = t::lib::TestBuilder->new;
  30. subtest 'hidden_in_opac() tests' => sub {
  31. plan tests => 4;
  32. $schema->storage->txn_begin;
  33. my $item = $builder->build_sample_item({ itemlost => 2 });
  34. my $rules = {};
  35. # disable hidelostitems as it interteres with OpachiddenItems for the calculation
  36. t::lib::Mocks::mock_preference( 'hidelostitems', 0 );
  37. ok( !$item->hidden_in_opac, 'No rules passed, shouldn\'t hide' );
  38. ok( !$item->hidden_in_opac({ rules => $rules }), 'Empty rules passed, shouldn\'t hide' );
  39. # enable hidelostitems to verify correct behaviour
  40. t::lib::Mocks::mock_preference( 'hidelostitems', 1 );
  41. ok( $item->hidden_in_opac, 'Even with no rules, item should hide because of hidelostitems syspref' );
  42. # disable hidelostitems
  43. t::lib::Mocks::mock_preference( 'hidelostitems', 0 );
  44. my $withdrawn = $item->withdrawn + 1; # make sure this attribute doesn't match
  45. $rules = { withdrawn => [$withdrawn], itype => [ $item->itype ] };
  46. ok( $item->hidden_in_opac({ rules => $rules }), 'Rule matching itype passed, should hide' );
  47. $schema->storage->txn_rollback;
  48. };
  49. subtest 'has_pending_hold() tests' => sub {
  50. plan tests => 2;
  51. $schema->storage->txn_begin;
  52. my $dbh = C4::Context->dbh;
  53. my $item = $builder->build_sample_item({ itemlost => 0 });
  54. my $itemnumber = $item->itemnumber;
  55. $dbh->do("INSERT INTO tmp_holdsqueue (surname,borrowernumber,itemnumber) VALUES ('Clamp',42,$itemnumber)");
  56. ok( $item->has_pending_hold, "Yes, we have a pending hold");
  57. $dbh->do("DELETE FROM tmp_holdsqueue WHERE itemnumber=$itemnumber");
  58. ok( !$item->has_pending_hold, "We don't have a pending hold if nothing in the tmp_holdsqueue");
  59. $schema->storage->txn_rollback;
  60. };
  61. subtest "as_marc_field() tests" => sub {
  62. my $mss = C4::Biblio::GetMarcSubfieldStructure( '', { unsafe => 1 } );
  63. my @schema_columns = $schema->resultset('Item')->result_source->columns;
  64. my @mapped_columns = grep { exists $mss->{'items.'.$_} } @schema_columns;
  65. plan tests => 2 * (scalar @mapped_columns + 1) + 2;
  66. $schema->storage->txn_begin;
  67. my $item = $builder->build_sample_item;
  68. # Make sure it has at least one undefined attribute
  69. $item->set({ replacementprice => undef })->store->discard_changes;
  70. # Tests with the mss parameter
  71. my $marc_field = $item->as_marc_field({ mss => $mss });
  72. is(
  73. $marc_field->tag,
  74. $mss->{'items.itemnumber'}[0]->{tagfield},
  75. 'Generated field set the right tag number'
  76. );
  77. foreach my $column ( @mapped_columns ) {
  78. my $tagsubfield = $mss->{ 'items.' . $column }[0]->{tagsubfield};
  79. is( $marc_field->subfield($tagsubfield),
  80. $item->$column, "Value is mapped correctly for column $column" );
  81. }
  82. # Tests without the mss parameter
  83. $marc_field = $item->as_marc_field();
  84. is(
  85. $marc_field->tag,
  86. $mss->{'items.itemnumber'}[0]->{tagfield},
  87. 'Generated field set the right tag number'
  88. );
  89. foreach my $column (@mapped_columns) {
  90. my $tagsubfield = $mss->{ 'items.' . $column }[0]->{tagsubfield};
  91. is( $marc_field->subfield($tagsubfield),
  92. $item->$column, "Value is mapped correctly for column $column" );
  93. }
  94. my $unmapped_subfield = Koha::MarcSubfieldStructure->new(
  95. {
  96. frameworkcode => '',
  97. tagfield => $mss->{'items.itemnumber'}[0]->{tagfield},
  98. tagsubfield => 'X',
  99. }
  100. )->store;
  101. $mss = C4::Biblio::GetMarcSubfieldStructure( '', { unsafe => 0 } );
  102. my @unlinked_subfields;
  103. push @unlinked_subfields, X => 'Something weird';
  104. $item->more_subfields_xml( C4::Items::_get_unlinked_subfields_xml( \@unlinked_subfields ) )->store;
  105. $marc_field = $item->as_marc_field;
  106. my @subfields = $marc_field->subfields;
  107. my $result = all { defined $_->[1] } @subfields;
  108. ok( $result, 'There are no undef subfields' );
  109. is( scalar $marc_field->subfield('X'), 'Something weird', 'more_subfield_xml is considered' );
  110. $schema->storage->txn_rollback;
  111. };
  112. subtest 'pickup_locations' => sub {
  113. $schema->storage->txn_begin;
  114. my $dbh = C4::Context->dbh;
  115. my $root1 = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1, branchcode => undef } } );
  116. my $root2 = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1, branchcode => undef } } );
  117. my $library1 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1, } } );
  118. my $library2 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1, } } );
  119. my $library3 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 0, } } );
  120. my $library4 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1, } } );
  121. my $group1_1 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root1->id, branchcode => $library1->branchcode } } );
  122. my $group1_2 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root1->id, branchcode => $library2->branchcode } } );
  123. my $group2_1 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root2->id, branchcode => $library3->branchcode } } );
  124. my $group2_2 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root2->id, branchcode => $library4->branchcode } } );
  125. my $item1 = $builder->build_sample_item(
  126. {
  127. homebranch => $library1->branchcode,
  128. holdingbranch => $library2->branchcode,
  129. barcode => '1',
  130. ccode => 'Gollum'
  131. }
  132. )->store;
  133. my $item3 = $builder->build_sample_item(
  134. {
  135. homebranch => $library3->branchcode,
  136. holdingbranch => $library4->branchcode,
  137. barcode => '3',
  138. itype => $item1->itype,
  139. }
  140. )->store;
  141. Koha::CirculationRules->set_rules(
  142. {
  143. categorycode => undef,
  144. itemtype => $item1->itype,
  145. branchcode => undef,
  146. rules => {
  147. reservesallowed => 25,
  148. }
  149. }
  150. );
  151. my $patron1 = $builder->build_object( { class => 'Koha::Patrons', value => { branchcode => $library1->branchcode, firstname => '1' } } );
  152. my $patron4 = $builder->build_object( { class => 'Koha::Patrons', value => { branchcode => $library4->branchcode, firstname => '4' } } );
  153. my $all_count = Koha::Libraries->search({ pickup_location => 1})->count();
  154. plan tests => ($all_count +1) * 7 + 31 + 60;
  155. my $results = {
  156. "1-1-1-any" => $all_count,
  157. "1-1-1-holdgroup" => 2,
  158. "1-1-1-patrongroup" => 2,
  159. "1-1-1-homebranch" => 1,
  160. "1-1-1-holdingbranch" => 1,
  161. "1-1-2-any" => $all_count,
  162. "1-1-2-holdgroup" => 2,
  163. "1-1-2-patrongroup" => 2,
  164. "1-1-2-homebranch" => 1,
  165. "1-1-2-holdingbranch" => 1,
  166. "1-1-3-any" => $all_count,
  167. "1-1-3-holdgroup" => 2,
  168. "1-1-3-patrongroup" => 2,
  169. "1-1-3-homebranch" => 1,
  170. "1-1-3-holdingbranch" => 1,
  171. "1-4-1-any" => 0,
  172. "1-4-1-holdgroup" => 0,
  173. "1-4-1-patrongroup" => 0,
  174. "1-4-1-homebranch" => 0,
  175. "1-4-1-holdingbranch" => 0,
  176. "1-4-2-any" => $all_count,
  177. "1-4-2-holdgroup" => 2,
  178. "1-4-2-patrongroup" => 1,
  179. "1-4-2-homebranch" => 1,
  180. "1-4-2-holdingbranch" => 1,
  181. "1-4-3-any" => 0,
  182. "1-4-3-holdgroup" => 0,
  183. "1-4-3-patrongroup" => 0,
  184. "1-4-3-homebranch" => 0,
  185. "1-4-3-holdingbranch" => 0,
  186. "3-1-1-any" => 0,
  187. "3-1-1-holdgroup" => 0,
  188. "3-1-1-patrongroup" => 0,
  189. "3-1-1-homebranch" => 0,
  190. "3-1-1-holdingbranch" => 0,
  191. "3-1-2-any" => $all_count,
  192. "3-1-2-holdgroup" => 1,
  193. "3-1-2-patrongroup" => 2,
  194. "3-1-2-homebranch" => 0,
  195. "3-1-2-holdingbranch" => 1,
  196. "3-1-3-any" => 0,
  197. "3-1-3-holdgroup" => 0,
  198. "3-1-3-patrongroup" => 0,
  199. "3-1-3-homebranch" => 0,
  200. "3-1-3-holdingbranch" => 0,
  201. "3-4-1-any" => 0,
  202. "3-4-1-holdgroup" => 0,
  203. "3-4-1-patrongroup" => 0,
  204. "3-4-1-homebranch" => 0,
  205. "3-4-1-holdingbranch" => 0,
  206. "3-4-2-any" => $all_count,
  207. "3-4-2-holdgroup" => 1,
  208. "3-4-2-patrongroup" => 1,
  209. "3-4-2-homebranch" => 0,
  210. "3-4-2-holdingbranch" => 1,
  211. "3-4-3-any" => $all_count,
  212. "3-4-3-holdgroup" => 1,
  213. "3-4-3-patrongroup" => 1,
  214. "3-4-3-homebranch" => 0,
  215. "3-4-3-holdingbranch" => 1
  216. };
  217. sub _doTest {
  218. my ( $item, $patron, $ha, $hfp, $results ) = @_;
  219. Koha::CirculationRules->set_rules(
  220. {
  221. branchcode => undef,
  222. itemtype => undef,
  223. rules => {
  224. holdallowed => $ha,
  225. hold_fulfillment_policy => $hfp,
  226. returnbranch => 'any'
  227. }
  228. }
  229. );
  230. my @pl = $item->pickup_locations( { patron => $patron} )->as_list;
  231. my $ha_value=$ha==3?'holdgroup':($ha==2?'any':'homebranch');
  232. foreach my $pickup_location (@pl) {
  233. is( ref($pickup_location), 'Koha::Library', 'Object type is correct' );
  234. }
  235. ok(
  236. scalar(@pl) == $results->{
  237. $item->barcode . '-'
  238. . $patron->firstname . '-'
  239. . $ha . '-'
  240. . $hfp
  241. },
  242. 'item'
  243. . $item->barcode
  244. . ', patron'
  245. . $patron->firstname
  246. . ', holdallowed: '
  247. . $ha_value
  248. . ', hold_fulfillment_policy: '
  249. . $hfp
  250. . ' should return '
  251. . $results->{
  252. $item->barcode . '-'
  253. . $patron->firstname . '-'
  254. . $ha . '-'
  255. . $hfp
  256. }
  257. . ' and returns '
  258. . scalar(@pl)
  259. );
  260. }
  261. foreach my $item ($item1, $item3) {
  262. foreach my $patron ($patron1, $patron4) {
  263. #holdallowed 1: homebranch, 2: any, 3: holdgroup
  264. foreach my $ha (1, 2, 3) {
  265. foreach my $hfp ('any', 'holdgroup', 'patrongroup', 'homebranch', 'holdingbranch') {
  266. _doTest($item, $patron, $ha, $hfp, $results);
  267. }
  268. }
  269. }
  270. }
  271. # Now test that branchtransferlimits will further filter the pickup locations
  272. t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1);
  273. t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype');
  274. Koha::CirculationRules->set_rules(
  275. {
  276. branchcode => undef,
  277. itemtype => $item1->itype,
  278. rules => {
  279. holdallowed => 1,
  280. hold_fulfillment_policy => 1,
  281. returnbranch => 'any'
  282. }
  283. }
  284. );
  285. $builder->build_object(
  286. {
  287. class => 'Koha::Item::Transfer::Limits',
  288. value => {
  289. toBranch => $library1->branchcode,
  290. fromBranch => $library2->branchcode,
  291. itemtype => $item1->itype,
  292. ccode => undef,
  293. }
  294. }
  295. );
  296. my $pickup_locations = $item1->pickup_locations( { patron => $patron1 } )->as_list;
  297. is( scalar @$pickup_locations, $all_count - 1, "With a transfer limits we get back the libraries that are pickup locations minus 1 limited library");
  298. $builder->build_object(
  299. {
  300. class => 'Koha::Item::Transfer::Limits',
  301. value => {
  302. toBranch => $library4->branchcode,
  303. fromBranch => $library2->branchcode,
  304. itemtype => $item1->itype,
  305. ccode => undef,
  306. }
  307. }
  308. );
  309. $pickup_locations = $item1->pickup_locations( { patron => $patron1 } )->as_list;
  310. is( scalar @$pickup_locations, $all_count - 2, "With 2 transfer limits we get back the libraries that are pickup locations minus 2 limited libraries");
  311. t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'ccode');
  312. $pickup_locations = $item1->pickup_locations( { patron => $patron1 } )->as_list;
  313. is( scalar @$pickup_locations, $all_count, "With no transfer limits of type ccode we get back the libraries that are pickup locations");
  314. $builder->build_object(
  315. {
  316. class => 'Koha::Item::Transfer::Limits',
  317. value => {
  318. toBranch => $library2->branchcode,
  319. fromBranch => $library2->branchcode,
  320. itemtype => undef,
  321. ccode => $item1->ccode,
  322. }
  323. }
  324. );
  325. $pickup_locations = $item1->pickup_locations( { patron => $patron1 } )->as_list;
  326. is( scalar @$pickup_locations, $all_count - 1, "With a transfer limits we get back the libraries that are pickup locations minus 1 limited library");
  327. $builder->build_object(
  328. {
  329. class => 'Koha::Item::Transfer::Limits',
  330. value => {
  331. toBranch => $library4->branchcode,
  332. fromBranch => $library2->branchcode,
  333. itemtype => undef,
  334. ccode => $item1->ccode,
  335. }
  336. }
  337. );
  338. $pickup_locations = $item1->pickup_locations( { patron => $patron1 } )->as_list;
  339. is( scalar @$pickup_locations, $all_count - 2, "With 2 transfer limits we get back the libraries that are pickup locations minus 2 limited libraries");
  340. t::lib::Mocks::mock_preference('UseBranchTransferLimits', 0);
  341. $schema->storage->txn_rollback;
  342. };
  343. subtest 'deletion' => sub {
  344. plan tests => 12;
  345. $schema->storage->txn_begin;
  346. my $biblio = $builder->build_sample_biblio();
  347. my $item = $builder->build_sample_item(
  348. {
  349. biblionumber => $biblio->biblionumber,
  350. }
  351. );
  352. is( ref( $item->move_to_deleted ), 'Koha::Schema::Result::Deleteditem', 'Koha::Item->move_to_deleted should return the Deleted item' )
  353. ; # FIXME This should be Koha::Deleted::Item
  354. is( Koha::Old::Items->search({itemnumber => $item->itemnumber})->count, 1, '->move_to_deleted must have moved the item to deleteditem' );
  355. $item = $builder->build_sample_item(
  356. {
  357. biblionumber => $biblio->biblionumber,
  358. }
  359. );
  360. $item->delete;
  361. is( Koha::Old::Items->search({itemnumber => $item->itemnumber})->count, 0, '->move_to_deleted must not have moved the item to deleteditem' );
  362. my $library = $builder->build_object({ class => 'Koha::Libraries' });
  363. my $library_2 = $builder->build_object({ class => 'Koha::Libraries' });
  364. t::lib::Mocks::mock_userenv({ branchcode => $library->branchcode });
  365. my $patron = $builder->build_object({class => 'Koha::Patrons'});
  366. $item = $builder->build_sample_item({ library => $library->branchcode });
  367. # book_on_loan
  368. C4::Circulation::AddIssue( $patron->unblessed, $item->barcode );
  369. is(
  370. $item->safe_to_delete,
  371. 'book_on_loan',
  372. 'Koha::Item->safe_to_delete reports item on loan',
  373. );
  374. is(
  375. $item->safe_delete,
  376. 'book_on_loan',
  377. 'item that is on loan cannot be deleted',
  378. );
  379. AddReturn( $item->barcode, $library->branchcode );
  380. # book_reserved is tested in t/db_dependent/Reserves.t
  381. # not_same_branch
  382. t::lib::Mocks::mock_preference('IndependentBranches', 1);
  383. my $item_2 = $builder->build_sample_item({ library => $library_2->branchcode });
  384. is(
  385. $item_2->safe_to_delete,
  386. 'not_same_branch',
  387. 'Koha::Item->safe_to_delete reports IndependentBranches restriction',
  388. );
  389. is(
  390. $item_2->safe_delete,
  391. 'not_same_branch',
  392. 'IndependentBranches prevents deletion at another branch',
  393. );
  394. # linked_analytics
  395. { # codeblock to limit scope of $module->mock
  396. my $module = Test::MockModule->new('C4::Items');
  397. $module->mock( GetAnalyticsCount => sub { return 1 } );
  398. $item->discard_changes;
  399. is(
  400. $item->safe_to_delete,
  401. 'linked_analytics',
  402. 'Koha::Item->safe_to_delete reports linked analytics',
  403. );
  404. is(
  405. $item->safe_delete,
  406. 'linked_analytics',
  407. 'Linked analytics prevents deletion of item',
  408. );
  409. }
  410. { # last_item_for_hold
  411. C4::Reserves::AddReserve({ branchcode => $patron->branchcode, borrowernumber => $patron->borrowernumber, biblionumber => $item->biblionumber });
  412. is( $item->safe_to_delete, 'last_item_for_hold', 'Item cannot be deleted if a biblio-level is placed on the biblio and there is only 1 item attached to the biblio' );
  413. # With another item attached to the biblio, the item can be deleted
  414. $builder->build_sample_item({ biblionumber => $item->biblionumber });
  415. }
  416. is(
  417. $item->safe_to_delete,
  418. 1,
  419. 'Koha::Item->safe_to_delete shows item safe to delete'
  420. );
  421. $item->safe_delete,
  422. my $test_item = Koha::Items->find( $item->itemnumber );
  423. is( $test_item, undef,
  424. "Koha::Item->safe_delete should delete item if safe_to_delete returns true"
  425. );
  426. $schema->storage->txn_rollback;
  427. };
  428. subtest 'renewal_branchcode' => sub {
  429. plan tests => 13;
  430. $schema->storage->txn_begin;
  431. my $item = $builder->build_sample_item();
  432. my $branch = $builder->build_object({ class => 'Koha::Libraries' });
  433. my $checkout = $builder->build_object({
  434. class => 'Koha::Checkouts',
  435. value => {
  436. itemnumber => $item->itemnumber,
  437. }
  438. });
  439. C4::Context->interface( 'intranet' );
  440. t::lib::Mocks::mock_userenv({ branchcode => $branch->branchcode });
  441. is( $item->renewal_branchcode, $branch->branchcode, "If interface not opac, we get the branch from context");
  442. is( $item->renewal_branchcode({ branch => "PANDA"}), $branch->branchcode, "If interface not opac, we get the branch from context even if we pass one in");
  443. C4::Context->set_userenv(51, 'userid4tests', undef, 'firstname', 'surname', undef, undef, 0, undef, undef, undef ); #mock userenv doesn't let us set null branch
  444. is( $item->renewal_branchcode({ branch => "PANDA"}), "PANDA", "If interface not opac, we get the branch we pass one in if context not set");
  445. C4::Context->interface( 'opac' );
  446. t::lib::Mocks::mock_preference('OpacRenewalBranch', undef);
  447. is( $item->renewal_branchcode, 'OPACRenew', "If interface opac and OpacRenewalBranch undef, we get OPACRenew");
  448. is( $item->renewal_branchcode({branch=>'COW'}), 'OPACRenew', "If interface opac and OpacRenewalBranch undef, we get OPACRenew even if branch passed");
  449. t::lib::Mocks::mock_preference('OpacRenewalBranch', 'none');
  450. is( $item->renewal_branchcode, '', "If interface opac and OpacRenewalBranch is none, we get blank string");
  451. is( $item->renewal_branchcode({branch=>'COW'}), '', "If interface opac and OpacRenewalBranch is none, we get blank string even if branch passed");
  452. t::lib::Mocks::mock_preference('OpacRenewalBranch', 'checkoutbranch');
  453. is( $item->renewal_branchcode, $checkout->branchcode, "If interface opac and OpacRenewalBranch set to checkoutbranch, we get branch of checkout");
  454. is( $item->renewal_branchcode({branch=>'MONKEY'}), $checkout->branchcode, "If interface opac and OpacRenewalBranch set to checkoutbranch, we get branch of checkout even if branch passed");
  455. t::lib::Mocks::mock_preference('OpacRenewalBranch','patronhomebranch');
  456. is( $item->renewal_branchcode, $checkout->patron->branchcode, "If interface opac and OpacRenewalBranch set to patronbranch, we get branch of patron");
  457. is( $item->renewal_branchcode({branch=>'TURKEY'}), $checkout->patron->branchcode, "If interface opac and OpacRenewalBranch set to patronbranch, we get branch of patron even if branch passed");
  458. t::lib::Mocks::mock_preference('OpacRenewalBranch','itemhomebranch');
  459. is( $item->renewal_branchcode, $item->homebranch, "If interface opac and OpacRenewalBranch set to itemhomebranch, we get homebranch of item");
  460. is( $item->renewal_branchcode({branch=>'MANATEE'}), $item->homebranch, "If interface opac and OpacRenewalBranch set to itemhomebranch, we get homebranch of item even if branch passed");
  461. $schema->storage->txn_rollback;
  462. };
  463. subtest 'Tests for itemtype' => sub {
  464. plan tests => 2;
  465. $schema->storage->txn_begin;
  466. my $biblio = $builder->build_sample_biblio;
  467. my $itemtype = $builder->build_object({ class => 'Koha::ItemTypes' });
  468. my $item = $builder->build_sample_item({ biblionumber => $biblio->biblionumber, itype => $itemtype->itemtype });
  469. t::lib::Mocks::mock_preference('item-level_itypes', 1);
  470. is( $item->itemtype->itemtype, $item->itype, 'Pref enabled' );
  471. t::lib::Mocks::mock_preference('item-level_itypes', 0);
  472. is( $item->itemtype->itemtype, $biblio->biblioitem->itemtype, 'Pref disabled' );
  473. $schema->storage->txn_rollback;
  474. };