Bug 43375: (QA follow-up) Add test coverage for form-data fallback in userinfo parsing

_get_data_and_patron() falls back to Mojo::Parameters form-data
parsing whenever $tx->res->json fails to decode the userinfo
response body. That branch was untested: all existing userinfo_url
subtests mock json() to return a hashref, so the fallback path was
never actually exercised.

This adds a subtest that mocks a genuine url-encoded response body
(json() returning undef) and confirms the fallback still maps data
and finds the matching patron correctly.

Test plan:
1. Run:
   $ ktd --shell
  k$ prove t/db_dependent/Koha/Auth/Client/OAuth.t
=> SUCCESS: All 6 subtests pass, including the new fallback-path test
2. Sign off

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This commit is contained in:
Martin Renvoize 2026-09-16 08:38:51 +01:00 committed by Pedro Amorim
parent 8b1e8f80ba
commit 255eeaf4f6
No known key found for this signature in database
GPG Key ID: 06B75BA7F3894D55
1 changed files with 88 additions and 1 deletions

View File

@ -19,7 +19,7 @@
use Modern::Perl;
use Test::More tests => 5;
use Test::More tests => 6;
use Test::MockModule;
use Test::NoWarnings;
@ -355,3 +355,90 @@ subtest '_get_data_and_patron() userinfo_url with extra Content-Type params (bug
$schema->storage->txn_rollback;
};
subtest '_get_data_and_patron() userinfo_url falls back to form-encoded body (bug 43375)' => sub {
plan tests => 2;
$schema->storage->txn_begin;
my $client = Koha::Auth::Client::OAuth->new;
# Create test patron
my $patron = $builder->build_object(
{
class => 'Koha::Patrons',
value => { email => 'formuser@example.com' }
}
);
# Create provider with email matchpoint
my $provider = $builder->build_object(
{
class => 'Koha::Auth::Identity::Providers',
value => {
matchpoint => 'email',
mapping => encode_json(
{
email => 'mail',
firstname => 'given_name',
}
)
}
}
);
# Mock UserAgent - simulate a provider that returns a genuine
# url-encoded body, so res->json fails to decode (returns undef)
# and _get_data_and_patron must fall back to Mojo::Parameters
my $ua_mock = Test::MockModule->new('Mojo::UserAgent');
my $tx_mock = Test::MockModule->new('Mojo::Transaction::HTTP');
my $res_mock = Test::MockModule->new('Mojo::Message::Response');
my $headers_mock = Test::MockModule->new('Mojo::Headers');
$headers_mock->mock( 'content_type', sub { 'application/x-www-form-urlencoded' } );
$res_mock->mock( 'code', sub { '200' } );
$res_mock->mock( 'json', sub { undef } );
$res_mock->mock( 'body', sub { 'mail=formuser%40example.com&given_name=Form' } );
$res_mock->mock(
'headers',
sub {
my $headers = {};
bless $headers, 'Mojo::Headers';
return $headers;
}
);
$tx_mock->mock(
'res',
sub {
my $res = {};
bless $res, 'Mojo::Message::Response';
return $res;
}
);
$ua_mock->mock(
'get',
sub {
my $tx = {};
bless $tx, 'Mojo::Transaction::HTTP';
return $tx;
}
);
my $data = { access_token => 'form_token' };
my $config = { userinfo_url => 'https://provider.example.com/userinfo' };
my ( $mapped_data, $found_patron ) = $client->_get_data_and_patron(
{
provider => $provider,
data => $data,
config => $config
}
);
is( $mapped_data->{email}, 'formuser@example.com', 'Email mapped from url-encoded fallback body' );
is( $found_patron->id, $patron->id, 'Patron found via form-data fallback parsing' );
$schema->storage->txn_rollback;
};