|
Lines 19-25
Link Here
|
| 19 |
|
19 |
|
| 20 |
use Modern::Perl; |
20 |
use Modern::Perl; |
| 21 |
|
21 |
|
| 22 |
use Test::More tests => 34; |
22 |
use Test::More tests => 39; |
| 23 |
use Test::Warn; |
23 |
use Test::Warn; |
| 24 |
use Test::Exception; |
24 |
use Test::Exception; |
| 25 |
use Test::MockModule; |
25 |
use Test::MockModule; |
|
Lines 1453-1458
subtest 'Log cardnumber change' => sub {
Link Here
|
| 1453 |
is( scalar @logs, 2, 'With BorrowerLogs, Change in cardnumber should be logged, as well as general alert of patron mod.' ); |
1453 |
is( scalar @logs, 2, 'With BorrowerLogs, Change in cardnumber should be logged, as well as general alert of patron mod.' ); |
| 1454 |
}; |
1454 |
}; |
| 1455 |
|
1455 |
|
|
|
1456 |
subtest 'search_unsubscribed' => sub { |
| 1457 |
plan tests => 4; |
| 1458 |
|
| 1459 |
t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 3 ); |
| 1460 |
t::lib::Mocks::mock_preference( 'UnsubscribeReflectionDelay', '' ); |
| 1461 |
is( Koha::Patrons->search_unsubscribed->count, 0, 'Empty delay should return empty set' ); |
| 1462 |
|
| 1463 |
my $patron1 = $builder->build_object({ class => 'Koha::Patrons' }); |
| 1464 |
my $patron2 = $builder->build_object({ class => 'Koha::Patrons' }); |
| 1465 |
|
| 1466 |
t::lib::Mocks::mock_preference( 'UnsubscribeReflectionDelay', 0 ); |
| 1467 |
Koha::Patron::Consents->delete; # for correct counts |
| 1468 |
Koha::Patron::Consent->new({ borrowernumber => $patron1->borrowernumber, type => 'GDPR_PROCESSING', refused_on => dt_from_string })->store; |
| 1469 |
is( Koha::Patrons->search_unsubscribed->count, 1, 'Find patron1' ); |
| 1470 |
|
| 1471 |
# Add another refusal but shift the period |
| 1472 |
t::lib::Mocks::mock_preference( 'UnsubscribeReflectionDelay', 2 ); |
| 1473 |
Koha::Patron::Consent->new({ borrowernumber => $patron2->borrowernumber, type => 'GDPR_PROCESSING', refused_on => dt_from_string->subtract(days=>2) })->store; |
| 1474 |
is( Koha::Patrons->search_unsubscribed->count, 1, 'Find patron2 only' ); |
| 1475 |
|
| 1476 |
# Try another (special) attempts setting |
| 1477 |
t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 0 ); |
| 1478 |
# Lockout is now disabled |
| 1479 |
# Patron2 still matches: refused earlier, not locked |
| 1480 |
is( Koha::Patrons->search_unsubscribed->count, 1, 'Lockout disabled' ); |
| 1481 |
}; |
| 1482 |
|
| 1483 |
subtest 'search_anonymize_candidates' => sub { |
| 1484 |
plan tests => 5; |
| 1485 |
my $patron1 = $builder->build_object({ class => 'Koha::Patrons' }); |
| 1486 |
my $patron2 = $builder->build_object({ class => 'Koha::Patrons' }); |
| 1487 |
$patron1->flgAnonymized(0); |
| 1488 |
$patron1->dateexpiry( dt_from_string->add(days => 1) )->store; |
| 1489 |
$patron2->flgAnonymized(undef); |
| 1490 |
$patron2->dateexpiry( dt_from_string->add(days => 1) )->store; |
| 1491 |
|
| 1492 |
t::lib::Mocks::mock_preference( 'PatronAnonymizeDelay', q{} ); |
| 1493 |
is( Koha::Patrons->search_anonymize_candidates->count, 0, 'Empty set' ); |
| 1494 |
|
| 1495 |
t::lib::Mocks::mock_preference( 'PatronAnonymizeDelay', 0 ); |
| 1496 |
my $cnt = Koha::Patrons->search_anonymize_candidates->count; |
| 1497 |
$patron1->dateexpiry( dt_from_string->subtract(days => 1) )->store; |
| 1498 |
$patron2->dateexpiry( dt_from_string->subtract(days => 3) )->store; |
| 1499 |
is( Koha::Patrons->search_anonymize_candidates->count, $cnt+2, 'Delay 0' ); |
| 1500 |
|
| 1501 |
t::lib::Mocks::mock_preference( 'PatronAnonymizeDelay', 2 ); |
| 1502 |
$patron1->dateexpiry( dt_from_string->add(days => 1) )->store; |
| 1503 |
$patron2->dateexpiry( dt_from_string->add(days => 1) )->store; |
| 1504 |
$cnt = Koha::Patrons->search_anonymize_candidates->count; |
| 1505 |
$patron1->dateexpiry( dt_from_string->subtract(days => 1) )->store; |
| 1506 |
$patron2->dateexpiry( dt_from_string->subtract(days => 3) )->store; |
| 1507 |
is( Koha::Patrons->search_anonymize_candidates->count, $cnt+1, 'Delay 2' ); |
| 1508 |
|
| 1509 |
t::lib::Mocks::mock_preference( 'PatronAnonymizeDelay', 4 ); |
| 1510 |
$patron1->dateexpiry( dt_from_string->add(days => 1) )->store; |
| 1511 |
$patron2->dateexpiry( dt_from_string->add(days => 1) )->store; |
| 1512 |
$cnt = Koha::Patrons->search_anonymize_candidates->count; |
| 1513 |
$patron1->dateexpiry( dt_from_string->subtract(days => 1) )->store; |
| 1514 |
$patron2->dateexpiry( dt_from_string->subtract(days => 3) )->store; |
| 1515 |
is( Koha::Patrons->search_anonymize_candidates->count, $cnt, 'Delay 4' ); |
| 1516 |
|
| 1517 |
t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 3 ); |
| 1518 |
$patron1->dateexpiry( dt_from_string->subtract(days => 5) )->store; |
| 1519 |
$patron1->login_attempts(0)->store; |
| 1520 |
$patron2->dateexpiry( dt_from_string->subtract(days => 5) )->store; |
| 1521 |
$patron2->login_attempts(0)->store; |
| 1522 |
$cnt = Koha::Patrons->search_anonymize_candidates({locked => 1})->count; |
| 1523 |
$patron1->login_attempts(3)->store; |
| 1524 |
is( Koha::Patrons->search_anonymize_candidates({locked => 1})->count, |
| 1525 |
$cnt+1, 'Locked flag' ); |
| 1526 |
}; |
| 1527 |
|
| 1528 |
subtest 'search_anonymized' => sub { |
| 1529 |
plan tests => 3; |
| 1530 |
my $patron1 = $builder->build_object( { class => 'Koha::Patrons' } ); |
| 1531 |
|
| 1532 |
t::lib::Mocks::mock_preference( 'PatronRemovalDelay', q{} ); |
| 1533 |
is( Koha::Patrons->search_anonymized->count, 0, 'Empty set' ); |
| 1534 |
|
| 1535 |
t::lib::Mocks::mock_preference( 'PatronRemovalDelay', 1 ); |
| 1536 |
$patron1->dateexpiry( dt_from_string ); |
| 1537 |
$patron1->flgAnonymized(0)->store; |
| 1538 |
my $cnt = Koha::Patrons->search_anonymized->count; |
| 1539 |
$patron1->flgAnonymized(1)->store; |
| 1540 |
is( Koha::Patrons->search_anonymized->count, $cnt, 'Number unchanged' ); |
| 1541 |
$patron1->dateexpiry( dt_from_string->subtract(days => 1) )->store; |
| 1542 |
is( Koha::Patrons->search_anonymized->count, $cnt+1, 'Found patron1' ); |
| 1543 |
}; |
| 1544 |
|
| 1545 |
subtest 'lock' => sub { |
| 1546 |
plan tests => 8; |
| 1547 |
|
| 1548 |
my $patron1 = $builder->build_object( { class => 'Koha::Patrons' } ); |
| 1549 |
my $patron2 = $builder->build_object( { class => 'Koha::Patrons' } ); |
| 1550 |
my $hold = $builder->build_object({ |
| 1551 |
class => 'Koha::Holds', |
| 1552 |
value => { borrowernumber => $patron1->borrowernumber }, |
| 1553 |
}); |
| 1554 |
|
| 1555 |
t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 3 ); |
| 1556 |
my $expiry = dt_from_string->add(days => 1); |
| 1557 |
$patron1->dateexpiry( $expiry ); |
| 1558 |
$patron1->lock; |
| 1559 |
is( $patron1->login_attempts, Koha::Patron::ADMINISTRATIVE_LOCKOUT, 'Check login_attempts' ); |
| 1560 |
is( $patron1->dateexpiry, $expiry, 'Not expired yet' ); |
| 1561 |
is( $patron1->holds->count, 1, 'No holds removed' ); |
| 1562 |
|
| 1563 |
$patron1->lock({ expire => 1, remove => 1}); |
| 1564 |
isnt( $patron1->dateexpiry, $expiry, 'Expiry date adjusted' ); |
| 1565 |
is( $patron1->holds->count, 0, 'Holds removed' ); |
| 1566 |
|
| 1567 |
# Disable lockout feature |
| 1568 |
t::lib::Mocks::mock_preference( 'FailedLoginAttempts', q{} ); |
| 1569 |
$patron1->login_attempts(0); |
| 1570 |
$patron1->dateexpiry( $expiry ); |
| 1571 |
$patron1->store; |
| 1572 |
$patron1->lock; |
| 1573 |
is( $patron1->login_attempts, Koha::Patron::ADMINISTRATIVE_LOCKOUT, 'Check login_attempts' ); |
| 1574 |
|
| 1575 |
# Trivial wrapper test (Koha::Patrons->lock) |
| 1576 |
$patron1->login_attempts(0)->store; |
| 1577 |
Koha::Patrons->search({ borrowernumber => [ $patron1->borrowernumber, $patron2->borrowernumber ] })->lock; |
| 1578 |
$patron1->discard_changes; # refresh |
| 1579 |
$patron2->discard_changes; |
| 1580 |
is( $patron1->login_attempts, Koha::Patron::ADMINISTRATIVE_LOCKOUT, 'Check login_attempts patron 1' ); |
| 1581 |
is( $patron2->login_attempts, Koha::Patron::ADMINISTRATIVE_LOCKOUT, 'Check login_attempts patron 2' ); |
| 1582 |
}; |
| 1583 |
|
| 1584 |
subtest 'anonymize' => sub { |
| 1585 |
plan tests => 9; |
| 1586 |
|
| 1587 |
my $patron1 = $builder->build_object( { class => 'Koha::Patrons' } ); |
| 1588 |
my $patron2 = $builder->build_object( { class => 'Koha::Patrons' } ); |
| 1589 |
|
| 1590 |
# First try patron with issues |
| 1591 |
my $issue = $builder->build_object({ class => 'Koha::Checkouts', value => { borrowernumber => $patron2->borrowernumber } }); |
| 1592 |
warning_like { $patron2->anonymize } qr/still has issues/, 'Skip patron with issues'; |
| 1593 |
$issue->delete; |
| 1594 |
|
| 1595 |
t::lib::Mocks::mock_preference( 'BorrowerMandatoryField', 'surname|email|cardnumber' ); |
| 1596 |
my $surname = $patron1->surname; # expect change, no clear |
| 1597 |
my $branchcode = $patron1->branchcode; # expect skip |
| 1598 |
$patron1->anonymize; |
| 1599 |
is($patron1->flgAnonymized, 1, 'Check flag' ); |
| 1600 |
|
| 1601 |
is( $patron1->dateofbirth, undef, 'Birth date cleared' ); |
| 1602 |
is( $patron1->firstname, undef, 'First name cleared' ); |
| 1603 |
isnt( $patron1->surname, $surname, 'Surname changed' ); |
| 1604 |
ok( $patron1->surname =~ /^\w{10}$/, 'Mandatory surname randomized' ); |
| 1605 |
is( $patron1->branchcode, $branchcode, 'Branch code skipped' ); |
| 1606 |
|
| 1607 |
# Test wrapper in Koha::Patrons |
| 1608 |
$patron1->surname($surname)->store; # restore |
| 1609 |
my $rs = Koha::Patrons->search({ borrowernumber => [ $patron1->borrowernumber, $patron2->borrowernumber ] })->anonymize; |
| 1610 |
$patron1->discard_changes; # refresh |
| 1611 |
isnt( $patron1->surname, $surname, 'Surname patron1 changed again' ); |
| 1612 |
$patron2->discard_changes; # refresh |
| 1613 |
is( $patron2->firstname, undef, 'First name patron2 cleared' ); |
| 1614 |
}; |
| 1615 |
|
| 1456 |
$schema->storage->txn_rollback; |
1616 |
$schema->storage->txn_rollback; |
| 1457 |
|
1617 |
|
| 1458 |
subtest 'Test Koha::Patrons::merge' => sub { |
1618 |
subtest 'Test Koha::Patrons::merge' => sub { |
| 1459 |
- |
|
|