From b47c02a154284a44aeb69642a816956fbca72024 Mon Sep 17 00:00:00 2001 From: Ryan Higgins Date: Mon, 5 Nov 2007 17:13:58 -0600 Subject: [PATCH] adding koha-specific / data specific test cases Signed-off-by: Chris Cormack Signed-off-by: Joshua Ferraro --- C4/SIP/koha_test/.SIPtest.pm.swp | Bin 0 -> 16384 bytes C4/SIP/koha_test/00sc_status.t | 26 ++++ C4/SIP/koha_test/01patron_status.t | 80 ++++++++++ C4/SIP/koha_test/02patron_info.t | 172 ++++++++++++++++++++++ C4/SIP/koha_test/03checkout.t | 209 ++++++++++++++++++++++++++ C4/SIP/koha_test/04patron_status.t | 100 +++++++++++++ C4/SIP/koha_test/05block_patron.t | 45 ++++++ C4/SIP/koha_test/06patron_enable.t | 144 ++++++++++++++++++ C4/SIP/koha_test/07hold.t | 187 ++++++++++++++++++++++++ C4/SIP/koha_test/08checkin.t | 67 +++++++++ C4/SIP/koha_test/09renew.t | 147 +++++++++++++++++++ C4/SIP/koha_test/10renew_all.t | 107 ++++++++++++++ C4/SIP/koha_test/11item_info.t | 42 ++++++ C4/SIP/koha_test/Makefile | 16 ++ C4/SIP/koha_test/README | 50 +++++++ C4/SIP/koha_test/SIPtest.pm | 227 +++++++++++++++++++++++++++++ 16 files changed, 1619 insertions(+) create mode 100644 C4/SIP/koha_test/.SIPtest.pm.swp create mode 100644 C4/SIP/koha_test/00sc_status.t create mode 100644 C4/SIP/koha_test/01patron_status.t create mode 100644 C4/SIP/koha_test/02patron_info.t create mode 100644 C4/SIP/koha_test/03checkout.t create mode 100644 C4/SIP/koha_test/04patron_status.t create mode 100644 C4/SIP/koha_test/05block_patron.t create mode 100644 C4/SIP/koha_test/06patron_enable.t create mode 100644 C4/SIP/koha_test/07hold.t create mode 100644 C4/SIP/koha_test/08checkin.t create mode 100644 C4/SIP/koha_test/09renew.t create mode 100644 C4/SIP/koha_test/10renew_all.t create mode 100644 C4/SIP/koha_test/11item_info.t create mode 100644 C4/SIP/koha_test/Makefile create mode 100644 C4/SIP/koha_test/README create mode 100644 C4/SIP/koha_test/SIPtest.pm diff --git a/C4/SIP/koha_test/.SIPtest.pm.swp b/C4/SIP/koha_test/.SIPtest.pm.swp new file mode 100644 index 0000000000000000000000000000000000000000..f0f0e48bb73722b1e365902e90d3690dcccf1646 GIT binary patch literal 16384 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 dPG{y@yBOP 'Invalid username', + msg => "9300CNinvalid$username|CO$password|CPThe floor|", + pat => qr/^940/, + fields => [], }; + +my $invalid_pwd = { id => 'Invalid username', + msg => "9300CN$username|COinvalid$password|CPThe floor|", + pat => qr/^940/, + fields => [], }; + +my @tests = ( $invalid_uname, $invalid_pwd, $login_test, $sc_status_test ); + +SIPtest::run_sip_tests(@tests); + +1; diff --git a/C4/SIP/koha_test/01patron_status.t b/C4/SIP/koha_test/01patron_status.t new file mode 100644 index 0000000000..a00c074f14 --- /dev/null +++ b/C4/SIP/koha_test/01patron_status.t @@ -0,0 +1,80 @@ +#!/usr/bin/perl +# +# patron_status: check status of valid patron and invalid patron + +use strict; +use warnings; + +use Sip::Constants qw(:all); +use SIPtest qw($datepat $instid $currency $user_barcode $user_pin + $user_fullname $user_homeaddr $user_email $user_phone + $user_birthday); + +my @tests = ( + $SIPtest::login_test, + $SIPtest::sc_status_test, + { id => 'valid Patron Status', + msg => "2300120060101 084237AO$SIPtest::instid|AA$user_barcode|AD$user_pin|AC|", + pat => qr/^24 [ Y]{13}\d{3}$datepat/, + fields => [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PERSONAL_NAME, + pat => qr/^$user_fullname$/o, + required => 1, }, + { field => FID_PATRON_ID, + pat => qr/^$user_barcode/o, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^Y$/, + required => 0, }, + { field => FID_VALID_PATRON_PWD, + pat => qr/^Y$/, + required => 0, }, + { field => FID_CURRENCY, + pat => qr/^$currency$/io, + required => 0, }, + { field => FID_FEE_AMT, + pat => qr/^[0-9.]+$/, + required => 0, }, + ], }, + { id => 'invalid password Patron Status', + msg => "2300120060101 084237AO$instid|AA$user_barcode|AC|ADbadw|", + pat => qr/^24[ Y]{14}\d{3}$datepat/, + fields => [ + { field => FID_PERSONAL_NAME, + pat => qr/^$user_fullname$/o, + required => 1, }, + { field => FID_PATRON_ID, + pat => qr/^$user_barcode$/o, + required => 1, }, + { field => FID_INST_ID, + pat => qr/^$instid$/o, + required => 1, }, + { field => FID_VALID_PATRON_PWD, + pat => qr/^N$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^Y$/, + required => 1, }, + ], }, + { id => 'invalid Patron Status', + msg => "2300120060101 084237AO$instid|AAwshakespeare|AC|", + pat => qr/^24Y[ Y]{13}\d{3}$datepat/, + fields => [ + { field => FID_PERSONAL_NAME, + pat => qr/^$/, + required => 1, }, + { field => FID_PATRON_ID, + pat => qr/^wshakespeare$/, + required => 1, }, + { field => FID_INST_ID, + pat => qr/^$instid$/o, + required => 1, }, + ], }, + ); + +SIPtest::run_sip_tests(@tests); + +1; diff --git a/C4/SIP/koha_test/02patron_info.t b/C4/SIP/koha_test/02patron_info.t new file mode 100644 index 0000000000..292c279532 --- /dev/null +++ b/C4/SIP/koha_test/02patron_info.t @@ -0,0 +1,172 @@ +#!/usr/bin/perl +# patron_info: test Patron Information Response + +use strict; +use warnings; +use Clone qw(clone); + +use Sip::Constants qw(:all); + +use SIPtest qw($datepat $textpat $instid $currency $user_barcode $user_pin + $user_fullname $user_homeaddr $user_email $user_phone + $user_birthday $user_ptype $user_inet); + +# This is a template test case for the Patron Information +# message handling. Because of the large number of fields, +# this template forms the basis for all of the different +# situations: valid patron no details, valid patron with each +# individual detail requested, invalid patron, invalid patron +# password, etc. +my $patron_info_test_template = { + id => 'valid Patron Info no details', + msg => "6300020060329 201700 AO$instid|AA$user_barcode|", + pat => qr/^64 [ Y]{13}\d{3}$datepat(\d{4}){6}/, + fields => [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^$user_barcode$/o, + required => 1, }, + { field => FID_PERSONAL_NAME, + pat => qr/^$user_fullname$/o, + required => 1, }, + $SIPtest::field_specs{(FID_HOLD_ITEMS_LMT)}, + $SIPtest::field_specs{(FID_OVERDUE_ITEMS_LMT)}, + $SIPtest::field_specs{(FID_CHARGED_ITEMS_LMT)}, + { field => FID_VALID_PATRON, + pat => qr/^Y$/, + # Not required by the spec, but by the test + required => 1, }, + $SIPtest::field_specs{(FID_CURRENCY)}, + { field => FID_FEE_AMT, + pat => $textpat, + required => 0, }, + { field => FID_FEE_LMT, + pat => $textpat, + required => 0, }, + { field => FID_HOME_ADDR, + pat => qr/^$user_homeaddr$/o, + required => 1, }, # required by this test case + { field => FID_EMAIL, + pat => qr/^$user_email$/o, + required => 1, }, + { field => FID_HOME_PHONE, + pat => qr/^$user_phone$/o, + required => 1, }, + { field => FID_PATRON_BIRTHDATE, + pat => qr/^$user_birthday$/o, + required => 1, }, + { field => FID_PATRON_CLASS, + pat => qr/^$user_ptype$/o, + required => 1, }, + { field => FID_INET_PROFILE, + pat => qr/^$user_inet$/, + required => 1, }, + ], }; + +my @tests = ( + $SIPtest::login_test, + $SIPtest::sc_status_test, + clone($patron_info_test_template), + ); + + +# Create the test cases for the various summary detail fields +sub create_patron_summary_tests { + my $test; + my @patron_info_summary_tests = ( + { field => FID_HOLD_ITEMS, + pat => $textpat, + required => 0, }, + { field => FID_OVERDUE_ITEMS, + pat => $textpat, + required => 0, }, + { field => FID_CHARGED_ITEMS, + pat => $textpat, + required => 0, }, +# The test user has no items of these types, so the tests seem to fail +# { field => FID_FINE_ITEMS, +# pat => $textpat, +# required => 1, }, +# { field => FID_RECALL_ITEMS, +# pat => $textpat, +# required => 0, }, +# { field => FID_UNAVAILABLE_HOLD_ITEMS, +# pat => $textpat, +# required => 0, }, + ); + + foreach my $i (0 .. scalar @patron_info_summary_tests-1) { + # The tests for each of the summary fields are exactly the + # same as the basic one, except for the fact that there's + # an extra field to test + + # Copy the hash, adjust it, add it to the end of the list + $test = clone($patron_info_test_template); + + substr($test->{msg}, 23+$i, 1) = 'Y'; + $test->{id} = "valid Patron Info details: " + . $patron_info_summary_tests[$i]->{field}; + push @{$test->{fields}}, $patron_info_summary_tests[$i]; + push @tests, $test; + } +} + +sub create_invalid_patron_tests { + my $test; + + $test = clone($patron_info_test_template); + $test->{id} = "invalid Patron Info id"; + $test->{msg} =~ s/AA$user_barcode\|/AAberick|/o; + $test->{pat} = qr/^64Y[ Y]{13}\d{3}$datepat(\d{4}){6}/; + delete $test->{fields}; + $test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^berick$/, + required => 1, }, + { field => FID_PERSONAL_NAME, + pat => qr/^$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^N$/, + required => 1, }, + ]; + push @tests, $test; + + # Valid patron, invalid patron password + $test = clone($patron_info_test_template); + $test->{id} = "valid Patron Info, invalid password"; + $test->{msg} .= (FID_PATRON_PWD) . 'badpwd|'; + $test->{pat} = qr/^64[ Y]{14}\d{3}$datepat(\d{4}){6}/; + delete $test->{fields}; + $test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^$user_barcode$/, + required => 1, }, + { field => FID_PERSONAL_NAME, + pat => qr/^$user_fullname$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^Y$/, + required => 1, }, + { field => FID_VALID_PATRON_PWD, + pat => qr/^N$/, + required => 1, }, + ]; + push @tests, $test; +} + +create_patron_summary_tests; + +create_invalid_patron_tests; + +SIPtest::run_sip_tests(@tests); + +1; diff --git a/C4/SIP/koha_test/03checkout.t b/C4/SIP/koha_test/03checkout.t new file mode 100644 index 0000000000..da9dd28b16 --- /dev/null +++ b/C4/SIP/koha_test/03checkout.t @@ -0,0 +1,209 @@ +#!/usr/bin/perl +# checkout: test Checkout Response + +use strict; +use warnings; +use Clone qw(clone); + +use Sip::Constants qw(:all); + +use SIPtest qw($datepat $textpat $instid $currency $user_barcode + $item_barcode $item_title + $item_diacritic_barcode $item_diacritic_title + $item_diacritic_owner); + +my $patron_enable_template = { + id => 'Renew All: prep: enable patron permissions', + msg => "2520060102 084238AO$instid|AA$user_barcode|", + pat => qr/^26 {4}[ Y]{10}000$datepat/o, + fields => [], +}; + +my $patron_disable_template = { + id => 'Checkout: block patron (prep to test checkout denied)', + msg => "01N20060102 084238AO$instid|ALHe's a jerk|AA$user_barcode|", + # response to block patron is a patron status message + pat => qr/^24Y{4}[ Y]{10}000$datepat/o, + fields => [], }; + +my $checkin_template = { + id => 'Checkout: cleanup: check in item', + msg => "09N20050102 08423620060113 084235APUnder the bed|AO$instid|AB$item_barcode|ACterminal password|", + pat => qr/^101YNN$datepat/o, + fields => [], + }; + +my $checkout_test_template = { + id => 'Checkout: valid item, valid patron', + msg => "11YN20060329 203000 AO$instid|AA$user_barcode|AB$item_barcode|AC|", + pat => qr/^121NNY$datepat/, + fields => [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^$user_barcode$/o, + required => 1, }, + { field => FID_ITEM_ID, + pat => qr/^$item_barcode$/o, + required => 1, }, + { field => FID_TITLE_ID, + pat => qr/^$item_title\s*$/o, + required => 1, }, + { field => FID_DUE_DATE, + pat => $textpat, + required => 1, }, + { field => FID_FEE_TYPE, + pat => qr/^\d{2}$/, + required => 0, }, + { field => FID_SECURITY_INHIBIT, + pat => qr/^[YN]$/, + required => 0, }, + { field => FID_CURRENCY, + pat => qr/^$currency$/o, + required => 0, }, + { field => FID_FEE_AMT, + pat => qr/^[.0-9]+$/, + required => 0, }, + { field => FID_MEDIA_TYPE, + pat => qr/^\d{3}$/, + required => 0, }, + { field => FID_ITEM_PROPS, + pat => $textpat, + required => 0, }, + { field => FID_TRANSACTION_ID, + pat => $textpat, + required => 0, }, + ], }; + +my @tests = ( + $SIPtest::login_test, + $SIPtest::sc_status_test, + clone($checkout_test_template), + # Don't check the item in, because we're about to test renew + ); + +my $test; + +## Renewal OK +## Test this by checking out exactly the same book a second time. +## The only difference should be that the "Renewal OK" flag should now +## be 'Y'. +#$test = clone($checkout_test_template); +#$test->{id} = 'Checkout: patron renewal'; +#$test->{pat} = qr/^121YNY$datepat/; +# +#push @tests, $test; + +# NOW check it in + +push @tests, $checkin_template; + +# Valid Patron, item with diacritical in the title +$test = clone($checkout_test_template); + +$test->{id} = 'Checkout: valid patron, diacritical character in title'; +$test->{msg} =~ s/AB$item_barcode/AB$item_diacritic_barcode/; + +foreach my $i (0 .. (scalar @{$test->{fields}})-1) { + my $field = $test->{fields}[$i]; + + if ($field->{field} eq FID_ITEM_ID) { + $field->{pat} = qr/^$item_diacritic_barcode$/; + } elsif ($field->{field} eq FID_TITLE_ID) { + $field->{pat} = qr/^$item_diacritic_title\s*$/; + } elsif ($field->{field} eq FID_OWNER) { + $field->{pat} = qr/^$item_diacritic_owner$/; + } +} + +push @tests, $test; + +$test = clone($checkin_template); +$test->{msg} =~ s/AB$item_barcode/AB$item_diacritic_barcode/; +push @tests, $test; + +# Valid Patron, Invalid Item_id +$test = clone($checkout_test_template); + +$test->{id} = 'Checkout: valid patron, invalid item'; +$test->{msg} =~ s/AB$item_barcode/ABno-barcode/o; +$test->{pat} = qr/^120NUN$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^$user_barcode$/o, + required => 1, }, + { field => FID_ITEM_ID, + pat => qr/^no-barcode$/, + required => 1, }, + { field => FID_TITLE_ID, + pat => qr/^$/, + required => 1, }, + { field => FID_DUE_DATE, + pat => qr/^$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^Y$/, + required => 1, }, + ]; + +push @tests, $test; + +# Invalid patron, valid item +$test = clone($checkout_test_template); +$test->{id} = 'Checkout: invalid patron, valid item'; +$test->{msg} =~ s/AA$user_barcode/AAberick/; +$test->{pat} = qr/^120NUN$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^berick$/, + required => 1, }, + { field => FID_ITEM_ID, + pat => qr/^$item_barcode$/o, + required => 1, }, + { field => FID_TITLE_ID, + pat => qr/^$item_title\s*$/o, + required => 1, }, + { field => FID_DUE_DATE, + pat => qr/^$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^N$/, + required => 1, }, + ]; + +push @tests, $test; + +# Needed: tests for blocked patrons, patrons with excessive +# fines/fees, magnetic media, charging fees to borrow items. + +## Blocked patron +#$test = clone($checkout_test_template); +#$test->{id} = 'Checkout: Blocked patron'; +#$test->{pat} = qr/^120NUN$datepat/; +#delete $test->{fields}; +#$test->{fields} = [ +# $SIPtest::field_specs{(FID_INST_ID)}, +# $SIPtest::field_specs{(FID_SCREEN_MSG)}, +# $SIPtest::field_specs{(FID_PRINT_LINE)}, +# { field => FID_PATRON_ID, +# pat => qr/^$user_barcode$/, +# required => 1, }, +# { field => FID_VALID_PATRON, +# pat => qr/^Y$/, +# required => 1, }, +# ]; +# +#push @tests, $patron_disable_template, $test, $patron_enable_template; +# +SIPtest::run_sip_tests(@tests); + +1; diff --git a/C4/SIP/koha_test/04patron_status.t b/C4/SIP/koha_test/04patron_status.t new file mode 100644 index 0000000000..ebec04ecc3 --- /dev/null +++ b/C4/SIP/koha_test/04patron_status.t @@ -0,0 +1,100 @@ +#!/usr/bin/perl +# patron_status: test Patron Status Response + +use strict; +use warnings; +use Clone qw(clone); + +use Sip::Constants qw(:all); + +use SIPtest qw($datepat $textpat); + +my $patron_status_test_template = { + id => 'Patron Status: valid patron, no patron password', + msg => '2300120060101 084237AOUWOLS|AAdjfiander|ACterminal password|', + pat => qr/^24 [ Y]{13}001$datepat/, + fields => [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^djfiander$/, + required => 1, }, + { field => FID_PERSONAL_NAME, + pat => qr/^David J\. Fiander$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^Y$/, + # Not required by the spec, but by the test + required => 1, }, + $SIPtest::field_specs{(FID_CURRENCY)}, + { field => FID_FEE_AMT, + pat => $textpat, + required => 0, }, + ], }; + +my @tests = ( + $SIPtest::login_test, + $SIPtest::sc_status_test, + clone($patron_status_test_template), + ); + +# Invalid patron +my $test = clone($patron_status_test_template); + +$test->{id} = 'Patron Status invalid id'; +$test->{msg} =~ s/AAdjfiander\|/AAberick|/; + +# The test assumes that the language sent by the terminal is +# just echoed back for invalid patrons. +$test->{pat} = qr/^24Y[ Y]{13}001$datepat/; + +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^berick$/, + required => 1, }, + { field => FID_PERSONAL_NAME, + pat => qr/^$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^N$/, + required => 1, }, + ]; + +push @tests, $test; + +# Valid patron, invalid patron password +$test = clone($patron_status_test_template); +$test->{id} = 'Patron Status: Valid patron, invalid patron password'; +$test->{msg} .= (FID_PATRON_PWD) . 'badpwd|'; +$test->{pat} = qr/^24[ Y]{14}001$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^djfiander$/, + required => 1, }, + { field => FID_PERSONAL_NAME, + pat => qr/^David J\. Fiander$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^Y$/, + required => 1, }, + { field => FID_VALID_PATRON_PWD, + pat => qr/^N$/, + required => 1, }, + ]; +push @tests, $test; + +# TODO: Need multiple patrons to test each individual +# status field + +SIPtest::run_sip_tests(@tests); + +1; diff --git a/C4/SIP/koha_test/05block_patron.t b/C4/SIP/koha_test/05block_patron.t new file mode 100644 index 0000000000..3bdbdb27ac --- /dev/null +++ b/C4/SIP/koha_test/05block_patron.t @@ -0,0 +1,45 @@ +#!/usr/bin/perl +# block_patron: test Block Patron Response + +use strict; +use warnings; +use Clone qw(clone); + +use Sip::Constants qw(:all); + +use SIPtest qw($datepat $textpat $instid $user_barcode $user_fullname); + +my $block_patron_test_template = { + id => 'Block Patron: valid patron, card not retained', + msg => "01N20060102 084238AO$instid|ALHe's a jerk|AA$user_barcode|ACterminal password|", + # response to block patron is a patron status message + pat => qr/^24Y[ Y]{13}000$datepat/o, + fields => [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^$user_barcode$/o, + required => 1, }, + { field => FID_PERSONAL_NAME, + pat => qr/^$user_fullname$/o, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^Y$/, + # Not required by the spec, but by the test + required => 1, }, + $SIPtest::field_specs{(FID_CURRENCY)}, + { field => FID_FEE_AMT, + pat => $textpat, + required => 0, }, + ], }; + +my @tests = ( + $SIPtest::login_test, + $SIPtest::sc_status_test, + clone($block_patron_test_template), + ); + +SIPtest::run_sip_tests(@tests); + +1; diff --git a/C4/SIP/koha_test/06patron_enable.t b/C4/SIP/koha_test/06patron_enable.t new file mode 100644 index 0000000000..56486c053b --- /dev/null +++ b/C4/SIP/koha_test/06patron_enable.t @@ -0,0 +1,144 @@ +#!/usr/bin/perl +# patron_enable: test Patron Enable Response + +use strict; +use warnings; +use Clone qw(clone); + +use Sip::Constants qw(:all); + +use SIPtest qw($datepat $textpat); + +my $patron_enable_test_template = { + id => 'Patron Enable: valid patron', + msg => "2520060102 084238AOUWOLS|AAdjfiander|", + pat => qr/^26 {4}[ Y]{10}000$datepat/, + fields => [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^djfiander$/, + required => 1, }, + { field => FID_PERSONAL_NAME, + pat => qr/^David J\. Fiander$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^Y$/, + # Not required by the spec, but by the test + required => 1, }, + ], }; + +# We need to disable the valid patron before we can +# ensure that he was properly enabled. +my $patron_disable_test_template = { + id => 'Patron Enable: block patron (prep to test enabling)', + msg => "01N20060102 084238AOUWOLS|ALHe's a jerk|AAdjfiander|", + # response to block patron is a patron status message + pat => qr/^24Y{4}[ Y]{10}000$datepat/, + fields => [ + $SIPtest::field_specs{(FID_INST_ID)}, + { field => FID_PATRON_ID, + pat => qr/^djfiander$/, + required => 1, }, + { field => FID_PERSONAL_NAME, + pat => qr/^David J\. Fiander$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^Y$/, + # Not required by the spec, but by the test + required => 1, }, + ], }; + +my @tests = ( + $SIPtest::login_test, + $SIPtest::sc_status_test, + $patron_disable_test_template, + clone($patron_enable_test_template), + ); + +my $test; + +# Valid patron, valid password +$test = clone($patron_enable_test_template); +$test->{id} = "Patron Enable: valid patron, valid password"; +$test->{msg} .= FID_PATRON_PWD . '6789|'; +$test->{pat} = qr/^26 {4}[ Y]{10}000$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^djfiander$/, + required => 1, }, + { field => FID_PERSONAL_NAME, + pat => qr/^David J\. Fiander$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^Y$/, + # Not required by the spec, but by the test + required => 1, }, + { field => FID_VALID_PATRON_PWD, + pat => qr/^Y$/, + required => 1, }, + ]; + +push @tests, $patron_disable_test_template, $test; + +# Valid patron, invalid password +$test = clone($patron_enable_test_template); +$test->{id} = "Patron Enable: valid patron, invalid password"; +$test->{msg} .= FID_PATRON_PWD . 'bad password|'; +$test->{pat} = qr/^26[ Y]{14}000$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^djfiander$/, + required => 1, }, + { field => FID_PERSONAL_NAME, + pat => qr/^David J\. Fiander$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^Y$/, + # Not required by the spec, but by the test + required => 1, }, + { field => FID_VALID_PATRON_PWD, + pat => qr/^N$/, + required => 1, }, + ]; + +push @tests, $patron_disable_test_template, $test; +# After this test, the patron is left disabled, so re-enable +push @tests, $patron_enable_test_template; + +# Invalid patron +$test = clone($patron_enable_test_template); +$test->{id} =~ s/valid/invalid/; +$test->{msg} =~ s/AAdjfiander\|/AAberick|/; +$test->{pat} = qr/^26Y{4}[ Y]{10}000$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^berick$/, + required => 1, }, + { field => FID_PERSONAL_NAME, + pat => qr/^$/, + required => 1, }, + { field => FID_VALID_PATRON, + pat => qr/^N$/, + # Not required by the spec, but by the test + required => 1, }, + ]; + +push @tests, $test; + +SIPtest::run_sip_tests(@tests); + +1; diff --git a/C4/SIP/koha_test/07hold.t b/C4/SIP/koha_test/07hold.t new file mode 100644 index 0000000000..bddb31218a --- /dev/null +++ b/C4/SIP/koha_test/07hold.t @@ -0,0 +1,187 @@ +#!/usr/bin/perl +# patron_enable: test Patron Enable Response + +use strict; +use warnings; +use Clone qw(clone); + +use Sip::Constants qw(:all); + +use SIPtest qw($datepat $textpat); + +my $hold_test_template = { + id => 'Place Hold: valid item, valid patron', + msg => '15+20060415 110158BW20060815 110158|BSTaylor|BY2|AOUWOLS|AAdjfiander|AB1565921879|', + pat => qr/^161N$datepat/, + fields => [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^djfiander$/, + required => 1, }, + { field => FID_EXPIRATION, + pat => $datepat, + required => 0, }, + { field => FID_QUEUE_POS, + pat => qr/^1$/, + required => 1, }, + { field => FID_PICKUP_LOCN, + pat => qr/^Taylor$/, + required => 1, }, + { field => FID_TITLE_ID, + pat => qr/^Perl 5 desktop reference$/, + required => 1, }, + { field => FID_ITEM_ID, + pat => qr/^1565921879$/, + required => 1, }, + ],}; + +my $hold_count_test_template0 = { + id => 'Confirm patron has 0 holds', + msg => '6300020060329 201700 AOUWOLS|AAdjfiander|', + pat => qr/^64 [ Y]{13}\d{3}${datepat}0000(\d{4}){5}/, + fields => [], +}; + +my $hold_count_test_template1 = { + id => 'Confirm patron has 1 hold', + msg => '6300020060329 201700 AOUWOLS|AAdjfiander|', + pat => qr/^64 [ Y]{13}\d{3}${datepat}0001(\d{4}){5}/, + fields => [], +}; + + +my @tests = ( + $SIPtest::login_test, + $SIPtest::sc_status_test, + $hold_test_template, $hold_count_test_template1, + ); + +my $test; + +# Hold Queue: second hold placed on item +$test = clone($hold_test_template); +$test->{id} = 'Place hold: second hold on item'; +$test->{msg} =~ s/djfiander/miker/; +$test->{pat} = qr/^161N$datepat/; +foreach my $i (0 .. (scalar @{$test->{fields}})-1) { + my $field = $test->{fields}[$i]; + + if ($field->{field} eq FID_PATRON_ID) { + $field->{pat} = qr/^miker$/; + } elsif ($field->{field} eq FID_QUEUE_POS) { + $field->{pat} = qr/^2$/; + } +} + +push @tests, $test; + +# Cancel hold: valid hold +$test = clone($hold_test_template); +$test->{id} = 'Cancel hold: valid hold'; +$test->{msg} =~ s/\+/-/; +$test->{pat} = qr/^161[NY]$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^djfiander$/, + required => 1, }, + ]; + +push @tests, $test, $hold_count_test_template0; + +# Cancel Hold: no hold on item +# $test is already set up to cancel a hold, just change +# the field tests +$test = clone($test); +$test->{id} = 'Cancel Hold: no hold on specified item'; +$test->{pat} = qr/^160N$datepat/; + +push @tests, $test, $hold_count_test_template0; + +# Cleanup: cancel miker's hold too. +$test = clone($hold_test_template); +$test->{id} = "Cancel hold: cleanup second patron's hold"; +$test->{msg} =~ s/\+/-/; +$test->{msg} =~ s/djfiander/miker/; +$test->{pat} = qr/^161[NY]$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^miker$/, + required => 1, }, + ]; + +push @tests, $test; + +# Place hold: valid patron, item, invalid patron pwd +$test = clone($hold_test_template); +$test->{id} = 'Place hold: invalid patron password'; +$test->{msg} .= FID_PATRON_PWD . 'bad password|'; +$test->{pat} = qr/^160N$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^djfiander$/, + required => 1, }, + ]; + +push @tests, $test, $hold_count_test_template0; + +# Place hold: invalid patron +$test = clone($hold_test_template); +$test->{id} = 'Place hold: invalid patron'; +$test->{msg} =~ s/AAdjfiander\|/AAberick|/; +$test->{pat} = qr/^160N$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^berick$/, + required => 1, }, + ]; + +# There's no patron to check the number of holds against +push @tests, $test; + +# Place hold: invalid item +$test = clone($hold_test_template); +$test->{id} = 'Place hold: invalid item'; +$test->{msg} =~ s/AB1565921879\|/ABnosuchitem|/; +$test->{pat} = qr/^160N$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^djfiander$/, + required => 1, }, + { field => FID_ITEM_ID, + pat => qr/^nosuchitem$/, + required => 0, }, + ]; + +push @tests, $test, $hold_count_test_template0; + +# Still need tests for: +# - valid patron not permitted to place holds +# - valid item, not allowed to hold item +# - multiple holds on item: correct queue position management +# - setting and verifying hold expiry dates (requires ILS support) + +SIPtest::run_sip_tests(@tests); + +1; diff --git a/C4/SIP/koha_test/08checkin.t b/C4/SIP/koha_test/08checkin.t new file mode 100644 index 0000000000..395cda5171 --- /dev/null +++ b/C4/SIP/koha_test/08checkin.t @@ -0,0 +1,67 @@ +#!/usr/bin/perl +# checkin: test Checkin Response + +use strict; +use warnings; +use Clone qw(clone); + +use Sip::Constants qw(:all); + +use SIPtest qw($datepat $textpat $instid $user_barcode + $item_barcode $item_title); + +my $checkin_test_template = { + id => 'Checkin: Item is checked out', + msg => "09N20060102 08423620060113 084235APUnder the bed|AO$instid|AB$item_barcode|ACterminal password|", + pat => qr/^101YNN$datepat/o, + fields => [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^$user_barcode$/o, + required => 1, }, + { field => FID_ITEM_ID, + pat => qr/^$item_barcode$/o, + required => 1, }, + { field => FID_PERM_LOCN, + pat => $textpat, + required => 1, }, + { field => FID_TITLE_ID, + pat => qr/^$item_title\s*$/o, + required => 1, }, # not required by the spec. + ],}; + +my $checkout_template = { + id => 'Checkin: prep: check out item', + msg => "11YN20060329 203000 AO$instid|AA$user_barcode|AB$item_barcode|AC|", + pat => qr/^121NNY$datepat/o, + fields => [], +}; + +my @tests = ( + $SIPtest::login_test, + $SIPtest::sc_status_test, + $checkout_template, + $checkin_test_template, + ); + +my $test; + +# Checkin item that's not checked out. Basically, this +# is identical to the first case, except the header says that +# the ILS didn't check the item in, and there's no patron id. +$test = clone($checkin_test_template); +$test->{id} = 'Checkin: Item not checked out'; +$test->{pat} = qr/^100YNN$datepat/o; +$test->{fields} = [grep $_->{field} ne FID_PATRON_ID, @{$test->{fields}}]; + +push @tests, $test; + +# +# Still need tests for magnetic media +# + +SIPtest::run_sip_tests(@tests); + +1; diff --git a/C4/SIP/koha_test/09renew.t b/C4/SIP/koha_test/09renew.t new file mode 100644 index 0000000000..ad9fb06640 --- /dev/null +++ b/C4/SIP/koha_test/09renew.t @@ -0,0 +1,147 @@ +#!/usr/bin/perl +# renew: test Renew Response + +use strict; +use warnings; +use Clone qw(clone); + +use Sip::Constants qw(:all); + +use SIPtest qw($datepat $textpat $instid $currency $user_barcode + $item_barcode $item_title); + +my $checkout_template = { + id => 'Renew: prep: check out item', + msg => "11YN20060329 203000 AO$instid|AA$user_barcode|AB$item_barcode|AC|", + pat => qr/^121NNY$datepat/, + fields => [], + }; + +my $checkin_template = { + id => 'Renew: prep: check in item', + msg => "09N20060102 08423620060113 084235APUnder the bed|AO$instid|AB$item_barcode|ACterminal password|", + pat => qr/^101YNN$datepat/, + fields => [], + }; + +#my $hold_template = { +# id => 'Renew: prep: place hold on item', +# msg =>"15+20060415 110158BW20060815 110158|BSTaylor|BY2|AO$instid|AAmiker|AB$item_barcode|", +# pat => qr/^161N$datepat/, +# fields => [], +# }; +# +#my $cancel_hold_template = { +# id => 'Renew: cleanup: cancel hold on item', +# msg =>"15-20060415 110158BW20060815 110158|BSTaylor|BY2|AO$instid|AAmiker|AB$item_barcode|", +# pat => qr/^161[NY]$datepat/, +# fields => [], +# }; +# + +my $renew_test_template = { + id => 'Renew: item id checked out to patron, renewal permitted, no 3rd party, no fees', + msg => "29NN20060102 084236 AO$instid|AA$user_barcode|AB$item_barcode|", + pat => qr/^301YNN$datepat/, + fields => [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_PATRON_ID, + pat => qr/^$user_barcode$/, + required => 1, }, + { field => FID_ITEM_ID, + pat => qr/^$item_barcode$/, + required => 1, }, + { field => FID_TITLE_ID, + pat => qr/^$item_title\s*$/, + required => 1, }, + { field => FID_DUE_DATE, + pat => qr/^$datepat$/, + required => 1, }, + { field => FID_SECURITY_INHIBIT, + pat => qr/^[YN]$/, + required => 0, }, + ],}; + +my @tests = ( + $SIPtest::login_test, + $SIPtest::sc_status_test, + $checkout_template, + $renew_test_template, + ); + +my $test; + +# Renew: item checked out, identify by title +#$test = clone($renew_test_template); +#$test->{id} = 'Renew: identify item by title'; +#$test->{msg} =~ s/AB$item_barcode\|/AJ$item_title|/; +## Everything else should be the same +#push @tests, $test; +# +## Renew: Item checked out, but another patron has placed a hold +#$test = clone($renew_test_template); +#$test->{id} = 'Renew: Item has outstanding hold'; +#$test->{pat} = qr/^300NUN$datepat/; +#foreach my $field (@{$test->{fields}}) { +# if ($field->{field} eq FID_DUE_DATE || $field->{field} eq FID_TITLE_ID) { +# $field->{pat} = qr/^$/; +# } +#} +# +#push @tests, $hold_template, $test, $cancel_hold_template; +# +# Renew: item not checked out. Basically the same, except +# for the leader test. +$test = clone($renew_test_template); +$test->{id} = 'Renew: item not checked out at all'; +$test->{pat} = qr/^300NUN$datepat/; +foreach my $field (@{$test->{fields}}) { + if ($field->{field} eq FID_DUE_DATE) { + $field->{pat} = qr/^$/; + } elsif ($field->{field} eq FID_TITLE_ID) { + $field->{pat} = qr/^($item_title\s*|)$/; + } +} + +push @tests, $checkin_template, $test; + +$test = clone($renew_test_template); +$test->{id} = 'Renew: Invalid item'; +$test->{msg} =~ s/AB[^|]+/ABbad-item/; +$test->{pat} = qr/^300NUN$datepat/; +foreach my $field (@{$test->{fields}}) { + if ($field->{field} eq FID_TITLE_ID || $field->{field} eq FID_DUE_DATE) { + $field->{pat} = qr/^$/; + } elsif ($field->{field} eq FID_ITEM_ID) { + $field->{pat} = qr/^bad-item$/; + } +} + +push @tests, $test; + +$test = clone($renew_test_template); +$test->{id} = 'Renew: Invalid user'; +$test->{msg} =~ s/AA$user_barcode/AAberick/; +$test->{pat} = qr/^300NUN$datepat/; +foreach my $field (@{$test->{fields}}) { + if ($field->{field} eq FID_DUE_DATE) { + $field->{pat} = qr/^$/; + } elsif ($field->{field} eq FID_PATRON_ID) { + $field->{pat} = qr/^berick$/; + } elsif ($field->{field} eq FID_TITLE_ID) { + $field->{pat} = qr/^($item_title\s*|)$/; + } +} + +push @tests, $test; + +# Still need tests for +# - renewing a for-fee item +# - patrons that are not permitted to renew +# - renewing item that has reached limit on number of renewals + +SIPtest::run_sip_tests(@tests); + +1; diff --git a/C4/SIP/koha_test/10renew_all.t b/C4/SIP/koha_test/10renew_all.t new file mode 100644 index 0000000000..2cf6ee5bd3 --- /dev/null +++ b/C4/SIP/koha_test/10renew_all.t @@ -0,0 +1,107 @@ +#!/usr/bin/perl +# renew_all: test Renew All Response + +use strict; +use warnings; +use Clone qw(clone); + +use Sip::Constants qw(:all); + +use SIPtest qw($datepat $textpat $user_barcode $item_barcode $item_owner + $item2_barcode $item2_owner $instid); + +my $enable_template = { + id => 'Renew All: prep: enable patron permissions', + msg => "2520060102 084238AO$instid|AA$user_barcode|", + pat => qr/^26 {4}[ Y]{10}000$datepat/, + fields => [], +}; + +my @checkout_templates = ( + { id => "Renew All: prep: check out $item_barcode", + msg => "11YN20060329 203000 AO$instid|AA$user_barcode|AB$item_barcode|AC|", + pat => qr/^121NNY$datepat/, + fields => [],}, + { id => "Renew All: prep: check out $item2_barcode", + msg => "11YN20060329 203000 AO$instid|AA$user_barcode|AB$item2_barcode|AC|", + pat => qr/^121NNY$datepat/, + fields => [],} + ); + +my @checkin_templates = ( + { id => "Renew All: prep: check in $item_barcode", + msg => "09N20060102 08423620060113 084235APUnder the bed|AO$instid|AB$item_barcode|ACterminal password|", + pat => qr/^101YNN$datepat/, + fields => [],}, + { id => "Renew All: prep: check in $item2_barcode", + msg => "09N20060102 08423620060113 084235APUnder the bed|AO$instid|AB$item2_barcode|ACterminal password|", + pat => qr/^101YNN$datepat/, + fields => [],} + ); + +my $renew_all_test_template = { + id => 'Renew All: valid patron with one item checked out, no patron password', + msg => "6520060102 084236AO$instid|AA$user_barcode|", + pat => qr/^66100010000$datepat/, + fields => [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_RENEWED_ITEMS, + pat => qr/^$item_barcode$/, + required => 1, }, + ],}; + +my @tests = ( + $SIPtest::login_test, + $SIPtest::sc_status_test, +# $enable_template, + $checkout_templates[0], + $renew_all_test_template, + $checkin_templates[0], # check the book in, when done testing + ); + +my $test; + +#$test = clone($renew_all_test_template); +#$test->{id} = 'Renew All: Valid patron, two items checked out'; +#$test->{pat} = qr/^66100020000$datepat/; +#foreach my $i (0 .. (scalar @{$test->{fields}})-1) { +# my $field = $test->{fields}[$i]; +# +# if ($field->{field} eq FID_RENEWED_ITEMS) { +# $field->{pat} = qr/^$item_barcode\|$item2_barcode$/; +# } +#} +# +#push @tests, $checkout_templates[0], $checkout_templates[1], +# $renew_all_test_template, $checkin_templates[0], $checkin_templates[1]; + +$test = clone($renew_all_test_template); +$test->{id} = 'Renew All: valid patron, invalid patron password'; +$test->{msg} .= (FID_PATRON_PWD) . 'badpwd|'; +$test->{pat} = qr/^66000000000$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + ]; + +push @tests, $checkout_templates[0], $test, $checkin_templates[0]; + +$test = clone($renew_all_test_template); +$test->{id} = 'Renew All: invalid patron'; +$test->{msg} =~ s/AA$user_barcode/AAberick/; +$test->{pat} = qr/^66000000000$datepat/; +delete $test->{fields}; +$test->{fields} = [ + $SIPtest::field_specs{(FID_INST_ID)}, + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + ]; +push @tests, $test; + +SIPtest::run_sip_tests(@tests); + +1; diff --git a/C4/SIP/koha_test/11item_info.t b/C4/SIP/koha_test/11item_info.t new file mode 100644 index 0000000000..a0d7ad2474 --- /dev/null +++ b/C4/SIP/koha_test/11item_info.t @@ -0,0 +1,42 @@ +#!/usr/bin/perl +# renew_all: test Renew All Response + +use strict; +use warnings; +use Clone qw(clone); + +use Sip::Constants qw(:all); + +use SIPtest qw($datepat $textpat $instid $currency $user_barcode + $item_barcode $item_title $item_owner); + +my $item_info_test_template = { + id => 'Item Information: check information for available item', + msg => "1720060110 215612AO$instid|AB$item_barcode|", + pat => qr/^180[13]0201$datepat/, # status of 'other' or 'available' + fields => [ + $SIPtest::field_specs{(FID_SCREEN_MSG)}, + $SIPtest::field_specs{(FID_PRINT_LINE)}, + { field => FID_ITEM_ID, + pat => qr/^$item_barcode$/, + required => 1, }, + { field => FID_TITLE_ID, + pat => qr/^$item_title\s*$/, + required => 1, }, + { field => FID_MEDIA_TYPE, + pat => qr/^\d{3}$/, + required => 0, }, + { field => FID_OWNER, + pat => qr/^$item_owner$/, + required => 0, }, + ], }; + +my @tests = ( + $SIPtest::login_test, + $SIPtest::sc_status_test, + clone($item_info_test_template), + ); + +SIPtest::run_sip_tests(@tests); + +1; diff --git a/C4/SIP/koha_test/Makefile b/C4/SIP/koha_test/Makefile new file mode 100644 index 0000000000..9f2e2480d1 --- /dev/null +++ b/C4/SIP/koha_test/Makefile @@ -0,0 +1,16 @@ +# +# +# + +TESTS = 00sc_status.t 01patron_status.t 02patron_info.t 03checkout.t \ + 04patron_status.t 05block_patron.t 06patron_enable.t 07hold.t \ + 08checkin.t 09renew.t 10renew_all.t 11item_info.t + +OILS_TESTS = 00sc_status.t 01patron_status.t 02patron_info.t 03checkout.t \ + 08checkin.t 09renew.t 11item_info.t 05block_patron.t + +test-openils: + prove -I.. $(OILS_TESTS) + +test: + prove -I.. $(TESTS) diff --git a/C4/SIP/koha_test/README b/C4/SIP/koha_test/README new file mode 100644 index 0000000000..9f954f34ec --- /dev/null +++ b/C4/SIP/koha_test/README @@ -0,0 +1,50 @@ +CONFIGURING THE TEST SUITE + +Before you can run the test suite, you need to configure certain +information about the SIP server and the ILS data in the file +SIPtest.pm. + +RUNNING THE TESTS + +Every file tests a different protocol transaction. +Unfortunately, a lot of test cases are missing, but the basics +are tested, as are most of the simple error conditions (invalid +users, unknown items, checking in item that's not checked out). + +To run a single test, just run + + perl -I.. + +If the test fails, the output should be pretty clear about what +went wrong (assuming you can read raw SIP packets). + +To run all the tests, just type + + make test + +Right now, that will run tests for functionality that isn't +supported in the Evergreen environment (the two main cases are +enable patron and hold management). To run just the Evergreen tests, use + + make test-openils + +which will run just the tests + + 00sc_status.t + 01patron_status.t + 02patron_info.t + 03checkout.t + 06patron_enable.t + 08checkin.t + 09renew.t + 11item_info.t + 05block_patron.t + +NOTE: the Block Patron tests are run last because "Patron Enable" +isn't supported. Thus, after running the "Block Patron" test, +manual intervention is required to unblock the test patron. + +The Renew All tests will fail when running the stub "ILS" +implementation unless there's only one ILS server running. This +won't be a problem for any real backend implementation that +properly manages the database of users and items. diff --git a/C4/SIP/koha_test/SIPtest.pm b/C4/SIP/koha_test/SIPtest.pm new file mode 100644 index 0000000000..ec0f21d0cf --- /dev/null +++ b/C4/SIP/koha_test/SIPtest.pm @@ -0,0 +1,227 @@ +package SIPtest; + +use strict; +use warnings; + +use Exporter; + +our @ISA = qw(Exporter); + +our @EXPORT_OK = qw(run_sip_tests no_tagged_fields + $datepat $textpat + $login_test $sc_status_test + %field_specs + + $instid $currency $server $username $password + $user_barcode $user_pin $user_fullname $user_homeaddr + $user_email $user_phone $user_birthday $user_ptype + $user_inet + $item_barcode $item_title $item_owner + $item2_barcode $item2_title $item2_owner + $item_diacritic_barcode $item_diacritic_title + $item_diacritic_owner); +#use Data::Dumper; + +# The number of tests is set in run_sip_tests() below, based +# on the size of the array of tests. +use Test::More; + +use IO::Socket::INET; +use Sip qw(:all); +use Sip::Checksum qw(verify_cksum); +use Sip::Constants qw(:all); + +# +# Configuration parameters to run the test suite +# +our $instid = 'kohalibrary'; +our $currency = 'USD'; +#our $instid = 'UWOLS'; +#our $currency = 'CAD'; +our $server = 'localhost:6001'; # Address of the SIP server + +# SIP username and password to connect to the server. See the +# SIP config.xml for the correct values. +our $username = 'koha'; +our $password = 'koha'; + +# ILS Information + +# Valid user barcode and corresponding user password/pin and full name +our $user_barcode = '900002'; +our $user_pin = 'password'; +our $user_fullname= 'firstname surname'; +our $user_homeaddr= '35 address'; +our $user_email = 'patron@liblime.com'; +our $user_phone = '555'; +our $user_birthday= ''; +our $user_ptype = ''; +our $user_inet = ''; + +# Valid item barcode and corresponding title +our $item_barcode = '1565921879'; +our $item_title = 'Perl 5 desktop reference'; +our $item_owner = 'kohalibrary'; + +# Another valid item +our $item2_barcode = '0440242746'; +our $item2_title = 'The deep blue alibi'; +our $item2_owner = 'kohalibrary'; + +# An item with a diacritical in the title +our $item_diacritic_barcode = '660'; +our $item_diacritic_title = 'Harry Potter y el cáliz de fuego'; +our $item_diacritic_owner = 'kohalibrary'; + +# End configuration + +# Pattern for a SIP datestamp, to be used by individual tests to +# match timestamp fields (duh). +our $datepat = '\d{8} {4}\d{6}'; + +# Pattern for a random text field (may be empty) +our $textpat = qr/^[^|]*$/; + +our %field_specs = ( + (FID_SCREEN_MSG) => { field => FID_SCREEN_MSG, + pat => $textpat, + required => 0, }, + (FID_PRINT_LINE) => { field => FID_PRINT_LINE, + pat => $textpat, + required => 0, }, + (FID_INST_ID) => { field => FID_INST_ID, + pat => qr/^$instid$/o, + required => 1, }, + (FID_HOLD_ITEMS_LMT)=> { field => FID_HOLD_ITEMS_LMT, + pat => qr/^\d{4}$/, + required => 0, }, + (FID_OVERDUE_ITEMS_LMT)=> { field => FID_OVERDUE_ITEMS_LMT, + pat => qr/^\d{4}$/, + required => 0, }, + (FID_CHARGED_ITEMS_LMT)=> { field => FID_CHARGED_ITEMS_LMT, + pat => qr/^\d{4}$/, + required => 0, }, + (FID_VALID_PATRON) => { field => FID_VALID_PATRON, + pat => qr/^[NY]$/, + required => 0, }, + (FID_VALID_PATRON_PWD)=> { field => FID_VALID_PATRON_PWD, + pat => qr/^[NY]$/, + required => 0, }, + (FID_CURRENCY) => { field => FID_CURRENCY, + pat => qr/^$currency$/io, + required => 0, }, + ); + +# Login and SC Status are always the first two messages that +# the terminal sends to the server, so just create the test +# cases here and reference them in the individual test files. + +our $login_test = { id => 'login', + msg => "9300CN$username|CO$password|CPThe floor|", + pat => qr/^941/, + fields => [], }; + +our $sc_status_test = { id => 'SC status', + msg => '9910302.00', + pat => qr/^98[YN]{6}\d{3}\d{3}$datepat(2\.00|1\.00)/, + fields => [ + $field_specs{(FID_SCREEN_MSG)}, + $field_specs{(FID_PRINT_LINE)}, + $field_specs{(FID_INST_ID)}, + { field => 'AM', + pat => $textpat, + required => 0, }, + { field => 'BX', + pat => qr/^[YN]{16}$/, + required => 1, }, + { field => 'AN', + pat => $textpat, + required => 0, }, + ], + }; + +sub one_msg { + my ($sock, $test, $seqno) = @_; + my $resp; + my %fields; + + # If reading or writing fails, then the server's dead, + # so there's no point in continuing. + if (!write_msg({seqno => $seqno}, $test->{msg}, $sock)) { + BAIL_OUT("Write failure in $test->{id}"); + } elsif (!($resp = <$sock>)) { + BAIL_OUT("Read failure in $test->{id}"); + } + + chomp($resp); + + if (!verify_cksum($resp)) { + fail("checksum $test->{id}"); + return; + } + if ($resp !~ $test->{pat}) { + fail("match leader $test->{id}"); + diag("Response '$resp' doesn't match pattern '$test->{pat}'"); + return; + } + + # Split the tagged fields of the response into (name, value) + # pairs and stuff them into the hash. + $resp =~ $test->{pat}; + %fields = substr($resp, $+[0]) =~ /(..)([^|]*)\|/go; + +# print STDERR Dumper($test); +# print STDERR Dumper(\%fields); + if (!defined($test->{fields})) { + diag("TODO: $test->{id} field tests not written yet"); + } else { + # If there are no tagged fields, then 'fields' should be an + # empty list which will automatically skip this loop + foreach my $ftest (@{$test->{fields}}) { + my $field = $ftest->{field}; + + if ($ftest->{required} && !exists($fields{$field})) { + fail("$test->{id} required field '$field' exists in '$resp'"); + return; + } + + if (exists($fields{$field}) && ($fields{$field} !~ $ftest->{pat})) { + + fail("$test->{id} field test $field"); + diag("Field pattern '$ftest->{pat}' for '$field' doesn't match in '$resp'"); + return; + } + } + } + pass("$test->{id}"); + return; +} + +# +# _count_tests: Count the number of tests in a test array +sub _count_tests { + return scalar @_; +} + +sub run_sip_tests { + my ($sock, $seqno); + + $Sip::error_detection = 1; + $/ = "\r"; + + $sock = new IO::Socket::INET(PeerAddr => $server, + Type => SOCK_STREAM); + + BAIL_OUT('failed to create connection to server') unless $sock; + + $seqno = 1; + + plan tests => _count_tests(@_); + + foreach my $test (@_) { + one_msg($sock, $test, $seqno++); + $seqno %= 10; # sequence number is one digit + } +} + +1; -- 2.39.2