a82ebfb0a9
Verify beginnings of implementation
1342 lines
58 KiB
Perl
1342 lines
58 KiB
Perl
# Supporters.t -*- Perl -*-
|
|
# Basic unit tests for Supporters.pm
|
|
#
|
|
# License: AGPLv3-or-later
|
|
# Copyright info in COPYRIGHT.md, License details in LICENSE.md with this package.
|
|
###############################################################################
|
|
# FIXME: Untested things: request holds, and fulfill failure
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Test::More tests => 353;
|
|
use Test::Exception;
|
|
use Sub::Override;
|
|
use File::Temp qw/tempfile/;
|
|
|
|
use Scalar::Util qw(looks_like_number reftype);
|
|
use POSIX qw(strftime);
|
|
|
|
# Yes, this may cause tests to fail if you run them near midnight. :)
|
|
my $today = strftime "%Y-%m-%d", gmtime;
|
|
|
|
=pod
|
|
|
|
Supporters.t is the basic unit tests for Supporters.pm. It tests the
|
|
following things:
|
|
|
|
=over
|
|
|
|
=item use command for the module.
|
|
|
|
=cut
|
|
|
|
BEGIN { use_ok('Supporters') };
|
|
|
|
|
|
require 't/CreateTestDB.pl';
|
|
|
|
my $dbh = get_test_dbh();
|
|
|
|
# Set up test data for ledger-related tests
|
|
|
|
my($fakeLedgerFH, $fakeLedgerFile) = tempfile("fakeledgerXXXXXXXX", UNLINK => 1);
|
|
|
|
print $fakeLedgerFH <<FAKE_LEDGER_TEST_DATA_END;
|
|
Supporters:Annual 2015-05-04 Whitman-Dick \$-5.00
|
|
Supporters:Monthly 2015-05-25 Olson-Margaret \$-10.00
|
|
Supporters:Monthly 2015-01-15 Olson-Margaret \$-10.00
|
|
Supporters:Monthly 2015-03-17 Olson-Margaret \$-10.00
|
|
Supporters:Annual 2015-12-04 Harris-Joan \$-120.00
|
|
Supporters:Monthly 2015-04-20 Olson-Margaret \$-10.00
|
|
Supporters:Match Pledge 2015-02-26 Whitman-Dick \$-300.00
|
|
Supporters:Monthly 2015-02-16 Olson-Margaret \$-10.00
|
|
Supporters:Monthly 2015-06-30 Olson-Margaret \$-10.00
|
|
Supporters:Annual 2015-03-04 Harris-Joan \$-120.00
|
|
Supporters:Annual 2016-01-10 \$-120.00
|
|
FAKE_LEDGER_TEST_DATA_END
|
|
|
|
=item Public-facing methods of the module, as follows:
|
|
|
|
=over
|
|
|
|
=item new
|
|
|
|
=cut
|
|
|
|
my $sp;
|
|
|
|
dies_ok { $sp = new Supporters(undef, "test"); }
|
|
"new: dies when dbh is undefined.";
|
|
dies_ok { $sp = new Supporters(bless({}, "Not::A::Real::Module"), "test"); }
|
|
"new: dies when dbh is blessed into another module.";
|
|
|
|
dies_ok { $sp = new Supporters($dbh, "testcmd"); }
|
|
"new: dies when if the command is a string.";
|
|
|
|
dies_ok { $sp = new Supporters($dbh, [ "testcmd" ], {}); }
|
|
"new: dies when programTypeSearch is an empty hash.";
|
|
|
|
dies_ok { $sp = new Supporters($dbh, [ "testcmd" ], {monthly => 'test', annual => 'test', dummy => 'test' }); }
|
|
"new: dies when programTypeSearch has stray value.";
|
|
|
|
dies_ok { $sp = new Supporters($dbh, [ "testcmd" ], {monthly => 'test' }); }
|
|
"new: dies when programTypeSearch key annual is missing .";
|
|
|
|
dies_ok { $sp = new Supporters($dbh, [ "testcmd" ], {annual => 'test' }); }
|
|
"new: dies when programTypeSearch key monthly is missing .";
|
|
|
|
my $cmd = [ "/bin/cat", $fakeLedgerFile ];
|
|
|
|
$sp = new Supporters($dbh, $cmd, { monthly => '^Supporters:Monthly',
|
|
annual => '^Supporters:(?:Annual|Match Pledge)'});
|
|
|
|
is($dbh, $sp->dbh(), "new: verify dbh set");
|
|
is_deeply($sp->ledgerCmd(), $cmd, "new: verify ledgerCmd set");
|
|
|
|
=item addSupporter
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->addSupporter({}) }
|
|
"addSupporter: ledger_entity_id required";
|
|
|
|
my $campbellId;
|
|
lives_ok { $campbellId = $sp->addSupporter({ ledger_entity_id => "Campbell-Peter" }); }
|
|
"addSupporter: add works for minimal acceptable settings";
|
|
|
|
ok( (looks_like_number($campbellId) and $campbellId > 0),
|
|
"addSupporter: add works for minimal acceptable settings");
|
|
|
|
dies_ok { $sp->addSupporter({ public_ack => 1, ledger_entity_id => "Whitman-Dick" }) }
|
|
"addSupporter: display_name required";
|
|
|
|
my $drapperId;
|
|
lives_ok { $drapperId = $sp->addSupporter({ display_name => "Donald Drapper",
|
|
public_ack => 1, ledger_entity_id => "Whitman-Dick" }); }
|
|
"addSupporter: public_ack set to true with a display_name given";
|
|
|
|
ok( (looks_like_number($drapperId) and $drapperId > $campbellId),
|
|
"addSupporter: add works with public_ack set to true and a display_name given");
|
|
|
|
my $olsonId;
|
|
|
|
lives_ok { $olsonId = $sp->addSupporter({ display_name => "Peggy Olson",
|
|
public_ack => 0, ledger_entity_id => "Olson-Margaret",
|
|
email_address => 'olson@example.net',
|
|
email_address_type => 'home' }); }
|
|
"addSupporter: succeeds with email address";
|
|
|
|
ok( (looks_like_number($olsonId) and $olsonId > $drapperId),
|
|
"addSupporter: add succeeded with email address added.");
|
|
|
|
my $val = $sp->dbh()->selectall_hashref("SELECT donor_id, email_address_id " .
|
|
"FROM donor_email_address_mapping " .
|
|
"WHERE donor_id = " . $sp->dbh->quote($olsonId, 'SQL_INTEGER'),
|
|
'donor_id');
|
|
|
|
ok((defined $val and defined $val->{$olsonId}{email_address_id} and $val->{$olsonId}{email_address_id} > 0),
|
|
"addSupporter: email address mapping is created on addSupporter() w/ email address included");
|
|
|
|
my $olsonFirstEmailId = $val->{$olsonId}{email_address_id};
|
|
|
|
my $sterlingId;
|
|
lives_ok { $sterlingId = $sp->addSupporter({ display_name => "Roger Sterling",
|
|
ledger_entity_id => "Sterling-Roger",
|
|
email_address => 'sterlingjr@example.com',
|
|
email_address_type => 'home' }) }
|
|
"addSupporter: succeeds with no public_ack setting specified...";
|
|
|
|
ok( (looks_like_number($sterlingId) and $sterlingId > $olsonId),
|
|
"addSupporter: ... and return value is sane.");
|
|
|
|
my $harrisId;
|
|
|
|
lives_ok { $harrisId = $sp->addSupporter({ ledger_entity_id => 'Harris-Joan' }) }
|
|
"addSupporter: set up one more in db (use this one for future test types on addSupporter)...";
|
|
ok( (looks_like_number($harrisId) and $harrisId > $sterlingId),
|
|
"addSupporter: ... and return value is sane.");
|
|
|
|
|
|
=item getPublicAck
|
|
|
|
=cut
|
|
|
|
my $publicAckVal;
|
|
|
|
dies_ok { $publicAckVal = $sp->getPublicAck(0); }
|
|
"getPublicAck: fails supporterId invalid";
|
|
dies_ok { $publicAckVal = $sp->getPublicAck("String"); }
|
|
"getPublicAck: fails supporterId is string";
|
|
dies_ok { $publicAckVal = $sp->getPublicAck(undef); }
|
|
"getPublicAck: fails supporterId is undef";
|
|
|
|
# Replace _verifyId() to always return true
|
|
|
|
my $overrideSub = Sub::Override->new( 'Supporters::_verifyId' => sub ($$) { return 1;} );
|
|
dies_ok { my $ledgerId = $sp->getPublicAck(0); }
|
|
"getPublicAck: fails when rows are not returned but _verifyId() somehow passed";
|
|
$overrideSub->restore;
|
|
|
|
lives_ok { $publicAckVal = $sp->getPublicAck($olsonId); }
|
|
"getPublicAck: lives when valid id is given for someone who does not want it...";
|
|
|
|
is($publicAckVal, 0, "getPublicAck: ...and return value is correct.");
|
|
|
|
lives_ok { $publicAckVal = $sp->getPublicAck($drapperId); }
|
|
"getPublicAck: lives when valid id is given for someone who wants it...";
|
|
|
|
is($publicAckVal, 1, "getPublicAck: ...and return value is correct.");
|
|
|
|
lives_ok { $publicAckVal = $sp->getPublicAck($sterlingId); }
|
|
"getPublicAck: lives when valid id is given for someone who is undecided...";
|
|
|
|
is($publicAckVal, undef, "getPublicAck: ...and return value is correct.");
|
|
|
|
|
|
=item isSupporter
|
|
|
|
=cut
|
|
|
|
my $isSupporter;
|
|
|
|
dies_ok { $isSupporter = $sp->isSupporter(0); }
|
|
"isSupporter: fails when rows are not returned but _verifyId() somehow passed";
|
|
|
|
# Replace _verifyId() to always return true
|
|
|
|
$overrideSub = Sub::Override->new( 'Supporters::_verifyId' => sub ($$) { return 1;} );
|
|
dies_ok { my $ledgerId = $sp->isSupporter(0); }
|
|
"isSupporter: fails when rows are not returned but _verifyId() somehow passed";
|
|
$overrideSub->restore;
|
|
|
|
lives_ok { $isSupporter = $sp->isSupporter($olsonId); }
|
|
"isSupporter: lives when valid id...";
|
|
|
|
is($isSupporter, 1, "isSupporter: ...and return value is correct.");
|
|
|
|
=item getDisplayName
|
|
|
|
=cut
|
|
|
|
my $displayNameVal;
|
|
|
|
dies_ok { $displayNameVal = $sp->getDisplayName(0); }
|
|
"getDisplayName: fails when rows are not returned but _verifyId() somehow passed";
|
|
|
|
# Replace _verifyId() to always return true
|
|
|
|
$overrideSub = Sub::Override->new( 'Supporters::_verifyId' => sub ($$) { return 1;} );
|
|
dies_ok { $displayNameVal = $sp->getDisplayName(0); }
|
|
"getDisplayName: fails when rows are not returned but _verifyId() somehow passed";
|
|
$overrideSub->restore;
|
|
|
|
lives_ok { $displayNameVal = $sp->getDisplayName($olsonId); }
|
|
"getDisplayName: lives when valid id is given for someone who does not want it...";
|
|
|
|
is($displayNameVal, "Peggy Olson", "getDisplayName: ...and return value is correct.");
|
|
|
|
lives_ok { $displayNameVal = $sp->getDisplayName($drapperId); }
|
|
"getDisplayName: lives when valid id is given for someone who wants it...";
|
|
|
|
is($displayNameVal, "Donald Drapper", "getDisplayName: ...and return value is correct.");
|
|
|
|
lives_ok { $displayNameVal = $sp->getDisplayName($campbellId); }
|
|
"getDisplayName: lives when valid id is given for someone who is undecided...";
|
|
|
|
is($displayNameVal, undef, "getDisplayName: ...and return value is correct.");
|
|
|
|
|
|
=item getLedgerEntityId
|
|
|
|
=cut
|
|
|
|
dies_ok { my $ledgerId = $sp->getLedgerEntityId(0); }
|
|
"getLedgerEntityId: fails when rows are not returned but _verifyId() somehow passed";
|
|
|
|
# Replace _verifyId() to always return true
|
|
|
|
$overrideSub = Sub::Override->new( 'Supporters::_verifyId' => sub ($$) { return 1;} );
|
|
dies_ok { my $ledgerId = $sp->getLedgerEntityId(0); }
|
|
"getLedgerEntityId: fails when rows are not returned but _verifyId() somehow passed";
|
|
$overrideSub->restore;
|
|
|
|
my $olsonLedgerEntity;
|
|
lives_ok { $olsonLedgerEntity = $sp->getLedgerEntityId($olsonId); }
|
|
"getLedgerEntityId: lives when valid id is given...";
|
|
|
|
is($olsonLedgerEntity, "Olson-Margaret", "getLedgerEntityId: ...and return value is correct.");
|
|
|
|
=item setPublicAck
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->setPublicAck(0); } "setPublicAck: fails supporterId invalid";
|
|
dies_ok { $sp->setPublicAck("String"); } "setPublicAck: fails supporterId is string";
|
|
dies_ok { $sp->setPublicAck(undef); } "setPublicAck: fails supporterId is undef";
|
|
|
|
is($sp->getPublicAck($olsonId), 0, "setPublicAck: 1 failed calls changed nothing.");
|
|
is($sp->getPublicAck($drapperId), 1, "setPublicAck: 1 failed calls changed nothing.");
|
|
is($sp->getPublicAck($sterlingId), undef, "setPublicAck: 1 failed calls changed nothing.");
|
|
|
|
lives_ok { $sp->setPublicAck($olsonId, undef); }
|
|
"setPublicAck: lives when valid id is given for undefining...";
|
|
is($sp->getPublicAck($olsonId), undef, "setPublicAck: ...and suceeds in changing value.");
|
|
|
|
lives_ok { $sp->setPublicAck($drapperId, 0); }
|
|
"setPublicAck: lives when valid id is given for off...";
|
|
is($sp->getPublicAck($drapperId), 0, "setPublicAck: ...and suceeds in changing value.");
|
|
|
|
lives_ok { $sp->setPublicAck($sterlingId, 1); }
|
|
"setPublicAck: lives when valid id is given for on...";
|
|
is($sp->getPublicAck($sterlingId), 1, "setPublicAck: ...and suceeds in changing value.");
|
|
|
|
=item addEmailAddress
|
|
|
|
=cut
|
|
|
|
$val = $sp->dbh()->selectall_hashref("SELECT id, name FROM address_type WHERE name = 'home'", 'name');
|
|
|
|
ok((defined $val and defined $val->{home}{id} and $val->{home}{id} > 0),
|
|
"addSupporter/addEmailAddress: emailAddressType was added when new one given to addSupporter");
|
|
|
|
my $emailAddressTypeHomeId = $val->{home}{id};
|
|
|
|
dies_ok { $sp->addEmailAddress(undef, 'drapper@example.org', 'paypal'); }
|
|
"addEmailAddress: dies for undefined id";
|
|
dies_ok { $sp->addEmailAddress("String", 'drapper@example.org', 'paypal'); }
|
|
"addEmailAddress: dies for non-numeric id";
|
|
dies_ok { $sp->addEmailAddress($drapperId, undef, 'work') }
|
|
"addEmailAddress: email address undefined fails";
|
|
dies_ok { $sp->addEmailAddress($drapperId, 'drapper@ex@ample.org', 'work') }
|
|
"addEmailAddress: email address with extra @ fails to add.";
|
|
|
|
# Verify that the addressType wasn't added when the Email address is invalid
|
|
# and the address type did not already exist.
|
|
|
|
$val = $sp->dbh()->selectall_hashref("SELECT id, name FROM address_type WHERE name = 'work'", 'name');
|
|
|
|
ok((not defined $val or not defined $val->{'name'}),
|
|
"addEmailAddress: type is not added with email address is bad");
|
|
|
|
my $sameOlsonId;
|
|
dies_ok { $sameOlsonId = $sp->addEmailAddress($olsonId, 'olson@example.net', 'paypal') }
|
|
"addEmailAddress: fails adding existing email address with mismatched type.";
|
|
|
|
lives_ok { $sameOlsonId = $sp->addEmailAddress($olsonId, 'olson@example.net', 'home') }
|
|
"addEmailAddress: succeeds when adding email that already exists...";
|
|
|
|
is($sameOlsonId, $olsonFirstEmailId, "addEmailAddress: ... and returns same id.");
|
|
|
|
my $drapperEmailId;
|
|
|
|
lives_ok { $drapperEmailId = $sp->addEmailAddress($drapperId, 'drapper@example.org', 'work') }
|
|
"addEmailAddress: inserting a valid email address works";
|
|
ok((looks_like_number($drapperEmailId) and $drapperEmailId > 0), "addEmailAddress: id returned is sane.");
|
|
|
|
my $olsonEmailId2;
|
|
|
|
dies_ok { $olsonEmailId2 = $sp->addEmailAddress($olsonId, 'drapper@example.org', 'paypal') }
|
|
"addEmailAddress: fails when adding the same email address for someone else, but as a different type";
|
|
|
|
my $drapperEmailId2;
|
|
lives_ok { $drapperEmailId2 = $sp->addEmailAddress($drapperId, 'everyone@example.net', 'paypal') }
|
|
"addEmailAddress: inserting a second valid email address works";
|
|
ok((looks_like_number($drapperEmailId2) and $drapperEmailId2 > 0 and $drapperEmailId != $drapperEmailId2),
|
|
"addEmailAddress: id returned is sane and is not same as previous id.");
|
|
|
|
lives_ok { $olsonEmailId2 = $sp->addEmailAddress($olsonId, 'everyone@example.net', 'paypal') }
|
|
"addEmailAddress: binding known email address to another person works...";
|
|
ok((looks_like_number($olsonEmailId2) and $olsonEmailId2 > 0 and $olsonEmailId2 == $drapperEmailId2),
|
|
"addEmailAddress: ... and id returned is sane and is same.");
|
|
|
|
=item addAddressType
|
|
|
|
=cut
|
|
|
|
# This test cheats a bit -- it assumes that the database is assigning serials starting with 1
|
|
|
|
ok($sp->addAddressType('work') > $emailAddressTypeHomeId,
|
|
"addEmailAddress: verify addEmailAddress added the addressType underneath");
|
|
|
|
dies_ok { $sp->addAddressType(undef); } "addAddressType: dies for undef";
|
|
|
|
my $paypalPayerAddressType;
|
|
|
|
ok($paypalPayerAddressType = $sp->addAddressType("paypal payer"), "addAddressType: basic add works");
|
|
|
|
my $same;
|
|
|
|
ok($same = $sp->addAddressType("paypal payer"), "addAddressType: lookup works");
|
|
|
|
ok($same == $paypalPayerAddressType, "addAddressType: lookup returns same as the basic add");
|
|
|
|
=item addEmailError
|
|
|
|
=cut
|
|
|
|
# Add an "undeliverable" delivery_error type
|
|
|
|
$val = 1;
|
|
lives_ok { $val = $sp->_lookupDeliveryError("undeliverable"); },
|
|
"_lookupDeliveryError: succeeds for unknown error ...";
|
|
|
|
is($val, undef, "_lookupDeliveryError: ... but returns undef");
|
|
|
|
my $sth = $sp->dbh->prepare("INSERT INTO delivery_error(error) VALUES(?)"); $sth->execute("undeliverable"); $sth->finish;
|
|
my $undeliverableId = $sp->dbh->last_insert_id("","","delivery_error","");
|
|
|
|
$val = -1;
|
|
lives_ok { $val = $sp->_lookupDeliveryError("undeliverable"); },
|
|
"_lookupDeliveryError: succeeds for known error ...";
|
|
is($val, $undeliverable, "_lookupDeliveryError: ... and returns proper id number");
|
|
|
|
dies_ok { $sp->addEmailError(undef); }
|
|
"addEmailError: undef argument dies.";
|
|
|
|
dies_ok { $sp->addEmailError({}); } "addEmailError: dies if donorId not specified.";
|
|
|
|
dies_ok { $sp->addEmailError({emailAddress => undef}); } "addEmailError: dies if emailAddress is undef.";
|
|
|
|
$val = 1;
|
|
lives_ok { $val = $sp->addEmailError({emailAddress => 'nobody@example.com', errorCode => 'undeliverable', dateEncountered => '2017-11-22' }); }
|
|
"addEmailError: succeeds to run if emailAddress not in database with all other valid args....";
|
|
is($val, undef, "... but returns undef in that situation.");
|
|
|
|
dies_ok { $sp->addEmailError({emailAddress => 'everyone@example.net', errorCode => 'invalidErrorcode',
|
|
dateEncountered => '2017-11-22' }); }
|
|
"addEmailError: dies if errorCode given is invalid.";
|
|
|
|
$val = -1;
|
|
lives_ok { $val = $sp->addEmailError({emailAddress => 'everyone@example.net', errorCode => 'undeliverable', dateEncountered => '2017-11-22' }) }
|
|
"addEmailError: succeeds when all options are valid but comment is missing";
|
|
|
|
is($val > 0, "addEmailError: ... and returns a value greater than 0.");
|
|
|
|
$val = $sp->dbh()->selectrow_hashref("SELECT delivery_error_code_id, email_address_id, date_encountered, comments " .
|
|
"FROM email_error_log " .
|
|
"WHERE email_address_id = " . $sp->dbh->quote($olsonEmailId2, 'SQL_INTEGER'));
|
|
|
|
ok((defined $val and defined $val->{email_address_id} and $val->{date_encountered} eq '2017-11-22'
|
|
and not defined $val->{comments} and $val->{delivery_error_code_id} == $undeliverableId),
|
|
"addSuporter: error log entry created without comment");
|
|
|
|
$val = -1;
|
|
lives_ok {$val = $sp->addEmailError({emailAddress => 'drapper@example.org', errorCode => 'undeliverable', dateEncountered => '2017-11-25', comments => "seems he has no email address" }) }
|
|
"addEmailError: succeeds for valid email address and other options, including comment";
|
|
|
|
is($val > 0, "addEmailError: ... and returns > 0 in that situation.");
|
|
|
|
$val = $sp->dbh()->selectrow_hashref("SELECT delivery_error_code_id, email_address_id, date_encountered, comments " .
|
|
"FROM email_error_log " .
|
|
"WHERE email_address_id = " . $sp->dbh->quote($drapperEmailId, 'SQL_INTEGER'));
|
|
|
|
ok((defined $val and defined $val->{email_address_id} and $val->{date_encountered} eq '2017-11-25'
|
|
and $val->{comments} eq "seems he has no email address" and
|
|
$val->{delivery_error_code_id} == $undeliverableId),
|
|
"addSuporter: error log entry created with comment added");
|
|
|
|
=cut
|
|
|
|
=item addPostalAddress
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->addPostalAddress(undef, "405 Madison Avenue\nNew York, NY 10000\nUSA", 'office'); }
|
|
"addPostalAddress: dies for undefined id";
|
|
dies_ok { $sp->addPostalAddress("String", "405 Madison Avenue\nNew York, NY 10000\nUSA", 'office'); }
|
|
"addPostalAddress: dies for non-numeric id";
|
|
dies_ok { $sp->addPostalAddress($drapperId, undef, 'work') }
|
|
"addPostalAddress: postal address undefined fails";
|
|
|
|
# Verify that the addressType wasn't added when the Email address is invalid
|
|
# and the address type did not already exist.
|
|
|
|
$val = $sp->dbh()->selectall_hashref("SELECT id, name FROM address_type WHERE name = 'office'", 'name');
|
|
|
|
ok((not defined $val or not defined $val->{'name'}),
|
|
"addPostalAddress: type is not added when other input paramaters are invalid");
|
|
|
|
my $drapperPostalId;
|
|
|
|
lives_ok { $drapperPostalId = $sp->addPostalAddress($drapperId,
|
|
"405 Madison Avenue\nNew York, NY 10000\nUSA", 'office'); }
|
|
"addPostalAddress: addPostalAddress of a valid formatted_address works.";
|
|
ok((looks_like_number($drapperPostalId) and $drapperPostalId > 0), "addPostalAddress: id returned is sane.");
|
|
|
|
=item addRequestType/getRequestType
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->addRequestType(undef); }
|
|
"addRequestType: undef argument dies.";
|
|
|
|
my $tShirt0RequestTypeId;
|
|
|
|
ok( (not defined $sp->getRequestType('t-shirt-0')), "getRequestType: returns undef when not found");
|
|
|
|
lives_ok { $tShirt0RequestTypeId = $sp->addRequestType('t-shirt-0'); }
|
|
"addRequestType: succeeds on add";
|
|
|
|
ok( (defined $tShirt0RequestTypeId and looks_like_number($tShirt0RequestTypeId) and $tShirt0RequestTypeId > 0),
|
|
"addRequestType: id is a number");
|
|
|
|
my @allRequestsList = $sp->getRequestType();
|
|
|
|
is_deeply(\@allRequestsList, ['t-shirt-0' ], "getRequestType: no argument returns full list of request types (1)");
|
|
|
|
my $testSameRequestType;
|
|
|
|
lives_ok { $testSameRequestType = $sp->addRequestType('t-shirt-0'); }
|
|
"addRequestType: succeeds on add when type already exists";
|
|
|
|
is $tShirt0RequestTypeId, $testSameRequestType,
|
|
"addRequestType: lookup first of existing request type before adding.";
|
|
|
|
=item addRequestConfigurations
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->addRequestConfigurations(undef, undef); } "addRequestConfigurations: undef type dies";
|
|
|
|
is_deeply({ $tShirt0RequestTypeId => {} },
|
|
$sp->addRequestConfigurations('t-shirt-0'),
|
|
"addRequestConfigurations: existing requestType with no configuration yields same");
|
|
|
|
my @sizeList = qw/LadiesS LadiesM LadiesL LadiesXL MenS MenM MenL MenXL Men2XL/;
|
|
|
|
my $tShirt0Data;
|
|
|
|
dies_ok { $sp->addRequestConfigurations('t-shirt-1', [ @sizeList, 'Men2XL']) }
|
|
"addRequestConfigurations: dies with duplicate items on configuration list.";
|
|
|
|
is($sp->{__NESTED_TRANSACTION_COUNTER__}, 0, "addRequestConfigurations: assure proper beginWork/commit matching.");
|
|
|
|
is_deeply($sp->getRequestConfigurations('t-shirt-1'), undef,
|
|
"addRequestConfigurations/getRequestConfigurations: add fails with undefined configuration list");
|
|
|
|
lives_ok { $tShirt0Data = $sp->addRequestConfigurations('t-shirt-0', \@sizeList) }
|
|
"addRequestConfigurations: existing requestType with configuration runs.";
|
|
|
|
is( keys %{$tShirt0Data}, ($tShirt0RequestTypeId),
|
|
"addRequestConfigurations: reuses same requestTypeId on add of configurations");
|
|
|
|
is($sp->{__NESTED_TRANSACTION_COUNTER__}, 0, "addRequestConfigurations: assure proper beginWork/commit matching.");
|
|
|
|
my $cnt = 0;
|
|
foreach my $size (@sizeList) {
|
|
ok( (defined $tShirt0Data->{$tShirt0RequestTypeId}{$size} and
|
|
looks_like_number($tShirt0Data->{$tShirt0RequestTypeId}{$size}) and
|
|
$tShirt0Data->{$tShirt0RequestTypeId}{$size} > 0),
|
|
sprintf "addRequestConfigurations: item %d added correctly", $cnt++);
|
|
}
|
|
|
|
|
|
=item addRequest
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->addRequest({}); } "addRequest: dies if donorId not specified.";
|
|
|
|
dies_ok { $sp->addRequest({ donorId => $drapperId }); }
|
|
"addRequest: dies if requestTypeId / requestType not specified.";
|
|
|
|
dies_ok { $sp->addRequest({ donorId => 0, requestTypeId => $tShirt0RequestTypeId }); }
|
|
"addRequest: dies if donorId invalid.";
|
|
|
|
dies_ok { $sp->addRequest({ donorId => $drapperId, requestTypeId => 0 }); }
|
|
"addRequest: dies if requestTypeId invalid.";
|
|
|
|
is($sp->{__NESTED_TRANSACTION_COUNTER__}, 0, "addRequest: assure proper beginWork/commit matching.");
|
|
|
|
my $emailListRequestId;
|
|
|
|
lives_ok { $emailListRequestId =
|
|
$sp->addRequest({ donorId => $drapperId, requestType => "join-announce-email-list" }); }
|
|
"addRequest: succeeds with a requestType but no configuration parameter.";
|
|
|
|
ok( (defined $emailListRequestId and looks_like_number($emailListRequestId) and $emailListRequestId > 0),
|
|
"addRequest: id returned on successful addRequest() is a number");
|
|
|
|
my $joinEmailListRequestId = $sp->getRequestType("join-announce-email-list");
|
|
ok((defined $joinEmailListRequestId and looks_like_number($joinEmailListRequestId) and $joinEmailListRequestId > 0),
|
|
"addRequest: underlying call to addRequestType works properly, per getRequestType");
|
|
|
|
@allRequestsList = $sp->getRequestType();
|
|
|
|
is_deeply(\@allRequestsList, ['t-shirt-0', 'join-announce-email-list'],
|
|
"getRequestType: no argument returns full list of request types (2)");
|
|
|
|
my $tshirtSmallRequestId;
|
|
|
|
lives_ok { $tshirtSmallRequestId =
|
|
$sp->addRequest({ donorId => $drapperId, requestType => "t-shirt-small-only",
|
|
requestConfiguration => 'Small',
|
|
notes => 'he probably needs a larger size but this shirt has none'}); }
|
|
"addRequest: succeeds with a requestType and requestConfiguration and a note.";
|
|
|
|
ok( (defined $tshirtSmallRequestId and looks_like_number($tshirtSmallRequestId) and $tshirtSmallRequestId > 0),
|
|
"addRequest: successful call returns an integer id.");
|
|
|
|
@allRequestsList = $sp->getRequestType();
|
|
|
|
is_deeply(\@allRequestsList, ['t-shirt-0', 'join-announce-email-list', 't-shirt-small-only' ],
|
|
"getRequestType: no argument returns full list of request types (3)");
|
|
|
|
my $tShirt0RequestId;
|
|
|
|
lives_ok { $tShirt0RequestId =
|
|
$sp->addRequest({ donorId => $drapperId, requestTypeId => $tShirt0RequestTypeId,
|
|
requestConfigurationId => $tShirt0Data->{$tShirt0RequestTypeId}{'MenL'} }); }
|
|
"addRequest: succeeds with a requestTypeId and requestConfigurationId with no a note.";
|
|
|
|
ok( (defined $tShirt0RequestId and looks_like_number($tShirt0RequestId) and $tShirt0RequestId > 0),
|
|
"addRequest: another successful call returns an integer id.");
|
|
|
|
my $olsonTShirtRequest;
|
|
|
|
lives_ok { $olsonTShirtRequest =
|
|
$sp->addRequest({ donorId => $olsonId, requestTypeId => $tShirt0RequestTypeId,
|
|
requestConfigurationId => $tShirt0Data->{$tShirt0RequestTypeId}{'LadiesXL'} }); }
|
|
"addRequest: different donor succeeds with a requestTypeId and requestConfigurationId with no a note....";
|
|
|
|
ok( (defined $olsonTShirtRequest and looks_like_number($olsonTShirtRequest) and $olsonTShirtRequest > 0
|
|
and $olsonTShirtRequest != $tShirt0RequestTypeId and $olsonTShirtRequest != $tshirtSmallRequestId),
|
|
"addRequest: ... and successful call returns an integer id that's different from others.");
|
|
|
|
=item holdRequest
|
|
|
|
=cut
|
|
|
|
my $drapperTShirt0HoldId;
|
|
my $newHoldId;
|
|
|
|
dies_ok { $drapperTShirt0HoldId = $sp->holdRequest(requestType => "t-shirt-0", who => 'joe',
|
|
heldBecause => "will see him soon and give t-shirt in person" ); }
|
|
"holdRequest: dies if donorId not specified";
|
|
|
|
dies_ok { $drapperTShirt0HoldId = $sp->holdRequest(donorId => $drapperId + 1000,
|
|
requestType => "t-shirt-0", who => 'joe',
|
|
heldBecause => "will see him soon and give t-shirt in person"); }
|
|
"holdRequest: dies if donorId not found in database";
|
|
|
|
dies_ok { $drapperTShirt0HoldId = $sp->holdRequest(donorId => $drapperId, who => 'joe',
|
|
heldBecause => "in-person delivery" ); }
|
|
"holdRequest: dies if requestType not specified";
|
|
|
|
dies_ok { $drapperTShirt0HoldId = $sp->holdRequest( { donorId => $drapperId,
|
|
requestType => "t-shirt-0",
|
|
heldBecause => "in-person delivery" }); }
|
|
"holdRequest: dies if who not specified";
|
|
|
|
lives_ok { $drapperTShirt0HoldId = $sp->holdRequest( { donorId => $drapperId,
|
|
requestType => "t-shirt-0", who => 'joe', holdReleaseDate => '9999-12-31',
|
|
heldBecause => "in-person delivery planned" }); }
|
|
"holdRequest: succeeds for existing request...";
|
|
|
|
ok( (defined $drapperTShirt0HoldId and looks_like_number($drapperTShirt0HoldId) and $drapperTShirt0HoldId > 0),
|
|
"holdRequest: ... and id returned on successful holdRequest() is a number");
|
|
|
|
lives_ok { $val = $sp->dbh()->selectall_hashref("SELECT id, hold_date, release_date, who, request_id, why FROM request_hold", 'id'); }
|
|
"holdRequest: sql command in database for entry succeeds.";
|
|
is_deeply($val, { $drapperTShirt0HoldId => { id => $drapperTShirt0HoldId, hold_date => $today,
|
|
release_date => '9999-12-31',
|
|
why => 'in-person delivery planned', who => 'joe',
|
|
request_id => $tShirt0RequestId } },
|
|
"holdRequest: database entry from successful return is correct");
|
|
|
|
my $badHold;
|
|
lives_ok { $badHold = $sp->holdRequest( { donorId => $drapperId, who => 'john', holdReleaseDate => '1983-01-05',
|
|
requestType => "does-not-exist",
|
|
heldBecause => "in-person delivery" }); }
|
|
"holdRequest: attempt to hold a request never made does not die...";
|
|
|
|
ok( (not defined $badHold),
|
|
"holdRequest: ... but, rather, returns undef.");
|
|
|
|
is($sp->getRequestType("does-not-exist"), undef,
|
|
"holdRequest: requestType not created when holdRequest fails.");
|
|
|
|
my $reHoldId;
|
|
|
|
# FIXME: Do the following two tests really exhibit the behavior we actually
|
|
# want? The API caller might be receiving unexpected results here,
|
|
# because as the two tests below show, it's possible, when attempting
|
|
# to hold a request that is already held, that you're returned an id
|
|
# for a hold that has different details (other than the requestType,
|
|
# of course).
|
|
|
|
|
|
lives_ok { $reHoldId = $sp->holdRequest( { donorId => $drapperId, holdReleaseDate => '2112-05-15',
|
|
requestType => "t-shirt-0", who => 'peggy',
|
|
heldBecause => "will leave in his office." }); }
|
|
"holdRequest: attempt to hold an already-held request lives ...";
|
|
|
|
is_deeply($reHoldId, $drapperTShirt0HoldId, "holdRequest: ... but returns the id of the old hold request.");
|
|
my $holdRequest;
|
|
|
|
lives_ok { $newHoldId = $sp->holdRequest( { donorId => $olsonId, holdReleaseDate => '2048-05-15',
|
|
requestTypeId => $tShirt0RequestTypeId, who => 'john',
|
|
heldBecause => "will delivery at conference" }); }
|
|
"holdRequest: succeeds for existing request, using requestTypeId";
|
|
|
|
ok( (defined $newHoldId and looks_like_number($newHoldId) and $newHoldId > 0 and ($newHoldId != $drapperTShirt0HoldId)),
|
|
"holdRequest: id returned on successful holdRequest() is a number and is not the one returned by previous");
|
|
|
|
|
|
=item fulfillRequest
|
|
|
|
=cut
|
|
|
|
|
|
my $fulfillRequestId;
|
|
|
|
|
|
dies_ok { $fulfillRequestId = $sp->fulfillRequest( { requestType => "t-shirt-small-only", who => 'joe',
|
|
how => "in-person delivery" }); }
|
|
"fulfillRequest: dies if donorId not specified";
|
|
|
|
dies_ok { $fulfillRequestId = $sp->fulfillRequest( { donorId => $drapperId + 1000,
|
|
requestType => "t-shirt-small-only", who => 'joe',
|
|
how => "in-person delivery" }); }
|
|
"fulfillRequest: dies if donorId not found in database";
|
|
|
|
dies_ok { $fulfillRequestId = $sp->fulfillRequest( { donorId => $drapperId, who => 'joe',
|
|
how => "in-person delivery" }); }
|
|
"fulfillRequest: dies if requestType not specified";
|
|
|
|
dies_ok { $fulfillRequestId = $sp->fulfillRequest( { donorId => $drapperId,
|
|
requestType => "t-shirt-small-only",
|
|
how => "in-person delivery" }); }
|
|
"fulfillRequest: dies if who not specified";
|
|
|
|
my $req;
|
|
lives_ok { $req = $sp->getRequest({donorId => $drapperId, requestType => "t-shirt-small-only" }); }
|
|
"getRequest: success after failed fulfillRequest attempts...";
|
|
|
|
is($req->{requestType}, "t-shirt-small-only", "getRequest: ... with correct type");
|
|
is($req->{requestDate}, $today, "getRequest: ... and correct request date.");
|
|
is($req->{fulfillDate}, undef, "getRequest: ... but no fulfillDate.");
|
|
|
|
lives_ok { $fulfillRequestId = $sp->fulfillRequest( { donorId => $drapperId,
|
|
requestType => "t-shirt-small-only", who => 'joe',
|
|
how => "in-person delivery" }); }
|
|
"fulfillRequest: succeeds for existing request";
|
|
|
|
ok( (defined $fulfillRequestId and looks_like_number($fulfillRequestId) and $fulfillRequestId > 0),
|
|
"fulfillRequest: id returned on successful fulfillRequest() is a number");
|
|
|
|
lives_ok { $val = $sp->dbh()->selectall_hashref("SELECT id, date, who, how, request_id FROM fulfillment", 'id'); }
|
|
"fulfillRequest: sql command in database for entry succeeds.";
|
|
is_deeply($val, { $fulfillRequestId => { id => $fulfillRequestId, date => $today,
|
|
how => 'in-person delivery', who => 'joe',
|
|
request_id => $tshirtSmallRequestId } },
|
|
"fulfillRequest: databse entry from successful return is correct");
|
|
|
|
my $badFR;
|
|
lives_ok { $badFR = $sp->fulfillRequest( { donorId => $drapperId, who => 'john',
|
|
requestType => "does-not-exist",
|
|
how => "in-person delivery" }); }
|
|
"fulfillRequest: attempt to fulfill a request never made does not die...";
|
|
|
|
ok( (not defined $badFR),
|
|
"fulfillRequest: ... but, rather, returns undef.");
|
|
|
|
is($sp->getRequestType("does-not-exist"), undef,
|
|
"fulfillRequest: requestType not created when fulfillRequest fails.");
|
|
|
|
|
|
my $lookedUpFulfillmentId;
|
|
|
|
lives_ok { $lookedUpFulfillmentId = $sp->fulfillRequest( { donorId => $drapperId,
|
|
requestType => "t-shirt-small-only", who => 'peggy',
|
|
how => "left in his office." }); }
|
|
"fulfillRequest: attempt to fulfill an already-fulfill request does not die ...";
|
|
|
|
is($lookedUpFulfillmentId, $fulfillRequestId,
|
|
"fulfillRequest: ... but, rather, returns the same value from the previous fulfillRequest() call.");
|
|
|
|
|
|
my $newFRID;
|
|
lives_ok { $newFRID = $sp->fulfillRequest( { donorId => $drapperId,
|
|
requestTypeId => $tShirt0RequestTypeId, who => 'john',
|
|
how => "mailed" }); }
|
|
"fulfillRequest: returns properly for an existing request, using requestTypeId for lookup, when the request his held...";
|
|
|
|
is($newFRID, undef, "fulfillRequest: .... but undef is returned when attempting to fulfill a held request.");
|
|
|
|
=item getRequest
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->getRequest({} ); } "getRequest: dies if donorId not specified.";
|
|
|
|
dies_ok { $sp->getRequest({ donorId => 0, requestType => "t-shirt-small-only" }); } "getRequest: dies if donorId invalid.";
|
|
|
|
dies_ok { $sp->getRequest({ donorId => $drapperId, requestType => undef}); }
|
|
"getRequest: dies if requestType not specified.";
|
|
|
|
my $tt;
|
|
lives_ok { $tt = $sp->getRequest({ donorId => $drapperId, requestType => 'this-one-is-not-there' }); }
|
|
"getRequest: returns normally with non-existent request.";
|
|
|
|
is($tt, undef, "getRequest: returns undef for valid supporter and on-existent request.");
|
|
|
|
lives_ok { $tt = $sp->getRequest({donorId => $drapperId, requestType => 't-shirt-small-only' }); }
|
|
"getRequest: succeeds with valid parameters, using requestType.";
|
|
|
|
is($tt->{requestType}, 't-shirt-small-only', "getRequest: requestType is correct.");
|
|
is($tt->{fulfillDate}, $today, "getRequest: fulfilled request is today.");
|
|
is($tt->{requestDate}, $today, "getRequest: request date is today.");
|
|
is($tt->{requestConfiguration}, 'Small', "getRequest: configuration is correct.");
|
|
is($tt->{notes}, 'he probably needs a larger size but this shirt has none',
|
|
"getRequest: notes are correct.");
|
|
|
|
lives_ok { $tt = $sp->getRequest({donorId => $drapperId, requestType => 't-shirt-small-only', ignoreFulfilledRequests => 1}); }
|
|
"getRequest: succeeds for lookup criteria that are known to return nothing ....";
|
|
|
|
is($tt, undef, 'getRequest: .... and undef is indeed returned');
|
|
|
|
lives_ok { $tt = $sp->getRequest({donorId => $drapperId, requestTypeId => $tShirt0RequestTypeId } ); }
|
|
"getRequest: succeeds with valid parameters, using requestTypeId.";
|
|
|
|
is($tt->{requestType}, 't-shirt-0', "getRequest: requestType is correct.");
|
|
is($tt->{requestDate}, $today, "getRequest: request date is today.");
|
|
is($tt->{requestConfiguration}, 'MenL', "getRequest: configuration is correct.");
|
|
is($tt->{holdReleaseDate}, '9999-12-31', "getRequest: releaseDate is correct.");
|
|
is($tt->{holdDate}, $today, "getRequest: holdDate is correct.");
|
|
is($tt->{holder}, 'joe', "getRequest: holder is correct.");
|
|
is($tt->{heldBecause}, 'in-person delivery planned', "getRequest: heldBecause is correct.");
|
|
is($tt->{notes}, undef, "getRequest: notes are undef when null in database.");
|
|
|
|
lives_ok { $tt = $sp->getRequest({donorId => $drapperId, requestTypeId => $tShirt0RequestTypeId,
|
|
ignoreHeldRequests => 1}); }
|
|
"getRequest: succeeds for lookup criteria, including ignoreHeldRequests, that are known to return nothing ....";
|
|
is($tt, undef, 'getRequest: .... and undef is indeed returned');
|
|
|
|
|
|
lives_ok { $tt = $sp->getRequest({ donorId => $drapperId, requestType => "join-announce-email-list" }); }
|
|
"getRequest: succeeds with valid parameters.";
|
|
|
|
is($tt->{requestType}, "join-announce-email-list", "getRequest: requestType is correct.");
|
|
is($tt->{requestDate}, $today, "getRequest: request date is today.");
|
|
is($tt->{requestConfiguration}, undef, "getRequest: configuration is undefined when there is none.");
|
|
is($tt->{notes}, undef, "getRequest: notes are undef when null in database.");
|
|
|
|
|
|
=item releaseRequestHold
|
|
|
|
=cut
|
|
|
|
my $releasedHoldId;
|
|
|
|
lives_ok { $releasedHoldId = $sp->releaseRequestHold({ donorId => $drapperId, requestType => 't-shirt-0' }); }
|
|
"releaseRequestHold: release of a known held request succeeds...";
|
|
is($releasedHoldId, $drapperTShirt0HoldId, "releaseRequestHold: ... & returns same hold id as holdRequest() call did");
|
|
lives_ok { $req = $sp->getRequest({ donorId => $drapperId, requestType => 't-shirt-0'}) }
|
|
"releaseRequestHold: lookup of request after release succeeds....";
|
|
is($req->{holdReleaseDate}, $today, "... and the release date is today.");
|
|
|
|
lives_ok { $releasedHoldId = $sp->releaseRequestHold({ donorId => $drapperId, requestType => 't-shirt-0' }); }
|
|
"releaseRequestHold: release again of the same a hold request also succeeds...";
|
|
is($releasedHoldId, $drapperTShirt0HoldId, "releaseRequestHold: ... & also returns same hold id as holdRequest() call did");
|
|
lives_ok { $req = $sp->getRequest({ donorId => $drapperId, requestType => 't-shirt-0'}) }
|
|
"releaseRequestHold: lookup of request after second release succeeds....";
|
|
is($req->{holdReleaseDate}, $today, "... and the release date is still set to today.");
|
|
|
|
|
|
lives_ok { $newFRID = $sp->fulfillRequest( { donorId => $drapperId,
|
|
requestTypeId => $tShirt0RequestTypeId, who => 'john',
|
|
how => "mailed" }); }
|
|
"fulfillRequest: succeeds once the request is no longer on hold...";
|
|
|
|
ok( (defined $newFRID and looks_like_number($newFRID) and $newFRID > 0 and ($newFRID != $fulfillRequestId)),
|
|
"....id returned on successful fulfillRequest() is a number and is not the one returned by previous");
|
|
|
|
lives_ok { $tt = $sp->getRequest({donorId => $drapperId, requestTypeId => $tShirt0RequestTypeId } ); }
|
|
"getRequest: succeeds with valid parameters, using requestTypeId.";
|
|
|
|
is($tt->{requestType}, 't-shirt-0', "getRequest: requestType is correct.");
|
|
is($tt->{requestDate}, $today, "getRequest: request date is today.");
|
|
is($tt->{requestConfiguration}, 'MenL', "getRequest: configuration is correct.");
|
|
is($tt->{holdReleaseDate}, $today, "getRequest: holdReleaseDate is correct.");
|
|
is($tt->{holdDate}, $today, "getRequest: holdDate is correct.");
|
|
is($tt->{holder}, 'joe', "getRequest: holder is correct.");
|
|
is($tt->{heldBecause}, 'in-person delivery planned', "getRequest: heldBecause is correct.");
|
|
is($tt->{fulfillDate}, $today, "getRequest: fulfilled request is today.");
|
|
is($tt->{notes}, undef, "getRequest: notes are undef when null in database.");
|
|
|
|
=item getRequestConfigurations
|
|
|
|
=cut
|
|
|
|
my $tShirtSmallOnlyRequestId;
|
|
lives_ok { $tShirtSmallOnlyRequestId = $sp->getRequestType('t-shirt-small-only'); }
|
|
"addRequest: added request type";
|
|
|
|
my $tShirtSmallOnlyData = $sp->getRequestConfigurations('t-shirt-small-only');
|
|
|
|
is(scalar keys %{$tShirtSmallOnlyData->{$tShirtSmallOnlyRequestId}}, 1,
|
|
"addRequest: just one configuration added correctly");
|
|
|
|
ok( (defined $tShirtSmallOnlyData->{$tShirtSmallOnlyRequestId}{'Small'} and
|
|
looks_like_number($tShirtSmallOnlyData->{$tShirtSmallOnlyRequestId}{'Small'}) and
|
|
$tShirtSmallOnlyData->{$tShirtSmallOnlyRequestId}{'Small'} > 0),
|
|
"addRequest: configuration added correctly");
|
|
|
|
is undef, $sp->getRequestConfigurations(undef), "getRequestConfigurations: undef type returns undef";
|
|
|
|
is undef, $sp->getRequestConfigurations('Hae2Ohlu'), "getRequestConfigurations: non-existent type returns undef";
|
|
|
|
is_deeply $tShirt0Data,
|
|
$sp->getRequestConfigurations('t-shirt-0'),
|
|
"getRequestConfigurations: lookup of previously added items is same";
|
|
|
|
|
|
=item setPreferredEmailAddress/getPreferredEmailAddress
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->setPreferredEmailAddress(undef, 'drapper@example.org'); }
|
|
"setPreferredEmailAddress: dies for undefined id";
|
|
dies_ok { $sp->setPreferredEmailAddress("String", 'drapper@example.org'); }
|
|
"setPreferredEmailAddress: dies for non-numeric id";
|
|
dies_ok { $sp->setPreferredEmailAddress($drapperId, undef) }
|
|
"setPreferredEmailAddress: email address undefined fails";
|
|
dies_ok { $sp->setPreferredEmailAddress($drapperId, 'drapper@ex@ample.org') }
|
|
"setPreferredEmailAddress: email address with extra @ fails to add.";
|
|
|
|
dies_ok { $sp->getPreferredEmailAddress(undef); }
|
|
"getPreferredEmailAddress: dies for undefined id";
|
|
dies_ok { $sp->getPreferredEmailAddress("String"); }
|
|
"getPreferredEmailAddress: dies for non-numeric id";
|
|
|
|
my $ret;
|
|
|
|
lives_ok { $ret = $sp->setPreferredEmailAddress($drapperId, 'drapper@example.com') }
|
|
"setPreferredEmailAddress: email address not found in database does not die....";
|
|
is($ret, undef, "setPreferredEmailAddress: ....but returns undef");
|
|
|
|
lives_ok { $ret = $sp->getPreferredEmailAddress($drapperId) }
|
|
"getPreferredEmailAddress: no preferred does not die....";
|
|
is($ret, undef, "getPreferredEmailAddress: ....but returns undef");
|
|
|
|
lives_ok { $ret = $sp->setPreferredEmailAddress($drapperId, 'drapper@example.org') }
|
|
"setPreferredEmailAddress: setting preferred email address succeeds....";
|
|
|
|
ok( (defined $ret and looks_like_number($ret) and $ret == $drapperEmailId),
|
|
"setPreferredEmailAddress: ... and returns correct email_address_id on success");
|
|
|
|
is($sp->{__NESTED_TRANSACTION_COUNTER__}, 0, "setPreferredEmailAddress: assure proper beginWork/commit matching.");
|
|
|
|
lives_ok { $ret = $sp->getPreferredEmailAddress($drapperId) }
|
|
"getPreferredEmailAddress: lookup of known preferred email address succeeds... ";
|
|
is($ret, 'drapper@example.org', "getPreferredEmailAddress: ....and returns the correct value.");
|
|
|
|
=item getEmailAddresses
|
|
|
|
=cut
|
|
|
|
my %emailAddresses;
|
|
|
|
dies_ok { %emailAddresses = $sp->getEmailAddresses(0); }
|
|
"getEmailAddresses: fails with 0 donorId";
|
|
|
|
dies_ok { %emailAddresses = $sp->getEmailAddresses("String"); }
|
|
"getEmailAddresses: fails with string donorId";
|
|
|
|
dies_ok { %emailAddresses = $sp->getEmailAddresses(undef); }
|
|
"getEmailAddresses: fails with string donorId";
|
|
|
|
lives_ok { %emailAddresses = $sp->getEmailAddresses($olsonId); }
|
|
"getEmailAddresses: 1 lookup of addresses succeeds...";
|
|
|
|
is_deeply(\%emailAddresses, {'everyone@example.net' => { 'date_encountered' => $today, 'name' => 'paypal' },
|
|
'olson@example.net' => { 'date_encountered' => $today, 'name' => 'home' }},
|
|
"getEmailAddresses: ... and returns correct results.");
|
|
|
|
lives_ok { %emailAddresses = $sp->getEmailAddresses($drapperId); }
|
|
"getEmailAddresses: 2 lookup of addresses succeeds...";
|
|
|
|
is_deeply(\%emailAddresses, {'everyone@example.net' => { 'date_encountered' => $today, 'name' => 'paypal' },
|
|
'drapper@example.org' => { 'date_encountered' => $today, 'name' => 'work' }},
|
|
"getEmailAddresses: ... and returns correct results.");
|
|
|
|
lives_ok { %emailAddresses = $sp->getEmailAddresses($sterlingId); }
|
|
"getEmailAddresses: 3 lookup of addresses succeeds...";
|
|
|
|
is_deeply(\%emailAddresses, {'sterlingjr@example.com' => { 'name' => 'home', 'date_encountered' => $today }},
|
|
"getEmailAddresses: ... and returns correct results.");
|
|
|
|
lives_ok { %emailAddresses = $sp->getEmailAddresses($campbellId); }
|
|
"getEmailAddresses: lookup of *empty* addresses succeeds...";
|
|
|
|
is_deeply(\%emailAddresses, {},
|
|
"getEmailAddresses: ... and returns correct results.");
|
|
|
|
# FIXME: getPostalAddresses needs unit tests.
|
|
|
|
=item findDonor
|
|
|
|
=cut
|
|
|
|
my @lookupDonorIds;
|
|
|
|
lives_ok { @lookupDonorIds = $sp->findDonor({}); }
|
|
"findDonor: no search criteria succeeds and...";
|
|
|
|
my(%vals);
|
|
@vals{@lookupDonorIds} = @lookupDonorIds;
|
|
|
|
is_deeply(\%vals, { $campbellId => $campbellId, $sterlingId => $sterlingId, $harrisId => $harrisId,
|
|
$olsonId => $olsonId, $drapperId => $drapperId },
|
|
"findDonor: ... and returns all donorIds.");
|
|
|
|
lives_ok { @lookupDonorIds = $sp->findDonor({ledgerEntityId => "NotFound" }); }
|
|
"findDonor: 1 lookup of known missing succeeds ...";
|
|
|
|
is(scalar(@lookupDonorIds), 0, "findDonor: ... but finds nothing.");
|
|
|
|
lives_ok { @lookupDonorIds = $sp->findDonor({emailAddress => "nothingthere" }); }
|
|
"findDonor: 2 lookup of known missing succeeds ...";
|
|
|
|
is(scalar(@lookupDonorIds), 0, "findDonor: ... but finds nothing.");
|
|
|
|
lives_ok { @lookupDonorIds = $sp->findDonor({emailAddress => 'drapper@example.org', ledgerEntityId => "NOTFOUND" }); }
|
|
"findDonor: 1 and'ed criteria succeeds ...";
|
|
|
|
is(scalar(@lookupDonorIds), 0, "findDonor: ... but finds nothing.");
|
|
|
|
lives_ok { @lookupDonorIds = $sp->findDonor({emailAddress => 'NOTFOUND', ledgerEntityId => "Whitman-Dick" }); }
|
|
"findDonor: 2 and'ed criteria succeeds ...";
|
|
|
|
is(scalar(@lookupDonorIds), 0, "findDonor: ... but finds nothing.");
|
|
|
|
lives_ok { @lookupDonorIds = $sp->findDonor({emailAddress => 'drapper@example.org', ledgerEntityId => "Whitman-Dick" }); }
|
|
"findDonor: 1 valid multiple criteria succeeds ...";
|
|
|
|
is_deeply(\@lookupDonorIds, [$drapperId], "findDonor: ... and finds right entry.");
|
|
|
|
lives_ok { @lookupDonorIds = $sp->findDonor({emailAddress => 'everyone@example.net', ledgerEntityId => "Whitman-Dick" }); }
|
|
"findDonor: 2 valid multiple criteria succeeds ...";
|
|
|
|
is_deeply(\@lookupDonorIds, [$drapperId], "findDonor: ... and finds right entry.");
|
|
|
|
lives_ok { @lookupDonorIds = $sp->findDonor({emailAddress => 'everyone@example.net', ledgerEntityId => "Olson-Margaret" }); }
|
|
"findDonor: 3 valid multiple criteria succeeds ...";
|
|
|
|
is_deeply(\@lookupDonorIds, [$olsonId], "findDonor: ... and finds right entry.");
|
|
|
|
lives_ok { @lookupDonorIds = $sp->findDonor({emailAddress => 'everyone@example.net'}); }
|
|
"findDonor: single criteria find expecting multiple records succeeds...";
|
|
|
|
%vals = ();
|
|
@vals{@lookupDonorIds} = @lookupDonorIds;
|
|
|
|
is_deeply(\%vals, { $olsonId => $olsonId, $drapperId => $drapperId }, "findDonor: ... and finds the right entires.");
|
|
|
|
|
|
|
|
=item donorLastGave
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->donorLastGave(undef); } "donorLastGave(): dies with undefined donorId";
|
|
dies_ok { $sp->donorLastGave("str"); } "donorLastGave(): dies with non-numeric donorId";
|
|
dies_ok { $sp->donorLastGave(0); } "donorLastGave(): dies with non-existent id";
|
|
|
|
my $date;
|
|
|
|
lives_ok { $date = $sp->donorLastGave($drapperId) } "donorLastGave(): check for known annual donor success...";
|
|
|
|
is($date, '2015-05-04', "donorLastGave(): ...and returned value is correct. ");
|
|
|
|
lives_ok { $date = $sp->donorLastGave($olsonId) } "donorLastGave(): check for known monthly donor success...";
|
|
|
|
is($date, '2015-06-30', "donorLastGave(): ...and returned value is correct. ");
|
|
|
|
=item donorFirstGave
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->donorFirstGave(undef); } "donorFirstGave(): dies with undefined donorId";
|
|
dies_ok { $sp->donorFirstGave("str"); } "donorFirstGave(): dies with non-numeric donorId";
|
|
dies_ok { $sp->donorFirstGave(0); } "donorFirstGave(): dies with non-existent id";
|
|
|
|
lives_ok { $date = $sp->donorFirstGave($drapperId) } "donorFirstGave(): check for known annual donor success...";
|
|
|
|
is($date, '2015-02-26', "donorFirstGave(): ...and returned value is correct. ");
|
|
|
|
lives_ok { $date = $sp->donorFirstGave($olsonId) } "donorFirstGave(): check for known monthly donor success...";
|
|
|
|
is($date, '2015-01-15', "donorFirstGave(): ...and returned value is correct. ");
|
|
|
|
=item donorTotalGaveInPeriod
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->donorTotalGaveInPeriod(donorId => undef); } "donorTotalGaveInPeriod(): dies with undefined donorId";
|
|
dies_ok { $sp->donorTotalGaveInPeriod(donorId => "str"); } "donorTotalGaveInPeriod(): dies with non-numeric donorId";
|
|
dies_ok { $sp->donorTotalGaveInPeriod(donorId => 0); } "donorTotalGaveInPeriod(): dies with non-existent id";
|
|
|
|
foreach my $arg (qw/startDate endDate/) {
|
|
dies_ok { $sp->donorTotalGaveInPeriod(donorId => $drapperId, $arg => '2015-1-5'); }
|
|
"donorTotalGaveInPeriod(): dies with non ISO-8601 string in $arg";
|
|
}
|
|
dies_ok { $sp->donorTotalGaveInPeriod(donorId => $drapperId, wrong => ''); }
|
|
"donorTotalGaveInPeriod(): dies if given an argument that is not recognized";
|
|
|
|
my $amount;
|
|
|
|
lives_ok { $amount = $sp->donorTotalGaveInPeriod(donorId => $drapperId) }
|
|
"donorTotalGaveInPeriod(): total for a donor with no period named succeeds...";
|
|
|
|
is($amount, 305.00, "donorTotalGaveInPeriod(): ...and returned value is correct. ");
|
|
|
|
lives_ok { $amount = $sp->donorTotalGaveInPeriod(donorId => $olsonId, startDate => '2015-02-17',
|
|
endDate => '2015-06-29') }
|
|
"donorTotalGaveInPeriod(): check for total with both start and end date succeeds...";
|
|
|
|
is($amount, 30.00, "donorTotalGaveInPeriod(): ...and returned value is correct. ");
|
|
|
|
lives_ok { $amount = $sp->donorTotalGaveInPeriod(donorId => $harrisId, startDate => '2015-12-04'); }
|
|
"donorTotalGaveInPeriod(): check for total with just a start date succeeds...";
|
|
|
|
is($amount, 120.00, "donorTotalGaveInPeriod(): ...and returned value is correct. ");
|
|
|
|
lives_ok { $amount = $sp->donorTotalGaveInPeriod(donorId => $olsonId, endDate => '2015-02-16'); }
|
|
"donorTotalGaveInPeriod(): check for total with just a end date succeeds...";
|
|
|
|
is($amount, 20.00, "donorTotalGaveInPeriod(): ...and returned value is correct. ");
|
|
|
|
=item donorDonationOnDate
|
|
|
|
# FIXME: way to lookup donation on a date.
|
|
|
|
=cut
|
|
|
|
=item supporterExpirationDate
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->supporterExpirationDate(undef); } "supporterExpirationDate(): dies with undefined donorId";
|
|
dies_ok { $sp->supporterExpirationDate("str"); } "supporterExpirationDate(): dies with non-numeric donorId";
|
|
dies_ok { $sp->supporterExpirationDate(0); } "supporterExpirationDate(): dies with non-existent id";
|
|
|
|
lives_ok { $date = $sp->supporterExpirationDate($drapperId) } "supporterExpirationDate(): check for known annual donor success...";
|
|
|
|
is($date, '2016-02-26', "supporterExpirationDate(): ...and returned value is correct. ");
|
|
|
|
lives_ok { $date = $sp->supporterExpirationDate($olsonId) } "supporterExpirationDate(): check for known monthly donor success...";
|
|
|
|
is($date, '2015-08-29', "supporterExpirationDate(): ...and returned value is correct. ");
|
|
|
|
lives_ok { $date = $sp->supporterExpirationDate($sterlingId) } "supporterExpirationDate(): check for never donation success...";
|
|
|
|
is($date, undef, "supporterExpirationDate(): ...and returned undef.");
|
|
|
|
lives_ok { $date = $sp->supporterExpirationDate($harrisId) } "supporterExpirationDate(): same donation amount in year...";
|
|
|
|
is($date, '2016-12-04', "supporterExpirationDate(): ...returns the latter date.");
|
|
|
|
$dbh->do("UPDATE donor SET is_supporter = 0 WHERE id = " . $sp->dbh->quote($campbellId));
|
|
|
|
lives_ok { $date = $sp->supporterExpirationDate($campbellId) } "supporterExpirationDate(): check for no supporter success...";
|
|
|
|
is($date, undef, "supporterExpirationDate(): ...and returned undef.");
|
|
|
|
=back
|
|
|
|
=item Internal methods used only by the module itself.
|
|
|
|
=over
|
|
|
|
=item _verifyId
|
|
|
|
=cut
|
|
|
|
ok( $sp->_verifyId($drapperId), "_verifyId: id just added exists");
|
|
|
|
dies_ok { $sp->_verifyId(undef); } "_verifyId: dies for undefined id";
|
|
dies_ok { $sp->_verifyId("String") } "_verifyId: dies for non-numeric id";
|
|
|
|
# This is a hacky way to test this; but should work
|
|
ok(not ($sp->_verifyId($drapperId + 10)), "_verifyId: non-existent id is not found");
|
|
|
|
=item _lookupEmailAddress
|
|
|
|
=cut
|
|
|
|
dies_ok { $sp->_lookupEmailAddress(undef); } "_lookupEmailAddressId: dies for undefined email_address";
|
|
|
|
is_deeply($sp->_lookupEmailAddress('drapper@example.org'),
|
|
{ emailAddress => 'drapper@example.org', id => $drapperEmailId, type => 'work', dateEncountered => $today },
|
|
"_lookupEmailAddressId: 1 returns email Id for known item");
|
|
|
|
is_deeply($sp->_lookupEmailAddress('everyone@example.net'),
|
|
{ emailAddress => 'everyone@example.net', id => $olsonEmailId2, type => 'paypal', dateEncountered => $today },
|
|
"_lookupEmailAddressId: 2 returns email id for known item");
|
|
|
|
is($sp->_lookupEmailAddress('drapper@example.com'), undef,
|
|
"_lookupEmailAddressId: returns undef for unknown item.");
|
|
|
|
$sp = undef;
|
|
|
|
sub ResetDB($) {
|
|
$_[0]->disconnect() if defined $_[0];
|
|
my $tempDBH = get_test_dbh();
|
|
my $tempSP = new Supporters($tempDBH, [ "testcmd" ]);
|
|
return ($tempDBH, $tempSP);
|
|
}
|
|
|
|
my($tempDBH, $tempSP) = ResetDB($dbh);
|
|
|
|
=item _getOrCreateRequestType
|
|
|
|
=cut
|
|
|
|
dies_ok { $tempSP->_getOrCreateRequestType({ }); }
|
|
"_getOrCreateRequestType: dies on empty hash";
|
|
|
|
dies_ok { $tempSP->_getOrCreateRequestType({ requestTypeId => "NoStringsPlease" }); }
|
|
"_getOrCreateRequestType: dies for string request id";
|
|
|
|
dies_ok { $tempSP->_getOrCreateRequestType({ requestTypeId => 0 }); }
|
|
"_getOrCreateRequestType: dies for non-existant requestTypeId";
|
|
|
|
my %hh = ( requestType => 'test-request' );
|
|
lives_ok { $tempSP->_getOrCreateRequestType(\%hh); }
|
|
"_getOrCreateRequestType: succeeds with just requestType";
|
|
|
|
my $rr;
|
|
lives_ok { $rr = $tempSP->getRequestType("test-request"); }
|
|
"_getOrCreateRequestType: lookup of a request works after _getOrCreateRequestType";
|
|
|
|
is_deeply(\%hh, { requestTypeId => $rr },
|
|
"_getOrCreateRequestType: lookup of a request works after _getOrCreateRequestType");
|
|
|
|
%hh = ( requestTypeId => $rr, requestType => 'this-arg-matters-not' );
|
|
|
|
lives_ok { $tempSP->_getOrCreateRequestType(\%hh); }
|
|
"_getOrCreateRequestType: lookup of existing requestType suceeds.";
|
|
|
|
is_deeply(\%hh, { requestTypeId => $rr },
|
|
"_getOrCreateRequestType: deletes requestType if both are provided.");
|
|
|
|
dies_ok { $tempSP->_lookupRequestTypeById(undef); }
|
|
"_lookupRequestTypeById: dies for undefined requestTypeId";
|
|
|
|
dies_ok { $tempSP->_lookupRequestTypeById("NoStringsPlease"); }
|
|
"_lookupRequestTypeById: dies for a string requestTypeId";
|
|
|
|
ok( (not $tempSP->_lookupRequestTypeById(0)), "_lookupRequestTypeById: returns false for id lookup for 0");
|
|
|
|
# Assumption here: that id number one more than the last added would never be in db.
|
|
ok( (not $tempSP->_lookupRequestTypeById($rr + 1)),
|
|
"_lookupRequestTypeById: returns false for id one greater than last added");
|
|
|
|
is($tempSP->_lookupRequestTypeById($rr), "test-request",
|
|
"_lookupRequestTypeById: returns proper result for id known to be in database");
|
|
|
|
=item _getOrCreateRequestConfiguration
|
|
|
|
=cut
|
|
|
|
dies_ok { $tempSP->_getOrCreateRequestConfiguration({ }); }
|
|
"_getOrCreateRequestConfiguration: dies on empty hash";
|
|
|
|
dies_ok { $tempSP->_getOrCreateRequestConfiguration({ requestConfigurationId => "NoStringsPlease" }); }
|
|
"_getOrCreateRequestConfiguration: dies for string requestConfigurationId";
|
|
|
|
dies_ok { $tempSP->_getOrCreateRequestConfiguration({ requestConfigurationId => 0 }); }
|
|
"_getOrCreateRequestConfiguration: dies for non-existant requestConfigurationId";
|
|
|
|
dies_ok { $tempSP->_getOrCreateRequestConfiguration({ requestTypeId => "NoStringsPlease" }); }
|
|
"_getOrCreateRequestConfiguration: dies for string request id";
|
|
|
|
dies_ok { $tempSP->_getOrCreateRequestConfiguration({ requestTypeId => 0 }); }
|
|
"_getOrCreateRequestConfiguration: dies for non-existant requestTypeId";
|
|
|
|
dies_ok { $tempSP->_getOrCreateRequestConfiguration({ requestTypeId => $rr,
|
|
requestConfigurationId => "NoStringsPlease" }); }
|
|
"_getOrCreateRequestConfiguration: dies for string requestConfigurationId with valid requestTypeId";
|
|
|
|
%hh = ( requestConfiguration => 'test-request-config' );
|
|
dies_ok { $tempSP->_getOrCreateRequestConfiguration(\%hh); }
|
|
"_getOrCreateRequestConfiguration: fails with just requestConfiguration.";
|
|
|
|
$val = $tempSP->dbh()->selectall_hashref("SELECT id, description FROM request_configuration", 'description');
|
|
|
|
ok((defined $val and (keys(%$val) == 0)),
|
|
"_getOrCreateRequestConfiguration: no request_configuration record added for failed attempts");
|
|
|
|
%hh = ( requestTypeId => $rr, requestConfiguration => 'test-request-config' );
|
|
lives_ok { $tempSP->_getOrCreateRequestConfiguration(\%hh); }
|
|
"_getOrCreateRequestConfiguration: succeeds with requestConfiguration and requestType";
|
|
|
|
my($fullConfig, $rc);
|
|
lives_ok { $fullConfig = $tempSP->getRequestConfigurations('test-request'); }
|
|
"getRequestConfigurations: succeeds after successful _getOrCreateRequestConfiguration()";
|
|
|
|
$rc = $fullConfig->{$rr}{'test-request-config'};
|
|
|
|
is_deeply(\%hh, { requestTypeId => $rr, requestConfigurationId => $rc },
|
|
"_getOrCreateRequestConfiguration: modification of paramater argument was correct after successful add");
|
|
|
|
is_deeply $fullConfig,
|
|
{ 1 => { 'test-request-config' => 1 } },
|
|
"_getOrCreateRequestConfiguration: lookup of a request configuration works after _getOrCreateRequestConfiguration";
|
|
|
|
%hh = (requestTypeId => $rr, requestConfiguration => "test-request-config");
|
|
lives_ok { $tempSP->_getOrCreateRequestConfiguration(\%hh); }
|
|
"_getOrCreateRequestConfiguration: looks up one previously added by _getOrCreateRequestConfiguration()";
|
|
|
|
is_deeply(\%hh, { requestTypeId => $rr, requestConfigurationId => $rc },
|
|
"_getOrCreateRequestConfiguration: lookup of a request works after _getOrCreateRequestConfiguration");
|
|
|
|
%hh = ( requestTypeId => $rr, requestConfigurationId => $rc, requestConfiguration => 'this-arg-matters-not' );
|
|
|
|
lives_ok { $tempSP->_getOrCreateRequestConfiguration(\%hh); }
|
|
"_getOrCreateRequestConfiguration: lookup of existing requestConfigurationId succeeds, ignoring requestConfiguration parameter.";
|
|
|
|
is_deeply(\%hh, { requestTypeId => $rr, requestConfigurationId => $rc },
|
|
"_getOrCreateRequestConfiguration: deletes requestTypeConfiguration if both are provided.");
|
|
|
|
=back
|
|
|
|
=item Database weirdness tests
|
|
|
|
=cut
|
|
|
|
($tempDBH, $tempSP) = ResetDB($tempDBH);
|
|
$tempDBH->do("DROP TABLE email_address;");
|
|
|
|
dies_ok { $tempSP->addSupporter({ display_name => "Roger Sterling",
|
|
public_ack => 0, ledger_entity_id => "Sterling-Roger",
|
|
email_address => 'sterlingjr@example.com',
|
|
email_address_type => 'home' }) }
|
|
"addSupporter: dies when email_address table does not exist & email adress given";
|
|
|
|
|
|
$tempDBH->disconnect; $tempDBH = reopen_test_dbh();
|
|
|
|
$val = $tempDBH->selectall_hashref("SELECT id FROM donor;", 'id');
|
|
|
|
ok( (defined $val and reftype $val eq "HASH" and keys(%{$val}) == 0),
|
|
"addSupporter: fails if email_address given but email cannot be inserted");
|
|
|
|
$tempDBH->disconnect; $tempDBH = reopen_test_dbh();
|
|
|
|
|
|
|
|
=back
|
|
|
|
=cut
|
|
|
|
$tempDBH->disconnect;
|
|
1;
|
|
###############################################################################
|
|
#
|
|
# Local variables:
|
|
# compile-command: "perl -c Supporters.t && cd ..; make clean; perl Makefile.PL && make && make test TEST_VERBOSE=1"
|
|
# End:
|
|
|