Bugzilla – Attachment 185031 Details for
Bug 40391
EDI: Add support for GIR:LSL field
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 40391: Add unit tests for GIR:LSL support in EDI
Bug-40391-Add-unit-tests-for-GIRLSL-support-in-EDI.patch (text/plain), 12.11 KB, created by
Martin Renvoize (ashimema)
on 2025-08-01 14:44:33 UTC
(
hide
)
Description:
Bug 40391: Add unit tests for GIR:LSL support in EDI
Filename:
MIME Type:
Creator:
Martin Renvoize (ashimema)
Created:
2025-08-01 14:44:33 UTC
Size:
12.11 KB
patch
obsolete
>From 39c1ffdc117b55b1533d404dcfd198053a18780d Mon Sep 17 00:00:00 2001 >From: Martin Renvoize <martin.renvoize@openfifth.co.uk> >Date: Fri, 1 Aug 2025 14:29:39 +0000 >Subject: [PATCH] Bug 40391: Add unit tests for GIR:LSL support in EDI > >This adds unit tests for adding supprt for the new LSL field support: > >- GIR segment extraction tests in t/Edifact.t for sub_location_code field mapping >- Validation function tests in t/db_dependent/Koha/EDI.t for location/collection code validation >- gir_segments generation tests in t/db_dependent/Koha/Edifact/Order.t for preference handling > >Tests cover: >- LSL field extraction from GIR segments alongside existing LSQ fields >- Independent LSQ/LSL preference mapping (location/ccode/empty combinations) >- Validation of location and collection codes against authorised values >- Error handling and message formatting >- Backwards compatibility with existing LSQ-only configurations >- Edge cases including missing data and invalid preference values > >Test plan: >1. Apply this patch >2. Run: prove t/Edifact.t > - Should pass with 8 new LSL-related tests included >3. Run: prove t/db_dependent/Koha/EDI.t > - Should pass with 16 new validation function tests >4. Run: prove t/db_dependent/Koha/Edifact/Order.t > - Should pass with 14 new gir_segments LSL/LSQ tests >5. Verify all existing tests still pass - no regression >--- > t/Edifact.t | 47 ++++++++++- > t/db_dependent/Koha/EDI.t | 116 +++++++++++++++++++++++++++- > t/db_dependent/Koha/Edifact/Order.t | 99 +++++++++++++++++++++++- > 3 files changed, 259 insertions(+), 3 deletions(-) > >diff --git a/t/Edifact.t b/t/Edifact.t >index 9dec48c28f7..fd6353639ec 100755 >--- a/t/Edifact.t >+++ b/t/Edifact.t >@@ -4,7 +4,7 @@ use warnings; > use FindBin qw( $Bin ); > > use Test::NoWarnings; >-use Test::More tests => 42; >+use Test::More tests => 49; > use Koha::EDI; > > BEGIN { use_ok('Koha::Edifact') } >@@ -139,3 +139,48 @@ is( $dp, 9.0, 'Discount calculated with discount = 0' ); > > $dp = Koha::EDI::_discounted_price( 0.0, 9, 8.0 ); > is( $dp, 8.0, 'Discount overridden by incoming calculated value' ); >+ >+# Test LSL (Library Sub-Location) field extraction from GIR segments >+my $mock_line_data = { >+ GIR => [ >+ { >+ copy => '001', >+ sub_location_code => 'FICTION', # LSL field >+ sequence_code => 'ADULT', # LSQ field >+ branch => 'MAIN' >+ }, >+ { >+ copy => '002', >+ sub_location_code => 'REFERENCE', # LSL field >+ branch => 'BRANCH2' >+ >+ # sequence_code missing for this item >+ } >+ ] >+}; >+ >+my $mock_line = bless $mock_line_data, 'Koha::Edifact::Line'; >+ >+# Test LSL field access via girfield method >+$y = $mock_line->girfield('sub_location_code'); >+is( $y, 'FICTION', 'LSL field (sub_location_code) returned for first occurrence' ); >+ >+$y = $mock_line->girfield( 'sub_location_code', 0 ); >+is( $y, 'FICTION', 'LSL field returned for explicit occurrence 0' ); >+ >+$y = $mock_line->girfield( 'sub_location_code', 1 ); >+is( $y, 'REFERENCE', 'LSL field returned for occurrence 1' ); >+ >+$y = $mock_line->girfield( 'sub_location_code', 2 ); >+is( $y, undef, 'LSL field returns undef for non-existent occurrence' ); >+ >+# Test that both LSL and LSQ can coexist >+$y = $mock_line->girfield( 'sequence_code', 0 ); >+is( $y, 'ADULT', 'LSQ field still works when LSL is present' ); >+ >+$y = $mock_line->girfield( 'sequence_code', 1 ); >+is( $y, undef, 'LSQ field correctly returns undef when not present for occurrence' ); >+ >+# Test LSL field when LSQ is missing >+$y = $mock_line->girfield( 'sub_location_code', 1 ); >+is( $y, 'REFERENCE', 'LSL field works correctly when LSQ is missing for that occurrence' ); >diff --git a/t/db_dependent/Koha/EDI.t b/t/db_dependent/Koha/EDI.t >index d136b6f08f6..26bfa5f71e5 100755 >--- a/t/db_dependent/Koha/EDI.t >+++ b/t/db_dependent/Koha/EDI.t >@@ -21,7 +21,7 @@ use Modern::Perl; > use FindBin qw( $Bin ); > > use Test::NoWarnings; >-use Test::More tests => 5; >+use Test::More tests => 6; > use Test::MockModule; > > use t::lib::Mocks; >@@ -976,3 +976,117 @@ subtest 'create_edi_order_logging' => sub { > > $schema->storage->txn_rollback; > }; >+ >+subtest 'LSL and LSQ validation functions' => sub { >+ plan tests => 16; >+ >+ $schema->storage->txn_begin; >+ >+ # Mock quote message object for testing >+ { >+ >+ package MockQuoteMessage; >+ >+ sub new { >+ my $class = shift; >+ return bless { errors => [] }, $class; >+ } >+ >+ sub add_to_edifact_errors { >+ my ( $self, $error ) = @_; >+ push @{ $self->{errors} }, $error; >+ } >+ } >+ >+ # Create test authorised values >+ my $loc_av = $builder->build( >+ { >+ source => 'AuthorisedValue', >+ value => { >+ category => 'LOC', >+ authorised_value => 'FICTION', >+ lib => 'Fiction Section' >+ } >+ } >+ ); >+ >+ my $ccode_av = $builder->build( >+ { >+ source => 'AuthorisedValue', >+ value => { >+ category => 'CCODE', >+ authorised_value => 'ADULT', >+ lib => 'Adult Collection' >+ } >+ } >+ ); >+ >+ my $quote_message = MockQuoteMessage->new(); >+ >+ # Test valid location code validation >+ ok( >+ Koha::EDI::_validate_location_code( 'FICTION', $quote_message ), >+ 'Valid location code passes validation' >+ ); >+ is( scalar @{ $quote_message->{errors} }, 0, 'No errors for valid location code' ); >+ >+ # Test invalid location code validation >+ ok( >+ !Koha::EDI::_validate_location_code( 'INVALID_LOC', $quote_message ), >+ 'Invalid location code fails validation' >+ ); >+ is( scalar @{ $quote_message->{errors} }, 1, 'One error logged for invalid location code' ); >+ like( >+ $quote_message->{errors}->[0]->{details}, qr/Invalid location code 'INVALID_LOC'/, >+ 'Error details contain correct location code' >+ ); >+ >+ # Reset errors for collection code tests >+ $quote_message = MockQuoteMessage->new(); >+ >+ # Test valid collection code validation >+ ok( >+ Koha::EDI::_validate_collection_code( 'ADULT', $quote_message ), >+ 'Valid collection code passes validation' >+ ); >+ is( scalar @{ $quote_message->{errors} }, 0, 'No errors for valid collection code' ); >+ >+ # Test invalid collection code validation >+ ok( >+ !Koha::EDI::_validate_collection_code( 'INVALID_CCODE', $quote_message ), >+ 'Invalid collection code fails validation' >+ ); >+ is( scalar @{ $quote_message->{errors} }, 1, 'One error logged for invalid collection code' ); >+ like( >+ $quote_message->{errors}->[0]->{details}, qr/Invalid collection code 'INVALID_CCODE'/, >+ 'Error details contain correct collection code' >+ ); >+ >+ # Test empty/null handling >+ $quote_message = MockQuoteMessage->new(); >+ ok( >+ Koha::EDI::_validate_location_code( '', $quote_message ), >+ 'Empty location code passes validation' >+ ); >+ ok( >+ Koha::EDI::_validate_location_code( undef, $quote_message ), >+ 'Undefined location code passes validation' >+ ); >+ ok( >+ Koha::EDI::_validate_collection_code( '', $quote_message ), >+ 'Empty collection code passes validation' >+ ); >+ ok( >+ Koha::EDI::_validate_collection_code( undef, $quote_message ), >+ 'Undefined collection code passes validation' >+ ); >+ is( scalar @{ $quote_message->{errors} }, 0, 'No errors for empty/undefined values' ); >+ >+ # Test error message format >+ $quote_message = MockQuoteMessage->new(); >+ Koha::EDI::_validate_location_code( 'TEST_ERROR', $quote_message ); >+ my $error = $quote_message->{errors}->[0]; >+ is( $error->{section}, 'GIR+LSQ/LSL validation', 'Error has correct section identifier' ); >+ >+ $schema->storage->txn_rollback; >+}; >diff --git a/t/db_dependent/Koha/Edifact/Order.t b/t/db_dependent/Koha/Edifact/Order.t >index 3a565a93bff..f520179fa24 100755 >--- a/t/db_dependent/Koha/Edifact/Order.t >+++ b/t/db_dependent/Koha/Edifact/Order.t >@@ -20,7 +20,7 @@ > use Modern::Perl; > > use Test::NoWarnings; >-use Test::More tests => 4; >+use Test::More tests => 5; > > use Koha::Edifact::Order; > >@@ -280,3 +280,100 @@ subtest 'filename() tests' => sub { > > $schema->storage->txn_rollback; > }; >+ >+subtest 'gir_segments() with LSL and LSQ preferences' => sub { >+ plan tests => 14; >+ >+ $schema->storage->txn_begin; >+ >+ # Test LSL and LSQ preferences >+ t::lib::Mocks::mock_preference( 'EdifactLSQ', 'location' ); >+ t::lib::Mocks::mock_preference( 'EdifactLSL', 'ccode' ); >+ >+ # Create test items with both location and ccode >+ my @test_items = ( >+ { >+ branchcode => 'BRANCH1', >+ itype => 'BOOK', >+ itemcallnumber => 'CALL1', >+ location => 'FICTION', # Will be used for LSQ >+ ccode => 'ADULT', # Will be used for LSL >+ }, >+ { >+ branchcode => 'BRANCH2', >+ itype => 'DVD', >+ itemcallnumber => 'CALL2', >+ location => 'MEDIA', # Will be used for LSQ >+ ccode => 'CHILD', # Will be used for LSL >+ } >+ ); >+ >+ my $params = { >+ ol_fields => { budget_code => 'FUND123' }, >+ items => \@test_items >+ }; >+ >+ my @segments = Koha::Edifact::Order::gir_segments($params); >+ >+ ok( scalar @segments >= 2, 'At least two segments created for two items' ); >+ >+ # Check first item's GIR segment (segments are strings in EDI format) >+ my $first_gir = $segments[0]; >+ ok( $first_gir, 'First segment exists' ); >+ >+ # Check that the segment contains expected data >+ like( $first_gir, qr/GIR/, 'Segment contains GIR tag' ); >+ like( $first_gir, qr/FUND123:LFN/, 'Budget code included in first segment' ); >+ like( $first_gir, qr/BRANCH1:LLO/, 'Branch code included in first segment' ); >+ like( $first_gir, qr/BOOK:LST/, 'Item type included in first segment' ); >+ like( $first_gir, qr/FICTION:LSQ/, 'LSQ field contains location value' ); >+ like( $first_gir, qr/ADULT:LSL/, 'LSL field contains collection code value' ); >+ >+ # Test reversed preferences >+ t::lib::Mocks::mock_preference( 'EdifactLSQ', 'ccode' ); # LSQ -> collection >+ t::lib::Mocks::mock_preference( 'EdifactLSL', 'location' ); # LSL -> location >+ >+ my @test_items_rev = ( >+ { >+ branchcode => 'BRANCH3', >+ itype => 'BOOK', >+ itemcallnumber => 'CALL3', >+ location => 'REFERENCE', # Will be used for LSL >+ ccode => 'RARE', # Will be used for LSQ >+ } >+ ); >+ >+ my $params_rev = { >+ ol_fields => { budget_code => 'FUND456' }, >+ items => \@test_items_rev >+ }; >+ >+ @segments = Koha::Edifact::Order::gir_segments($params_rev); >+ my $gir_rev = $segments[0]; >+ >+ # Check that the segment contains expected reversed mappings >+ like( $gir_rev, qr/RARE:LSQ/, 'LSQ field contains collection code when preference is ccode' ); >+ like( $gir_rev, qr/REFERENCE:LSL/, 'LSL field contains location when preference is location' ); >+ >+ # Test with one preference empty >+ t::lib::Mocks::mock_preference( 'EdifactLSQ', 'location' ); >+ t::lib::Mocks::mock_preference( 'EdifactLSL', '' ); # Empty = ignore >+ >+ @segments = Koha::Edifact::Order::gir_segments($params); >+ my $gir_partial = $segments[0]; >+ >+ like( $gir_partial, qr/FICTION:LSQ/, 'LSQ field included when preference is set' ); >+ unlike( $gir_partial, qr/:LSL/, 'LSL field not included when preference is empty' ); >+ >+ # Test with both preferences empty >+ t::lib::Mocks::mock_preference( 'EdifactLSQ', '' ); >+ t::lib::Mocks::mock_preference( 'EdifactLSL', '' ); >+ >+ @segments = Koha::Edifact::Order::gir_segments($params); >+ my $gir_empty = $segments[0]; >+ >+ unlike( $gir_empty, qr/:LSQ/, 'LSQ field not included when preference is empty' ); >+ unlike( $gir_empty, qr/:LSL/, 'LSL field not included when preference is empty' ); >+ >+ $schema->storage->txn_rollback; >+}; >-- >2.50.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 40391
:
185031
|
185032
|
185233
|
185234