#!/usr/bin/perl use DateTime; use Data::Dumper; use Data::Printer; use Test::Exception; use Test::Builder::Tester; use Test::WWW::Mechanize::CGIApp; use strict; use warnings; use Test::More; # done_testing() at end # use Test::More 'no_plan'; =begin # tests: 0) create new data for tests - outcome not tested 1) update unit_number on single patient entry to unique val - old val replaced by new 2) delete unit_number on single patient entry - old val replaced by default val 3) change unit_number of patient_case with > 1 request attached - single record change 4) select a previous patient_case and set scope to all 5) test effect of resubmitting same patient_case data - should be no change 6) manually change unit_number to match existing patient_case - for scope set to one 7) delete unit number - set scope to all 8) change location to one in same parent_organisation 9) change location to one in different parent_organisation 10) change hospital location to practice 11) change location and unit_number together 12) use back button & re-submit form (should not cause error) 13) emulate consequence of incomplete updates using 2 browser tabs =cut require 't/test-lib.pl'; my $mech = get_mech(); # login/logout tests handled by test-lib.pl do_login(); # print $fh $mech->content; # exit; my $time_now = DateTime->now(); # create some new patient/request/patient_case records for this test suite: { my $dbix = get_dbix(); my $year = $time_now->year(); # new data: my %new = ( parent_organisations => [ # parent_code description referral_type_id [ 'DEF', 'OLDTOWN NHS TRUST', 3 ], ], patient_case => [ # patient_id, referral_source_id, unit_number [ 2, 1, 'ABC123' ], ], referral_sources => [ # display_name org_code parent_org_id referral_type_id [ 'Newtown District Hospital', 'ABC02', 1, 3 ], [ 'Oldtown & Region Trust ', 'DEF01', 5, 3 ], ], requests => [ # yr, request_id, patient_case_id, referrer_dept_id, now [ $year, 3, 2, 1, $time_now ], # hospital referral - duplicate of request #2 [ $year, 4, 3, 1, $time_now ], # hospital referral - same as request #2, diff unit_number ], request_specimen => [ # request_id, specimen_id [ 3, 1 ], [ 4, 3 ], ], ); my $test_data = get_test_data(); while ( my ($tbl, $data) = each %new ) { # warn $tbl, "\n"; my $fields = $test_data->{$tbl}->{fields}; # warn Dumper $fields; foreach my $data_set (@$data) { # warn $data_set, "\n"; my $i = 0; # map field_name to its value: my %data = map { $fields->[$i++] => $_ } @$data_set; # warn Dumper \%data; $dbix->insert($tbl, \%data); } } # create_view(); } # edit request patient_case: { # update unit_number only: # load request_edit page direct: $mech->get_ok('/request/edit/1'); # print_and_exit(); # no changes, just tests 'reason for edit': $mech->submit_form(); # print_and_exit(); has_dfv_errors(); has_missing(); # change unit number to unqiue - will create new record: $mech->field( unit_number => 'ABC123'); $mech->field( error_code_id =>1 ); $mech->submit_form(); # print_and_exit(); has_edit_success(1); # check fields are as expected: my %params = ( name => 'green', old_unit_number => 1011, new_unit_number => 'ABC123', location => 'The Surgery, Newtown, NT1 1NT', old_val_retained => 0, # old unit_number should not be detected ); check_edit(\%params); # print_and_exit(); # check history: $mech->get_ok('/history/=/1'); # print_and_exit(); $mech->has_tag_like( td => qr(amended unit number \[1011 -> ABC123\]), 'OK: expected history found', ); # print_and_exit(); } { # delete unit_number on single-patient entry: $mech->get_ok('/request/edit/1'); # print_and_exit(); # delete unit number: $mech->field( unit_number => ''); $mech->field( error_code_id =>1 ); $mech->submit_form(); # print_and_exit(); has_edit_success(1); # check fields are as expected: my %params = ( name => 'green', old_unit_number => 'ABC123', new_unit_number => 'UNKNOWN', location => 'The Surgery, Newtown, NT1 1NT', old_val_retained => 0, # old unit_number should not be detected ); check_edit(\%params); # check history: $mech->get_ok('/history/=/1'); # print_and_exit(); $mech->has_tag_like( td => qr(deleted unit number \[ABC123\]), 'OK: expected history found', ); # print_and_exit(); } { # change unit number of patient_case with > 1 request attached: # load request_edit page direct: $mech->get_ok('/request/edit/2'); # print_and_exit(); # check other patient_case data loaded: my %args = ( unit_number => 'ABC123', patient_case_id => 3, record_count => 2, ); check_previous(\%args); # change unit number to unqiue - will create new record: $mech->field( unit_number => '11223344'); $mech->field( error_code_id =>1 ); # just this record - no point testing missing 'scope' as it's not deselectable # should default to 'one' if unit_number not 'unknown' - tests opposite below # $mech->field( scope => 'one'); $mech->submit_form(); # print_and_exit(); has_edit_success(1); # check fields are as expected: my %params = ( name => 'brown', old_unit_number => 1234, new_unit_number => 11223344, location => 'Newtown General Infirmary', old_val_retained => 1, # old unit_number should still be detected ); check_edit(\%params); # print_and_exit(); # check history: $mech->get_ok('/history/=/2'); # print_and_exit(); $mech->has_tag_like( td => qr(amended unit number \[1234 -> 11223344\]), 'OK: expected history found', ); # print_and_exit(); } # select a previous patient_case and change all records to match: { # load page direct: $mech->get_ok('/request/edit/2'); # print_and_exit(); # check other patient_cases data loaded: { my %args = ( unit_number => '1234', patient_case_id => 2, ); check_previous(\%args); } { my %args = ( unit_number => 'ABC123', patient_case_id => 3, ); check_previous(\%args); } # print_and_exit(); $mech->field( use_patient_case_id => 2); $mech->field( scope => 'all'); $mech->field( error_code_id =>1 ); $mech->submit_form(); # print_and_exit(); has_edit_success(1); # check fields are as expected: my %params = ( name => 'brown', new_unit_number => 1234, old_unit_number => 11223344, location => 'Newtown General Infirmary', old_val_retained => 0, # old unit_number should not exist ); check_edit(\%params); # print_and_exit(); # should also be detectable: $params{new_unit_number} = 'ABC123'; check_edit(\%params); # print_and_exit(); # check history: $mech->get_ok('/history/=/2'); # print_and_exit(); $mech->has_tag_like( td => qr(amended unit number \[11223344 -> 1234\]), 'OK: expected history found', ); # print_and_exit(); } # test effect of resubmitting same patient_case data - should be no change: { $mech->get_ok('/request/edit/2'); # print_and_exit(); $mech->field( scope => 'all'); $mech->field( error_code_id =>1 ); $mech->submit_form(); # print_and_exit(); # should have 'no changes' msg instead of 'edit success': $mech->content_lacks( get_messages('action')->{edit_success}, 'OK: edit success message not present', ); $mech->content_contains( get_messages('request_edit')->{edit_failed}, 'OK: no changes detected message present', ); $mech->has_tag( td => 1234, 'OK: original unit number still present', ); # print_and_exit(); } # manually change unit_number to match existing patient_case - for scope set to all: { $mech->get_ok('/request/edit/2'); # print_and_exit(); # check other patient_cases data loaded: { my %args = ( unit_number => 'ABC123', patient_case_id => 3, record_count => 2, ); check_previous(\%args); } # change unit number to one match one previously used: $mech->field( unit_number => 'ABC123' ); $mech->field( scope => 'all'); $mech->field( error_code_id =>1 ); $mech->submit_form(); # print_and_exit(); has_edit_success(2); # check fields are as expected: my %params = ( name => 'brown', new_unit_number => 'ABC123', old_unit_number => 1234, location => 'Newtown General Infirmary', old_val_retained => 0, # old unit_number should not exist ); check_edit(\%params); # print_and_exit(); # check history: $mech->get_ok('/history/=/2'); # print_and_exit(); $mech->has_tag_like( td => qr(amended unit number \[1234 -> ABC123\]), 'OK: expected history found', ); # print_and_exit(); } { # delete unit_number - scope = all: $mech->get_ok('/request/edit/2'); # print_and_exit(); # should have 3 records: $mech->text_contains( 'all 3 records', 'OK: correct number of records', ); # delete unit number: $mech->field( unit_number => ''); $mech->field( error_code_id =>1 ); $mech->field( scope => 'all'); $mech->submit_form(); # print_and_exit(); has_edit_success(3); # check fields are as expected: my %params = ( name => 'brown', old_unit_number => 'ABC123', new_unit_number => 'UNKNOWN', location => 'Newtown General Infirmary', old_val_retained => 0, # old unit_number should not be detected ); check_edit(\%params); # check history: $mech->get_ok('/history/=/2'); # print_and_exit(); $mech->has_tag_like( td => qr(deleted unit number \[ABC123\]), 'OK: expected history found', ); # print_and_exit(); } { # update unit_number from 'unknown' - tests scope defaults to 'all': $mech->get_ok('/request/edit/2'); # print_and_exit(); # should have 3 records: $mech->text_contains( 'all 3 records', 'OK: correct number of records', ); # print_and_exit(); # change unit number to one match one previously used: $mech->field( unit_number => 123456 ); $mech->field( error_code_id =>1 ); # should default to 'all' if unit_number = 'unknown' # $mech->field( scope => 'all'); $mech->submit_form(); # print_and_exit(); has_edit_success(3); # check fields are as expected: my %params = ( name => 'brown', new_unit_number => 123456, old_unit_number => 'UNKNOWN', location => 'Newtown General Infirmary', old_val_retained => 0, # old unit_number should not exist ); check_edit(\%params); # print_and_exit(); # check history: $mech->get_ok('/history/=/2'); # print_and_exit(); $mech->has_tag_like( td => qr(amended unit number \[UNKNOWN -> 123456\]), 'OK: expected history found', ); # print_and_exit(); } # change location to one in same parent_organisation: { $mech->get_ok("/register/patient_search?name=brown"); # print_and_exit(); $mech->follow_link(text => 'Select', n => 1); # print_and_exit(); =begin TODO: # need to test for following before edit: #1. Newtown General Infirmary 123456 =cut $mech->get_ok('/search/=/2'); # print_and_exit(); $mech->has_tag( td => 'Newtown General Infirmary', 'OK: expected location value found' ); $mech->has_tag( td => 123456, 'OK: expected unit_number value found' ); $mech->has_tag_like( span => qr(Brown CC), 'OK: expected referrer value found' ); # print_and_exit(); $mech->follow_link_ok( # {n => 8}, "Logout $_ via eighth link on page", { url_regex => qr(request/edit), }, 'edit request using link', ); # print_and_exit(); # change location to one in same parent_org as current: $mech->field( referral_source_id => 5 ); # this would be done automatically by ajax function: $mech->field( _location_name => 'Newtown District Hospital'); $mech->field( error_code_id =>1 ); $mech->field( scope => 'one'); $mech->submit_form(); # print_and_exit(); has_edit_success(1); # check new details: $mech->has_tag( td => 'Newtown District Hospital', 'OK: expected location value found' ); $mech->has_tag( td => 123456, 'OK: expected unit_number value found' ); $mech->has_tag_like( span => qr(Brown CC), 'OK: expected referrer value found' ); # print_and_exit(); # check old location not found: $mech->content_lacks( 'Newtown General Infirmary', 'OK: old location value not found' ); # print_and_exit(); # check history: $mech->get_ok('/history/=/2'); # print_and_exit(); $mech->has_tag_like( td => qr(amended referral source \[Newtown General Infirmary -> Newtown District Hospital\]), 'OK: expected history found', ); # print_and_exit(); $mech->get_ok("/register/patient_search?name=brown"); # print_and_exit(); $mech->follow_link(text => 'Select', n => 1); # print_and_exit(); =begin # TODO: need to test for following after edit: #1. Newtown General Infirmary 123456 #2. Newtown District Hospital 123456 # <= new patient_case =cut } # change location to one in different parent_organisation: { # check referrer & location 1st: $mech->get_ok('/search/=/2'); # print_and_exit(); $mech->has_tag( td => 'Newtown District Hospital', 'OK: expected location value found' ); $mech->has_tag( td => 123456, 'OK: expected unit_number value found' ); $mech->has_tag_like( span => qr(Brown CC), 'OK: expected referrer value found' ); # print_and_exit(); # going to create new referrer_department, so check correct type: $mech->content_like( qr(span class="acronym"(\s+)title="Haematology"), 'OK: correct hospital_department attribute detected', ); $mech->get_ok('/request/edit/2'); # print_and_exit(); $mech->field( referral_source_id => 6 ); # this would be done automatically by ajax function: $mech->field( _location_name => 'Oldtown & Region Trust'); $mech->field( error_code_id =>1 ); $mech->field( scope => 'one'); $mech->submit_form(); # print_and_exit(); has_edit_success(1); $mech->has_tag( td => 'Oldtown & Region Trust', 'OK: new location detected', ); $mech->has_tag( span => 'Unknown', 'OK: unknown referrer detected', ); # print_and_exit(); # have created new referrer_department, so check correct type: $mech->content_like( qr(span class="acronym"(\s+)title="Unknown/other"), 'OK: changed hospital_department attribute correct', ); # check history: $mech->get_ok('/history/=/2'); # print_and_exit(); $mech->has_tag_like( td => qr(amended referral source \[Newtown District Hospital -> Oldtown & Region Trust\]), 'OK: expected history found', ); # print_and_exit(); $mech->get_ok("/register/patient_search?name=brown"); # print_and_exit(); $mech->follow_link(text => 'Select', n => 1); # print_and_exit(); =begin # TODO: need to test for following after edit: 1. Newtown General Infirmary 123456 2. Newtown District Hospital 123456 3. Oldtown & Region Trust 123456 <= new patient_case =cut } # change hospital to gp: { # check referrer & location 1st: $mech->get_ok('/search/=/3'); # print_and_exit(); $mech->has_tag( td => 'Newtown General Infirmary', 'OK: expected location value found' ); $mech->has_tag_like( span => qr(Brown CC), 'OK: expected referrer value found' ); # print_and_exit(); # going to create new referrer_department, so check correct type: $mech->content_like( qr(span class="acronym"(\s+)title="Haematology"), 'OK: correct hospital_department attribute detected', ); $mech->get_ok('/request/edit/3'); # print_and_exit(); $mech->field( referral_source_id => 2 ); # this would be done automatically by ajax function: $mech->field( _location_name => 'The Surgery, Newtown, NT1 1NT'); $mech->field( error_code_id =>1 ); $mech->field( scope => 'one'); $mech->submit_form(); # print_and_exit(); has_edit_success(1); $mech->has_tag( td => 'The Surgery, Newtown, NT1 1NT', 'OK: new location detected', ); $mech->has_tag( span => 'Unknown', 'OK: unknown referrer detected', ); # print_and_exit(); $mech->content_lacks( 'Newtown General Infirmary', 'OK: old location not detected', ); $mech->content_lacks( 'Brown, CC', 'OK: old referrer not detected', ); # print_and_exit(); # have created new referrer_department, so check correct type: $mech->content_like( qr(span class="acronym"(\s+)title="General Medical Practice"), 'OK: changed hospital_department attribute correct', ); # check history: $mech->get_ok('/history/=/3'); # print_and_exit(); $mech->has_tag_like( td => qr(amended referral source \[Newtown General Infirmary -> The Surgery, Newtown, NT1 1NT\]), 'OK: expected history found', ); # print_and_exit(); } # change location and unit_number together: { $mech->get_ok('/request/edit/1'); # print_and_exit(); is( $mech->value('unit_number', 1), 'UNKNOWN', 'OK: expected unit number detected', ); # print_and_exit(); is( $mech->value('_location_name', 1), 'The Surgery, Newtown, NT1 1NT', 'OK: expected location detected', ); # print_and_exit(); $mech->field( referral_source_id => 6 ); $mech->field( unit_number => 54321 ); # this would be done automatically by ajax function: $mech->field( _location_name => 'Oldtown & Region Trust'); $mech->field( error_code_id =>1 ); $mech->field( scope => 'one'); $mech->submit_form(); # print_and_exit(); has_edit_success(1); # check new details: $mech->has_tag( td => 'Oldtown & Region Trust', 'OK: expected location value found' ); $mech->has_tag( td => 54321, 'OK: expected unit_number value found' ); $mech->has_tag_like( span => qr(Unknown), 'OK: expected referrer value found' ); # print_and_exit(); # check old location not found: $mech->content_lacks( 'The Surgery, Newtown, NT1 1NT', 'OK: old location value not found' ); # print_and_exit(); # check old referrer not found: $mech->content_lacks( 'Brown, CC', 'OK: old referrer not found' ); # print_and_exit(); # have created new referrer_department, so check correct type: $mech->content_like( qr(span class="acronym"(\s+)title="Unknown/other"), 'OK: changed hospital_department attribute correct', ); # check history: $mech->get_ok('/history/=/1'); # print_and_exit(); $mech->has_tag_like( td => qr(amended referral source \[The Surgery, Newtown, NT1 1NT -> Oldtown & Region Trust\]), 'OK: expected history found', ); $mech->has_tag_like( td => qr(amended unit number \[UNKNOWN -> 54321\]), 'OK: expected history found', ); # print_and_exit(); } # use back button & re-submit form (should not cause error): { $mech->get_ok('/request/edit/3'); # print_and_exit(); $mech->field( unit_number => 'ABC123'); $mech->field( error_code_id =>1 ); $mech->field( scope => 'one'); $mech->submit_form(); # print_and_exit(); has_edit_success(1); $mech->back(); # print_and_exit(); $mech->field( error_code_id =>1 ); # still need to add this $mech->submit_form(); # print_and_exit(); $mech->content_contains( get_messages('request_edit')->{edit_failed}, 'OK: no changes detected message present', ); } # emulate what happens when request data loaded in tab1 then update on another # record done in tab2, then tab1 update completed: { # load request/patient_case data into session (1st tab): $mech->get_ok('/request/edit/2'); # print_and_exit(); # submit data for a different request (emulating 2nd tab): $mech->post_ok('/request/update/3', { unit_number => 'ABC1234', error_code_id => 1 }); # print_and_exit(); $mech->content_contains( 'session data belongs to a different request', 'OK: incorrect request data', ); my $yr = $time_now->year - 2000; $mech->content_like( qr{expected 3/$yr, retrieved 2/$yr}, 'OK: expected vs retrieved request mismatch', ); # print_and_exit(); } # rfc447 - register new patient but stop before attaching request. Then re-commence # by selecting new patient and attempt to change its patient-case entry - link to # "delete case" should not be available as consequence is patient cannot be found # on registration search but also cannot be re-registered if it has an nhs number { my $dbix = get_dbix(); my %patient = ( last_name => 'plumb', first_name => 'peter', dob => '1901-01-01', gender => 'M', nhs_number => 3333333333, ); $dbix->insert('patients', \%patient); my $patient_id = get_last_insert_id('patients'); my %patient_case = ( patient_id => $patient_id, unit_number => 'ABC123', referral_source_id => 5, # Newtown District Hospital ); $dbix->insert('patient_case', \%patient_case); # select new patient in registration page: $mech->get_ok('/register/patient_search?name=plumb'); # print_and_exit(); $mech->follow_link_ok( { url_regex => qr(patient/select_patient), }, 'select new patient using link', ); # print_and_exit(); # select "edit patient case" link: $mech->follow_link_ok( { url_regex => qr(patient/edit_case), }, 'select patient case using link', ); # print_and_exit(); # does NOT have 'delete patient case' link: $mech->content_lacks( # have checked this fails when link *is* present: 'DELETE CASE', 'OK: delete patient case link not found', ); # p $mech->content; # add new patient_case for this patient and repeat edit patient case: $patient_case{referral_source_id} = 1; # Newtown General Infirmary $patient_case{unit_number} = 'ABC321'; $dbix->insert('patient_case', \%patient_case); # print_and_exit(); # short-cut to select patient-case: $mech->get_ok('/patient/select_patient/3'); # print_and_exit(); { # have 2 patient case links: my @links = $mech->find_all_links( url_regex => qr/edit_case/ ); is( scalar @links, 2, 'OK: found 2 links to edit patient case' ); } # follow either one $mech->follow_link_ok( { url_regex => qr/edit_case/ }, 'OK: followed link to edit patient case' ); # print_and_exit(); # does have 'delete patient case' link: $mech->content_contains( 'DELETE CASE', 'OK: delete patient case link found', ); # p $mech->content; # follow 'delete case' link: $mech->follow_link_ok( { url_regex => qr/delete_case/ }, 'OK: followed link to delete patient case' ); # print_and_exit(); $mech->text_contains('Confirm you really want to delete this case', 'OK: confirmation page loaded' ); $mech->tick('confirm_delete', 1); $mech->submit(); # print_and_exit(); { # now only 1 patient case: my @links = $mech->find_all_links( url_regex => qr/edit_case/ ); is( scalar @links, 1, 'OK: found 1 link to edit patient case' ); } # follow link: $mech->follow_link_ok( { url_regex => qr/edit_case/ }, 'OK: followed link to edit patient case' ); # print_and_exit(); # does NOT have 'delete patient case' link: $mech->content_lacks( 'DELETE CASE', 'OK: delete patient case link found', ); # p $mech->content; } { # change both location and unit number on existing patient case: $mech->get_ok('/patient/select_patient/3'); # print_and_exit(); $mech->follow_link_ok( { url_regex => qr/edit_case/ }, 'OK: followed link to edit patient case' ); # print_and_exit(); $mech->content_contains('ABC321', 'OK: expected location'); # in text box only $mech->text_contains('Newtown General Infirmary', 'OK: expected unit number'); $mech->field( unit_number => 'XYZ987' ); $mech->field( referral_source_id => 6 ); # Oldtown $mech->submit(); # print_and_exit(); $mech->text_contains('XYZ987', 'OK: new unit number found'); $mech->text_contains('Oldtown & Region Trust', 'OK: new location found'); } do_logout(); done_testing(185); sub check_edit { my $params = shift; my $name = $params->{name}; # check new unit_number loaded $mech->has_tag( td => $params->{new_unit_number}, 'OK: new unit_number loaded', ); # check old location still present: $mech->has_tag( td => $params->{location}, 'OK: original refereral_source still present', ); # print_and_exit(); # do reg lookup for same patient to check old record doesn't exist: $mech->get_ok("/register/patient_search?name=$name"); # print_and_exit(); # should only be 1 record: $mech->content_like( qr(Found 1 record matching name=$name), 'OK: only 1 matching record found', ); # print_content(); $mech->follow_link(text => 'Select', n => 1); # if ($name eq 'brown') { print_and_exit(); } # check it's the new record: $mech->has_tag( td => $params->{new_unit_number}, 'OK: new unit_number record found', ); # print_and_exit(); # old unit_number should be retained: if ($params->{old_val_retained}) { $mech->has_tag( td => $params->{old_unit_number}, 'OK: old unit_number record found', ); # print_and_exit(); } # old unit_number should be deleted: else { test_out( 'not ok 1 - foo' ); test_fail( +1 ); $mech->has_tag( td => $params->{old_unit_number}, 'foo' ); test_test( 'OK: old unit_number record not found' ); # print_and_exit(); } # print_content(); } sub check_previous { my $args = shift; # check we have 'previous record' option: $mech->content_like( qr(name="use_patient_case_id"(\s+)value="$args->{patient_case_id}"), 'OK: previous record case_id loaded' ); $mech->content_like( qr(value="$args->{unit_number}"), 'OK: previous record unit_number loaded' ); $mech->has_tag_like( span => qr(select), "OK: 'select' label present", ); # print_and_exit(); if ( my $count = $args->{record_count} ) { # check we have 'Apply change to': $mech->has_tag_like( span => qr(Apply change to), 'OK: scope options loaded', ); $mech->text_contains( "all $count records", 'OK: correct number of records', ); # print_and_exit(); } } sub has_edit_success { my $i = shift; my $msg = sprintf get_messages('request_edit')->{edit_success}, $i; $msg =~ s/([\(\)])/\\$1/g; # need to escape parens in edit_success msg or qr fails $mech->has_tag_like( p => qr(INFO: $msg), 'OK: edit action succeeded', ); } sub create_view { my $sql = <do( qq!CREATE OR REPLACE ALGORITHM=UNDEFINED SQL SECURITY DEFINER VIEW `test`.`_requests` AS $sql! ); }