View | Details | Raw Unified | Return to bug 41076
Collapse All | Expand All

(-)a/C4/Auth.pm (-2 / +2 lines)
Lines 1268-1274 sub checkauth { Link Here
1268
                            : Koha::Cash::Registers->search(
1268
                            : Koha::Cash::Registers->search(
1269
                            { branch => $branchcode, branch_default => 1 },
1269
                            { branch => $branchcode, branch_default => 1 },
1270
                            { rows   => 1 }
1270
                            { rows   => 1 }
1271
                        )->single;
1271
                            )->single;
1272
                        $register_id   = $register->id   if ($register);
1272
                        $register_id   = $register->id   if ($register);
1273
                        $register_name = $register->name if ($register);
1273
                        $register_name = $register->name if ($register);
1274
                    }
1274
                    }
Lines 1478-1484 sub checkauth { Link Here
1478
    # get the inputs from the incoming query
1478
    # get the inputs from the incoming query
1479
    my @inputs          = ();
1479
    my @inputs          = ();
1480
    my @inputs_to_clean = qw( login_userid login_password ticket logout.x otp_token );
1480
    my @inputs_to_clean = qw( login_userid login_password ticket logout.x otp_token );
1481
    foreach my $name ( param $query) {
1481
    foreach my $name ( param $query ) {
1482
        next if grep { $name eq $_ } @inputs_to_clean;
1482
        next if grep { $name eq $_ } @inputs_to_clean;
1483
        my @value = $query->multi_param($name);
1483
        my @value = $query->multi_param($name);
1484
        push @inputs, { name => $name, value => $_ } for @value;
1484
        push @inputs, { name => $name, value => $_ } for @value;
(-)a/C4/Auth_with_shibboleth.pm (-1 / +1 lines)
Lines 158-164 sub _autocreate { Link Here
158
                module      => 'members',
158
                module      => 'members',
159
                letter_code => 'WELCOME',
159
                letter_code => 'WELCOME',
160
                branchcode  => $patron->branchcode,
160
                branchcode  => $patron->branchcode,
161
                ,
161
162
                lang   => $patron->lang || 'default',
162
                lang   => $patron->lang || 'default',
163
                tables => {
163
                tables => {
164
                    'branches'  => $patron->branchcode,
164
                    'branches'  => $patron->branchcode,
(-)a/C4/AuthoritiesMarc.pm (-1 / +1 lines)
Lines 532-538 ORDER BY tagfield, display_order, tagsubfield" Link Here
532
532
533
    while (
533
    while (
534
        (
534
        (
535
            $tag,           $subfield,     $liblibrarian,,    $libopac, $tab,
535
            $tag,           $subfield,     $liblibrarian,     $libopac, $tab,
536
            $mandatory,     $repeatable,   $authorised_value, $authtypecode,
536
            $mandatory,     $repeatable,   $authorised_value, $authtypecode,
537
            $value_builder, $kohafield,    $seealso,          $hidden,
537
            $value_builder, $kohafield,    $seealso,          $hidden,
538
            $isurl,         $defaultvalue, $display_order
538
            $isurl,         $defaultvalue, $display_order
(-)a/C4/Biblio.pm (-1 / +1 lines)
Lines 1565-1571 sub GetAuthorisedValueDesc { Link Here
1565
                    Koha::AuthorisedValues->search(
1565
                    Koha::AuthorisedValues->search(
1566
                    { category => $category },
1566
                    { category => $category },
1567
                    { columns  => [ 'authorised_value', 'lib_opac', 'lib' ] }
1567
                    { columns  => [ 'authorised_value', 'lib_opac', 'lib' ] }
1568
                )->as_list
1568
                    )->as_list
1569
            };
1569
            };
1570
            $cache->set_in_cache( $cache_key, $av_descriptions );
1570
            $cache->set_in_cache( $cache_key, $av_descriptions );
1571
        }
1571
        }
(-)a/C4/Circulation.pm (-1 / +1 lines)
Lines 3300-3306 sub CanBookBeRenewed { Link Here
3300
                        unless CanItemBeReserved(
3300
                        unless CanItemBeReserved(
3301
                        $patron_with_reserve, $other_item, undef,
3301
                        $patron_with_reserve, $other_item, undef,
3302
                        { ignore_hold_counts => 1 }
3302
                        { ignore_hold_counts => 1 }
3303
                    )->{status} eq 'OK';
3303
                        )->{status} eq 'OK';
3304
3304
3305
                    # NOTE: At checkin we call 'CheckReserves' which checks hold 'policy'
3305
                    # NOTE: At checkin we call 'CheckReserves' which checks hold 'policy'
3306
                    # CanItemBeReserved checks 'rules' and 'policies' which means
3306
                    # CanItemBeReserved checks 'rules' and 'policies' which means
(-)a/C4/InstallAuth.pm (-1 / +1 lines)
Lines 365-371 sub checkauth { Link Here
365
    # else we have a problem...
365
    # else we have a problem...
366
    # get the inputs from the incoming query
366
    # get the inputs from the incoming query
367
    my @inputs = ();
367
    my @inputs = ();
368
    foreach my $name ( param $query) {
368
    foreach my $name ( param $query ) {
369
        (next) if ( $name eq 'userid' || $name eq 'password' );
369
        (next) if ( $name eq 'userid' || $name eq 'password' );
370
        my $value = $query->param($name);
370
        my $value = $query->param($name);
371
        push @inputs, { name => $name, value => $value };
371
        push @inputs, { name => $name, value => $value };
(-)a/C4/Letters.pm (-3 / +3 lines)
Lines 217-224 sub GetLettersAvailableForALibrary { Link Here
217
    }
217
    }
218
218
219
    return [
219
    return [
220
        map      { $letters{$_} }
220
        map  { $letters{$_} }
221
            sort { $letters{$a}->{name} cmp $letters{$b}->{name} }
221
        sort { $letters{$a}->{name} cmp $letters{$b}->{name} }
222
            keys %letters
222
            keys %letters
223
    ];
223
    ];
224
224
Lines 1214-1220 sub GetQueuedMessages { Link Here
1214
    my $params = shift;
1214
    my $params = shift;
1215
1215
1216
    my $dbh       = C4::Context->dbh();
1216
    my $dbh       = C4::Context->dbh();
1217
    my $statement = << 'ENDSQL';
1217
    my $statement = <<'ENDSQL';
1218
SELECT message_id, borrowernumber, subject, content, message_transport_type, status, time_queued, updated_on, failure_code, from_address, to_address, cc_address
1218
SELECT message_id, borrowernumber, subject, content, message_transport_type, status, time_queued, updated_on, failure_code, from_address, to_address, cc_address
1219
FROM message_queue
1219
FROM message_queue
1220
ENDSQL
1220
ENDSQL
(-)a/Koha/Item.pm (-5 / +6 lines)
Lines 179-185 sub store { Link Here
179
179
180
            # If the field has changed otherwise, we much update
180
            # If the field has changed otherwise, we much update
181
            # the 'on' field
181
            # the 'on' field
182
            elsif (exists $updated_columns{$field}
182
            elsif ( exists $updated_columns{$field}
183
                && $updated_columns{$field}
183
                && $updated_columns{$field}
184
                && !$pre_mod_item->$field )
184
                && !$pre_mod_item->$field )
185
            {
185
            {
Lines 376-382 sub safe_to_delete { Link Here
376
        {
376
        {
377
            itemnumber => undef,
377
            itemnumber => undef,
378
        }
378
        }
379
    )->count;
379
        )->count;
380
380
381
    if ($error) {
381
    if ($error) {
382
        return Koha::Result::Boolean->new(0)->add_message( { message => $error } );
382
        return Koha::Result::Boolean->new(0)->add_message( { message => $error } );
Lines 1455-1462 sub columns_to_str { Link Here
1455
              $subfield
1455
              $subfield
1456
            ? $subfield->{authorised_value}
1456
            ? $subfield->{authorised_value}
1457
                ? C4::Biblio::GetAuthorisedValueDesc(
1457
                ? C4::Biblio::GetAuthorisedValueDesc(
1458
                    $itemtagfield,
1458
                $itemtagfield,
1459
                    $subfield->{tagsubfield}, $value, '', $tagslib
1459
                $subfield->{tagsubfield}, $value, '', $tagslib
1460
                )
1460
                )
1461
                : $value
1461
                : $value
1462
            : $value;
1462
            : $value;
Lines 1680-1686 sub _set_found_trigger { Link Here
1680
                            if ($lost_fee_payment) {
1680
                            if ($lost_fee_payment) {
1681
                                my $today = dt_from_string();
1681
                                my $today = dt_from_string();
1682
                                my $payment_age_in_days =
1682
                                my $payment_age_in_days =
1683
                                    dt_from_string( $lost_fee_payment->created_on )->delta_days($today)
1683
                                    dt_from_string( $lost_fee_payment->created_on )
1684
                                    ->delta_days($today)
1684
                                    ->in_units('days');
1685
                                    ->in_units('days');
1685
                                if ( $payment_age_in_days > $no_refund_if_lost_fee_paid_age ) {
1686
                                if ( $payment_age_in_days > $no_refund_if_lost_fee_paid_age ) {
1686
                                    $self->add_message(
1687
                                    $self->add_message(
(-)a/Koha/List/Patron.pm (-2 / +5 lines)
Lines 216-223 sub DelPatronsFromList { Link Here
216
216
217
    return unless ( $list && $patron_list_patrons );
217
    return unless ( $list && $patron_list_patrons );
218
218
219
    return Koha::Database->new()->schema()->resultset('PatronListPatron')
219
    return Koha::Database->new()
220
        ->search( { patron_list_patron_id => { 'IN' => $patron_list_patrons } } )->delete();
220
        ->schema()
221
        ->resultset('PatronListPatron')
222
        ->search( { patron_list_patron_id => { 'IN' => $patron_list_patrons } } )
223
        ->delete();
221
}
224
}
222
225
223
=head1 AUTHOR
226
=head1 AUTHOR
(-)a/Koha/Object/Limit/Library.pm (-2 / +4 lines)
Lines 78-85 It returns undef if no library limits defined. Link Here
78
sub get_library_limits {
78
sub get_library_limits {
79
    my ($self) = @_;
79
    my ($self) = @_;
80
80
81
    my @branchcodes = $self->_library_limit_rs->search( { $self->_library_limits->{id} => $self->id } )
81
    my @branchcodes =
82
        ->get_column( $self->_library_limits->{library} )->all();
82
        $self->_library_limit_rs->search( { $self->_library_limits->{id} => $self->id } )
83
        ->get_column( $self->_library_limits->{library} )
84
        ->all();
83
85
84
    return unless @branchcodes;
86
    return unless @branchcodes;
85
87
(-)a/Koha/Patron.pm (-1 / +1 lines)
Lines 1113-1119 sub set_password { Link Here
1113
                    module      => 'members',
1113
                    module      => 'members',
1114
                    letter_code => 'PASSWORD_CHANGE',
1114
                    letter_code => 'PASSWORD_CHANGE',
1115
                    branchcode  => $self_from_storage->branchcode,
1115
                    branchcode  => $self_from_storage->branchcode,
1116
                    ,
1116
1117
                    lang   => $self_from_storage->lang || 'default',
1117
                    lang   => $self_from_storage->lang || 'default',
1118
                    tables => {
1118
                    tables => {
1119
                        'branches'  => $self_from_storage->branchcode,
1119
                        'branches'  => $self_from_storage->branchcode,
(-)a/Koha/Patrons/Import.pm (-1 / +1 lines)
Lines 521-527 LINE: while ( my $borrowerline = <$handle> ) { Link Here
521
                    my $letter = GetPreparedLetter(
521
                    my $letter = GetPreparedLetter(
522
                        module      => 'members',
522
                        module      => 'members',
523
                        letter_code => 'WELCOME',
523
                        letter_code => 'WELCOME',
524
                        branchcode  => $patron->branchcode,,
524
                        branchcode  => $patron->branchcode,
525
                        lang        => $patron->lang || 'default',
525
                        lang        => $patron->lang || 'default',
526
                        tables      => {
526
                        tables      => {
527
                            'branches'  => $patron->branchcode,
527
                            'branches'  => $patron->branchcode,
(-)a/Koha/Plugins.pm (-2 / +2 lines)
Lines 235-242 sub GetPlugins { Link Here
235
                    {
235
                    {
236
                        enable_plugins => $self->{'enable_plugins'}
236
                        enable_plugins => $self->{'enable_plugins'}
237
237
238
                            # loads even if plugins are disabled
238
                        # loads even if plugins are disabled
239
                            # FIXME: is this for testing without bothering to mock config?
239
                        # FIXME: is this for testing without bothering to mock config?
240
                    }
240
                    }
241
                );
241
                );
242
            } catch {
242
            } catch {
(-)a/Koha/Policy/Patrons/Cardnumber.pm (-1 / +1 lines)
Lines 60-66 sub is_valid { Link Here
60
            cardnumber => $cardnumber,
60
            cardnumber => $cardnumber,
61
            ( $patron ? ( borrowernumber => { '!=' => $patron->borrowernumber } ) : () )
61
            ( $patron ? ( borrowernumber => { '!=' => $patron->borrowernumber } ) : () )
62
        }
62
        }
63
    )->count;
63
        )->count;
64
64
65
    my ( $min_length, $max_length ) = $class->get_valid_length();
65
    my ( $min_length, $max_length ) = $class->get_valid_length();
66
    return Koha::Result::Boolean->new(0)->add_message( { message => "invalid_length" } )
66
    return Koha::Result::Boolean->new(0)->add_message( { message => "invalid_length" } )
(-)a/Koha/REST/V1/Suggestions.pm (-2 / +4 lines)
Lines 102-109 sub add { Link Here
102
102
103
                if ( $max_total and $days_range ) {
103
                if ( $max_total and $days_range ) {
104
104
105
                    my $total = Koha::Suggestions->search( { suggestedby => $body->{suggested_by} } )
105
                    my $total =
106
                        ->filter_by_suggested_days_range($days_range)->count;
106
                        Koha::Suggestions->search( { suggestedby => $body->{suggested_by} } )
107
                        ->filter_by_suggested_days_range($days_range)
108
                        ->count;
107
109
108
                    if ( $total >= $max_total ) {
110
                    if ( $total >= $max_total ) {
109
                        return $c->render(
111
                        return $c->render(
(-)a/Koha/Schema/Loader/mysql.pm (-1 / +1 lines)
Lines 43-49 sub _extra_column_info { Link Here
43
        $extra_info{extra}{list} = $dbi_info->{mysql_values};
43
        $extra_info{extra}{list} = $dbi_info->{mysql_values};
44
    }
44
    }
45
    if (
45
    if (
46
        ( not blessed $dbi_info)    # isa $sth
46
        ( not blessed $dbi_info )    # isa $sth
47
        && lc( $dbi_info->{COLUMN_DEF} ) =~ m/^current_timestamp/
47
        && lc( $dbi_info->{COLUMN_DEF} ) =~ m/^current_timestamp/
48
        && lc( $dbi_info->{mysql_type_name} ) eq 'timestamp'
48
        && lc( $dbi_info->{mysql_type_name} ) eq 'timestamp'
49
        )
49
        )
(-)a/Koha/Subscription.pm (-1 / +3 lines)
Lines 74-80 sub subscribers { Link Here
74
    my ($self) = @_;
74
    my ($self) = @_;
75
    my $schema = Koha::Database->new->schema;
75
    my $schema = Koha::Database->new->schema;
76
    my @borrowernumbers =
76
    my @borrowernumbers =
77
        $schema->resultset('Alert')->search( { externalid => $self->subscriptionid } )->get_column('borrowernumber')
77
        $schema->resultset('Alert')
78
        ->search( { externalid => $self->subscriptionid } )
79
        ->get_column('borrowernumber')
78
        ->all;
80
        ->all;
79
    return Koha::Patrons->search( { borrowernumber => { -in => \@borrowernumbers } } );
81
    return Koha::Patrons->search( { borrowernumber => { -in => \@borrowernumbers } } );
80
}
82
}
(-)a/Koha/Suggestion.pm (-1 / +1 lines)
Lines 61-67 sub store { Link Here
61
            category         => 'SUGGEST_STATUS',
61
            category         => 'SUGGEST_STATUS',
62
            authorised_value => $self->STATUS
62
            authorised_value => $self->STATUS
63
        }
63
        }
64
    )->count;
64
        )->count;
65
65
66
    $self->branchcode(undef) if defined $self->branchcode && $self->branchcode eq '';
66
    $self->branchcode(undef) if defined $self->branchcode && $self->branchcode eq '';
67
    unless ( $self->suggesteddate() ) {
67
    unless ( $self->suggesteddate() ) {
(-)a/Koha/Uploader.pm (-1 / +1 lines)
Lines 138-144 sub count { Link Here
138
138
139
sub result {
139
sub result {
140
    my ($self) = @_;
140
    my ($self) = @_;
141
    my @a      = map { $self->{files}->{$_}->{id} }
141
    my @a = map { $self->{files}->{$_}->{id} }
142
        grep { !exists $self->{files}->{$_}->{errcode} }
142
        grep { !exists $self->{files}->{$_}->{errcode} }
143
        keys %{ $self->{files} };
143
        keys %{ $self->{files} };
144
    return @a ? ( join ',', @a ) : undef;
144
    return @a ? ( join ',', @a ) : undef;
(-)a/Makefile.PL (-14 / +14 lines)
Lines 340-347 my $target_map = { Link Here
340
    './members'                                        => 'INTRANET_CGI_DIR',
340
    './members'                                        => 'INTRANET_CGI_DIR',
341
    './misc'                                           => { target => 'SCRIPT_NONDEV_DIR', trimdir => -1 },
341
    './misc'                                           => { target => 'SCRIPT_NONDEV_DIR', trimdir => -1 },
342
    './misc/bin'                                       => { target => 'SCRIPT_DIR',        trimdir => -1 },
342
    './misc/bin'                                       => { target => 'SCRIPT_DIR',        trimdir => -1 },
343
    './misc/release_notes'                             => { target => 'DOC_DIR',           trimdir => 2 },
343
    './misc/release_notes'                             => { target => 'DOC_DIR',           trimdir =>  2 },
344
    './misc/translator'                                => { target => 'MISC_DIR',          trimdir => 2 },
344
    './misc/translator'                                => { target => 'MISC_DIR',          trimdir =>  2 },
345
    './misc/koha-install-log'                          => { target => 'MISC_DIR',          trimdir => -1 },
345
    './misc/koha-install-log'                          => { target => 'MISC_DIR',          trimdir => -1 },
346
    './misc/installer_devel_notes'                     => 'NONE',
346
    './misc/installer_devel_notes'                     => 'NONE',
347
    './opac'                                           => 'OPAC_CGI_DIR',
347
    './opac'                                           => 'OPAC_CGI_DIR',
Lines 367-384 my $target_map = { Link Here
367
    './skel/var/log/koha'                              => { target => 'LOG_DIR',        trimdir => -1 },
367
    './skel/var/log/koha'                              => { target => 'LOG_DIR',        trimdir => -1 },
368
    './skel/var/spool/koha'                            => { target => 'BACKUP_DIR',     trimdir => -1 },
368
    './skel/var/spool/koha'                            => { target => 'BACKUP_DIR',     trimdir => -1 },
369
    './skel/var/run/koha/zebradb'                      => { target => 'ZEBRA_RUN_DIR',  trimdir => -1 },
369
    './skel/var/run/koha/zebradb'                      => { target => 'ZEBRA_RUN_DIR',  trimdir => -1 },
370
    './skel/var/lock/koha/zebradb/authorities'         => { target => 'ZEBRA_LOCK_DIR', trimdir => 6 },
370
    './skel/var/lock/koha/zebradb/authorities'         => { target => 'ZEBRA_LOCK_DIR', trimdir =>  6 },
371
    './skel/var/lib/koha/zebradb/authorities/key'      => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
371
    './skel/var/lib/koha/zebradb/authorities/key'      => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
372
    './skel/var/lib/koha/zebradb/authorities/register' => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
372
    './skel/var/lib/koha/zebradb/authorities/register' => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
373
    './skel/var/lib/koha/zebradb/authorities/shadow'   => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
373
    './skel/var/lib/koha/zebradb/authorities/shadow'   => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
374
    './skel/var/lib/koha/zebradb/authorities/tmp'      => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
374
    './skel/var/lib/koha/zebradb/authorities/tmp'      => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
375
    './skel/var/lock/koha/zebradb/biblios'             => { target => 'ZEBRA_LOCK_DIR', trimdir => 6 },
375
    './skel/var/lock/koha/zebradb/biblios'             => { target => 'ZEBRA_LOCK_DIR', trimdir =>  6 },
376
    './skel/var/lib/koha/zebradb/biblios/key'          => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
376
    './skel/var/lib/koha/zebradb/biblios/key'          => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
377
    './skel/var/lib/koha/zebradb/biblios/register'     => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
377
    './skel/var/lib/koha/zebradb/biblios/register'     => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
378
    './skel/var/lib/koha/zebradb/biblios/shadow'       => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
378
    './skel/var/lib/koha/zebradb/biblios/shadow'       => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
379
    './skel/var/lib/koha/zebradb/biblios/tmp'          => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
379
    './skel/var/lib/koha/zebradb/biblios/tmp'          => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
380
    './skel/var/lock/koha/zebradb/rebuild'             => { target => 'ZEBRA_LOCK_DIR', trimdir => 6 },
380
    './skel/var/lock/koha/zebradb/rebuild'             => { target => 'ZEBRA_LOCK_DIR', trimdir =>  6 },
381
    './skel/var/lib/koha/plugins'                      => { target => 'PLUGINS_DIR',    trimdir => 6 },
381
    './skel/var/lib/koha/plugins'                      => { target => 'PLUGINS_DIR',    trimdir =>  6 },
382
    './sms'                                            => 'INTRANET_CGI_DIR',
382
    './sms'                                            => 'INTRANET_CGI_DIR',
383
    './suggestion'                                     => 'INTRANET_CGI_DIR',
383
    './suggestion'                                     => 'INTRANET_CGI_DIR',
384
    './svc'                                            => 'INTRANET_CGI_DIR',
384
    './svc'                                            => 'INTRANET_CGI_DIR',
(-)a/admin/preferences.pl (-2 / +2 lines)
Lines 167-173 sub _get_chunk { Link Here
167
        @values = split /,/, $value if defined($value);
167
        @values = split /,/, $value if defined($value);
168
        $chunk->{'CHOICES'} = [
168
        $chunk->{'CHOICES'} = [
169
            sort { $a->{'text'} cmp $b->{'text'} }
169
            sort { $a->{'text'} cmp $b->{'text'} }
170
                map {
170
            map {
171
                my $c = $_;
171
                my $c = $_;
172
                {
172
                {
173
                    text     => $options{'choices'}->{$c},
173
                    text     => $options{'choices'}->{$c},
Lines 190-196 sub _get_chunk { Link Here
190
        $chunk->{type}    = 'multiple';
190
        $chunk->{type}    = 'multiple';
191
        $chunk->{CHOICES} = [
191
        $chunk->{CHOICES} = [
192
            sort { $a->{'text'} cmp $b->{'text'} }
192
            sort { $a->{'text'} cmp $b->{'text'} }
193
                map {
193
            map {
194
                my $option_value = $_;
194
                my $option_value = $_;
195
                {
195
                {
196
                    text     => $options{multiple}->{$option_value},
196
                    text     => $options{multiple}->{$option_value},
(-)a/ill/ill-requests.pl (-2 / +2 lines)
Lines 144-155 if ($backends_available) { Link Here
144
            $op = 'historycheck';
144
            $op = 'historycheck';
145
            $template->param( $history_check->history_check_template_params($params) )
145
            $template->param( $history_check->history_check_template_params($params) )
146
146
147
                # ILLCheckAvailability operation
147
            # ILLCheckAvailability operation
148
        } elsif ( $availability->show_availability($request) ) {
148
        } elsif ( $availability->show_availability($request) ) {
149
            $op = 'availability';
149
            $op = 'availability';
150
            $template->param( $availability->availability_template_params($params) )
150
            $template->param( $availability->availability_template_params($params) )
151
151
152
                # ILLModuleDisclaimerByType operation
152
            # ILLModuleDisclaimerByType operation
153
        } elsif ( $type_disclaimer->show_type_disclaimer($request) ) {
153
        } elsif ( $type_disclaimer->show_type_disclaimer($request) ) {
154
            $op = 'typedisclaimer';
154
            $op = 'typedisclaimer';
155
            $template->param( $type_disclaimer->type_disclaimer_template_params($params) );
155
            $template->param( $type_disclaimer->type_disclaimer_template_params($params) );
(-)a/installer/data/mysql/db_revs/221200010.pl (-1 / +1 lines)
Lines 86-92 return { Link Here
86
            )[0] == 0
86
            )[0] == 0
87
            )
87
            )
88
        {    # Check to make idempotent
88
        {    # Check to make idempotent
89
            my $cc_template = <<~ 'END_TEMPLATE';
89
            my $cc_template = <<~'END_TEMPLATE';
90
            **Describe the concern**
90
            **Describe the concern**
91
            A clear and concise description of what the concern is.
91
            A clear and concise description of what the concern is.
92
92
(-)a/installer/data/mysql/fix_unclosed_nonaccruing_fines_bug17135.pl (-1 / +1 lines)
Lines 37-43 GetOptions( Link Here
37
    'p|print'   => \$stdout_log
37
    'p|print'   => \$stdout_log
38
);
38
);
39
39
40
my $usage = << 'ENDUSAGE';
40
my $usage = <<'ENDUSAGE';
41
41
42
Script for fixing unclosed (FU), non accruing fine records, which
42
Script for fixing unclosed (FU), non accruing fine records, which
43
may still need FU -> F correction post-Bug 15675. For details,
43
may still need FU -> F correction post-Bug 15675. For details,
(-)a/installer/data/mysql/updatedatabase.pl (-2 / +2 lines)
Lines 2136-2142 VALUES Link Here
2136
('EnhancedMessagingPreferences',0,'If ON, allows patrons to select to receive additional messages about items due or nearly due.','','YesNo')
2136
('EnhancedMessagingPreferences',0,'If ON, allows patrons to select to receive additional messages about items due or nearly due.','','YesNo')
2137
END_SQL
2137
END_SQL
2138
2138
2139
    $dbh->do( <<'END_SQL');
2139
    $dbh->do(<<'END_SQL');
2140
INSERT INTO `letter`
2140
INSERT INTO `letter`
2141
(module, code, name, title, content)
2141
(module, code, name, title, content)
2142
VALUES
2142
VALUES
Lines 3682-3688 if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { Link Here
3682
3682
3683
$DBversion = '3.01.00.080';
3683
$DBversion = '3.01.00.080';
3684
if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
3684
if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
3685
    $dbh->do(<<BUDG_PERM );
3685
    $dbh->do(<<BUDG_PERM);
3686
INSERT INTO permissions (module_bit, code, description) VALUES
3686
INSERT INTO permissions (module_bit, code, description) VALUES
3687
            (11, 'vendors_manage', 'Manage vendors'),
3687
            (11, 'vendors_manage', 'Manage vendors'),
3688
            (11, 'contracts_manage', 'Manage contracts'),
3688
            (11, 'contracts_manage', 'Manage contracts'),
(-)a/installer/install.pl (-1 / +1 lines)
Lines 415-421 if ( $step && $step == 1 ) { Link Here
415
        my $cmd = C4::Context->config("intranetdir")
415
        my $cmd = C4::Context->config("intranetdir")
416
            . "/installer/data/$info{dbms}/updatedatabase.pl >> $logfilepath 2>> $logfilepath_errors";
416
            . "/installer/data/$info{dbms}/updatedatabase.pl >> $logfilepath 2>> $logfilepath_errors";
417
417
418
        system($cmd );
418
        system($cmd);
419
419
420
        my $fh;
420
        my $fh;
421
        open( $fh, "<:encoding(utf-8)", $logfilepath )
421
        open( $fh, "<:encoding(utf-8)", $logfilepath )
(-)a/members/maninvoice.pl (-1 / +1 lines)
Lines 140-146 if ( $op eq 'cud-add' ) { Link Here
140
                    borrowernumber => $borrowernumber
140
                    borrowernumber => $borrowernumber
141
                },
141
                },
142
                { order_by => { -desc => 'returndate' }, rows => 1 }
142
                { order_by => { -desc => 'returndate' }, rows => 1 }
143
            )->next;
143
                )->next;
144
            $issue_id = $checkout ? $checkout->issue_id : undef;
144
            $issue_id = $checkout ? $checkout->issue_id : undef;
145
        }
145
        }
146
    }
146
    }
(-)a/members/memberentry.pl (-1 / +1 lines)
Lines 488-494 if ( ( !$nok ) and $nodouble and ( $op eq 'cud-insert' or $op eq 'cud-save' ) ) Link Here
488
                    my $letter = GetPreparedLetter(
488
                    my $letter = GetPreparedLetter(
489
                        module      => 'members',
489
                        module      => 'members',
490
                        letter_code => 'WELCOME',
490
                        letter_code => 'WELCOME',
491
                        branchcode  => $patron->branchcode,,
491
                        branchcode  => $patron->branchcode,
492
                        lang        => $patron->lang || 'default',
492
                        lang        => $patron->lang || 'default',
493
                        tables      => {
493
                        tables      => {
494
                            'branches'  => $patron->branchcode,
494
                            'branches'  => $patron->branchcode,
(-)a/members/notices.pl (-2 / +2 lines)
Lines 76-82 if ( $op eq 'send_welcome' ) { Link Here
76
            my $letter = GetPreparedLetter(
76
            my $letter = GetPreparedLetter(
77
                module      => 'members',
77
                module      => 'members',
78
                letter_code => 'WELCOME',
78
                letter_code => 'WELCOME',
79
                branchcode  => $patron->branchcode,,
79
                branchcode  => $patron->branchcode,
80
                lang        => $patron->lang || 'default',
80
                lang        => $patron->lang || 'default',
81
                tables      => {
81
                tables      => {
82
                    'branches'  => $patron->branchcode,
82
                    'branches'  => $patron->branchcode,
Lines 99-105 if ( $op eq 'send_welcome' ) { Link Here
99
            my $print = GetPreparedLetter(
99
            my $print = GetPreparedLetter(
100
                module      => 'members',
100
                module      => 'members',
101
                letter_code => 'WELCOME',
101
                letter_code => 'WELCOME',
102
                branchcode  => $patron->branchcode,,
102
                branchcode  => $patron->branchcode,
103
                lang        => $patron->lang || 'default',
103
                lang        => $patron->lang || 'default',
104
                tables      => {
104
                tables      => {
105
                    'branches'  => $patron->branchcode,
105
                    'branches'  => $patron->branchcode,
(-)a/misc/cronjobs/cart_to_shelf.pl (-1 / +1 lines)
Lines 42-48 cronlogaction( { info => $command_line_options } ); Link Here
42
42
43
GetOptions( 'h|hours=s' => \$hours, );
43
GetOptions( 'h|hours=s' => \$hours, );
44
44
45
my $usage = << 'ENDUSAGE';
45
my $usage = <<'ENDUSAGE';
46
cart_to_shelf.pl: This cron script will set any item of the location CART ( Shelving Cart ) to it's original shelving location
46
cart_to_shelf.pl: This cron script will set any item of the location CART ( Shelving Cart ) to it's original shelving location
47
                 after the given number of hours has passed.
47
                 after the given number of hours has passed.
48
48
(-)a/misc/cronjobs/fines.pl (-1 / +1 lines)
Lines 61-67 GetOptions( Link Here
61
    'm|maxdays:i'   => \$maxdays,
61
    'm|maxdays:i'   => \$maxdays,
62
    'i|verifyissue' => \$verify_issue,
62
    'i|verifyissue' => \$verify_issue,
63
);
63
);
64
my $usage = << 'ENDUSAGE';
64
my $usage = <<'ENDUSAGE';
65
65
66
This script calculates and charges overdue fines
66
This script calculates and charges overdue fines
67
to patron accounts.  The Koha system preference 'finesMode' controls
67
to patron accounts.  The Koha system preference 'finesMode' controls
(-)a/misc/cronjobs/harvest_oai.pl (-1 / +1 lines)
Lines 41-47 GetOptions( Link Here
41
    'l|list'         => \$list,
41
    'l|list'         => \$list,
42
    'f|force'        => \$force,
42
    'f|force'        => \$force,
43
);
43
);
44
my $usage = << 'ENDUSAGE';
44
my $usage = <<'ENDUSAGE';
45
45
46
This script starts an OAI Harvest
46
This script starts an OAI Harvest
47
47
(-)a/misc/cronjobs/process_message_queue.pl (-1 / +1 lines)
Lines 52-58 GetOptions( Link Here
52
    'w|where:s'                => \$where,
52
    'w|where:s'                => \$where,
53
    'e|exit-on-plugin-failure' => \$exit_on_plugin_failure,
53
    'e|exit-on-plugin-failure' => \$exit_on_plugin_failure,
54
);
54
);
55
my $usage = << 'ENDUSAGE';
55
my $usage = <<'ENDUSAGE';
56
56
57
This script processes the message queue in the message_queue database
57
This script processes the message queue in the message_queue database
58
table. It sends out the messages in that queue and marks them
58
table. It sends out the messages in that queue and marks them
(-)a/misc/cronjobs/purge_suggestions.pl (-1 / +1 lines)
Lines 38-44 GetOptions( Link Here
38
    'v|verbose' => \$verbose,
38
    'v|verbose' => \$verbose,
39
);
39
);
40
40
41
my $usage = << 'ENDUSAGE';
41
my $usage = <<'ENDUSAGE';
42
This script deletes old suggestions
42
This script deletes old suggestions
43
Parameters:
43
Parameters:
44
-help|? This message
44
-help|? This message
(-)a/misc/cronjobs/staticfines.pl (-1 / +1 lines)
Lines 64-70 GetOptions( Link Here
64
    'u|use-borrower-library' => \$useborrowerlibrary,
64
    'u|use-borrower-library' => \$useborrowerlibrary,
65
    'b|borrower:i'           => \$borrowernumberlimit
65
    'b|borrower:i'           => \$borrowernumberlimit
66
);
66
);
67
my $usage = << 'ENDUSAGE';
67
my $usage = <<'ENDUSAGE';
68
68
69
This script calculates and charges overdue fines to patron accounts.
69
This script calculates and charges overdue fines to patron accounts.
70
70
(-)a/misc/migration_tools/import_lexile.pl (-1 / +1 lines)
Lines 67-73 GetOptions( Link Here
67
    'source-value=s'         => $subfield_source_value,
67
    'source-value=s'         => $subfield_source_value,
68
);
68
);
69
69
70
my $usage = << 'ENDUSAGE';
70
my $usage = <<'ENDUSAGE';
71
import_lexile.pl: Import lexile scores for records from csv.
71
import_lexile.pl: Import lexile scores for records from csv.
72
72
73
import_lexile.pl -f /path/to/LexileTitles.txt
73
import_lexile.pl -f /path/to/LexileTitles.txt
(-)a/misc/migration_tools/koha-svc.pl (-1 / +1 lines)
Lines 36-42 if ( $#ARGV >= 3 && !caller ) { # process command-line params only if not cal Link Here
36
    if ( !$file ) {
36
    if ( !$file ) {
37
        my $marcxml = $svc->get($biblionumber);
37
        my $marcxml = $svc->get($biblionumber);
38
        my $file    = "bib-$biblionumber.xml";
38
        my $file    = "bib-$biblionumber.xml";
39
        write_file $file , $marcxml;
39
        write_file $file, $marcxml;
40
        print "saved $file ", -s $file, " bytes\n";
40
        print "saved $file ", -s $file, " bytes\n";
41
        print $marcxml;
41
        print $marcxml;
42
    } else {
42
    } else {
(-)a/misc/translator/TmplTokenizer.pm (-2 / +2 lines)
Lines 71-78 sub new { Link Here
71
        filename => $filename,
71
        filename => $filename,
72
        _parser  => $parser
72
        _parser  => $parser
73
73
74
            #     , handle => $handle
74
        #     , handle => $handle
75
            #     , readahead => []
75
        #     , readahead => []
76
        },
76
        },
77
        __PACKAGE__;
77
        __PACKAGE__;
78
}
78
}
(-)a/opac/opac-memberentry.pl (-1 / +1 lines)
Lines 269-275 if ( $op eq 'cud-create' ) { Link Here
269
                            my $letter = GetPreparedLetter(
269
                            my $letter = GetPreparedLetter(
270
                                module      => 'members',
270
                                module      => 'members',
271
                                letter_code => 'WELCOME',
271
                                letter_code => 'WELCOME',
272
                                branchcode  => $patron->branchcode,,
272
                                branchcode  => $patron->branchcode,
273
                                lang        => $patron->lang || 'default',
273
                                lang        => $patron->lang || 'default',
274
                                tables      => {
274
                                tables      => {
275
                                    'branches'  => $patron->branchcode,
275
                                    'branches'  => $patron->branchcode,
(-)a/opac/opac-registration-verify.pl (-1 / +1 lines)
Lines 133-139 if ( $rego_found Link Here
133
                    my $letter = GetPreparedLetter(
133
                    my $letter = GetPreparedLetter(
134
                        module      => 'members',
134
                        module      => 'members',
135
                        letter_code => 'WELCOME',
135
                        letter_code => 'WELCOME',
136
                        branchcode  => $patron->branchcode,,
136
                        branchcode  => $patron->branchcode,
137
                        lang        => $patron->lang || 'default',
137
                        lang        => $patron->lang || 'default',
138
                        tables      => {
138
                        tables      => {
139
                            'branches'  => $patron->branchcode,
139
                            'branches'  => $patron->branchcode,
(-)a/reserve/request.pl (-1 / +2 lines)
Lines 287-293 if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) Link Here
287
287
288
    if ( $patron && $multi_hold ) {
288
    if ( $patron && $multi_hold ) {
289
        my @multi_pickup_locations =
289
        my @multi_pickup_locations =
290
            Koha::Biblios->search( { biblionumber => \@biblionumbers } )->pickup_locations( { patron => $patron } )
290
            Koha::Biblios->search( { biblionumber => \@biblionumbers } )
291
            ->pickup_locations( { patron => $patron } )
291
            ->as_list;
292
            ->as_list;
292
        $template->param( multi_pickup_locations => \@multi_pickup_locations );
293
        $template->param( multi_pickup_locations => \@multi_pickup_locations );
293
    }
294
    }
(-)a/t/00-valid-xml.t (-1 / +1 lines)
Lines 43-49 find( Link Here
43
            }
43
            }
44
        },
44
        },
45
    },
45
    },
46
    ,
46
47
    File::Spec->curdir()
47
    File::Spec->curdir()
48
);
48
);
49
49
(-)a/t/Koha/REST/Plugin/Query.t (-19 / +39 lines)
Lines 391-420 subtest 'extract_reserved_params() tests' => sub { Link Here
391
391
392
    my $t = Test::Mojo->new;
392
    my $t = Test::Mojo->new;
393
393
394
    $t->get_ok('/query?_page=2&_per_page=3&firstname=Manuel&surname=Cohen%20Arazi')->status_is(200)
394
    $t->get_ok('/query?_page=2&_per_page=3&firstname=Manuel&surname=Cohen%20Arazi')
395
        ->status_is(200)
395
        ->json_is( '/filtered_params' => { firstname => 'Manuel', surname   => 'Cohen Arazi' } )
396
        ->json_is( '/filtered_params' => { firstname => 'Manuel', surname   => 'Cohen Arazi' } )
396
        ->json_is( '/reserved_params' => { _page     => 2,        _per_page => 3 } );
397
        ->json_is( '/reserved_params' => { _page     => 2,        _per_page => 3 } );
397
398
398
    $t->get_ok(
399
    $t->get_ok(
399
        '/query_full/with/path?_match=exact&_order_by=blah&_page=2&_per_page=3&firstname=Manuel&surname=Cohen%20Arazi')
400
        '/query_full/with/path?_match=exact&_order_by=blah&_page=2&_per_page=3&firstname=Manuel&surname=Cohen%20Arazi')
400
        ->status_is(200)->json_is(
401
        ->status_is(200)
402
        ->json_is(
401
        '/filtered_params' => {
403
        '/filtered_params' => {
402
            firstname => 'Manuel',
404
            firstname => 'Manuel',
403
            surname   => 'Cohen Arazi'
405
            surname   => 'Cohen Arazi'
404
        }
406
        }
405
    )->json_is(
407
        )->json_is(
406
        '/reserved_params' => {
408
        '/reserved_params' => {
407
            _page     => 2,
409
            _page     => 2,
408
            _per_page => 3,
410
            _per_page => 3,
409
            _match    => 'exact',
411
            _match    => 'exact',
410
            _order_by => 'blah'
412
            _order_by => 'blah'
411
        }
413
        }
412
    )->json_is(
414
        )->json_is(
413
        '/path_params' => {
415
        '/path_params' => {
414
            id    => 'with',
416
            id    => 'with',
415
            subid => 'path'
417
            subid => 'path'
416
        }
418
        }
417
    );
419
        );
418
420
419
};
421
};
420
422
Lines 424-431 subtest 'dbic_merge_sorting() tests' => sub { Link Here
424
426
425
    my $t = Test::Mojo->new;
427
    my $t = Test::Mojo->new;
426
428
427
    $t->get_ok('/dbic_merge_sorting')->status_is(200)->json_is( '/a' => 'a', 'Existing values are kept (a)' )
429
    $t->get_ok('/dbic_merge_sorting')
428
        ->json_is( '/b' => 'b', 'Existing values are kept (b)' )->json_is(
430
        ->status_is(200)
431
        ->json_is( '/a' => 'a', 'Existing values are kept (a)' )
432
        ->json_is( '/b' => 'b', 'Existing values are kept (b)' )
433
        ->json_is(
429
        '/order_by' => [
434
        '/order_by' => [
430
            'uno',
435
            'uno',
431
            { -desc => 'dos' },
436
            { -desc => 'dos' },
Lines 434-442 subtest 'dbic_merge_sorting() tests' => sub { Link Here
434
        ]
439
        ]
435
        );
440
        );
436
441
437
    $t->get_ok('/dbic_merge_sorting_result_set')->status_is(200)
442
    $t->get_ok('/dbic_merge_sorting_result_set')
443
        ->status_is(200)
438
        ->json_is( '/a' => 'a', 'Existing values are kept (a)' )
444
        ->json_is( '/a' => 'a', 'Existing values are kept (a)' )
439
        ->json_is( '/b' => 'b', 'Existing values are kept (b)' )->json_is(
445
        ->json_is( '/b' => 'b', 'Existing values are kept (b)' )
446
        ->json_is(
440
        '/order_by' => [
447
        '/order_by' => [
441
            'city_name',
448
            'city_name',
442
            { -desc => 'city_zipcode' },
449
            { -desc => 'city_zipcode' },
Lines 445-456 subtest 'dbic_merge_sorting() tests' => sub { Link Here
445
        ]
452
        ]
446
        );
453
        );
447
454
448
    $t->get_ok('/dbic_merge_sorting_date')->status_is(200)->json_is( '/a' => 'a', 'Existing values are kept (a)' )
455
    $t->get_ok('/dbic_merge_sorting_date')
456
        ->status_is(200)
457
        ->json_is( '/a'        => 'a', 'Existing values are kept (a)' )
449
        ->json_is( '/b'        => 'b', 'Existing values are kept (b)' )
458
        ->json_is( '/b'        => 'b', 'Existing values are kept (b)' )
450
        ->json_is( '/order_by' => [ { -desc => 'reservedate' } ] );
459
        ->json_is( '/order_by' => [ { -desc => 'reservedate' } ] );
451
460
452
    $t->get_ok('/dbic_merge_sorting_single')->status_is(200)->json_is( '/a' => 'a', 'Existing values are kept (a)' )
461
    $t->get_ok('/dbic_merge_sorting_single')
453
        ->json_is( '/b' => 'b', 'Existing values are kept (b)' )->json_is( '/order_by' => [ { '-desc' => 'uno' } ] );
462
        ->status_is(200)
463
        ->json_is( '/a'        => 'a', 'Existing values are kept (a)' )
464
        ->json_is( '/b'        => 'b', 'Existing values are kept (b)' )
465
        ->json_is( '/order_by' => [ { '-desc' => 'uno' } ] );
454
};
466
};
455
467
456
subtest '/dbic_merge_prefetch' => sub {
468
subtest '/dbic_merge_prefetch' => sub {
Lines 458-464 subtest '/dbic_merge_prefetch' => sub { Link Here
458
470
459
    my $t = Test::Mojo->new;
471
    my $t = Test::Mojo->new;
460
472
461
    $t->get_ok('/dbic_merge_prefetch')->status_is(200)->json_is( '/prefetch/0' => { 'biblio' => 'orders' } )
473
    $t->get_ok('/dbic_merge_prefetch')
474
        ->status_is(200)
475
        ->json_is( '/prefetch/0' => { 'biblio' => 'orders' } )
462
        ->json_is( '/prefetch/1' => 'item' );
476
        ->json_is( '/prefetch/1' => 'item' );
463
477
464
    $t->get_ok('/dbic_merge_prefetch_recursive')->status_is(200)->json_is(
478
    $t->get_ok('/dbic_merge_prefetch_recursive')->status_is(200)->json_is(
Lines 519-541 subtest '_build_query_params_from_api' => sub { Link Here
519
    my $t = Test::Mojo->new;
533
    my $t = Test::Mojo->new;
520
534
521
    # _match => contains
535
    # _match => contains
522
    $t->get_ok('/build_query?_match=contains&title=Ender&author=Orson')->status_is(200)
536
    $t->get_ok('/build_query?_match=contains&title=Ender&author=Orson')
537
        ->status_is(200)
523
        ->json_is( '/query' => { author => { like => '%Orson%' }, title => { like => '%Ender%' } } );
538
        ->json_is( '/query' => { author => { like => '%Orson%' }, title => { like => '%Ender%' } } );
524
539
525
    # _match => starts_with
540
    # _match => starts_with
526
    $t->get_ok('/build_query?_match=starts_with&title=Ender&author=Orson')->status_is(200)
541
    $t->get_ok('/build_query?_match=starts_with&title=Ender&author=Orson')
542
        ->status_is(200)
527
        ->json_is( '/query' => { author => { like => 'Orson%' }, title => { like => 'Ender%' } } );
543
        ->json_is( '/query' => { author => { like => 'Orson%' }, title => { like => 'Ender%' } } );
528
544
529
    # _match => ends_with
545
    # _match => ends_with
530
    $t->get_ok('/build_query?_match=ends_with&title=Ender&author=Orson')->status_is(200)
546
    $t->get_ok('/build_query?_match=ends_with&title=Ender&author=Orson')
547
        ->status_is(200)
531
        ->json_is( '/query' => { author => { like => '%Orson' }, title => { like => '%Ender' } } );
548
        ->json_is( '/query' => { author => { like => '%Orson' }, title => { like => '%Ender' } } );
532
549
533
    # _match => exact
550
    # _match => exact
534
    $t->get_ok('/build_query?_match=exact&title=Ender&author=Orson')->status_is(200)
551
    $t->get_ok('/build_query?_match=exact&title=Ender&author=Orson')
552
        ->status_is(200)
535
        ->json_is( '/query' => { author => 'Orson', title => 'Ender' } );
553
        ->json_is( '/query' => { author => 'Orson', title => 'Ender' } );
536
554
537
    # _match => blah
555
    # _match => blah
538
    $t->get_ok('/build_query?_match=blah&title=Ender&author=Orson')->status_is(400)
556
    $t->get_ok('/build_query?_match=blah&title=Ender&author=Orson')
557
        ->status_is(400)
539
        ->json_is( '/exception_msg'  => 'Invalid value for _match param (blah)' )
558
        ->json_is( '/exception_msg'  => 'Invalid value for _match param (blah)' )
540
        ->json_is( '/exception_type' => 'Koha::Exceptions::WrongParameter' );
559
        ->json_is( '/exception_type' => 'Koha::Exceptions::WrongParameter' );
541
560
Lines 580-586 subtest 'stash_embed() tests' => sub { Link Here
580
        }
599
        }
581
    )->json_is( '/strings' => 1 );
600
    )->json_is( '/strings' => 1 );
582
601
583
    $t->get_ok( '/stash_embed_no_spec' => { 'x-koha-embed' => 'checkouts,checkouts.item,patron' } )->status_is(400)
602
    $t->get_ok( '/stash_embed_no_spec' => { 'x-koha-embed' => 'checkouts,checkouts.item,patron' } )
603
        ->status_is(400)
584
        ->json_is( '/error' =>
604
        ->json_is( '/error' =>
585
            qq{Exception 'Koha::Exceptions::BadParameter' thrown 'Embedding objects is not allowed on this endpoint.'\n}
605
            qq{Exception 'Koha::Exceptions::BadParameter' thrown 'Embedding objects is not allowed on this endpoint.'\n}
586
        );
606
        );
(-)a/t/Test/Dates.t (-2 / +2 lines)
Lines 10-19 my $dt_1 = dt_from_string($date_1); Link Here
10
my $dt_2   = dt_from_string($date_2);
10
my $dt_2   = dt_from_string($date_2);
11
11
12
is( t::lib::Dates::compare( $dt_1, $dt_2 ), -1, '2017 is before 2018' );
12
is( t::lib::Dates::compare( $dt_1, $dt_2 ), -1, '2017 is before 2018' );
13
is( t::lib::Dates::compare( $dt_2, $dt_1 ), 1,  '2018 is after 2017' );
13
is( t::lib::Dates::compare( $dt_2, $dt_1 ),  1, '2018 is after 2017' );
14
14
15
is( t::lib::Dates::compare( $date_1, $date_2 ), -1, '2017 is before 2018 (strings comparison)' );
15
is( t::lib::Dates::compare( $date_1, $date_2 ), -1, '2017 is before 2018 (strings comparison)' );
16
is( t::lib::Dates::compare( $date_2, $date_1 ), 1,  '2018 is after 2017 (strings comparison)' );
16
is( t::lib::Dates::compare( $date_2, $date_1 ),  1, '2018 is after 2017 (strings comparison)' );
17
17
18
my $dt_3 = $dt_1->clone->subtract( seconds => 5 );
18
my $dt_3 = $dt_1->clone->subtract( seconds => 5 );
19
is(
19
is(
(-)a/t/db_dependent/Auth.t (-4 / +4 lines)
Lines 1192-1198 subtest 'checkpw() return values tests' => sub { Link Here
1192
        $password_expired = 1;
1192
        $password_expired = 1;
1193
        @return           = checkpw( $patron->userid, $password, undef, );
1193
        @return           = checkpw( $patron->userid, $password, undef, );
1194
1194
1195
        is( scalar @return,    2,  "Two results on expired password scenario" );
1195
        is( scalar @return,     2, "Two results on expired password scenario" );
1196
        is( $return[0],        -2, '-2 returned' );
1196
        is( $return[0],        -2, '-2 returned' );
1197
        is( ref( $return[1] ), 'Koha::Patron' );
1197
        is( ref( $return[1] ), 'Koha::Patron' );
1198
        is( $return[1]->id,    $patron->id, 'Patron matched correctly' );
1198
        is( $return[1]->id,    $patron->id, 'Patron matched correctly' );
Lines 1200-1206 subtest 'checkpw() return values tests' => sub { Link Here
1200
        t::lib::Mocks::mock_preference( 'AnonymousPatron', $patron->id );
1200
        t::lib::Mocks::mock_preference( 'AnonymousPatron', $patron->id );
1201
        @return = checkpw( $patron->userid, $password, undef, );
1201
        @return = checkpw( $patron->userid, $password, undef, );
1202
1202
1203
        is( scalar @return,    2,  "Two results on expired password scenario" );
1203
        is( scalar @return,     2, "Two results on expired password scenario" );
1204
        is( $return[0],        -3, '-3 returned' );
1204
        is( $return[0],        -3, '-3 returned' );
1205
        is( ref( $return[1] ), 'Koha::Patron' );
1205
        is( ref( $return[1] ), 'Koha::Patron' );
1206
        is( $return[1]->id,    $patron->id, 'Patron matched correctly' );
1206
        is( $return[1]->id,    $patron->id, 'Patron matched correctly' );
Lines 1284-1297 subtest 'checkpw() return values tests' => sub { Link Here
1284
        $password_expired = 1;
1284
        $password_expired = 1;
1285
        @return           = checkpw( $patron->userid, $password, $query, );
1285
        @return           = checkpw( $patron->userid, $password, $query, );
1286
1286
1287
        is( scalar @return,    2,  "Two results on expired password scenario" );
1287
        is( scalar @return,     2, "Two results on expired password scenario" );
1288
        is( $return[0],        -2, '-2 returned' );
1288
        is( $return[0],        -2, '-2 returned' );
1289
        is( ref( $return[1] ), 'Koha::Patron' );
1289
        is( ref( $return[1] ), 'Koha::Patron' );
1290
        is( $return[1]->id,    $patron->id, 'Patron matched correctly' );
1290
        is( $return[1]->id,    $patron->id, 'Patron matched correctly' );
1291
1291
1292
        t::lib::Mocks::mock_preference( 'AnonymousPatron', $patron->id );
1292
        t::lib::Mocks::mock_preference( 'AnonymousPatron', $patron->id );
1293
        @return = checkpw( $patron->userid, $password, undef, );
1293
        @return = checkpw( $patron->userid, $password, undef, );
1294
        is( scalar @return,    2,  "Two results on expired password scenario" );
1294
        is( scalar @return,     2, "Two results on expired password scenario" );
1295
        is( $return[0],        -3, '-3 returned' );
1295
        is( $return[0],        -3, '-3 returned' );
1296
        is( ref( $return[1] ), 'Koha::Patron' );
1296
        is( ref( $return[1] ), 'Koha::Patron' );
1297
        is( $return[1]->id,    $patron->id, 'Patron matched correctly' );
1297
        is( $return[1]->id,    $patron->id, 'Patron matched correctly' );
(-)a/t/db_dependent/Auth_with_shibboleth.t (-9 / +17 lines)
Lines 168-174 subtest "get_login_shib tests" => sub { Link Here
168
168
169
    my $login = get_login_shib();
169
    my $login = get_login_shib();
170
    $logger->debug_is( "koha borrower field to match: userid", "borrower match field debug info" )
170
    $logger->debug_is( "koha borrower field to match: userid", "borrower match field debug info" )
171
        ->debug_is( "shibboleth attribute to match: uid", "shib match attribute debug info" )->clear();
171
        ->debug_is( "shibboleth attribute to match: uid", "shib match attribute debug info" )
172
        ->clear();
172
    is( $login, "test1234", "good config, attribute value returned" );
173
    is( $login, "test1234", "good config, attribute value returned" );
173
};
174
};
174
175
Lines 207-213 subtest "checkpw_shib tests" => sub { Link Here
207
    is( ref($retpatron),  'Koha::Patron',   "expected Koha::Patron object returned" );
208
    is( ref($retpatron),  'Koha::Patron',   "expected Koha::Patron object returned" );
208
209
209
    $logger->debug_is( "koha borrower field to match: userid", "borrower match field debug info" )
210
    $logger->debug_is( "koha borrower field to match: userid", "borrower match field debug info" )
210
        ->debug_is( "shibboleth attribute to match: uid", "shib match attribute debug info" )->clear();
211
        ->debug_is( "shibboleth attribute to match: uid", "shib match attribute debug info" )
212
        ->clear();
211
213
212
    # bad user
214
    # bad user
213
    $shib_login = 'martin';
215
    $shib_login = 'martin';
Lines 217-223 subtest "checkpw_shib tests" => sub { Link Here
217
    is( $retuserid, undef );
219
    is( $retuserid, undef );
218
    is( $retpatron, undef );
220
    is( $retpatron, undef );
219
    $logger->debug_is( "koha borrower field to match: userid", "borrower match field debug info" )
221
    $logger->debug_is( "koha borrower field to match: userid", "borrower match field debug info" )
220
        ->debug_is( "shibboleth attribute to match: uid", "shib match attribute debug info" )->clear();
222
        ->debug_is( "shibboleth attribute to match: uid", "shib match attribute debug info" )
223
        ->clear();
221
224
222
    # duplicated matchpoint
225
    # duplicated matchpoint
223
    change_config( { matchpoint => 'email', mapping => { email => { is => 'email' } } } );
226
    change_config( { matchpoint => 'email', mapping => { email => { is => 'email' } } } );
Lines 228-234 subtest "checkpw_shib tests" => sub { Link Here
228
    is( $retuserid, undef );
231
    is( $retuserid, undef );
229
    is( $retpatron, undef );
232
    is( $retpatron, undef );
230
    $logger->debug_is( "koha borrower field to match: email", "borrower match field debug info" )
233
    $logger->debug_is( "koha borrower field to match: email", "borrower match field debug info" )
231
        ->debug_is( "shibboleth attribute to match: email", "shib match attribute debug info" )->clear();
234
        ->debug_is( "shibboleth attribute to match: email", "shib match attribute debug info" )
235
        ->clear();
232
236
233
    ( $retval, $retcard, $retuserid, $retpatron ) = checkpw_shib($shib_login);
237
    ( $retval, $retcard, $retuserid, $retpatron ) = checkpw_shib($shib_login);
234
    is( $retval,    0 );
238
    is( $retval,    0 );
Lines 236-245 subtest "checkpw_shib tests" => sub { Link Here
236
    is( $retuserid, undef );
240
    is( $retuserid, undef );
237
    is( $retpatron, undef );
241
    is( $retpatron, undef );
238
    $logger->debug_is( "koha borrower field to match: email", "borrower match field debug info" )
242
    $logger->debug_is( "koha borrower field to match: email", "borrower match field debug info" )
239
        ->debug_is( "shibboleth attribute to match: email", "shib match attribute debug info" )->warn_is(
243
        ->debug_is( "shibboleth attribute to match: email", "shib match attribute debug info" )
244
        ->warn_is(
240
        'There are several users with email of kid@clamp.io, matchpoints must be unique',
245
        'There are several users with email of kid@clamp.io, matchpoints must be unique',
241
        "duplicated matchpoint warned with debug"
246
        "duplicated matchpoint warned with debug"
242
    )->clear();
247
        )->clear();
243
248
244
    # autocreate user (welcome)
249
    # autocreate user (welcome)
245
    change_config( { autocreate => 1, welcome => 1 } );
250
    change_config( { autocreate => 1, welcome => 1 } );
Lines 261-267 subtest "checkpw_shib tests" => sub { Link Here
261
    is( $retuserid,                              "test4321",     "expected userid returned" );
266
    is( $retuserid,                              "test4321",     "expected userid returned" );
262
    is( ref($retpatron),                         'Koha::Patron', "expected Koha::Patron object returned" );
267
    is( ref($retpatron),                         'Koha::Patron', "expected Koha::Patron object returned" );
263
    $logger->debug_is( "koha borrower field to match: userid", "borrower match field debug info" )
268
    $logger->debug_is( "koha borrower field to match: userid", "borrower match field debug info" )
264
        ->debug_is( "shibboleth attribute to match: uid", "shib match attribute debug info" )->clear();
269
        ->debug_is( "shibboleth attribute to match: uid", "shib match attribute debug info" )
270
        ->clear();
265
271
266
    ok my $new_user = $schema->resultset('Borrower')->search( { 'userid' => 'test4321' }, { rows => 1 } ),
272
    ok my $new_user = $schema->resultset('Borrower')->search( { 'userid' => 'test4321' }, { rows => 1 } ),
267
        "new user found";
273
        "new user found";
Lines 280-286 subtest "checkpw_shib tests" => sub { Link Here
280
    is( $retuserid,      $shib_login,    "expected userid returned" );
286
    is( $retuserid,      $shib_login,    "expected userid returned" );
281
    is( ref($retpatron), 'Koha::Patron', "expected Koha::Patron object returned" );
287
    is( ref($retpatron), 'Koha::Patron', "expected Koha::Patron object returned" );
282
    $logger->debug_is( "koha borrower field to match: userid", "borrower match field debug info" )
288
    $logger->debug_is( "koha borrower field to match: userid", "borrower match field debug info" )
283
        ->debug_is( "shibboleth attribute to match: uid", "shib match attribute debug info" )->clear();
289
        ->debug_is( "shibboleth attribute to match: uid", "shib match attribute debug info" )
290
        ->clear();
284
291
285
    ok my $sync_user = $schema->resultset('Borrower')->search( { 'userid' => 'test4321' }, { rows => 1 } ),
292
    ok my $sync_user = $schema->resultset('Borrower')->search( { 'userid' => 'test4321' }, { rows => 1 } ),
286
        "sync user found";
293
        "sync user found";
Lines 301-307 subtest "checkpw_shib tests" => sub { Link Here
301
    is( $retuserid,      "test1234",       "expected userid returned" );
308
    is( $retuserid,      "test1234",       "expected userid returned" );
302
    is( ref($retpatron), 'Koha::Patron',   "expected Koha::Patron object returned" );
309
    is( ref($retpatron), 'Koha::Patron',   "expected Koha::Patron object returned" );
303
    $logger->debug_is( "koha borrower field to match: userid", "borrower match field debug info" )
310
    $logger->debug_is( "koha borrower field to match: userid", "borrower match field debug info" )
304
        ->debug_is( "shibboleth attribute to match: uid", "shib match attribute debug info" )->clear();
311
        ->debug_is( "shibboleth attribute to match: uid", "shib match attribute debug info" )
312
        ->clear();
305
313
306
    # bad user
314
    # bad user
307
    $shib_login = "martin";
315
    $shib_login = "martin";
(-)a/t/db_dependent/Circulation.t (-10 / +10 lines)
Lines 1185-1191 subtest "CanBookBeRenewed tests" => sub { Link Here
1185
        );
1185
        );
1186
1186
1187
        my $ten_days_before = dt_from_string->add( days => -10 );
1187
        my $ten_days_before = dt_from_string->add( days => -10 );
1188
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
1188
        my $ten_days_ahead  = dt_from_string->add( days =>  10 );
1189
        my $issue           = AddIssue(
1189
        my $issue           = AddIssue(
1190
            $renewing_borrower_obj, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before,
1190
            $renewing_borrower_obj, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before,
1191
            undef, { auto_renew => 1 }
1191
            undef, { auto_renew => 1 }
Lines 1335-1341 subtest "CanBookBeRenewed tests" => sub { Link Here
1335
        );
1335
        );
1336
1336
1337
        my $ten_days_before = dt_from_string->add( days => -10 );
1337
        my $ten_days_before = dt_from_string->add( days => -10 );
1338
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
1338
        my $ten_days_ahead  = dt_from_string->add( days =>  10 );
1339
        my $issue           = AddIssue(
1339
        my $issue           = AddIssue(
1340
            $renewing_borrower_obj, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before,
1340
            $renewing_borrower_obj, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before,
1341
            undef, { auto_renew => 1 }
1341
            undef, { auto_renew => 1 }
Lines 1445-1451 subtest "CanBookBeRenewed tests" => sub { Link Here
1445
        );
1445
        );
1446
1446
1447
        my $ten_days_before = dt_from_string->add( days => -10 );
1447
        my $ten_days_before = dt_from_string->add( days => -10 );
1448
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
1448
        my $ten_days_ahead  = dt_from_string->add( days =>  10 );
1449
1449
1450
        # Patron is expired and BlockExpiredPatronOpacActions=''
1450
        # Patron is expired and BlockExpiredPatronOpacActions=''
1451
        # => auto renew is allowed
1451
        # => auto renew is allowed
Lines 1497-1503 subtest "CanBookBeRenewed tests" => sub { Link Here
1497
        );
1497
        );
1498
1498
1499
        my $ten_days_before = dt_from_string->add( days => -10 );
1499
        my $ten_days_before = dt_from_string->add( days => -10 );
1500
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
1500
        my $ten_days_ahead  = dt_from_string->add( days =>  10 );
1501
        my $issue           = AddIssue(
1501
        my $issue           = AddIssue(
1502
            $renewing_borrower_obj, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before,
1502
            $renewing_borrower_obj, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before,
1503
            undef, { auto_renew => 1 }
1503
            undef, { auto_renew => 1 }
Lines 1618-1624 subtest "CanBookBeRenewed tests" => sub { Link Here
1618
        );
1618
        );
1619
1619
1620
        my $ten_days_before = dt_from_string->add( days => -10 );
1620
        my $ten_days_before = dt_from_string->add( days => -10 );
1621
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
1621
        my $ten_days_ahead  = dt_from_string->add( days =>  10 );
1622
        my $issue           = AddIssue(
1622
        my $issue           = AddIssue(
1623
            $renewing_borrower_obj, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before,
1623
            $renewing_borrower_obj, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before,
1624
            undef, { auto_renew => 1 }
1624
            undef, { auto_renew => 1 }
Lines 1969-1975 subtest "GetUpcomingDueIssues" => sub { Link Here
1969
    my $a_borrower                = Koha::Patrons->find($a_borrower_borrowernumber);
1969
    my $a_borrower                = Koha::Patrons->find($a_borrower_borrowernumber);
1970
1970
1971
    my $yesterday      = DateTime->today( time_zone => C4::Context->tz() )->add( days => -1 );
1971
    my $yesterday      = DateTime->today( time_zone => C4::Context->tz() )->add( days => -1 );
1972
    my $two_days_ahead = DateTime->today( time_zone => C4::Context->tz() )->add( days => 2 );
1972
    my $two_days_ahead = DateTime->today( time_zone => C4::Context->tz() )->add( days =>  2 );
1973
    my $today          = DateTime->today( time_zone => C4::Context->tz() );
1973
    my $today          = DateTime->today( time_zone => C4::Context->tz() );
1974
1974
1975
    my $issue    = AddIssue( $a_borrower, $item_1->barcode, $yesterday );
1975
    my $issue    = AddIssue( $a_borrower, $item_1->barcode, $yesterday );
Lines 3881-3887 subtest 'AddReturn | is_overdue' => sub { Link Here
3881
        is( $line->status,                'RETURNED', "Overdue fine is fixed" );
3881
        is( $line->status,                'RETURNED', "Overdue fine is fixed" );
3882
        $line = $lines->next;
3882
        $line = $lines->next;
3883
        is( $line->amount + 0,            -2, "Original payment amount remains as 2" );
3883
        is( $line->amount + 0,            -2, "Original payment amount remains as 2" );
3884
        is( $line->amountoutstanding + 0, 0,  "Original payment remains applied" );
3884
        is( $line->amountoutstanding + 0,  0, "Original payment remains applied" );
3885
        $line = $lines->next;
3885
        $line = $lines->next;
3886
        is( $line->amount + 0,            -1, "Refund amount correctly set to 1" );
3886
        is( $line->amount + 0,            -1, "Refund amount correctly set to 1" );
3887
        is( $line->amountoutstanding + 0, -1, "Refund amount outstanding unspent" );
3887
        is( $line->amountoutstanding + 0, -1, "Refund amount outstanding unspent" );
Lines 4835-4841 subtest '_FixOverduesOnReturn' => sub { Link Here
4835
    my $credit = $offset->credit;
4835
    my $credit = $offset->credit;
4836
    is( ref $credit,                    "Koha::Account::Line", "Found matching credit for fine forgiveness" );
4836
    is( ref $credit,                    "Koha::Account::Line", "Found matching credit for fine forgiveness" );
4837
    is( $credit->amount + 0,            -99,                   "Credit amount is set correctly" );
4837
    is( $credit->amount + 0,            -99,                   "Credit amount is set correctly" );
4838
    is( $credit->amountoutstanding + 0, 0,                     "Credit amountoutstanding is correctly set to 0" );
4838
    is( $credit->amountoutstanding + 0,  0,                    "Credit amountoutstanding is correctly set to 0" );
4839
4839
4840
    # Bug 25417 - Only forgive fines where there is an amount outstanding to forgive
4840
    # Bug 25417 - Only forgive fines where there is an amount outstanding to forgive
4841
    $accountline->set(
4841
    $accountline->set(
Lines 7488-7494 subtest 'NoRefundOnLostFinesPaidAge' => sub { Link Here
7488
        {
7488
        {
7489
            borrowernumber    => $patron->id,
7489
            borrowernumber    => $patron->id,
7490
            date              => '1970-01-01 14:00:01',
7490
            date              => '1970-01-01 14:00:01',
7491
            amountoutstanding => 0,
7491
            amountoutstanding =>  0,
7492
            amount            => -5,
7492
            amount            => -5,
7493
            interface         => 'commandline',
7493
            interface         => 'commandline',
7494
            credit_type_code  => 'PAYMENT'
7494
            credit_type_code  => 'PAYMENT'
Lines 7544-7550 subtest 'NoRefundOnLostFinesPaidAge' => sub { Link Here
7544
            borrowernumber    => $patron2->id,
7544
            borrowernumber    => $patron2->id,
7545
            date              => '1970-01-01 14:00:01',
7545
            date              => '1970-01-01 14:00:01',
7546
            amount            => -5,
7546
            amount            => -5,
7547
            amountoutstanding => 0,
7547
            amountoutstanding =>  0,
7548
            interface         => 'commandline',
7548
            interface         => 'commandline',
7549
            credit_type_code  => 'PAYMENT'
7549
            credit_type_code  => 'PAYMENT'
7550
        }
7550
        }
(-)a/t/db_dependent/Circulation/maxsuspensiondays.t (-1 / +1 lines)
Lines 76-82 $dbh->do('DELETE FROM special_holidays'); Link Here
76
$dbh->do('DELETE FROM repeatable_holidays');
76
$dbh->do('DELETE FROM repeatable_holidays');
77
77
78
my $daysago20   = dt_from_string->add_duration( DateTime::Duration->new( days => -20 ) );
78
my $daysago20   = dt_from_string->add_duration( DateTime::Duration->new( days => -20 ) );
79
my $daysafter40 = dt_from_string->add_duration( DateTime::Duration->new( days => 40 ) );
79
my $daysafter40 = dt_from_string->add_duration( DateTime::Duration->new( days =>  40 ) );
80
80
81
AddIssue( $patron, $barcode, $daysago20 );
81
AddIssue( $patron, $barcode, $daysago20 );
82
AddReturn( $barcode, $branchcode );
82
AddReturn( $barcode, $branchcode );
(-)a/t/db_dependent/Filter_MARC_ViewPolicy.t (-1 / +1 lines)
Lines 53-59 sub run_hiding_tests { Link Here
53
    my @valid_hidden_values = ( -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8 );
53
    my @valid_hidden_values = ( -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8 );
54
54
55
    my $hidden = {
55
    my $hidden = {
56
        'opac'     => [ -8, 1,  2,  3,  4,  5, 6, 7, 8 ],
56
        'opac'     => [ -8,  1,  2,  3,  4, 5, 6, 7, 8 ],
57
        'intranet' => [ -8, -7, -4, -3, -2, 2, 3, 5, 8 ]
57
        'intranet' => [ -8, -7, -4, -3, -2, 2, 3, 5, 8 ]
58
    };
58
    };
59
59
(-)a/t/db_dependent/Hold.t (-6 / +12 lines)
Lines 356-363 subtest "delete() tests" => sub { Link Here
356
        "Koha::Hold->delete should have deleted the hold"
356
        "Koha::Hold->delete should have deleted the hold"
357
    );
357
    );
358
358
359
    my $number_of_logs = $schema->resultset('ActionLog')
359
    my $number_of_logs =
360
        ->search( { module => 'HOLDS', action => 'DELETE', object => $hold->{reserve_id} } )->count;
360
        $schema->resultset('ActionLog')
361
        ->search( { module => 'HOLDS', action => 'DELETE', object => $hold->{reserve_id} } )
362
        ->count;
361
    is( $number_of_logs, 0, 'With HoldsLogs, Koha::Hold->delete shouldn\'t have been logged' );
363
    is( $number_of_logs, 0, 'With HoldsLogs, Koha::Hold->delete shouldn\'t have been logged' );
362
364
363
    # Enable logging
365
    # Enable logging
Lines 376-383 subtest "delete() tests" => sub { Link Here
376
        "Koha::Hold->delete should have deleted the hold"
378
        "Koha::Hold->delete should have deleted the hold"
377
    );
379
    );
378
380
379
    $number_of_logs = $schema->resultset('ActionLog')
381
    $number_of_logs =
380
        ->search( { module => 'HOLDS', action => 'DELETE', object => $hold->{reserve_id} } )->count;
382
        $schema->resultset('ActionLog')
383
        ->search( { module => 'HOLDS', action => 'DELETE', object => $hold->{reserve_id} } )
384
        ->count;
381
    is( $number_of_logs, 1, 'With HoldsLogs, Koha::Hold->delete should have been logged' );
385
    is( $number_of_logs, 1, 'With HoldsLogs, Koha::Hold->delete should have been logged' );
382
386
383
    $schema->storage->txn_rollback();
387
    $schema->storage->txn_rollback();
Lines 469-475 subtest 'suspend() tests' => sub { Link Here
469
    t::lib::Mocks::mock_preference( 'HoldsLog', 1 );
473
    t::lib::Mocks::mock_preference( 'HoldsLog', 1 );
470
474
471
    my $logs_count =
475
    my $logs_count =
472
        $schema->resultset('ActionLog')->search( { module => 'HOLDS', action => 'SUSPEND', object => $hold->id } )
476
        $schema->resultset('ActionLog')
477
        ->search( { module => 'HOLDS', action => 'SUSPEND', object => $hold->id } )
473
        ->count;
478
        ->count;
474
479
475
    $hold = $builder->build_object(
480
    $hold = $builder->build_object(
Lines 481-487 subtest 'suspend() tests' => sub { Link Here
481
486
482
    $hold->suspend_hold;
487
    $hold->suspend_hold;
483
    my $new_logs_count =
488
    my $new_logs_count =
484
        $schema->resultset('ActionLog')->search( { module => 'HOLDS', action => 'SUSPEND', object => $hold->id } )
489
        $schema->resultset('ActionLog')
490
        ->search( { module => 'HOLDS', action => 'SUSPEND', object => $hold->id } )
485
        ->count;
491
        ->count;
486
492
487
    is( $new_logs_count, $logs_count + 1, 'If logging is enabled, suspending a hold gets logged' );
493
    is( $new_logs_count, $logs_count + 1, 'If logging is enabled, suspending a hold gets logged' );
(-)a/t/db_dependent/HoldsQueue/TransportCostOptimizations.t (-14 / +14 lines)
Lines 273-280 test_allocation( Link Here
273
test_allocation(
273
test_allocation(
274
    "different costs 1",
274
    "different costs 1",
275
    [
275
    [
276
        [ 0,  2,  2 ],
276
        [  0,  2, 2 ],
277
        [ 1,  0,  1 ],
277
        [  1,  0, 1 ],
278
        [ -1, -1, 0 ]
278
        [ -1, -1, 0 ]
279
    ],
279
    ],
280
    [ 3,        3,        0 ],
280
    [ 3,        3,        0 ],
Lines 286-293 test_allocation( Link Here
286
test_allocation(
286
test_allocation(
287
    "different costs 2",
287
    "different costs 2",
288
    [
288
    [
289
        [ 0,  2,  2 ],
289
        [  0,  2, 2 ],
290
        [ 1,  0,  1 ],
290
        [  1,  0, 1 ],
291
        [ -1, -1, 0 ]
291
        [ -1, -1, 0 ]
292
    ],
292
    ],
293
    [ 2,        2,        0 ],
293
    [ 2,        2,        0 ],
Lines 299-306 test_allocation( Link Here
299
test_allocation(
299
test_allocation(
300
    "allocation prohibited",
300
    "allocation prohibited",
301
    [
301
    [
302
        [ 0,  -1 ],
302
        [  0, -1 ],
303
        [ -1, 0 ],
303
        [ -1,  0 ],
304
    ],
304
    ],
305
    [ 2, 0 ],
305
    [ 2, 0 ],
306
    [ 0, 2 ],
306
    [ 0, 2 ],
Lines 311-319 test_allocation( Link Here
311
test_allocation(
311
test_allocation(
312
    "some allocation prohibited",
312
    "some allocation prohibited",
313
    [
313
    [
314
        [ 0,  -1, -1 ],
314
        [  0, -1, -1 ],
315
        [ -1, 0,  1 ],
315
        [ -1,  0,  1 ],
316
        [ -1, -1, 0 ]
316
        [ -1, -1,  0 ]
317
    ],
317
    ],
318
    [ 2,        2, 0 ],
318
    [ 2,        2, 0 ],
319
    [ 0,        0, 4 ],
319
    [ 0,        0, 4 ],
Lines 337-347 test_allocation( Link Here
337
test_allocation(
337
test_allocation(
338
    "prefer fewer fails",
338
    "prefer fewer fails",
339
    [
339
    [
340
        [ 0,  1,  1,  1,  1 ],
340
        [  0,  1,  1,  1,  1 ],
341
        [ -1, 0,  -1, -1, 1 ],
341
        [ -1,  0, -1, -1,  1 ],
342
        [ -1, -1, 0,  -1, -1 ],
342
        [ -1, -1,  0, -1, -1 ],
343
        [ -1, -1, -1, 0,  -1 ],
343
        [ -1, -1, -1,  0, -1 ],
344
        [ -1, -1, -1, -1, 0 ]
344
        [ -1, -1, -1, -1,  0 ]
345
    ],
345
    ],
346
    [ 1,        1, 0, 0, 0 ],
346
    [ 1,        1, 0, 0, 0 ],
347
    [ 0,        0, 1, 1, 1 ],
347
    [ 0,        0, 1, 1, 1 ],
(-)a/t/db_dependent/Koha/Account.t (-15 / +15 lines)
Lines 132-138 subtest 'outstanding_debits() tests' => sub { Link Here
132
        {
132
        {
133
            borrowernumber    => $patron_4->id,
133
            borrowernumber    => $patron_4->id,
134
            amount            => -3,
134
            amount            => -3,
135
            amountoutstanding => 3,
135
            amountoutstanding =>  3,
136
            interface         => 'commandline',
136
            interface         => 'commandline',
137
            credit_type_code  => 'PAYMENT'
137
            credit_type_code  => 'PAYMENT'
138
        }
138
        }
Lines 176-182 subtest 'outstanding_credits() tests' => sub { Link Here
176
    Koha::Account::Line->new(
176
    Koha::Account::Line->new(
177
        {
177
        {
178
            borrowernumber    => $patron_2->id,
178
            borrowernumber    => $patron_2->id,
179
            amount            => 2,
179
            amount            =>  2,
180
            amountoutstanding => -3,
180
            amountoutstanding => -3,
181
            interface         => 'commandline',
181
            interface         => 'commandline',
182
            debit_type_code   => 'OVERDUE'
182
            debit_type_code   => 'OVERDUE'
Lines 544-556 subtest 'reconcile_balance' => sub { Link Here
544
        )->store;
544
        )->store;
545
545
546
        is( $account->balance(),                              -5,  "Account balance is -5" );
546
        is( $account->balance(),                              -5,  "Account balance is -5" );
547
        is( $account->outstanding_debits->total_outstanding,  10,  'Outstanding debits sum 10' );
547
        is( $account->outstanding_debits->total_outstanding,   10, 'Outstanding debits sum 10' );
548
        is( $account->outstanding_credits->total_outstanding, -15, 'Outstanding credits sum -15' );
548
        is( $account->outstanding_credits->total_outstanding, -15, 'Outstanding credits sum -15' );
549
549
550
        $account->reconcile_balance();
550
        $account->reconcile_balance();
551
551
552
        is( $account->balance(),                              -5, "Account balance is -5" );
552
        is( $account->balance(),                              -5, "Account balance is -5" );
553
        is( $account->outstanding_debits->total_outstanding,  0,  'No outstanding debits' );
553
        is( $account->outstanding_debits->total_outstanding,   0, 'No outstanding debits' );
554
        is( $account->outstanding_credits->total_outstanding, -5, 'Outstanding credits sum -5' );
554
        is( $account->outstanding_credits->total_outstanding, -5, 'Outstanding credits sum -5' );
555
555
556
        $schema->storage->txn_rollback;
556
        $schema->storage->txn_rollback;
Lines 597-604 subtest 'reconcile_balance' => sub { Link Here
597
            }
597
            }
598
        )->store;
598
        )->store;
599
599
600
        is( $account->balance(),                              0,   "Account balance is 0" );
600
        is( $account->balance(),                               0,  "Account balance is 0" );
601
        is( $account->outstanding_debits->total_outstanding,  10,  'Outstanding debits sum 10' );
601
        is( $account->outstanding_debits->total_outstanding,   10, 'Outstanding debits sum 10' );
602
        is( $account->outstanding_credits->total_outstanding, -10, 'Outstanding credits sum -10' );
602
        is( $account->outstanding_credits->total_outstanding, -10, 'Outstanding credits sum -10' );
603
603
604
        $account->reconcile_balance();
604
        $account->reconcile_balance();
Lines 652-659 subtest 'reconcile_balance' => sub { Link Here
652
            }
652
            }
653
        )->store;
653
        )->store;
654
654
655
        is( $account->balance(),                              5,   "Account balance is 5" );
655
        is( $account->balance(),                               5,  "Account balance is 5" );
656
        is( $account->outstanding_debits->total_outstanding,  15,  'Outstanding debits sum 15' );
656
        is( $account->outstanding_debits->total_outstanding,   15, 'Outstanding debits sum 15' );
657
        is( $account->outstanding_credits->total_outstanding, -10, 'Outstanding credits sum -10' );
657
        is( $account->outstanding_credits->total_outstanding, -10, 'Outstanding credits sum -10' );
658
658
659
        $account->reconcile_balance();
659
        $account->reconcile_balance();
Lines 683-690 subtest 'reconcile_balance' => sub { Link Here
683
        my $debit_2 = $account->add_debit( { amount => 2, interface => 'commandline', type => 'OVERDUE' } );
683
        my $debit_2 = $account->add_debit( { amount => 2, interface => 'commandline', type => 'OVERDUE' } );
684
        my $debit_3 = $account->add_debit( { amount => 3, interface => 'commandline', type => 'OVERDUE' } );
684
        my $debit_3 = $account->add_debit( { amount => 3, interface => 'commandline', type => 'OVERDUE' } );
685
685
686
        is( $account->balance(),                              2,  "Account balance is 2" );
686
        is( $account->balance(),                               2, "Account balance is 2" );
687
        is( $account->outstanding_debits->total_outstanding,  6,  'Outstanding debits sum 6' );
687
        is( $account->outstanding_debits->total_outstanding,   6, 'Outstanding debits sum 6' );
688
        is( $account->outstanding_credits->total_outstanding, -4, 'Outstanding credits sum -4' );
688
        is( $account->outstanding_credits->total_outstanding, -4, 'Outstanding credits sum -4' );
689
689
690
        $account->reconcile_balance();
690
        $account->reconcile_balance();
Lines 1019-1025 subtest 'pay() handles lost items when paying by amount ( not specifying the los Link Here
1019
1019
1020
    $account->pay(
1020
    $account->pay(
1021
        {
1021
        {
1022
            amount     => .5,,
1022
            amount     => .5,
1023
            library_id => $library->id,
1023
            library_id => $library->id,
1024
        }
1024
        }
1025
    );
1025
    );
Lines 1363-1369 subtest 'Koha::Account::payout_amount() tests' => sub { Link Here
1363
    my $credit_3 = $account->add_credit( { amount => 5,  interface => 'commandline' } );
1363
    my $credit_3 = $account->add_credit( { amount => 5,  interface => 'commandline' } );
1364
    my $credit_4 = $account->add_credit( { amount => 10, interface => 'commandline' } );
1364
    my $credit_4 = $account->add_credit( { amount => 10, interface => 'commandline' } );
1365
    my $credits  = $account->outstanding_credits();
1365
    my $credits  = $account->outstanding_credits();
1366
    is( $credits->count,                 4,   "Found 4 credits with outstanding amounts" );
1366
    is( $credits->count,                  4,  "Found 4 credits with outstanding amounts" );
1367
    is( $credits->total_outstanding + 0, -20, "Total -20 outstanding credit" );
1367
    is( $credits->total_outstanding + 0, -20, "Total -20 outstanding credit" );
1368
1368
1369
    my $payout = $account->payout_amount($payout_params);
1369
    my $payout = $account->payout_amount($payout_params);
Lines 1371-1377 subtest 'Koha::Account::payout_amount() tests' => sub { Link Here
1371
    is( $payout->amount + 0,            10,                    "Payout amount recorded correctly" );
1371
    is( $payout->amount + 0,            10,                    "Payout amount recorded correctly" );
1372
    is( $payout->amountoutstanding + 0, 0,                     "Full amount was paid out" );
1372
    is( $payout->amountoutstanding + 0, 0,                     "Full amount was paid out" );
1373
    $credits = $account->outstanding_credits();
1373
    $credits = $account->outstanding_credits();
1374
    is( $credits->count,                 1,   "Payout was applied against oldest outstanding credits first" );
1374
    is( $credits->count,                  1,  "Payout was applied against oldest outstanding credits first" );
1375
    is( $credits->total_outstanding + 0, -10, "Total of 10 outstanding credit remaining" );
1375
    is( $credits->total_outstanding + 0, -10, "Total of 10 outstanding credit remaining" );
1376
1376
1377
    my $offsets = Koha::Account::Offsets->search( { debit_id => $payout->id } );
1377
    my $offsets = Koha::Account::Offsets->search( { debit_id => $payout->id } );
Lines 1400-1406 subtest 'Koha::Account::payout_amount() tests' => sub { Link Here
1400
    $payout                   = $account->payout_amount($payout_params);
1400
    $payout                   = $account->payout_amount($payout_params);
1401
1401
1402
    $credits = $account->outstanding_credits();
1402
    $credits = $account->outstanding_credits();
1403
    is( $credits->count,                 2,      "Second credit not fully paid off" );
1403
    is( $credits->count,                  2,     "Second credit not fully paid off" );
1404
    is( $credits->total_outstanding + 0, -12.50, "12.50 outstanding credit remaining" );
1404
    is( $credits->total_outstanding + 0, -12.50, "12.50 outstanding credit remaining" );
1405
    $credit_4->discard_changes;
1405
    $credit_4->discard_changes;
1406
    $credit_5->discard_changes;
1406
    $credit_5->discard_changes;
Lines 1496-1502 subtest 'Koha::Account::payin_amount() tests' => sub { Link Here
1496
    my $payin = $account->payin_amount($payin_params);
1496
    my $payin = $account->payin_amount($payin_params);
1497
    is( ref($payin),                   'Koha::Account::Line', 'Return the Koha::Account::Line object for the payin' );
1497
    is( ref($payin),                   'Koha::Account::Line', 'Return the Koha::Account::Line object for the payin' );
1498
    is( $payin->amount + 0,            -10,                   "Payin amount recorded correctly" );
1498
    is( $payin->amount + 0,            -10,                   "Payin amount recorded correctly" );
1499
    is( $payin->amountoutstanding + 0, 0,                     "Full amount was used to pay debts" );
1499
    is( $payin->amountoutstanding + 0,  0,                    "Full amount was used to pay debts" );
1500
    $debits = $account->outstanding_debits();
1500
    $debits = $account->outstanding_debits();
1501
    is( $debits->count,                 1,  "Payin was applied against oldest outstanding debits first" );
1501
    is( $debits->count,                 1,  "Payin was applied against oldest outstanding debits first" );
1502
    is( $debits->total_outstanding + 0, 10, "Total of 10 outstanding debit remaining" );
1502
    is( $debits->total_outstanding + 0, 10, "Total of 10 outstanding debit remaining" );
(-)a/t/db_dependent/Koha/Account/Line.t (-1 / +1 lines)
Lines 966-972 subtest "void() tests" => sub { Link Here
966
    is( $account_payment->credit_type_code,      'PAYMENT', 'Voided payment credit_type_code is still PAYMENT' );
966
    is( $account_payment->credit_type_code,      'PAYMENT', 'Voided payment credit_type_code is still PAYMENT' );
967
    is( $account_payment->status,                'VOID',    'Voided payment status is VOID' );
967
    is( $account_payment->status,                'VOID',    'Voided payment status is VOID' );
968
    is( $account_payment->amount + 0,            -30,       'Voided payment amount is still -30' );
968
    is( $account_payment->amount + 0,            -30,       'Voided payment amount is still -30' );
969
    is( $account_payment->amountoutstanding + 0, 0,         'Voided payment amount outstanding is 0' );
969
    is( $account_payment->amountoutstanding + 0,  0,        'Voided payment amount outstanding is 0' );
970
970
971
    is( $line1->amountoutstanding + 0, 10, 'First fee again has amount outstanding of 10' );
971
    is( $line1->amountoutstanding + 0, 10, 'First fee again has amount outstanding of 10' );
972
    is( $line2->amountoutstanding + 0, 20, 'Second fee again has amount outstanding of 20' );
972
    is( $line2->amountoutstanding + 0, 20, 'Second fee again has amount outstanding of 20' );
(-)a/t/db_dependent/Koha/Account/Lines.t (-3 / +3 lines)
Lines 311-317 subtest 'debits_total() tests' => sub { Link Here
311
            borrowernumber    => $patron->id,
311
            borrowernumber    => $patron->id,
312
            credit_type_code  => "PAYMENT",
312
            credit_type_code  => "PAYMENT",
313
            amount            => -10,
313
            amount            => -10,
314
            amountoutstanding => 0,
314
            amountoutstanding =>  0,
315
            interface         => 'commandline',
315
            interface         => 'commandline',
316
        }
316
        }
317
    )->store;
317
    )->store;
Lines 324-330 subtest 'debits_total() tests' => sub { Link Here
324
            borrowernumber    => $patron->id,
324
            borrowernumber    => $patron->id,
325
            credit_type_code  => "PAYMENT",
325
            credit_type_code  => "PAYMENT",
326
            amount            => -10,
326
            amount            => -10,
327
            amountoutstanding => 0,
327
            amountoutstanding =>  0,
328
            interface         => 'commandline',
328
            interface         => 'commandline',
329
        }
329
        }
330
    )->store;
330
    )->store;
Lines 337-343 subtest 'debits_total() tests' => sub { Link Here
337
            borrowernumber    => $patron->id,
337
            borrowernumber    => $patron->id,
338
            credit_type_code  => "PAYMENT",
338
            credit_type_code  => "PAYMENT",
339
            amount            => -100,
339
            amount            => -100,
340
            amountoutstanding => 0,
340
            amountoutstanding =>  0,
341
            interface         => 'commandline',
341
            interface         => 'commandline',
342
        }
342
        }
343
    )->store;
343
    )->store;
(-)a/t/db_dependent/Koha/Acquisition/Orders.t (-2 / +6 lines)
Lines 178-185 subtest 'filter_by_obsolete and cancel' => sub { Link Here
178
178
179
    # First make order 1 obsolete by removing biblio, and order 3 by status problem.
179
    # First make order 1 obsolete by removing biblio, and order 3 by status problem.
180
    my $date = Koha::DateUtils::dt_from_string->subtract( days => 7 );
180
    my $date = Koha::DateUtils::dt_from_string->subtract( days => 7 );
181
    $order_1->orderstatus('ordered')->quantity(2)->quantityreceived(0)->datecancellationprinted(undef)
181
    $order_1->orderstatus('ordered')
182
        ->entrydate($date)->store;
182
        ->quantity(2)
183
        ->quantityreceived(0)
184
        ->datecancellationprinted(undef)
185
        ->entrydate($date)
186
        ->store;
183
    Koha::Biblios->find( $order_1->biblionumber )->delete;
187
    Koha::Biblios->find( $order_1->biblionumber )->delete;
184
    $order_1->discard_changes;
188
    $order_1->discard_changes;
185
    $order_2->orderstatus('ordered')->quantity(3)->quantityreceived(0)->datecancellationprinted(undef)->store;
189
    $order_2->orderstatus('ordered')->quantity(3)->quantityreceived(0)->datecancellationprinted(undef)->store;
(-)a/t/db_dependent/Koha/AdditionalContents.t (-2 / +2 lines)
Lines 110-116 subtest '->is_expired' => sub { Link Here
110
110
111
    my $today     = dt_from_string;
111
    my $today     = dt_from_string;
112
    my $yesterday = dt_from_string->add( days => -1 );
112
    my $yesterday = dt_from_string->add( days => -1 );
113
    my $tomorrow  = dt_from_string->add( days => 1 );
113
    my $tomorrow  = dt_from_string->add( days =>  1 );
114
    my $new_today = $builder->build_object(
114
    my $new_today = $builder->build_object(
115
        {
115
        {
116
            class => 'Koha::AdditionalContents',
116
            class => 'Koha::AdditionalContents',
Lines 200-206 subtest '->search_for_display' => sub { Link Here
200
200
201
    my $today     = dt_from_string;
201
    my $today     = dt_from_string;
202
    my $yesterday = dt_from_string->add( days => -1 );
202
    my $yesterday = dt_from_string->add( days => -1 );
203
    my $tomorrow  = dt_from_string->add( days => 1 );
203
    my $tomorrow  = dt_from_string->add( days =>  1 );
204
    my $library1  = $builder->build_object( { class => 'Koha::Libraries' } );
204
    my $library1  = $builder->build_object( { class => 'Koha::Libraries' } );
205
    my $library2  = $builder->build_object( { class => 'Koha::Libraries' } );
205
    my $library2  = $builder->build_object( { class => 'Koha::Libraries' } );
206
206
(-)a/t/db_dependent/Koha/Charges/Sales.t (-1 / +1 lines)
Lines 231-237 subtest 'purchase tests' => sub { Link Here
231
    ok( $credit->is_credit, "return is a credit for payment" );
231
    ok( $credit->is_credit, "return is a credit for payment" );
232
    is( $credit->credit_type_code,      'PURCHASE', "credit_type_code set correctly to 'PURCHASE' for payment" );
232
    is( $credit->credit_type_code,      'PURCHASE', "credit_type_code set correctly to 'PURCHASE' for payment" );
233
    is( $credit->amount * 1,            -5,         "amount is calculated correctly for payment" );
233
    is( $credit->amount * 1,            -5,         "amount is calculated correctly for payment" );
234
    is( $credit->amountoutstanding * 1, 0,          "amountoutstanding is set to zero for payment" );
234
    is( $credit->amountoutstanding * 1,  0,         "amountoutstanding is set to zero for payment" );
235
    is( $credit->manager_id,            $staff->borrowernumber, "manager_id set correctionly for payment" );
235
    is( $credit->manager_id,            $staff->borrowernumber, "manager_id set correctionly for payment" );
236
    is( $credit->register_id,           $cash_register->id,     "register_id set correctly for payment" );
236
    is( $credit->register_id,           $cash_register->id,     "register_id set correctly for payment" );
237
    is( $credit->payment_type,          'CASH',                 "payment_type set correctly for payment" );
237
    is( $credit->payment_type,          'CASH',                 "payment_type set correctly for payment" );
(-)a/t/db_dependent/Koha/Checkouts.t (-3 / +3 lines)
Lines 78-86 is( Link Here
78
subtest 'is_overdue' => sub {
78
subtest 'is_overdue' => sub {
79
    plan tests => 6;
79
    plan tests => 6;
80
    my $ten_days_ago   = dt_from_string->add( days => -10 );
80
    my $ten_days_ago   = dt_from_string->add( days => -10 );
81
    my $ten_days_later = dt_from_string->add( days => 10 );
81
    my $ten_days_later = dt_from_string->add( days =>  10 );
82
    my $yesterday      = dt_from_string->add( days => -1 );
82
    my $yesterday      = dt_from_string->add( days => -1 );
83
    my $tomorrow       = dt_from_string->add( days => 1 );
83
    my $tomorrow       = dt_from_string->add( days =>  1 );
84
84
85
    $retrieved_checkout_1->date_due($ten_days_ago)->store;
85
    $retrieved_checkout_1->date_due($ten_days_ago)->store;
86
    is(
86
    is(
Lines 299-305 subtest 'Koha::Old::Checkouts->filter_by_todays_checkins' => sub { Link Here
299
                itemnumber     => $item->itemnumber,
299
                itemnumber     => $item->itemnumber,
300
                branchcode     => $library->{branchcode},
300
                branchcode     => $library->{branchcode},
301
            }
301
            }
302
        )->store;
302
            )->store;
303
    }
303
    }
304
304
305
    # Checkin 3 today - 2 days
305
    # Checkin 3 today - 2 days
(-)a/t/db_dependent/Koha/Holds.t (-4 / +6 lines)
Lines 466-472 subtest 'cancel' => sub { Link Here
466
        my $reserve_id = C4::Reserves::AddReserve($hold_info);
466
        my $reserve_id = C4::Reserves::AddReserve($hold_info);
467
        Koha::Holds->find($reserve_id)->cancel;
467
        Koha::Holds->find($reserve_id)->cancel;
468
        my $number_of_logs =
468
        my $number_of_logs =
469
            $schema->resultset('ActionLog')->search( { module => 'HOLDS', action => 'CANCEL', object => $reserve_id } )
469
            $schema->resultset('ActionLog')
470
            ->search( { module => 'HOLDS', action => 'CANCEL', object => $reserve_id } )
470
            ->count;
471
            ->count;
471
        is( $number_of_logs, 0, 'Without HoldsLog, Koha::Hold->cancel should not have logged' );
472
        is( $number_of_logs, 0, 'Without HoldsLog, Koha::Hold->cancel should not have logged' );
472
473
Lines 474-480 subtest 'cancel' => sub { Link Here
474
        $reserve_id = C4::Reserves::AddReserve($hold_info);
475
        $reserve_id = C4::Reserves::AddReserve($hold_info);
475
        Koha::Holds->find($reserve_id)->cancel;
476
        Koha::Holds->find($reserve_id)->cancel;
476
        $number_of_logs =
477
        $number_of_logs =
477
            $schema->resultset('ActionLog')->search( { module => 'HOLDS', action => 'CANCEL', object => $reserve_id } )
478
            $schema->resultset('ActionLog')
479
            ->search( { module => 'HOLDS', action => 'CANCEL', object => $reserve_id } )
478
            ->count;
480
            ->count;
479
        is( $number_of_logs, 1, 'With HoldsLog, Koha::Hold->cancel should have logged' );
481
        is( $number_of_logs, 1, 'With HoldsLog, Koha::Hold->cancel should have logged' );
480
    };
482
    };
Lines 828-835 subtest 'get_items_that_can_fill' => sub { Link Here
828
    my $item_4 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, itype => $itype_1->itemtype } )
830
    my $item_4 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, itype => $itype_1->itemtype } )
829
        ;    # in transfer
831
        ;    # in transfer
830
    my $item_5 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, itype => $itype_2->itemtype } );
832
    my $item_5 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, itype => $itype_2->itemtype } );
831
    my $lost       = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, itemlost   => 1 } );
833
    my $lost       = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, itemlost   =>  1 } );
832
    my $withdrawn  = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, withdrawn  => 1 } );
834
    my $withdrawn  = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, withdrawn  =>  1 } );
833
    my $notforloan = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, notforloan => -1 } );
835
    my $notforloan = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, notforloan => -1 } );
834
836
835
    my $patron_1 = $builder->build_object( { class => 'Koha::Patrons' } );
837
    my $patron_1 = $builder->build_object( { class => 'Koha::Patrons' } );
(-)a/t/db_dependent/Koha/ILL/Request/Config.t (-1 / +1 lines)
Lines 142-148 subtest 'opac_available_backends() tests' => sub { Link Here
142
};
142
};
143
143
144
my $base_limits = {
144
my $base_limits = {
145
    branch  => { CPL   => { count => 1,  method => 'annual' } },
145
    branch  => { CPL   => { count =>  1, method => 'annual' } },
146
    brw_cat => { A     => { count => -1, method => 'active' } },
146
    brw_cat => { A     => { count => -1, method => 'active' } },
147
    default => { count => 10, method => 'annual' },
147
    default => { count => 10, method => 'annual' },
148
};
148
};
(-)a/t/db_dependent/Koha/Item.t (-1 / +1 lines)
Lines 2863-2869 subtest 'store() tests' => sub { Link Here
2863
            {
2863
            {
2864
                borrowernumber    => $patron->id,
2864
                borrowernumber    => $patron->id,
2865
                date              => '1970-01-01 14:00:01',
2865
                date              => '1970-01-01 14:00:01',
2866
                amountoutstanding => 0,
2866
                amountoutstanding =>  0,
2867
                amount            => -5,
2867
                amount            => -5,
2868
                interface         => 'commandline',
2868
                interface         => 'commandline',
2869
                credit_type_code  => 'PAYMENT'
2869
                credit_type_code  => 'PAYMENT'
(-)a/t/db_dependent/Koha/Objects.t (-1 / +1 lines)
Lines 1186-1192 subtest "filter_by_last_update" => sub { Link Here
1186
                class => 'Koha::Patrons',
1186
                class => 'Koha::Patrons',
1187
                value => { updated_on => $now->clone->subtract( days => $i ) }
1187
                value => { updated_on => $now->clone->subtract( days => $i ) }
1188
            }
1188
            }
1189
        )->borrowernumber;
1189
            )->borrowernumber;
1190
    }
1190
    }
1191
1191
1192
    my $patrons = Koha::Patrons->search( { borrowernumber => { -in => \@borrowernumbers } } );
1192
    my $patrons = Koha::Patrons->search( { borrowernumber => { -in => \@borrowernumbers } } );
(-)a/t/db_dependent/Koha/Patrons.t (-11 / +20 lines)
Lines 502-508 subtest 'renew_account' => sub { Link Here
502
        );
502
        );
503
        my $number_of_logs =
503
        my $number_of_logs =
504
            $schema->resultset('ActionLog')
504
            $schema->resultset('ActionLog')
505
            ->search( { module => 'MEMBERS', action => 'RENEW', object => $retrieved_patron->borrowernumber } )->count;
505
            ->search( { module => 'MEMBERS', action => 'RENEW', object => $retrieved_patron->borrowernumber } )
506
            ->count;
506
        is( $number_of_logs, 1, 'With BorrowersLog, Koha::Patron->renew_account should have logged' );
507
        is( $number_of_logs, 1, 'With BorrowersLog, Koha::Patron->renew_account should have logged' );
507
508
508
        t::lib::Mocks::mock_preference( 'BorrowerRenewalPeriodBase', 'now' );
509
        t::lib::Mocks::mock_preference( 'BorrowerRenewalPeriodBase', 'now' );
Lines 518-524 subtest 'renew_account' => sub { Link Here
518
        is( dt_from_string($retrieved_expiry_date), $a_year_later, "today + 12 months must be $a_year_later" );
519
        is( dt_from_string($retrieved_expiry_date), $a_year_later, "today + 12 months must be $a_year_later" );
519
        $number_of_logs =
520
        $number_of_logs =
520
            $schema->resultset('ActionLog')
521
            $schema->resultset('ActionLog')
521
            ->search( { module => 'MEMBERS', action => 'RENEW', object => $retrieved_patron->borrowernumber } )->count;
522
            ->search( { module => 'MEMBERS', action => 'RENEW', object => $retrieved_patron->borrowernumber } )
523
            ->count;
522
        is( $number_of_logs, 1, 'Without BorrowersLog, Koha::Patron->renew_account should not have logged' );
524
        is( $number_of_logs, 1, 'Without BorrowersLog, Koha::Patron->renew_account should not have logged' );
523
525
524
        t::lib::Mocks::mock_preference( 'BorrowerRenewalPeriodBase', 'combination' );
526
        t::lib::Mocks::mock_preference( 'BorrowerRenewalPeriodBase', 'combination' );
Lines 654-660 subtest "delete" => sub { Link Here
654
656
655
    my $number_of_logs =
657
    my $number_of_logs =
656
        $schema->resultset('ActionLog')
658
        $schema->resultset('ActionLog')
657
        ->search( { module => 'MEMBERS', action => 'DELETE', object => $patron->borrowernumber } )->count;
659
        ->search( { module => 'MEMBERS', action => 'DELETE', object => $patron->borrowernumber } )
660
        ->count;
658
    is( $number_of_logs, 1, 'With BorrowersLog, Koha::Patron->delete should have logged' );
661
    is( $number_of_logs, 1, 'With BorrowersLog, Koha::Patron->delete should have logged' );
659
662
660
    # Test deletion with designated fallback owner
663
    # Test deletion with designated fallback owner
Lines 727-733 subtest 'add_enrolment_fee_if_needed' => sub { Link Here
727
    foreach ( keys %{$enrolmentfees} ) {
730
    foreach ( keys %{$enrolmentfees} ) {
728
        ( Koha::Patron::Categories->find($_)
731
        ( Koha::Patron::Categories->find($_)
729
                // $builder->build_object( { class => 'Koha::Patron::Categories', value => { categorycode => $_ } } ) )
732
                // $builder->build_object( { class => 'Koha::Patron::Categories', value => { categorycode => $_ } } ) )
730
            ->enrolmentfee( $enrolmentfees->{$_} )->store;
733
            ->enrolmentfee( $enrolmentfees->{$_} )
734
            ->store;
731
    }
735
    }
732
    my $enrolmentfee_K  = $enrolmentfees->{K};
736
    my $enrolmentfee_K  = $enrolmentfees->{K};
733
    my $enrolmentfee_J  = $enrolmentfees->{J};
737
    my $enrolmentfee_J  = $enrolmentfees->{J};
Lines 2475-2481 subtest '->set_password' => sub { Link Here
2475
2479
2476
    my $number_of_logs =
2480
    my $number_of_logs =
2477
        $schema->resultset('ActionLog')
2481
        $schema->resultset('ActionLog')
2478
        ->search( { module => 'MEMBERS', action => 'CHANGE PASS', object => $patron->borrowernumber } )->count;
2482
        ->search( { module => 'MEMBERS', action => 'CHANGE PASS', object => $patron->borrowernumber } )
2483
        ->count;
2479
    is( $number_of_logs, 0, 'Without BorrowersLog, Koha::Patron->set_password doesn\'t log password changes' );
2484
    is( $number_of_logs, 0, 'Without BorrowersLog, Koha::Patron->set_password doesn\'t log password changes' );
2480
2485
2481
    # Enable logging password changes
2486
    # Enable logging password changes
Lines 3005-3012 subtest "search_patrons_to_update_category tests" => sub { Link Here
3005
                class => 'Koha::Patrons',
3010
                class => 'Koha::Patrons',
3006
                value => {
3011
                value => {
3007
                    categorycode => $category_code,
3012
                    categorycode => $category_code,
3008
                    dateofbirth  =>
3013
                    dateofbirth  => $current_dt->clone->subtract( years => $category->upperagelimit + 1 )
3009
                        $current_dt->clone->subtract( years => $category->upperagelimit + 1 )->subtract( days => 1 )
3014
                        ->subtract( days => 1 )
3010
                        ->ymd,
3015
                        ->ymd,
3011
                }
3016
                }
3012
            }
3017
            }
Lines 3456-3462 subtest 'filter_by_have_permission' => sub { Link Here
3456
    is_deeply(
3461
    is_deeply(
3457
        [
3462
        [
3458
            Koha::Patrons->search( { branchcode => $library->branchcode } )
3463
            Koha::Patrons->search( { branchcode => $library->branchcode } )
3459
                ->filter_by_have_permission('suggestions.suggestions_manage')->get_column('borrowernumber')
3464
                ->filter_by_have_permission('suggestions.suggestions_manage')
3465
                ->get_column('borrowernumber')
3460
        ],
3466
        ],
3461
        [ $patron_1->borrowernumber, $patron_2->borrowernumber ],
3467
        [ $patron_1->borrowernumber, $patron_2->borrowernumber ],
3462
        'Superlibrarian and patron with suggestions.suggestions_manage'
3468
        'Superlibrarian and patron with suggestions.suggestions_manage'
Lines 3465-3471 subtest 'filter_by_have_permission' => sub { Link Here
3465
    is_deeply(
3471
    is_deeply(
3466
        [
3472
        [
3467
            Koha::Patrons->search( { branchcode => $library->branchcode } )
3473
            Koha::Patrons->search( { branchcode => $library->branchcode } )
3468
                ->filter_by_have_permission('acquisition.order_manage')->get_column('borrowernumber')
3474
                ->filter_by_have_permission('acquisition.order_manage')
3475
                ->get_column('borrowernumber')
3469
        ],
3476
        ],
3470
        [ $patron_1->borrowernumber, $patron_3->borrowernumber ],
3477
        [ $patron_1->borrowernumber, $patron_3->borrowernumber ],
3471
        'Superlibrarian and patron with acquisition.order_manage'
3478
        'Superlibrarian and patron with acquisition.order_manage'
Lines 3474-3480 subtest 'filter_by_have_permission' => sub { Link Here
3474
    is_deeply(
3481
    is_deeply(
3475
        [
3482
        [
3476
            Koha::Patrons->search( { branchcode => $library->branchcode } )
3483
            Koha::Patrons->search( { branchcode => $library->branchcode } )
3477
                ->filter_by_have_permission('parameters.manage_cities')->get_column('borrowernumber')
3484
                ->filter_by_have_permission('parameters.manage_cities')
3485
                ->get_column('borrowernumber')
3478
        ],
3486
        ],
3479
        [ $patron_1->borrowernumber ],
3487
        [ $patron_1->borrowernumber ],
3480
        'Only Superlibrarian is returned'
3488
        'Only Superlibrarian is returned'
Lines 3482-3488 subtest 'filter_by_have_permission' => sub { Link Here
3482
3490
3483
    is_deeply(
3491
    is_deeply(
3484
        [
3492
        [
3485
            Koha::Patrons->search( { branchcode => $library->branchcode } )->filter_by_have_permission('suggestions')
3493
            Koha::Patrons->search( { branchcode => $library->branchcode } )
3494
                ->filter_by_have_permission('suggestions')
3486
                ->get_column('borrowernumber')
3495
                ->get_column('borrowernumber')
3487
        ],
3496
        ],
3488
        [ $patron_1->borrowernumber, $patron_2->borrowernumber ],
3497
        [ $patron_1->borrowernumber, $patron_2->borrowernumber ],
(-)a/t/db_dependent/Koha/Plugins/Plugins.t (-10 / +10 lines)
Lines 563-582 subtest 'Test _version_compare' => sub { Link Here
563
    t::lib::Mocks::mock_config( 'enable_plugins', 1 );
563
    t::lib::Mocks::mock_config( 'enable_plugins', 1 );
564
564
565
    is( Koha::Plugins::Base::_version_compare( '1.1.1',    '2.2.2' ), -1, "1.1.1 is less then 2.2.2" );
565
    is( Koha::Plugins::Base::_version_compare( '1.1.1',    '2.2.2' ), -1, "1.1.1 is less then 2.2.2" );
566
    is( Koha::Plugins::Base::_version_compare( '2.2.2',    '1.1.1' ), 1,  "1.1.1 is greater then 2.2.2" );
566
    is( Koha::Plugins::Base::_version_compare( '2.2.2',    '1.1.1' ),  1, "1.1.1 is greater then 2.2.2" );
567
    is( Koha::Plugins::Base::_version_compare( '1.1.1',    '1.1.1' ), 0,  "1.1.1 is equal to 1.1.1" );
567
    is( Koha::Plugins::Base::_version_compare( '1.1.1',    '1.1.1' ),  0, "1.1.1 is equal to 1.1.1" );
568
    is( Koha::Plugins::Base::_version_compare( '1.01.001', '1.1.1' ), 0,  "1.01.001 is equal to 1.1.1" );
568
    is( Koha::Plugins::Base::_version_compare( '1.01.001', '1.1.1' ),  0, "1.01.001 is equal to 1.1.1" );
569
    is( Koha::Plugins::Base::_version_compare( '1',        '1.0.0' ), 0,  "1 is equal to 1.0.0" );
569
    is( Koha::Plugins::Base::_version_compare( '1',        '1.0.0' ),  0, "1 is equal to 1.0.0" );
570
    is( Koha::Plugins::Base::_version_compare( '1.0',      '1.0.0' ), 0,  "1.0 is equal to 1.0.0" );
570
    is( Koha::Plugins::Base::_version_compare( '1.0',      '1.0.0' ),  0, "1.0 is equal to 1.0.0" );
571
571
572
    # OO tests
572
    # OO tests
573
    my $plugin = Koha::Plugin::Test->new;
573
    my $plugin = Koha::Plugin::Test->new;
574
    is( $plugin->_version_compare( '1.1.1',    '2.2.2' ), -1, "1.1.1 is less then 2.2.2" );
574
    is( $plugin->_version_compare( '1.1.1',    '2.2.2' ), -1, "1.1.1 is less then 2.2.2" );
575
    is( $plugin->_version_compare( '2.2.2',    '1.1.1' ), 1,  "1.1.1 is greater then 2.2.2" );
575
    is( $plugin->_version_compare( '2.2.2',    '1.1.1' ),  1, "1.1.1 is greater then 2.2.2" );
576
    is( $plugin->_version_compare( '1.1.1',    '1.1.1' ), 0,  "1.1.1 is equal to 1.1.1" );
576
    is( $plugin->_version_compare( '1.1.1',    '1.1.1' ),  0, "1.1.1 is equal to 1.1.1" );
577
    is( $plugin->_version_compare( '1.01.001', '1.1.1' ), 0,  "1.01.001 is equal to 1.1.1" );
577
    is( $plugin->_version_compare( '1.01.001', '1.1.1' ),  0, "1.01.001 is equal to 1.1.1" );
578
    is( $plugin->_version_compare( '1',        '1.0.0' ), 0,  "1 is equal to 1.0.0" );
578
    is( $plugin->_version_compare( '1',        '1.0.0' ),  0, "1 is equal to 1.0.0" );
579
    is( $plugin->_version_compare( '1.0',      '1.0.0' ), 0,  "1.0 is equal to 1.0.0" );
579
    is( $plugin->_version_compare( '1.0',      '1.0.0' ),  0, "1.0 is equal to 1.0.0" );
580
};
580
};
581
581
582
subtest 'bundle_path() tests' => sub {
582
subtest 'bundle_path() tests' => sub {
(-)a/t/db_dependent/Koha/REST/Plugin/Auth/IdP.t (-5 / +10 lines)
Lines 150-160 subtest 'auth.register helper' => sub { Link Here
150
    )->status_is(200)->json_is( '/userid', $userid_1 );
150
    )->status_is(200)->json_is( '/userid', $userid_1 );
151
151
152
    $t->post_ok( '/register_user' => json =>
152
    $t->post_ok( '/register_user' => json =>
153
            { data => {}, domain_id => $domain_2->identity_provider_domain_id, interface => 'opac' } )->status_is(401)
153
            { data => {}, domain_id => $domain_2->identity_provider_domain_id, interface => 'opac' } )
154
        ->status_is(401)
154
        ->json_is( '/message', 'unauthorized' );
155
        ->json_is( '/message', 'unauthorized' );
155
156
156
    $t->post_ok( '/register_user' => json =>
157
    $t->post_ok( '/register_user' => json =>
157
            { data => {}, domain_id => $domain_1->identity_provider_domain_id, interface => 'staff' } )->status_is(401)
158
            { data => {}, domain_id => $domain_1->identity_provider_domain_id, interface => 'staff' } )
159
        ->status_is(401)
158
        ->json_is( '/message', 'unauthorized' );
160
        ->json_is( '/message', 'unauthorized' );
159
161
160
    $t->post_ok(
162
    $t->post_ok(
Lines 172-182 subtest 'auth.register helper' => sub { Link Here
172
    )->status_is(200)->json_is( '/userid', $userid_2 );
174
    )->status_is(200)->json_is( '/userid', $userid_2 );
173
175
174
    $t->post_ok( '/register_user' => json => { data => {}, domain_id => $domain_1->identity_provider_domain_id } )
176
    $t->post_ok( '/register_user' => json => { data => {}, domain_id => $domain_1->identity_provider_domain_id } )
175
        ->status_is(400)->json_is( '/message', 'missing parameter: interface' );
177
        ->status_is(400)
178
        ->json_is( '/message', 'missing parameter: interface' );
176
179
177
    $t->post_ok( '/register_user' => json =>
180
    $t->post_ok( '/register_user' => json =>
178
            { data => {}, domain_id => $domain_1->identity_provider_domain_id, interface => 'invalid' } )
181
            { data => {}, domain_id => $domain_1->identity_provider_domain_id, interface => 'invalid' } )
179
        ->status_is(400)->json_is( '/message', 'bad parameter: interface' );
182
        ->status_is(400)
183
        ->json_is( '/message', 'bad parameter: interface' );
180
184
181
    $schema->storage->txn_rollback;
185
    $schema->storage->txn_rollback;
182
};
186
};
Lines 188-194 subtest 'auth.session helper' => sub { Link Here
188
192
189
    my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
193
    my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
190
194
191
    $t->post_ok( '/start_session' => json => { userid => $patron->userid } )->status_is(200)
195
    $t->post_ok( '/start_session' => json => { userid => $patron->userid } )
196
        ->status_is(200)
192
        ->json_has( '/status', 'ok' );
197
        ->json_has( '/status', 'ok' );
193
198
194
    $schema->storage->txn_rollback;
199
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/Koha/REST/Plugin/Auth/PublicRoutes.t (-7 / +14 lines)
Lines 96-111 subtest 'auth.public helper' => sub { Link Here
96
96
97
    my $t = Test::Mojo->new;
97
    my $t = Test::Mojo->new;
98
98
99
    $t->post_ok( '/public' => json => { patron_id => $another_patron->borrowernumber } )->status_is(401)
99
    $t->post_ok( '/public' => json => { patron_id => $another_patron->borrowernumber } )
100
        ->status_is(401)
100
        ->json_is( { message => 'authentication_required' } );
101
        ->json_is( { message => 'authentication_required' } );
101
102
102
    $t->post_ok( '/public' => json =>
103
    $t->post_ok( '/public' => json =>
103
            { user => $unprivileged_patron->borrowernumber, patron_id => $another_patron->borrowernumber } )
104
            { user => $unprivileged_patron->borrowernumber, patron_id => $another_patron->borrowernumber } )
104
        ->status_is(403)->json_is( { message => 'unauthorized' } );
105
        ->status_is(403)
106
        ->json_is( { message => 'unauthorized' } );
105
107
106
    $t->post_ok( '/public' => json =>
108
    $t->post_ok( '/public' => json =>
107
            { user => $unprivileged_patron->borrowernumber, patron_id => $unprivileged_patron->borrowernumber } )
109
            { user => $unprivileged_patron->borrowernumber, patron_id => $unprivileged_patron->borrowernumber } )
108
        ->status_is(200)->json_is('OK');
110
        ->status_is(200)
111
        ->json_is('OK');
109
112
110
    $schema->storage->txn_rollback;
113
    $schema->storage->txn_rollback;
111
};
114
};
Lines 124-144 subtest 'auth.public_guarantor helper' => sub { Link Here
124
127
125
    my $t = Test::Mojo->new;
128
    my $t = Test::Mojo->new;
126
129
127
    $t->post_ok( '/public_guarantor' => json => { patron_id => $another_patron->borrowernumber } )->status_is(401)
130
    $t->post_ok( '/public_guarantor' => json => { patron_id => $another_patron->borrowernumber } )
131
        ->status_is(401)
128
        ->json_is( { message => 'authentication_required' } );
132
        ->json_is( { message => 'authentication_required' } );
129
133
130
    $t->post_ok( '/public_guarantor' => json =>
134
    $t->post_ok( '/public_guarantor' => json =>
131
            { user => $guarantor->borrowernumber, patron_id => $another_patron->borrowernumber } )->status_is(403)
135
            { user => $guarantor->borrowernumber, patron_id => $another_patron->borrowernumber } )
136
        ->status_is(403)
132
        ->json_is( { message => 'unauthorized' } );
137
        ->json_is( { message => 'unauthorized' } );
133
138
134
    # user is not a guarantor of themself
139
    # user is not a guarantor of themself
135
    $t->post_ok(
140
    $t->post_ok(
136
        '/public_guarantor' => json => { user => $guarantor->borrowernumber, patron_id => $guarantor->borrowernumber } )
141
        '/public_guarantor' => json => { user => $guarantor->borrowernumber, patron_id => $guarantor->borrowernumber } )
137
        ->status_is(403)->json_is( { message => 'unauthorized' } );
142
        ->status_is(403)
143
        ->json_is( { message => 'unauthorized' } );
138
144
139
    $t->post_ok(
145
    $t->post_ok(
140
        '/public_guarantor' => json => { user => $guarantor->borrowernumber, patron_id => $guarantee->borrowernumber } )
146
        '/public_guarantor' => json => { user => $guarantor->borrowernumber, patron_id => $guarantee->borrowernumber } )
141
        ->status_is(200)->json_is('OK');
147
        ->status_is(200)
148
        ->json_is('OK');
142
149
143
    $schema->storage->txn_rollback;
150
    $schema->storage->txn_rollback;
144
};
151
};
(-)a/t/db_dependent/Koha/REST/Plugin/Objects.t (-42 / +128 lines)
Lines 186-193 subtest 'objects.search helper' => sub { Link Here
186
    );
186
    );
187
187
188
    my $t = Test::Mojo->new;
188
    my $t = Test::Mojo->new;
189
    $t->get_ok('/cities?name=manuel&_per_page=1&_page=1')->status_is(200)
189
    $t->get_ok('/cities?name=manuel&_per_page=1&_page=1')
190
        ->header_like( 'Link' => qr/<http:\/\/.*[\?&]_page=2.*>; rel="next",/ )->json_has('/0')->json_hasnt('/1')
190
        ->status_is(200)
191
        ->header_like( 'Link' => qr/<http:\/\/.*[\?&]_page=2.*>; rel="next",/ )
192
        ->json_has('/0')
193
        ->json_hasnt('/1')
191
        ->json_is( '/0/name' => 'Manuel' );
194
        ->json_is( '/0/name' => 'Manuel' );
192
195
193
    $builder->build_object(
196
    $builder->build_object(
Lines 198-219 subtest 'objects.search helper' => sub { Link Here
198
    );
201
    );
199
202
200
    # _match=starts_with
203
    # _match=starts_with
201
    $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=starts_with')->status_is(200)->json_has('/0')
204
    $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=starts_with')
202
        ->json_has('/1')->json_has('/2')->json_hasnt('/3')->json_is( '/0/name' => 'Manuel' )
205
        ->status_is(200)
203
        ->json_is( '/1/name' => 'Manuela' )->json_is( '/2/name' => 'Manuelab' );
206
        ->json_has('/0')
207
        ->json_has('/1')
208
        ->json_has('/2')
209
        ->json_hasnt('/3')
210
        ->json_is( '/0/name' => 'Manuel' )
211
        ->json_is( '/1/name' => 'Manuela' )
212
        ->json_is( '/2/name' => 'Manuelab' );
204
213
205
    # _match=ends_with
214
    # _match=ends_with
206
    $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=ends_with')->status_is(200)->json_has('/0')
215
    $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=ends_with')
207
        ->json_has('/1')->json_hasnt('/2')->json_is( '/0/name' => 'Manuel' )->json_is( '/1/name' => 'Emanuel' );
216
        ->status_is(200)
217
        ->json_has('/0')
218
        ->json_has('/1')
219
        ->json_hasnt('/2')
220
        ->json_is( '/0/name' => 'Manuel' )
221
        ->json_is( '/1/name' => 'Emanuel' );
208
222
209
    # _match=exact
223
    # _match=exact
210
    $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=exact')->status_is(200)->json_has('/0')
224
    $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=exact')
211
        ->json_hasnt('/1')->json_is( '/0/name' => 'Manuel' );
225
        ->status_is(200)
226
        ->json_has('/0')
227
        ->json_hasnt('/1')
228
        ->json_is( '/0/name' => 'Manuel' );
212
229
213
    # _match=contains
230
    # _match=contains
214
    $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=contains')->status_is(200)->json_has('/0')
231
    $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=contains')
215
        ->json_has('/1')->json_has('/2')->json_has('/3')->json_hasnt('/4')->json_is( '/0/name' => 'Manuel' )
232
        ->status_is(200)
216
        ->json_is( '/1/name' => 'Manuela' )->json_is( '/2/name' => 'Manuelab' )->json_is( '/3/name' => 'Emanuel' );
233
        ->json_has('/0')
234
        ->json_has('/1')
235
        ->json_has('/2')
236
        ->json_has('/3')
237
        ->json_hasnt('/4')
238
        ->json_is( '/0/name' => 'Manuel' )
239
        ->json_is( '/1/name' => 'Manuela' )
240
        ->json_is( '/2/name' => 'Manuelab' )
241
        ->json_is( '/3/name' => 'Emanuel' );
217
242
218
    # Add 20 more cities
243
    # Add 20 more cities
219
    for ( 1 .. 20 ) {
244
    for ( 1 .. 20 ) {
Lines 262-287 subtest 'objects.search helper, sorting on mapped column' => sub { Link Here
262
    my $t = Test::Mojo->new;
287
    my $t = Test::Mojo->new;
263
288
264
    # CSV-param
289
    # CSV-param
265
    $t->get_ok('/cities?_order_by=%2Bname,-country')->status_is(200)->json_has('/0')->json_has('/1')
290
    $t->get_ok('/cities?_order_by=%2Bname,-country')
266
        ->json_is( '/0/name' => 'A' )->json_is( '/1/name' => 'B' )->json_is( '/2/name' => 'C' )
291
        ->status_is(200)
267
        ->json_is( '/2/country' => 'Belarus' )->json_is( '/3/name' => 'C' )->json_is( '/3/country' => 'Argentina' )
292
        ->json_has('/0')
293
        ->json_has('/1')
294
        ->json_is( '/0/name'    => 'A' )
295
        ->json_is( '/1/name'    => 'B' )
296
        ->json_is( '/2/name'    => 'C' )
297
        ->json_is( '/2/country' => 'Belarus' )
298
        ->json_is( '/3/name'    => 'C' )
299
        ->json_is( '/3/country' => 'Argentina' )
268
        ->json_hasnt('/4');
300
        ->json_hasnt('/4');
269
301
270
    # Multi-param: traditional
302
    # Multi-param: traditional
271
    $t->get_ok('/cities?_order_by=%2Bname&_order_by=-country')->status_is(200)->json_has('/0')->json_has('/1')
303
    $t->get_ok('/cities?_order_by=%2Bname&_order_by=-country')
272
        ->json_is( '/0/name' => 'A' )->json_is( '/1/name' => 'B' )->json_is( '/2/name' => 'C' )
304
        ->status_is(200)
273
        ->json_is( '/2/country' => 'Belarus' )->json_is( '/3/name' => 'C' )->json_is( '/3/country' => 'Argentina' )
305
        ->json_has('/0')
306
        ->json_has('/1')
307
        ->json_is( '/0/name'    => 'A' )
308
        ->json_is( '/1/name'    => 'B' )
309
        ->json_is( '/2/name'    => 'C' )
310
        ->json_is( '/2/country' => 'Belarus' )
311
        ->json_is( '/3/name'    => 'C' )
312
        ->json_is( '/3/country' => 'Argentina' )
274
        ->json_hasnt('/4');
313
        ->json_hasnt('/4');
275
314
276
    # Multi-param: PHP Style, Passes validation as above, subsequently explodes
315
    # Multi-param: PHP Style, Passes validation as above, subsequently explodes
277
    $t->get_ok('/cities?_order_by[]=%2Bname&_order_by[]=-country')->status_is(200)->json_has('/0')->json_has('/1')
316
    $t->get_ok('/cities?_order_by[]=%2Bname&_order_by[]=-country')
278
        ->json_is( '/0/name' => 'A' )->json_is( '/1/name' => 'B' )->json_is( '/2/name' => 'C' )
317
        ->status_is(200)
279
        ->json_is( '/2/country' => 'Belarus' )->json_is( '/3/name' => 'C' )->json_is( '/3/country' => 'Argentina' )
318
        ->json_has('/0')
319
        ->json_has('/1')
320
        ->json_is( '/0/name'    => 'A' )
321
        ->json_is( '/1/name'    => 'B' )
322
        ->json_is( '/2/name'    => 'C' )
323
        ->json_is( '/2/country' => 'Belarus' )
324
        ->json_is( '/3/name'    => 'C' )
325
        ->json_is( '/3/country' => 'Argentina' )
280
        ->json_hasnt('/4');
326
        ->json_hasnt('/4');
281
327
282
    # Single-param
328
    # Single-param
283
    $t->get_ok('/cities?_order_by=-name')->status_is(200)->json_has('/0')->json_has('/1')->json_is( '/0/name' => 'C' )
329
    $t->get_ok('/cities?_order_by=-name')
284
        ->json_is( '/1/name' => 'C' )->json_is( '/2/name' => 'B' )->json_is( '/3/name' => 'A' )->json_hasnt('/4');
330
        ->status_is(200)
331
        ->json_has('/0')
332
        ->json_has('/1')
333
        ->json_is( '/0/name' => 'C' )
334
        ->json_is( '/1/name' => 'C' )
335
        ->json_is( '/2/name' => 'B' )
336
        ->json_is( '/3/name' => 'A' )
337
        ->json_hasnt('/4');
285
338
286
    $schema->storage->txn_rollback;
339
    $schema->storage->txn_rollback;
287
};
340
};
Lines 298-304 subtest 'objects.search helper, encoding' => sub { Link Here
298
    $builder->build_object( { class => 'Koha::Cities', value => { city_name => 'B', city_country => '❤Argentina❤' } } );
351
    $builder->build_object( { class => 'Koha::Cities', value => { city_name => 'B', city_country => '❤Argentina❤' } } );
299
352
300
    my $t = Test::Mojo->new;
353
    my $t = Test::Mojo->new;
301
    $t->get_ok('/cities?q={"country": "❤Argentina❤"}')->status_is(200)->json_has('/0')->json_hasnt('/1')
354
    $t->get_ok('/cities?q={"country": "❤Argentina❤"}')
355
        ->status_is(200)
356
        ->json_has('/0')
357
        ->json_hasnt('/1')
302
        ->json_is( '/0/name' => 'B' );
358
        ->json_is( '/0/name' => 'B' );
303
359
304
    $schema->storage->txn_rollback;
360
    $schema->storage->txn_rollback;
Lines 326-336 subtest 'objects.search helper, X-Total-Count and X-Base-Total-Count' => sub { Link Here
326
    }
382
    }
327
383
328
    my $t = Test::Mojo->new;
384
    my $t = Test::Mojo->new;
329
    $t->get_ok('/cities?name=L&_per_page=10&_page=1&_match=starts_with')->status_is(200)
385
    $t->get_ok('/cities?name=L&_per_page=10&_page=1&_match=starts_with')
386
        ->status_is(200)
330
        ->header_is( 'X-Total-Count'      => 20, 'X-Total-Count header present' )
387
        ->header_is( 'X-Total-Count'      => 20, 'X-Total-Count header present' )
331
        ->header_is( 'X-Base-Total-Count' => 20, 'X-Base-Total-Count header present' );
388
        ->header_is( 'X-Base-Total-Count' => 20, 'X-Base-Total-Count header present' );
332
389
333
    $t->get_ok('/cities?name=Llan&_per_page=10&_page=1&_match=starts_with')->status_is(200)
390
    $t->get_ok('/cities?name=Llan&_per_page=10&_page=1&_match=starts_with')
391
        ->status_is(200)
334
        ->header_is( 'X-Total-Count'      => 17, 'X-Total-Count header present' )
392
        ->header_is( 'X-Total-Count'      => 17, 'X-Total-Count header present' )
335
        ->header_is( 'X-Base-Total-Count' => 20, 'X-Base-Total-Count header present' );
393
        ->header_is( 'X-Base-Total-Count' => 20, 'X-Base-Total-Count header present' );
336
394
Lines 656-668 subtest 'objects.search helper, search_limited() tests' => sub { Link Here
656
    t::lib::Mocks::mock_userenv( { patron => $patron } );
714
    t::lib::Mocks::mock_userenv( { patron => $patron } );
657
715
658
    $t->get_ok( "/my_patrons?q=" . encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )
716
    $t->get_ok( "/my_patrons?q=" . encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )
659
        ->status_is(200)->json_is( '/0/patron_id' => $patron_1->id )->json_is( '/1/patron_id' => $patron_2->id )
717
        ->status_is(200)
718
        ->json_is( '/0/patron_id' => $patron_1->id )
719
        ->json_is( '/1/patron_id' => $patron_2->id )
660
        ->json_is( '/2/patron_id' => $patron_3->id );
720
        ->json_is( '/2/patron_id' => $patron_3->id );
661
721
662
    @libraries_where_can_see_patrons = ( $library_2->id );
722
    @libraries_where_can_see_patrons = ( $library_2->id );
663
723
664
    my $res = $t->get_ok( "/my_patrons?q=" . encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )
724
    my $res =
665
        ->status_is(200)->json_is( '/0/patron_id' => $patron_3->id, 'Returns the only allowed patron' )->tx->res->json;
725
        $t->get_ok( "/my_patrons?q=" . encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )
726
        ->status_is(200)
727
        ->json_is( '/0/patron_id' => $patron_3->id, 'Returns the only allowed patron' )
728
        ->tx->res->json;
666
729
667
    is( scalar @{$res}, 1, 'Only one patron returned' );
730
    is( scalar @{$res}, 1, 'Only one patron returned' );
668
731
Lines 760-775 subtest 'objects.find helper with expanded authorised values' => sub { Link Here
760
        }
823
        }
761
    );
824
    );
762
825
763
    $t->get_ok( '/cities/' . $manuel->id => { 'x-koha-embed' => '+strings' } )->status_is(200)
826
    $t->get_ok( '/cities/' . $manuel->id => { 'x-koha-embed' => '+strings' } )
764
        ->json_is( '/name' => 'Manuel' )->json_has('/_strings')->json_is( '/_strings/country/type' => 'av' )
827
        ->status_is(200)
828
        ->json_is( '/name' => 'Manuel' )
829
        ->json_has('/_strings')
830
        ->json_is( '/_strings/country/type'     => 'av' )
765
        ->json_is( '/_strings/country/category' => $cat->category_name )
831
        ->json_is( '/_strings/country/category' => $cat->category_name )
766
        ->json_is( '/_strings/country/str'      => $ar->lib );
832
        ->json_is( '/_strings/country/str'      => $ar->lib );
767
833
768
    $t->get_ok( '/cities/' . $manuel->id => { 'x-koha-embed' => '' } )->status_is(200)->json_is( '/name' => 'Manuel' )
834
    $t->get_ok( '/cities/' . $manuel->id => { 'x-koha-embed' => '' } )
835
        ->status_is(200)
836
        ->json_is( '/name' => 'Manuel' )
769
        ->json_hasnt('/_strings');
837
        ->json_hasnt('/_strings');
770
838
771
    $t->get_ok( '/cities/' . $manuela->id => { 'x-koha-embed' => '+strings' } )->status_is(200)
839
    $t->get_ok( '/cities/' . $manuela->id => { 'x-koha-embed' => '+strings' } )
772
        ->json_is( '/name' => 'Manuela' )->json_has('/_strings')->json_is( '/_strings/country/type' => 'av' )
840
        ->status_is(200)
841
        ->json_is( '/name' => 'Manuela' )
842
        ->json_has('/_strings')
843
        ->json_is( '/_strings/country/type'     => 'av' )
773
        ->json_is( '/_strings/country/category' => $cat->category_name )
844
        ->json_is( '/_strings/country/category' => $cat->category_name )
774
        ->json_is( '/_strings/country/str'      => $us->lib );
845
        ->json_is( '/_strings/country/str'      => $us->lib );
775
846
Lines 868-884 subtest 'objects.search helper with expanded authorised values' => sub { Link Here
868
    );
939
    );
869
940
870
    $t->get_ok( '/cities?name=manuel&_per_page=4&_page=1&_match=starts_with' => { 'x-koha-embed' => '+strings' } )
941
    $t->get_ok( '/cities?name=manuel&_per_page=4&_page=1&_match=starts_with' => { 'x-koha-embed' => '+strings' } )
871
        ->status_is(200)->json_has('/0')->json_has('/1')->json_hasnt('/2')->json_is( '/0/name' => 'Manuel' )
942
        ->status_is(200)
872
        ->json_has('/0/_strings')->json_is( '/0/_strings/country/str' => $ar->lib )
943
        ->json_has('/0')
944
        ->json_has('/1')
945
        ->json_hasnt('/2')
946
        ->json_is( '/0/name' => 'Manuel' )
947
        ->json_has('/0/_strings')
948
        ->json_is( '/0/_strings/country/str'      => $ar->lib )
873
        ->json_is( '/0/_strings/country/type'     => 'av' )
949
        ->json_is( '/0/_strings/country/type'     => 'av' )
874
        ->json_is( '/0/_strings/country/category' => $cat->category_name )->json_is( '/1/name' => 'Manuela' )
950
        ->json_is( '/0/_strings/country/category' => $cat->category_name )
875
        ->json_has('/1/_strings')->json_is( '/1/_strings/country/str' => $us->lib )
951
        ->json_is( '/1/name'                      => 'Manuela' )
952
        ->json_has('/1/_strings')
953
        ->json_is( '/1/_strings/country/str'      => $us->lib )
876
        ->json_is( '/1/_strings/country/type'     => 'av' )
954
        ->json_is( '/1/_strings/country/type'     => 'av' )
877
        ->json_is( '/1/_strings/country/category' => $cat->category_name );
955
        ->json_is( '/1/_strings/country/category' => $cat->category_name );
878
956
879
    $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=starts_with')->status_is(200)->json_has('/0')
957
    $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=starts_with')
880
        ->json_has('/1')->json_hasnt('/2')->json_is( '/0/name' => 'Manuel' )->json_hasnt('/0/_strings')
958
        ->status_is(200)
881
        ->json_is( '/1/name' => 'Manuela' )->json_hasnt('/1/_strings');
959
        ->json_has('/0')
960
        ->json_has('/1')
961
        ->json_hasnt('/2')
962
        ->json_is( '/0/name' => 'Manuel' )
963
        ->json_hasnt('/0/_strings')
964
        ->json_is( '/1/name' => 'Manuela' )
965
        ->json_hasnt('/1/_strings');
882
966
883
    $schema->storage->txn_rollback;
967
    $schema->storage->txn_rollback;
884
};
968
};
Lines 994-1000 subtest 'date handling' => sub { Link Here
994
            borrowernumber => $patron->id
1078
            borrowernumber => $patron->id
995
        }
1079
        }
996
    );
1080
    );
997
    $t->get_ok( "//$userid:$password@/api/v1/jobs?q=" . $q )->status_is(200)->json_is( '/0/job_id' => $job_1->id )
1081
    $t->get_ok( "//$userid:$password@/api/v1/jobs?q=" . $q )
1082
        ->status_is(200)
1083
        ->json_is( '/0/job_id' => $job_1->id )
998
        ->json_is( '/1/job_id' => $job_3->id );
1084
        ->json_is( '/1/job_id' => $job_3->id );
999
    $response_count = scalar @{ $t->tx->res->json };
1085
    $response_count = scalar @{ $t->tx->res->json };
1000
    is( $response_count, 2 );
1086
    is( $response_count, 2 );
(-)a/t/db_dependent/Koha/REST/Plugin/Pagination.t (-11 / +23 lines)
Lines 101-111 subtest 'add_pagination_headers() tests' => sub { Link Here
101
101
102
    my $t = Test::Mojo->new;
102
    my $t = Test::Mojo->new;
103
103
104
    $t->get_ok('/empty')->status_is(200)->header_is( 'X-Total-Count' => undef, 'X-Total-Count is undefined' )
104
    $t->get_ok('/empty')
105
        ->status_is(200)
106
        ->header_is( 'X-Total-Count'      => undef, 'X-Total-Count is undefined' )
105
        ->header_is( 'X-Base-Total-Count' => undef, 'X-Base-Total-Count is undefined' )
107
        ->header_is( 'X-Base-Total-Count' => undef, 'X-Base-Total-Count is undefined' )
106
        ->header_is( 'Link'               => undef, 'Link is undefined' );
108
        ->header_is( 'Link'               => undef, 'Link is undefined' );
107
109
108
    $t->get_ok('/pagination_headers?firstname=Jonathan&_page=2&_per_page=3')->status_is(200)
110
    $t->get_ok('/pagination_headers?firstname=Jonathan&_page=2&_per_page=3')
111
        ->status_is(200)
109
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count correctly set' )
112
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count correctly set' )
110
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
113
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
111
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*_per_page=3.*>; rel="prev",/ )
114
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*_per_page=3.*>; rel="prev",/ )
Lines 121-127 subtest 'add_pagination_headers() tests' => sub { Link Here
121
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*_page=4.*>; rel="last"/ )
124
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*_page=4.*>; rel="last"/ )
122
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
125
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
123
126
124
    $t->get_ok('/pagination_headers?firstname=Jonathan&_page=1&_per_page=3')->status_is(200)
127
    $t->get_ok('/pagination_headers?firstname=Jonathan&_page=1&_per_page=3')
128
        ->status_is(200)
125
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count correctly set' )
129
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count correctly set' )
126
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
130
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
127
        ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*>; rel="prev",/ )
131
        ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*>; rel="prev",/ )
Lines 135-141 subtest 'add_pagination_headers() tests' => sub { Link Here
135
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*_page=4.*>; rel="last"/ )
139
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*_page=4.*>; rel="last"/ )
136
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
140
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
137
141
138
    $t->get_ok('/pagination_headers?firstname=Jonathan&_page=4&_per_page=3')->status_is(200)
142
    $t->get_ok('/pagination_headers?firstname=Jonathan&_page=4&_per_page=3')
143
        ->status_is(200)
139
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count correctly set' )
144
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count correctly set' )
140
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
145
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
141
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*_per_page=3.*>; rel="prev",/ )
146
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*_per_page=3.*>; rel="prev",/ )
Lines 150-156 subtest 'add_pagination_headers() tests' => sub { Link Here
150
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
155
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
151
156
152
    t::lib::Mocks::mock_preference( 'RESTdefaultPageSize', 3 );
157
    t::lib::Mocks::mock_preference( 'RESTdefaultPageSize', 3 );
153
    $t->get_ok('/pagination_headers?firstname=Jonathan&_page=2')->status_is(200)
158
    $t->get_ok('/pagination_headers?firstname=Jonathan&_page=2')
159
        ->status_is(200)
154
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count correctly set' )
160
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count correctly set' )
155
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
161
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
156
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=3.*>; rel="prev",/ )
162
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=3.*>; rel="prev",/ )
Lines 166-172 subtest 'add_pagination_headers() tests' => sub { Link Here
166
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=4.*>; rel="last"/ )
172
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=4.*>; rel="last"/ )
167
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
173
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
168
174
169
    $t->get_ok('/pagination_headers?firstname=Jonathan&_per_page=3')->status_is(200)
175
    $t->get_ok('/pagination_headers?firstname=Jonathan&_per_page=3')
176
        ->status_is(200)
170
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count header present, even without page param' )
177
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count header present, even without page param' )
171
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
178
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
172
        ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*per_page=3.*>; rel="prev",/,         'First page, no previous' )
179
        ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*per_page=3.*>; rel="prev",/,         'First page, no previous' )
Lines 182-188 subtest 'add_pagination_headers() tests' => sub { Link Here
182
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=4.*>; rel="last"/ )
189
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=4.*>; rel="last"/ )
183
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
190
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
184
191
185
    $t->get_ok('/pagination_headers?firstname=Jonathan&_per_page=-1')->status_is(200)
192
    $t->get_ok('/pagination_headers?firstname=Jonathan&_per_page=-1')
193
        ->status_is(200)
186
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count header present, with per_page=-1' )
194
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count header present, with per_page=-1' )
187
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
195
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
188
        ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="prev",/,        'First page, no previous' )
196
        ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="prev",/,        'First page, no previous' )
Lines 191-204 subtest 'add_pagination_headers() tests' => sub { Link Here
191
        ->header_unlike(
199
        ->header_unlike(
192
        'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="next",/,
200
        'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="next",/,
193
        'No next page, all resources are fetched'
201
        'No next page, all resources are fetched'
194
    )->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="first",/ )
202
        )
203
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="first",/ )
195
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="first",/ )
204
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="first",/ )
196
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="first",/ )
205
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="first",/ )
197
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="last"/ )
206
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="last"/ )
198
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="last"/ )
207
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="last"/ )
199
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
208
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
200
209
201
    $t->get_ok('/pagination_headers?firstname=Jonathan&_per_page=-1&_page=100')->status_is(200)
210
    $t->get_ok('/pagination_headers?firstname=Jonathan&_per_page=-1&_page=100')
211
        ->status_is(200)
202
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count header present, with per_page=-1' )
212
        ->header_is( 'X-Total-Count'      => 10, 'X-Total-Count header present, with per_page=-1' )
203
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
213
        ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
204
        ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="prev",/,        'First page, no previous' )
214
        ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="prev",/,        'First page, no previous' )
Lines 207-213 subtest 'add_pagination_headers() tests' => sub { Link Here
207
        ->header_unlike(
217
        ->header_unlike(
208
        'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="next",/,
218
        'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="next",/,
209
        'No next page, all resources are fetched'
219
        'No next page, all resources are fetched'
210
    )->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="first",/ )
220
        )
221
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="first",/ )
211
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="first",/ )
222
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="first",/ )
212
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="first",/ )
223
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="first",/ )
213
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="last"/ )
224
        ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="last"/ )
Lines 221-226 subtest 'dbic_merge_pagination() tests' => sub { Link Here
221
232
222
    my $t = Test::Mojo->new;
233
    my $t = Test::Mojo->new;
223
234
224
    $t->get_ok('/dbic_merge_pagination')->status_is(200)
235
    $t->get_ok('/dbic_merge_pagination')
236
        ->status_is(200)
225
        ->json_is( { firstname => 'Kyle', surname => 'Hall', page => 1, rows => 3 } );
237
        ->json_is( { firstname => 'Kyle', surname => 'Hall', page => 1, rows => 3 } );
226
};
238
};
(-)a/t/db_dependent/Koha/UI/Form/Builder/Item.t (-1 / +1 lines)
Lines 83-89 subtest 'authorised values' => sub { Link Here
83
            $subfield->{marc_value}->{values},
83
            $subfield->{marc_value}->{values},
84
            [
84
            [
85
                "",
85
                "",
86
                map      { $_->authorised_value }
86
                map { $_->authorised_value }
87
                    sort { $a->lib cmp $b->lib } $avs->as_list
87
                    sort { $a->lib cmp $b->lib } $avs->as_list
88
            ],
88
            ],
89
            'AVs are sorted by lib and en empty option is created first'
89
            'AVs are sorted by lib and en empty option is created first'
(-)a/t/db_dependent/Patrons.t (-3 / +6 lines)
Lines 247-256 subtest "Update patron categories" => sub { Link Here
247
    is( Koha::Patrons->search_patrons_to_update_category( { from => $c_categorycode, too_old => 1 } )
247
    is( Koha::Patrons->search_patrons_to_update_category( { from => $c_categorycode, too_old => 1 } )
248
            ->next->borrowernumber, $child3->borrowernumber, 'Over age patron in child category is expected one' );
248
            ->next->borrowernumber, $child3->borrowernumber, 'Over age patron in child category is expected one' );
249
    is( Koha::Patrons->search( { branchcode => $branchcode2 } )
249
    is( Koha::Patrons->search( { branchcode => $branchcode2 } )
250
            ->search_patrons_to_update_category( { from => $a_categorycode } )->count, 1, 'One patron in branch 2' );
250
            ->search_patrons_to_update_category( { from => $a_categorycode } )
251
            ->count, 1, 'One patron in branch 2' );
251
    is(
252
    is(
252
        Koha::Patrons->search( { branchcode => $branchcode2 } )
253
        Koha::Patrons->search( { branchcode => $branchcode2 } )
253
            ->search_patrons_to_update_category( { from => $a_categorycode } )->next->borrowernumber,
254
            ->search_patrons_to_update_category( { from => $a_categorycode } )
255
            ->next->borrowernumber,
254
        $adult2->borrowernumber, 'Adult patron in branch 2 is expected one'
256
        $adult2->borrowernumber, 'Adult patron in branch 2 is expected one'
255
    );
257
    );
256
    is(
258
    is(
Lines 344-350 subtest "Update patron categories" => sub { Link Here
344
346
345
    is(
347
    is(
346
        Koha::Patrons->search_patrons_to_update_category( { from => $a_categorycode, fine_max => 5 } )
348
        Koha::Patrons->search_patrons_to_update_category( { from => $a_categorycode, fine_max => 5 } )
347
            ->search( { "me.borrowernumber" => $adult1->borrowernumber } )->next->borrowernumber,
349
            ->search( { "me.borrowernumber" => $adult1->borrowernumber } )
350
            ->next->borrowernumber,
348
        $adult1->borrowernumber, 'Expected patron is in the list of patrons to update'
351
        $adult1->borrowernumber, 'Expected patron is in the list of patrons to update'
349
    );
352
    );
350
    my $userid_before = $adult1->userid;
353
    my $userid_before = $adult1->userid;
(-)a/t/db_dependent/Reserves/CancelExpiredReserves.t (-1 / +1 lines)
Lines 130-136 subtest 'Test handling of waiting reserves by CancelExpiredReserves' => sub { Link Here
130
130
131
    my $resdate    = dt_from_string->add( days => -20 );
131
    my $resdate    = dt_from_string->add( days => -20 );
132
    my $expdate    = dt_from_string->add( days => -2 );
132
    my $expdate    = dt_from_string->add( days => -2 );
133
    my $notexpdate = dt_from_string->add( days => 2 );
133
    my $notexpdate = dt_from_string->add( days =>  2 );
134
134
135
    my $hold1 = Koha::Hold->new(
135
    my $hold1 = Koha::Hold->new(
136
        {
136
        {
(-)a/t/db_dependent/SocialData.t (-1 / +2 lines)
Lines 59-65 subtest 'get_report' => sub { Link Here
59
    is( $report->{'without'}->[0]->{'isbn'},     '9780596526740', 'testing get_report' );
59
    is( $report->{'without'}->[0]->{'isbn'},     '9780596526740', 'testing get_report' );
60
60
61
    # test if we can get with key instead
61
    # test if we can get with key instead
62
    $schema->resultset('SocialData')->search( { isbn => '0-596-52674-1' } )
62
    $schema->resultset('SocialData')
63
        ->search( { isbn => '0-596-52674-1' } )
63
        ->next->update( { isbn => '9780596526740' } );
64
        ->next->update( { isbn => '9780596526740' } );
64
    $report = C4::SocialData::get_report();
65
    $report = C4::SocialData::get_report();
65
    is( $report->{with}->[0]->{isbn}, '9780596526740', 'this isbn has social data' );
66
    is( $report->{with}->[0]->{isbn}, '9780596526740', 'this isbn has social data' );
(-)a/t/db_dependent/TestBuilder.t (-1 / +2 lines)
Lines 162-168 subtest 'Test FKs in overduerules_transport_type' => sub { Link Here
162
        'build stores the categorycode correctly'
162
        'build stores the categorycode correctly'
163
    );
163
    );
164
    is(
164
    is(
165
        $schema->resultset('MessageTransportType')->find( $overduerules_transport_type->{message_transport_type} )
165
        $schema->resultset('MessageTransportType')
166
            ->find( $overduerules_transport_type->{message_transport_type} )
166
            ->message_transport_type,
167
            ->message_transport_type,
167
        $overduerules_transport_type->{message_transport_type},
168
        $overduerules_transport_type->{message_transport_type},
168
        'build stores the foreign key message_transport_type correctly'
169
        'build stores the foreign key message_transport_type correctly'
(-)a/t/db_dependent/api/v1/acquisitions_funds.t (-1 / +2 lines)
Lines 81-87 $t->get_ok( "//$unauth_userid:$unauth_password@/api/v1/acquisitions/funds?name=" Link Here
81
81
82
$t->get_ok("//$userid:$password@/api/v1/acquisitions/funds")->status_is(200);
82
$t->get_ok("//$userid:$password@/api/v1/acquisitions/funds")->status_is(200);
83
83
84
$t->get_ok( "//$userid:$password@/api/v1/acquisitions/funds?name=" . $fund_name )->status_is(200)
84
$t->get_ok( "//$userid:$password@/api/v1/acquisitions/funds?name=" . $fund_name )
85
    ->status_is(200)
85
    ->json_like( '/0/name' => qr/$fund_name/ );
86
    ->json_like( '/0/name' => qr/$fund_name/ );
86
87
87
$schema->storage->txn_rollback;
88
$schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/acquisitions_orders.t (-13 / +26 lines)
Lines 81-87 subtest 'list() tests' => sub { Link Here
81
81
82
    # Make sure we are returned with the correct amount of orders
82
    # Make sure we are returned with the correct amount of orders
83
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/orders?status=new&_per_page=-1")
83
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/orders?status=new&_per_page=-1")
84
        ->status_is( 200, 'REST3.2.2' )->json_has( '/' . ( $count_of_orders - 1 ) . '/order_id' )
84
        ->status_is( 200, 'REST3.2.2' )
85
        ->json_has( '/' . ( $count_of_orders - 1 ) . '/order_id' )
85
        ->json_hasnt( '/' . ($count_of_orders) . '/order_id' );
86
        ->json_hasnt( '/' . ($count_of_orders) . '/order_id' );
86
87
87
    subtest 'query parameters' => sub {
88
    subtest 'query parameters' => sub {
Lines 146-152 subtest 'list() tests' => sub { Link Here
146
    is( scalar @{ $result->tx->res->json }, 1, 'Only one order is active' );
147
    is( scalar @{ $result->tx->res->json }, 1, 'Only one order is active' );
147
148
148
    # Warn on unsupported query parameter
149
    # Warn on unsupported query parameter
149
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/orders?order_blah=blah")->status_is(400)
150
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/orders?order_blah=blah")
151
        ->status_is(400)
150
        ->json_is( [ { path => '/query/order_blah', message => 'Malformed query string' } ] );
152
        ->json_is( [ { path => '/query/order_blah', message => 'Malformed query string' } ] );
151
153
152
    subtest 'sorting tests' => sub {
154
    subtest 'sorting tests' => sub {
Lines 184-190 subtest 'list() tests' => sub { Link Here
184
        my $result =
186
        my $result =
185
            $t->get_ok(
187
            $t->get_ok(
186
            "//$userid:$password@/api/v1/acquisitions/orders?_order_by=+me.order_id&basket_id=" . $basket->id )
188
            "//$userid:$password@/api/v1/acquisitions/orders?_order_by=+me.order_id&basket_id=" . $basket->id )
187
            ->status_is( 200, "query successful" )->tx->res->json;
189
            ->status_is( 200, "query successful" )
190
            ->tx->res->json;
188
191
189
        is( scalar @$result, 2, 'Two elements returned' );
192
        is( scalar @$result, 2, 'Two elements returned' );
190
193
Lines 195-201 subtest 'list() tests' => sub { Link Here
195
        $result =
198
        $result =
196
            $t->get_ok(
199
            $t->get_ok(
197
            "//$userid:$password@/api/v1/acquisitions/orders?_order_by=-me.order_id&basket_id=" . $basket->id )
200
            "//$userid:$password@/api/v1/acquisitions/orders?_order_by=-me.order_id&basket_id=" . $basket->id )
198
            ->status_is( 200, "query successful" )->tx->res->json;
201
            ->status_is( 200, "query successful" )
202
            ->tx->res->json;
199
203
200
        is( scalar @$result, 2, 'Two elements returned' );
204
        is( scalar @$result, 2, 'Two elements returned' );
201
205
Lines 255-266 subtest 'get() tests' => sub { Link Here
255
    my $userid = $patron->userid;
259
    my $userid = $patron->userid;
256
260
257
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/orders/" . $order->ordernumber )
261
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/orders/" . $order->ordernumber )
258
        ->status_is( 200, 'REST3.2.2' )->json_is( '' => $order->to_api, 'REST3.3.2' );
262
        ->status_is( 200, 'REST3.2.2' )
263
        ->json_is( '' => $order->to_api, 'REST3.3.2' );
259
264
260
    my $non_existent_order_id = $order->ordernumber;
265
    my $non_existent_order_id = $order->ordernumber;
261
    $order->delete;
266
    $order->delete;
262
267
263
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/orders/" . $non_existent_order_id )->status_is(404)
268
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/orders/" . $non_existent_order_id )
269
        ->status_is(404)
264
        ->json_is( '/error' => 'Order not found' );
270
        ->json_is( '/error' => 'Order not found' );
265
271
266
    # FIXME This does not work on all the OS we support
272
    # FIXME This does not work on all the OS we support
Lines 336-342 subtest 'add() tests' => sub { Link Here
336
    $order_with_invalid_field->{'orderinvalid'} = 'Order invalid';
342
    $order_with_invalid_field->{'orderinvalid'} = 'Order invalid';
337
343
338
    $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders" => json => $order_with_invalid_field )
344
    $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders" => json => $order_with_invalid_field )
339
        ->status_is(400)->json_is(
345
        ->status_is(400)
346
        ->json_is(
340
        "/errors" => [
347
        "/errors" => [
341
            {
348
            {
342
                message => "Properties not allowed: orderinvalid.",
349
                message => "Properties not allowed: orderinvalid.",
Lines 347-353 subtest 'add() tests' => sub { Link Here
347
354
348
    # Authorized attempt to write
355
    # Authorized attempt to write
349
    $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders" => json => $order )
356
    $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders" => json => $order )
350
        ->status_is( 201, 'REST3.2.1' )->json_is( '/internal_note' => $order->{internal_note}, 'REST3.3.1' )
357
        ->status_is( 201, 'REST3.2.1' )
358
        ->json_is( '/internal_note' => $order->{internal_note}, 'REST3.3.1' )
351
        ->header_like( Location => qr/\/api\/v1\/acquisitions\/orders\/\d*/, 'REST3.4.1' );
359
        ->header_like( Location => qr/\/api\/v1\/acquisitions\/orders\/\d*/, 'REST3.4.1' );
352
360
353
    # save the order_id
361
    # save the order_id
Lines 356-369 subtest 'add() tests' => sub { Link Here
356
    # Authorized attempt to create with null id
364
    # Authorized attempt to create with null id
357
    $order->{order_id} = undef;
365
    $order->{order_id} = undef;
358
366
359
    $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders" => json => $order )->status_is(400)
367
    $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders" => json => $order )
368
        ->status_is(400)
360
        ->json_has('/errors');
369
        ->json_has('/errors');
361
370
362
    # Authorized attempt to create with existing id
371
    # Authorized attempt to create with existing id
363
    $order->{order_id} = $order_id;
372
    $order->{order_id} = $order_id;
364
373
365
    warning_like {
374
    warning_like {
366
        $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders" => json => $order )->status_is(409)
375
        $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders" => json => $order )
376
            ->status_is(409)
367
            ->json_has( '/error' => "Fails when trying to add an existing order_id" )
377
            ->json_has( '/error' => "Fails when trying to add an existing order_id" )
368
            ->json_like( '/conflict' => qr/(aqorders\.)?PRIMARY/ );
378
            ->json_like( '/conflict' => qr/(aqorders\.)?PRIMARY/ );
369
    }
379
    }
Lines 437-450 subtest 'update() tests' => sub { Link Here
437
    $deleted_library->delete;
447
    $deleted_library->delete;
438
448
439
    $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_updated_field )
449
    $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_updated_field )
440
        ->status_is( 200, 'REST3.2.1' )->json_is( '' => $library_with_updated_field, 'REST3.3.3' );
450
        ->status_is( 200, 'REST3.2.1' )
451
        ->json_is( '' => $library_with_updated_field, 'REST3.3.3' );
441
452
442
    # Authorized attempt to write invalid data
453
    # Authorized attempt to write invalid data
443
    my $library_with_invalid_field = {%$library_with_updated_field};
454
    my $library_with_invalid_field = {%$library_with_updated_field};
444
    $library_with_invalid_field->{'branchinvalid'} = 'Library invalid';
455
    $library_with_invalid_field->{'branchinvalid'} = 'Library invalid';
445
456
446
    $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_invalid_field )
457
    $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_invalid_field )
447
        ->status_is(400)->json_is(
458
        ->status_is(400)
459
        ->json_is(
448
        "/errors" => [
460
        "/errors" => [
449
            {
461
            {
450
                message => "Properties not allowed: branchinvalid.",
462
                message => "Properties not allowed: branchinvalid.",
Lines 494-500 subtest 'delete() tests' => sub { Link Here
494
    $t->delete_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders/" . $order->ordernumber )->status_is(409);
506
    $t->delete_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders/" . $order->ordernumber )->status_is(409);
495
    $order->orderstatus('cancelled')->store;
507
    $order->orderstatus('cancelled')->store;
496
    $t->delete_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders/" . $order->ordernumber )
508
    $t->delete_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders/" . $order->ordernumber )
497
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
509
        ->status_is( 204, 'REST3.2.4' )
510
        ->content_is( '', 'REST3.3.4' );
498
    $t->delete_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders/" . $order->ordernumber )->status_is(404);
511
    $t->delete_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders/" . $order->ordernumber )->status_is(404);
499
512
500
    $schema->storage->txn_rollback;
513
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/acquisitions_vendor_issues.t (-2 / +4 lines)
Lines 64-76 subtest 'list() tests' => sub { Link Here
64
    )->store;
64
    )->store;
65
65
66
    # One issue created, should get returned
66
    # One issue created, should get returned
67
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/vendors/$vendor_id/issues")->status_is(200)
67
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/vendors/$vendor_id/issues")
68
        ->status_is(200)
68
        ->json_is( [ $issue->to_api ] );
69
        ->json_is( [ $issue->to_api ] );
69
70
70
    # Embed the AV description
71
    # Embed the AV description
71
    $t->get_ok(
72
    $t->get_ok(
72
        "//$userid:$password@/api/v1/acquisitions/vendors/$vendor_id/issues" => { 'x-koha-embed' => '+strings' } )
73
        "//$userid:$password@/api/v1/acquisitions/vendors/$vendor_id/issues" => { 'x-koha-embed' => '+strings' } )
73
        ->status_is(200)->json_is( [ $issue->to_api( { strings => 1 } ) ] );
74
        ->status_is(200)
75
        ->json_is( [ $issue->to_api( { strings => 1 } ) ] );
74
76
75
    $vendor->delete;
77
    $vendor->delete;
76
78
(-)a/t/db_dependent/api/v1/acquisitions_vendors.t (-43 / +95 lines)
Lines 63-93 subtest 'list() and delete() tests | authorized user' => sub { Link Here
63
        $builder->build_object( { class => 'Koha::Acquisition::Booksellers', value => { name => $vendor_name } } );
63
        $builder->build_object( { class => 'Koha::Acquisition::Booksellers', value => { name => $vendor_name } } );
64
64
65
    # One vendor created, should get returned
65
    # One vendor created, should get returned
66
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/vendors")->status_is(200)
66
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/vendors")
67
        ->status_is(200)
67
        ->json_like( '/0/name' => qr/$vendor_name/ );
68
        ->json_like( '/0/name' => qr/$vendor_name/ );
68
69
69
    my $other_vendor_name = 'Amerindia';
70
    my $other_vendor_name = 'Amerindia';
70
    my $other_vendor      = $builder->build_object(
71
    my $other_vendor      = $builder->build_object(
71
        { class => 'Koha::Acquisition::Booksellers', value => { name => $other_vendor_name } } );
72
        { class => 'Koha::Acquisition::Booksellers', value => { name => $other_vendor_name } } );
72
73
73
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/vendors")->status_is(200)->json_like( '/0/name' => qr/Ruben/ )
74
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/vendors")
75
        ->status_is(200)
76
        ->json_like( '/0/name' => qr/Ruben/ )
74
        ->json_like( '/1/name' => qr/Amerindia/ );
77
        ->json_like( '/1/name' => qr/Amerindia/ );
75
78
76
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/vendors?name=$vendor_name")->status_is(200)
79
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/vendors?name=$vendor_name")
80
        ->status_is(200)
77
        ->json_like( '/0/name' => qr/Ruben/ );
81
        ->json_like( '/0/name' => qr/Ruben/ );
78
82
79
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/vendors?name=$other_vendor_name")->status_is(200)
83
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/vendors?name=$other_vendor_name")
84
        ->status_is(200)
80
        ->json_like( '/0/name' => qr/Amerindia/ );
85
        ->json_like( '/0/name' => qr/Amerindia/ );
81
86
82
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors?accountnumber=" . $vendor->accountnumber )
87
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors?accountnumber=" . $vendor->accountnumber )
83
        ->status_is(200)->json_like( '/0/name' => qr/Ruben/ );
88
        ->status_is(200)
89
        ->json_like( '/0/name' => qr/Ruben/ );
84
90
85
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors?accountnumber=" . $other_vendor->accountnumber )
91
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors?accountnumber=" . $other_vendor->accountnumber )
86
        ->status_is(200)->json_like( '/0/name' => qr/Amerindia/ );
92
        ->status_is(200)
93
        ->json_like( '/0/name' => qr/Amerindia/ );
87
94
88
    my @aliases = ( { alias => 'alias 1' }, { alias => 'alias 2' } );
95
    my @aliases = ( { alias => 'alias 1' }, { alias => 'alias 2' } );
89
    $vendor->aliases( \@aliases );
96
    $vendor->aliases( \@aliases );
90
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors" => { 'x-koha-embed' => 'aliases' } )->status_is(200)
97
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors" => { 'x-koha-embed' => 'aliases' } )
98
        ->status_is(200)
91
        ->json_has( '/0/aliases', 'aliases are embedded' )
99
        ->json_has( '/0/aliases', 'aliases are embedded' )
92
        ->json_is( '/0/aliases/0/alias' => 'alias 1', 'alias 1 is embedded' )
100
        ->json_is( '/0/aliases/0/alias' => 'alias 1', 'alias 1 is embedded' )
93
        ->json_is( '/0/aliases/1/alias' => 'alias 2', 'alias 2 is embedded' );
101
        ->json_is( '/0/aliases/1/alias' => 'alias 2', 'alias 2 is embedded' );
Lines 104-110 subtest 'list() and delete() tests | authorized user' => sub { Link Here
104
            { class => 'Koha::Acquisition::Invoices', value => { booksellerid => $vendor->id } } );
112
            { class => 'Koha::Acquisition::Invoices', value => { booksellerid => $vendor->id } } );
105
    }
113
    }
106
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors" =>
114
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors" =>
107
            { 'x-koha-embed' => 'subscriptions+count,baskets+count,invoices+count' } )->status_is(200)
115
            { 'x-koha-embed' => 'subscriptions+count,baskets+count,invoices+count' } )
116
        ->status_is(200)
108
        ->json_is( '/0/subscriptions_count', 2, 'subscriptions_count is 2' )
117
        ->json_is( '/0/subscriptions_count', 2, 'subscriptions_count is 2' )
109
        ->json_is( '/0/baskets_count',       2, 'baskets_count is 2' )
118
        ->json_is( '/0/baskets_count',       2, 'baskets_count is 2' )
110
        ->json_is( '/0/invoices_count',      2, 'invoices_count is 2' );
119
        ->json_is( '/0/invoices_count',      2, 'invoices_count is 2' );
Lines 113-119 subtest 'list() and delete() tests | authorized user' => sub { Link Here
113
    # A vendor deletion should be rejected if it has baskets or subscriptions (or invoices?) linked to it
122
    # A vendor deletion should be rejected if it has baskets or subscriptions (or invoices?) linked to it
114
    $_->delete for @cleanup;
123
    $_->delete for @cleanup;
115
124
116
    $t->delete_ok( "//$userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id )->status_is( 204, 'REST3.2.4' )
125
    $t->delete_ok( "//$userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id )
126
        ->status_is( 204, 'REST3.2.4' )
117
        ->content_is( '', 'REST3.3.4' );
127
        ->content_is( '', 'REST3.3.4' );
118
128
119
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors/" . $other_vendor->id )->status_is(200);
129
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors/" . $other_vendor->id )->status_is(200);
Lines 143-164 subtest 'get() test' => sub { Link Here
143
    $patron->set_password( { password => $password, skip_validation => 1 } );
153
    $patron->set_password( { password => $password, skip_validation => 1 } );
144
    my $userid = $patron->userid;
154
    my $userid = $patron->userid;
145
155
146
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id )->status_is(200)
156
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id )
157
        ->status_is(200)
147
        ->json_is( $vendor->to_api );
158
        ->json_is( $vendor->to_api );
148
159
149
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors/"
160
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors/"
150
            . $vendor->id => { 'x-koha-embed' => 'subscriptions+count,baskets+count,invoices+count' } )->status_is(200)
161
            . $vendor->id => { 'x-koha-embed' => 'subscriptions+count,baskets+count,invoices+count' } )
162
        ->status_is(200)
151
        ->json_has( '/subscriptions_count', 'subscriptions_count is embedded' )
163
        ->json_has( '/subscriptions_count', 'subscriptions_count is embedded' )
152
        ->json_has( '/baskets_count',       'baskets_count is embedded' )
164
        ->json_has( '/baskets_count',       'baskets_count is embedded' )
153
        ->json_has( '/invoices_count',      'invoices_count is embedded' );
165
        ->json_has( '/invoices_count',      'invoices_count is embedded' );
154
166
155
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors/" . $non_existent_id )->status_is(404)
167
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors/" . $non_existent_id )
168
        ->status_is(404)
156
        ->json_is( '/error' => 'Vendor not found' );
169
        ->json_is( '/error' => 'Vendor not found' );
157
170
158
    # remove permissions
171
    # remove permissions
159
    $patron->set( { flags => 0 } )->store;
172
    $patron->set( { flags => 0 } )->store;
160
173
161
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id )->status_is(403)
174
    $t->get_ok( "//$userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id )
175
        ->status_is(403)
162
        ->json_is( '/error', 'Authorization failure. Missing required permission(s).' );
176
        ->json_is( '/error', 'Authorization failure. Missing required permission(s).' );
163
177
164
    $schema->storage->txn_rollback;
178
    $schema->storage->txn_rollback;
Lines 201-207 subtest 'add() tests' => sub { Link Here
201
    };
215
    };
202
216
203
    $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors" => json => $vendor_with_invalid_field )
217
    $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors" => json => $vendor_with_invalid_field )
204
        ->status_is(400)->json_is(
218
        ->status_is(400)
219
        ->json_is(
205
        "/errors" => [
220
        "/errors" => [
206
            {
221
            {
207
                message => "Properties not allowed: address5.",
222
                message => "Properties not allowed: address5.",
Lines 214-227 subtest 'add() tests' => sub { Link Here
214
    $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors" => json => $vendor )
229
    $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors" => json => $vendor )
215
        ->status_is( 201, 'REST3 .2.1' )
230
        ->status_is( 201, 'REST3 .2.1' )
216
        ->header_like( Location => qr|^\/api\/v1\/acquisitions\/vendors/\d*|, 'REST3.4.1' )
231
        ->header_like( Location => qr|^\/api\/v1\/acquisitions\/vendors/\d*|, 'REST3.4.1' )
217
        ->json_is( '/name' => $vendor->{name} )->json_is( '/address1' => $vendor->{address1} );
232
        ->json_is( '/name'     => $vendor->{name} )
233
        ->json_is( '/address1' => $vendor->{address1} );
218
234
219
    # read the response vendor id for later use
235
    # read the response vendor id for later use
220
    my $vendor_id = $t->tx->res->json('/id');
236
    my $vendor_id = $t->tx->res->json('/id');
221
237
222
    # Authorized attempt to create with null id
238
    # Authorized attempt to create with null id
223
    $vendor->{id} = undef;
239
    $vendor->{id} = undef;
224
    $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors" => json => $vendor )->status_is(400)
240
    $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors" => json => $vendor )
241
        ->status_is(400)
225
        ->json_has('/errors');
242
        ->json_has('/errors');
226
243
227
    # Authorized attempt to create with existing id
244
    # Authorized attempt to create with existing id
Lines 237-273 subtest 'add() tests' => sub { Link Here
237
254
238
    subtest 'relationships contracts, interfaces, aliases' => sub {
255
    subtest 'relationships contracts, interfaces, aliases' => sub {
239
        plan tests => 32;
256
        plan tests => 32;
240
        my $vendor    = { name => 'another vendor', contacts => [], interfaces => [], aliases => [] };
257
        my $vendor = { name => 'another vendor', contacts => [], interfaces => [], aliases => [] };
241
        my $vendor_id = $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors" => json => $vendor )
258
        my $vendor_id =
242
            ->status_is( 201, 'REST3 .2.1' )->json_is( '/name' => $vendor->{name} )
259
            $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors" => json => $vendor )
260
            ->status_is( 201, 'REST3 .2.1' )
261
            ->json_is( '/name' => $vendor->{name} )
243
262
244
            # FIXME Maybe we expect instead
263
            # FIXME Maybe we expect instead
245
            # ->json_is( '/contacts' => [] )->json_is('/interfaces' => [], '/aliases' => [] );
264
            # ->json_is( '/contacts' => [] )->json_is('/interfaces' => [], '/aliases' => [] );
246
            ->json_hasnt('/contacts')->json_hasnt('/interfaces')->json_hasnt('/aliases')->tx->res->json->{id};
265
            ->json_hasnt('/contacts')->json_hasnt('/interfaces')->json_hasnt('/aliases')->tx->res->json->{id};
247
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor_id )->status_is(200)
266
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor_id )
248
            ->json_hasnt('/contacts')->json_hasnt('/interfaces')->json_hasnt('/aliases');
267
            ->status_is(200)
268
            ->json_hasnt('/contacts')
269
            ->json_hasnt('/interfaces')
270
            ->json_hasnt('/aliases');
249
271
250
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
272
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
251
                . $vendor_id => { 'x-koha-embed' => 'contacts,interfaces,aliases' } )->status_is(200)
273
                . $vendor_id => { 'x-koha-embed' => 'contacts,interfaces,aliases' } )
252
            ->json_is( '/contacts', [] )->json_is( '/interfaces', [] )->json_is( '/aliases', [] );
274
            ->status_is(200)
275
            ->json_is( '/contacts',   [] )
276
            ->json_is( '/interfaces', [] )
277
            ->json_is( '/aliases',    [] );
253
278
254
        $vendor = {
279
        $vendor = {
255
            name       => 'yet another vendor', contacts => [ { name => 'contact name' } ],
280
            name       => 'yet another vendor', contacts => [ { name => 'contact name' } ],
256
            interfaces => [ { name => 'interface name' } ], aliases => [ { alias => 'foo' } ]
281
            interfaces => [ { name => 'interface name' } ], aliases => [ { alias => 'foo' } ]
257
        };
282
        };
258
        $vendor_id = $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors" => json => $vendor )
283
        $vendor_id =
259
            ->status_is( 201, 'REST3 .2.1' )->json_is( '/name' => $vendor->{name} )
284
            $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors" => json => $vendor )
285
            ->status_is( 201, 'REST3 .2.1' )
286
            ->json_is( '/name' => $vendor->{name} )
260
287
261
            # FIXME Maybe we expect instead
288
            # FIXME Maybe we expect instead
262
            # ->json_is( '/contacts' => [] )->json_is('/interfaces' => [], '/aliases' => [] );
289
            # ->json_is( '/contacts' => [] )->json_is('/interfaces' => [], '/aliases' => [] );
263
            ->json_hasnt('/contacts')->json_hasnt('/interfaces')->json_hasnt('/aliases')->tx->res->json->{id};
290
            ->json_hasnt('/contacts')->json_hasnt('/interfaces')->json_hasnt('/aliases')->tx->res->json->{id};
264
291
265
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor_id )->status_is(200)
292
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor_id )
266
            ->json_hasnt('/contacts')->json_hasnt('/interfaces')->json_hasnt('/aliases');
293
            ->status_is(200)
294
            ->json_hasnt('/contacts')
295
            ->json_hasnt('/interfaces')
296
            ->json_hasnt('/aliases');
267
297
268
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
298
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
269
                . $vendor_id => { 'x-koha-embed' => 'contacts,interfaces,aliases' } )->status_is(200)
299
                . $vendor_id => { 'x-koha-embed' => 'contacts,interfaces,aliases' } )
270
            ->json_has('/contacts/0/name')->json_has('/interfaces/0/name')->json_has('/aliases/0/alias');
300
            ->status_is(200)
301
            ->json_has('/contacts/0/name')
302
            ->json_has('/interfaces/0/name')
303
            ->json_has('/aliases/0/alias');
271
    };
304
    };
272
305
273
    $schema->storage->txn_rollback;
306
    $schema->storage->txn_rollback;
Lines 308-314 subtest 'update() tests' => sub { Link Here
308
    my $vendor_without_mandatory_field = { address1 => 'New address' };
341
    my $vendor_without_mandatory_field = { address1 => 'New address' };
309
342
310
    $t->put_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
343
    $t->put_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
311
            . $vendor->id => json => $vendor_without_mandatory_field )->status_is(400)
344
            . $vendor->id => json => $vendor_without_mandatory_field )
345
        ->status_is(400)
312
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
346
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
313
347
314
    # Full object update on PUT
348
    # Full object update on PUT
Lines 316-322 subtest 'update() tests' => sub { Link Here
316
350
317
    $t->put_ok(
351
    $t->put_ok(
318
        "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id => json => $vendor_with_updated_field )
352
        "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id => json => $vendor_with_updated_field )
319
        ->status_is(200)->json_is( '/name' => 'London books' );
353
        ->status_is(200)
354
        ->json_is( '/name' => 'London books' );
320
355
321
    # Authorized attempt to write invalid data
356
    # Authorized attempt to write invalid data
322
    my $vendor_with_invalid_field = {
357
    my $vendor_with_invalid_field = {
Lines 328-334 subtest 'update() tests' => sub { Link Here
328
363
329
    $t->put_ok(
364
    $t->put_ok(
330
        "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id => json => $vendor_with_invalid_field )
365
        "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id => json => $vendor_with_invalid_field )
331
        ->status_is(400)->json_is(
366
        ->status_is(400)
367
        ->json_is(
332
        "/errors" => [
368
        "/errors" => [
333
            {
369
            {
334
                message => "Properties not allowed: blah.",
370
                message => "Properties not allowed: blah.",
Lines 357-364 subtest 'update() tests' => sub { Link Here
357
        $vendor->aliases( [] );
393
        $vendor->aliases( [] );
358
394
359
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
395
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
360
                . $vendor->id => { 'x-koha-embed' => 'contacts,interfaces,aliases' } )->status_is(200)
396
                . $vendor->id => { 'x-koha-embed' => 'contacts,interfaces,aliases' } )
361
            ->json_is( '/contacts', [] )->json_is( '/interfaces', [] )->json_is( '/aliases', [] );
397
            ->status_is(200)
398
            ->json_is( '/contacts',   [] )
399
            ->json_is( '/interfaces', [] )
400
            ->json_is( '/aliases',    [] );
362
401
363
        my $api_vendor = $vendor->to_api;
402
        my $api_vendor = $vendor->to_api;
364
        delete $api_vendor->{id};
403
        delete $api_vendor->{id};
Lines 368-379 subtest 'update() tests' => sub { Link Here
368
        $api_vendor->{aliases}    = [ { alias => 'foo' } ];
407
        $api_vendor->{aliases}    = [ { alias => 'foo' } ];
369
408
370
        $t->put_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id => json => $api_vendor )
409
        $t->put_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id => json => $api_vendor )
371
            ->status_is( 200, 'REST3 .2.1' )->json_is( '/name' => $vendor->name )->json_hasnt('/contacts')
410
            ->status_is( 200, 'REST3 .2.1' )
372
            ->json_hasnt('/interfaces')->json_hasnt('/aliases');
411
            ->json_is( '/name' => $vendor->name )
412
            ->json_hasnt('/contacts')
413
            ->json_hasnt('/interfaces')
414
            ->json_hasnt('/aliases');
373
415
374
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
416
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
375
                . $vendor->id => { 'x-koha-embed' => 'contacts,interfaces,aliases' } )->status_is(200)
417
                . $vendor->id => { 'x-koha-embed' => 'contacts,interfaces,aliases' } )
376
            ->json_has('/contacts/0/name')->json_has('/interfaces/0/name')->json_has('/aliases/0/alias');
418
            ->status_is(200)
419
            ->json_has('/contacts/0/name')
420
            ->json_has('/interfaces/0/name')
421
            ->json_has('/aliases/0/alias');
377
422
378
        delete $api_vendor->{contacts};
423
        delete $api_vendor->{contacts};
379
        delete $api_vendor->{interfaces};
424
        delete $api_vendor->{interfaces};
Lines 383-390 subtest 'update() tests' => sub { Link Here
383
            ->status_is( 200, 'REST3 .2.1' );
428
            ->status_is( 200, 'REST3 .2.1' );
384
429
385
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
430
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
386
                . $vendor->id => { 'x-koha-embed' => 'contacts,interfaces,aliases' } )->status_is(200)
431
                . $vendor->id => { 'x-koha-embed' => 'contacts,interfaces,aliases' } )
387
            ->json_has('/contacts/0/name')->json_has('/interfaces/0/name')->json_has('/aliases/0/alias');
432
            ->status_is(200)
433
            ->json_has('/contacts/0/name')
434
            ->json_has('/interfaces/0/name')
435
            ->json_has('/aliases/0/alias');
388
436
389
        $api_vendor->{contacts}   = [];
437
        $api_vendor->{contacts}   = [];
390
        $api_vendor->{interfaces} = [];
438
        $api_vendor->{interfaces} = [];
Lines 394-401 subtest 'update() tests' => sub { Link Here
394
            ->status_is( 200, 'REST3 .2.1' );
442
            ->status_is( 200, 'REST3 .2.1' );
395
443
396
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
444
        $t->get_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/"
397
                . $vendor->id => { 'x-koha-embed' => 'contacts,interfaces,aliases' } )->status_is(200)
445
                . $vendor->id => { 'x-koha-embed' => 'contacts,interfaces,aliases' } )
398
            ->json_is( '/contacts', [] )->json_is( '/interfaces', [] )->json_is( '/aliases', [] );
446
            ->status_is(200)
447
            ->json_is( '/contacts',   [] )
448
            ->json_is( '/interfaces', [] )
449
            ->json_is( '/aliases',    [] );
399
    };
450
    };
400
451
401
    $schema->storage->txn_rollback;
452
    $schema->storage->txn_rollback;
Lines 452-458 subtest 'delete() tests' => sub { Link Here
452
    $invoice->delete;
503
    $invoice->delete;
453
504
454
    $t->delete_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id )
505
    $t->delete_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id )
455
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
506
        ->status_is( 204, 'REST3.2.4' )
507
        ->content_is( '', 'REST3.3.4' );
456
508
457
    $t->delete_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id )->status_is(404);
509
    $t->delete_ok( "//$auth_userid:$password@/api/v1/acquisitions/vendors/" . $vendor->id )->status_is(404);
458
510
(-)a/t/db_dependent/api/v1/additional_contents.t (-4 / +5 lines)
Lines 43-49 subtest 'anonymous access' => sub { Link Here
43
43
44
    my $today     = dt_from_string;
44
    my $today     = dt_from_string;
45
    my $yesterday = dt_from_string->add( days => -1 );
45
    my $yesterday = dt_from_string->add( days => -1 );
46
    my $tomorrow  = dt_from_string->add( days => 1 );
46
    my $tomorrow  = dt_from_string->add( days =>  1 );
47
    my $res;
47
    my $res;
48
48
49
    $builder->build_object(
49
    $builder->build_object(
Lines 104-110 subtest 'anonymous access' => sub { Link Here
104
104
105
    is( scalar @{$res}, 1, 'There is now one active and public additional content' );
105
    is( scalar @{$res}, 1, 'There is now one active and public additional content' );
106
106
107
    $t->get_ok( "/api/v1/public/additional_contents" => { 'x-koha-embed' => 'translated_contents' } )->status_is(200)
107
    $t->get_ok( "/api/v1/public/additional_contents" => { 'x-koha-embed' => 'translated_contents' } )
108
        ->status_is(200)
108
        ->json_is(
109
        ->json_is(
109
        '/0' => {
110
        '/0' => {
110
            %{ $public_additional_contents->to_api( { public => 1 } ) },
111
            %{ $public_additional_contents->to_api( { public => 1 } ) },
Lines 142-148 subtest 'anonymous access' => sub { Link Here
142
            %{ $public_additional_contents->to_api( { public => 1 } ) },
143
            %{ $public_additional_contents->to_api( { public => 1 } ) },
143
            translated_contents => $public_additional_contents->translated_contents->to_api( { public => 1 } )
144
            translated_contents => $public_additional_contents->translated_contents->to_api( { public => 1 } )
144
        }
145
        }
145
    )->json_hasnt('/1');
146
        )->json_hasnt('/1');
146
147
147
    $t->get_ok( "/api/v1/public/additional_contents?q={\"translated_contents.lang\": \"fr-FR\"}" =>
148
    $t->get_ok( "/api/v1/public/additional_contents?q={\"translated_contents.lang\": \"fr-FR\"}" =>
148
            { 'x-koha-embed' => 'translated_contents' } )->status_is(200)->json_is(
149
            { 'x-koha-embed' => 'translated_contents' } )->status_is(200)->json_is(
Lines 150-156 subtest 'anonymous access' => sub { Link Here
150
            %{ $second_public_additional_contents->to_api( { public => 1 } ) },
151
            %{ $second_public_additional_contents->to_api( { public => 1 } ) },
151
            translated_contents => $second_public_additional_contents->translated_contents->to_api( { public => 1 } )
152
            translated_contents => $second_public_additional_contents->translated_contents->to_api( { public => 1 } )
152
        }
153
        }
153
    )->json_hasnt('/1');
154
        )->json_hasnt('/1');
154
155
155
    $schema->storage->txn_rollback;
156
    $schema->storage->txn_rollback;
156
157
(-)a/t/db_dependent/api/v1/advanced_editor_macros.t (-16 / +32 lines)
Lines 105-130 subtest 'list() tests' => sub { Link Here
105
        ->count - 1;
105
        ->count - 1;
106
    ## Authorized user tests
106
    ## Authorized user tests
107
    # Make sure we are returned with the correct amount of macros
107
    # Make sure we are returned with the correct amount of macros
108
    $t->get_ok("//$userid:$password@/api/v1/advanced_editor/macros")->status_is( 200, 'REST3.2.2' )
108
    $t->get_ok("//$userid:$password@/api/v1/advanced_editor/macros")
109
        ->json_has( '/' . $macros_index . '/macro_id' )->json_hasnt( '/' . ( $macros_index + 1 ) . '/macro_id' );
109
        ->status_is( 200, 'REST3.2.2' )
110
        ->json_has( '/' . $macros_index . '/macro_id' )
111
        ->json_hasnt( '/' . ( $macros_index + 1 ) . '/macro_id' );
110
112
111
    subtest 'query parameters' => sub {
113
    subtest 'query parameters' => sub {
112
114
113
        plan tests => 15;
115
        plan tests => 15;
114
        $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros?name=" . $macro_2->name )->status_is(200)
116
        $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros?name=" . $macro_2->name )
117
            ->status_is(200)
115
            ->json_is( [ $macro_2->to_api ] );
118
            ->json_is( [ $macro_2->to_api ] );
116
        $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros?name=" . $macro_3->name )->status_is(200)
119
        $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros?name=" . $macro_3->name )
120
            ->status_is(200)
117
            ->json_is( [] );
121
            ->json_is( [] );
118
        $t->get_ok("//$userid:$password@/api/v1/advanced_editor/macros?macro_text=delete%20100")->status_is(200)
122
        $t->get_ok("//$userid:$password@/api/v1/advanced_editor/macros?macro_text=delete%20100")
123
            ->status_is(200)
119
            ->json_is( [ $macro_1->to_api, $macro_2->to_api, $macro_4->to_api ] );
124
            ->json_is( [ $macro_1->to_api, $macro_2->to_api, $macro_4->to_api ] );
120
        $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros?patron_id=" . $patron_1->borrowernumber )
125
        $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros?patron_id=" . $patron_1->borrowernumber )
121
            ->status_is(200)->json_is( [ $macro_1->to_api, $macro_2->to_api ] );
126
            ->status_is(200)
122
        $t->get_ok("//$userid:$password@/api/v1/advanced_editor/macros?shared=1")->status_is(200)
127
            ->json_is( [ $macro_1->to_api, $macro_2->to_api ] );
128
        $t->get_ok("//$userid:$password@/api/v1/advanced_editor/macros?shared=1")
129
            ->status_is(200)
123
            ->json_is( [ $macro_2->to_api, $macro_4->to_api ] );
130
            ->json_is( [ $macro_2->to_api, $macro_4->to_api ] );
124
    };
131
    };
125
132
126
    # Warn on unsupported query parameter
133
    # Warn on unsupported query parameter
127
    $t->get_ok("//$userid:$password@/api/v1/advanced_editor/macros?macro_blah=blah")->status_is(400)
134
    $t->get_ok("//$userid:$password@/api/v1/advanced_editor/macros?macro_blah=blah")
135
        ->status_is(400)
128
        ->json_is( [ { path => '/query/macro_blah', message => 'Malformed query string' } ] );
136
        ->json_is( [ { path => '/query/macro_blah', message => 'Malformed query string' } ] );
129
137
130
};
138
};
Lines 174-192 subtest 'get() tests' => sub { Link Here
174
        ->json_is( '/error' => 'This macro is shared, you must access it via advanced_editor/macros/shared' );
182
        ->json_is( '/error' => 'This macro is shared, you must access it via advanced_editor/macros/shared' );
175
183
176
    $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros/shared/" . $macro_1->id )
184
    $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros/shared/" . $macro_1->id )
177
        ->status_is( 200, 'Can get a shared macro via shared endpoint' )->json_is( $macro_1->to_api );
185
        ->status_is( 200, 'Can get a shared macro via shared endpoint' )
186
        ->json_is( $macro_1->to_api );
178
187
179
    $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros/" . $macro_2->id )
188
    $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros/" . $macro_2->id )
180
        ->status_is( 403, 'Cannot access another users macro' )
189
        ->status_is( 403, 'Cannot access another users macro' )
181
        ->json_is( '/error' => 'You do not have permission to access this macro' );
190
        ->json_is( '/error' => 'You do not have permission to access this macro' );
182
191
183
    $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros/" . $macro_3->id )
192
    $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros/" . $macro_3->id )
184
        ->status_is( 200, 'Can get your own private macro' )->json_is( $macro_3->to_api );
193
        ->status_is( 200, 'Can get your own private macro' )
194
        ->json_is( $macro_3->to_api );
185
195
186
    my $non_existent_code = $macro_1->id;
196
    my $non_existent_code = $macro_1->id;
187
    $macro_1->delete;
197
    $macro_1->delete;
188
198
189
    $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros/" . $non_existent_code )->status_is(404)
199
    $t->get_ok( "//$userid:$password@/api/v1/advanced_editor/macros/" . $non_existent_code )
200
        ->status_is(404)
190
        ->json_is( '/error' => 'Macro not found' );
201
        ->json_is( '/error' => 'Macro not found' );
191
202
192
};
203
};
Lines 243-249 subtest 'add() tests' => sub { Link Here
243
    $macro_with_invalid_field->{'big_mac_ro'} = 'Mac attack';
254
    $macro_with_invalid_field->{'big_mac_ro'} = 'Mac attack';
244
255
245
    $t->post_ok( "//$auth_userid:$password@/api/v1/advanced_editor/macros" => json => $macro_with_invalid_field )
256
    $t->post_ok( "//$auth_userid:$password@/api/v1/advanced_editor/macros" => json => $macro_with_invalid_field )
246
        ->status_is(400)->json_is(
257
        ->status_is(400)
258
        ->json_is(
247
        "/errors" => [
259
        "/errors" => [
248
            {
260
            {
249
                message => "Properties not allowed: big_mac_ro.",
261
                message => "Properties not allowed: big_mac_ro.",
Lines 254-260 subtest 'add() tests' => sub { Link Here
254
266
255
    # Authorized attempt to write
267
    # Authorized attempt to write
256
    $t->post_ok( "//$auth_userid:$password@/api/v1/advanced_editor/macros" => json => $macro_values )
268
    $t->post_ok( "//$auth_userid:$password@/api/v1/advanced_editor/macros" => json => $macro_values )
257
        ->status_is( 201, 'REST3.2.1' )->json_has( '/macro_id', 'We generated a new id' )
269
        ->status_is( 201, 'REST3.2.1' )
270
        ->json_has( '/macro_id', 'We generated a new id' )
258
        ->json_is( '/name'       => $macro_values->{name},       'The name matches what we supplied' )
271
        ->json_is( '/name'       => $macro_values->{name},       'The name matches what we supplied' )
259
        ->json_is( '/macro_text' => $macro_values->{macro_text}, 'The text matches what we supplied' )
272
        ->json_is( '/macro_text' => $macro_values->{macro_text}, 'The text matches what we supplied' )
260
        ->json_is( '/patron_id'  => $macro_values->{patron_id},  'The borrower matches the borrower who submitted' )
273
        ->json_is( '/patron_id'  => $macro_values->{patron_id},  'The borrower matches the borrower who submitted' )
Lines 267-273 subtest 'add() tests' => sub { Link Here
267
    # Authorized attempt to create with existing id
280
    # Authorized attempt to create with existing id
268
    $macro_values->{macro_id} = $macro_id;
281
    $macro_values->{macro_id} = $macro_id;
269
282
270
    $t->post_ok( "//$auth_userid:$password@/api/v1/advanced_editor/macros" => json => $macro_values )->status_is(400)
283
    $t->post_ok( "//$auth_userid:$password@/api/v1/advanced_editor/macros" => json => $macro_values )
284
        ->status_is(400)
271
        ->json_is(
285
        ->json_is(
272
        '/errors' => [
286
        '/errors' => [
273
            {
287
            {
Lines 368-374 subtest 'update() tests' => sub { Link Here
368
382
369
    $t->put_ok(
383
    $t->put_ok(
370
        "//$auth_userid:$password@/api/v1/advanced_editor/macros/$macro_id" => json => $macro_with_missing_field )
384
        "//$auth_userid:$password@/api/v1/advanced_editor/macros/$macro_id" => json => $macro_with_missing_field )
371
        ->status_is(400)->json_has( "/errors" => [ { message => "Missing property.", path => "/body/macro_text" } ] );
385
        ->status_is(400)
386
        ->json_has( "/errors" => [ { message => "Missing property.", path => "/body/macro_text" } ] );
372
387
373
    my $macro_update = {
388
    my $macro_update = {
374
        name       => "Macro-update",
389
        name       => "Macro-update",
Lines 422-428 subtest 'update() tests' => sub { Link Here
422
437
423
    $t->put_ok(
438
    $t->put_ok(
424
        "//$auth_userid:$password@/api/v1/advanced_editor/macros/$macro_id" => json => $macro_with_invalid_field )
439
        "//$auth_userid:$password@/api/v1/advanced_editor/macros/$macro_id" => json => $macro_with_invalid_field )
425
        ->status_is(400)->json_is(
440
        ->status_is(400)
441
        ->json_is(
426
        "/errors" => [
442
        "/errors" => [
427
            {
443
            {
428
                message => "Properties not allowed: big_mac_ro.",
444
                message => "Properties not allowed: big_mac_ro.",
(-)a/t/db_dependent/api/v1/article_requests.t (-7 / +14 lines)
Lines 52-58 subtest 'cancel() tests' => sub { Link Here
52
    my $deleted_article_request_id = $deleted_article_request->id;
52
    my $deleted_article_request_id = $deleted_article_request->id;
53
    $deleted_article_request->delete;
53
    $deleted_article_request->delete;
54
54
55
    $t->delete_ok("//$userid:$password@/api/v1/article_requests/$deleted_article_request_id")->status_is(404)
55
    $t->delete_ok("//$userid:$password@/api/v1/article_requests/$deleted_article_request_id")
56
        ->status_is(404)
56
        ->json_is( '/error_code' => 'not_found' );
57
        ->json_is( '/error_code' => 'not_found' );
57
58
58
    my $article_request = $builder->build_object(
59
    my $article_request = $builder->build_object(
Lines 67-73 subtest 'cancel() tests' => sub { Link Here
67
68
68
    $t->delete_ok( "//$userid:$password@/api/v1/article_requests/"
69
    $t->delete_ok( "//$userid:$password@/api/v1/article_requests/"
69
            . $article_request->id
70
            . $article_request->id
70
            . "?cancellation_reason=$reason&notes=$notes" )->status_is( 204, 'REST3.2.4' )
71
            . "?cancellation_reason=$reason&notes=$notes" )
72
        ->status_is( 204, 'REST3.2.4' )
71
        ->content_is( q{}, 'REST3.2.4' );
73
        ->content_is( q{}, 'REST3.2.4' );
72
74
73
    # refresh object
75
    # refresh object
Lines 109-115 subtest 'patron_cancel() tests' => sub { Link Here
109
111
110
    # delete non existent article request
112
    # delete non existent article request
111
    $t->delete_ok("//$userid:$password@/api/v1/public/patrons/$patron_id/article_requests/$deleted_article_request_id")
113
    $t->delete_ok("//$userid:$password@/api/v1/public/patrons/$patron_id/article_requests/$deleted_article_request_id")
112
        ->status_is(404)->json_is( '/error_code' => 'not_found' );
114
        ->status_is(404)
115
        ->json_is( '/error_code' => 'not_found' );
113
116
114
    my $another_patron    = $builder->build_object( { class => 'Koha::Patrons' } );
117
    my $another_patron    = $builder->build_object( { class => 'Koha::Patrons' } );
115
    my $another_patron_id = $another_patron->id;
118
    my $another_patron_id = $another_patron->id;
Lines 119-130 subtest 'patron_cancel() tests' => sub { Link Here
119
122
120
    # delete another patron's request when unauthorized
123
    # delete another patron's request when unauthorized
121
    $t->delete_ok( "/api/v1/public/patrons/$another_patron_id/article_requests/" . $article_request_2->id )
124
    $t->delete_ok( "/api/v1/public/patrons/$another_patron_id/article_requests/" . $article_request_2->id )
122
        ->status_is(401)->json_is( '/error' => "Authentication failure." );
125
        ->status_is(401)
126
        ->json_is( '/error' => "Authentication failure." );
123
127
124
    # delete another patron's request
128
    # delete another patron's request
125
    $t->delete_ok(
129
    $t->delete_ok(
126
        "//$userid:$password@/api/v1/public/patrons/$another_patron_id/article_requests/" . $article_request_2->id )
130
        "//$userid:$password@/api/v1/public/patrons/$another_patron_id/article_requests/" . $article_request_2->id )
127
        ->status_is(403)->json_is( '/error' => "Unprivileged user cannot access another user's resources" );
131
        ->status_is(403)
132
        ->json_is( '/error' => "Unprivileged user cannot access another user's resources" );
128
133
129
    my $another_article_request = $builder->build_object(
134
    my $another_article_request = $builder->build_object(
130
        {
135
        {
Lines 135-141 subtest 'patron_cancel() tests' => sub { Link Here
135
140
136
    $t->delete_ok(
141
    $t->delete_ok(
137
        "//$userid:$password@/api/v1/public/patrons/$patron_id/article_requests/" . $another_article_request->id )
142
        "//$userid:$password@/api/v1/public/patrons/$patron_id/article_requests/" . $another_article_request->id )
138
        ->status_is(404)->json_is( '/error_code' => 'not_found' );
143
        ->status_is(404)
144
        ->json_is( '/error_code' => 'not_found' );
139
145
140
    my $article_request = $builder->build_object(
146
    my $article_request = $builder->build_object(
141
        {
147
        {
Lines 149-155 subtest 'patron_cancel() tests' => sub { Link Here
149
155
150
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/article_requests/"
156
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/article_requests/"
151
            . $article_request->id
157
            . $article_request->id
152
            . "?cancellation_reason=$reason&notes=$notes" )->status_is( 204, 'REST3.2.4' )
158
            . "?cancellation_reason=$reason&notes=$notes" )
159
        ->status_is( 204, 'REST3.2.4' )
153
        ->content_is( q{}, 'REST3.2.4' );
160
        ->content_is( q{}, 'REST3.2.4' );
154
161
155
    # refresh object
162
    # refresh object
(-)a/t/db_dependent/api/v1/auth.t (-1 / +2 lines)
Lines 51-57 subtest 'under() tests' => sub { Link Here
51
    t::lib::Mocks::mock_preference( 'RESTPublicAPI', 0 );
51
    t::lib::Mocks::mock_preference( 'RESTPublicAPI', 0 );
52
    $tx = $t->ua->build_tx( POST => "/api/v1/public/patrons/$borrowernumber/password" );
52
    $tx = $t->ua->build_tx( POST => "/api/v1/public/patrons/$borrowernumber/password" );
53
    $tx->req->env( { REMOTE_ADDR => $remote_address } );
53
    $tx->req->env( { REMOTE_ADDR => $remote_address } );
54
    $t->request_ok($tx)->status_is(403)
54
    $t->request_ok($tx)
55
        ->status_is(403)
55
        ->json_is( '/error', 'Configuration prevents the usage of this endpoint by unprivileged users' );
56
        ->json_is( '/error', 'Configuration prevents the usage of this endpoint by unprivileged users' );
56
57
57
    # enable the /public namespace
58
    # enable the /public namespace
(-)a/t/db_dependent/api/v1/auth_authenticate_api_request.t (-4 / +9 lines)
Lines 68-75 subtest 'token-based tests' => sub { Link Here
68
        client_id     => $api_key->client_id,
68
        client_id     => $api_key->client_id,
69
        client_secret => $api_key->plain_text_secret
69
        client_secret => $api_key->plain_text_secret
70
    };
70
    };
71
    $t->post_ok( '/api/v1/oauth/token', form => $formData )->status_is(200)->json_is( '/expires_in' => 3600 )
71
    $t->post_ok( '/api/v1/oauth/token', form => $formData )
72
        ->json_is( '/token_type' => 'Bearer' )->json_has('/access_token');
72
        ->status_is(200)
73
        ->json_is( '/expires_in' => 3600 )
74
        ->json_is( '/token_type' => 'Bearer' )
75
        ->json_has('/access_token');
73
76
74
    my $access_token = $t->tx->res->json->{access_token};
77
    my $access_token = $t->tx->res->json->{access_token};
75
78
Lines 167-173 subtest 'cookie-based tests' => sub { Link Here
167
        $tx->req->cookies( { name => 'CGISESSID', value => $session->id } );
170
        $tx->req->cookies( { name => 'CGISESSID', value => $session->id } );
168
        $tx->req->env( { REMOTE_ADDR => $remote_address } );
171
        $tx->req->env( { REMOTE_ADDR => $remote_address } );
169
172
170
        $t->request_ok($tx)->status_is( 401, 'Anonymous session on permission protected resource returns 401' )
173
        $t->request_ok($tx)
174
            ->status_is( 401, 'Anonymous session on permission protected resource returns 401' )
171
            ->json_is( { error => 'Authentication failure.' } );
175
            ->json_is( { error => 'Authentication failure.' } );
172
    };
176
    };
173
177
Lines 259-265 subtest 'x-koha-library tests' => sub { Link Here
259
    is( $userenv->{branch}, $unprivileged->branchcode, 'branch set correctly' );
263
    is( $userenv->{branch}, $unprivileged->branchcode, 'branch set correctly' );
260
264
261
    $t->get_ok( "//$unprivileged_userid:$password@/api/v1/cities" => { 'x-koha-library' => $library->id } )
265
    $t->get_ok( "//$unprivileged_userid:$password@/api/v1/cities" => { 'x-koha-library' => $library->id } )
262
        ->status_is(403)->json_is( '/error' => 'Unauthorized attempt to set library to ' . $library->id );
266
        ->status_is(403)
267
        ->json_is( '/error' => 'Unauthorized attempt to set library to ' . $library->id );
263
268
264
    $t->get_ok( "//$superlibrarian_userid:$password@/api/v1/cities" => { 'x-koha-library' => $library->id } )
269
    $t->get_ok( "//$superlibrarian_userid:$password@/api/v1/cities" => { 'x-koha-library' => $library->id } )
265
        ->status_is(200);
270
        ->status_is(200);
(-)a/t/db_dependent/api/v1/auth_basic.t (-5 / +10 lines)
Lines 78-84 subtest 'success tests' => sub { Link Here
78
        $patron->flags(undef)->store;
78
        $patron->flags(undef)->store;
79
79
80
        $t->get_ok("//$userid:$password@/api/v1/patrons")
80
        $t->get_ok("//$userid:$password@/api/v1/patrons")
81
            ->status_is( 403, 'Successful authentication and not enough permissions' )->json_is(
81
            ->status_is( 403, 'Successful authentication and not enough permissions' )
82
            ->json_is(
82
            '/error' => 'Authorization failure. Missing required permission(s).',
83
            '/error' => 'Authorization failure. Missing required permission(s).',
83
            'Error message returned'
84
            'Error message returned'
84
            );
85
            );
Lines 103-109 subtest 'success tests' => sub { Link Here
103
        $patron->flags(undef)->store;
104
        $patron->flags(undef)->store;
104
105
105
        $t->get_ok("//$cardnumber:$password@/api/v1/patrons")
106
        $t->get_ok("//$cardnumber:$password@/api/v1/patrons")
106
            ->status_is( 403, 'Successful authentication and not enough permissions' )->json_is(
107
            ->status_is( 403, 'Successful authentication and not enough permissions' )
108
            ->json_is(
107
            '/error' => 'Authorization failure. Missing required permission(s).',
109
            '/error' => 'Authorization failure. Missing required permission(s).',
108
            'Error message returned'
110
            'Error message returned'
109
            );
111
            );
Lines 133-149 subtest 'failure tests' => sub { Link Here
133
    # expire patron's password
135
    # expire patron's password
134
    $patron->password_expiration_date( dt_from_string->subtract( days => 1 ) )->store;
136
    $patron->password_expiration_date( dt_from_string->subtract( days => 1 ) )->store;
135
137
136
    $t->get_ok("//$userid:$password@/api/v1/patrons")->status_is(403)
138
    $t->get_ok("//$userid:$password@/api/v1/patrons")
139
        ->status_is(403)
137
        ->json_is( '/error' => 'Password has expired', 'Password expired' );
140
        ->json_is( '/error' => 'Password has expired', 'Password expired' );
138
141
139
    $t->get_ok("//@/api/v1/patrons")->status_is( 401, 'No credentials passed' );
142
    $t->get_ok("//@/api/v1/patrons")->status_is( 401, 'No credentials passed' );
140
143
141
    $t->get_ok("//$userid:$bad_password@/api/v1/patrons")->status_is( 403, 'Failed authentication, invalid password' )
144
    $t->get_ok("//$userid:$bad_password@/api/v1/patrons")
145
        ->status_is( 403, 'Failed authentication, invalid password' )
142
        ->json_is( '/error' => 'Invalid password', 'Error message returned' );
146
        ->json_is( '/error' => 'Invalid password', 'Error message returned' );
143
147
144
    t::lib::Mocks::mock_preference( 'RESTBasicAuth', 0 );
148
    t::lib::Mocks::mock_preference( 'RESTBasicAuth', 0 );
145
149
146
    $t->get_ok("//$userid:$password@/api/v1/patrons")->status_is( 401, 'Basic authentication is disabled' )
150
    $t->get_ok("//$userid:$password@/api/v1/patrons")
151
        ->status_is( 401, 'Basic authentication is disabled' )
147
        ->json_is( '/error' => 'Basic authentication disabled', 'Expected error message rendered' );
152
        ->json_is( '/error' => 'Basic authentication disabled', 'Expected error message rendered' );
148
153
149
    $schema->storage->txn_rollback;
154
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/authorised_values.t (-5 / +10 lines)
Lines 63-81 subtest 'list_av_from_category() tests' => sub { Link Here
63
63
64
    ## Authorized user tests
64
    ## Authorized user tests
65
    # No category, 404 expected
65
    # No category, 404 expected
66
    $t->get_ok("//$userid:$password@/api/v1/authorised_value_categories/NON_EXISTS/authorised_values")->status_is(404)
66
    $t->get_ok("//$userid:$password@/api/v1/authorised_value_categories/NON_EXISTS/authorised_values")
67
        ->status_is(404)
67
        ->json_is( '/error' => 'Category not found' );
68
        ->json_is( '/error' => 'Category not found' );
68
69
69
    my $av_cat = $builder->build_object( { class => 'Koha::AuthorisedValueCategories' } )->category_name;
70
    my $av_cat = $builder->build_object( { class => 'Koha::AuthorisedValueCategories' } )->category_name;
70
71
71
    # No AVs, so empty array should be returned
72
    # No AVs, so empty array should be returned
72
    $t->get_ok("//$userid:$password@/api/v1/authorised_value_categories/$av_cat/authorised_values")->status_is(200)
73
    $t->get_ok("//$userid:$password@/api/v1/authorised_value_categories/$av_cat/authorised_values")
74
        ->status_is(200)
73
        ->json_is( [] );
75
        ->json_is( [] );
74
76
75
    my $av = $builder->build_object( { class => 'Koha::AuthorisedValues', value => { category => $av_cat } } );
77
    my $av = $builder->build_object( { class => 'Koha::AuthorisedValues', value => { category => $av_cat } } );
76
78
77
    # One av created, should get returned
79
    # One av created, should get returned
78
    $t->get_ok("//$userid:$password@/api/v1/authorised_value_categories/$av_cat/authorised_values")->status_is(200)
80
    $t->get_ok("//$userid:$password@/api/v1/authorised_value_categories/$av_cat/authorised_values")
81
        ->status_is(200)
79
        ->json_is( [ $av->to_api ] );
82
        ->json_is( [ $av->to_api ] );
80
83
81
    # Unauthorized access
84
    # Unauthorized access
Lines 88-100 subtest 'list_av_from_category() tests' => sub { Link Here
88
    my $av_cat_3 =
91
    my $av_cat_3 =
89
        $builder->build_object( { class => 'Koha::AuthorisedValueCategories', value => { category_name => 'cat_b' } } );
92
        $builder->build_object( { class => 'Koha::AuthorisedValueCategories', value => { category_name => 'cat_b' } } );
90
    my $query = { "me.category_name" => [ $av_cat_2->category_name, $av_cat_3->category_name ] };
93
    my $query = { "me.category_name" => [ $av_cat_2->category_name, $av_cat_3->category_name ] };
91
    $t->get_ok( "//$userid:$password@/api/v1/authorised_value_categories?q=" . encode_json($query) )->status_is(200)
94
    $t->get_ok( "//$userid:$password@/api/v1/authorised_value_categories?q=" . encode_json($query) )
95
        ->status_is(200)
92
        ->json_is( [ $av_cat_2->to_api, $av_cat_3->to_api ] );
96
        ->json_is( [ $av_cat_2->to_api, $av_cat_3->to_api ] );
93
97
94
    # Test the above but with x-koha-embed: authorised_values
98
    # Test the above but with x-koha-embed: authorised_values
95
    my $embedded_query = { "me.category_name" => [ $av_cat_2->category_name, $av_cat_3->category_name ] };
99
    my $embedded_query = { "me.category_name" => [ $av_cat_2->category_name, $av_cat_3->category_name ] };
96
    $t->get_ok( "//$userid:$password@/api/v1/authorised_value_categories?q="
100
    $t->get_ok( "//$userid:$password@/api/v1/authorised_value_categories?q="
97
            . encode_json($embedded_query) => { 'x-koha-embed' => 'authorised_values' } )->status_is(200)
101
            . encode_json($embedded_query) => { 'x-koha-embed' => 'authorised_values' } )
102
        ->status_is(200)
98
        ->json_has( '/0/authorised_values', 'authorised_values object correctly embedded' )
103
        ->json_has( '/0/authorised_values', 'authorised_values object correctly embedded' )
99
        ->json_has( '/1/authorised_values', 'authorised_values object correctly embedded' )
104
        ->json_has( '/1/authorised_values', 'authorised_values object correctly embedded' )
100
        ->json_hasnt( '/2/', 'authorised_values object correctly embedded' );
105
        ->json_hasnt( '/2/', 'authorised_values object correctly embedded' );
(-)a/t/db_dependent/api/v1/authorities.t (-8 / +16 lines)
Lines 84-90 subtest 'get() tests' => sub { Link Here
84
        ->status_is(400);
84
        ->status_is(400);
85
85
86
    $t->get_ok( "//$userid:$password@/api/v1/authorities/" . $authority->id => { Accept => 'application/json' } )
86
    $t->get_ok( "//$userid:$password@/api/v1/authorities/" . $authority->id => { Accept => 'application/json' } )
87
        ->status_is(200)->json_is( '/authority_id', $authority->id )
87
        ->status_is(200)
88
        ->json_is( '/authority_id', $authority->id )
88
        ->json_is( '/framework_id', $authority->authtypecode );
89
        ->json_is( '/framework_id', $authority->authtypecode );
89
90
90
    $t->get_ok( "//$userid:$password@/api/v1/authorities/" . $authority->id => { Accept => 'application/marcxml+xml' } )
91
    $t->get_ok( "//$userid:$password@/api/v1/authorities/" . $authority->id => { Accept => 'application/marcxml+xml' } )
Lines 98-104 subtest 'get() tests' => sub { Link Here
98
        ->status_is(200);
99
        ->status_is(200);
99
100
100
    $t->get_ok( "//$userid:$password@/api/v1/authorities/" . $authority->id => { Accept => 'text/plain' } )
101
    $t->get_ok( "//$userid:$password@/api/v1/authorities/" . $authority->id => { Accept => 'text/plain' } )
101
        ->status_is(200)->content_is(
102
        ->status_is(200)
103
        ->content_is(
102
        q|LDR 00079     2200049   4500
104
        q|LDR 00079     2200049   4500
103
001     1001
105
001     1001
104
110    _9102
106
110    _9102
Lines 107-113 subtest 'get() tests' => sub { Link Here
107
109
108
    $authority->delete;
110
    $authority->delete;
109
    $t->get_ok( "//$userid:$password@/api/v1/authorities/" . $authority->id => { Accept => 'application/marc' } )
111
    $t->get_ok( "//$userid:$password@/api/v1/authorities/" . $authority->id => { Accept => 'application/marc' } )
110
        ->status_is(404)->json_is( '/error', 'Authority record not found' );
112
        ->status_is(404)
113
        ->json_is( '/error', 'Authority record not found' );
111
114
112
    $schema->storage->txn_rollback;
115
    $schema->storage->txn_rollback;
113
};
116
};
Lines 149-155 subtest 'delete() tests' => sub { Link Here
149
152
150
    $patron->flags( 2**14 )->store;    # 14 => editauthorities userflag
153
    $patron->flags( 2**14 )->store;    # 14 => editauthorities userflag
151
154
152
    $t->delete_ok( "//$userid:$password@/api/v1/authorities/" . $authority->id )->status_is( 204, 'REST3.2.4' )
155
    $t->delete_ok( "//$userid:$password@/api/v1/authorities/" . $authority->id )
156
        ->status_is( 204, 'REST3.2.4' )
153
        ->content_is( '', 'REST3.3.4' );
157
        ->content_is( '', 'REST3.3.4' );
154
158
155
    $t->delete_ok( "//$userid:$password@/api/v1/authorities/" . $authority->id )->status_is(404);
159
    $t->delete_ok( "//$userid:$password@/api/v1/authorities/" . $authority->id )->status_is(404);
Lines 214-220 subtest 'post() tests' => sub { Link Here
214
            { 'Content-Type' => 'application/marc-in-json', 'x-authority-type' => 'CORPO_NAME' } => $mij )
218
            { 'Content-Type' => 'application/marc-in-json', 'x-authority-type' => 'CORPO_NAME' } => $mij )
215
        ->status_is(409)
219
        ->status_is(409)
216
        ->header_exists_not( 'Location', 'Location header is only set when the new resource is created' )
220
        ->header_exists_not( 'Location', 'Location header is only set when the new resource is created' )
217
        ->json_like( '/error' => qr/Duplicate record (\d*)/ )->json_is( '/error_code' => q{duplicate} );
221
        ->json_like( '/error' => qr/Duplicate record (\d*)/ )
222
        ->json_is( '/error_code' => q{duplicate} );
218
223
219
    $t->post_ok(
224
    $t->post_ok(
220
        "//$userid:$password@/api/v1/authorities" => {
225
        "//$userid:$password@/api/v1/authorities" => {
Lines 308-314 subtest 'put() tests' => sub { Link Here
308
313
309
    $t->put_ok( "//$userid:$password@/api/v1/authorities/$authid" =>
314
    $t->put_ok( "//$userid:$password@/api/v1/authorities/$authid" =>
310
            { 'Content-Type' => 'application/marcxml+xml', 'x-authority-type' => $authtypecode } => $marcxml )
315
            { 'Content-Type' => 'application/marcxml+xml', 'x-authority-type' => $authtypecode } => $marcxml )
311
        ->status_is(200)->json_has('/id');
316
        ->status_is(200)
317
        ->json_has('/id');
312
318
313
    $authority  = Koha::Authorities->find($authid);
319
    $authority  = Koha::Authorities->find($authid);
314
    $record     = $authority->record;
320
    $record     = $authority->record;
Lines 318-324 subtest 'put() tests' => sub { Link Here
318
324
319
    $t->put_ok( "//$userid:$password@/api/v1/authorities/$authid" =>
325
    $t->put_ok( "//$userid:$password@/api/v1/authorities/$authid" =>
320
            { 'Content-Type' => 'application/marc-in-json', 'x-authority-type' => $authtypecode } => $mij )
326
            { 'Content-Type' => 'application/marc-in-json', 'x-authority-type' => $authtypecode } => $mij )
321
        ->status_is(200)->json_has('/id');
327
        ->status_is(200)
328
        ->json_has('/id');
322
329
323
    $authority  = Koha::Authorities->find($authid);
330
    $authority  = Koha::Authorities->find($authid);
324
    $record     = $authority->record;
331
    $record     = $authority->record;
Lines 327-333 subtest 'put() tests' => sub { Link Here
327
    is( $subfield_a, 'MIJ' );
334
    is( $subfield_a, 'MIJ' );
328
335
329
    $t->put_ok( "//$userid:$password@/api/v1/authorities/$authid" =>
336
    $t->put_ok( "//$userid:$password@/api/v1/authorities/$authid" =>
330
            { 'Content-Type' => 'application/marc', 'x-authority-type' => $authtypecode } => $marc )->status_is(200)
337
            { 'Content-Type' => 'application/marc', 'x-authority-type' => $authtypecode } => $marc )
338
        ->status_is(200)
331
        ->json_has('/id');
339
        ->json_has('/id');
332
340
333
    $authority  = Koha::Authorities->find($authid);
341
    $authority  = Koha::Authorities->find($authid);
(-)a/t/db_dependent/api/v1/biblios.t (-45 / +95 lines)
Lines 81-87 subtest 'get() tests' => sub { Link Here
81
        ->status_is(400);
81
        ->status_is(400);
82
82
83
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber => { Accept => 'application/json' } )
83
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber => { Accept => 'application/json' } )
84
        ->status_is(200)->json_is( '/title', 'The unbearable lightness of being' )
84
        ->status_is(200)
85
        ->json_is( '/title',  'The unbearable lightness of being' )
85
        ->json_is( '/author', 'Milan Kundera' );
86
        ->json_is( '/author', 'Milan Kundera' );
86
87
87
    $t->get_ok(
88
    $t->get_ok(
Lines 96-113 subtest 'get() tests' => sub { Link Here
96
        ->status_is(200);
97
        ->status_is(200);
97
98
98
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber => { Accept => 'text/plain' } )
99
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber => { Accept => 'text/plain' } )
99
        ->status_is(200)->content_is( $biblio->metadata->record->as_formatted );
100
        ->status_is(200)
101
        ->content_is( $biblio->metadata->record->as_formatted );
100
102
101
    # Simulate a data error situation (BZ35246)
103
    # Simulate a data error situation (BZ35246)
102
    $biblio->biblioitem->delete();
104
    $biblio->biblioitem->delete();
103
105
104
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber => { Accept => 'application/json' } )
106
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber => { Accept => 'application/json' } )
105
        ->status_is(500)->json_is( '/error_code', 'internal_server_error' )
107
        ->status_is(500)
106
        ->json_is( '/error', 'Something went wrong, check Koha logs for details.' );
108
        ->json_is( '/error_code', 'internal_server_error' )
109
        ->json_is( '/error',      'Something went wrong, check Koha logs for details.' );
107
110
108
    $biblio->delete;
111
    $biblio->delete;
109
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber => { Accept => 'application/marc' } )
112
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber => { Accept => 'application/marc' } )
110
        ->status_is(404)->json_is( '/error', 'Bibliographic record not found' );
113
        ->status_is(404)
114
        ->json_is( '/error', 'Bibliographic record not found' );
111
115
112
    subtest 'marc-in-json encoding tests' => sub {
116
    subtest 'marc-in-json encoding tests' => sub {
113
117
Lines 124-130 subtest 'get() tests' => sub { Link Here
124
128
125
        my $result = $t->get_ok(
129
        my $result = $t->get_ok(
126
            "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber => { Accept => 'application/marc-in-json' } )
130
            "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber => { Accept => 'application/marc-in-json' } )
127
            ->status_is(200)->tx->res->body;
131
            ->status_is(200)
132
            ->tx->res->body;
128
133
129
        my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
134
        my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
130
135
Lines 153-159 subtest 'get() tests' => sub { Link Here
153
158
154
        my $result = $t->get_ok(
159
        my $result = $t->get_ok(
155
            "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber => { Accept => 'application/marcxml+xml' } )
160
            "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber => { Accept => 'application/marcxml+xml' } )
156
            ->status_is(200)->tx->res->body;
161
            ->status_is(200)
162
            ->tx->res->body;
157
163
158
        my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
164
        my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
159
165
Lines 186-199 subtest 'get_items() tests' => sub { Link Here
186
192
187
    $patron->flags(4)->store;
193
    $patron->flags(4)->store;
188
194
189
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items" )->status_is(200)
195
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items" )
196
        ->status_is(200)
190
        ->json_is( '' => [], 'No items on the biblio' );
197
        ->json_is( '' => [], 'No items on the biblio' );
191
198
192
    my $item_1 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber } );
199
    my $item_1 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber } );
193
    my $item_2 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber } );
200
    my $item_2 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber } );
194
201
195
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items?_order_by=item_id" )
202
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items?_order_by=item_id" )
196
        ->status_is(200)->json_is( '' => [ $item_1->to_api, $item_2->to_api ], 'The items are returned' );
203
        ->status_is(200)
204
        ->json_is( '' => [ $item_1->to_api, $item_2->to_api ], 'The items are returned' );
197
205
198
    $t->get_ok(
206
    $t->get_ok(
199
        "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items" => { "x-koha-embed" => "+strings" } )
207
        "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items" => { "x-koha-embed" => "+strings" } )
Lines 234-240 subtest 'get_items() tests' => sub { Link Here
234
242
235
        $t->get_ok( "//$userid:$password@/api/v1/biblios/"
243
        $t->get_ok( "//$userid:$password@/api/v1/biblios/"
236
                . $item->biblionumber
244
                . $item->biblionumber
237
                . "/items" => { "x-koha-embed" => "first_hold+strings" } )->status_is(200)
245
                . "/items" => { "x-koha-embed" => "first_hold+strings" } )
246
            ->status_is(200)
238
            ->json_is(
247
            ->json_is(
239
            '/0/first_hold/_strings/pickup_library_id' => { type => 'library', str => $pickup_library->branchname } );
248
            '/0/first_hold/_strings/pickup_library_id' => { type => 'library', str => $pickup_library->branchname } );
240
    };
249
    };
Lines 282-288 subtest 'delete() tests' => sub { Link Here
282
    $item->delete();
291
    $item->delete();
283
292
284
    # Bibs with no items can be deleted
293
    # Bibs with no items can be deleted
285
    $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")->status_is( 204, 'REST3.2.4' )
294
    $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
295
        ->status_is( 204, 'REST3.2.4' )
286
        ->content_is( '', 'REST3.3.4' );
296
        ->content_is( '', 'REST3.3.4' );
287
297
288
    $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")->status_is(404);
298
    $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")->status_is(404);
Lines 329-335 subtest 'get_public() tests' => sub { Link Here
329
            . $biblio->biblionumber => { Accept => 'application/weird+format' } )->status_is(400);
339
            . $biblio->biblionumber => { Accept => 'application/weird+format' } )->status_is(400);
330
340
331
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'text/plain' } )
341
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'text/plain' } )
332
        ->status_is(200)->content_like(qr{100\s+_aMilan Kundera})
342
        ->status_is(200)
343
        ->content_like(qr{100\s+_aMilan Kundera})
333
        ->content_like(qr{245\s+_aThe unbearable lightness of being});
344
        ->content_like(qr{245\s+_aThe unbearable lightness of being});
334
345
335
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/"
346
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/"
Lines 343-349 subtest 'get_public() tests' => sub { Link Here
343
        ->status_is(200);
354
        ->status_is(200);
344
355
345
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'text/plain' } )
356
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'text/plain' } )
346
        ->status_is(200)->content_is( $biblio->metadata->record->as_formatted );
357
        ->status_is(200)
358
        ->content_is( $biblio->metadata->record->as_formatted );
347
359
348
    subtest 'anonymous access' => sub {
360
    subtest 'anonymous access' => sub {
349
        plan tests => 9;
361
        plan tests => 9;
Lines 357-363 subtest 'get_public() tests' => sub { Link Here
357
        $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'application/marc' } )
369
        $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'application/marc' } )
358
            ->status_is(200);
370
            ->status_is(200);
359
371
360
        $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'text/plain' } )->status_is(200)
372
        $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'text/plain' } )
373
            ->status_is(200)
361
            ->content_is( $biblio->metadata->record->as_formatted );
374
            ->content_is( $biblio->metadata->record->as_formatted );
362
    };
375
    };
363
376
Lines 376-382 subtest 'get_public() tests' => sub { Link Here
376
389
377
        my $result =
390
        my $result =
378
            $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'application/marc-in-json' } )
391
            $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'application/marc-in-json' } )
379
            ->status_is(200)->tx->res->body;
392
            ->status_is(200)
393
            ->tx->res->body;
380
394
381
        my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
395
        my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
382
396
Lines 392-398 subtest 'get_public() tests' => sub { Link Here
392
    Koha::Caches->get_instance()->flush_all;
406
    Koha::Caches->get_instance()->flush_all;
393
407
394
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'text/plain' } )
408
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'text/plain' } )
395
        ->status_is(200)->content_unlike(qr{100\s+_aMilan Kundera})
409
        ->status_is(200)
410
        ->content_unlike(qr{100\s+_aMilan Kundera})
396
        ->content_like(qr{245\s+_aThe unbearable lightness of being});
411
        ->content_like(qr{245\s+_aThe unbearable lightness of being});
397
412
398
    subtest 'hidden_in_opac tests' => sub {
413
    subtest 'hidden_in_opac tests' => sub {
Lines 428-434 subtest 'get_public() tests' => sub { Link Here
428
    $biblio->delete;
443
    $biblio->delete;
429
    $t->get_ok(
444
    $t->get_ok(
430
        "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'application/marc' } )
445
        "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'application/marc' } )
431
        ->status_is(404)->json_is( '/error', 'Bibliographic record not found' );
446
        ->status_is(404)
447
        ->json_is( '/error', 'Bibliographic record not found' );
432
448
433
    $schema->storage->txn_rollback;
449
    $schema->storage->txn_rollback;
434
};
450
};
Lines 553-559 subtest 'pickup_locations() tests' => sub { Link Here
553
                . "patron_id="
569
                . "patron_id="
554
                . $patron->id
570
                . $patron->id
555
                . "&_order_by=marc_org_code"
571
                . "&_order_by=marc_org_code"
556
                . "&_per_page=1" )->json_is( [$library_1_api] )
572
                . "&_per_page=1" )
573
            ->json_is( [$library_1_api] )
557
            ->header_is( 'X-Total-Count',      '4', '4 is the count for libraries with pickup_location=1' )
574
            ->header_is( 'X-Total-Count',      '4', '4 is the count for libraries with pickup_location=1' )
558
            ->header_is( 'X-Base-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
575
            ->header_is( 'X-Base-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
559
            ->header_unlike( 'Link', qr|rel="prev"| )
576
            ->header_unlike( 'Link', qr|rel="prev"| )
Lines 584-591 subtest 'pickup_locations() tests' => sub { Link Here
584
                . "patron_id="
601
                . "patron_id="
585
                . $patron->id
602
                . $patron->id
586
                . "&_order_by=marc_org_code"
603
                . "&_order_by=marc_org_code"
587
                . "&_per_page=1" )->json_is( [$library_1_api] )->header_is( 'X-Total-Count', '2' )
604
                . "&_per_page=1" )
588
            ->header_is( 'X-Base-Total-Count', '2' )->header_unlike( 'Link', qr|rel="prev"| )
605
            ->json_is( [$library_1_api] )
606
            ->header_is( 'X-Total-Count',      '2' )
607
            ->header_is( 'X-Base-Total-Count', '2' )
608
            ->header_unlike( 'Link', qr|rel="prev"| )
589
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1.*)>\; rel="next"# )
609
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1.*)>\; rel="next"# )
590
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=1.*|_page=1.*\&_per_page=1).*>\; rel="first"# )
610
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=1.*|_page=1.*\&_per_page=1).*>\; rel="first"# )
591
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1).*>\; rel="last"# );
611
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1).*>\; rel="last"# );
Lines 605-611 subtest 'pickup_locations() tests' => sub { Link Here
605
625
606
    $t->get_ok(
626
    $t->get_ok(
607
        "//$userid:$password@/api/v1/biblios/" . $biblio->id . "/pickup_locations?" . "patron_id=" . $patron->id )
627
        "//$userid:$password@/api/v1/biblios/" . $biblio->id . "/pickup_locations?" . "patron_id=" . $patron->id )
608
        ->status_is(404)->json_is( '/error' => 'Bibliographic record not found' );
628
        ->status_is(404)
629
        ->json_is( '/error' => 'Bibliographic record not found' );
609
630
610
    $schema->storage->txn_rollback;
631
    $schema->storage->txn_rollback;
611
};
632
};
Lines 644-656 subtest 'get_items_public() tests' => sub { Link Here
644
665
645
    my $biblio = $builder->build_sample_biblio();
666
    my $biblio = $builder->build_sample_biblio();
646
667
647
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->id . "/items" )->status_is(200)
668
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->id . "/items" )
669
        ->status_is(200)
648
        ->json_is( '' => [], 'No items on the biblio' );
670
        ->json_is( '' => [], 'No items on the biblio' );
649
671
650
    my $item_1 = $builder->build_sample_item( { biblionumber => $biblio->id } );
672
    my $item_1 = $builder->build_sample_item( { biblionumber => $biblio->id } );
651
    my $item_2 = $builder->build_sample_item( { biblionumber => $biblio->id, withdrawn => 1 } );
673
    my $item_2 = $builder->build_sample_item( { biblionumber => $biblio->id, withdrawn => 1 } );
652
674
653
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/items" )->status_is(200)
675
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/items" )
676
        ->status_is(200)
654
        ->json_is(
677
        ->json_is(
655
        '' => [
678
        '' => [
656
            $item_1->to_api( { public => 1 } ),
679
            $item_1->to_api( { public => 1 } ),
Lines 661-667 subtest 'get_items_public() tests' => sub { Link Here
661
684
662
    $rules = { withdrawn => ['1'] };
685
    $rules = { withdrawn => ['1'] };
663
686
664
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/items" )->status_is(200)
687
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/items" )
688
        ->status_is(200)
665
        ->json_is(
689
        ->json_is(
666
        '' => [ $item_1->to_api( { public => 1 } ) ],
690
        '' => [ $item_1->to_api( { public => 1 } ) ],
667
        'The items are returned, hidden one is not returned'
691
        'The items are returned, hidden one is not returned'
Lines 674-680 subtest 'get_items_public() tests' => sub { Link Here
674
698
675
    $override_hidden_items = 1;
699
    $override_hidden_items = 1;
676
700
677
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/items" )->status_is(200)
701
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/items" )
702
        ->status_is(200)
678
        ->json_is(
703
        ->json_is(
679
        '' => [
704
        '' => [
680
            $item_1->to_api( { public => 1 } ),
705
            $item_1->to_api( { public => 1 } ),
Lines 727-733 subtest 'get_bookings() tests' => sub { Link Here
727
752
728
    $t->get_ok( "//$unauth_userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )->status_is(403);
753
    $t->get_ok( "//$unauth_userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )->status_is(403);
729
754
730
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )->status_is(200)
755
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )
756
        ->status_is(200)
731
        ->json_is( '' => [], 'No bookings on the biblio' );
757
        ->json_is( '' => [], 'No bookings on the biblio' );
732
758
733
    # One booking
759
    # One booking
Lines 745-751 subtest 'get_bookings() tests' => sub { Link Here
745
        }
771
        }
746
    );
772
    );
747
773
748
    my $ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )->status_is(200)
774
    my $ret =
775
        $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )
776
        ->status_is(200)
749
        ->tx->res->json;
777
        ->tx->res->json;
750
778
751
    is_deeply( $ret, [ $booking_0->to_api ] );
779
    is_deeply( $ret, [ $booking_0->to_api ] );
Lines 818-824 subtest 'get_checkouts() tests' => sub { Link Here
818
    AddIssue( $patron, $item_2->barcode );
846
    AddIssue( $patron, $item_2->barcode );
819
847
820
    my $ret =
848
    my $ret =
821
        $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts" )->status_is(200)
849
        $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts" )
850
        ->status_is(200)
822
        ->tx->res->json;
851
        ->tx->res->json;
823
852
824
    my $checkout_1 = Koha::Checkouts->find( { itemnumber => $item_1->id } );
853
    my $checkout_1 = Koha::Checkouts->find( { itemnumber => $item_1->id } );
Lines 828-840 subtest 'get_checkouts() tests' => sub { Link Here
828
857
829
    AddReturn( $item_1->barcode );
858
    AddReturn( $item_1->barcode );
830
859
831
    $ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts" )->status_is(200)
860
    $ret =
861
        $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts" )
862
        ->status_is(200)
832
        ->tx->res->json;
863
        ->tx->res->json;
833
864
834
    is_deeply( $ret, [ $checkout_2->to_api ] );
865
    is_deeply( $ret, [ $checkout_2->to_api ] );
835
866
836
    $ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts?checked_in=1" )
867
    $ret =
837
        ->status_is(200)->tx->res->json;
868
        $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts?checked_in=1" )
869
        ->status_is(200)
870
        ->tx->res->json;
838
871
839
    my $old_checkout_1 = Koha::Old::Checkouts->find( $checkout_1->id );
872
    my $old_checkout_1 = Koha::Old::Checkouts->find( $checkout_1->id );
840
873
Lines 866-877 subtest 'set_rating() tests' => sub { Link Here
866
899
867
    $t->post_ok(
900
    $t->post_ok(
868
        "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/ratings" => json => { rating => 3 } )
901
        "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/ratings" => json => { rating => 3 } )
869
        ->status_is(200)->json_is( '/rating', '3' )->json_is( '/average', '3' )->json_is( '/count', '1' );
902
        ->status_is(200)
903
        ->json_is( '/rating',  '3' )
904
        ->json_is( '/average', '3' )
905
        ->json_is( '/count',   '1' );
870
906
871
    $t->post_ok( "//$userid:$password@/api/v1/public/biblios/"
907
    $t->post_ok( "//$userid:$password@/api/v1/public/biblios/"
872
            . $biblio->biblionumber
908
            . $biblio->biblionumber
873
            . "/ratings" => json => { rating => undef } )->status_is(200)->json_is( '/rating', undef )
909
            . "/ratings" => json => { rating => undef } )
874
        ->json_is( '/average', '0' )->json_is( '/count', '0' );
910
        ->status_is(200)
911
        ->json_is( '/rating',  undef )
912
        ->json_is( '/average', '0' )
913
        ->json_is( '/count',   '0' );
875
914
876
    $schema->storage->txn_rollback;
915
    $schema->storage->txn_rollback;
877
916
Lines 1297-1303 subtest 'add() tests' => sub { Link Here
1297
1336
1298
    $t->post_ok( "//$userid:$password@/api/v1/biblios" =>
1337
    $t->post_ok( "//$userid:$password@/api/v1/biblios" =>
1299
            { 'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode } => $marcxml )
1338
            { 'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode } => $marcxml )
1300
        ->status_is(200)->json_has('/id')
1339
        ->status_is(200)
1340
        ->json_has('/id')
1301
        ->header_is( 'Location' => "/api/v1/biblios/" . $t->tx->res->json->{id}, "REST3.4.1" );
1341
        ->header_is( 'Location' => "/api/v1/biblios/" . $t->tx->res->json->{id}, "REST3.4.1" );
1302
1342
1303
    $t->post_ok(
1343
    $t->post_ok(
Lines 1308-1314 subtest 'add() tests' => sub { Link Here
1308
    )->status_is(200)->json_has('/id');
1348
    )->status_is(200)->json_has('/id');
1309
1349
1310
    $t->post_ok( "//$userid:$password@/api/v1/biblios" =>
1350
    $t->post_ok( "//$userid:$password@/api/v1/biblios" =>
1311
            { 'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode } => $marc )->status_is(200)
1351
            { 'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode } => $marc )
1352
        ->status_is(200)
1312
        ->json_has('/id');
1353
        ->json_has('/id');
1313
1354
1314
    subtest 'x-record-source-id header tests' => sub {
1355
    subtest 'x-record-source-id header tests' => sub {
Lines 1352-1358 subtest 'add() tests' => sub { Link Here
1352
    $mock_biblio->mock( 'AddBiblio', sub { return ( undef, undef ); } );
1393
    $mock_biblio->mock( 'AddBiblio', sub { return ( undef, undef ); } );
1353
1394
1354
    $t->post_ok( "//$userid:$password@/api/v1/biblios" =>
1395
    $t->post_ok( "//$userid:$password@/api/v1/biblios" =>
1355
            { 'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode } => $marc )->status_is(400)
1396
            { 'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode } => $marc )
1397
        ->status_is(400)
1356
        ->json_is(
1398
        ->json_is(
1357
        {
1399
        {
1358
            error      => 'Error creating record',
1400
            error      => 'Error creating record',
Lines 1780-1786 subtest 'put() tests' => sub { Link Here
1780
1822
1781
    $t->put_ok( "//$userid:$password@/api/v1/biblios/$biblionumber" =>
1823
    $t->put_ok( "//$userid:$password@/api/v1/biblios/$biblionumber" =>
1782
            { 'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode } => $marcxml )
1824
            { 'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode } => $marcxml )
1783
        ->status_is(200)->json_has('/id');
1825
        ->status_is(200)
1826
        ->json_has('/id');
1784
1827
1785
    $biblio = Koha::Biblios->find($biblionumber);
1828
    $biblio = Koha::Biblios->find($biblionumber);
1786
1829
Lines 1788-1801 subtest 'put() tests' => sub { Link Here
1788
1831
1789
    $t->put_ok( "//$userid:$password@/api/v1/biblios/$biblionumber" =>
1832
    $t->put_ok( "//$userid:$password@/api/v1/biblios/$biblionumber" =>
1790
            { 'Content-Type' => 'application/marc-in-json', 'x-framework-id' => $frameworkcode } => $mij )
1833
            { 'Content-Type' => 'application/marc-in-json', 'x-framework-id' => $frameworkcode } => $mij )
1791
        ->status_is(200)->json_has('/id');
1834
        ->status_is(200)
1835
        ->json_has('/id');
1792
1836
1793
    $biblio = Koha::Biblios->find($biblionumber);
1837
    $biblio = Koha::Biblios->find($biblionumber);
1794
1838
1795
    is( $biblio->title, 'Introduction to Attic Greek  (Using mij) /' );
1839
    is( $biblio->title, 'Introduction to Attic Greek  (Using mij) /' );
1796
1840
1797
    $t->put_ok( "//$userid:$password@/api/v1/biblios/$biblionumber" =>
1841
    $t->put_ok( "//$userid:$password@/api/v1/biblios/$biblionumber" =>
1798
            { 'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode } => $marc )->status_is(200)
1842
            { 'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode } => $marc )
1843
        ->status_is(200)
1799
        ->json_has('/id');
1844
        ->json_has('/id');
1800
1845
1801
    $biblio = Koha::Biblios->find($biblionumber);
1846
    $biblio = Koha::Biblios->find($biblionumber);
Lines 1852-1859 subtest 'list() tests' => sub { Link Here
1852
1897
1853
    $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/json' } )->status_is(200);
1898
    $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/json' } )->status_is(200);
1854
1899
1855
    my $result = $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/marcxml+xml' } )
1900
    my $result =
1856
        ->status_is(200)->tx->res->body;
1901
        $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/marcxml+xml' } )
1902
        ->status_is(200)
1903
        ->tx->res->body;
1857
1904
1858
    my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
1905
    my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
1859
    like( $result, qr/\Q$encoded_title/, "The title is not double encoded" );
1906
    like( $result, qr/\Q$encoded_title/, "The title is not double encoded" );
Lines 1881-1887 subtest 'list() tests' => sub { Link Here
1881
1928
1882
    $query = encode_json( { biblio_id => $biblio->id } );
1929
    $query = encode_json( { biblio_id => $biblio->id } );
1883
1930
1884
    $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/json' } )->status_is(200)
1931
    $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/json' } )
1932
        ->status_is(200)
1885
        ->json_is( '/0/timestamp' =>
1933
        ->json_is( '/0/timestamp' =>
1886
            output_pref( { dt => $fixed_date, dateformat => 'rfc3339' }, 'biblio table timestamp takes precedence' ) );
1934
            output_pref( { dt => $fixed_date, dateformat => 'rfc3339' }, 'biblio table timestamp takes precedence' ) );
1887
1935
Lines 2245-2251 subtest 'merge() tests' => sub { Link Here
2245
    my $result =
2293
    my $result =
2246
        $t->post_ok( "//$userid:$password@/api/v1/biblios/$biblio_id1/merge" =>
2294
        $t->post_ok( "//$userid:$password@/api/v1/biblios/$biblio_id1/merge" =>
2247
            { 'Content-Type' => 'application/json', 'Accept' => 'application/marc-in-json' } => $json_input1 )
2295
            { 'Content-Type' => 'application/json', 'Accept' => 'application/marc-in-json' } => $json_input1 )
2248
        ->status_is(200)->tx->res->body;
2296
        ->status_is(200)
2297
        ->tx->res->body;
2249
    like( $result, qr/$title_1/, "Merged record has the correct title" );
2298
    like( $result, qr/$title_1/, "Merged record has the correct title" );
2250
    unlike( $result, qr/$title_2/, "Merged record doesn't have the wrong title" );
2299
    unlike( $result, qr/$title_2/, "Merged record doesn't have the wrong title" );
2251
2300
Lines 2257-2263 subtest 'merge() tests' => sub { Link Here
2257
    $result =
2306
    $result =
2258
        $t->post_ok( "//$userid:$password@/api/v1/biblios/$biblio_id1/merge" =>
2307
        $t->post_ok( "//$userid:$password@/api/v1/biblios/$biblio_id1/merge" =>
2259
            { 'Content-Type' => 'application/json', 'Accept' => 'application/marc-in-json' } => $json_input2 )
2308
            { 'Content-Type' => 'application/json', 'Accept' => 'application/marc-in-json' } => $json_input2 )
2260
        ->status_is(200)->tx->res->body;
2309
        ->status_is(200)
2310
        ->tx->res->body;
2261
    like( $result, qr/Using mij/, "Update with Marc-in-json record" );
2311
    like( $result, qr/Using mij/, "Update with Marc-in-json record" );
2262
    unlike( $result, qr/$title_1/, "Change all record with dat in the 'datarecord' field" );
2312
    unlike( $result, qr/$title_1/, "Change all record with dat in the 'datarecord' field" );
2263
2313
(-)a/t/db_dependent/api/v1/bookings.t (-13 / +26 lines)
Lines 135-145 subtest 'list() tests' => sub { Link Here
135
135
136
    $api_filter = encode_json(
136
    $api_filter = encode_json(
137
        { 'me.start_date' => { '<=' => output_pref( { dateformat => "rfc3339", dt => dt_from_string } ) } } );
137
        { 'me.start_date' => { '<=' => output_pref( { dateformat => "rfc3339", dt => dt_from_string } ) } } );
138
    $t->get_ok("//$userid:$password@/api/v1/bookings?q=$api_filter")->status_is(200)
138
    $t->get_ok("//$userid:$password@/api/v1/bookings?q=$api_filter")
139
        ->status_is(200)
139
        ->json_is( '' => [ $booking_0->to_api ], 'filtering to before today also works' );
140
        ->json_is( '' => [ $booking_0->to_api ], 'filtering to before today also works' );
140
141
141
    # Warn on unsupported query parameter
142
    # Warn on unsupported query parameter
142
    $t->get_ok("//$userid:$password@/api/v1/bookings?booking_blah=blah")->status_is(400)
143
    $t->get_ok("//$userid:$password@/api/v1/bookings?booking_blah=blah")
144
        ->status_is(400)
143
        ->json_is( [ { path => '/query/booking_blah', message => 'Malformed query string' } ] );
145
        ->json_is( [ { path => '/query/booking_blah', message => 'Malformed query string' } ] );
144
146
145
    $schema->storage->txn_rollback;
147
    $schema->storage->txn_rollback;
Lines 176-189 subtest 'get() tests' => sub { Link Here
176
    $t->get_ok( "//$unauth_userid:$password@/api/v1/bookings/" . $booking->booking_id )->status_is(403);
178
    $t->get_ok( "//$unauth_userid:$password@/api/v1/bookings/" . $booking->booking_id )->status_is(403);
177
179
178
    # Authorized user tests
180
    # Authorized user tests
179
    $t->get_ok( "//$userid:$password@/api/v1/bookings/" . $booking->booking_id )->status_is(200)
181
    $t->get_ok( "//$userid:$password@/api/v1/bookings/" . $booking->booking_id )
182
        ->status_is(200)
180
        ->json_is( $booking->to_api );
183
        ->json_is( $booking->to_api );
181
184
182
    my $booking_to_delete = $builder->build_object( { class => 'Koha::Bookings' } );
185
    my $booking_to_delete = $builder->build_object( { class => 'Koha::Bookings' } );
183
    my $non_existent_id   = $booking_to_delete->id;
186
    my $non_existent_id   = $booking_to_delete->id;
184
    $booking_to_delete->delete;
187
    $booking_to_delete->delete;
185
188
186
    $t->get_ok("//$userid:$password@/api/v1/bookings/$non_existent_id")->status_is(404)
189
    $t->get_ok("//$userid:$password@/api/v1/bookings/$non_existent_id")
190
        ->status_is(404)
187
        ->json_is( '/error' => 'Booking not found' );
191
        ->json_is( '/error' => 'Booking not found' );
188
192
189
    $schema->storage->txn_rollback;
193
    $schema->storage->txn_rollback;
Lines 244-250 subtest 'add() tests' => sub { Link Here
244
    # Authorized attempt to write invalid data
248
    # Authorized attempt to write invalid data
245
    my $booking_with_invalid_field = { %{$booking}, blah => 'some stuff' };
249
    my $booking_with_invalid_field = { %{$booking}, blah => 'some stuff' };
246
250
247
    $t->post_ok( "//$userid:$password@/api/v1/bookings" => json => $booking_with_invalid_field )->status_is(400)
251
    $t->post_ok( "//$userid:$password@/api/v1/bookings" => json => $booking_with_invalid_field )
252
        ->status_is(400)
248
        ->json_is(
253
        ->json_is(
249
        "/errors" => [
254
        "/errors" => [
250
            {
255
            {
Lines 256-263 subtest 'add() tests' => sub { Link Here
256
261
257
    # Authorized attempt to write
262
    # Authorized attempt to write
258
    my $booking_id =
263
    my $booking_id =
259
        $t->post_ok( "//$userid:$password@/api/v1/bookings" => json => $booking )->status_is( 201, 'REST3.2.1' )
264
        $t->post_ok( "//$userid:$password@/api/v1/bookings" => json => $booking )
260
        ->header_like( Location => qr|^\/api\/v1\/bookings/\d*|, 'REST3.4.1' )->json_is( '/biblio_id' => $biblio->id )
265
        ->status_is( 201, 'REST3.2.1' )
266
        ->header_like( Location => qr|^\/api\/v1\/bookings/\d*|, 'REST3.4.1' )
267
        ->json_is( '/biblio_id' => $biblio->id )
261
        ->tx->res->json->{booking_id};
268
        ->tx->res->json->{booking_id};
262
269
263
    # Authorized attempt to create with null id
270
    # Authorized attempt to create with null id
Lines 267-273 subtest 'add() tests' => sub { Link Here
267
    # Authorized attempt to create with existing id
274
    # Authorized attempt to create with existing id
268
    $booking->{booking_id} = $booking_id;
275
    $booking->{booking_id} = $booking_id;
269
    warnings_like {
276
    warnings_like {
270
        $t->post_ok( "//$userid:$password@/api/v1/bookings" => json => $booking )->status_is(409)
277
        $t->post_ok( "//$userid:$password@/api/v1/bookings" => json => $booking )
278
            ->status_is(409)
271
            ->json_is( "/error" => "Duplicate booking_id" );
279
            ->json_is( "/error" => "Duplicate booking_id" );
272
    }
280
    }
273
    qr/DBD::mysql::st execute failed: Duplicate entry '(.*?)' for key '(.*\.?)PRIMARY'/;
281
    qr/DBD::mysql::st execute failed: Duplicate entry '(.*?)' for key '(.*\.?)PRIMARY'/;
Lines 335-341 subtest 'update() tests' => sub { Link Here
335
    };
343
    };
336
344
337
    $t->put_ok( "//$userid:$password@/api/v1/bookings/$booking_id" => json => $booking_with_missing_field )
345
    $t->put_ok( "//$userid:$password@/api/v1/bookings/$booking_id" => json => $booking_with_missing_field )
338
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/biblio_id" } ] );
346
        ->status_is(400)
347
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/biblio_id" } ] );
339
348
340
    # Full object update on PUT
349
    # Full object update on PUT
341
    my $booking_with_updated_field = {
350
    my $booking_with_updated_field = {
Lines 348-354 subtest 'update() tests' => sub { Link Here
348
    };
357
    };
349
358
350
    $t->put_ok( "//$userid:$password@/api/v1/bookings/$booking_id" => json => $booking_with_updated_field )
359
    $t->put_ok( "//$userid:$password@/api/v1/bookings/$booking_id" => json => $booking_with_updated_field )
351
        ->status_is(200)->json_is( '/biblio_id' => $biblio->id );
360
        ->status_is(200)
361
        ->json_is( '/biblio_id' => $biblio->id );
352
362
353
    # Authorized attempt to write invalid data
363
    # Authorized attempt to write invalid data
354
    my $booking_with_invalid_field = {
364
    my $booking_with_invalid_field = {
Lines 362-368 subtest 'update() tests' => sub { Link Here
362
    };
372
    };
363
373
364
    $t->put_ok( "//$userid:$password@/api/v1/bookings/$booking_id" => json => $booking_with_invalid_field )
374
    $t->put_ok( "//$userid:$password@/api/v1/bookings/$booking_id" => json => $booking_with_invalid_field )
365
        ->status_is(400)->json_is(
375
        ->status_is(400)
376
        ->json_is(
366
        "/errors" => [
377
        "/errors" => [
367
            {
378
            {
368
                message => "Properties not allowed: blah.",
379
                message => "Properties not allowed: blah.",
Lines 431-437 subtest 'delete() tests' => sub { Link Here
431
    # Unauthorized attempt to delete
442
    # Unauthorized attempt to delete
432
    $t->delete_ok("//$unauth_userid:$password@/api/v1/bookings/$booking_id")->status_is(403);
443
    $t->delete_ok("//$unauth_userid:$password@/api/v1/bookings/$booking_id")->status_is(403);
433
444
434
    $t->delete_ok("//$userid:$password@/api/v1/bookings/$booking_id")->status_is( 204, 'REST3.2.4' )
445
    $t->delete_ok("//$userid:$password@/api/v1/bookings/$booking_id")
446
        ->status_is( 204, 'REST3.2.4' )
435
        ->content_is( '', 'REST3.3.4' );
447
        ->content_is( '', 'REST3.3.4' );
436
448
437
    $t->delete_ok("//$userid:$password@/api/v1/bookings/$booking_id")->status_is(404);
449
    $t->delete_ok("//$userid:$password@/api/v1/bookings/$booking_id")->status_is(404);
Lines 491-497 subtest 'patch() tests' => sub { Link Here
491
    };
503
    };
492
504
493
    $t->patch_ok( "//$userid:$password@/api/v1/bookings/$booking_id" => json => $booking_with_invalid_field )
505
    $t->patch_ok( "//$userid:$password@/api/v1/bookings/$booking_id" => json => $booking_with_invalid_field )
494
        ->status_is(400)->json_is(
506
        ->status_is(400)
507
        ->json_is(
495
        "/errors" => [
508
        "/errors" => [
496
            {
509
            {
497
                message => "Properties not allowed: blah.",
510
                message => "Properties not allowed: blah.",
(-)a/t/db_dependent/api/v1/cash_registers.t (-1 / +2 lines)
Lines 68-74 subtest 'list() tests' => sub { Link Here
68
    my $new_register = $builder->build_object( { class => 'Koha::Cash::Registers' } );
68
    my $new_register = $builder->build_object( { class => 'Koha::Cash::Registers' } );
69
69
70
    # One more register created, both should be returned
70
    # One more register created, both should be returned
71
    $t->get_ok("//$userid:$password@/api/v1/cash_registers")->status_is(200)
71
    $t->get_ok("//$userid:$password@/api/v1/cash_registers")
72
        ->status_is(200)
72
        ->json_is( [ $register->to_api, $new_register->to_api, ] );
73
        ->json_is( [ $register->to_api, $new_register->to_api, ] );
73
74
74
    # Unauthorized access
75
    # Unauthorized access
(-)a/t/db_dependent/api/v1/cashups.t (-5 / +10 lines)
Lines 68-74 subtest 'list() tests' => sub { Link Here
68
    my $non_existent_cr_id      = $cash_register_to_delete->id;
68
    my $non_existent_cr_id      = $cash_register_to_delete->id;
69
    $cash_register_to_delete->delete;
69
    $cash_register_to_delete->delete;
70
70
71
    $t->get_ok("//$userid:$password@/api/v1/cash_registers/$non_existent_cr_id/cashups")->status_is(404)
71
    $t->get_ok("//$userid:$password@/api/v1/cash_registers/$non_existent_cr_id/cashups")
72
        ->status_is(404)
72
        ->json_is( '/error' => 'Register not found' );
73
        ->json_is( '/error' => 'Register not found' );
73
74
74
    my $register    = $builder->build_object( { class => 'Koha::Cash::Registers' } );
75
    my $register    = $builder->build_object( { class => 'Koha::Cash::Registers' } );
Lines 89-95 subtest 'list() tests' => sub { Link Here
89
    );
90
    );
90
91
91
    # One cashup created, should get returned
92
    # One cashup created, should get returned
92
    $t->get_ok("//$userid:$password@/api/v1/cash_registers/$register_id/cashups")->status_is(200)
93
    $t->get_ok("//$userid:$password@/api/v1/cash_registers/$register_id/cashups")
94
        ->status_is(200)
93
        ->json_is( [ $cashup->to_api ] );
95
        ->json_is( [ $cashup->to_api ] );
94
96
95
    my $another_cashup = $builder->build_object(
97
    my $another_cashup = $builder->build_object(
Lines 104-114 subtest 'list() tests' => sub { Link Here
104
    );
106
    );
105
107
106
    # One more cashup created, both should be returned
108
    # One more cashup created, both should be returned
107
    $t->get_ok("//$userid:$password@/api/v1/cash_registers/$register_id/cashups")->status_is(200)
109
    $t->get_ok("//$userid:$password@/api/v1/cash_registers/$register_id/cashups")
110
        ->status_is(200)
108
        ->json_is( [ $another_cashup->to_api, $cashup->to_api, ] );
111
        ->json_is( [ $another_cashup->to_api, $cashup->to_api, ] );
109
112
110
    # Warn on unsupported query parameter
113
    # Warn on unsupported query parameter
111
    $t->get_ok("//$userid:$password@/api/v1/cash_registers/$register_id/cashups?cashup_blah=blah")->status_is(400)
114
    $t->get_ok("//$userid:$password@/api/v1/cash_registers/$register_id/cashups?cashup_blah=blah")
115
        ->status_is(400)
112
        ->json_is(
116
        ->json_is(
113
        [
117
        [
114
            {
118
            {
Lines 159-165 subtest 'get() tests' => sub { Link Here
159
    my $non_existent_id  = $cashup_to_delete->id;
163
    my $non_existent_id  = $cashup_to_delete->id;
160
    $cashup_to_delete->delete;
164
    $cashup_to_delete->delete;
161
165
162
    $t->get_ok("//$userid:$password@/api/v1/cashups/$non_existent_id")->status_is(404)
166
    $t->get_ok("//$userid:$password@/api/v1/cashups/$non_existent_id")
167
        ->status_is(404)
163
        ->json_is( '/error' => 'Cashup not found' );
168
        ->json_is( '/error' => 'Cashup not found' );
164
169
165
    $schema->storage->txn_rollback;
170
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/checkouts.t (-59 / +127 lines)
Lines 91-97 $bookings_librarian->set_password( { password => $password, skip_validation => 1 Link Here
91
my $bookings_userid = $bookings_librarian->userid;
91
my $bookings_userid = $bookings_librarian->userid;
92
92
93
$t->get_ok("//$bookings_userid:$password@/api/v1/checkouts?patron_id=$patron_id")
93
$t->get_ok("//$bookings_userid:$password@/api/v1/checkouts?patron_id=$patron_id")
94
    ->status_is( 200, 'manage_bookings allows checkouts access' )->json_is( [] );
94
    ->status_is( 200, 'manage_bookings allows checkouts access' )
95
    ->json_is( [] );
95
96
96
Koha::CirculationRules->set_rules(
97
Koha::CirculationRules->set_rules(
97
    {
98
    {
Lines 121-146 my $date_due3 = Koha::DateUtils::dt_from_string( $issue3->date_due ); Link Here
121
my $issue4    = C4::Circulation::AddIssue( $patron, $item4->barcode );
122
my $issue4    = C4::Circulation::AddIssue( $patron, $item4->barcode );
122
C4::Circulation::AddReturn( $item4->barcode, $branchcode );
123
C4::Circulation::AddReturn( $item4->barcode, $branchcode );
123
124
124
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id")->status_is(200)
125
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id")
125
    ->json_is( '/0/patron_id' => $patron_id )->json_is( '/0/item_id' => $item1->itemnumber )
126
    ->status_is(200)
127
    ->json_is( '/0/patron_id' => $patron_id )
128
    ->json_is( '/0/item_id'   => $item1->itemnumber )
126
    ->json_is( '/0/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due1 } ) )
129
    ->json_is( '/0/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due1 } ) )
127
    ->json_is( '/1/patron_id' => $patron_id )->json_is( '/1/item_id' => $item2->itemnumber )
130
    ->json_is( '/1/patron_id' => $patron_id )
128
    ->json_is( '/1/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due2 } ) )->json_hasnt('/2');
131
    ->json_is( '/1/item_id'   => $item2->itemnumber )
132
    ->json_is( '/1/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due2 } ) )
133
    ->json_hasnt('/2');
129
134
130
# Test checked_in parameter, zero means, the response is same as without it
135
# Test checked_in parameter, zero means, the response is same as without it
131
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id&checked_in=0")->status_is(200)
136
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id&checked_in=0")
132
    ->json_is( '/0/patron_id' => $patron_id )->json_is( '/0/item_id' => $item1->itemnumber )
137
    ->status_is(200)
138
    ->json_is( '/0/patron_id' => $patron_id )
139
    ->json_is( '/0/item_id'   => $item1->itemnumber )
133
    ->json_is( '/0/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due1 } ) )
140
    ->json_is( '/0/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due1 } ) )
134
    ->json_is( '/1/patron_id' => $patron_id )->json_is( '/1/item_id' => $item2->itemnumber )
141
    ->json_is( '/1/patron_id' => $patron_id )
135
    ->json_is( '/1/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due2 } ) )->json_hasnt('/2');
142
    ->json_is( '/1/item_id'   => $item2->itemnumber )
143
    ->json_is( '/1/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due2 } ) )
144
    ->json_hasnt('/2');
136
145
137
# Test checked_in parameter, one measn, the checked in checkout is in the response too
146
# Test checked_in parameter, one measn, the checked in checkout is in the response too
138
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id&checked_in=1")->status_is(200)
147
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id&checked_in=1")
139
    ->json_is( '/0/patron_id' => $patron_id )->json_is( '/0/item_id' => $item4->itemnumber )->json_hasnt('/1');
148
    ->status_is(200)
149
    ->json_is( '/0/patron_id' => $patron_id )
150
    ->json_is( '/0/item_id'   => $item4->itemnumber )
151
    ->json_hasnt('/1');
140
152
141
$item4->delete;
153
$item4->delete;
142
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id&checked_in=1")->status_is(200)
154
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id&checked_in=1")
143
    ->json_is( '/0/patron_id' => $patron_id )->json_is( '/0/item_id' => undef );
155
    ->status_is(200)
156
    ->json_is( '/0/patron_id' => $patron_id )
157
    ->json_is( '/0/item_id'   => undef );
144
158
145
$t->get_ok( "//$unauth_userid:$unauth_password@/api/v1/checkouts/" . $issue3->issue_id )->status_is(403)->json_is(
159
$t->get_ok( "//$unauth_userid:$unauth_password@/api/v1/checkouts/" . $issue3->issue_id )->status_is(403)->json_is(
146
    {
160
    {
Lines 149-197 $t->get_ok( "//$unauth_userid:$unauth_password@/api/v1/checkouts/" . $issue3->is Link Here
149
    }
163
    }
150
);
164
);
151
165
152
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id")->status_is(200)
166
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id")
153
    ->json_is( '/0/patron_id' => $patron_id )->json_is( '/0/item_id' => $item1->itemnumber )
167
    ->status_is(200)
168
    ->json_is( '/0/patron_id' => $patron_id )
169
    ->json_is( '/0/item_id'   => $item1->itemnumber )
154
    ->json_is( '/0/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due1 } ) )
170
    ->json_is( '/0/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due1 } ) )
155
    ->json_is( '/1/patron_id' => $patron_id )->json_is( '/1/item_id' => $item2->itemnumber )
171
    ->json_is( '/1/patron_id' => $patron_id )
156
    ->json_is( '/1/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due2 } ) )->json_hasnt('/2');
172
    ->json_is( '/1/item_id'   => $item2->itemnumber )
157
173
    ->json_is( '/1/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due2 } ) )
158
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id&_per_page=1&_page=1")->status_is(200)
174
    ->json_hasnt('/2');
159
    ->header_is( 'X-Total-Count', '2' )->header_like( 'Link', qr|rel="next"| )->header_like( 'Link', qr|rel="first"| )
175
160
    ->header_like( 'Link', qr|rel="last"| )->json_is( '/0/patron_id' => $patron_id )
176
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id&_per_page=1&_page=1")
161
    ->json_is( '/0/item_id'  => $item1->itemnumber )
177
    ->status_is(200)
162
    ->json_is( '/0/due_date' => output_pref( { dateformat => "rfc3339", dt => $date_due1 } ) )->json_hasnt('/1');
178
    ->header_is( 'X-Total-Count', '2' )
163
179
    ->header_like( 'Link', qr|rel="next"| )
164
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id&_per_page=1&_page=2")->status_is(200)
180
    ->header_like( 'Link', qr|rel="first"| )
165
    ->header_is( 'X-Total-Count', '2' )->header_like( 'Link', qr|rel="prev"| )->header_like( 'Link', qr|rel="first"| )
181
    ->header_like( 'Link', qr|rel="last"| )
166
    ->header_like( 'Link', qr|rel="last"| )->json_is( '/0/patron_id' => $patron_id )
182
    ->json_is( '/0/patron_id' => $patron_id )
167
    ->json_is( '/0/item_id'  => $item2->itemnumber )
183
    ->json_is( '/0/item_id'   => $item1->itemnumber )
168
    ->json_is( '/0/due_date' => output_pref( { dateformat => "rfc3339", dt => $date_due2 } ) )->json_hasnt('/1');
184
    ->json_is( '/0/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due1 } ) )
169
185
    ->json_hasnt('/1');
170
$t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue1->issue_id )->status_is(200)
186
171
    ->json_is( '/patron_id' => $patron_id )->json_is( '/item_id' => $item1->itemnumber )
187
$t->get_ok("//$userid:$password@/api/v1/checkouts?patron_id=$patron_id&_per_page=1&_page=2")
172
    ->json_is( '/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due1 } ) )->json_hasnt('/1');
188
    ->status_is(200)
173
189
    ->header_is( 'X-Total-Count', '2' )
174
$t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue1->issue_id )->status_is(200)
190
    ->header_like( 'Link', qr|rel="prev"| )
191
    ->header_like( 'Link', qr|rel="first"| )
192
    ->header_like( 'Link', qr|rel="last"| )
193
    ->json_is( '/0/patron_id' => $patron_id )
194
    ->json_is( '/0/item_id'   => $item2->itemnumber )
195
    ->json_is( '/0/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due2 } ) )
196
    ->json_hasnt('/1');
197
198
$t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue1->issue_id )
199
    ->status_is(200)
200
    ->json_is( '/patron_id' => $patron_id )
201
    ->json_is( '/item_id'   => $item1->itemnumber )
202
    ->json_is( '/due_date'  => output_pref( { dateformat => "rfc3339", dt => $date_due1 } ) )
203
    ->json_hasnt('/1');
204
205
$t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue1->issue_id )
206
    ->status_is(200)
175
    ->json_is( '/due_date' => output_pref( { dateformat => "rfc3339", dt => $date_due1 } ) );
207
    ->json_is( '/due_date' => output_pref( { dateformat => "rfc3339", dt => $date_due1 } ) );
176
208
177
$t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue2->issue_id )->status_is(200)
209
$t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue2->issue_id )
210
    ->status_is(200)
178
    ->json_is( '/due_date' => output_pref( { dateformat => "rfc3339", dt => $date_due2 } ) );
211
    ->json_is( '/due_date' => output_pref( { dateformat => "rfc3339", dt => $date_due2 } ) );
179
212
180
my $expected_datedue =
213
my $expected_datedue =
181
    $date_due->set_time_zone('local')->add( days => 7 )->set( hour => 23, minute => 59, second => 0 );
214
    $date_due->set_time_zone('local')->add( days => 7 )->set( hour => 23, minute => 59, second => 0 );
182
215
183
$t->post_ok( "//$userid:$password@/api/v1/checkouts/" . $issue1->issue_id . "/renewal" )->status_is(201)
216
$t->post_ok( "//$userid:$password@/api/v1/checkouts/" . $issue1->issue_id . "/renewal" )
217
    ->status_is(201)
184
    ->json_is( '/due_date' => output_pref( { dateformat => "rfc3339", dt => $expected_datedue } ) )
218
    ->json_is( '/due_date' => output_pref( { dateformat => "rfc3339", dt => $expected_datedue } ) )
185
    ->header_is( Location => "/api/v1/checkouts/" . $issue1->issue_id . "/renewal" );
219
    ->header_is( Location => "/api/v1/checkouts/" . $issue1->issue_id . "/renewal" );
186
220
187
my $renewal = $issue1->renewals->last;
221
my $renewal = $issue1->renewals->last;
188
is( $renewal->renewal_type, 'Manual', 'Manual renewal recorded' );
222
is( $renewal->renewal_type, 'Manual', 'Manual renewal recorded' );
189
223
190
$t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue1->issue_id . "/renewals" )->status_is(200)
224
$t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue1->issue_id . "/renewals" )
191
    ->json_is( '/0/checkout_id' => $issue1->issue_id )->json_is( '/0/interface' => 'api' )
225
    ->status_is(200)
226
    ->json_is( '/0/checkout_id' => $issue1->issue_id )
227
    ->json_is( '/0/interface'   => 'api' )
192
    ->json_is( '/0/renewer_id'  => $librarian->borrowernumber );
228
    ->json_is( '/0/renewer_id'  => $librarian->borrowernumber );
193
229
194
$t->post_ok( "//$unauth_userid:$unauth_password@/api/v1/checkouts/" . $issue3->issue_id . "/renewal" )->status_is(403)
230
$t->post_ok( "//$unauth_userid:$unauth_password@/api/v1/checkouts/" . $issue3->issue_id . "/renewal" )
231
    ->status_is(403)
195
    ->json_is(
232
    ->json_is(
196
    {
233
    {
197
        error                => "Authorization failure. Missing required permission(s).",
234
        error                => "Authorization failure. Missing required permission(s).",
Lines 199-205 $t->post_ok( "//$unauth_userid:$unauth_password@/api/v1/checkouts/" . $issue3->i Link Here
199
    }
236
    }
200
    );
237
    );
201
238
202
$t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue2->issue_id . "/allows_renewal" )->status_is(200)
239
$t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue2->issue_id . "/allows_renewal" )
240
    ->status_is(200)
203
    ->json_is(
241
    ->json_is(
204
    {
242
    {
205
        allows_renewal   => Mojo::JSON->true,
243
        allows_renewal   => Mojo::JSON->true,
Lines 210-223 $t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue2->issue_id . "/all Link Here
210
    }
248
    }
211
    );
249
    );
212
250
213
$t->post_ok( "//$userid:$password@/api/v1/checkouts/" . $issue2->issue_id . "/renewal" )->status_is(201)
251
$t->post_ok( "//$userid:$password@/api/v1/checkouts/" . $issue2->issue_id . "/renewal" )
252
    ->status_is(201)
214
    ->json_is( '/due_date' => output_pref( { dateformat => "rfc3339", dt => $expected_datedue } ) )
253
    ->json_is( '/due_date' => output_pref( { dateformat => "rfc3339", dt => $expected_datedue } ) )
215
    ->header_is( Location => "/api/v1/checkouts/" . $issue2->issue_id . "/renewal" );
254
    ->header_is( Location => "/api/v1/checkouts/" . $issue2->issue_id . "/renewal" );
216
255
217
$t->post_ok( "//$userid:$password@/api/v1/checkouts/" . $issue1->issue_id . "/renewal" )->status_is(403)
256
$t->post_ok( "//$userid:$password@/api/v1/checkouts/" . $issue1->issue_id . "/renewal" )
257
    ->status_is(403)
218
    ->json_is( { error => 'Renewal not authorized (too_many)' } );
258
    ->json_is( { error => 'Renewal not authorized (too_many)' } );
219
259
220
$t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue2->issue_id . "/allows_renewal" )->status_is(200)
260
$t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue2->issue_id . "/allows_renewal" )
261
    ->status_is(200)
221
    ->json_is(
262
    ->json_is(
222
    {
263
    {
223
        allows_renewal   => Mojo::JSON->false,
264
        allows_renewal   => Mojo::JSON->false,
Lines 275-281 subtest 'get_availability' => sub { Link Here
275
316
276
    $t->get_ok(
317
    $t->get_ok(
277
        "//$unauth_userid:$unauth_password@/api/v1/checkouts/availability?item_id=$item1_id&patron_id=$patron_id")
318
        "//$unauth_userid:$unauth_password@/api/v1/checkouts/availability?item_id=$item1_id&patron_id=$patron_id")
278
        ->status_is(403)->json_is(
319
        ->status_is(403)
320
        ->json_is(
279
        {
321
        {
280
            error                => "Authorization failure. Missing required permission(s).",
322
            error                => "Authorization failure. Missing required permission(s).",
281
            required_permissions => { circulate => "circulate_remaining_permissions" }
323
            required_permissions => { circulate => "circulate_remaining_permissions" }
Lines 284-304 subtest 'get_availability' => sub { Link Here
284
326
285
    # Available
327
    # Available
286
    $t->get_ok("//$userid:$password@/api/v1/checkouts/availability?item_id=$item1_id&patron_id=$patron_id")
328
    $t->get_ok("//$userid:$password@/api/v1/checkouts/availability?item_id=$item1_id&patron_id=$patron_id")
287
        ->status_is(200)->json_is( '/blockers' => {} )->json_is( '/confirms' => {} )->json_is( '/warnings' => {} )
329
        ->status_is(200)
330
        ->json_is( '/blockers' => {} )
331
        ->json_is( '/confirms' => {} )
332
        ->json_is( '/warnings' => {} )
288
        ->json_has('/confirmation_token');
333
        ->json_has('/confirmation_token');
289
334
290
    # Blocked
335
    # Blocked
291
    %issuingimpossible = ( GNA => 1 );
336
    %issuingimpossible = ( GNA => 1 );
292
    $t->get_ok("//$userid:$password@/api/v1/checkouts/availability?item_id=$item1_id&patron_id=$patron_id")
337
    $t->get_ok("//$userid:$password@/api/v1/checkouts/availability?item_id=$item1_id&patron_id=$patron_id")
293
        ->status_is(200)->json_is( '/blockers' => { GNA => 1 } )->json_is( '/confirms' => {} )
338
        ->status_is(200)
294
        ->json_is( '/warnings' => {} )->json_has('/confirmation_token');
339
        ->json_is( '/blockers' => { GNA => 1 } )
340
        ->json_is( '/confirms' => {} )
341
        ->json_is( '/warnings' => {} )
342
        ->json_has('/confirmation_token');
295
    %issuingimpossible = ();
343
    %issuingimpossible = ();
296
344
297
    # Warnings/Info
345
    # Warnings/Info
298
    %alerts   = ( alert1   => "this is an alert" );
346
    %alerts   = ( alert1   => "this is an alert" );
299
    %messages = ( message1 => "this is a message" );
347
    %messages = ( message1 => "this is a message" );
300
    $t->get_ok("//$userid:$password@/api/v1/checkouts/availability?item_id=$item1_id&patron_id=$patron_id")
348
    $t->get_ok("//$userid:$password@/api/v1/checkouts/availability?item_id=$item1_id&patron_id=$patron_id")
301
        ->status_is(200)->json_is( '/blockers' => {} )->json_is( '/confirms' => {} )
349
        ->status_is(200)
350
        ->json_is( '/blockers' => {} )
351
        ->json_is( '/confirms' => {} )
302
        ->json_is( '/warnings' => { alert1 => "this is an alert", message1 => "this is a message" } )
352
        ->json_is( '/warnings' => { alert1 => "this is an alert", message1 => "this is a message" } )
303
        ->json_has('/confirmation_token');
353
        ->json_has('/confirmation_token');
304
    %alerts   = ();
354
    %alerts   = ();
Lines 308-315 subtest 'get_availability' => sub { Link Here
308
    %needsconfirmation = ( confirm1 => 1, confirm2 => 'please' );
358
    %needsconfirmation = ( confirm1 => 1, confirm2 => 'please' );
309
    my $token = Koha::Token->new->generate_jwt( { id => $librarian->id . ":" . $item1_id . ":confirm1:confirm2" } );
359
    my $token = Koha::Token->new->generate_jwt( { id => $librarian->id . ":" . $item1_id . ":confirm1:confirm2" } );
310
    $t->get_ok("//$userid:$password@/api/v1/checkouts/availability?item_id=$item1_id&patron_id=$patron_id")
360
    $t->get_ok("//$userid:$password@/api/v1/checkouts/availability?item_id=$item1_id&patron_id=$patron_id")
311
        ->status_is(200)->json_is( '/blockers' => {} )
361
        ->status_is(200)
312
        ->json_is( '/confirms' => { confirm1 => 1, confirm2 => 'please' } )->json_is( '/warnings' => {} )
362
        ->json_is( '/blockers' => {} )
363
        ->json_is( '/confirms' => { confirm1 => 1, confirm2 => 'please' } )
364
        ->json_is( '/warnings' => {} )
313
        ->json_has('/confirmation_token');
365
        ->json_has('/confirmation_token');
314
    my $confirmation_token = $t->tx->res->json('/confirmation_token');
366
    my $confirmation_token = $t->tx->res->json('/confirmation_token');
315
    ok(
367
    ok(
Lines 336-350 subtest 'get_availability' => sub { Link Here
336
        # All ok
388
        # All ok
337
        $t->get_ok(
389
        $t->get_ok(
338
            "//$unauth_userid:$unauth_password@/api/v1/public/checkouts/availability?item_id=$item1_id&patron_id=$patron_id"
390
            "//$unauth_userid:$unauth_password@/api/v1/public/checkouts/availability?item_id=$item1_id&patron_id=$patron_id"
339
        )->status_is(200)->json_is( '/blockers' => {} )->json_is( '/confirms' => {} )->json_is( '/warnings' => {} )
391
            )
392
            ->status_is(200)
393
            ->json_is( '/blockers' => {} )
394
            ->json_is( '/confirms' => {} )
395
            ->json_is( '/warnings' => {} )
340
            ->json_has('/confirmation_token');
396
            ->json_has('/confirmation_token');
341
397
342
        # Needs confirmation upgrade to blocker
398
        # Needs confirmation upgrade to blocker
343
        %needsconfirmation = ( TOO_MANY => 1, ISSUED_TO_ANOTHER => 1 );
399
        %needsconfirmation = ( TOO_MANY => 1, ISSUED_TO_ANOTHER => 1 );
344
        $t->get_ok(
400
        $t->get_ok(
345
            "//$unauth_userid:$unauth_password@/api/v1/public/checkouts/availability?item_id=$item1_id&patron_id=$patron_id"
401
            "//$unauth_userid:$unauth_password@/api/v1/public/checkouts/availability?item_id=$item1_id&patron_id=$patron_id"
346
        )->status_is(200)->json_is( '/blockers' => { TOO_MANY => 1, ISSUED_TO_ANOTHER => 1 } )
402
            )
347
            ->json_is( '/confirms' => {} )->json_is( '/warnings' => {} )->json_has('/confirmation_token');
403
            ->status_is(200)
404
            ->json_is( '/blockers' => { TOO_MANY => 1, ISSUED_TO_ANOTHER => 1 } )
405
            ->json_is( '/confirms' => {} )
406
            ->json_is( '/warnings' => {} )
407
            ->json_has('/confirmation_token');
348
        %needsconfirmation = ();
408
        %needsconfirmation = ();
349
409
350
        # Remove personal information from public endpoint
410
        # Remove personal information from public endpoint
Lines 393-399 subtest 'get_availability' => sub { Link Here
393
        );
453
        );
394
        $t->get_ok(
454
        $t->get_ok(
395
            "//$unauth_userid:$unauth_password@/api/v1/public/checkouts/availability?item_id=$item1_id&patron_id=$patron_id"
455
            "//$unauth_userid:$unauth_password@/api/v1/public/checkouts/availability?item_id=$item1_id&patron_id=$patron_id"
396
        )->status_is(200)->json_is( '/blockers' => {} )->json_is( '/confirms' => {} )->json_is( '/warnings' => {} )
456
            )
457
            ->status_is(200)
458
            ->json_is( '/blockers' => {} )
459
            ->json_is( '/confirms' => {} )
460
            ->json_is( '/warnings' => {} )
397
            ->json_has('/confirmation_token');
461
            ->json_has('/confirmation_token');
398
        %issuingimpossible = ();
462
        %issuingimpossible = ();
399
        %alerts            = ();
463
        %alerts            = ();
Lines 504-513 subtest 'add checkout' => sub { Link Here
504
568
505
        $t->post_ok(
569
        $t->post_ok(
506
            "/api/v1/public/patrons/$patron_id/checkouts" => json => { item_id => $item1_id, patron_id => $patron_id } )
570
            "/api/v1/public/patrons/$patron_id/checkouts" => json => { item_id => $item1_id, patron_id => $patron_id } )
507
            ->status_is(401)->json_is( { error => "Authentication failure." } );
571
            ->status_is(401)
572
            ->json_is( { error => "Authentication failure." } );
508
573
509
        $t->post_ok( "//$useridp:$password@/api/v1/public/patrons/$patron_id/checkouts" => json =>
574
        $t->post_ok( "//$useridp:$password@/api/v1/public/patrons/$patron_id/checkouts" => json =>
510
                { item_id => $item1_id, patron_id => $patron_id } )->status_is(405)
575
                { item_id => $item1_id, patron_id => $patron_id } )
576
            ->status_is(405)
511
            ->json_is( { error => "Feature disabled", error_code => "FEATURE_DISABLED" } );
577
            ->json_is( { error => "Feature disabled", error_code => "FEATURE_DISABLED" } );
512
578
513
        # Feature enabled
579
        # Feature enabled
Lines 515-524 subtest 'add checkout' => sub { Link Here
515
581
516
        $t->post_ok(
582
        $t->post_ok(
517
            "/api/v1/public/patrons/$patron_id/checkouts" => json => { item_id => $item1_id, patron_id => $patron_id } )
583
            "/api/v1/public/patrons/$patron_id/checkouts" => json => { item_id => $item1_id, patron_id => $patron_id } )
518
            ->status_is(401)->json_is( { error => "Authentication failure." } );
584
            ->status_is(401)
585
            ->json_is( { error => "Authentication failure." } );
519
586
520
        $t->post_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/checkouts" => json =>
587
        $t->post_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/checkouts" => json =>
521
                { item_id => $item1_id, patron_id => $patron_id } )->status_is(403)
588
                { item_id => $item1_id, patron_id => $patron_id } )
589
            ->status_is(403)
522
            ->json_is( { error => "Unprivileged user cannot access another user's resources" } );
590
            ->json_is( { error => "Unprivileged user cannot access another user's resources" } );
523
591
524
        $t->post_ok( "//$useridp:$password@/api/v1/public/patrons/$patron_id/checkouts" => json =>
592
        $t->post_ok( "//$useridp:$password@/api/v1/public/patrons/$patron_id/checkouts" => json =>
(-)a/t/db_dependent/api/v1/circulation_rules.t (-11 / +22 lines)
Lines 94-100 subtest 'list_rules() tests' => sub { Link Here
94
    );
94
    );
95
95
96
    note("One default rule defined");
96
    note("One default rule defined");
97
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules")->status_is(200)
97
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules")
98
        ->status_is(200)
98
        ->json_is( '/0/fine'     => 2,     "Default fine rule is returned as expected" )
99
        ->json_is( '/0/fine'     => 2,     "Default fine rule is returned as expected" )
99
        ->json_is( '/0/finedays' => undef, "Rule finedays is undefined as expected" );
100
        ->json_is( '/0/finedays' => undef, "Rule finedays is undefined as expected" );
100
101
Lines 113-119 subtest 'list_rules() tests' => sub { Link Here
113
    );
114
    );
114
115
115
    note("Two default rules defined");
116
    note("Two default rules defined");
116
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules")->status_is(200)
117
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules")
118
        ->status_is(200)
117
        ->json_is( '/0/fine'     => 2, "Default fine rule is returned as expected" )
119
        ->json_is( '/0/fine'     => 2, "Default fine rule is returned as expected" )
118
        ->json_is( '/0/finedays' => 5, "Default finedays rule is returned as expected" );
120
        ->json_is( '/0/finedays' => 5, "Default finedays rule is returned as expected" );
119
121
Lines 132-145 subtest 'list_rules() tests' => sub { Link Here
132
    );
134
    );
133
135
134
    note("Two default rules and one branch rule defined");
136
    note("Two default rules and one branch rule defined");
135
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules?library_id=$branchcode")->status_is(200)
137
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules?library_id=$branchcode")
138
        ->status_is(200)
136
        ->json_is( '/0/fine' => 4, "Branch specific fine rule is returned when library is added to request query" )
139
        ->json_is( '/0/fine' => 4, "Branch specific fine rule is returned when library is added to request query" )
137
        ->json_is(
140
        ->json_is(
138
        '/0/finedays' => 5,
141
        '/0/finedays' => 5,
139
        "Default finedays rule is returned when library is added to request query but no branch specific rule is defined"
142
        "Default finedays rule is returned when library is added to request query but no branch specific rule is defined"
140
        );
143
        );
141
144
142
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules")->status_is(200)
145
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules")
146
        ->status_is(200)
143
        ->json_is( '/0/fine'     => 2, "Default fine rule returned when no library is added to request query" )
147
        ->json_is( '/0/fine'     => 2, "Default fine rule returned when no library is added to request query" )
144
        ->json_is( '/0/finedays' => 5, "Default finedays rule returned when no library is added to request query" );
148
        ->json_is( '/0/finedays' => 5, "Default finedays rule returned when no library is added to request query" );
145
149
Lines 152-158 subtest 'list_rules() tests' => sub { Link Here
152
    );
156
    );
153
157
154
    # Warn on unsupported query parameter
158
    # Warn on unsupported query parameter
155
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules?rules_blah=blah")->status_is(400)
159
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules?rules_blah=blah")
160
        ->status_is(400)
156
        ->json_is( [ { path => '/query/rules_blah', message => 'Malformed query string' } ] );
161
        ->json_is( [ { path => '/query/rules_blah', message => 'Malformed query string' } ] );
157
162
158
    # Make sure we have a non-existent library
163
    # Make sure we have a non-existent library
Lines 161-167 subtest 'list_rules() tests' => sub { Link Here
161
    $library_to_delete->delete;
166
    $library_to_delete->delete;
162
167
163
    # Warn on incorrect query parameter value
168
    # Warn on incorrect query parameter value
164
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules?library_id=$non_existent_library")->status_is(400)
169
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules?library_id=$non_existent_library")
170
        ->status_is(400)
165
        ->json_is(
171
        ->json_is(
166
        '' => {
172
        '' => {
167
            error      => 'Invalid parameter value',
173
            error      => 'Invalid parameter value',
Lines 182-188 subtest 'list_rules() tests' => sub { Link Here
182
188
183
    # Warn on incorrect query parameter value
189
    # Warn on incorrect query parameter value
184
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules?patron_category_id=$non_existent_category")
190
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules?patron_category_id=$non_existent_category")
185
        ->status_is(400)->json_is(
191
        ->status_is(400)
192
        ->json_is(
186
        '' => {
193
        '' => {
187
            error      => 'Invalid parameter value',
194
            error      => 'Invalid parameter value',
188
            error_code => 'invalid_parameter_value',
195
            error_code => 'invalid_parameter_value',
Lines 201-207 subtest 'list_rules() tests' => sub { Link Here
201
    $itemtype_to_delete->delete;
208
    $itemtype_to_delete->delete;
202
209
203
    # Warn on incorrect query parameter value
210
    # Warn on incorrect query parameter value
204
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules?item_type_id=$non_existent_itemtype")->status_is(400)
211
    $t->get_ok("//$userid:$password@/api/v1/circulation_rules?item_type_id=$non_existent_itemtype")
212
        ->status_is(400)
205
        ->json_is(
213
        ->json_is(
206
        '' => {
214
        '' => {
207
            error      => 'Invalid parameter value',
215
            error      => 'Invalid parameter value',
Lines 343-363 subtest 'set_rules() tests' => sub { Link Here
343
    # Invalid item_type_id
351
    # Invalid item_type_id
344
    note("Invalid item_type_id");
352
    note("Invalid item_type_id");
345
    $rules_to_set->{context}->{item_type_id} = 'invalid_itemtype';
353
    $rules_to_set->{context}->{item_type_id} = 'invalid_itemtype';
346
    $t->put_ok( "//$userid:$password@/api/v1/circulation_rules" => json => $rules_to_set )->status_is(400)
354
    $t->put_ok( "//$userid:$password@/api/v1/circulation_rules" => json => $rules_to_set )
355
        ->status_is(400)
347
        ->json_is( '/error_code' => 'invalid_parameter_value', "Handled invalid item_type_id" );
356
        ->json_is( '/error_code' => 'invalid_parameter_value', "Handled invalid item_type_id" );
348
357
349
    # Invalid library_id
358
    # Invalid library_id
350
    note("Invalid library_id");
359
    note("Invalid library_id");
351
    $rules_to_set->{context}->{item_type_id} = $itemtype;
360
    $rules_to_set->{context}->{item_type_id} = $itemtype;
352
    $rules_to_set->{context}->{library_id}   = 'invalid_library';
361
    $rules_to_set->{context}->{library_id}   = 'invalid_library';
353
    $t->put_ok( "//$userid:$password@/api/v1/circulation_rules" => json => $rules_to_set )->status_is(400)
362
    $t->put_ok( "//$userid:$password@/api/v1/circulation_rules" => json => $rules_to_set )
363
        ->status_is(400)
354
        ->json_is( '/error_code' => 'invalid_parameter_value', "Handled invalid library_id" );
364
        ->json_is( '/error_code' => 'invalid_parameter_value', "Handled invalid library_id" );
355
365
356
    # Invalid patron_category_id
366
    # Invalid patron_category_id
357
    note("Invalid patron_category_id");
367
    note("Invalid patron_category_id");
358
    $rules_to_set->{context}->{library_id}         = $branchcode;
368
    $rules_to_set->{context}->{library_id}         = $branchcode;
359
    $rules_to_set->{context}->{patron_category_id} = 'invalid_category';
369
    $rules_to_set->{context}->{patron_category_id} = 'invalid_category';
360
    $t->put_ok( "//$userid:$password@/api/v1/circulation_rules" => json => $rules_to_set )->status_is(400)
370
    $t->put_ok( "//$userid:$password@/api/v1/circulation_rules" => json => $rules_to_set )
371
        ->status_is(400)
361
        ->json_is( '/error_code' => 'invalid_parameter_value', "Handled invalid patron_category_id" );
372
        ->json_is( '/error_code' => 'invalid_parameter_value', "Handled invalid patron_category_id" );
362
373
363
    # Unauthorized user tests
374
    # Unauthorized user tests
(-)a/t/db_dependent/api/v1/cities.t (-10 / +21 lines)
Lines 91-101 subtest 'list() tests' => sub { Link Here
91
        ]
91
        ]
92
    );
92
    );
93
93
94
    $t->get_ok( "//$userid:$password@/api/v1/cities?name=" . $city->city_name )->status_is(200)
94
    $t->get_ok( "//$userid:$password@/api/v1/cities?name=" . $city->city_name )
95
        ->status_is(200)
95
        ->json_is( [ $city->to_api ] );
96
        ->json_is( [ $city->to_api ] );
96
97
97
    # Warn on unsupported query parameter
98
    # Warn on unsupported query parameter
98
    $t->get_ok("//$userid:$password@/api/v1/cities?city_blah=blah")->status_is(400)
99
    $t->get_ok("//$userid:$password@/api/v1/cities?city_blah=blah")
100
        ->status_is(400)
99
        ->json_is( [ { path => '/query/city_blah', message => 'Malformed query string' } ] );
101
        ->json_is( [ { path => '/query/city_blah', message => 'Malformed query string' } ] );
100
102
101
    # Unauthorized access
103
    # Unauthorized access
Lines 139-145 subtest 'get() tests' => sub { Link Here
139
    my $non_existent_id = $city_to_delete->id;
141
    my $non_existent_id = $city_to_delete->id;
140
    $city_to_delete->delete;
142
    $city_to_delete->delete;
141
143
142
    $t->get_ok("//$userid:$password@/api/v1/cities/$non_existent_id")->status_is(404)
144
    $t->get_ok("//$userid:$password@/api/v1/cities/$non_existent_id")
145
        ->status_is(404)
143
        ->json_is( '/error' => 'City not found' );
146
        ->json_is( '/error' => 'City not found' );
144
147
145
    $schema->storage->txn_rollback;
148
    $schema->storage->txn_rollback;
Lines 200-211 subtest 'add() tests' => sub { Link Here
200
203
201
    # Authorized attempt to write
204
    # Authorized attempt to write
202
    my $city_id =
205
    my $city_id =
203
        $t->post_ok( "//$userid:$password@/api/v1/cities" => json => $city )->status_is( 201, 'REST3.2.1' )
206
        $t->post_ok( "//$userid:$password@/api/v1/cities" => json => $city )
207
        ->status_is( 201, 'REST3.2.1' )
204
        ->header_like(
208
        ->header_like(
205
        Location => qr|^\/api\/v1\/cities/\d*|,
209
        Location => qr|^\/api\/v1\/cities/\d*|,
206
        'REST3.4.1'
210
        'REST3.4.1'
207
    )->json_is( '/name' => $city->{name} )->json_is( '/state' => $city->{state} )
211
        )
208
        ->json_is( '/postal_code' => $city->{postal_code} )->json_is( '/country' => $city->{country} )
212
        ->json_is( '/name'        => $city->{name} )
213
        ->json_is( '/state'       => $city->{state} )
214
        ->json_is( '/postal_code' => $city->{postal_code} )
215
        ->json_is( '/country'     => $city->{country} )
209
        ->tx->res->json->{city_id};
216
        ->tx->res->json->{city_id};
210
217
211
    # Authorized attempt to create with null id
218
    # Authorized attempt to create with null id
Lines 266-272 subtest 'update() tests' => sub { Link Here
266
        country => 'New country'
273
        country => 'New country'
267
    };
274
    };
268
275
269
    $t->put_ok( "//$userid:$password@/api/v1/cities/$city_id" => json => $city_with_missing_field )->status_is(400)
276
    $t->put_ok( "//$userid:$password@/api/v1/cities/$city_id" => json => $city_with_missing_field )
277
        ->status_is(400)
270
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/postal_code" } ] );
278
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/postal_code" } ] );
271
279
272
    # Full object update on PUT
280
    # Full object update on PUT
Lines 277-283 subtest 'update() tests' => sub { Link Here
277
        country     => "City Country"
285
        country     => "City Country"
278
    };
286
    };
279
287
280
    $t->put_ok( "//$userid:$password@/api/v1/cities/$city_id" => json => $city_with_updated_field )->status_is(200)
288
    $t->put_ok( "//$userid:$password@/api/v1/cities/$city_id" => json => $city_with_updated_field )
289
        ->status_is(200)
281
        ->json_is( '/name' => 'London' );
290
        ->json_is( '/name' => 'London' );
282
291
283
    # Authorized attempt to write invalid data
292
    # Authorized attempt to write invalid data
Lines 288-294 subtest 'update() tests' => sub { Link Here
288
        country     => "City Country"
297
        country     => "City Country"
289
    };
298
    };
290
299
291
    $t->put_ok( "//$userid:$password@/api/v1/cities/$city_id" => json => $city_with_invalid_field )->status_is(400)
300
    $t->put_ok( "//$userid:$password@/api/v1/cities/$city_id" => json => $city_with_invalid_field )
301
        ->status_is(400)
292
        ->json_is(
302
        ->json_is(
293
        "/errors" => [
303
        "/errors" => [
294
            {
304
            {
Lines 344-350 subtest 'delete() tests' => sub { Link Here
344
    # Unauthorized attempt to delete
354
    # Unauthorized attempt to delete
345
    $t->delete_ok("//$unauth_userid:$password@/api/v1/cities/$city_id")->status_is(403);
355
    $t->delete_ok("//$unauth_userid:$password@/api/v1/cities/$city_id")->status_is(403);
346
356
347
    $t->delete_ok("//$userid:$password@/api/v1/cities/$city_id")->status_is( 204, 'REST3.2.4' )
357
    $t->delete_ok("//$userid:$password@/api/v1/cities/$city_id")
358
        ->status_is( 204, 'REST3.2.4' )
348
        ->content_is( '', 'REST3.3.4' );
359
        ->content_is( '', 'REST3.3.4' );
349
360
350
    $t->delete_ok("//$userid:$password@/api/v1/cities/$city_id")->status_is(404);
361
    $t->delete_ok("//$userid:$password@/api/v1/cities/$city_id")->status_is(404);
(-)a/t/db_dependent/api/v1/clubs_holds.t (-10 / +20 lines)
Lines 134-140 subtest 'add() tests' => sub { Link Here
134
134
135
        $t->post_ok( "//$userid:$password@/api/v1/clubs/"
135
        $t->post_ok( "//$userid:$password@/api/v1/clubs/"
136
                . $club_with_enrollments->id
136
                . $club_with_enrollments->id
137
                . "/holds" => json => { pickup_library_id => $non_existent_item_homebranch } )->status_is(400)
137
                . "/holds" => json => { pickup_library_id => $non_existent_item_homebranch } )
138
            ->status_is(400)
138
            ->json_is( '/error' => 'At least one of biblio_id, item_id should be given' );
139
            ->json_is( '/error' => 'At least one of biblio_id, item_id should be given' );
139
140
140
        $t->post_ok(
141
        $t->post_ok(
Lines 170-181 subtest 'add() tests' => sub { Link Here
170
171
171
            $t->post_ok(
172
            $t->post_ok(
172
                "//$userid:$password@/api/v1/clubs/" . $club_without_enrollments->id . "/holds" => json => $data )
173
                "//$userid:$password@/api/v1/clubs/" . $club_without_enrollments->id . "/holds" => json => $data )
173
                ->status_is(409)->json_is( '/error' => "Cannot place a hold on a club without patrons." );
174
                ->status_is(409)
175
                ->json_is( '/error' => "Cannot place a hold on a club without patrons." );
174
176
175
            # place a club hold with top level reserveforothers permission - should succeed
177
            # place a club hold with top level reserveforothers permission - should succeed
176
            $t->post_ok( "//$userid:$password@/api/v1/clubs/" . $club_with_enrollments->id . "/holds" => json => $data )
178
            $t->post_ok( "//$userid:$password@/api/v1/clubs/" . $club_with_enrollments->id . "/holds" => json => $data )
177
                ->status_is( 201, 'Created Hold' )->json_has( '/club_hold_id', 'got a club hold id' )
179
                ->status_is( 201, 'Created Hold' )
178
                ->json_is( '/club_id' => $club_with_enrollments->id )->json_is( '/biblio_id' => $item->biblionumber )
180
                ->json_has( '/club_hold_id', 'got a club hold id' )
181
                ->json_is( '/club_id'   => $club_with_enrollments->id )
182
                ->json_is( '/biblio_id' => $item->biblionumber )
179
                ->header_is(
183
                ->header_is(
180
                      'Location' => '/api/v1/clubs/'
184
                      'Location' => '/api/v1/clubs/'
181
                    . $club_with_enrollments->id
185
                    . $club_with_enrollments->id
Lines 189-195 subtest 'add() tests' => sub { Link Here
189
                "//$userid_2:$password_2@/api/v1/clubs/" . $club_with_enrollments->id . "/holds" => json => $data )
193
                "//$userid_2:$password_2@/api/v1/clubs/" . $club_with_enrollments->id . "/holds" => json => $data )
190
                ->status_is( 201, 'Created Hold with specific place_holds permission' )
194
                ->status_is( 201, 'Created Hold with specific place_holds permission' )
191
                ->json_has( '/club_hold_id', 'got a club hold id' )
195
                ->json_has( '/club_hold_id', 'got a club hold id' )
192
                ->json_is( '/club_id' => $club_with_enrollments->id )->json_is( '/biblio_id' => $item->biblionumber );
196
                ->json_is( '/club_id'   => $club_with_enrollments->id )
197
                ->json_is( '/biblio_id' => $item->biblionumber );
193
198
194
            # place a club hold with no reserveforothers or specific permsision - should fail
199
            # place a club hold with no reserveforothers or specific permsision - should fail
195
            $t->post_ok(
200
            $t->post_ok(
Lines 233-244 subtest 'add() tests' => sub { Link Here
233
238
234
            $t->post_ok(
239
            $t->post_ok(
235
                "//$userid:$password@/api/v1/clubs/" . $club_without_enrollments->id . "/holds" => json => $data )
240
                "//$userid:$password@/api/v1/clubs/" . $club_without_enrollments->id . "/holds" => json => $data )
236
                ->status_is(409)->json_is( '/error' => "Cannot place a hold on a club without patrons." );
241
                ->status_is(409)
242
                ->json_is( '/error' => "Cannot place a hold on a club without patrons." );
237
243
238
            # place a club hold with top level reserveforothers permission - should succeed
244
            # place a club hold with top level reserveforothers permission - should succeed
239
            $t->post_ok( "//$userid:$password@/api/v1/clubs/" . $club_with_enrollments->id . "/holds" => json => $data )
245
            $t->post_ok( "//$userid:$password@/api/v1/clubs/" . $club_with_enrollments->id . "/holds" => json => $data )
240
                ->status_is( 201, 'Created Hold' )->json_has( '/club_hold_id', 'got a club hold id' )
246
                ->status_is( 201, 'Created Hold' )
241
                ->json_is( '/club_id' => $club_with_enrollments->id )->json_is( '/biblio_id' => $item->biblionumber )
247
                ->json_has( '/club_hold_id', 'got a club hold id' )
248
                ->json_is( '/club_id'   => $club_with_enrollments->id )
249
                ->json_is( '/biblio_id' => $item->biblionumber )
242
                ->header_is(
250
                ->header_is(
243
                      'Location' => '/api/v1/clubs/'
251
                      'Location' => '/api/v1/clubs/'
244
                    . $club_with_enrollments->id
252
                    . $club_with_enrollments->id
Lines 252-258 subtest 'add() tests' => sub { Link Here
252
                "//$userid_2:$password_2@/api/v1/clubs/" . $club_with_enrollments->id . "/holds" => json => $data )
260
                "//$userid_2:$password_2@/api/v1/clubs/" . $club_with_enrollments->id . "/holds" => json => $data )
253
                ->status_is( 201, 'Created Hold with specific place_holds permission' )
261
                ->status_is( 201, 'Created Hold with specific place_holds permission' )
254
                ->json_has( '/club_hold_id', 'got a club hold id' )
262
                ->json_has( '/club_hold_id', 'got a club hold id' )
255
                ->json_is( '/club_id' => $club_with_enrollments->id )->json_is( '/biblio_id' => $item->biblionumber );
263
                ->json_is( '/club_id'   => $club_with_enrollments->id )
264
                ->json_is( '/biblio_id' => $item->biblionumber );
256
265
257
            # place a club hold with no reserveforothers or specific permsision - should fail
266
            # place a club hold with no reserveforothers or specific permsision - should fail
258
            $t->post_ok(
267
            $t->post_ok(
Lines 348-354 sub unauthorized_access_tests { Link Here
348
        $unauthorized_patron->set_password( { password => $password, skip_validation => 1 } );
357
        $unauthorized_patron->set_password( { password => $password, skip_validation => 1 } );
349
        my $unauth_userid = $unauthorized_patron->userid;
358
        my $unauth_userid = $unauthorized_patron->userid;
350
359
351
        $t->$verb_ok( "//$unauth_userid:$password\@$endpoint" => json => $json )->status_is(403)
360
        $t->$verb_ok( "//$unauth_userid:$password\@$endpoint" => json => $json )
361
            ->status_is(403)
352
            ->json_has('/required_permissions');
362
            ->json_has('/required_permissions');
353
    };
363
    };
354
}
364
}
(-)a/t/db_dependent/api/v1/deleted_biblios.t (-5 / +11 lines)
Lines 86-92 subtest 'get() tests' => sub { Link Here
86
86
87
    $t->get_ok(
87
    $t->get_ok(
88
        "//$userid:$password@/api/v1/deleted/biblios/" . $biblio->biblionumber => { Accept => 'application/json' } )
88
        "//$userid:$password@/api/v1/deleted/biblios/" . $biblio->biblionumber => { Accept => 'application/json' } )
89
        ->status_is(200)->json_is( '/title', 'The unbearable lightness of being' )
89
        ->status_is(200)
90
        ->json_is( '/title',  'The unbearable lightness of being' )
90
        ->json_is( '/author', 'Milan Kundera' );
91
        ->json_is( '/author', 'Milan Kundera' );
91
92
92
    $t->get_ok( "//$userid:$password@/api/v1/deleted/biblios/"
93
    $t->get_ok( "//$userid:$password@/api/v1/deleted/biblios/"
Lines 100-110 subtest 'get() tests' => sub { Link Here
100
        ->status_is(200);
101
        ->status_is(200);
101
102
102
    $t->get_ok( "//$userid:$password@/api/v1/deleted/biblios/" . $biblio->biblionumber => { Accept => 'text/plain' } )
103
    $t->get_ok( "//$userid:$password@/api/v1/deleted/biblios/" . $biblio->biblionumber => { Accept => 'text/plain' } )
103
        ->status_is(200)->content_is($formatted);
104
        ->status_is(200)
105
        ->content_is($formatted);
104
106
105
    my $biblio_exist = $builder->build_sample_biblio();
107
    my $biblio_exist = $builder->build_sample_biblio();
106
    $t->get_ok( "//$userid:$password@/api/v1/deleted/biblios/"
108
    $t->get_ok( "//$userid:$password@/api/v1/deleted/biblios/"
107
            . $biblio_exist->biblionumber => { Accept => 'application/marc' } )->status_is(404)
109
            . $biblio_exist->biblionumber => { Accept => 'application/marc' } )
110
        ->status_is(404)
108
        ->json_is( '/error', 'Bibliographic record not found' );
111
        ->json_is( '/error', 'Bibliographic record not found' );
109
112
110
    subtest 'marc-in-json encoding tests' => sub {
113
    subtest 'marc-in-json encoding tests' => sub {
Lines 217-223 subtest 'list() tests' => sub { Link Here
217
220
218
    my $result =
221
    my $result =
219
        $t->get_ok( "//$userid:$password@/api/v1/deleted/biblios?q=$query" => { Accept => 'application/marcxml+xml' } )
222
        $t->get_ok( "//$userid:$password@/api/v1/deleted/biblios?q=$query" => { Accept => 'application/marcxml+xml' } )
220
        ->status_is(200)->tx->res->body;
223
        ->status_is(200)
224
        ->tx->res->body;
221
225
222
    my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
226
    my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
223
    like( $result, qr/\Q$encoded_title/, "The title is not double encoded" );
227
    like( $result, qr/\Q$encoded_title/, "The title is not double encoded" );
Lines 249-255 subtest 'list() tests' => sub { Link Here
249
    );
253
    );
250
254
251
    $t->get_ok( "//$userid:$password@/api/v1/deleted/biblios?q=$query" => { Accept => 'application/json' } )
255
    $t->get_ok( "//$userid:$password@/api/v1/deleted/biblios?q=$query" => { Accept => 'application/json' } )
252
        ->status_is(200)->json_is( '/0/biblio_id' => $old_biblio_1->id )->json_is( '/1/biblio_id' => undef );
256
        ->status_is(200)
257
        ->json_is( '/0/biblio_id' => $old_biblio_1->id )
258
        ->json_is( '/1/biblio_id' => undef );
253
259
254
    # DELETE any biblio with ISBN = TOMAS
260
    # DELETE any biblio with ISBN = TOMAS
255
    Koha::Biblios->search( { 'biblioitem.isbn' => 'TOMAS' }, { join => ['biblioitem'] } )->delete;
261
    Koha::Biblios->search( { 'biblioitem.isbn' => 'TOMAS' }, { join => ['biblioitem'] } )->delete;
(-)a/t/db_dependent/api/v1/edifact_files.t (-2 / +4 lines)
Lines 102-113 subtest 'list() tests' => sub { Link Here
102
    );
102
    );
103
103
104
    $api_filter = encode_json( { 'me.filename' => $file->filename } );
104
    $api_filter = encode_json( { 'me.filename' => $file->filename } );
105
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/edifiles?q=$api_filter")->status_is(200)
105
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/edifiles?q=$api_filter")
106
        ->status_is(200)
106
        ->json_is( [ $file->to_api ] );
107
        ->json_is( [ $file->to_api ] );
107
108
108
    # Warn on unsupported query parameter
109
    # Warn on unsupported query parameter
109
    $api_filter = encode_json( { 'me.file_blah' => 'blah' } );
110
    $api_filter = encode_json( { 'me.file_blah' => 'blah' } );
110
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/edifiles?file_blah=blah")->status_is(400)
111
    $t->get_ok("//$userid:$password@/api/v1/acquisitions/edifiles?file_blah=blah")
112
        ->status_is(400)
111
        ->json_is( [ { path => '/query/file_blah', message => 'Malformed query string' } ] );
113
        ->json_is( [ { path => '/query/file_blah', message => 'Malformed query string' } ] );
112
114
113
    # Unauthorized access
115
    # Unauthorized access
(-)a/t/db_dependent/api/v1/erm_agreements.t (-18 / +37 lines)
Lines 101-114 subtest 'list() tests' => sub { Link Here
101
    );
101
    );
102
102
103
    # Filtering works, two agreements sharing vendor_id
103
    # Filtering works, two agreements sharing vendor_id
104
    $t->get_ok( "//$userid:$password@/api/v1/erm/agreements?vendor_id=" . $vendor_1->id )->status_is(200)
104
    $t->get_ok( "//$userid:$password@/api/v1/erm/agreements?vendor_id=" . $vendor_1->id )
105
        ->status_is(200)
105
        ->json_is( [ $agreement->to_api, $another_agreement->to_api ] );
106
        ->json_is( [ $agreement->to_api, $another_agreement->to_api ] );
106
107
107
    # Attempt to search by name like 'ko'
108
    # Attempt to search by name like 'ko'
108
    $agreement->delete;
109
    $agreement->delete;
109
    $another_agreement->delete;
110
    $another_agreement->delete;
110
    $agreement_with_another_vendor_id->delete;
111
    $agreement_with_another_vendor_id->delete;
111
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/agreements?q=[{"me.name":{"like":"%ko%"}}]~)->status_is(200)
112
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/agreements?q=[{"me.name":{"like":"%ko%"}}]~)
113
        ->status_is(200)
112
        ->json_is( [] );
114
        ->json_is( [] );
113
115
114
    my $agreement_to_search = $builder->build_object(
116
    my $agreement_to_search = $builder->build_object(
Lines 121-127 subtest 'list() tests' => sub { Link Here
121
    );
123
    );
122
124
123
    # Search works, searching for name like 'ko'
125
    # Search works, searching for name like 'ko'
124
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/agreements?q=[{"me.name":{"like":"%ko%"}}]~)->status_is(200)
126
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/agreements?q=[{"me.name":{"like":"%ko%"}}]~)
127
        ->status_is(200)
125
        ->json_is( [ $agreement_to_search->to_api ] );
128
        ->json_is( [ $agreement_to_search->to_api ] );
126
129
127
    # Warn on incorrect filter date format
130
    # Warn on incorrect filter date format
Lines 135-141 subtest 'list() tests' => sub { Link Here
135
    );
138
    );
136
139
137
    # Attempt to filter by expired on 2021-03-19
140
    # Attempt to filter by expired on 2021-03-19
138
    $t->get_ok("//$userid:$password@/api/v1/erm/agreements?max_expiration_date=2021-03-19")->status_is(200)
141
    $t->get_ok("//$userid:$password@/api/v1/erm/agreements?max_expiration_date=2021-03-19")
142
        ->status_is(200)
139
        ->json_is( [] );
143
        ->json_is( [] );
140
144
141
    my $agreement_to_filter = $builder->build_object( { class => 'Koha::ERM::Agreements' } );
145
    my $agreement_to_filter = $builder->build_object( { class => 'Koha::ERM::Agreements' } );
Lines 149-159 subtest 'list() tests' => sub { Link Here
149
    );
153
    );
150
154
151
    # Filter by expired on 2021-03-19
155
    # Filter by expired on 2021-03-19
152
    $t->get_ok("//$userid:$password@/api/v1/erm/agreements?max_expiration_date=2021-03-19")->status_is(200)
156
    $t->get_ok("//$userid:$password@/api/v1/erm/agreements?max_expiration_date=2021-03-19")
157
        ->status_is(200)
153
        ->json_is( [ $agreement_to_filter->to_api ] );
158
        ->json_is( [ $agreement_to_filter->to_api ] );
154
159
155
    # Warn on unsupported query parameter
160
    # Warn on unsupported query parameter
156
    $t->get_ok("//$userid:$password@/api/v1/erm/agreements?blah=blah")->status_is(400)
161
    $t->get_ok("//$userid:$password@/api/v1/erm/agreements?blah=blah")
162
        ->status_is(400)
157
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
163
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
158
164
159
    # Unauthorized access
165
    # Unauthorized access
Lines 190-196 subtest 'get() tests' => sub { Link Here
190
    my $unauth_userid = $patron->userid;
196
    my $unauth_userid = $patron->userid;
191
197
192
    # This agreement exists, should get returned
198
    # This agreement exists, should get returned
193
    $t->get_ok( "//$userid:$password@/api/v1/erm/agreements/" . $agreement->agreement_id )->status_is(200)
199
    $t->get_ok( "//$userid:$password@/api/v1/erm/agreements/" . $agreement->agreement_id )
200
        ->status_is(200)
194
        ->json_is( $agreement->to_api );
201
        ->json_is( $agreement->to_api );
195
202
196
    # Return one agreement with some embeds
203
    # Return one agreement with some embeds
Lines 214-220 subtest 'get() tests' => sub { Link Here
214
    my $non_existent_id     = $agreement_to_delete->agreement_id;
221
    my $non_existent_id     = $agreement_to_delete->agreement_id;
215
    $agreement_to_delete->delete;
222
    $agreement_to_delete->delete;
216
223
217
    $t->get_ok("//$userid:$password@/api/v1/erm/agreements/$non_existent_id")->status_is(404)
224
    $t->get_ok("//$userid:$password@/api/v1/erm/agreements/$non_existent_id")
225
        ->status_is(404)
218
        ->json_is( '/error' => 'Agreement not found' );
226
        ->json_is( '/error' => 'Agreement not found' );
219
227
220
    $schema->storage->txn_rollback;
228
    $schema->storage->txn_rollback;
Lines 273-279 subtest 'add() tests' => sub { Link Here
273
    };
281
    };
274
282
275
    $t->post_ok( "//$userid:$password@/api/v1/erm/agreements" => json => $agreement_with_invalid_field )
283
    $t->post_ok( "//$userid:$password@/api/v1/erm/agreements" => json => $agreement_with_invalid_field )
276
        ->status_is(400)->json_is(
284
        ->status_is(400)
285
        ->json_is(
277
        "/errors" => [
286
        "/errors" => [
278
            {
287
            {
279
                message => "Properties not allowed: blah.",
288
                message => "Properties not allowed: blah.",
Lines 285-303 subtest 'add() tests' => sub { Link Here
285
    # Authorized attempt to write
294
    # Authorized attempt to write
286
    my $agreement_id =
295
    my $agreement_id =
287
        $t->post_ok( "//$userid:$password@/api/v1/erm/agreements" => json => $agreement )
296
        $t->post_ok( "//$userid:$password@/api/v1/erm/agreements" => json => $agreement )
288
        ->status_is( 201, 'REST3.2.1' )->header_like(
297
        ->status_is( 201, 'REST3.2.1' )
298
        ->header_like(
289
        Location => qr|^/api/v1/erm/agreements/\d*|,
299
        Location => qr|^/api/v1/erm/agreements/\d*|,
290
        'REST3.4.1'
300
        'REST3.4.1'
291
    )->json_is( '/vendor_id' => $agreement->{vendor_id} )->json_is( '/name' => $agreement->{name} )
301
        )
292
        ->json_is( '/description'      => $agreement->{description} )->json_is( '/status' => $agreement->{status} )
302
        ->json_is( '/vendor_id'        => $agreement->{vendor_id} )
303
        ->json_is( '/name'             => $agreement->{name} )
304
        ->json_is( '/description'      => $agreement->{description} )
305
        ->json_is( '/status'           => $agreement->{status} )
293
        ->json_is( '/closure_reason'   => $agreement->{closure_reason} )
306
        ->json_is( '/closure_reason'   => $agreement->{closure_reason} )
294
        ->json_is( '/is_perpetual'     => $agreement->{is_perpetual} )
307
        ->json_is( '/is_perpetual'     => $agreement->{is_perpetual} )
295
        ->json_is( '/renewal_priority' => $agreement->{renewal_priority} )
308
        ->json_is( '/renewal_priority' => $agreement->{renewal_priority} )
296
        ->json_is( '/license_info'     => $agreement->{license_info} )->tx->res->json->{agreement_id};
309
        ->json_is( '/license_info'     => $agreement->{license_info} )
310
        ->tx->res->json->{agreement_id};
297
311
298
    # Authorized attempt to create with null id
312
    # Authorized attempt to create with null id
299
    $agreement->{agreement_id} = undef;
313
    $agreement->{agreement_id} = undef;
300
    $t->post_ok( "//$userid:$password@/api/v1/erm/agreements" => json => $agreement )->status_is(400)
314
    $t->post_ok( "//$userid:$password@/api/v1/erm/agreements" => json => $agreement )
315
        ->status_is(400)
301
        ->json_has('/errors');
316
        ->json_has('/errors');
302
317
303
    # Authorized attempt to create with existing id
318
    # Authorized attempt to create with existing id
Lines 357-363 subtest 'update() tests' => sub { Link Here
357
    };
372
    };
358
373
359
    $t->put_ok( "//$userid:$password@/api/v1/erm/agreements/$agreement_id" => json => $agreement_with_missing_field )
374
    $t->put_ok( "//$userid:$password@/api/v1/erm/agreements/$agreement_id" => json => $agreement_with_missing_field )
360
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
375
        ->status_is(400)
376
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
361
377
362
    # Full object update on PUT
378
    # Full object update on PUT
363
    my $agreement_with_updated_field = {
379
    my $agreement_with_updated_field = {
Lines 372-378 subtest 'update() tests' => sub { Link Here
372
    };
388
    };
373
389
374
    $t->put_ok( "//$userid:$password@/api/v1/erm/agreements/$agreement_id" => json => $agreement_with_updated_field )
390
    $t->put_ok( "//$userid:$password@/api/v1/erm/agreements/$agreement_id" => json => $agreement_with_updated_field )
375
        ->status_is(200)->json_is( '/name' => 'New name' );
391
        ->status_is(200)
392
        ->json_is( '/name' => 'New name' );
376
393
377
    # Authorized attempt to write invalid data
394
    # Authorized attempt to write invalid data
378
    my $agreement_with_invalid_field = {
395
    my $agreement_with_invalid_field = {
Lines 387-393 subtest 'update() tests' => sub { Link Here
387
    };
404
    };
388
405
389
    $t->put_ok( "//$userid:$password@/api/v1/erm/agreements/$agreement_id" => json => $agreement_with_invalid_field )
406
    $t->put_ok( "//$userid:$password@/api/v1/erm/agreements/$agreement_id" => json => $agreement_with_invalid_field )
390
        ->status_is(400)->json_is(
407
        ->status_is(400)
408
        ->json_is(
391
        "/errors" => [
409
        "/errors" => [
392
            {
410
            {
393
                message => "Properties not allowed: blah.",
411
                message => "Properties not allowed: blah.",
Lines 445-451 subtest 'delete() tests' => sub { Link Here
445
    $t->delete_ok("//$unauth_userid:$password@/api/v1/erm/agreements/$agreement_id")->status_is(403);
463
    $t->delete_ok("//$unauth_userid:$password@/api/v1/erm/agreements/$agreement_id")->status_is(403);
446
464
447
    # Delete existing agreement
465
    # Delete existing agreement
448
    $t->delete_ok("//$userid:$password@/api/v1/erm/agreements/$agreement_id")->status_is( 204, 'REST3.2.4' )
466
    $t->delete_ok("//$userid:$password@/api/v1/erm/agreements/$agreement_id")
467
        ->status_is( 204, 'REST3.2.4' )
449
        ->content_is( '', 'REST3.3.4' );
468
        ->content_is( '', 'REST3.3.4' );
450
469
451
    # Attempt to delete non-existent agreement
470
    # Attempt to delete non-existent agreement
(-)a/t/db_dependent/api/v1/erm_counter_files.t (-6 / +12 lines)
Lines 79-91 subtest 'list() tests' => sub { Link Here
79
    );
79
    );
80
80
81
    # Two counter_files created, they should both be returned
81
    # Two counter_files created, they should both be returned
82
    $t->get_ok("//$userid:$password@/api/v1/erm/counter_files")->status_is(200)
82
    $t->get_ok("//$userid:$password@/api/v1/erm/counter_files")
83
        ->status_is(200)
83
        ->json_is( [ $counter_file->to_api, $another_counter_file->to_api, ] );
84
        ->json_is( [ $counter_file->to_api, $another_counter_file->to_api, ] );
84
85
85
    # Attempt to search by type like 'ko'
86
    # Attempt to search by type like 'ko'
86
    $counter_file->delete;
87
    $counter_file->delete;
87
    $another_counter_file->delete;
88
    $another_counter_file->delete;
88
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/counter_files?q=[{"me.type":{"like":"%ko%"}}]~)->status_is(200)
89
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/counter_files?q=[{"me.type":{"like":"%ko%"}}]~)
90
        ->status_is(200)
89
        ->json_is( [] );
91
        ->json_is( [] );
90
92
91
    my $counter_file_to_search = $builder->build_object(
93
    my $counter_file_to_search = $builder->build_object(
Lines 98-108 subtest 'list() tests' => sub { Link Here
98
    );
100
    );
99
101
100
    # Search works, searching for type like 'ko'
102
    # Search works, searching for type like 'ko'
101
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/counter_files?q=[{"me.type":{"like":"%ko%"}}]~)->status_is(200)
103
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/counter_files?q=[{"me.type":{"like":"%ko%"}}]~)
104
        ->status_is(200)
102
        ->json_is( [ $counter_file_to_search->to_api ] );
105
        ->json_is( [ $counter_file_to_search->to_api ] );
103
106
104
    # Warn on unsupported query parameter
107
    # Warn on unsupported query parameter
105
    $t->get_ok("//$userid:$password@/api/v1/erm/counter_files?blah=blah")->status_is(400)
108
    $t->get_ok("//$userid:$password@/api/v1/erm/counter_files?blah=blah")
109
        ->status_is(400)
106
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
110
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
107
111
108
    # Unauthorized access
112
    # Unauthorized access
Lines 153-159 subtest 'get() tests' => sub { Link Here
153
    my $non_existent_id        = $counter_file_to_delete->erm_counter_files_id;
157
    my $non_existent_id        = $counter_file_to_delete->erm_counter_files_id;
154
    $counter_file_to_delete->delete;
158
    $counter_file_to_delete->delete;
155
159
156
    $t->get_ok("//$userid:$password@/api/v1/erm/counter_files/$non_existent_id/file/content")->status_is(404)
160
    $t->get_ok("//$userid:$password@/api/v1/erm/counter_files/$non_existent_id/file/content")
161
        ->status_is(404)
157
        ->json_is( '/error' => 'COUNTER file not found' );
162
        ->json_is( '/error' => 'COUNTER file not found' );
158
163
159
    $schema->storage->txn_rollback;
164
    $schema->storage->txn_rollback;
Lines 192-198 subtest 'delete() tests' => sub { Link Here
192
    $t->delete_ok("//$unauth_userid:$password@/api/v1/erm/counter_files/$counter_file_id")->status_is(403);
197
    $t->delete_ok("//$unauth_userid:$password@/api/v1/erm/counter_files/$counter_file_id")->status_is(403);
193
198
194
    # Delete existing counter_file
199
    # Delete existing counter_file
195
    $t->delete_ok("//$userid:$password@/api/v1/erm/counter_files/$counter_file_id")->status_is( 204, 'REST3.2.4' )
200
    $t->delete_ok("//$userid:$password@/api/v1/erm/counter_files/$counter_file_id")
201
        ->status_is( 204, 'REST3.2.4' )
196
        ->content_is( '', 'REST3.3.4' );
202
        ->content_is( '', 'REST3.3.4' );
197
203
198
    # Attempt to delete non-existent counter_file
204
    # Attempt to delete non-existent counter_file
(-)a/t/db_dependent/api/v1/erm_counter_logs.t (-3 / +6 lines)
Lines 79-89 subtest 'list() tests' => sub { Link Here
79
    );
79
    );
80
80
81
    # Two counter_logs created, they should both be returned
81
    # Two counter_logs created, they should both be returned
82
    $t->get_ok("//$userid:$password@/api/v1/erm/counter_logs")->status_is(200)
82
    $t->get_ok("//$userid:$password@/api/v1/erm/counter_logs")
83
        ->status_is(200)
83
        ->json_is( [ $counter_log->to_api, $another_counter_log->to_api, ] );
84
        ->json_is( [ $counter_log->to_api, $another_counter_log->to_api, ] );
84
85
85
    # Return 2 counter logs with patron embedded
86
    # Return 2 counter logs with patron embedded
86
    $t->get_ok( "//$userid:$password@/api/v1/erm/counter_logs/" => { 'x-koha-embed' => 'patron' } )->status_is(200)
87
    $t->get_ok( "//$userid:$password@/api/v1/erm/counter_logs/" => { 'x-koha-embed' => 'patron' } )
88
        ->status_is(200)
87
        ->json_is(
89
        ->json_is(
88
        [
90
        [
89
            { %{ $counter_log->to_api }, patron => $counter_log->patron->to_api( { user => $librarian } ) },
91
            { %{ $counter_log->to_api }, patron => $counter_log->patron->to_api( { user => $librarian } ) },
Lines 95-101 subtest 'list() tests' => sub { Link Here
95
        );
97
        );
96
98
97
    # Warn on unsupported query parameter
99
    # Warn on unsupported query parameter
98
    $t->get_ok("//$userid:$password@/api/v1/erm/counter_logs?blah=blah")->status_is(400)
100
    $t->get_ok("//$userid:$password@/api/v1/erm/counter_logs?blah=blah")
101
        ->status_is(400)
99
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
102
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
100
103
101
    # Unauthorized access
104
    # Unauthorized access
(-)a/t/db_dependent/api/v1/erm_custom_reports.t (-14 / +28 lines)
Lines 113-119 subtest "monthly_report" => sub { Link Here
113
    my $expected_results1 = 2;    # One title, with one row for each metric type
113
    my $expected_results1 = 2;    # One title, with one row for each metric type
114
114
115
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/monthly_report/title?$query_string" =>
115
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/monthly_report/title?$query_string" =>
116
            { 'x-koha-embed' => 'erm_usage_muses' } )->status_is(200)
116
            { 'x-koha-embed' => 'erm_usage_muses' } )
117
        ->status_is(200)
117
        ->json_has( '/' . ( $expected_results1 - 2 ) . '/title_id' )
118
        ->json_has( '/' . ( $expected_results1 - 2 ) . '/title_id' )
118
        ->json_has( '/' . ( $expected_results1 - 1 ) . '/title_id' )
119
        ->json_has( '/' . ( $expected_results1 - 1 ) . '/title_id' )
119
        ->json_hasnt( '/' . ($expected_results1) . '/title_id' );
120
        ->json_hasnt( '/' . ($expected_results1) . '/title_id' );
Lines 135-141 subtest "monthly_report" => sub { Link Here
135
    my $expected_results2 = 4;    # Two titles this time
136
    my $expected_results2 = 4;    # Two titles this time
136
137
137
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/monthly_report/title?$query_string_with_multiple_years" =>
138
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/monthly_report/title?$query_string_with_multiple_years" =>
138
            { 'x-koha-embed' => 'erm_usage_muses' } )->status_is(200)
139
            { 'x-koha-embed' => 'erm_usage_muses' } )
140
        ->status_is(200)
139
        ->json_has( '/' . ( $expected_results2 - 4 ) . '/title_id' )
141
        ->json_has( '/' . ( $expected_results2 - 4 ) . '/title_id' )
140
        ->json_has( '/' . ( $expected_results2 - 3 ) . '/title_id' )
142
        ->json_has( '/' . ( $expected_results2 - 3 ) . '/title_id' )
141
        ->json_has( '/' . ( $expected_results2 - 2 ) . '/title_id' )
143
        ->json_has( '/' . ( $expected_results2 - 2 ) . '/title_id' )
Lines 210-216 subtest "yearly_report" => sub { Link Here
210
    my $expected_results1 = 2;    # One title, with one row for each metric type
212
    my $expected_results1 = 2;    # One title, with one row for each metric type
211
213
212
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/yearly_report/title?$query_string" =>
214
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/yearly_report/title?$query_string" =>
213
            { 'x-koha-embed' => 'erm_usage_yuses' } )->status_is(200)
215
            { 'x-koha-embed' => 'erm_usage_yuses' } )
216
        ->status_is(200)
214
        ->json_has( '/' . ( $expected_results1 - 2 ) . '/title_id' )
217
        ->json_has( '/' . ( $expected_results1 - 2 ) . '/title_id' )
215
        ->json_has( '/' . ( $expected_results1 - 1 ) . '/title_id' )
218
        ->json_has( '/' . ( $expected_results1 - 1 ) . '/title_id' )
216
        ->json_hasnt( '/' . ($expected_results1) . '/title_id' );
219
        ->json_hasnt( '/' . ($expected_results1) . '/title_id' );
Lines 225-231 subtest "yearly_report" => sub { Link Here
225
    my $expected_results2 = 4;    # Two titles this time
228
    my $expected_results2 = 4;    # Two titles this time
226
229
227
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/yearly_report/title?$query_string_with_multiple_years" =>
230
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/yearly_report/title?$query_string_with_multiple_years" =>
228
            { 'x-koha-embed' => 'erm_usage_yuses' } )->status_is(200)
231
            { 'x-koha-embed' => 'erm_usage_yuses' } )
232
        ->status_is(200)
229
        ->json_has( '/' . ( $expected_results2 - 4 ) . '/title_id' )
233
        ->json_has( '/' . ( $expected_results2 - 4 ) . '/title_id' )
230
        ->json_has( '/' . ( $expected_results2 - 3 ) . '/title_id' )
234
        ->json_has( '/' . ( $expected_results2 - 3 ) . '/title_id' )
231
        ->json_has( '/' . ( $expected_results2 - 2 ) . '/title_id' )
235
        ->json_has( '/' . ( $expected_results2 - 2 ) . '/title_id' )
Lines 302-308 subtest "metric_types_report" => sub { Link Here
302
    my $expected_results1 = 1;    # One title
306
    my $expected_results1 = 1;    # One title
303
307
304
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/metric_types_report/title?$query_string" =>
308
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/metric_types_report/title?$query_string" =>
305
            { 'x-koha-embed' => 'erm_usage_muses' } )->status_is(200)
309
            { 'x-koha-embed' => 'erm_usage_muses' } )
310
        ->status_is(200)
306
        ->json_has( '/' . ( $expected_results1 - 1 ) . '/title_id' )
311
        ->json_has( '/' . ( $expected_results1 - 1 ) . '/title_id' )
307
        ->json_hasnt( '/' . ($expected_results1) . '/title_id' );
312
        ->json_hasnt( '/' . ($expected_results1) . '/title_id' );
308
313
Lines 323-329 subtest "metric_types_report" => sub { Link Here
323
    my $expected_results2 = 2;    # Two titles this time
328
    my $expected_results2 = 2;    # Two titles this time
324
329
325
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/metric_types_report/title?$query_string_with_multiple_years" =>
330
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/metric_types_report/title?$query_string_with_multiple_years" =>
326
            { 'x-koha-embed' => 'erm_usage_muses' } )->status_is(200)
331
            { 'x-koha-embed' => 'erm_usage_muses' } )
332
        ->status_is(200)
327
        ->json_has( '/' . ( $expected_results2 - 2 ) . '/title_id' )
333
        ->json_has( '/' . ( $expected_results2 - 2 ) . '/title_id' )
328
        ->json_has( '/' . ( $expected_results2 - 1 ) . '/title_id' )
334
        ->json_has( '/' . ( $expected_results2 - 1 ) . '/title_id' )
329
        ->json_hasnt( '/' . ($expected_results2) . '/title_id' );
335
        ->json_hasnt( '/' . ($expected_results2) . '/title_id' );
Lines 398-404 subtest "provider_rollup_report" => sub { Link Here
398
    my $expected_results1 = 2;    # One provider repeated once for each metric type
404
    my $expected_results1 = 2;    # One provider repeated once for each metric type
399
405
400
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/provider_rollup_report/title?$query_string" =>
406
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/provider_rollup_report/title?$query_string" =>
401
            { 'x-koha-embed' => 'erm_usage_titles.erm_usage_muses' } )->status_is(200)
407
            { 'x-koha-embed' => 'erm_usage_titles.erm_usage_muses' } )
408
        ->status_is(200)
402
        ->json_is( '/' . ( $expected_results1 - 2 ) . '/provider_rollup_total' => 2, 'Total is correct' )
409
        ->json_is( '/' . ( $expected_results1 - 2 ) . '/provider_rollup_total' => 2, 'Total is correct' )
403
        ->json_is( '/' . ( $expected_results1 - 1 ) . '/provider_rollup_total' => 1, 'Total is correct' );
410
        ->json_is( '/' . ( $expected_results1 - 1 ) . '/provider_rollup_total' => 1, 'Total is correct' );
404
411
Lines 476-482 subtest "5.1 monthly_report" => sub { Link Here
476
    my $expected_results1 = 2;    # One title, with one row for each metric type
483
    my $expected_results1 = 2;    # One title, with one row for each metric type
477
484
478
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/monthly_report/title?$query_string" =>
485
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/monthly_report/title?$query_string" =>
479
            { 'x-koha-embed' => 'erm_usage_muses' } )->status_is(200)
486
            { 'x-koha-embed' => 'erm_usage_muses' } )
487
        ->status_is(200)
480
        ->json_has( '/' . ( $expected_results1 - 2 ) . '/title_id' )
488
        ->json_has( '/' . ( $expected_results1 - 2 ) . '/title_id' )
481
        ->json_has( '/' . ( $expected_results1 - 1 ) . '/title_id' )
489
        ->json_has( '/' . ( $expected_results1 - 1 ) . '/title_id' )
482
        ->json_hasnt( '/' . ($expected_results1) . '/title_id' );
490
        ->json_hasnt( '/' . ($expected_results1) . '/title_id' );
Lines 498-504 subtest "5.1 monthly_report" => sub { Link Here
498
    my $expected_results2 = 4;    # Two titles this time
506
    my $expected_results2 = 4;    # Two titles this time
499
507
500
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/monthly_report/title?$query_string_with_multiple_years" =>
508
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/monthly_report/title?$query_string_with_multiple_years" =>
501
            { 'x-koha-embed' => 'erm_usage_muses' } )->status_is(200)
509
            { 'x-koha-embed' => 'erm_usage_muses' } )
510
        ->status_is(200)
502
        ->json_has( '/' . ( $expected_results2 - 4 ) . '/title_id' )
511
        ->json_has( '/' . ( $expected_results2 - 4 ) . '/title_id' )
503
        ->json_has( '/' . ( $expected_results2 - 3 ) . '/title_id' )
512
        ->json_has( '/' . ( $expected_results2 - 3 ) . '/title_id' )
504
        ->json_has( '/' . ( $expected_results2 - 2 ) . '/title_id' )
513
        ->json_has( '/' . ( $expected_results2 - 2 ) . '/title_id' )
Lines 573-579 subtest "5.1 yearly_report" => sub { Link Here
573
    my $expected_results1 = 4;    # Two titles, with one row for each metric type
582
    my $expected_results1 = 4;    # Two titles, with one row for each metric type
574
583
575
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/yearly_report/title?$query_string" =>
584
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/yearly_report/title?$query_string" =>
576
            { 'x-koha-embed' => 'erm_usage_yuses' } )->status_is(200)
585
            { 'x-koha-embed' => 'erm_usage_yuses' } )
586
        ->status_is(200)
577
        ->json_has( '/' . ( $expected_results1 - 2 ) . '/title_id' )
587
        ->json_has( '/' . ( $expected_results1 - 2 ) . '/title_id' )
578
        ->json_has( '/' . ( $expected_results1 - 1 ) . '/title_id' )
588
        ->json_has( '/' . ( $expected_results1 - 1 ) . '/title_id' )
579
        ->json_hasnt( '/' . ($expected_results1) . '/title_id' );
589
        ->json_hasnt( '/' . ($expected_results1) . '/title_id' );
Lines 588-594 subtest "5.1 yearly_report" => sub { Link Here
588
    my $expected_results2 = 4;    # Two titles this time
598
    my $expected_results2 = 4;    # Two titles this time
589
599
590
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/yearly_report/title?$query_string_with_multiple_years" =>
600
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/yearly_report/title?$query_string_with_multiple_years" =>
591
            { 'x-koha-embed' => 'erm_usage_yuses' } )->status_is(200)
601
            { 'x-koha-embed' => 'erm_usage_yuses' } )
602
        ->status_is(200)
592
        ->json_has( '/' . ( $expected_results2 - 4 ) . '/title_id' )
603
        ->json_has( '/' . ( $expected_results2 - 4 ) . '/title_id' )
593
        ->json_has( '/' . ( $expected_results2 - 3 ) . '/title_id' )
604
        ->json_has( '/' . ( $expected_results2 - 3 ) . '/title_id' )
594
        ->json_has( '/' . ( $expected_results2 - 2 ) . '/title_id' )
605
        ->json_has( '/' . ( $expected_results2 - 2 ) . '/title_id' )
Lines 665-671 subtest "5.1 metric_types_report" => sub { Link Here
665
    my $expected_results1 = 1;    # One title
676
    my $expected_results1 = 1;    # One title
666
677
667
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/metric_types_report/title?$query_string" =>
678
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/metric_types_report/title?$query_string" =>
668
            { 'x-koha-embed' => 'erm_usage_muses' } )->status_is(200)
679
            { 'x-koha-embed' => 'erm_usage_muses' } )
680
        ->status_is(200)
669
        ->json_has( '/' . ( $expected_results1 - 1 ) . '/title_id' )
681
        ->json_has( '/' . ( $expected_results1 - 1 ) . '/title_id' )
670
        ->json_hasnt( '/' . ($expected_results1) . '/title_id' );
682
        ->json_hasnt( '/' . ($expected_results1) . '/title_id' );
671
683
Lines 686-692 subtest "5.1 metric_types_report" => sub { Link Here
686
    my $expected_results2 = 2;    # Two titles this time
698
    my $expected_results2 = 2;    # Two titles this time
687
699
688
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/metric_types_report/title?$query_string_with_multiple_years" =>
700
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/metric_types_report/title?$query_string_with_multiple_years" =>
689
            { 'x-koha-embed' => 'erm_usage_muses' } )->status_is(200)
701
            { 'x-koha-embed' => 'erm_usage_muses' } )
702
        ->status_is(200)
690
        ->json_has( '/' . ( $expected_results2 - 2 ) . '/title_id' )
703
        ->json_has( '/' . ( $expected_results2 - 2 ) . '/title_id' )
691
        ->json_has( '/' . ( $expected_results2 - 1 ) . '/title_id' )
704
        ->json_has( '/' . ( $expected_results2 - 1 ) . '/title_id' )
692
        ->json_hasnt( '/' . ($expected_results2) . '/title_id' );
705
        ->json_hasnt( '/' . ($expected_results2) . '/title_id' );
Lines 761-767 subtest "5.1 provider_rollup_report" => sub { Link Here
761
    my $expected_results1 = 2;    # One provider repeated once for each metric type
774
    my $expected_results1 = 2;    # One provider repeated once for each metric type
762
775
763
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/provider_rollup_report/title?$query_string" =>
776
    $t->get_ok( "//$userid:$password@/api/v1/erm/eUsage/provider_rollup_report/title?$query_string" =>
764
            { 'x-koha-embed' => 'erm_usage_titles.erm_usage_muses' } )->status_is(200)
777
            { 'x-koha-embed' => 'erm_usage_titles.erm_usage_muses' } )
778
        ->status_is(200)
765
        ->json_is( '/' . ( $expected_results1 - 2 ) . '/provider_rollup_total' => 528, 'Total is correct' )
779
        ->json_is( '/' . ( $expected_results1 - 2 ) . '/provider_rollup_total' => 528, 'Total is correct' )
766
        ->json_is( '/' . ( $expected_results1 - 1 ) . '/provider_rollup_total' => 228, 'Total is correct' );
780
        ->json_is( '/' . ( $expected_results1 - 1 ) . '/provider_rollup_total' => 228, 'Total is correct' );
767
781
(-)a/t/db_dependent/api/v1/erm_documents.t (-3 / +6 lines)
Lines 74-80 subtest 'get() tests' => sub { Link Here
74
74
75
    # This document exists, should get returned
75
    # This document exists, should get returned
76
    $t->get_ok( "//$userid:$password@/api/v1/erm/documents/" . $document->document_id . "/file/content" )
76
    $t->get_ok( "//$userid:$password@/api/v1/erm/documents/" . $document->document_id . "/file/content" )
77
        ->status_is(200)->json_is('123');
77
        ->status_is(200)
78
        ->json_is('123');
78
79
79
    # Create a document through a license, gets returned
80
    # Create a document through a license, gets returned
80
    my $license = $builder->build_object( { class => 'Koha::ERM::Licenses' } );
81
    my $license = $builder->build_object( { class => 'Koha::ERM::Licenses' } );
Lines 94-100 subtest 'get() tests' => sub { Link Here
94
    my @documents           = $license->documents->as_list;
95
    my @documents           = $license->documents->as_list;
95
    my $license_document_id = $documents[0]->document_id;
96
    my $license_document_id = $documents[0]->document_id;
96
97
97
    $t->get_ok( "//$userid:$password@/api/v1/erm/documents/" . $license_document_id . "/file/content" )->status_is(200)
98
    $t->get_ok( "//$userid:$password@/api/v1/erm/documents/" . $license_document_id . "/file/content" )
99
        ->status_is(200)
98
        ->content_is( decode_base64('321') );
100
        ->content_is( decode_base64('321') );
99
101
100
    # Delete a document through a license, no longer exists
102
    # Delete a document through a license, no longer exists
Lines 122-128 subtest 'get() tests' => sub { Link Here
122
    my $non_existent_id    = $document_to_delete->id;
124
    my $non_existent_id    = $document_to_delete->id;
123
    $document_to_delete->delete;
125
    $document_to_delete->delete;
124
126
125
    $t->get_ok("//$userid:$password@/api/v1/erm/documents/$non_existent_id/file/content")->status_is(404)
127
    $t->get_ok("//$userid:$password@/api/v1/erm/documents/$non_existent_id/file/content")
128
        ->status_is(404)
126
        ->json_is( '/error' => 'Document not found' );
129
        ->json_is( '/error' => 'Document not found' );
127
130
128
    $schema->storage->txn_rollback;
131
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/erm_eholdings_packages.t (-16 / +33 lines)
Lines 73-79 subtest 'list() tests' => sub { Link Here
73
    );
73
    );
74
74
75
    # One EHoldings package created, should get returned
75
    # One EHoldings package created, should get returned
76
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/packages")->status_is(200)
76
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/packages")
77
        ->status_is(200)
77
        ->json_is( [ $ehpackage->to_api ] );
78
        ->json_is( [ $ehpackage->to_api ] );
78
79
79
    my $another_ehpackage = $builder->build_object(
80
    my $another_ehpackage = $builder->build_object(
Lines 103-116 subtest 'list() tests' => sub { Link Here
103
104
104
    # Filtering works, two EHoldings packages sharing package_type
105
    # Filtering works, two EHoldings packages sharing package_type
105
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages?package_type=" . $ehpackage->package_type )
106
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages?package_type=" . $ehpackage->package_type )
106
        ->status_is(200)->json_is( [ $ehpackage->to_api, $another_ehpackage->to_api ] );
107
        ->status_is(200)
108
        ->json_is( [ $ehpackage->to_api, $another_ehpackage->to_api ] );
107
109
108
    # Attempt to search by name like 'ko'
110
    # Attempt to search by name like 'ko'
109
    $ehpackage->delete;
111
    $ehpackage->delete;
110
    $another_ehpackage->delete;
112
    $another_ehpackage->delete;
111
    $ehpackage_with_another_package_type->delete;
113
    $ehpackage_with_another_package_type->delete;
112
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/eholdings/local/packages?q=[{"me.name":{"like":"%ko%"}}]~)
114
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/eholdings/local/packages?q=[{"me.name":{"like":"%ko%"}}]~)
113
        ->status_is(200)->json_is( [] );
115
        ->status_is(200)
116
        ->json_is( [] );
114
117
115
    my $ehpackage_to_search = $builder->build_object(
118
    my $ehpackage_to_search = $builder->build_object(
116
        {
119
        {
Lines 124-133 subtest 'list() tests' => sub { Link Here
124
127
125
    # Search works, searching for name like 'ko'
128
    # Search works, searching for name like 'ko'
126
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/eholdings/local/packages?q=[{"me.name":{"like":"%ko%"}}]~)
129
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/eholdings/local/packages?q=[{"me.name":{"like":"%ko%"}}]~)
127
        ->status_is(200)->json_is( [ $ehpackage_to_search->to_api ] );
130
        ->status_is(200)
131
        ->json_is( [ $ehpackage_to_search->to_api ] );
128
132
129
    # Warn on unsupported query parameter
133
    # Warn on unsupported query parameter
130
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/packages?blah=blah")->status_is(400)
134
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/packages?blah=blah")
135
        ->status_is(400)
131
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
136
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
132
137
133
    # Unauthorized access
138
    # Unauthorized access
Lines 164-175 subtest 'get() tests' => sub { Link Here
164
    my $unauth_userid = $patron->userid;
169
    my $unauth_userid = $patron->userid;
165
170
166
    # This EHoldings package exists, should get returned
171
    # This EHoldings package exists, should get returned
167
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages/" . $ehpackage->package_id )->status_is(200)
172
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages/" . $ehpackage->package_id )
173
        ->status_is(200)
168
        ->json_is( $ehpackage->to_api );
174
        ->json_is( $ehpackage->to_api );
169
175
170
    # Return one EHoldings package with embed
176
    # Return one EHoldings package with embed
171
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages/"
177
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages/"
172
            . $ehpackage->package_id => { 'x-koha-embed' => 'resources+count' } )->status_is(200)
178
            . $ehpackage->package_id => { 'x-koha-embed' => 'resources+count' } )
179
        ->status_is(200)
173
        ->json_is( { %{ $ehpackage->to_api }, resources_count => 0 } );
180
        ->json_is( { %{ $ehpackage->to_api }, resources_count => 0 } );
174
181
175
    # Unauthorized access
182
    # Unauthorized access
Lines 181-187 subtest 'get() tests' => sub { Link Here
181
    my $non_existent_id     = $ehpackage_to_delete->package_id;
188
    my $non_existent_id     = $ehpackage_to_delete->package_id;
182
    $ehpackage_to_delete->delete;
189
    $ehpackage_to_delete->delete;
183
190
184
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/packages/$non_existent_id")->status_is(404)
191
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/packages/$non_existent_id")
192
        ->status_is(404)
185
        ->json_is( '/error' => 'Package not found' );
193
        ->json_is( '/error' => 'Package not found' );
186
194
187
    $schema->storage->txn_rollback;
195
    $schema->storage->txn_rollback;
Lines 231-237 subtest 'add() tests' => sub { Link Here
231
    };
239
    };
232
240
233
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages" => json => $ehpackage_with_invalid_field )
241
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages" => json => $ehpackage_with_invalid_field )
234
        ->status_is(400)->json_is(
242
        ->status_is(400)
243
        ->json_is(
235
        "/errors" => [
244
        "/errors" => [
236
            {
245
            {
237
                message => "Properties not allowed: blah.",
246
                message => "Properties not allowed: blah.",
Lines 243-263 subtest 'add() tests' => sub { Link Here
243
    # Authorized attempt to write
252
    # Authorized attempt to write
244
    my $ehpackage_id =
253
    my $ehpackage_id =
245
        $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages" => json => $ehpackage )
254
        $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages" => json => $ehpackage )
246
        ->status_is( 201, 'REST3.2.1' )->header_like(
255
        ->status_is( 201, 'REST3.2.1' )
256
        ->header_like(
247
        Location => qr|^/api/v1/erm/eholdings/local/packages/\d*|,
257
        Location => qr|^/api/v1/erm/eholdings/local/packages/\d*|,
248
        'REST3.4.1'
258
        'REST3.4.1'
249
    )->json_is( '/name' => $ehpackage->{name} )->json_is( '/print_identifier' => $ehpackage->{print_identifier} )
259
        )
250
        ->json_is( '/notes' => $ehpackage->{notes} )->json_is( '/publisher_name' => $ehpackage->{publisher_name} )
260
        ->json_is( '/name'             => $ehpackage->{name} )
261
        ->json_is( '/print_identifier' => $ehpackage->{print_identifier} )
262
        ->json_is( '/notes'            => $ehpackage->{notes} )
263
        ->json_is( '/publisher_name'   => $ehpackage->{publisher_name} )
251
        ->tx->res->json->{package_id};
264
        ->tx->res->json->{package_id};
252
265
253
    # Authorized attempt to create with null id
266
    # Authorized attempt to create with null id
254
    $ehpackage->{package_id} = undef;
267
    $ehpackage->{package_id} = undef;
255
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages" => json => $ehpackage )->status_is(400)
268
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages" => json => $ehpackage )
269
        ->status_is(400)
256
        ->json_has('/errors');
270
        ->json_has('/errors');
257
271
258
    # Authorized attempt to create with existing id
272
    # Authorized attempt to create with existing id
259
    $ehpackage->{package_id} = $ehpackage_id;
273
    $ehpackage->{package_id} = $ehpackage_id;
260
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages" => json => $ehpackage )->status_is(400)
274
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages" => json => $ehpackage )
275
        ->status_is(400)
261
        ->json_is(
276
        ->json_is(
262
        "/errors" => [
277
        "/errors" => [
263
            {
278
            {
Lines 306-312 subtest 'update() tests' => sub { Link Here
306
    my $ehpackage_with_missing_field = { package_type => "Package type", };
321
    my $ehpackage_with_missing_field = { package_type => "Package type", };
307
322
308
    $t->put_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages/$ehpackage_id" => json =>
323
    $t->put_ok( "//$userid:$password@/api/v1/erm/eholdings/local/packages/$ehpackage_id" => json =>
309
            $ehpackage_with_missing_field )->status_is(400)
324
            $ehpackage_with_missing_field )
325
        ->status_is(400)
310
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
326
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
311
327
312
    # Full object update on PUT
328
    # Full object update on PUT
Lines 386-392 subtest 'delete() tests' => sub { Link Here
386
402
387
    # Delete existing EHolding package
403
    # Delete existing EHolding package
388
    $t->delete_ok("//$userid:$password@/api/v1/erm/eholdings/local/packages/$ehpackage_id")
404
    $t->delete_ok("//$userid:$password@/api/v1/erm/eholdings/local/packages/$ehpackage_id")
389
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
405
        ->status_is( 204, 'REST3.2.4' )
406
        ->content_is( '', 'REST3.3.4' );
390
407
391
    # Attempt to delete non-existent EHolding package
408
    # Attempt to delete non-existent EHolding package
392
    $t->delete_ok("//$userid:$password@/api/v1/erm/eholdings/local/packages/$ehpackage_id")->status_is(404);
409
    $t->delete_ok("//$userid:$password@/api/v1/erm/eholdings/local/packages/$ehpackage_id")->status_is(404);
(-)a/t/db_dependent/api/v1/erm_eholdings_resources.t (-5 / +10 lines)
Lines 68-74 subtest 'list() tests' => sub { Link Here
68
    my $resource = $builder->build_object( { class => 'Koha::ERM::EHoldings::Resources' } );
68
    my $resource = $builder->build_object( { class => 'Koha::ERM::EHoldings::Resources' } );
69
69
70
    # One resource created, should get returned
70
    # One resource created, should get returned
71
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/resources")->status_is(200)
71
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/resources")
72
        ->status_is(200)
72
        ->json_is( [ $resource->to_api ] );
73
        ->json_is( [ $resource->to_api ] );
73
74
74
    my $another_resource = $builder->build_object(
75
    my $another_resource = $builder->build_object(
Lines 90-99 subtest 'list() tests' => sub { Link Here
90
91
91
    # Filtering works, two resources sharing vendor_id
92
    # Filtering works, two resources sharing vendor_id
92
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/resources?vendor_id=" . $resource->vendor_id )
93
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/resources?vendor_id=" . $resource->vendor_id )
93
        ->status_is(200)->json_is( [ $resource->to_api, $another_resource->to_api ] );
94
        ->status_is(200)
95
        ->json_is( [ $resource->to_api, $another_resource->to_api ] );
94
96
95
    # Warn on unsupported query parameter
97
    # Warn on unsupported query parameter
96
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/resources?blah=blah")->status_is(400)
98
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/resources?blah=blah")
99
        ->status_is(400)
97
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
100
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
98
101
99
    # Unauthorized access
102
    # Unauthorized access
Lines 130-136 subtest 'get() tests' => sub { Link Here
130
    my $unauth_userid = $patron->userid;
133
    my $unauth_userid = $patron->userid;
131
134
132
    # This resource exists, should get returned
135
    # This resource exists, should get returned
133
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/resources/" . $resource->resource_id )->status_is(200)
136
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/resources/" . $resource->resource_id )
137
        ->status_is(200)
134
        ->json_is( $resource->to_api );
138
        ->json_is( $resource->to_api );
135
139
136
    # Unauthorized access
140
    # Unauthorized access
Lines 142-148 subtest 'get() tests' => sub { Link Here
142
    my $non_existent_id    = $resource_to_delete->resource_id;
146
    my $non_existent_id    = $resource_to_delete->resource_id;
143
    $resource_to_delete->delete;
147
    $resource_to_delete->delete;
144
148
145
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/resources/$non_existent_id")->status_is(404)
149
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/resources/$non_existent_id")
150
        ->status_is(404)
146
        ->json_is( '/error' => 'eHolding resource not found' );
151
        ->json_is( '/error' => 'eHolding resource not found' );
147
152
148
    $schema->storage->txn_rollback;
153
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/erm_eholdings_titles.t (-23 / +46 lines)
Lines 72-78 subtest 'list() tests' => sub { Link Here
72
    my $ehtitle = $builder->build_object( { class => 'Koha::ERM::EHoldings::Titles' } );
72
    my $ehtitle = $builder->build_object( { class => 'Koha::ERM::EHoldings::Titles' } );
73
73
74
    # One EHoldings title created, should get returned
74
    # One EHoldings title created, should get returned
75
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/titles")->status_is(200)
75
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/titles")
76
        ->status_is(200)
76
        ->json_is( [ $ehtitle->to_api ] );
77
        ->json_is( [ $ehtitle->to_api ] );
77
78
78
    my $another_ehtitle = $builder->build_object(
79
    my $another_ehtitle = $builder->build_object(
Lines 95-108 subtest 'list() tests' => sub { Link Here
95
    # Filtering works, two EHoldings titles sharing publication_type
96
    # Filtering works, two EHoldings titles sharing publication_type
96
    $t->get_ok(
97
    $t->get_ok(
97
        "//$userid:$password@/api/v1/erm/eholdings/local/titles?publication_type=" . $ehtitle->publication_type )
98
        "//$userid:$password@/api/v1/erm/eholdings/local/titles?publication_type=" . $ehtitle->publication_type )
98
        ->status_is(200)->json_is( [ $ehtitle->to_api, $another_ehtitle->to_api ] );
99
        ->status_is(200)
100
        ->json_is( [ $ehtitle->to_api, $another_ehtitle->to_api ] );
99
101
100
    # Attempt to search by publication_title like 'ko'
102
    # Attempt to search by publication_title like 'ko'
101
    $ehtitle->delete;
103
    $ehtitle->delete;
102
    $another_ehtitle->delete;
104
    $another_ehtitle->delete;
103
    $ehtitle_with_another_publication_type->delete;
105
    $ehtitle_with_another_publication_type->delete;
104
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/eholdings/local/titles?q=[{"me.publication_title":{"like":"%ko%"}}]~)
106
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/eholdings/local/titles?q=[{"me.publication_title":{"like":"%ko%"}}]~)
105
        ->status_is(200)->json_is( [] );
107
        ->status_is(200)
108
        ->json_is( [] );
106
109
107
    my $ehtitle_to_search = $builder->build_object(
110
    my $ehtitle_to_search = $builder->build_object(
108
        {
111
        {
Lines 115-124 subtest 'list() tests' => sub { Link Here
115
118
116
    # Search works, searching for publication_title like 'ko'
119
    # Search works, searching for publication_title like 'ko'
117
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/eholdings/local/titles?q=[{"me.publication_title":{"like":"%ko%"}}]~)
120
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/eholdings/local/titles?q=[{"me.publication_title":{"like":"%ko%"}}]~)
118
        ->status_is(200)->json_is( [ $ehtitle_to_search->to_api ] );
121
        ->status_is(200)
122
        ->json_is( [ $ehtitle_to_search->to_api ] );
119
123
120
    # Warn on unsupported query parameter
124
    # Warn on unsupported query parameter
121
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/titles?blah=blah")->status_is(400)
125
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/titles?blah=blah")
126
        ->status_is(400)
122
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
127
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
123
128
124
    # Unauthorized access
129
    # Unauthorized access
Lines 155-166 subtest 'get() tests' => sub { Link Here
155
    my $unauth_userid = $patron->userid;
160
    my $unauth_userid = $patron->userid;
156
161
157
    # This EHoldings title exists, should get returned
162
    # This EHoldings title exists, should get returned
158
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles/" . $ehtitle->title_id )->status_is(200)
163
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles/" . $ehtitle->title_id )
164
        ->status_is(200)
159
        ->json_is( $ehtitle->to_api );
165
        ->json_is( $ehtitle->to_api );
160
166
161
    # Return one EHoldings title with embed
167
    # Return one EHoldings title with embed
162
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles/"
168
    $t->get_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles/"
163
            . $ehtitle->title_id => { 'x-koha-embed' => 'resources,resources.package' } )->status_is(200)
169
            . $ehtitle->title_id => { 'x-koha-embed' => 'resources,resources.package' } )
170
        ->status_is(200)
164
        ->json_is( { %{ $ehtitle->to_api }, resources => [] } );
171
        ->json_is( { %{ $ehtitle->to_api }, resources => [] } );
165
172
166
    # Unauthorized access
173
    # Unauthorized access
Lines 171-177 subtest 'get() tests' => sub { Link Here
171
    my $non_existent_id   = $ehtitle_to_delete->title_id;
178
    my $non_existent_id   = $ehtitle_to_delete->title_id;
172
    $ehtitle_to_delete->delete;
179
    $ehtitle_to_delete->delete;
173
180
174
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/titles/$non_existent_id")->status_is(404)
181
    $t->get_ok("//$userid:$password@/api/v1/erm/eholdings/local/titles/$non_existent_id")
182
        ->status_is(404)
175
        ->json_is( '/error' => 'eHolding title not found' );
183
        ->json_is( '/error' => 'eHolding title not found' );
176
184
177
    $schema->storage->txn_rollback;
185
    $schema->storage->txn_rollback;
Lines 241-247 subtest 'add() tests' => sub { Link Here
241
    };
249
    };
242
250
243
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles" => json => $ehtitle_with_invalid_field )
251
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles" => json => $ehtitle_with_invalid_field )
244
        ->status_is(400)->json_is(
252
        ->status_is(400)
253
        ->json_is(
245
        "/errors" => [
254
        "/errors" => [
246
            {
255
            {
247
                message => "Properties not allowed: blah.",
256
                message => "Properties not allowed: blah.",
Lines 253-264 subtest 'add() tests' => sub { Link Here
253
    # Authorized attempt to write
262
    # Authorized attempt to write
254
    my $ehtitle_id =
263
    my $ehtitle_id =
255
        $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles" => json => $ehtitle )
264
        $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles" => json => $ehtitle )
256
        ->status_is( 201, 'REST3.2.1' )->header_like(
265
        ->status_is( 201, 'REST3.2.1' )
266
        ->header_like(
257
        Location => qr|^/api/v1/erm/eholdings/local/titles/\d*|,
267
        Location => qr|^/api/v1/erm/eholdings/local/titles/\d*|,
258
        'REST3.4.1'
268
        'REST3.4.1'
259
    )->json_is( '/publication_title' => $ehtitle->{publication_title} )
269
        )
260
        ->json_is( '/print_identifier' => $ehtitle->{print_identifier} )->json_is( '/notes' => $ehtitle->{notes} )
270
        ->json_is( '/publication_title' => $ehtitle->{publication_title} )
261
        ->json_is( '/publisher_name'   => $ehtitle->{publisher_name} )->tx->res->json->{title_id};
271
        ->json_is( '/print_identifier'  => $ehtitle->{print_identifier} )
272
        ->json_is( '/notes'             => $ehtitle->{notes} )
273
        ->json_is( '/publisher_name'    => $ehtitle->{publisher_name} )
274
        ->tx->res->json->{title_id};
262
275
263
    # Import titles from virtualshelf to package
276
    # Import titles from virtualshelf to package
264
    my $ehpackage_id = $builder->build_object( { class => 'Koha::ERM::EHoldings::Packages' } )->package_id;
277
    my $ehpackage_id = $builder->build_object( { class => 'Koha::ERM::EHoldings::Packages' } )->package_id;
Lines 277-297 subtest 'add() tests' => sub { Link Here
277
    };
290
    };
278
291
279
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles/import" => json => $import_request )
292
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles/import" => json => $import_request )
280
        ->status_is(201)->json_has('/job_id');
293
        ->status_is(201)
294
        ->json_has('/job_id');
281
295
282
    # Attempt to import titles from a virtualshelf that doesn't exist
296
    # Attempt to import titles from a virtualshelf that doesn't exist
283
    $virtual_shelf->delete;
297
    $virtual_shelf->delete;
284
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles/import" => json => $import_request )
298
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles/import" => json => $import_request )
285
        ->status_is(404)->json_is( '/error' => 'List not found' );
299
        ->status_is(404)
300
        ->json_is( '/error' => 'List not found' );
286
301
287
    # Authorized attempt to create with null id
302
    # Authorized attempt to create with null id
288
    $ehtitle->{title_id} = undef;
303
    $ehtitle->{title_id} = undef;
289
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles" => json => $ehtitle )->status_is(400)
304
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles" => json => $ehtitle )
305
        ->status_is(400)
290
        ->json_has('/errors');
306
        ->json_has('/errors');
291
307
292
    # Authorized attempt to create with existing id
308
    # Authorized attempt to create with existing id
293
    $ehtitle->{title_id} = $ehtitle_id;
309
    $ehtitle->{title_id} = $ehtitle_id;
294
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles" => json => $ehtitle )->status_is(400)
310
    $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles" => json => $ehtitle )
311
        ->status_is(400)
295
        ->json_is(
312
        ->json_is(
296
        "/errors" => [
313
        "/errors" => [
297
            {
314
            {
Lines 312-318 subtest 'add() tests' => sub { Link Here
312
        $request_body->{create_linked_biblio} = 1;
329
        $request_body->{create_linked_biblio} = 1;
313
        my $biblios_count = Koha::Biblios->search()->count;
330
        my $biblios_count = Koha::Biblios->search()->count;
314
        $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles/" => json => $request_body )
331
        $t->post_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles/" => json => $request_body )
315
            ->status_is(201)->json_is( '/publication_title' => 'Publication title' );
332
            ->status_is(201)
333
            ->json_is( '/publication_title' => 'Publication title' );
316
        my $new_biblios_count = Koha::Biblios->search()->count;
334
        my $new_biblios_count = Koha::Biblios->search()->count;
317
        is( $new_biblios_count, $biblios_count + 1, "Biblio was added" );
335
        is( $new_biblios_count, $biblios_count + 1, "Biblio was added" );
318
    };
336
    };
Lines 359-365 subtest 'update() tests' => sub { Link Here
359
377
360
    $t->put_ok(
378
    $t->put_ok(
361
        "//$userid:$password@/api/v1/erm/eholdings/local/titles/$ehtitle_id" => json => $ehtitle_with_missing_field )
379
        "//$userid:$password@/api/v1/erm/eholdings/local/titles/$ehtitle_id" => json => $ehtitle_with_missing_field )
362
        ->status_is(400)->json_is(
380
        ->status_is(400)
381
        ->json_is(
363
        "/errors" => [
382
        "/errors" => [
364
            {
383
            {
365
                message => "Missing property.",
384
                message => "Missing property.",
Lines 398-404 subtest 'update() tests' => sub { Link Here
398
417
399
    $t->put_ok(
418
    $t->put_ok(
400
        "//$userid:$password@/api/v1/erm/eholdings/local/titles/$ehtitle_id" => json => $ehtitle_with_updated_field )
419
        "//$userid:$password@/api/v1/erm/eholdings/local/titles/$ehtitle_id" => json => $ehtitle_with_updated_field )
401
        ->status_is(200)->json_is( '/publication_title' => 'Publication title' );
420
        ->status_is(200)
421
        ->json_is( '/publication_title' => 'Publication title' );
402
422
403
    # Authorized attempt to write invalid data
423
    # Authorized attempt to write invalid data
404
    my $ehtitle_with_invalid_field = {
424
    my $ehtitle_with_invalid_field = {
Lines 409-415 subtest 'update() tests' => sub { Link Here
409
429
410
    $t->put_ok(
430
    $t->put_ok(
411
        "//$userid:$password@/api/v1/erm/eholdings/local/titles/$ehtitle_id" => json => $ehtitle_with_invalid_field )
431
        "//$userid:$password@/api/v1/erm/eholdings/local/titles/$ehtitle_id" => json => $ehtitle_with_invalid_field )
412
        ->status_is(400)->json_is(
432
        ->status_is(400)
433
        ->json_is(
413
        "/errors" => [
434
        "/errors" => [
414
            {
435
            {
415
                message => "Properties not allowed: blah.",
436
                message => "Properties not allowed: blah.",
Lines 446-452 subtest 'update() tests' => sub { Link Here
446
        my $ehtitle_updated_title = { publication_title => "The journal of writing unit tests :" };
467
        my $ehtitle_updated_title = { publication_title => "The journal of writing unit tests :" };
447
468
448
        $t->put_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles/$ehtitle_id" => json =>
469
        $t->put_ok( "//$userid:$password@/api/v1/erm/eholdings/local/titles/$ehtitle_id" => json =>
449
                { %$ehtitle_updated_title, create_linked_biblio => 1 } )->status_is(200)
470
                { %$ehtitle_updated_title, create_linked_biblio => 1 } )
471
            ->status_is(200)
450
            ->json_is( '/publication_title' => 'The journal of writing unit tests :' );
472
            ->json_is( '/publication_title' => 'The journal of writing unit tests :' );
451
473
452
        $biblio->discard_changes;
474
        $biblio->discard_changes;
Lines 502-508 subtest 'delete() tests' => sub { Link Here
502
    $t->delete_ok("//$unauth_userid:$password@/api/v1/erm/eholdings/local/titles/$ehtitle_id")->status_is(403);
524
    $t->delete_ok("//$unauth_userid:$password@/api/v1/erm/eholdings/local/titles/$ehtitle_id")->status_is(403);
503
525
504
    # Delete existing EHolding title
526
    # Delete existing EHolding title
505
    $t->delete_ok("//$userid:$password@/api/v1/erm/eholdings/local/titles/$ehtitle_id")->status_is( 204, 'REST3.2.4' )
527
    $t->delete_ok("//$userid:$password@/api/v1/erm/eholdings/local/titles/$ehtitle_id")
528
        ->status_is( 204, 'REST3.2.4' )
506
        ->content_is( '', 'REST3.3.4' );
529
        ->content_is( '', 'REST3.3.4' );
507
530
508
    # Attempt to delete non-existent EHolding title
531
    # Attempt to delete non-existent EHolding title
(-)a/t/db_dependent/api/v1/erm_licenses.t (-15 / +31 lines)
Lines 88-101 subtest 'list() tests' => sub { Link Here
88
    );
88
    );
89
89
90
    # Filtering works, two licenses sharing vendor_id
90
    # Filtering works, two licenses sharing vendor_id
91
    $t->get_ok( "//$userid:$password@/api/v1/erm/licenses?vendor_id=" . $license->vendor_id )->status_is(200)
91
    $t->get_ok( "//$userid:$password@/api/v1/erm/licenses?vendor_id=" . $license->vendor_id )
92
        ->status_is(200)
92
        ->json_is( [ $license->to_api, $another_license->to_api ] );
93
        ->json_is( [ $license->to_api, $another_license->to_api ] );
93
94
94
    # Attempt to search by name like 'ko'
95
    # Attempt to search by name like 'ko'
95
    $license->delete;
96
    $license->delete;
96
    $another_license->delete;
97
    $another_license->delete;
97
    $license_with_another_vendor_id->delete;
98
    $license_with_another_vendor_id->delete;
98
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/licenses?q=[{"me.name":{"like":"%ko%"}}]~)->status_is(200)
99
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/licenses?q=[{"me.name":{"like":"%ko%"}}]~)
100
        ->status_is(200)
99
        ->json_is( [] );
101
        ->json_is( [] );
100
102
101
    my $license_to_search = $builder->build_object(
103
    my $license_to_search = $builder->build_object(
Lines 108-118 subtest 'list() tests' => sub { Link Here
108
    );
110
    );
109
111
110
    # Search works, searching for name like 'ko'
112
    # Search works, searching for name like 'ko'
111
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/licenses?q=[{"me.name":{"like":"%ko%"}}]~)->status_is(200)
113
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/licenses?q=[{"me.name":{"like":"%ko%"}}]~)
114
        ->status_is(200)
112
        ->json_is( [ $license_to_search->to_api ] );
115
        ->json_is( [ $license_to_search->to_api ] );
113
116
114
    # Warn on unsupported query parameter
117
    # Warn on unsupported query parameter
115
    $t->get_ok("//$userid:$password@/api/v1/erm/licenses?blah=blah")->status_is(400)
118
    $t->get_ok("//$userid:$password@/api/v1/erm/licenses?blah=blah")
119
        ->status_is(400)
116
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
120
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
117
121
118
    # Unauthorized access
122
    # Unauthorized access
Lines 149-161 subtest 'get() tests' => sub { Link Here
149
    my $unauth_userid = $patron->userid;
153
    my $unauth_userid = $patron->userid;
150
154
151
    # This license exists, should get returned
155
    # This license exists, should get returned
152
    $t->get_ok( "//$userid:$password@/api/v1/erm/licenses/" . $license->license_id )->status_is(200)
156
    $t->get_ok( "//$userid:$password@/api/v1/erm/licenses/" . $license->license_id )
157
        ->status_is(200)
153
        ->json_is( $license->to_api );
158
        ->json_is( $license->to_api );
154
159
155
    # Return one license with embed
160
    # Return one license with embed
156
    $t->get_ok(
161
    $t->get_ok(
157
        "//$userid:$password@/api/v1/erm/licenses/" . $license->license_id => { 'x-koha-embed' => 'documents' } )
162
        "//$userid:$password@/api/v1/erm/licenses/" . $license->license_id => { 'x-koha-embed' => 'documents' } )
158
        ->status_is(200)->json_is( { %{ $license->to_api }, documents => [] } );
163
        ->status_is(200)
164
        ->json_is( { %{ $license->to_api }, documents => [] } );
159
165
160
    # Unauthorized access
166
    # Unauthorized access
161
    $t->get_ok( "//$unauth_userid:$password@/api/v1/erm/licenses/" . $license->license_id )->status_is(403);
167
    $t->get_ok( "//$unauth_userid:$password@/api/v1/erm/licenses/" . $license->license_id )->status_is(403);
Lines 165-171 subtest 'get() tests' => sub { Link Here
165
    my $non_existent_id   = $license_to_delete->license_id;
171
    my $non_existent_id   = $license_to_delete->license_id;
166
    $license_to_delete->delete;
172
    $license_to_delete->delete;
167
173
168
    $t->get_ok("//$userid:$password@/api/v1/erm/licenses/$non_existent_id")->status_is(404)
174
    $t->get_ok("//$userid:$password@/api/v1/erm/licenses/$non_existent_id")
175
        ->status_is(404)
169
        ->json_is( '/error' => 'License not found' );
176
        ->json_is( '/error' => 'License not found' );
170
177
171
    $schema->storage->txn_rollback;
178
    $schema->storage->txn_rollback;
Lines 220-226 subtest 'add() tests' => sub { Link Here
220
        ended_on    => undef,
227
        ended_on    => undef,
221
    };
228
    };
222
229
223
    $t->post_ok( "//$userid:$password@/api/v1/erm/licenses" => json => $license_with_invalid_field )->status_is(400)
230
    $t->post_ok( "//$userid:$password@/api/v1/erm/licenses" => json => $license_with_invalid_field )
231
        ->status_is(400)
224
        ->json_is(
232
        ->json_is(
225
        "/errors" => [
233
        "/errors" => [
226
            {
234
            {
Lines 232-243 subtest 'add() tests' => sub { Link Here
232
240
233
    # Authorized attempt to write
241
    # Authorized attempt to write
234
    my $license_id =
242
    my $license_id =
235
        $t->post_ok( "//$userid:$password@/api/v1/erm/licenses" => json => $license )->status_is( 201, 'REST3.2.1' )
243
        $t->post_ok( "//$userid:$password@/api/v1/erm/licenses" => json => $license )
244
        ->status_is( 201, 'REST3.2.1' )
236
        ->header_like(
245
        ->header_like(
237
        Location => qr|^/api/v1/erm/licenses/\d*|,
246
        Location => qr|^/api/v1/erm/licenses/\d*|,
238
        'REST3.4.1'
247
        'REST3.4.1'
239
    )->json_is( '/name' => $license->{name} )->json_is( '/description' => $license->{description} )
248
        )
240
        ->json_is( '/type' => $license->{type} )->json_is( '/status' => $license->{status} )
249
        ->json_is( '/name'        => $license->{name} )
250
        ->json_is( '/description' => $license->{description} )
251
        ->json_is( '/type'        => $license->{type} )
252
        ->json_is( '/status'      => $license->{status} )
241
        ->tx->res->json->{license_id};
253
        ->tx->res->json->{license_id};
242
254
243
    # Authorized attempt to create with null id
255
    # Authorized attempt to create with null id
Lines 300-306 subtest 'update() tests' => sub { Link Here
300
    };
312
    };
301
313
302
    $t->put_ok( "//$userid:$password@/api/v1/erm/licenses/$license_id" => json => $license_with_missing_field )
314
    $t->put_ok( "//$userid:$password@/api/v1/erm/licenses/$license_id" => json => $license_with_missing_field )
303
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
315
        ->status_is(400)
316
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
304
317
305
    # Full object update on PUT
318
    # Full object update on PUT
306
    my $license_with_updated_field = {
319
    my $license_with_updated_field = {
Lines 313-319 subtest 'update() tests' => sub { Link Here
313
    };
326
    };
314
327
315
    $t->put_ok( "//$userid:$password@/api/v1/erm/licenses/$license_id" => json => $license_with_updated_field )
328
    $t->put_ok( "//$userid:$password@/api/v1/erm/licenses/$license_id" => json => $license_with_updated_field )
316
        ->status_is(200)->json_is( '/name' => 'New name' );
329
        ->status_is(200)
330
        ->json_is( '/name' => 'New name' );
317
331
318
    # Authorized attempt to write invalid data
332
    # Authorized attempt to write invalid data
319
    my $license_with_invalid_field = {
333
    my $license_with_invalid_field = {
Lines 327-333 subtest 'update() tests' => sub { Link Here
327
    };
341
    };
328
342
329
    $t->put_ok( "//$userid:$password@/api/v1/erm/licenses/$license_id" => json => $license_with_invalid_field )
343
    $t->put_ok( "//$userid:$password@/api/v1/erm/licenses/$license_id" => json => $license_with_invalid_field )
330
        ->status_is(400)->json_is(
344
        ->status_is(400)
345
        ->json_is(
331
        "/errors" => [
346
        "/errors" => [
332
            {
347
            {
333
                message => "Properties not allowed: blah.",
348
                message => "Properties not allowed: blah.",
Lines 385-391 subtest 'delete() tests' => sub { Link Here
385
    $t->delete_ok("//$unauth_userid:$password@/api/v1/erm/licenses/$license_id")->status_is(403);
400
    $t->delete_ok("//$unauth_userid:$password@/api/v1/erm/licenses/$license_id")->status_is(403);
386
401
387
    # Delete existing license
402
    # Delete existing license
388
    $t->delete_ok("//$userid:$password@/api/v1/erm/licenses/$license_id")->status_is( 204, 'REST3.2.4' )
403
    $t->delete_ok("//$userid:$password@/api/v1/erm/licenses/$license_id")
404
        ->status_is( 204, 'REST3.2.4' )
389
        ->content_is( '', 'REST3.3.4' );
405
        ->content_is( '', 'REST3.3.4' );
390
406
391
    # Attempt to delete non-existent license
407
    # Attempt to delete non-existent license
(-)a/t/db_dependent/api/v1/erm_usage_data_providers.t (-12 / +24 lines)
Lines 104-110 subtest 'list() tests' => sub { Link Here
104
    $usage_data_provider->delete;
104
    $usage_data_provider->delete;
105
    $another_usage_data_provider->delete;
105
    $another_usage_data_provider->delete;
106
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/usage_data_providers?q=[{"me.name":{"like":"%ko%"}}]~)
106
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/usage_data_providers?q=[{"me.name":{"like":"%ko%"}}]~)
107
        ->status_is(200)->json_is( [] );
107
        ->status_is(200)
108
        ->json_is( [] );
108
109
109
    my $usage_data_provider_to_search = $builder->build_object(
110
    my $usage_data_provider_to_search = $builder->build_object(
110
        {
111
        {
Lines 118-127 subtest 'list() tests' => sub { Link Here
118
119
119
    # Search works, searching for name like 'ko'
120
    # Search works, searching for name like 'ko'
120
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/usage_data_providers?q=[{"me.name":{"like":"%ko%"}}]~)
121
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/usage_data_providers?q=[{"me.name":{"like":"%ko%"}}]~)
121
        ->status_is(200)->json_is( [$search_udp_result] );
122
        ->status_is(200)
123
        ->json_is( [$search_udp_result] );
122
124
123
    # Warn on unsupported query parameter
125
    # Warn on unsupported query parameter
124
    $t->get_ok("//$userid:$password@/api/v1/erm/usage_data_providers?blah=blah")->status_is(400)
126
    $t->get_ok("//$userid:$password@/api/v1/erm/usage_data_providers?blah=blah")
127
        ->status_is(400)
125
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
128
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
126
129
127
    # Unauthorized access
130
    # Unauthorized access
Lines 160-166 subtest 'get() tests' => sub { Link Here
160
    # This usage_data_provider exists, should get returned
163
    # This usage_data_provider exists, should get returned
161
    $t->get_ok(
164
    $t->get_ok(
162
        "//$userid:$password@/api/v1/erm/usage_data_providers/" . $usage_data_provider->erm_usage_data_provider_id )
165
        "//$userid:$password@/api/v1/erm/usage_data_providers/" . $usage_data_provider->erm_usage_data_provider_id )
163
        ->status_is(200)->json_is( $usage_data_provider->to_api );
166
        ->status_is(200)
167
        ->json_is( $usage_data_provider->to_api );
164
168
165
    # Unauthorized access
169
    # Unauthorized access
166
    $t->get_ok( "//$unauth_userid:$password@/api/v1/erm/usage_data_providers/"
170
    $t->get_ok( "//$unauth_userid:$password@/api/v1/erm/usage_data_providers/"
Lines 171-177 subtest 'get() tests' => sub { Link Here
171
    my $non_existent_id               = $usage_data_provider_to_delete->erm_usage_data_provider_id;
175
    my $non_existent_id               = $usage_data_provider_to_delete->erm_usage_data_provider_id;
172
    $usage_data_provider_to_delete->delete;
176
    $usage_data_provider_to_delete->delete;
173
177
174
    $t->get_ok("//$userid:$password@/api/v1/erm/usage_data_providers/$non_existent_id")->status_is(404)
178
    $t->get_ok("//$userid:$password@/api/v1/erm/usage_data_providers/$non_existent_id")
179
        ->status_is(404)
175
        ->json_is( '/error' => 'Usage data provider not found' );
180
        ->json_is( '/error' => 'Usage data provider not found' );
176
181
177
    $schema->storage->txn_rollback;
182
    $schema->storage->txn_rollback;
Lines 229-235 subtest 'add() tests' => sub { Link Here
229
234
230
    $t->post_ok(
235
    $t->post_ok(
231
        "//$userid:$password@/api/v1/erm/usage_data_providers" => json => $usage_data_provider_with_invalid_field )
236
        "//$userid:$password@/api/v1/erm/usage_data_providers" => json => $usage_data_provider_with_invalid_field )
232
        ->status_is(400)->json_is(
237
        ->status_is(400)
238
        ->json_is(
233
        "/errors" => [
239
        "/errors" => [
234
            {
240
            {
235
                message => "Properties not allowed: blah.",
241
                message => "Properties not allowed: blah.",
Lines 241-250 subtest 'add() tests' => sub { Link Here
241
    # Authorized attempt to write
247
    # Authorized attempt to write
242
    my $usage_data_provider_id =
248
    my $usage_data_provider_id =
243
        $t->post_ok( "//$userid:$password@/api/v1/erm/usage_data_providers" => json => $usage_data_provider )
249
        $t->post_ok( "//$userid:$password@/api/v1/erm/usage_data_providers" => json => $usage_data_provider )
244
        ->status_is( 201, 'REST3.2.1' )->header_like(
250
        ->status_is( 201, 'REST3.2.1' )
251
        ->header_like(
245
        Location => qr|^/api/v1/erm/usage_data_providers/\d*|,
252
        Location => qr|^/api/v1/erm/usage_data_providers/\d*|,
246
        'REST3.4.1'
253
        'REST3.4.1'
247
    )->json_is( '/name' => $usage_data_provider->{name} )
254
        )
255
        ->json_is( '/name'           => $usage_data_provider->{name} )
248
        ->json_is( '/customer_id'    => $usage_data_provider->{customer_id} )
256
        ->json_is( '/customer_id'    => $usage_data_provider->{customer_id} )
249
        ->json_is( '/requestor_id'   => $usage_data_provider->{requestor_id} )
257
        ->json_is( '/requestor_id'   => $usage_data_provider->{requestor_id} )
250
        ->json_is( '/api_key'        => $usage_data_provider->{api_key} )
258
        ->json_is( '/api_key'        => $usage_data_provider->{api_key} )
Lines 255-266 subtest 'add() tests' => sub { Link Here
255
    # Authorized attempt to create with null id
263
    # Authorized attempt to create with null id
256
    $usage_data_provider->{erm_usage_data_provider_id} = undef;
264
    $usage_data_provider->{erm_usage_data_provider_id} = undef;
257
    $t->post_ok( "//$userid:$password@/api/v1/erm/usage_data_providers" => json => $usage_data_provider )
265
    $t->post_ok( "//$userid:$password@/api/v1/erm/usage_data_providers" => json => $usage_data_provider )
258
        ->status_is(400)->json_has('/errors');
266
        ->status_is(400)
267
        ->json_has('/errors');
259
268
260
    # Authorized attempt to create with existing id
269
    # Authorized attempt to create with existing id
261
    $usage_data_provider->{erm_usage_data_provider_id} = $usage_data_provider_id;
270
    $usage_data_provider->{erm_usage_data_provider_id} = $usage_data_provider_id;
262
    $t->post_ok( "//$userid:$password@/api/v1/erm/usage_data_providers" => json => $usage_data_provider )
271
    $t->post_ok( "//$userid:$password@/api/v1/erm/usage_data_providers" => json => $usage_data_provider )
263
        ->status_is(400)->json_is(
272
        ->status_is(400)
273
        ->json_is(
264
        "/errors" => [
274
        "/errors" => [
265
            {
275
            {
266
                message => "Read-only.",
276
                message => "Read-only.",
Lines 316-322 subtest 'update() tests' => sub { Link Here
316
    };
326
    };
317
327
318
    $t->put_ok( "//$userid:$password@/api/v1/erm/usage_data_providers/$usage_data_provider_id" => json =>
328
    $t->put_ok( "//$userid:$password@/api/v1/erm/usage_data_providers/$usage_data_provider_id" => json =>
319
            $usage_data_provider_with_missing_field )->status_is(400)
329
            $usage_data_provider_with_missing_field )
330
        ->status_is(400)
320
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
331
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
321
332
322
    # Full object update on PUT
333
    # Full object update on PUT
Lines 402-408 subtest 'delete() tests' => sub { Link Here
402
413
403
    # Delete existing usage_data_provider
414
    # Delete existing usage_data_provider
404
    $t->delete_ok("//$userid:$password@/api/v1/erm/usage_data_providers/$usage_data_provider_id")
415
    $t->delete_ok("//$userid:$password@/api/v1/erm/usage_data_providers/$usage_data_provider_id")
405
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
416
        ->status_is( 204, 'REST3.2.4' )
417
        ->content_is( '', 'REST3.3.4' );
406
418
407
    # Attempt to delete non-existent usage_data_provider
419
    # Attempt to delete non-existent usage_data_provider
408
    $t->delete_ok("//$userid:$password@/api/v1/erm/usage_data_providers/$usage_data_provider_id")->status_is(404);
420
    $t->delete_ok("//$userid:$password@/api/v1/erm/usage_data_providers/$usage_data_provider_id")->status_is(404);
(-)a/t/db_dependent/api/v1/erm_usage_titles.t (-4 / +8 lines)
Lines 79-91 subtest 'list() tests' => sub { Link Here
79
    );
79
    );
80
80
81
    # Two usage_titles created, they should both be returned
81
    # Two usage_titles created, they should both be returned
82
    $t->get_ok("//$userid:$password@/api/v1/erm/usage_titles")->status_is(200)
82
    $t->get_ok("//$userid:$password@/api/v1/erm/usage_titles")
83
        ->status_is(200)
83
        ->json_is( [ $usage_title->to_api, $another_usage_title->to_api, ] );
84
        ->json_is( [ $usage_title->to_api, $another_usage_title->to_api, ] );
84
85
85
    # Attempt to search by title like 'ko'
86
    # Attempt to search by title like 'ko'
86
    $usage_title->delete;
87
    $usage_title->delete;
87
    $another_usage_title->delete;
88
    $another_usage_title->delete;
88
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/usage_titles?q=[{"me.title":{"like":"%ko%"}}]~)->status_is(200)
89
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/usage_titles?q=[{"me.title":{"like":"%ko%"}}]~)
90
        ->status_is(200)
89
        ->json_is( [] );
91
        ->json_is( [] );
90
92
91
    my $usage_title_to_search = $builder->build_object(
93
    my $usage_title_to_search = $builder->build_object(
Lines 98-108 subtest 'list() tests' => sub { Link Here
98
    );
100
    );
99
101
100
    # Search works, searching for title like 'ko'
102
    # Search works, searching for title like 'ko'
101
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/usage_titles?q=[{"me.title":{"like":"%ko%"}}]~)->status_is(200)
103
    $t->get_ok(qq~//$userid:$password@/api/v1/erm/usage_titles?q=[{"me.title":{"like":"%ko%"}}]~)
104
        ->status_is(200)
102
        ->json_is( [ $usage_title_to_search->to_api ] );
105
        ->json_is( [ $usage_title_to_search->to_api ] );
103
106
104
    # Warn on unsupported query parameter
107
    # Warn on unsupported query parameter
105
    $t->get_ok("//$userid:$password@/api/v1/erm/usage_titles?blah=blah")->status_is(400)
108
    $t->get_ok("//$userid:$password@/api/v1/erm/usage_titles?blah=blah")
109
        ->status_is(400)
106
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
110
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
107
111
108
    # Unauthorized access
112
    # Unauthorized access
(-)a/t/db_dependent/api/v1/erm_users.t (-4 / +8 lines)
Lines 61-67 subtest 'list() tests' => sub { Link Here
61
    ## Authorized user tests
61
    ## Authorized user tests
62
    # One erm_user created, should get returned
62
    # One erm_user created, should get returned
63
    $librarian->discard_changes;
63
    $librarian->discard_changes;
64
    $t->get_ok("//$userid:$password@/api/v1/erm/users")->status_is(200)
64
    $t->get_ok("//$userid:$password@/api/v1/erm/users")
65
        ->status_is(200)
65
        ->json_is( [ $librarian->to_api( { user => $librarian } ) ] );
66
        ->json_is( [ $librarian->to_api( { user => $librarian } ) ] );
66
67
67
    my $another_erm_user = $builder->build_object(
68
    my $another_erm_user = $builder->build_object(
Lines 72-78 subtest 'list() tests' => sub { Link Here
72
    );
73
    );
73
74
74
    # Two erm_users created, only self is returned without permission to view_any_borrower
75
    # Two erm_users created, only self is returned without permission to view_any_borrower
75
    $t->get_ok("//$userid:$password@/api/v1/erm/users")->status_is(200)
76
    $t->get_ok("//$userid:$password@/api/v1/erm/users")
77
        ->status_is(200)
76
        ->json_is( [ $librarian->to_api( { user => $librarian } ) ] );
78
        ->json_is( [ $librarian->to_api( { user => $librarian } ) ] );
77
79
78
    my $dbh = C4::Context->dbh;
80
    my $dbh = C4::Context->dbh;
Lines 82-93 subtest 'list() tests' => sub { Link Here
82
    );
84
    );
83
85
84
    # Two erm_users created, they should both be returned
86
    # Two erm_users created, they should both be returned
85
    $t->get_ok("//$userid:$password@/api/v1/erm/users")->status_is(200)
87
    $t->get_ok("//$userid:$password@/api/v1/erm/users")
88
        ->status_is(200)
86
        ->json_is(
89
        ->json_is(
87
        [ $librarian->to_api( { user => $librarian } ), $another_erm_user->to_api( { user => $another_erm_user } ) ] );
90
        [ $librarian->to_api( { user => $librarian } ), $another_erm_user->to_api( { user => $another_erm_user } ) ] );
88
91
89
    # Warn on unsupported query parameter
92
    # Warn on unsupported query parameter
90
    $t->get_ok("//$userid:$password@/api/v1/erm/users?blah=blah")->status_is(400)
93
    $t->get_ok("//$userid:$password@/api/v1/erm/users?blah=blah")
94
        ->status_is(400)
91
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
95
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
92
96
93
    my $patron = $builder->build_object(
97
    my $patron = $builder->build_object(
(-)a/t/db_dependent/api/v1/extended_attribute_types.t (-7 / +14 lines)
Lines 73-79 subtest 'list() tests' => sub { Link Here
73
    );
73
    );
74
74
75
    # One additional_field created, should get returned
75
    # One additional_field created, should get returned
76
    $t->get_ok("//$userid:$password@/api/v1/extended_attribute_types")->status_is(200)
76
    $t->get_ok("//$userid:$password@/api/v1/extended_attribute_types")
77
        ->status_is(200)
77
        ->json_is( [ $additional_field->to_api ] );
78
        ->json_is( [ $additional_field->to_api ] );
78
79
79
    my $another_additional_field = $builder->build_object(
80
    my $another_additional_field = $builder->build_object(
Lines 117-131 subtest 'list() tests' => sub { Link Here
117
    );
118
    );
118
119
119
    # Filtering works, two existing additional fields returned for the queried table name
120
    # Filtering works, two existing additional fields returned for the queried table name
120
    $t->get_ok("//$userid:$password@/api/v1/extended_attribute_types?resource_type=invoice")->status_is(200)
121
    $t->get_ok("//$userid:$password@/api/v1/extended_attribute_types?resource_type=invoice")
122
        ->status_is(200)
121
        ->json_is( [ $additional_field->to_api, $another_additional_field->to_api ] );
123
        ->json_is( [ $additional_field->to_api, $another_additional_field->to_api ] );
122
124
123
    # Filtering works for unmapped tablename
125
    # Filtering works for unmapped tablename
124
    $t->get_ok("//$userid:$password@/api/v1/extended_attribute_types?resource_type=subscription")->status_is(200)
126
    $t->get_ok("//$userid:$password@/api/v1/extended_attribute_types?resource_type=subscription")
127
        ->status_is(200)
125
        ->json_is( [ $additional_field_yet_another_different_tablename->to_api ] );
128
        ->json_is( [ $additional_field_yet_another_different_tablename->to_api ] );
126
129
127
    # Warn on unsupported query parameter
130
    # Warn on unsupported query parameter
128
    $t->get_ok("//$userid:$password@/api/v1/extended_attribute_types?blah=blah")->status_is(400)
131
    $t->get_ok("//$userid:$password@/api/v1/extended_attribute_types?blah=blah")
132
        ->status_is(400)
129
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
133
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
130
134
131
    # Unauthorized access
135
    # Unauthorized access
Lines 208-223 subtest 'list_erm() tests' => sub { Link Here
208
    );
212
    );
209
213
210
    # Filtering works, two existing additional fields returned for the queried table name
214
    # Filtering works, two existing additional fields returned for the queried table name
211
    $t->get_ok("//$userid:$password@/api/v1/erm/extended_attribute_types?resource_type=license")->status_is(200)
215
    $t->get_ok("//$userid:$password@/api/v1/erm/extended_attribute_types?resource_type=license")
216
        ->status_is(200)
212
        ->json_is( [ $erm_license_additional_field->to_api ] );
217
        ->json_is( [ $erm_license_additional_field->to_api ] );
213
218
214
    # Cannot retrieve attributes from other tables
219
    # Cannot retrieve attributes from other tables
215
    $t->get_ok("//$userid:$password@/api/v1/erm/extended_attribute_types?resource_type=order")->status_is(400)
220
    $t->get_ok("//$userid:$password@/api/v1/erm/extended_attribute_types?resource_type=order")
221
        ->status_is(400)
216
        ->json_is(
222
        ->json_is(
217
        "/errors" => [ { message => "Not in enum list: license, agreement, package.", path => "/resource_type" } ] );
223
        "/errors" => [ { message => "Not in enum list: license, agreement, package.", path => "/resource_type" } ] );
218
224
219
    # Warn on unsupported query parameter
225
    # Warn on unsupported query parameter
220
    $t->get_ok("//$userid:$password@/api/v1/erm/extended_attribute_types?blah=blah")->status_is(400)
226
    $t->get_ok("//$userid:$password@/api/v1/erm/extended_attribute_types?blah=blah")
227
        ->status_is(400)
221
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
228
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
222
229
223
    # erm only user
230
    # erm only user
(-)a/t/db_dependent/api/v1/holds.t (-53 / +106 lines)
Lines 208-233 subtest "Test endpoints with permission" => sub { Link Here
208
208
209
    $t->get_ok("//$userid_1:$password@/api/v1/holds")->status_is(200)->json_has('/0')->json_has('/1')->json_hasnt('/2');
209
    $t->get_ok("//$userid_1:$password@/api/v1/holds")->status_is(200)->json_has('/0')->json_has('/1')->json_hasnt('/2');
210
210
211
    $t->get_ok("//$userid_1:$password@/api/v1/holds?priority=2")->status_is(200)
211
    $t->get_ok("//$userid_1:$password@/api/v1/holds?priority=2")
212
        ->json_is( '/0/patron_id', $patron_2->borrowernumber )->json_hasnt('/1');
212
        ->status_is(200)
213
        ->json_is( '/0/patron_id', $patron_2->borrowernumber )
214
        ->json_hasnt('/1');
213
215
214
    $t->delete_ok("//$userid_3:$password@/api/v1/holds/$reserve_id")->status_is( 204, 'REST3.2.4' )
216
    $t->delete_ok("//$userid_3:$password@/api/v1/holds/$reserve_id")
217
        ->status_is( 204, 'REST3.2.4' )
215
        ->content_is( '', 'REST3.3.4' );
218
        ->content_is( '', 'REST3.3.4' );
216
219
217
    $t->patch_ok( "//$userid_3:$password@/api/v1/holds/$reserve_id" => json => $patch_data )->status_is(404)
220
    $t->patch_ok( "//$userid_3:$password@/api/v1/holds/$reserve_id" => json => $patch_data )
221
        ->status_is(404)
218
        ->json_has('/error');
222
        ->json_has('/error');
219
223
220
    $t->delete_ok("//$userid_3:$password@/api/v1/holds/$reserve_id")->status_is(404)->json_has('/error');
224
    $t->delete_ok("//$userid_3:$password@/api/v1/holds/$reserve_id")->status_is(404)->json_has('/error');
221
225
222
    $t->get_ok( "//$userid_3:$password@/api/v1/holds?patron_id=" . $patron_1->borrowernumber )->status_is(200)
226
    $t->get_ok( "//$userid_3:$password@/api/v1/holds?patron_id=" . $patron_1->borrowernumber )
227
        ->status_is(200)
223
        ->json_is( [] );
228
        ->json_is( [] );
224
229
225
    my $inexisting_borrowernumber = $patron_2->borrowernumber * 2;
230
    my $inexisting_borrowernumber = $patron_2->borrowernumber * 2;
226
    $t->get_ok("//$userid_1:$password@/api/v1/holds?patron_id=$inexisting_borrowernumber")->status_is(200)
231
    $t->get_ok("//$userid_1:$password@/api/v1/holds?patron_id=$inexisting_borrowernumber")
232
        ->status_is(200)
227
        ->json_is( [] );
233
        ->json_is( [] );
228
234
229
    $t->delete_ok( "//$userid_3:$password@/api/v1/holds/$reserve_id2" => json => "Cancellation reason" )
235
    $t->delete_ok( "//$userid_3:$password@/api/v1/holds/$reserve_id2" => json => "Cancellation reason" )
230
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
236
        ->status_is( 204, 'REST3.2.4' )
237
        ->content_is( '', 'REST3.3.4' );
231
238
232
    # Make sure pickup location checks doesn't get in the middle
239
    # Make sure pickup location checks doesn't get in the middle
233
    my $mock_biblio = Test::MockModule->new('Koha::Biblio');
240
    my $mock_biblio = Test::MockModule->new('Koha::Biblio');
Lines 235-258 subtest "Test endpoints with permission" => sub { Link Here
235
    my $mock_item = Test::MockModule->new('Koha::Item');
242
    my $mock_item = Test::MockModule->new('Koha::Item');
236
    $mock_item->mock( 'pickup_locations', sub { return Koha::Libraries->search } );
243
    $mock_item->mock( 'pickup_locations', sub { return Koha::Libraries->search } );
237
244
238
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )->status_is(201)->json_has('/hold_id')
245
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )
246
        ->status_is(201)
247
        ->json_has('/hold_id')
239
        ->header_is( 'Location' => '/api/v1/holds/' . $t->tx->res->json->{hold_id}, "REST3.4.1" );
248
        ->header_is( 'Location' => '/api/v1/holds/' . $t->tx->res->json->{hold_id}, "REST3.4.1" );
240
249
241
    # Get id from response
250
    # Get id from response
242
    $reserve_id = $t->tx->res->json->{hold_id};
251
    $reserve_id = $t->tx->res->json->{hold_id};
243
252
244
    $t->get_ok( "//$userid_1:$password@/api/v1/holds?patron_id=" . $patron_1->borrowernumber )->status_is(200)
253
    $t->get_ok( "//$userid_1:$password@/api/v1/holds?patron_id=" . $patron_1->borrowernumber )
254
        ->status_is(200)
245
        ->json_is( '/0/hold_id',         $reserve_id )
255
        ->json_is( '/0/hold_id',         $reserve_id )
246
        ->json_is( '/0/expiration_date', output_pref( { dt => $expiration_date, dateformat => 'iso', dateonly => 1 } ) )
256
        ->json_is( '/0/expiration_date', output_pref( { dt => $expiration_date, dateformat => 'iso', dateonly => 1 } ) )
247
        ->json_is( '/0/pickup_library_id', $branchcode );
257
        ->json_is( '/0/pickup_library_id', $branchcode );
248
258
249
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )->status_is(403)
259
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )
260
        ->status_is(403)
250
        ->json_like( '/error', qr/itemAlreadyOnHold/ );
261
        ->json_like( '/error', qr/itemAlreadyOnHold/ );
251
262
252
    $post_data->{biblio_id} = $biblio_2->biblionumber;
263
    $post_data->{biblio_id} = $biblio_2->biblionumber;
253
    $post_data->{item_id}   = $item_2->itemnumber;
264
    $post_data->{item_id}   = $item_2->itemnumber;
254
265
255
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )->status_is(403)
266
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )
267
        ->status_is(403)
256
        ->json_like( '/error', qr/Hold cannot be placed. Reason: tooManyReserves/ );
268
        ->json_like( '/error', qr/Hold cannot be placed. Reason: tooManyReserves/ );
257
269
258
    my $to_delete_patron  = $builder->build_object( { class => 'Koha::Patrons' } );
270
    my $to_delete_patron  = $builder->build_object( { class => 'Koha::Patrons' } );
Lines 261-267 subtest "Test endpoints with permission" => sub { Link Here
261
273
262
    my $tmp_patron_id = $post_data->{patron_id};
274
    my $tmp_patron_id = $post_data->{patron_id};
263
    $post_data->{patron_id} = $deleted_patron_id;
275
    $post_data->{patron_id} = $deleted_patron_id;
264
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )->status_is(400)
276
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )
277
        ->status_is(400)
265
        ->json_is( { error => 'patron_id not found' } );
278
        ->json_is( { error => 'patron_id not found' } );
266
279
267
    # Restore the original patron_id as it is expected by the next subtest
280
    # Restore the original patron_id as it is expected by the next subtest
Lines 279-285 subtest 'Reserves with itemtype' => sub { Link Here
279
        item_type         => $itemtype,
292
        item_type         => $itemtype,
280
    };
293
    };
281
294
282
    $t->delete_ok("//$userid_3:$password@/api/v1/holds/$reserve_id")->status_is( 204, 'REST3.2.4' )
295
    $t->delete_ok("//$userid_3:$password@/api/v1/holds/$reserve_id")
296
        ->status_is( 204, 'REST3.2.4' )
283
        ->content_is( '', 'REST3.3.4' );
297
        ->content_is( '', 'REST3.3.4' );
284
298
285
    # Make sure pickup location checks doesn't get in the middle
299
    # Make sure pickup location checks doesn't get in the middle
Lines 292-299 subtest 'Reserves with itemtype' => sub { Link Here
292
306
293
    $reserve_id = $t->tx->res->json->{hold_id};
307
    $reserve_id = $t->tx->res->json->{hold_id};
294
308
295
    $t->get_ok( "//$userid_1:$password@/api/v1/holds?patron_id=" . $patron_1->borrowernumber )->status_is(200)
309
    $t->get_ok( "//$userid_1:$password@/api/v1/holds?patron_id=" . $patron_1->borrowernumber )
296
        ->json_is( '/0/hold_id', $reserve_id )->json_is( '/0/item_type', $itemtype );
310
        ->status_is(200)
311
        ->json_is( '/0/hold_id',   $reserve_id )
312
        ->json_is( '/0/item_type', $itemtype );
297
};
313
};
298
314
299
subtest 'test AllowHoldDateInFuture' => sub {
315
subtest 'test AllowHoldDateInFuture' => sub {
Lines 325-331 subtest 'test AllowHoldDateInFuture' => sub { Link Here
325
    my $mock_item = Test::MockModule->new('Koha::Item');
341
    my $mock_item = Test::MockModule->new('Koha::Item');
326
    $mock_item->mock( 'pickup_locations', sub { return Koha::Libraries->search } );
342
    $mock_item->mock( 'pickup_locations', sub { return Koha::Libraries->search } );
327
343
328
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )->status_is(201)
344
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )
345
        ->status_is(201)
329
        ->json_is( '/hold_date', output_pref( { dt => $future_hold_date, dateformat => 'iso', dateonly => 1 } ) );
346
        ->json_is( '/hold_date', output_pref( { dt => $future_hold_date, dateformat => 'iso', dateonly => 1 } ) );
330
};
347
};
331
348
Lines 384-390 subtest 'x-koha-override and AllowHoldPolicyOverride tests' => sub { Link Here
384
401
385
    $can_item_be_reserved_result = { status => 'ageRestricted' };
402
    $can_item_be_reserved_result = { status => 'ageRestricted' };
386
403
387
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $post_data )->status_is(403)
404
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $post_data )
405
        ->status_is(403)
388
        ->json_is( '/error' => "Hold cannot be placed. Reason: ageRestricted" );
406
        ->json_is( '/error' => "Hold cannot be placed. Reason: ageRestricted" );
389
407
390
    # x-koha-override doesn't override if AllowHoldPolicyOverride not set
408
    # x-koha-override doesn't override if AllowHoldPolicyOverride not set
Lines 395-401 subtest 'x-koha-override and AllowHoldPolicyOverride tests' => sub { Link Here
395
413
396
    $can_item_be_reserved_result = { status => 'pickupNotInHoldGroup' };
414
    $can_item_be_reserved_result = { status => 'pickupNotInHoldGroup' };
397
415
398
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $post_data )->status_is(403)
416
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $post_data )
417
        ->status_is(403)
399
        ->json_is( '/error' => "Hold cannot be placed. Reason: pickupNotInHoldGroup" );
418
        ->json_is( '/error' => "Hold cannot be placed. Reason: pickupNotInHoldGroup" );
400
419
401
    # x-koha-override overrides the status
420
    # x-koha-override overrides the status
Lines 493-499 subtest 'suspend and resume tests' => sub { Link Here
493
        'Hold suspension has correct end date'
512
        'Hold suspension has correct end date'
494
    );
513
    );
495
514
496
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id . "/suspension" )->status_is( 204, 'REST3.2.4' )
515
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id . "/suspension" )
516
        ->status_is( 204, 'REST3.2.4' )
497
        ->content_is( '', 'REST3.3.4' );
517
        ->content_is( '', 'REST3.3.4' );
498
518
499
    # Pass a an expiration date for the suspension
519
    # Pass a an expiration date for the suspension
Lines 502-513 subtest 'suspend and resume tests' => sub { Link Here
502
            . $hold->id
522
            . $hold->id
503
            . "/suspension" => json =>
523
            . "/suspension" => json =>
504
            { end_date => output_pref( { dt => $date, dateformat => 'iso', dateonly => 1 } ) } )
524
            { end_date => output_pref( { dt => $date, dateformat => 'iso', dateonly => 1 } ) } )
505
        ->status_is( 201, 'Hold suspension created' )->json_is(
525
        ->status_is( 201, 'Hold suspension created' )
526
        ->json_is(
506
        '/end_date',
527
        '/end_date',
507
        output_pref( { dt => $date, dateformat => 'iso', dateonly => 1 } )
528
        output_pref( { dt => $date, dateformat => 'iso', dateonly => 1 } )
508
    )->header_is( Location => "/api/v1/holds/" . $hold->id . "/suspension", 'The Location header is set' );
529
        )->header_is( Location => "/api/v1/holds/" . $hold->id . "/suspension", 'The Location header is set' );
509
530
510
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id . "/suspension" )->status_is( 204, 'REST3.2.4' )
531
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id . "/suspension" )
532
        ->status_is( 204, 'REST3.2.4' )
511
        ->content_is( '', 'REST3.3.4' );
533
        ->content_is( '', 'REST3.3.4' );
512
534
513
    $hold->set_waiting->discard_changes;
535
    $hold->set_waiting->discard_changes;
Lines 693-706 subtest 'PUT /holds/{hold_id}/priority tests' => sub { Link Here
693
715
694
    $t->put_ok( "//$userid_np:$password@/api/v1/holds/" . $hold_3->id . "/priority" => json => 1 )->status_is(403);
716
    $t->put_ok( "//$userid_np:$password@/api/v1/holds/" . $hold_3->id . "/priority" => json => 1 )->status_is(403);
695
717
696
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $hold_3->id . "/priority" => json => 1 )->status_is(200)
718
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $hold_3->id . "/priority" => json => 1 )
719
        ->status_is(200)
697
        ->json_is(1);
720
        ->json_is(1);
698
721
699
    is( $hold_1->discard_changes->priority, 2, 'Priority adjusted correctly' );
722
    is( $hold_1->discard_changes->priority, 2, 'Priority adjusted correctly' );
700
    is( $hold_2->discard_changes->priority, 3, 'Priority adjusted correctly' );
723
    is( $hold_2->discard_changes->priority, 3, 'Priority adjusted correctly' );
701
    is( $hold_3->discard_changes->priority, 1, 'Priority adjusted correctly' );
724
    is( $hold_3->discard_changes->priority, 1, 'Priority adjusted correctly' );
702
725
703
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $hold_3->id . "/priority" => json => 3 )->status_is(200)
726
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $hold_3->id . "/priority" => json => 3 )
727
        ->status_is(200)
704
        ->json_is(3);
728
        ->json_is(3);
705
729
706
    is( $hold_1->discard_changes->priority, 1, 'Priority adjusted correctly' );
730
    is( $hold_1->discard_changes->priority, 1, 'Priority adjusted correctly' );
Lines 880-886 subtest 'add() + can_place_holds() tests' => sub { Link Here
880
        my $hold_id =
904
        my $hold_id =
881
            $t->post_ok(
905
            $t->post_ok(
882
            "//$userid:$password@/api/v1/holds" => { 'x-koha-override' => 'debt_limit' } => json => $post_data )
906
            "//$userid:$password@/api/v1/holds" => { 'x-koha-override' => 'debt_limit' } => json => $post_data )
883
            ->status_is( 201, "Override works for 'debt_limit'" )->tx->res->json->{hold_id};
907
            ->status_is( 201, "Override works for 'debt_limit'" )
908
            ->tx->res->json->{hold_id};
884
909
885
        Koha::Holds->find($hold_id)->delete();
910
        Koha::Holds->find($hold_id)->delete();
886
911
Lines 1003-1009 subtest 'add() + can_place_holds() tests' => sub { Link Here
1003
1028
1004
        my $hold_id = $t->post_ok(
1029
        my $hold_id = $t->post_ok(
1005
            "//$userid:$password@/api/v1/holds" => { 'x-koha-override' => 'hold_limit' } => json => $post_data )
1030
            "//$userid:$password@/api/v1/holds" => { 'x-koha-override' => 'hold_limit' } => json => $post_data )
1006
            ->status_is( 201, "Override works for 'hold_limit'" )->tx->res->json->{hold_id};
1031
            ->status_is( 201, "Override works for 'hold_limit'" )
1032
            ->tx->res->json->{hold_id};
1007
1033
1008
        Koha::Holds->find($hold_id)->delete();
1034
        Koha::Holds->find($hold_id)->delete();
1009
1035
Lines 1283-1302 subtest 'edit() tests' => sub { Link Here
1283
    };
1309
    };
1284
1310
1285
    $t->patch_ok( "//$userid:$password@/api/v1/holds/" . $biblio_hold->id => json => $biblio_hold_data )
1311
    $t->patch_ok( "//$userid:$password@/api/v1/holds/" . $biblio_hold->id => json => $biblio_hold_data )
1286
        ->status_is(400)->json_is( { error => 'The supplied pickup location is not valid' } );
1312
        ->status_is(400)
1313
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1287
1314
1288
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $biblio_hold->id => json => $biblio_hold_data )->status_is(400)
1315
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $biblio_hold->id => json => $biblio_hold_data )
1316
        ->status_is(400)
1289
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1317
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1290
1318
1291
    $biblio_hold->discard_changes;
1319
    $biblio_hold->discard_changes;
1292
    is( $biblio_hold->branchcode, $library_3->branchcode, 'branchcode remains untouched' );
1320
    is( $biblio_hold->branchcode, $library_3->branchcode, 'branchcode remains untouched' );
1293
1321
1294
    $t->patch_ok( "//$userid:$password@/api/v1/holds/"
1322
    $t->patch_ok( "//$userid:$password@/api/v1/holds/"
1295
            . $biblio_hold->id => { 'x-koha-override' => 'any' } => json => $biblio_hold_data )->status_is(200)
1323
            . $biblio_hold->id => { 'x-koha-override' => 'any' } => json => $biblio_hold_data )
1324
        ->status_is(200)
1296
        ->json_has( '/pickup_library_id' => $library_1->id );
1325
        ->json_has( '/pickup_library_id' => $library_1->id );
1297
1326
1298
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1327
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1299
            . $biblio_hold->id => { 'x-koha-override' => 'any' } => json => $biblio_hold_data )->status_is(200)
1328
            . $biblio_hold->id => { 'x-koha-override' => 'any' } => json => $biblio_hold_data )
1329
        ->status_is(200)
1300
        ->json_has( '/pickup_library_id' => $library_1->id );
1330
        ->json_has( '/pickup_library_id' => $library_1->id );
1301
1331
1302
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
1332
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
Lines 1346-1366 subtest 'edit() tests' => sub { Link Here
1346
        priority          => $item_hold_api_data->{priority}
1376
        priority          => $item_hold_api_data->{priority}
1347
    };
1377
    };
1348
1378
1349
    $t->patch_ok( "//$userid:$password@/api/v1/holds/" . $item_hold->id => json => $item_hold_data )->status_is(400)
1379
    $t->patch_ok( "//$userid:$password@/api/v1/holds/" . $item_hold->id => json => $item_hold_data )
1380
        ->status_is(400)
1350
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1381
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1351
1382
1352
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $item_hold->id => json => $item_hold_data )->status_is(400)
1383
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $item_hold->id => json => $item_hold_data )
1384
        ->status_is(400)
1353
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1385
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1354
1386
1355
    $item_hold->discard_changes;
1387
    $item_hold->discard_changes;
1356
    is( $item_hold->branchcode, $library_3->branchcode, 'branchcode remains untouched' );
1388
    is( $item_hold->branchcode, $library_3->branchcode, 'branchcode remains untouched' );
1357
1389
1358
    $t->patch_ok( "//$userid:$password@/api/v1/holds/"
1390
    $t->patch_ok( "//$userid:$password@/api/v1/holds/"
1359
            . $item_hold->id => { 'x-koha-override' => 'any' } => json => $item_hold_data )->status_is(200)
1391
            . $item_hold->id => { 'x-koha-override' => 'any' } => json => $item_hold_data )
1392
        ->status_is(200)
1360
        ->json_has( '/pickup_library_id' => $library_1->id );
1393
        ->json_has( '/pickup_library_id' => $library_1->id );
1361
1394
1362
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1395
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1363
            . $item_hold->id => { 'x-koha-override' => 'any' } => json => $item_hold_data )->status_is(200)
1396
            . $item_hold->id => { 'x-koha-override' => 'any' } => json => $item_hold_data )
1397
        ->status_is(200)
1364
        ->json_has( '/pickup_library_id' => $library_1->id );
1398
        ->json_has( '/pickup_library_id' => $library_1->id );
1365
1399
1366
    $item_hold_data->{pickup_library_id} = $library_2->branchcode;
1400
    $item_hold_data->{pickup_library_id} = $library_2->branchcode;
Lines 1483-1489 subtest 'add() tests' => sub { Link Here
1483
        pickup_library_id => $library_1->branchcode,
1517
        pickup_library_id => $library_1->branchcode,
1484
    };
1518
    };
1485
1519
1486
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $biblio_hold_data )->status_is(400)
1520
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $biblio_hold_data )
1521
        ->status_is(400)
1487
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1522
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1488
1523
1489
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
1524
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
Lines 1512-1518 subtest 'add() tests' => sub { Link Here
1512
        pickup_library_id => $library_1->branchcode,
1547
        pickup_library_id => $library_1->branchcode,
1513
    };
1548
    };
1514
1549
1515
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $biblio_hold_data )->status_is(400)
1550
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $biblio_hold_data )
1551
        ->status_is(400)
1516
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1552
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1517
1553
1518
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
1554
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
Lines 1540-1546 subtest 'add() tests' => sub { Link Here
1540
        pickup_library_id => $library_1->branchcode,
1576
        pickup_library_id => $library_1->branchcode,
1541
    };
1577
    };
1542
1578
1543
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $item_hold_data )->status_is(400)
1579
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $item_hold_data )
1580
        ->status_is(400)
1544
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1581
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1545
1582
1546
    $can_item_be_reserved   = 'notReservable';
1583
    $can_item_be_reserved   = 'notReservable';
Lines 1565-1571 subtest 'add() tests' => sub { Link Here
1565
        }
1602
        }
1566
    );
1603
    );
1567
1604
1568
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $biblio_hold_data )->status_is(400)
1605
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $biblio_hold_data )
1606
        ->status_is(400)
1569
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1607
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1570
1608
1571
    # empty cases
1609
    # empty cases
Lines 1576-1582 subtest 'add() tests' => sub { Link Here
1576
        }
1614
        }
1577
    );
1615
    );
1578
1616
1579
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $item_hold_data )->status_is(400)
1617
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $item_hold_data )
1618
        ->status_is(400)
1580
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1619
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1581
1620
1582
    $schema->storage->txn_rollback;
1621
    $schema->storage->txn_rollback;
Lines 1636-1649 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1636
1675
1637
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1676
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1638
            . $hold->id
1677
            . $hold->id
1639
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )->status_is(200)
1678
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )
1679
        ->status_is(200)
1640
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1680
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1641
1681
1642
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library adjusted correctly' );
1682
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library adjusted correctly' );
1643
1683
1644
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1684
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1645
            . $hold->id
1685
            . $hold->id
1646
            . "/pickup_location" => json => { pickup_library_id => $library_3->branchcode } )->status_is(400)
1686
            . "/pickup_location" => json => { pickup_library_id => $library_3->branchcode } )
1687
        ->status_is(400)
1647
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1688
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1648
1689
1649
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library unchanged' );
1690
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library unchanged' );
Lines 1664-1670 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1664
    # Attempt to use an invalid pickup locations ends in 400
1705
    # Attempt to use an invalid pickup locations ends in 400
1665
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1706
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1666
            . $hold->id
1707
            . $hold->id
1667
            . "/pickup_location" => json => { pickup_library_id => $library_3->branchcode } )->status_is(400)
1708
            . "/pickup_location" => json => { pickup_library_id => $library_3->branchcode } )
1709
        ->status_is(400)
1668
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1710
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1669
1711
1670
    is( $hold->discard_changes->branchcode, $library_1->branchcode, 'pickup library unchanged' );
1712
    is( $hold->discard_changes->branchcode, $library_1->branchcode, 'pickup library unchanged' );
Lines 1675-1681 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1675
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1717
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1676
            . $hold->id
1718
            . $hold->id
1677
            . "/pickup_location" => { 'x-koha-override' => 'any' } => json =>
1719
            . "/pickup_location" => { 'x-koha-override' => 'any' } => json =>
1678
            { pickup_library_id => $library_2->branchcode } )->status_is(200)
1720
            { pickup_library_id => $library_2->branchcode } )
1721
        ->status_is(200)
1679
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1722
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1680
1723
1681
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library changed' );
1724
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library changed' );
Lines 1684-1697 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1684
1727
1685
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1728
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1686
            . $hold->id
1729
            . $hold->id
1687
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )->status_is(200)
1730
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )
1731
        ->status_is(200)
1688
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1732
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1689
1733
1690
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library adjusted correctly' );
1734
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library adjusted correctly' );
1691
1735
1692
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1736
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1693
            . $hold->id
1737
            . $hold->id
1694
            . "/pickup_location" => json => { pickup_library_id => $library_3->branchcode } )->status_is(400)
1738
            . "/pickup_location" => json => { pickup_library_id => $library_3->branchcode } )
1739
        ->status_is(400)
1695
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1740
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1696
1741
1697
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'invalid pickup library not used' );
1742
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'invalid pickup library not used' );
Lines 1699-1705 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1699
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1744
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1700
            . $hold->id
1745
            . $hold->id
1701
            . "/pickup_location" => { 'x-koha-override' => 'any' } => json =>
1746
            . "/pickup_location" => { 'x-koha-override' => 'any' } => json =>
1702
            { pickup_library_id => $library_3->branchcode } )->status_is(400)
1747
            { pickup_library_id => $library_3->branchcode } )
1748
        ->status_is(400)
1703
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1749
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1704
1750
1705
    is(
1751
    is(
Lines 1713-1729 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1713
1759
1714
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1760
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1715
            . $waiting_hold->id
1761
            . $waiting_hold->id
1716
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )->status_is(409)
1762
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )
1763
        ->status_is(409)
1717
        ->json_is( { error => q{Cannot change pickup location}, error_code => 'hold_waiting' } );
1764
        ->json_is( { error => q{Cannot change pickup location}, error_code => 'hold_waiting' } );
1718
1765
1719
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1766
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1720
            . $in_processing_hold->id
1767
            . $in_processing_hold->id
1721
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )->status_is(409)
1768
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )
1769
        ->status_is(409)
1722
        ->json_is( { error => q{Cannot change pickup location}, error_code => 'hold_in_processing' } );
1770
        ->json_is( { error => q{Cannot change pickup location}, error_code => 'hold_in_processing' } );
1723
1771
1724
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1772
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1725
            . $in_transit_hold->id
1773
            . $in_transit_hold->id
1726
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )->status_is(200)
1774
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )
1775
        ->status_is(200)
1727
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1776
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1728
1777
1729
    $schema->storage->txn_rollback;
1778
    $schema->storage->txn_rollback;
Lines 1777-1783 subtest 'delete() tests' => sub { Link Here
1777
        )
1826
        )
1778
    );
1827
    );
1779
1828
1780
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id )->status_is( 204, 'REST3.2.4' )
1829
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id )
1830
        ->status_is( 204, 'REST3.2.4' )
1781
        ->content_is( '', 'REST3.3.4' );
1831
        ->content_is( '', 'REST3.3.4' );
1782
1832
1783
    $hold = Koha::Holds->find(
1833
    $hold = Koha::Holds->find(
Lines 1793-1799 subtest 'delete() tests' => sub { Link Here
1793
    );
1843
    );
1794
1844
1795
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id => { 'x-koha-override' => q{} } )
1845
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id => { 'x-koha-override' => q{} } )
1796
        ->status_is( 204, 'Same behavior if header not set' )->content_is('');
1846
        ->status_is( 204, 'Same behavior if header not set' )
1847
        ->content_is('');
1797
1848
1798
    $hold = Koha::Holds->find(
1849
    $hold = Koha::Holds->find(
1799
        AddReserve(
1850
        AddReserve(
Lines 1809-1815 subtest 'delete() tests' => sub { Link Here
1809
1860
1810
    $t->delete_ok(
1861
    $t->delete_ok(
1811
        "//$userid:$password@/api/v1/holds/" . $hold->id => { 'x-koha-override' => q{cancellation-request-flow} } )
1862
        "//$userid:$password@/api/v1/holds/" . $hold->id => { 'x-koha-override' => q{cancellation-request-flow} } )
1812
        ->status_is( 204, 'Same behavior if header set but hold not waiting' )->content_is('');
1863
        ->status_is( 204, 'Same behavior if header set but hold not waiting' )
1864
        ->content_is('');
1813
1865
1814
    $hold = Koha::Holds->find(
1866
    $hold = Koha::Holds->find(
1815
        AddReserve(
1867
        AddReserve(
Lines 1928-1934 subtest 'Bug 40866: API hold creation with override logs confirmations' => sub { Link Here
1928
    # Create hold with override
1980
    # Create hold with override
1929
    my $hold_id =
1981
    my $hold_id =
1930
        $t->post_ok( "//$userid:$password@/api/v1/holds" => { 'x-koha-override' => 'any' } => json => $post_data )
1982
        $t->post_ok( "//$userid:$password@/api/v1/holds" => { 'x-koha-override' => 'any' } => json => $post_data )
1931
        ->status_is(201)->tx->res->json->{hold_id};
1983
        ->status_is(201)
1984
        ->tx->res->json->{hold_id};
1932
1985
1933
    ok( $hold_id, 'Hold created via API with override' );
1986
    ok( $hold_id, 'Hold created via API with override' );
1934
1987
(-)a/t/db_dependent/api/v1/ill_backends.t (-2 / +4 lines)
Lines 187-197 subtest 'list() tests' => sub { Link Here
187
187
188
    #Check for backend existing statuses
188
    #Check for backend existing statuses
189
    $t->get_ok( "//$userid:$password@/api/v1/ill/backends/Mock" => { 'x-koha-embed' => 'statuses+strings' } )
189
    $t->get_ok( "//$userid:$password@/api/v1/ill/backends/Mock" => { 'x-koha-embed' => 'statuses+strings' } )
190
        ->status_is(200)->json_has( '/statuses', [ $backend_status, $core_status, $alias_status ] );
190
        ->status_is(200)
191
        ->json_has( '/statuses', [ $backend_status, $core_status, $alias_status ] );
191
192
192
    #Check for backend existing statuses of a backend that doesn't exist
193
    #Check for backend existing statuses of a backend that doesn't exist
193
    $t->get_ok( "//$userid:$password@/api/v1/ill/backends/GhostBackend" => { 'x-koha-embed' => 'statuses+strings' } )
194
    $t->get_ok( "//$userid:$password@/api/v1/ill/backends/GhostBackend" => { 'x-koha-embed' => 'statuses+strings' } )
194
        ->status_is(200)->json_hasnt('statuses');
195
        ->status_is(200)
196
        ->json_hasnt('statuses');
195
197
196
    # Unauthorized attempt to list
198
    # Unauthorized attempt to list
197
    $t->get_ok("//$unauth_userid:$password@/api/v1/ill/backends")->status_is(403);
199
    $t->get_ok("//$unauth_userid:$password@/api/v1/ill/backends")->status_is(403);
(-)a/t/db_dependent/api/v1/ill_batches.t (-24 / +50 lines)
Lines 94-104 subtest 'list() tests' => sub { Link Here
94
94
95
    # One batch created, should get returned
95
    # One batch created, should get returned
96
    $t->get_ok( "//$userid:$password@/api/v1/ill/batches?q="
96
    $t->get_ok( "//$userid:$password@/api/v1/ill/batches?q="
97
            . encode_json($query) => { 'x-koha-embed' => '+strings,requests+count,patron,library' } )->status_is(200)
97
            . encode_json($query) => { 'x-koha-embed' => '+strings,requests+count,patron,library' } )
98
        ->json_has( '/0/ill_batch_id', 'Batch ID' )->json_has( '/0/name', 'Batch name' )
98
        ->status_is(200)
99
        ->json_has( '/0/backend',      'Backend name' )->json_has( '/0/patron_id', 'Borrowernumber' )
99
        ->json_has( '/0/ill_batch_id',   'Batch ID' )
100
        ->json_has( '/0/library_id',   'Branchcode' )->json_has( '/0/patron', 'patron embedded' )
100
        ->json_has( '/0/name',           'Batch name' )
101
        ->json_has( '/0/library',      'branch embedded' )->json_has( '/0/requests_count', 'request count' );
101
        ->json_has( '/0/backend',        'Backend name' )
102
        ->json_has( '/0/patron_id',      'Borrowernumber' )
103
        ->json_has( '/0/library_id',     'Branchcode' )
104
        ->json_has( '/0/patron',         'patron embedded' )
105
        ->json_has( '/0/library',        'branch embedded' )
106
        ->json_has( '/0/requests_count', 'request count' );
102
107
103
    # Create a second batch with a different name
108
    # Create a second batch with a different name
104
    my $batch_2 = $builder->build_object( { class => 'Koha::ILL::Batches' } );
109
    my $batch_2 = $builder->build_object( { class => 'Koha::ILL::Batches' } );
Lines 106-114 subtest 'list() tests' => sub { Link Here
106
    $query = { ill_batch_id => [ $batch_1->id, $batch_2->id ] };
111
    $query = { ill_batch_id => [ $batch_1->id, $batch_2->id ] };
107
112
108
    # Two batches created, they should both be returned
113
    # Two batches created, they should both be returned
109
    $t->get_ok( "//$userid:$password@/api/v1/ill/batches?q=" . encode_json($query) )->status_is(200)
114
    $t->get_ok( "//$userid:$password@/api/v1/ill/batches?q=" . encode_json($query) )
110
        ->json_has( '/0', 'has first batch' )->json_is( '/0/ill_batch_id', $batch_1->id )
115
        ->status_is(200)
111
        ->json_has( '/1', 'has second batch' )->json_is( '/1/ill_batch_id', $batch_2->id );
116
        ->json_has( '/0', 'has first batch' )
117
        ->json_is( '/0/ill_batch_id', $batch_1->id )
118
        ->json_has( '/1', 'has second batch' )
119
        ->json_is( '/1/ill_batch_id', $batch_2->id );
112
120
113
    my $patron = $builder->build_object(
121
    my $patron = $builder->build_object(
114
        {
122
        {
Lines 169-179 subtest 'get() tests' => sub { Link Here
169
    my $unauth_userid = $patron->userid;
177
    my $unauth_userid = $patron->userid;
170
178
171
    $t->get_ok( "//$userid:$password@/api/v1/ill/batches/"
179
    $t->get_ok( "//$userid:$password@/api/v1/ill/batches/"
172
            . $batch->id => { 'x-koha-embed' => '+strings,requests+count,patron,library' } )->status_is(200)
180
            . $batch->id => { 'x-koha-embed' => '+strings,requests+count,patron,library' } )
173
        ->json_has( '/ill_batch_id', 'Batch ID' )->json_has( '/name', 'Batch name' )
181
        ->status_is(200)
174
        ->json_has( '/backend',      'Backend name' )->json_has( '/patron_id', 'Borrowernumber' )
182
        ->json_has( '/ill_batch_id',   'Batch ID' )
175
        ->json_has( '/library_id',   'Branchcode' )->json_has( '/patron', 'patron embedded' )
183
        ->json_has( '/name',           'Batch name' )
176
        ->json_has( '/library',      'library embedded' )->json_has( '/requests_count', 'request count' );
184
        ->json_has( '/backend',        'Backend name' )
185
        ->json_has( '/patron_id',      'Borrowernumber' )
186
        ->json_has( '/library_id',     'Branchcode' )
187
        ->json_has( '/patron',         'patron embedded' )
188
        ->json_has( '/library',        'library embedded' )
189
        ->json_has( '/requests_count', 'request count' );
177
190
178
    $t->get_ok( "//$unauth_userid:$password@/api/v1/ill/batches/" . $batch->id )->status_is(403);
191
    $t->get_ok( "//$unauth_userid:$password@/api/v1/ill/batches/" . $batch->id )->status_is(403);
179
192
Lines 181-187 subtest 'get() tests' => sub { Link Here
181
    my $non_existent_id = $batch_to_delete->id;
194
    my $non_existent_id = $batch_to_delete->id;
182
    $batch_to_delete->delete;
195
    $batch_to_delete->delete;
183
196
184
    $t->get_ok("//$userid:$password@/api/v1/ill/batches/$non_existent_id")->status_is(404)
197
    $t->get_ok("//$userid:$password@/api/v1/ill/batches/$non_existent_id")
198
        ->status_is(404)
185
        ->json_is( '/error' => 'ILL batch not found' );
199
        ->json_is( '/error' => 'ILL batch not found' );
186
200
187
    $schema->storage->txn_rollback;
201
    $schema->storage->txn_rollback;
Lines 234-240 subtest 'add() tests' => sub { Link Here
234
        doh => 1
248
        doh => 1
235
    };
249
    };
236
250
237
    $t->post_ok( "//$userid:$password@/api/v1/ill/batches" => json => $batch_with_invalid_field )->status_is(400)
251
    $t->post_ok( "//$userid:$password@/api/v1/ill/batches" => json => $batch_with_invalid_field )
252
        ->status_is(400)
238
        ->json_is(
253
        ->json_is(
239
        "/errors" => [
254
        "/errors" => [
240
            {
255
            {
Lines 248-262 subtest 'add() tests' => sub { Link Here
248
    my $batch_id =
263
    my $batch_id =
249
        $t->post_ok(
264
        $t->post_ok(
250
        "//$userid:$password@/api/v1/ill/batches" => { 'x-koha-embed' => '+strings,requests+count,patron,library' } =>
265
        "//$userid:$password@/api/v1/ill/batches" => { 'x-koha-embed' => '+strings,requests+count,patron,library' } =>
251
            json => $batch_metadata )->status_is(201)->json_is( '/name' => $batch_metadata->{name} )
266
            json => $batch_metadata )
252
        ->json_is( '/backend'    => $batch_metadata->{backend} )->json_is( '/patron_id' => $librarian->borrowernumber )
267
        ->status_is(201)
253
        ->json_is( '/library_id' => $batch_metadata->{library_id} )->json_is( '/status_code' => $batch_status->code )
268
        ->json_is( '/name'        => $batch_metadata->{name} )
254
        ->json_has('/patron')->json_has('/_strings/status_code')->json_has('/_strings/library_id')
269
        ->json_is( '/backend'     => $batch_metadata->{backend} )
255
        ->json_has('/requests_count')->json_has('/library');
270
        ->json_is( '/patron_id'   => $librarian->borrowernumber )
271
        ->json_is( '/library_id'  => $batch_metadata->{library_id} )
272
        ->json_is( '/status_code' => $batch_status->code )
273
        ->json_has('/patron')
274
        ->json_has('/_strings/status_code')
275
        ->json_has('/_strings/library_id')
276
        ->json_has('/requests_count')
277
        ->json_has('/library');
256
278
257
    # Authorized attempt to create with null id
279
    # Authorized attempt to create with null id
258
    $batch_metadata->{id} = undef;
280
    $batch_metadata->{id} = undef;
259
    $t->post_ok( "//$userid:$password@/api/v1/ill/batches" => json => $batch_metadata )->status_is(400)
281
    $t->post_ok( "//$userid:$password@/api/v1/ill/batches" => json => $batch_metadata )
282
        ->status_is(400)
260
        ->json_has('/errors');
283
        ->json_has('/errors');
261
284
262
    $schema->storage->txn_rollback;
285
    $schema->storage->txn_rollback;
Lines 306-312 subtest 'update() tests' => sub { Link Here
306
    };
329
    };
307
330
308
    $t->put_ok( "//$userid:$password@/api/v1/ill/batches/$batch_id" => json => $batch_with_missing_field )
331
    $t->put_ok( "//$userid:$password@/api/v1/ill/batches/$batch_id" => json => $batch_with_missing_field )
309
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
332
        ->status_is(400)
333
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
310
334
311
    # Full object update on PUT
335
    # Full object update on PUT
312
    my $batch_with_updated_field = {
336
    my $batch_with_updated_field = {
Lines 318-324 subtest 'update() tests' => sub { Link Here
318
    };
342
    };
319
343
320
    $t->put_ok( "//$userid:$password@/api/v1/ill/batches/$batch_id" => json => $batch_with_updated_field )
344
    $t->put_ok( "//$userid:$password@/api/v1/ill/batches/$batch_id" => json => $batch_with_updated_field )
321
        ->status_is(200)->json_is( '/name' => 'Master Ploo Koon' );
345
        ->status_is(200)
346
        ->json_is( '/name' => 'Master Ploo Koon' );
322
347
323
    # Authorized attempt to write invalid data
348
    # Authorized attempt to write invalid data
324
    my $batch_with_invalid_field = {
349
    my $batch_with_invalid_field = {
Lines 328-334 subtest 'update() tests' => sub { Link Here
328
    };
353
    };
329
354
330
    $t->put_ok( "//$userid:$password@/api/v1/ill/batches/$batch_id" => json => $batch_with_invalid_field )
355
    $t->put_ok( "//$userid:$password@/api/v1/ill/batches/$batch_id" => json => $batch_with_invalid_field )
331
        ->status_is(400)->json_is(
356
        ->status_is(400)
357
        ->json_is(
332
        "/errors" => [
358
        "/errors" => [
333
            {
359
            {
334
                message => "Properties not allowed: doh.",
360
                message => "Properties not allowed: doh.",
(-)a/t/db_dependent/api/v1/ill_batchstatuses.t (-13 / +30 lines)
Lines 71-78 subtest 'list() tests' => sub { Link Here
71
    );
71
    );
72
72
73
    # One batch created, should get returned
73
    # One batch created, should get returned
74
    $t->get_ok("//$userid:$password@/api/v1/ill/batchstatuses")->status_is(200)->json_has( '/0/id', 'ID' )
74
    $t->get_ok("//$userid:$password@/api/v1/ill/batchstatuses")
75
        ->json_has( '/0/name', 'Name' )->json_has( '/0/code', 'Code' )->json_has( '/0/is_system', 'is_system' );
75
        ->status_is(200)
76
        ->json_has( '/0/id',        'ID' )
77
        ->json_has( '/0/name',      'Name' )
78
        ->json_has( '/0/code',      'Code' )
79
        ->json_has( '/0/is_system', 'is_system' );
76
80
77
    $schema->storage->txn_rollback;
81
    $schema->storage->txn_rollback;
78
};
82
};
Lines 114-121 subtest 'get() tests' => sub { Link Here
114
    $patron->set_password( { password => $password, skip_validation => 1 } );
118
    $patron->set_password( { password => $password, skip_validation => 1 } );
115
    my $unauth_userid = $patron->userid;
119
    my $unauth_userid = $patron->userid;
116
120
117
    $t->get_ok( "//$userid:$password@/api/v1/ill/batchstatuses/" . $status->code )->status_is(200)
121
    $t->get_ok( "//$userid:$password@/api/v1/ill/batchstatuses/" . $status->code )
118
        ->json_has( '/id',        'ID' )->json_has( '/name', 'Name' )->json_has( '/code', 'Code' )
122
        ->status_is(200)
123
        ->json_has( '/id',        'ID' )
124
        ->json_has( '/name',      'Name' )
125
        ->json_has( '/code',      'Code' )
119
        ->json_has( '/is_system', 'is_system' );
126
        ->json_has( '/is_system', 'is_system' );
120
127
121
    $t->get_ok( "//$unauth_userid:$password@/api/v1/ill/batchstatuses/" . $status->id )->status_is(403);
128
    $t->get_ok( "//$unauth_userid:$password@/api/v1/ill/batchstatuses/" . $status->id )->status_is(403);
Lines 124-130 subtest 'get() tests' => sub { Link Here
124
    my $non_existent_code = $status_to_delete->code;
131
    my $non_existent_code = $status_to_delete->code;
125
    $status_to_delete->delete;
132
    $status_to_delete->delete;
126
133
127
    $t->get_ok("//$userid:$password@/api/v1/ill/batchstatuses/$non_existent_code")->status_is(404)
134
    $t->get_ok("//$userid:$password@/api/v1/ill/batchstatuses/$non_existent_code")
135
        ->status_is(404)
128
        ->json_is( '/error' => 'ILL batch status not found' );
136
        ->json_is( '/error' => 'ILL batch status not found' );
129
137
130
    $schema->storage->txn_rollback;
138
    $schema->storage->txn_rollback;
Lines 171-177 subtest 'add() tests' => sub { Link Here
171
    };
179
    };
172
180
173
    $t->post_ok( "//$userid:$password@/api/v1/ill/batchstatuses" => json => $status_with_invalid_field )
181
    $t->post_ok( "//$userid:$password@/api/v1/ill/batchstatuses" => json => $status_with_invalid_field )
174
        ->status_is(400)->json_is(
182
        ->status_is(400)
183
        ->json_is(
175
        "/errors" => [
184
        "/errors" => [
176
            {
185
            {
177
                message => "Properties not allowed: doh.",
186
                message => "Properties not allowed: doh.",
Lines 181-194 subtest 'add() tests' => sub { Link Here
181
        );
190
        );
182
191
183
    # Authorized attempt to write
192
    # Authorized attempt to write
184
    $t->post_ok( "//$userid:$password@/api/v1/ill/batchstatuses" => json => $status_metadata )->status_is(201)
193
    $t->post_ok( "//$userid:$password@/api/v1/ill/batchstatuses" => json => $status_metadata )
185
        ->json_has( '/id',        'ID' )->json_has( '/name', 'Name' )->json_has( '/code', 'Code' )
194
        ->status_is(201)
195
        ->json_has( '/id',        'ID' )
196
        ->json_has( '/name',      'Name' )
197
        ->json_has( '/code',      'Code' )
186
        ->json_has( '/is_system', 'is_system' )
198
        ->json_has( '/is_system', 'is_system' )
187
        ->header_is( 'Location' => '/api/v1/ill/batchstatuses/' . $t->tx->res->json->{code}, "REST3.4.1" );
199
        ->header_is( 'Location' => '/api/v1/ill/batchstatuses/' . $t->tx->res->json->{code}, "REST3.4.1" );
188
200
189
    # Authorized attempt to create with null id
201
    # Authorized attempt to create with null id
190
    $status_metadata->{id} = undef;
202
    $status_metadata->{id} = undef;
191
    $t->post_ok( "//$userid:$password@/api/v1/ill/batchstatuses" => json => $status_metadata )->status_is(400)
203
    $t->post_ok( "//$userid:$password@/api/v1/ill/batchstatuses" => json => $status_metadata )
204
        ->status_is(400)
192
        ->json_has('/errors');
205
        ->json_has('/errors');
193
206
194
    $schema->storage->txn_rollback;
207
    $schema->storage->txn_rollback;
Lines 232-238 subtest 'update() tests' => sub { Link Here
232
    };
245
    };
233
246
234
    $t->put_ok( "//$userid:$password@/api/v1/ill/batchstatuses/$status_code" => json => $status_with_missing_field )
247
    $t->put_ok( "//$userid:$password@/api/v1/ill/batchstatuses/$status_code" => json => $status_with_missing_field )
235
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
248
        ->status_is(400)
249
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
236
250
237
    # Full object update on PUT
251
    # Full object update on PUT
238
    my $status_with_updated_field = {
252
    my $status_with_updated_field = {
Lines 242-248 subtest 'update() tests' => sub { Link Here
242
    };
256
    };
243
257
244
    $t->put_ok( "//$userid:$password@/api/v1/ill/batchstatuses/$status_code" => json => $status_with_updated_field )
258
    $t->put_ok( "//$userid:$password@/api/v1/ill/batchstatuses/$status_code" => json => $status_with_updated_field )
245
        ->status_is(200)->json_is( '/name' => 'Master Ploo Koon' );
259
        ->status_is(200)
260
        ->json_is( '/name' => 'Master Ploo Koon' );
246
261
247
    # Authorized attempt to write invalid data
262
    # Authorized attempt to write invalid data
248
    my $status_with_invalid_field = {
263
    my $status_with_invalid_field = {
Lines 252-258 subtest 'update() tests' => sub { Link Here
252
    };
267
    };
253
268
254
    $t->put_ok( "//$userid:$password@/api/v1/ill/batchstatuses/$status_code" => json => $status_with_invalid_field )
269
    $t->put_ok( "//$userid:$password@/api/v1/ill/batchstatuses/$status_code" => json => $status_with_invalid_field )
255
        ->status_is(400)->json_is(
270
        ->status_is(400)
271
        ->json_is(
256
        "/errors" => [
272
        "/errors" => [
257
            {
273
            {
258
                message => "Properties not allowed: doh.",
274
                message => "Properties not allowed: doh.",
Lines 319-325 subtest 'delete() tests' => sub { Link Here
319
335
320
    $t->delete_ok( "//$userid:$password@/api/v1/ill/batchstatuses/" . $non_system_status->code )->status_is(404);
336
    $t->delete_ok( "//$userid:$password@/api/v1/ill/batchstatuses/" . $non_system_status->code )->status_is(404);
321
337
322
    $t->delete_ok( "//$userid:$password@/api/v1/ill/batchstatuses/" . $system_status->code )->status_is(400)
338
    $t->delete_ok( "//$userid:$password@/api/v1/ill/batchstatuses/" . $system_status->code )
339
        ->status_is(400)
323
        ->json_is( "/errors" => [ { message => "ILL batch status cannot be deleted" } ] );
340
        ->json_is( "/errors" => [ { message => "ILL batch status cannot be deleted" } ] );
324
341
325
    $schema->storage->txn_rollback;
342
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/ill_requests.t (-12 / +24 lines)
Lines 181-187 subtest 'list() tests' => sub { Link Here
181
    # Two requests exist with status 'REQ', expect them to be returned
181
    # Two requests exist with status 'REQ', expect them to be returned
182
    # One of which also has a status_alias, expect that to be in that request's body
182
    # One of which also has a status_alias, expect that to be in that request's body
183
    $t->get_ok( "//$userid:$password@/api/v1/ill/requests?q=$status_query" => { "x-koha-embed" => "+strings" } )
183
    $t->get_ok( "//$userid:$password@/api/v1/ill/requests?q=$status_query" => { "x-koha-embed" => "+strings" } )
184
        ->status_is(200)->json_is(
184
        ->status_is(200)
185
        ->json_is(
185
        [
186
        [
186
            { _strings => { status => $response_status }, %{ $req_1->to_api( { user => $librarian } ) } },
187
            { _strings => { status => $response_status }, %{ $req_1->to_api( { user => $librarian } ) } },
187
            {
188
            {
Lines 193-199 subtest 'list() tests' => sub { Link Here
193
194
194
    # One request with status_alias 'print_copy' exists, expect that to be returned
195
    # One request with status_alias 'print_copy' exists, expect that to be returned
195
    $t->get_ok( "//$userid:$password@/api/v1/ill/requests?q=$status_alias_query" => { "x-koha-embed" => "+strings" } )
196
    $t->get_ok( "//$userid:$password@/api/v1/ill/requests?q=$status_alias_query" => { "x-koha-embed" => "+strings" } )
196
        ->status_is(200)->json_is(
197
        ->status_is(200)
198
        ->json_is(
197
        [
199
        [
198
            {
200
            {
199
                _strings => { status => $response_status, status_av => $response_status_av },
201
                _strings => { status => $response_status, status_av => $response_status_av },
Lines 206-212 subtest 'list() tests' => sub { Link Here
206
    my $patron_query = encode_json( { borrowernumber => $patron->borrowernumber } );
208
    my $patron_query = encode_json( { borrowernumber => $patron->borrowernumber } );
207
209
208
    # One request related to $patron, make sure it comes back
210
    # One request related to $patron, make sure it comes back
209
    $t->get_ok( "//$userid:$password@/api/v1/ill/requests" => { "x-koha-embed" => "patron" } )->status_is(200)
211
    $t->get_ok( "//$userid:$password@/api/v1/ill/requests" => { "x-koha-embed" => "patron" } )
212
        ->status_is(200)
210
        ->json_has( '/0/patron', $patron->to_api( { user => $librarian } ) );
213
        ->json_has( '/0/patron', $patron->to_api( { user => $librarian } ) );
211
214
212
    # x-koha-embed: comments
215
    # x-koha-embed: comments
Lines 223-229 subtest 'list() tests' => sub { Link Here
223
    );
226
    );
224
227
225
    # Make sure comments come back
228
    # Make sure comments come back
226
    $t->get_ok( "//$userid:$password@/api/v1/ill/requests" => { "x-koha-embed" => "comments" } )->status_is(200)
229
    $t->get_ok( "//$userid:$password@/api/v1/ill/requests" => { "x-koha-embed" => "comments" } )
230
        ->status_is(200)
227
        ->json_has( '/0/comments', $comment_text );
231
        ->json_has( '/0/comments', $comment_text );
228
232
229
    # x-koha-embed: id_prefix
233
    # x-koha-embed: id_prefix
Lines 234-256 subtest 'list() tests' => sub { Link Here
234
    $config->set_always( 'getPrefixes', $id_prefix );
238
    $config->set_always( 'getPrefixes', $id_prefix );
235
239
236
    # Make sure id_prefix comes back
240
    # Make sure id_prefix comes back
237
    $t->get_ok( "//$userid:$password@/api/v1/ill/requests" => { "x-koha-embed" => "id_prefix" } )->status_is(200)
241
    $t->get_ok( "//$userid:$password@/api/v1/ill/requests" => { "x-koha-embed" => "id_prefix" } )
242
        ->status_is(200)
238
        ->json_has( '/0/id_prefix', $id_prefix );
243
        ->json_has( '/0/id_prefix', $id_prefix );
239
244
240
    # ILLHiddenRequestStatuses syspref
245
    # ILLHiddenRequestStatuses syspref
241
    # Hide 'REQ', expect to return just 1 'RET'
246
    # Hide 'REQ', expect to return just 1 'RET'
242
    t::lib::Mocks::mock_preference( 'ILLHiddenRequestStatuses', 'REQ' );
247
    t::lib::Mocks::mock_preference( 'ILLHiddenRequestStatuses', 'REQ' );
243
    $t->get_ok("//$userid:$password@/api/v1/ill/requests")->status_is(200)
248
    $t->get_ok("//$userid:$password@/api/v1/ill/requests")
249
        ->status_is(200)
244
        ->json_is( [ $ret->to_api( { user => $librarian } ) ] );
250
        ->json_is( [ $ret->to_api( { user => $librarian } ) ] );
245
251
246
    # Hide 'RET', expect to return 2 'REQ'
252
    # Hide 'RET', expect to return 2 'REQ'
247
    t::lib::Mocks::mock_preference( 'ILLHiddenRequestStatuses', 'RET' );
253
    t::lib::Mocks::mock_preference( 'ILLHiddenRequestStatuses', 'RET' );
248
    $t->get_ok("//$userid:$password@/api/v1/ill/requests?_order_by=staff_notes")->status_is(200)
254
    $t->get_ok("//$userid:$password@/api/v1/ill/requests?_order_by=staff_notes")
255
        ->status_is(200)
249
        ->json_is( [ $req_1->to_api( { user => $librarian } ), $req_2->to_api( { user => $librarian } ) ] );
256
        ->json_is( [ $req_1->to_api( { user => $librarian } ), $req_2->to_api( { user => $librarian } ) ] );
250
257
251
    # Status code
258
    # Status code
252
    # Warn on unsupported query parameter
259
    # Warn on unsupported query parameter
253
    $t->get_ok("//$userid:$password@/api/v1/ill/requests?request_blah=blah")->status_is(400)
260
    $t->get_ok("//$userid:$password@/api/v1/ill/requests?request_blah=blah")
261
        ->status_is(400)
254
        ->json_is( [ { path => '/query/request_blah', message => 'Malformed query string' } ] );
262
        ->json_is( [ { path => '/query/request_blah', message => 'Malformed query string' } ] );
255
263
256
    # Unauthorized attempt to list
264
    # Unauthorized attempt to list
Lines 311-320 subtest 'public_patron_list() tests' => sub { Link Here
311
    my $patron_2_id     = $patron_2->id;
319
    my $patron_2_id     = $patron_2->id;
312
320
313
    # No requests yet, expect empty for both
321
    # No requests yet, expect empty for both
314
    $t->get_ok("//$patron_1_userid:$password@/api/v1/public/patrons/$patron_1_id/ill/requests")->status_is(200)
322
    $t->get_ok("//$patron_1_userid:$password@/api/v1/public/patrons/$patron_1_id/ill/requests")
323
        ->status_is(200)
315
        ->json_is( [] );
324
        ->json_is( [] );
316
325
317
    $t->get_ok("//$patron_2_userid:$password@/api/v1/public/patrons/$patron_2_id/ill/requests")->status_is(200)
326
    $t->get_ok("//$patron_2_userid:$password@/api/v1/public/patrons/$patron_2_id/ill/requests")
327
        ->status_is(200)
318
        ->json_is( [] );
328
        ->json_is( [] );
319
329
320
    for ( 0 .. 25 ) {
330
    for ( 0 .. 25 ) {
Lines 333-344 subtest 'public_patron_list() tests' => sub { Link Here
333
    }
343
    }
334
344
335
    # Other user should not see anything
345
    # Other user should not see anything
336
    $t->get_ok("//$patron_2_userid:$password@/api/v1/public/patrons/$patron_2_id/ill/requests")->status_is(200)
346
    $t->get_ok("//$patron_2_userid:$password@/api/v1/public/patrons/$patron_2_id/ill/requests")
347
        ->status_is(200)
337
        ->json_is( [] );
348
        ->json_is( [] );
338
349
339
    # Staff notes hidden in the public API
350
    # Staff notes hidden in the public API
340
    $t->get_ok("//$patron_1_userid:$password@/api/v1/public/patrons/$patron_1_id/ill/requests?_per_page=-1")
351
    $t->get_ok("//$patron_1_userid:$password@/api/v1/public/patrons/$patron_1_id/ill/requests?_per_page=-1")
341
        ->status_is(200)->json_is(
352
        ->status_is(200)
353
        ->json_is(
342
        '/0/staff_notes' => undef,
354
        '/0/staff_notes' => undef,
343
        );
355
        );
344
356
(-)a/t/db_dependent/api/v1/import_batch_profiles.t (-6 / +12 lines)
Lines 96-103 subtest 'list profiles' => sub { Link Here
96
96
97
    my $uid = $patron->userid;
97
    my $uid = $patron->userid;
98
98
99
    $t->get_ok("//$uid:$pwd@/api/v1/import_batch_profiles?_order_by=+name")->status_is(200)
99
    $t->get_ok("//$uid:$pwd@/api/v1/import_batch_profiles?_order_by=+name")
100
        ->json_is( '/0/name', $ibp1->name )->json_is( '/1/name', $ibp2->name );
100
        ->status_is(200)
101
        ->json_is( '/0/name', $ibp1->name )
102
        ->json_is( '/1/name', $ibp2->name );
101
103
102
    $schema->storage->txn_rollback;
104
    $schema->storage->txn_rollback;
103
105
Lines 135-142 subtest 'add() tests' => sub { Link Here
135
        overlay_action => 'overlay_action'
137
        overlay_action => 'overlay_action'
136
    };
138
    };
137
139
138
    $t->post_ok( "//$uid:$pwd@/api/v1/import_batch_profiles", json => $post_data )->status_is(201)
140
    $t->post_ok( "//$uid:$pwd@/api/v1/import_batch_profiles", json => $post_data )
139
        ->json_has('/profile_id')->json_is( '/name', $post_data->{name} )
141
        ->status_is(201)
142
        ->json_has('/profile_id')
143
        ->json_is( '/name',           $post_data->{name} )
140
        ->json_is( '/overlay_action', $post_data->{overlay_action} )
144
        ->json_is( '/overlay_action', $post_data->{overlay_action} )
141
        ->header_is( 'Location', '/api/v1/import_batch_profiles/' . $t->tx->res->json->{profile_id}, 'REST3.4.1' );
145
        ->header_is( 'Location', '/api/v1/import_batch_profiles/' . $t->tx->res->json->{profile_id}, 'REST3.4.1' );
142
146
Lines 175-182 subtest 'edit profile' => sub { Link Here
175
179
176
    my $post_data = { name => 'theProfile' };
180
    my $post_data = { name => 'theProfile' };
177
181
178
    $t->put_ok( "//$uid:$pwd@/api/v1/import_batch_profiles/" . $ibp->id, json => $post_data )->status_is(200)
182
    $t->put_ok( "//$uid:$pwd@/api/v1/import_batch_profiles/" . $ibp->id, json => $post_data )
179
        ->json_is( '/profile_id', $ibp->id )->json_is( '/name', $post_data->{name} );
183
        ->status_is(200)
184
        ->json_is( '/profile_id', $ibp->id )
185
        ->json_is( '/name',       $post_data->{name} );
180
186
181
    $ibp->discard_changes;
187
    $ibp->discard_changes;
182
188
(-)a/t/db_dependent/api/v1/import_record_matches.t (-1 / +2 lines)
Lines 102-108 subtest 'import record matches tests' => sub { Link Here
102
            . $del_import_batch_id
102
            . $del_import_batch_id
103
            . "/records/"
103
            . "/records/"
104
            . $del_match_id
104
            . $del_match_id
105
            . "/matches/chosen" => json => { candidate_match_id => $match_1->candidate_match_id } )->status_is(404)
105
            . "/matches/chosen" => json => { candidate_match_id => $match_1->candidate_match_id } )
106
        ->status_is(404)
106
        ->json_is( '/error' => "Match not found" );
107
        ->json_is( '/error' => "Match not found" );
107
108
108
    # Valid, authorised update
109
    # Valid, authorised update
(-)a/t/db_dependent/api/v1/item_groups.t (-3 / +6 lines)
Lines 161-167 subtest 'update() tests' => sub { Link Here
161
161
162
    # Authorized attempt
162
    # Authorized attempt
163
    $t->put_ok( "//$auth_userid:$password@/api/v1/biblios/$biblio_id/item_groups/$item_group_id" => json =>
163
    $t->put_ok( "//$auth_userid:$password@/api/v1/biblios/$biblio_id/item_groups/$item_group_id" => json =>
164
            { description => "Vol A" } )->status_is( 200, 'REST3.2.1' )
164
            { description => "Vol A" } )
165
        ->status_is( 200, 'REST3.2.1' )
165
        ->json_has( '/description' => "Vol A", 'REST3.3.3' );
166
        ->json_has( '/description' => "Vol A", 'REST3.3.3' );
166
167
167
    # Invalid biblio id
168
    # Invalid biblio id
Lines 209-215 subtest 'delete() tests' => sub { Link Here
209
    my $item_groupid = $item_group->id;
210
    my $item_groupid = $item_group->id;
210
211
211
    $t->delete_ok("//$auth_userid:$password@/api/v1/biblios/$biblio_id/item_groups/$item_groupid")
212
    $t->delete_ok("//$auth_userid:$password@/api/v1/biblios/$biblio_id/item_groups/$item_groupid")
212
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
213
        ->status_is( 204, 'REST3.2.4' )
214
        ->content_is( '', 'REST3.3.4' );
213
215
214
    # Unauthorized attempt to delete
216
    # Unauthorized attempt to delete
215
    $t->delete_ok("//$unauth_userid:$password@/api/v1/biblios/$biblio_id/item_groups/$item_groupid")->status_is(403);
217
    $t->delete_ok("//$unauth_userid:$password@/api/v1/biblios/$biblio_id/item_groups/$item_groupid")->status_is(403);
Lines 270-276 subtest 'volume items add() + delete() tests' => sub { Link Here
270
    is( scalar(@items), 2, 'Item group now has two items' );
272
    is( scalar(@items), 2, 'Item group now has two items' );
271
273
272
    $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id/item_groups/$item_groupid/items/$item_1_id")
274
    $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id/item_groups/$item_groupid/items/$item_1_id")
273
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
275
        ->status_is( 204, 'REST3.2.4' )
276
        ->content_is( '', 'REST3.3.4' );
274
277
275
    @items = $item_group->items;
278
    @items = $item_group->items;
276
    is( scalar(@items), 1, 'Item group now has one item' );
279
    is( scalar(@items), 1, 'Item group now has one item' );
(-)a/t/db_dependent/api/v1/item_types.t (-4 / +10 lines)
Lines 112-123 subtest 'list() tests' => sub { Link Here
112
112
113
    ## Authorized user tests
113
    ## Authorized user tests
114
    my $query = encode_json( { item_type_id => $item_type->id } );
114
    my $query = encode_json( { item_type_id => $item_type->id } );
115
    $t->get_ok("//$userid:$password@/api/v1/item_types?q=$query")->status_is(200)->json_has('/0')
115
    $t->get_ok("//$userid:$password@/api/v1/item_types?q=$query")
116
        ->json_is( '/0/description', $item_type->description )->json_hasnt('/0/translated_descriptions');
116
        ->status_is(200)
117
        ->json_has('/0')
118
        ->json_is( '/0/description', $item_type->description )
119
        ->json_hasnt('/0/translated_descriptions');
117
120
118
    $t->get_ok( "//$userid:$password@/api/v1/item_types?q=$query" => { 'x-koha-embed' => 'translated_descriptions' } )
121
    $t->get_ok( "//$userid:$password@/api/v1/item_types?q=$query" => { 'x-koha-embed' => 'translated_descriptions' } )
119
        ->status_is(200)->json_has('/0')->json_is( '/0/description', $item_type->description )
122
        ->status_is(200)
120
        ->json_has('/0/translated_descriptions')->json_is(
123
        ->json_has('/0')
124
        ->json_is( '/0/description', $item_type->description )
125
        ->json_has('/0/translated_descriptions')
126
        ->json_is(
121
        '/0/translated_descriptions',
127
        '/0/translated_descriptions',
122
        [
128
        [
123
            { lang => 'en',    translation => 'English word "test"' },
129
            { lang => 'en',    translation => 'English word "test"' },
(-)a/t/db_dependent/api/v1/items.t (-23 / +47 lines)
Lines 73-79 subtest 'list() tests' => sub { Link Here
73
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
73
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
74
    my $userid = $nonprivilegedpatron->userid;
74
    my $userid = $nonprivilegedpatron->userid;
75
75
76
    $t->get_ok("//$userid:$password@/api/v1/items")->status_is(403)
76
    $t->get_ok("//$userid:$password@/api/v1/items")
77
        ->status_is(403)
77
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
78
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
78
79
79
    $patron->set_password( { password => $password, skip_validation => 1 } );
80
    $patron->set_password( { password => $password, skip_validation => 1 } );
Lines 85-100 subtest 'list() tests' => sub { Link Here
85
86
86
    is( $response_count, 10, 'The API returns 10 items' );
87
    is( $response_count, 10, 'The API returns 10 items' );
87
88
88
    $t->get_ok( "//$userid:$password@/api/v1/items?external_id=" . $item->barcode )->status_is(200)
89
    $t->get_ok( "//$userid:$password@/api/v1/items?external_id=" . $item->barcode )
90
        ->status_is(200)
89
        ->json_is( '' => [ $item->to_api ], 'REST3.3.2' );
91
        ->json_is( '' => [ $item->to_api ], 'REST3.3.2' );
90
92
91
    $t->get_ok( "//$userid:$password@/api/v1/items?external_id=" . $item->barcode => { 'x-koha-embed' => 'biblio' } )
93
    $t->get_ok( "//$userid:$password@/api/v1/items?external_id=" . $item->barcode => { 'x-koha-embed' => 'biblio' } )
92
        ->status_is(200)->json_is( '' => [ { %{ $item->to_api }, biblio => $item->biblio->to_api } ], 'REST3.3.2' );
94
        ->status_is(200)
95
        ->json_is( '' => [ { %{ $item->to_api }, biblio => $item->biblio->to_api } ], 'REST3.3.2' );
93
96
94
    my $barcode = $item->barcode;
97
    my $barcode = $item->barcode;
95
    $item->delete;
98
    $item->delete;
96
99
97
    $t->get_ok( "//$userid:$password@/api/v1/items?external_id=" . $item->barcode )->status_is(200)
100
    $t->get_ok( "//$userid:$password@/api/v1/items?external_id=" . $item->barcode )
101
        ->status_is(200)
98
        ->json_is( '' => [] );
102
        ->json_is( '' => [] );
99
103
100
    $schema->storage->txn_rollback;
104
    $schema->storage->txn_rollback;
Lines 277-295 subtest 'get() tests' => sub { Link Here
277
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
281
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
278
    my $userid = $nonprivilegedpatron->userid;
282
    my $userid = $nonprivilegedpatron->userid;
279
283
280
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )->status_is(403)
284
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )
285
        ->status_is(403)
281
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
286
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
282
287
283
    $patron->set_password( { password => $password, skip_validation => 1 } );
288
    $patron->set_password( { password => $password, skip_validation => 1 } );
284
    $userid = $patron->userid;
289
    $userid = $patron->userid;
285
290
286
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )->status_is( 200, 'REST3.2.2' )
291
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )
292
        ->status_is( 200, 'REST3.2.2' )
287
        ->json_is( '' => $item->to_api, 'REST3.3.2' );
293
        ->json_is( '' => $item->to_api, 'REST3.3.2' );
288
294
289
    my $non_existent_code = $item->itemnumber;
295
    my $non_existent_code = $item->itemnumber;
290
    $item->delete;
296
    $item->delete;
291
297
292
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $non_existent_code )->status_is(404)
298
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $non_existent_code )
299
        ->status_is(404)
293
        ->json_is( '/error' => 'Item not found' );
300
        ->json_is( '/error' => 'Item not found' );
294
301
295
    t::lib::Mocks::mock_preference( 'item-level_itypes', 0 );
302
    t::lib::Mocks::mock_preference( 'item-level_itypes', 0 );
Lines 300-312 subtest 'get() tests' => sub { Link Here
300
307
301
    isnt( $biblio->itemtype, $itype->itemtype, "Test biblio level itemtype and item level itemtype do not match" );
308
    isnt( $biblio->itemtype, $itype->itemtype, "Test biblio level itemtype and item level itemtype do not match" );
302
309
303
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )->status_is( 200, 'REST3.2.2' )
310
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )
311
        ->status_is( 200, 'REST3.2.2' )
304
        ->json_is( '/item_type_id'           => $itype->itemtype,  'item-level_itypes:0' )
312
        ->json_is( '/item_type_id'           => $itype->itemtype,  'item-level_itypes:0' )
305
        ->json_is( '/effective_item_type_id' => $biblio->itemtype, 'item-level_itypes:0' );
313
        ->json_is( '/effective_item_type_id' => $biblio->itemtype, 'item-level_itypes:0' );
306
314
307
    t::lib::Mocks::mock_preference( 'item-level_itypes', 1 );
315
    t::lib::Mocks::mock_preference( 'item-level_itypes', 1 );
308
316
309
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )->status_is( 200, 'REST3.2.2' )
317
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )
318
        ->status_is( 200, 'REST3.2.2' )
310
        ->json_is( '/item_type_id'           => $itype->itemtype, 'item-level_itype:1' )
319
        ->json_is( '/item_type_id'           => $itype->itemtype, 'item-level_itype:1' )
311
        ->json_is( '/effective_item_type_id' => $itype->itemtype, 'item-level_itypes:1' );
320
        ->json_is( '/effective_item_type_id' => $itype->itemtype, 'item-level_itypes:1' );
312
321
Lines 315-341 subtest 'get() tests' => sub { Link Here
315
    $itype->notforloan(2)->store();
324
    $itype->notforloan(2)->store();
316
    $item->notforloan(1)->store();
325
    $item->notforloan(1)->store();
317
326
318
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )->status_is( 200, 'REST3.2.2' )
327
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )
328
        ->status_is( 200, 'REST3.2.2' )
319
        ->json_is( '/not_for_loan_status'           => 1, 'not_for_loan_status is 1' )
329
        ->json_is( '/not_for_loan_status'           => 1, 'not_for_loan_status is 1' )
320
        ->json_is( '/effective_not_for_loan_status' => 1, 'effective_not_for_loan_status picks up item level' );
330
        ->json_is( '/effective_not_for_loan_status' => 1, 'effective_not_for_loan_status picks up item level' );
321
331
322
    $item->notforloan(0)->store();
332
    $item->notforloan(0)->store();
323
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )->status_is( 200, 'REST3.2.2' )
333
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )
324
        ->json_is( '/not_for_loan_status' => 0, 'not_for_loan_status is 0' )->json_is(
334
        ->status_is( 200, 'REST3.2.2' )
335
        ->json_is( '/not_for_loan_status' => 0, 'not_for_loan_status is 0' )
336
        ->json_is(
325
        '/effective_not_for_loan_status' => 2,
337
        '/effective_not_for_loan_status' => 2,
326
        'effective_not_for_loan_status now picks up itemtype level - item-level_itypes:1'
338
        'effective_not_for_loan_status now picks up itemtype level - item-level_itypes:1'
327
        );
339
        );
328
340
329
    $itype->notforloan(0)->store();
341
    $itype->notforloan(0)->store();
330
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )->status_is( 200, 'REST3.2.2' )
342
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )
331
        ->json_is( '/not_for_loan_status' => 0, 'not_for_loan_status is 0' )->json_is(
343
        ->status_is( 200, 'REST3.2.2' )
344
        ->json_is( '/not_for_loan_status' => 0, 'not_for_loan_status is 0' )
345
        ->json_is(
332
        '/effective_not_for_loan_status' => 0,
346
        '/effective_not_for_loan_status' => 0,
333
        'effective_not_for_loan_status now picks up itemtype level and falls back to 0 because undef'
347
        'effective_not_for_loan_status now picks up itemtype level and falls back to 0 because undef'
334
        );
348
        );
335
349
336
    t::lib::Mocks::mock_preference( 'item-level_itypes', 0 );
350
    t::lib::Mocks::mock_preference( 'item-level_itypes', 0 );
337
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )->status_is( 200, 'REST3.2.2' )
351
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->itemnumber )
338
        ->json_is( '/not_for_loan_status' => 0, 'not_for_loan_status is 0' )->json_is(
352
        ->status_is( 200, 'REST3.2.2' )
353
        ->json_is( '/not_for_loan_status' => 0, 'not_for_loan_status is 0' )
354
        ->json_is(
339
        '/effective_not_for_loan_status' => 3,
355
        '/effective_not_for_loan_status' => 3,
340
        'effective_not_for_loan_status now picks up itemtype level - item-level_itypes:0'
356
        'effective_not_for_loan_status now picks up itemtype level - item-level_itypes:0'
341
        );
357
        );
Lines 416-422 subtest 'delete() tests' => sub { Link Here
416
432
417
    $expected_error = 'unknown_error';
433
    $expected_error = 'unknown_error';
418
    $t->delete_ok( "//$userid:$password@/api/v1/items/" . $item->id )
434
    $t->delete_ok( "//$userid:$password@/api/v1/items/" . $item->id )
419
        ->status_is( 500, 'unhandled error case generated default unhandled exception message' )->json_is(
435
        ->status_is( 500, 'unhandled error case generated default unhandled exception message' )
436
        ->json_is(
420
        {
437
        {
421
            error      => 'Something went wrong, check Koha logs for details.',
438
            error      => 'Something went wrong, check Koha logs for details.',
422
            error_code => 'internal_server_error',
439
            error_code => 'internal_server_error',
Lines 425-431 subtest 'delete() tests' => sub { Link Here
425
442
426
    $fail = 0;
443
    $fail = 0;
427
444
428
    $t->delete_ok( "//$userid:$password@/api/v1/items/" . $item->id )->status_is( 204, 'REST3.2.4' )
445
    $t->delete_ok( "//$userid:$password@/api/v1/items/" . $item->id )
446
        ->status_is( 204, 'REST3.2.4' )
429
        ->content_is( '', 'REST3.3.4' );
447
        ->content_is( '', 'REST3.3.4' );
430
448
431
    $t->delete_ok( "//$userid:$password@/api/v1/items/" . $item->id )->status_is(404);
449
    $t->delete_ok( "//$userid:$password@/api/v1/items/" . $item->id )->status_is(404);
Lines 548-554 subtest 'pickup_locations() tests' => sub { Link Here
548
                . "patron_id="
566
                . "patron_id="
549
                . $patron->id
567
                . $patron->id
550
                . "&_order_by=marc_org_code"
568
                . "&_order_by=marc_org_code"
551
                . "&_per_page=1" )->json_is( [$library_1_api] )
569
                . "&_per_page=1" )
570
            ->json_is( [$library_1_api] )
552
            ->header_is( 'X-Total-Count',      '4', '4 is the count for libraries with pickup_location=1' )
571
            ->header_is( 'X-Total-Count',      '4', '4 is the count for libraries with pickup_location=1' )
553
            ->header_is( 'X-Base-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
572
            ->header_is( 'X-Base-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
554
            ->header_unlike( 'Link', qr|rel="prev"| )
573
            ->header_unlike( 'Link', qr|rel="prev"| )
Lines 579-586 subtest 'pickup_locations() tests' => sub { Link Here
579
                . "patron_id="
598
                . "patron_id="
580
                . $patron->id
599
                . $patron->id
581
                . "&_order_by=marc_org_code"
600
                . "&_order_by=marc_org_code"
582
                . "&_per_page=1" )->json_is( [$library_1_api] )->header_is( 'X-Total-Count', '2' )
601
                . "&_per_page=1" )
583
            ->header_is( 'X-Base-Total-Count', '2' )->header_unlike( 'Link', qr|rel="prev"| )
602
            ->json_is( [$library_1_api] )
603
            ->header_is( 'X-Total-Count',      '2' )
604
            ->header_is( 'X-Base-Total-Count', '2' )
605
            ->header_unlike( 'Link', qr|rel="prev"| )
584
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1.*)>\; rel="next"# )
606
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1.*)>\; rel="next"# )
585
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=1.*|_page=1.*\&_per_page=1).*>\; rel="first"# )
607
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=1.*|_page=1.*\&_per_page=1).*>\; rel="first"# )
586
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1).*>\; rel="last"# );
608
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1).*>\; rel="last"# );
Lines 592-603 subtest 'pickup_locations() tests' => sub { Link Here
592
614
593
    $t->get_ok(
615
    $t->get_ok(
594
        "//$userid:$password@/api/v1/items/" . $item->id . "/pickup_locations?" . "patron_id=" . $deleted_patron_id )
616
        "//$userid:$password@/api/v1/items/" . $item->id . "/pickup_locations?" . "patron_id=" . $deleted_patron_id )
595
        ->status_is(400)->json_is( '/error' => 'Patron not found' );
617
        ->status_is(400)
618
        ->json_is( '/error' => 'Patron not found' );
596
619
597
    $item->delete;
620
    $item->delete;
598
621
599
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->id . "/pickup_locations?" . "patron_id=" . $patron->id )
622
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $item->id . "/pickup_locations?" . "patron_id=" . $patron->id )
600
        ->status_is(404)->json_is( '/error' => 'Item not found' );
623
        ->status_is(404)
624
        ->json_is( '/error' => 'Item not found' );
601
625
602
    $schema->storage->txn_rollback;
626
    $schema->storage->txn_rollback;
603
};
627
};
(-)a/t/db_dependent/api/v1/items/bundled_items.t (-2 / +4 lines)
Lines 51-57 subtest 'bundled_items()' => sub { Link Here
51
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
51
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
52
    my $userid = $nonprivilegedpatron->userid;
52
    my $userid = $nonprivilegedpatron->userid;
53
53
54
    $t->get_ok("//$userid:$password@/api/v1/items/$itemnumber/bundled_items")->status_is(403)
54
    $t->get_ok("//$userid:$password@/api/v1/items/$itemnumber/bundled_items")
55
        ->status_is(403)
55
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
56
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
56
57
57
    $patron->set_password( { password => $password, skip_validation => 1 } );
58
    $patron->set_password( { password => $password, skip_validation => 1 } );
Lines 130-136 subtest 'add_to_bundle' => sub { Link Here
130
        marc_link     => 0
131
        marc_link     => 0
131
    };
132
    };
132
133
133
    $t->post_ok( "//$userid:$password@/api/v1/items/$itemnumber/bundled_items" => json => $link )->status_is(403)
134
    $t->post_ok( "//$userid:$password@/api/v1/items/$itemnumber/bundled_items" => json => $link )
135
        ->status_is(403)
134
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
136
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
135
137
136
    $patron->set_password( { password => $password, skip_validation => 1 } );
138
    $patron->set_password( { password => $password, skip_validation => 1 } );
(-)a/t/db_dependent/api/v1/jobs.t (-5 / +11 lines)
Lines 106-115 my $job_current = $builder->build_object( Link Here
106
);
106
);
107
107
108
{
108
{
109
    $t->get_ok("//$superlibrarian_userid:$password@/api/v1/jobs")->status_is(200)
109
    $t->get_ok("//$superlibrarian_userid:$password@/api/v1/jobs")
110
        ->status_is(200)
110
        ->json_is( [ $job->to_api, $job_current->to_api ] );
111
        ->json_is( [ $job->to_api, $job_current->to_api ] );
111
112
112
    $t->get_ok("//$superlibrarian_userid:$password@/api/v1/jobs?only_current=1")->status_is(200)
113
    $t->get_ok("//$superlibrarian_userid:$password@/api/v1/jobs?only_current=1")
114
        ->status_is(200)
113
        ->json_is( [ $job_current->to_api ] );
115
        ->json_is( [ $job_current->to_api ] );
114
116
115
    $t->get_ok("//$librarian_userid:$password@/api/v1/jobs")->status_is(200)->json_is( [] );
117
    $t->get_ok("//$librarian_userid:$password@/api/v1/jobs")->status_is(200)->json_is( [] );
Lines 124-130 my $job_current = $builder->build_object( Link Here
124
}
126
}
125
127
126
{
128
{
127
    $t->get_ok( "//$superlibrarian_userid:$password@/api/v1/jobs/" . $job->id )->status_is(200)
129
    $t->get_ok( "//$superlibrarian_userid:$password@/api/v1/jobs/" . $job->id )
130
        ->status_is(200)
128
        ->json_is( $job->to_api );
131
        ->json_is( $job->to_api );
129
132
130
    $t->get_ok( "//$librarian_userid:$password@/api/v1/jobs/" . $job->id )->status_is(200)->json_is( $job->to_api );
133
    $t->get_ok( "//$librarian_userid:$password@/api/v1/jobs/" . $job->id )->status_is(200)->json_is( $job->to_api );
Lines 135-141 my $job_current = $builder->build_object( Link Here
135
138
136
{
139
{
137
    $job->delete;
140
    $job->delete;
138
    $t->get_ok( "//$superlibrarian_userid:$password@/api/v1/jobs/" . $job->id )->status_is(404)
141
    $t->get_ok( "//$superlibrarian_userid:$password@/api/v1/jobs/" . $job->id )
142
        ->status_is(404)
139
        ->json_is( '/error' => 'Job not found' );
143
        ->json_is( '/error' => 'Job not found' );
140
}
144
}
141
145
Lines 187-193 subtest 'finished jobs' => sub { Link Here
187
191
188
    $job->finish()->discard_changes();
192
    $job->finish()->discard_changes();
189
193
190
    $t->get_ok( "//$userid:$password@/api/v1/jobs/" . $job->id )->status_is(200)->json_is( $job->to_api )
194
    $t->get_ok( "//$userid:$password@/api/v1/jobs/" . $job->id )
195
        ->status_is(200)
196
        ->json_is( $job->to_api )
191
        ->json_is( '/data' => undef );
197
        ->json_is( '/data' => undef );
192
198
193
    $schema->storage->txn_rollback;
199
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/libraries.t (-21 / +44 lines)
Lines 104-110 subtest 'list() tests' => sub { Link Here
104
    };
104
    };
105
105
106
    # Warn on unsupported query parameter
106
    # Warn on unsupported query parameter
107
    $t->get_ok("//$userid:$password@/api/v1/libraries?library_blah=blah")->status_is(400)
107
    $t->get_ok("//$userid:$password@/api/v1/libraries?library_blah=blah")
108
        ->status_is(400)
108
        ->json_is( [ { path => '/query/library_blah', message => 'Malformed query string' } ] );
109
        ->json_is( [ { path => '/query/library_blah', message => 'Malformed query string' } ] );
109
110
110
    $schema->storage->txn_rollback;
111
    $schema->storage->txn_rollback;
Lines 127-137 subtest 'get() tests' => sub { Link Here
127
    $patron->set_password( { password => $password, skip_validation => 1 } );
128
    $patron->set_password( { password => $password, skip_validation => 1 } );
128
    my $userid = $patron->userid;
129
    my $userid = $patron->userid;
129
130
130
    $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode )->status_is( 200, 'REST3.2.2' )
131
    $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode )
132
        ->status_is( 200, 'REST3.2.2' )
131
        ->json_is( '' => $library->to_api, 'REST3.3.2' );
133
        ->json_is( '' => $library->to_api, 'REST3.3.2' );
132
134
133
    $t->get_ok( "//$userid:$password@/api/v1/libraries/"
135
    $t->get_ok( "//$userid:$password@/api/v1/libraries/"
134
            . $library->branchcode => { 'x-koha-embed' => 'cash_registers,desks' } )->status_is(200)
136
            . $library->branchcode => { 'x-koha-embed' => 'cash_registers,desks' } )
137
        ->status_is(200)
135
        ->json_is( { %{ $library->to_api }, desks => [], cash_registers => [] } );
138
        ->json_is( { %{ $library->to_api }, desks => [], cash_registers => [] } );
136
139
137
    my $desk = $builder->build_object( { class => 'Koha::Desks', value => { branchcode => $library->id } } );
140
    my $desk = $builder->build_object( { class => 'Koha::Desks', value => { branchcode => $library->id } } );
Lines 139-152 subtest 'get() tests' => sub { Link Here
139
        $builder->build_object( { class => 'Koha::Cash::Registers', value => { branch => $library->id } } );
142
        $builder->build_object( { class => 'Koha::Cash::Registers', value => { branch => $library->id } } );
140
143
141
    $t->get_ok( "//$userid:$password@/api/v1/libraries/"
144
    $t->get_ok( "//$userid:$password@/api/v1/libraries/"
142
            . $library->branchcode => { 'x-koha-embed' => 'cash_registers,desks' } )->status_is(200)
145
            . $library->branchcode => { 'x-koha-embed' => 'cash_registers,desks' } )
146
        ->status_is(200)
143
        ->json_is(
147
        ->json_is(
144
        { %{ $library->to_api }, desks => [ $desk->to_api ], cash_registers => [ $cash_register->to_api ] } );
148
        { %{ $library->to_api }, desks => [ $desk->to_api ], cash_registers => [ $cash_register->to_api ] } );
145
149
146
    my $non_existent_code = $library->branchcode;
150
    my $non_existent_code = $library->branchcode;
147
    $library->delete;
151
    $library->delete;
148
152
149
    $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $non_existent_code )->status_is(404)
153
    $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $non_existent_code )
154
        ->status_is(404)
150
        ->json_is( '/error' => 'Library not found' );
155
        ->json_is( '/error' => 'Library not found' );
151
156
152
    $schema->storage->txn_rollback;
157
    $schema->storage->txn_rollback;
Lines 188-194 subtest 'add() tests' => sub { Link Here
188
    my $library_with_invalid_field = {%$library};
193
    my $library_with_invalid_field = {%$library};
189
    $library_with_invalid_field->{'branchinvalid'} = 'Library invalid';
194
    $library_with_invalid_field->{'branchinvalid'} = 'Library invalid';
190
195
191
    $t->post_ok( "//$auth_userid:$password@/api/v1/libraries" => json => $library_with_invalid_field )->status_is(400)
196
    $t->post_ok( "//$auth_userid:$password@/api/v1/libraries" => json => $library_with_invalid_field )
197
        ->status_is(400)
192
        ->json_is(
198
        ->json_is(
193
        "/errors" => [
199
        "/errors" => [
194
            {
200
            {
Lines 199-205 subtest 'add() tests' => sub { Link Here
199
        );
205
        );
200
206
201
    # Authorized attempt to write
207
    # Authorized attempt to write
202
    $t->post_ok( "//$auth_userid:$password@/api/v1/libraries" => json => $library )->status_is( 201, 'REST3.2.1' )
208
    $t->post_ok( "//$auth_userid:$password@/api/v1/libraries" => json => $library )
209
        ->status_is( 201, 'REST3.2.1' )
203
        ->json_is( '' => $library, 'REST3.3.1' )
210
        ->json_is( '' => $library, 'REST3.3.1' )
204
        ->header_is( Location => '/api/v1/libraries/' . $library->{library_id}, 'REST3.4.1' );
211
        ->header_is( Location => '/api/v1/libraries/' . $library->{library_id}, 'REST3.4.1' );
205
212
Lines 209-222 subtest 'add() tests' => sub { Link Here
209
    # Authorized attempt to create with null id
216
    # Authorized attempt to create with null id
210
    $library->{library_id} = undef;
217
    $library->{library_id} = undef;
211
218
212
    $t->post_ok( "//$auth_userid:$password@/api/v1/libraries" => json => $library )->status_is(400)
219
    $t->post_ok( "//$auth_userid:$password@/api/v1/libraries" => json => $library )
220
        ->status_is(400)
213
        ->json_has('/errors');
221
        ->json_has('/errors');
214
222
215
    # Authorized attempt to create with existing id
223
    # Authorized attempt to create with existing id
216
    $library->{library_id} = $library_id;
224
    $library->{library_id} = $library_id;
217
225
218
    warning_like {
226
    warning_like {
219
        $t->post_ok( "//$auth_userid:$password@/api/v1/libraries" => json => $library )->status_is(409)
227
        $t->post_ok( "//$auth_userid:$password@/api/v1/libraries" => json => $library )
228
            ->status_is(409)
220
            ->json_has( '/error' => "Fails when trying to add an existing library_id" )
229
            ->json_has( '/error' => "Fails when trying to add an existing library_id" )
221
            ->json_like( '/conflict' => qr/(branches\.)?PRIMARY/ );
230
            ->json_like( '/conflict' => qr/(branches\.)?PRIMARY/ );
222
    }
231
    }
Lines 262-268 subtest 'update() tests' => sub { Link Here
262
    };
271
    };
263
272
264
    $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_missing_field )
273
    $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_missing_field )
265
        ->status_is(400)->json_has( "/errors" => [ { message => "Missing property.", path => "/body/address2" } ] );
274
        ->status_is(400)
275
        ->json_has( "/errors" => [ { message => "Missing property.", path => "/body/address2" } ] );
266
276
267
    my $deleted_library            = $builder->build_object( { class => 'Koha::Libraries' } );
277
    my $deleted_library            = $builder->build_object( { class => 'Koha::Libraries' } );
268
    my $library_with_updated_field = $deleted_library->to_api;
278
    my $library_with_updated_field = $deleted_library->to_api;
Lines 270-283 subtest 'update() tests' => sub { Link Here
270
    $deleted_library->delete;
280
    $deleted_library->delete;
271
281
272
    $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_updated_field )
282
    $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_updated_field )
273
        ->status_is( 200, 'REST3.2.1' )->json_is( '' => $library_with_updated_field, 'REST3.3.3' );
283
        ->status_is( 200, 'REST3.2.1' )
284
        ->json_is( '' => $library_with_updated_field, 'REST3.3.3' );
274
285
275
    # Authorized attempt to write invalid data
286
    # Authorized attempt to write invalid data
276
    my $library_with_invalid_field = {%$library_with_updated_field};
287
    my $library_with_invalid_field = {%$library_with_updated_field};
277
    $library_with_invalid_field->{'branchinvalid'} = 'Library invalid';
288
    $library_with_invalid_field->{'branchinvalid'} = 'Library invalid';
278
289
279
    $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_invalid_field )
290
    $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_invalid_field )
280
        ->status_is(400)->json_is(
291
        ->status_is(400)
292
        ->json_is(
281
        "/errors" => [
293
        "/errors" => [
282
            {
294
            {
283
                message => "Properties not allowed: branchinvalid.",
295
                message => "Properties not allowed: branchinvalid.",
Lines 322-328 subtest 'delete() tests' => sub { Link Here
322
    # Unauthorized attempt to delete
334
    # Unauthorized attempt to delete
323
    $t->delete_ok("//$unauth_userid:$password@/api/v1/libraries/$library_id")->status_is(403);
335
    $t->delete_ok("//$unauth_userid:$password@/api/v1/libraries/$library_id")->status_is(403);
324
336
325
    $t->delete_ok("//$auth_userid:$password@/api/v1/libraries/$library_id")->status_is( 204, 'REST3.2.4' )
337
    $t->delete_ok("//$auth_userid:$password@/api/v1/libraries/$library_id")
338
        ->status_is( 204, 'REST3.2.4' )
326
        ->content_is( '', 'REST3.3.4' );
339
        ->content_is( '', 'REST3.3.4' );
327
340
328
    $t->delete_ok("//$auth_userid:$password@/api/v1/libraries/$library_id")->status_is(404);
341
    $t->delete_ok("//$auth_userid:$password@/api/v1/libraries/$library_id")->status_is(404);
Lines 349-355 subtest 'list_desks() tests' => sub { Link Here
349
362
350
    t::lib::Mocks::mock_preference( 'UseCirculationDesks', 0 );
363
    t::lib::Mocks::mock_preference( 'UseCirculationDesks', 0 );
351
364
352
    $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode . "/desks" )->status_is(404)
365
    $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode . "/desks" )
366
        ->status_is(404)
353
        ->json_is( '/error' => q{Feature disabled} );
367
        ->json_is( '/error' => q{Feature disabled} );
354
368
355
    my $non_existent_code = $library->branchcode;
369
    my $non_existent_code = $library->branchcode;
Lines 357-370 subtest 'list_desks() tests' => sub { Link Here
357
371
358
    t::lib::Mocks::mock_preference( 'UseCirculationDesks', 1 );
372
    t::lib::Mocks::mock_preference( 'UseCirculationDesks', 1 );
359
373
360
    $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $non_existent_code . "/desks" )->status_is(404)
374
    $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $non_existent_code . "/desks" )
375
        ->status_is(404)
361
        ->json_is( '/error' => 'Library not found' );
376
        ->json_is( '/error' => 'Library not found' );
362
377
363
    my $desk_1 = $builder->build_object( { class => 'Koha::Desks', value => { branchcode => $library->id } } );
378
    my $desk_1 = $builder->build_object( { class => 'Koha::Desks', value => { branchcode => $library->id } } );
364
    my $desk_2 = $builder->build_object( { class => 'Koha::Desks', value => { branchcode => $library->id } } );
379
    my $desk_2 = $builder->build_object( { class => 'Koha::Desks', value => { branchcode => $library->id } } );
365
380
366
    my $res = $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode . "/desks" )->status_is(200)
381
    my $res =
367
        ->json_is( '/0/desk_id' => $desk_1->id )->json_is( '/1/desk_id' => $desk_2->id )->tx->res->json;
382
        $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode . "/desks" )
383
        ->status_is(200)
384
        ->json_is( '/0/desk_id' => $desk_1->id )
385
        ->json_is( '/1/desk_id' => $desk_2->id )
386
        ->tx->res->json;
368
387
369
    is( scalar @{$res}, 2 );
388
    is( scalar @{$res}, 2 );
370
389
Lines 390-396 subtest 'list_cash_registers() tests' => sub { Link Here
390
409
391
    t::lib::Mocks::mock_preference( 'UseCashRegisters', 0 );
410
    t::lib::Mocks::mock_preference( 'UseCashRegisters', 0 );
392
411
393
    $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode . "/cash_registers" )->status_is(404)
412
    $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode . "/cash_registers" )
413
        ->status_is(404)
394
        ->json_is( '/error' => q{Feature disabled} );
414
        ->json_is( '/error' => q{Feature disabled} );
395
415
396
    my $non_existent_code = $library->branchcode;
416
    my $non_existent_code = $library->branchcode;
Lines 398-404 subtest 'list_cash_registers() tests' => sub { Link Here
398
418
399
    t::lib::Mocks::mock_preference( 'UseCashRegisters', 1 );
419
    t::lib::Mocks::mock_preference( 'UseCashRegisters', 1 );
400
420
401
    $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $non_existent_code . "/cash_registers" )->status_is(404)
421
    $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $non_existent_code . "/cash_registers" )
422
        ->status_is(404)
402
        ->json_is( '/error' => 'Library not found' );
423
        ->json_is( '/error' => 'Library not found' );
403
424
404
    my $cash_register_1 =
425
    my $cash_register_1 =
Lines 408-415 subtest 'list_cash_registers() tests' => sub { Link Here
408
429
409
    my $res =
430
    my $res =
410
        $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode . "/cash_registers" )
431
        $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode . "/cash_registers" )
411
        ->status_is(200)->json_is( '/0/cash_register_id' => $cash_register_1->id )
432
        ->status_is(200)
412
        ->json_is( '/1/cash_register_id' => $cash_register_2->id )->tx->res->json;
433
        ->json_is( '/0/cash_register_id' => $cash_register_1->id )
434
        ->json_is( '/1/cash_register_id' => $cash_register_2->id )
435
        ->tx->res->json;
413
436
414
    is( scalar @{$res}, 2 );
437
    is( scalar @{$res}, 2 );
415
438
(-)a/t/db_dependent/api/v1/oauth.t (-13 / +29 lines)
Lines 52-64 subtest '/oauth/token tests' => sub { Link Here
52
    $t->post_ok('/api/v1/oauth/token')->status_is(400);
52
    $t->post_ok('/api/v1/oauth/token')->status_is(400);
53
53
54
    # Wrong grant type
54
    # Wrong grant type
55
    $t->post_ok( '/api/v1/oauth/token', form => { grant_type => 'password' } )->status_is(400)
55
    $t->post_ok( '/api/v1/oauth/token', form => { grant_type => 'password' } )
56
        ->status_is(400)
56
        ->json_is( { error => 'Unimplemented grant type' } );
57
        ->json_is( { error => 'Unimplemented grant type' } );
57
58
58
    t::lib::Mocks::mock_preference( 'RESTOAuth2ClientCredentials', 1 );
59
    t::lib::Mocks::mock_preference( 'RESTOAuth2ClientCredentials', 1 );
59
60
60
    # No client_id/client_secret
61
    # No client_id/client_secret
61
    $t->post_ok( '/api/v1/oauth/token', form => { grant_type => 'client_credentials' } )->status_is(403)
62
    $t->post_ok( '/api/v1/oauth/token', form => { grant_type => 'client_credentials' } )
63
        ->status_is(403)
62
        ->json_is( { error => 'unauthorized_client' } );
64
        ->json_is( { error => 'unauthorized_client' } );
63
65
64
    subtest 'Client credentials in body' => sub {
66
    subtest 'Client credentials in body' => sub {
Lines 96-103 subtest 'Net::OAuth2::AuthorizationServer missing tests' => sub { Link Here
96
        client_secret => $api_key->plain_text_secret
98
        client_secret => $api_key->plain_text_secret
97
    };
99
    };
98
100
99
    $t->post_ok( '/api/v1/oauth/token', form => $form_data )->status_is(200)->json_is( '/expires_in' => 3600 )
101
    $t->post_ok( '/api/v1/oauth/token', form => $form_data )
100
        ->json_is( '/token_type' => 'Bearer' )->json_has('/access_token');
102
        ->status_is(200)
103
        ->json_is( '/expires_in' => 3600 )
104
        ->json_is( '/token_type' => 'Bearer' )
105
        ->json_has('/access_token');
101
106
102
    my $access_token = $t->tx->res->json->{access_token};
107
    my $access_token = $t->tx->res->json->{access_token};
103
108
Lines 107-113 subtest 'Net::OAuth2::AuthorizationServer missing tests' => sub { Link Here
107
    $tx->req->headers->authorization("Bearer $access_token");
112
    $tx->req->headers->authorization("Bearer $access_token");
108
    $t->request_ok($tx)->status_is(403);
113
    $t->request_ok($tx)->status_is(403);
109
114
110
    $t->post_ok( '/api/v1/oauth/token', form => $form_data )->status_is(400)
115
    $t->post_ok( '/api/v1/oauth/token', form => $form_data )
116
        ->status_is(400)
111
        ->json_is( { error => 'Unimplemented grant type' } );
117
        ->json_is( { error => 'Unimplemented grant type' } );
112
118
113
    $schema->storage->txn_rollback;
119
    $schema->storage->txn_rollback;
Lines 139-146 sub run_oauth_tests { Link Here
139
145
140
        $formData = { grant_type => 'client_credentials' };
146
        $formData = { grant_type => 'client_credentials' };
141
147
142
        $t->post_ok( "//$client_id:$client_secret@/api/v1/oauth/token", form => $formData )->status_is(200)
148
        $t->post_ok( "//$client_id:$client_secret@/api/v1/oauth/token", form => $formData )
143
            ->json_is( '/expires_in' => 3600 )->json_is( '/token_type' => 'Bearer' )->json_has('/access_token');
149
            ->status_is(200)
150
            ->json_is( '/expires_in' => 3600 )
151
            ->json_is( '/token_type' => 'Bearer' )
152
            ->json_has('/access_token');
144
    } else {
153
    } else {
145
154
146
        $formData = {
155
        $formData = {
Lines 149-156 sub run_oauth_tests { Link Here
149
            client_secret => $api_key->plain_text_secret
158
            client_secret => $api_key->plain_text_secret
150
        };
159
        };
151
160
152
        $t->post_ok( '/api/v1/oauth/token', form => $formData )->status_is(200)->json_is( '/expires_in' => 3600 )
161
        $t->post_ok( '/api/v1/oauth/token', form => $formData )
153
            ->json_is( '/token_type' => 'Bearer' )->json_has('/access_token');
162
            ->status_is(200)
163
            ->json_is( '/expires_in' => 3600 )
164
            ->json_is( '/token_type' => 'Bearer' )
165
            ->json_has('/access_token');
154
    }
166
    }
155
167
156
    my $access_token = $t->tx->res->json->{access_token};
168
    my $access_token = $t->tx->res->json->{access_token};
Lines 180-189 sub run_oauth_tests { Link Here
180
    $api_key->active(0)->store;
192
    $api_key->active(0)->store;
181
193
182
    if ( $test_case eq 'header' ) {
194
    if ( $test_case eq 'header' ) {
183
        $t->post_ok( "//$client_id:$client_secret@/api/v1/oauth/token", form => $formData )->status_is(403)
195
        $t->post_ok( "//$client_id:$client_secret@/api/v1/oauth/token", form => $formData )
196
            ->status_is(403)
184
            ->json_is( { error => 'unauthorized_client' } );
197
            ->json_is( { error => 'unauthorized_client' } );
185
    } else {
198
    } else {
186
        $t->post_ok( '/api/v1/oauth/token', form => $formData )->status_is(403)
199
        $t->post_ok( '/api/v1/oauth/token', form => $formData )
200
            ->status_is(403)
187
            ->json_is( { error => 'unauthorized_client' } );
201
            ->json_is( { error => 'unauthorized_client' } );
188
    }
202
    }
189
203
Lines 195-204 sub run_oauth_tests { Link Here
195
209
196
    # Wrong grant type
210
    # Wrong grant type
197
    if ( $test_case eq 'header' ) {
211
    if ( $test_case eq 'header' ) {
198
        $t->post_ok( "//$client_id:$client_secret@/api/v1/oauth/token", form => $formData )->status_is(400)
212
        $t->post_ok( "//$client_id:$client_secret@/api/v1/oauth/token", form => $formData )
213
            ->status_is(400)
199
            ->json_is( { error => 'Unimplemented grant type' } );
214
            ->json_is( { error => 'Unimplemented grant type' } );
200
    } else {
215
    } else {
201
        $t->post_ok( '/api/v1/oauth/token', form => $formData )->status_is(400)
216
        $t->post_ok( '/api/v1/oauth/token', form => $formData )
217
            ->status_is(400)
202
            ->json_is( { error => 'Unimplemented grant type' } );
218
            ->json_is( { error => 'Unimplemented grant type' } );
203
    }
219
    }
204
220
(-)a/t/db_dependent/api/v1/pagination.t (-34 / +59 lines)
Lines 76-104 subtest 'list() pagination tests' => sub { Link Here
76
    t::lib::Mocks::mock_preference( 'RESTdefaultPageSize', 20 );
76
    t::lib::Mocks::mock_preference( 'RESTdefaultPageSize', 20 );
77
77
78
    my $cities =
78
    my $cities =
79
        $t->get_ok("//$userid:$password@/api/v1/cities")->status_is(200)->header_is( 'X-Total-Count', '10' )
79
        $t->get_ok("//$userid:$password@/api/v1/cities")
80
        ->header_is( 'X-Base-Total-Count', '10' )->header_unlike( 'Link', qr|rel="prev"| )
80
        ->status_is(200)
81
        ->header_unlike( 'Link', qr|rel="next"| )->header_like(
81
        ->header_is( 'X-Total-Count',      '10' )
82
        ->header_is( 'X-Base-Total-Count', '10' )
83
        ->header_unlike( 'Link', qr|rel="prev"| )
84
        ->header_unlike( 'Link', qr|rel="next"| )
85
        ->header_like(
82
        'Link',
86
        'Link',
83
        qr#(_per_page=20\&_page=1|_page=1\&_per_page=20)>\; rel="first"#
87
        qr#(_per_page=20\&_page=1|_page=1\&_per_page=20)>\; rel="first"#
84
    )->header_like(
88
        )->header_like(
85
        'Link',
89
        'Link',
86
        qr#(_per_page=20\&_page=1|_page=1\&_per_page=20)>\; rel="last"#
90
        qr#(_per_page=20\&_page=1|_page=1\&_per_page=20)>\; rel="last"#
87
    )->tx->res->json;
91
        )->tx->res->json;
88
92
89
    is( scalar @{$cities}, 10, '10 cities retrieved' );
93
    is( scalar @{$cities}, 10, '10 cities retrieved' );
90
94
91
    $cities =
95
    $cities =
92
        $t->get_ok("//$userid:$password@/api/v1/cities?q={\"name\":{\"-like\":\"\%A\"}}")->status_is(200)
96
        $t->get_ok("//$userid:$password@/api/v1/cities?q={\"name\":{\"-like\":\"\%A\"}}")
97
        ->status_is(200)
93
        ->header_is( 'X-Total-Count',      '5',  'The resultset has 5 items' )
98
        ->header_is( 'X-Total-Count',      '5',  'The resultset has 5 items' )
94
        ->header_is( 'X-Base-Total-Count', '10', 'The resultset, without the filter, has 10' )
99
        ->header_is( 'X-Base-Total-Count', '10', 'The resultset, without the filter, has 10' )
95
        ->header_unlike( 'Link', qr|rel="prev"| )->header_unlike( 'Link', qr|rel="next"| )->header_like(
100
        ->header_unlike( 'Link', qr|rel="prev"| )
101
        ->header_unlike( 'Link', qr|rel="next"| )
102
        ->header_like(
96
        'Link',
103
        'Link',
97
        qr#(_per_page=20.*\&_page=1.*|_page=1.*\&_per_page=20.*)>\; rel="first"#
104
        qr#(_per_page=20.*\&_page=1.*|_page=1.*\&_per_page=20.*)>\; rel="first"#
98
    )->header_like(
105
        )->header_like(
99
        'Link',
106
        'Link',
100
        qr#(_per_page=20.*\&_page=1.*|_page=1.*\&_per_page=20.*)>\; rel="last"#
107
        qr#(_per_page=20.*\&_page=1.*|_page=1.*\&_per_page=20.*)>\; rel="last"#
101
    )->tx->res->json;
108
        )->tx->res->json;
102
109
103
    is( scalar @{$cities}, 5, '5 cities retrieved' );
110
    is( scalar @{$cities}, 5, '5 cities retrieved' );
104
111
Lines 106-136 subtest 'list() pagination tests' => sub { Link Here
106
113
107
    # _per_page overrides RESTdefaultPageSize
114
    # _per_page overrides RESTdefaultPageSize
108
    $cities =
115
    $cities =
109
        $t->get_ok("//$userid:$password@/api/v1/cities?_per_page=20")->status_is(200)
116
        $t->get_ok("//$userid:$password@/api/v1/cities?_per_page=20")
110
        ->header_is( 'X-Total-Count', '10' )->header_is( 'X-Base-Total-Count', '10' )
117
        ->status_is(200)
111
        ->header_unlike( 'Link', qr|rel="prev"| )->header_unlike( 'Link', qr|rel="next"| )->header_like(
118
        ->header_is( 'X-Total-Count',      '10' )
119
        ->header_is( 'X-Base-Total-Count', '10' )
120
        ->header_unlike( 'Link', qr|rel="prev"| )
121
        ->header_unlike( 'Link', qr|rel="next"| )
122
        ->header_like(
112
        'Link',
123
        'Link',
113
        qr#(_per_page=20\&_page=1|_page=1\&_per_page=20)>\; rel="first"#
124
        qr#(_per_page=20\&_page=1|_page=1\&_per_page=20)>\; rel="first"#
114
    )->header_like(
125
        )->header_like(
115
        'Link',
126
        'Link',
116
        qr#(_per_page=20\&_page=1|_page=1\&_per_page=20)>\; rel="last"#
127
        qr#(_per_page=20\&_page=1|_page=1\&_per_page=20)>\; rel="last"#
117
    )->tx->res->json;
128
        )->tx->res->json;
118
129
119
    is( scalar @{$cities}, 10, '10 cities retrieved' );
130
    is( scalar @{$cities}, 10, '10 cities retrieved' );
120
131
121
    # page 1
132
    # page 1
122
    $cities =
133
    $cities =
123
        $t->get_ok("//$userid:$password@/api/v1/cities")->status_is(200)->header_is( 'X-Total-Count', '10' )
134
        $t->get_ok("//$userid:$password@/api/v1/cities")
124
        ->header_is( 'X-Base-Total-Count', '10' )->header_unlike( 'Link', qr|rel="prev"| )->header_like(
135
        ->status_is(200)
136
        ->header_is( 'X-Total-Count',      '10' )
137
        ->header_is( 'X-Base-Total-Count', '10' )
138
        ->header_unlike( 'Link', qr|rel="prev"| )
139
        ->header_like(
125
        'Link',
140
        'Link',
126
        qr#(_per_page=3\&_page=1|_page=1\&_per_page=3)>\; rel="first"#
141
        qr#(_per_page=3\&_page=1|_page=1\&_per_page=3)>\; rel="first"#
127
    )->header_like(
142
        )->header_like(
128
        'Link',
143
        'Link',
129
        qr#(_per_page=3\&_page=2|_page=2\&_per_page=3)>\; rel="next"#
144
        qr#(_per_page=3\&_page=2|_page=2\&_per_page=3)>\; rel="next"#
130
    )->header_like(
145
        )->header_like(
131
        'Link',
146
        'Link',
132
        qr#(_per_page=3\&_page=4|_page=4\&_per_page=3)>\; rel="last"#
147
        qr#(_per_page=3\&_page=4|_page=4\&_per_page=3)>\; rel="last"#
133
    )->tx->res->json;
148
        )->tx->res->json;
134
149
135
    is( scalar @{$cities}, 3, '3 cities retrieved' );
150
    is( scalar @{$cities}, 3, '3 cities retrieved' );
136
151
Lines 138-185 subtest 'list() pagination tests' => sub { Link Here
138
    # to add all combinations to the regex
153
    # to add all combinations to the regex
139
    $cities =
154
    $cities =
140
        $t->get_ok("//$userid:$password@/api/v1/cities?_per_page=2&_page=2&q={\"name\":{\"-like\":\"\%A\"}}")
155
        $t->get_ok("//$userid:$password@/api/v1/cities?_per_page=2&_page=2&q={\"name\":{\"-like\":\"\%A\"}}")
141
        ->status_is(200)->header_is( 'X-Total-Count', '5' )->header_is( 'X-Base-Total-Count', '10' )->header_like(
156
        ->status_is(200)
157
        ->header_is( 'X-Total-Count',      '5' )
158
        ->header_is( 'X-Base-Total-Count', '10' )
159
        ->header_like(
142
        'Link',
160
        'Link',
143
        qr#(_per_page=2.*\&_page=1.*|_page=1.*\&_per_page=2.*)>\; rel="prev"#
161
        qr#(_per_page=2.*\&_page=1.*|_page=1.*\&_per_page=2.*)>\; rel="prev"#
144
    )->header_like(
162
        )->header_like(
145
        'Link',
163
        'Link',
146
        qr#(_per_page=2.*\&_page=1.*|_page=1.*\&_per_page=2.*)>\; rel="first"#
164
        qr#(_per_page=2.*\&_page=1.*|_page=1.*\&_per_page=2.*)>\; rel="first"#
147
    )->header_like(
165
        )->header_like(
148
        'Link',
166
        'Link',
149
        qr#(_per_page=2.*\&_page=3.*|_page=3.*\&_per_page=2.*)>\; rel="next"#
167
        qr#(_per_page=2.*\&_page=3.*|_page=3.*\&_per_page=2.*)>\; rel="next"#
150
    )->header_like(
168
        )->header_like(
151
        'Link',
169
        'Link',
152
        qr#(_per_page=2.*\&_page=3.*|_page=3.*\&_per_page=2.*)>\; rel="last"#
170
        qr#(_per_page=2.*\&_page=3.*|_page=3.*\&_per_page=2.*)>\; rel="last"#
153
    )->tx->res->json;
171
        )->tx->res->json;
154
172
155
    is( scalar @{$cities}, 2, '2 cities retrieved' );
173
    is( scalar @{$cities}, 2, '2 cities retrieved' );
156
174
157
    # last page, with only one result
175
    # last page, with only one result
158
    $cities =
176
    $cities =
159
        $t->get_ok("//$userid:$password@/api/v1/cities?_page=4")->status_is(200)->header_is( 'X-Total-Count', '10' )
177
        $t->get_ok("//$userid:$password@/api/v1/cities?_page=4")
160
        ->header_is( 'X-Base-Total-Count', '10' )->header_like(
178
        ->status_is(200)
179
        ->header_is( 'X-Total-Count',      '10' )
180
        ->header_is( 'X-Base-Total-Count', '10' )
181
        ->header_like(
161
        'Link',
182
        'Link',
162
        qr#(_per_page=3\&_page=3|_page=3\&_per_page=3)>\; rel="prev"#
183
        qr#(_per_page=3\&_page=3|_page=3\&_per_page=3)>\; rel="prev"#
163
    )->header_like(
184
        )->header_like(
164
        'Link',
185
        'Link',
165
        qr#(_per_page=3\&_page=1|_page=1\&_per_page=3)>\; rel="first"#
186
        qr#(_per_page=3\&_page=1|_page=1\&_per_page=3)>\; rel="first"#
166
    )->header_unlike( 'Link', qr#rel="next"# )->header_like(
187
        )->header_unlike( 'Link', qr#rel="next"# )->header_like(
167
        'Link',
188
        'Link',
168
        qr#(_per_page=3\&_page=4|_page=4\&_per_page=3)>\; rel="last"#
189
        qr#(_per_page=3\&_page=4|_page=4\&_per_page=3)>\; rel="last"#
169
    )->tx->res->json;
190
        )->tx->res->json;
170
191
171
    is( scalar @{$cities}, 1, '1 city retrieved' );
192
    is( scalar @{$cities}, 1, '1 city retrieved' );
172
193
173
    $cities =
194
    $cities =
174
        $t->get_ok("//$userid:$password@/api/v1/cities?_per_page=-1")->status_is(200)
195
        $t->get_ok("//$userid:$password@/api/v1/cities?_per_page=-1")
175
        ->header_is( 'X-Total-Count', '10' )->header_is( 'X-Base-Total-Count', '10' )
196
        ->status_is(200)
176
        ->header_unlike( 'Link', qr|rel="prev"| )->header_unlike( 'Link', qr|rel="next"| )->header_like(
197
        ->header_is( 'X-Total-Count',      '10' )
198
        ->header_is( 'X-Base-Total-Count', '10' )
199
        ->header_unlike( 'Link', qr|rel="prev"| )
200
        ->header_unlike( 'Link', qr|rel="next"| )
201
        ->header_like(
177
        'Link',
202
        'Link',
178
        qr#(_per_page=-1\&_page=1|_page=1\&_per_page=-1)>\; rel="first"#
203
        qr#(_per_page=-1\&_page=1|_page=1\&_per_page=-1)>\; rel="first"#
179
    )->header_like(
204
        )->header_like(
180
        'Link',
205
        'Link',
181
        qr#(_per_page=-1\&_page=1|_page=1\&_per_page=-1)>\; rel="last"#
206
        qr#(_per_page=-1\&_page=1|_page=1\&_per_page=-1)>\; rel="last"#
182
    )->tx->res->json;
207
        )->tx->res->json;
183
208
184
    is( scalar @{$cities}, 10, '10 cities retrieved, -1 means all' );
209
    is( scalar @{$cities}, 10, '10 cities retrieved, -1 means all' );
185
210
(-)a/t/db_dependent/api/v1/password_validation.t (-10 / +20 lines)
Lines 73-84 subtest 'password validation - account lock out' => sub { Link Here
73
        password   => "bad",
73
        password   => "bad",
74
    };
74
    };
75
75
76
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )->status_is(400)
76
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
77
        ->status_is(400)
77
        ->json_is( { error => q{Validation failed} } );
78
        ->json_is( { error => q{Validation failed} } );
78
79
79
    $json->{password} = $password;
80
    $json->{password} = $password;
80
81
81
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )->status_is(400)
82
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
83
        ->status_is(400)
82
        ->json_is( { error => q{Validation failed} } );
84
        ->json_is( { error => q{Validation failed} } );
83
85
84
    $schema->storage->txn_rollback;
86
    $schema->storage->txn_rollback;
Lines 105-111 subtest 'password validation - unauthorized user' => sub { Link Here
105
        password   => "test",
107
        password   => "test",
106
    };
108
    };
107
109
108
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )->status_is(403)
110
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
111
        ->status_is(403)
109
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
112
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
110
113
111
    $schema->storage->txn_rollback;
114
    $schema->storage->txn_rollback;
Lines 122-128 subtest 'password validation - unauthenticated user' => sub { Link Here
122
    };
125
    };
123
126
124
    $t->post_ok( "/api/v1/auth/password/validation" => json => $json )
127
    $t->post_ok( "/api/v1/auth/password/validation" => json => $json )
125
        ->json_is( '/error' => 'Authentication failure.' )->status_is(401);
128
        ->json_is( '/error' => 'Authentication failure.' )
129
        ->status_is(401);
126
130
127
    $schema->storage->txn_rollback;
131
    $schema->storage->txn_rollback;
128
};
132
};
Lines 185-191 subtest 'Password validation - authorized requests tests' => sub { Link Here
185
    };
189
    };
186
190
187
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
191
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
188
        ->status_is( 400, 'Validating using and invalid userid fails' )->json_is( { error => 'Validation failed' } );
192
        ->status_is( 400, 'Validating using and invalid userid fails' )
193
        ->json_is( { error => 'Validation failed' } );
189
194
190
    $json = {
195
    $json = {
191
        password => $password,
196
        password => $password,
Lines 293-299 subtest 'password validation - expired password' => sub { Link Here
293
        password   => $patron_password,
298
        password   => $patron_password,
294
    };
299
    };
295
300
296
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )->status_is(400)
301
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
302
        ->status_is(400)
297
        ->json_is( '/error' => 'Password expired' );
303
        ->json_is( '/error' => 'Password expired' );
298
304
299
    $schema->storage->txn_rollback;
305
    $schema->storage->txn_rollback;
Lines 328-334 subtest 'password validation - users with shared cardnumber / userid' => sub { Link Here
328
        password   => $patron_password_1,
334
        password   => $patron_password_1,
329
    };
335
    };
330
336
331
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )->status_is(201)
337
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
338
        ->status_is(201)
332
        ->json_is(
339
        ->json_is(
333
        { cardnumber => $patron_1->cardnumber, patron_id => $patron_1->borrowernumber, userid => $patron_1->userid } );
340
        { cardnumber => $patron_1->cardnumber, patron_id => $patron_1->borrowernumber, userid => $patron_1->userid } );
334
341
Lines 337-343 subtest 'password validation - users with shared cardnumber / userid' => sub { Link Here
337
        password   => $patron_password_2,
344
        password   => $patron_password_2,
338
    };
345
    };
339
346
340
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )->status_is(201)
347
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
348
        ->status_is(201)
341
        ->json_is(
349
        ->json_is(
342
        { cardnumber => $patron_2->cardnumber, patron_id => $patron_2->borrowernumber, userid => $patron_2->userid } );
350
        { cardnumber => $patron_2->cardnumber, patron_id => $patron_2->borrowernumber, userid => $patron_2->userid } );
343
351
Lines 346-352 subtest 'password validation - users with shared cardnumber / userid' => sub { Link Here
346
        password => $patron_password_1,
354
        password => $patron_password_1,
347
    };
355
    };
348
356
349
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )->status_is(201)
357
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
358
        ->status_is(201)
350
        ->json_is(
359
        ->json_is(
351
        { cardnumber => $patron_1->cardnumber, patron_id => $patron_1->borrowernumber, userid => $patron_1->userid } );
360
        { cardnumber => $patron_1->cardnumber, patron_id => $patron_1->borrowernumber, userid => $patron_1->userid } );
352
361
Lines 355-361 subtest 'password validation - users with shared cardnumber / userid' => sub { Link Here
355
        password => $patron_password_2,
364
        password => $patron_password_2,
356
    };
365
    };
357
366
358
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )->status_is(201)
367
    $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
368
        ->status_is(201)
359
        ->json_is(
369
        ->json_is(
360
        { cardnumber => $patron_2->cardnumber, patron_id => $patron_2->borrowernumber, userid => $patron_2->userid } );
370
        { cardnumber => $patron_2->cardnumber, patron_id => $patron_2->borrowernumber, userid => $patron_2->userid } );
361
371
(-)a/t/db_dependent/api/v1/patron_categories.t (-4 / +11 lines)
Lines 66-73 subtest 'list() tests' => sub { Link Here
66
66
67
    $t->get_ok("//$userid:$password@/api/v1/patron_categories")->status_is(200);
67
    $t->get_ok("//$userid:$password@/api/v1/patron_categories")->status_is(200);
68
68
69
    $t->get_ok("//$userid:$password@/api/v1/patron_categories?q={\"me.categorycode\":\"TEST\"}")->status_is(200)
69
    $t->get_ok("//$userid:$password@/api/v1/patron_categories?q={\"me.categorycode\":\"TEST\"}")
70
        ->json_has('/0/name')->json_is( '/0/name' => 'Test' )->json_hasnt('/1');
70
        ->status_is(200)
71
        ->json_has('/0/name')
72
        ->json_is( '/0/name' => 'Test' )
73
        ->json_hasnt('/1');
71
74
72
    # Off limits search
75
    # Off limits search
73
76
Lines 92-105 subtest 'list() tests' => sub { Link Here
92
    my $off_limits_userid = $off_limits_librarian->userid;
95
    my $off_limits_userid = $off_limits_librarian->userid;
93
96
94
    $t->get_ok("//$off_limits_userid:$off_limits_password@/api/v1/patron_categories?q={\"me.categorycode\":\"TEST\"}")
97
    $t->get_ok("//$off_limits_userid:$off_limits_password@/api/v1/patron_categories?q={\"me.categorycode\":\"TEST\"}")
95
        ->status_is(200)->json_hasnt('/0');
98
        ->status_is(200)
99
        ->json_hasnt('/0');
96
100
97
    # Off limits librarian category has changed to one within limits
101
    # Off limits librarian category has changed to one within limits
98
102
99
    $off_limits_librarian->branchcode( $library->branchcode )->store;
103
    $off_limits_librarian->branchcode( $library->branchcode )->store;
100
104
101
    $t->get_ok("//$off_limits_userid:$off_limits_password@/api/v1/patron_categories?q={\"me.categorycode\":\"TEST\"}")
105
    $t->get_ok("//$off_limits_userid:$off_limits_password@/api/v1/patron_categories?q={\"me.categorycode\":\"TEST\"}")
102
        ->status_is(200)->json_has('/0/name')->json_is( [ $category->to_api ] )->json_hasnt('/1');
106
        ->status_is(200)
107
        ->json_has('/0/name')
108
        ->json_is( [ $category->to_api ] )
109
        ->json_hasnt('/1');
103
110
104
    $schema->storage->txn_rollback;
111
    $schema->storage->txn_rollback;
105
112
(-)a/t/db_dependent/api/v1/patrons.t (-57 / +114 lines)
Lines 125-137 subtest 'list() tests' => sub { Link Here
125
125
126
        $t->get_ok("//$userid:$password@/api/v1/patrons")->status_is( 200, 'list_borrowers makes /patrons accessible' );
126
        $t->get_ok("//$userid:$password@/api/v1/patrons")->status_is( 200, 'list_borrowers makes /patrons accessible' );
127
127
128
        $t->get_ok( "//$userid:$password@/api/v1/patrons?cardnumber=" . $librarian->cardnumber )->status_is(200)
128
        $t->get_ok( "//$userid:$password@/api/v1/patrons?cardnumber=" . $librarian->cardnumber )
129
            ->status_is(200)
129
            ->json_is( '/0/cardnumber' => $librarian->cardnumber );
130
            ->json_is( '/0/cardnumber' => $librarian->cardnumber );
130
131
131
        $t->get_ok( "//$userid:$password@/api/v1/patrons?q={\"cardnumber\":\"" . $librarian->cardnumber . "\"}" )
132
        $t->get_ok( "//$userid:$password@/api/v1/patrons?q={\"cardnumber\":\"" . $librarian->cardnumber . "\"}" )
132
            ->status_is(200)->json_is( '/0/cardnumber' => $librarian->cardnumber );
133
            ->status_is(200)
134
            ->json_is( '/0/cardnumber' => $librarian->cardnumber );
133
135
134
        $t->get_ok( "//$userid:$password@/api/v1/patrons?address2=" . $librarian->address2 )->status_is(200)
136
        $t->get_ok( "//$userid:$password@/api/v1/patrons?address2=" . $librarian->address2 )
137
            ->status_is(200)
135
            ->json_is( '/0/address2' => $librarian->address2 );
138
            ->json_is( '/0/address2' => $librarian->address2 );
136
139
137
        subtest 'restricted & expired' => sub {
140
        subtest 'restricted & expired' => sub {
Lines 145-157 subtest 'list() tests' => sub { Link Here
145
            $t->get_ok( "//$userid:$password@/api/v1/patrons?restricted="
148
            $t->get_ok( "//$userid:$password@/api/v1/patrons?restricted="
146
                    . Mojo::JSON->true
149
                    . Mojo::JSON->true
147
                    . "&cardnumber="
150
                    . "&cardnumber="
148
                    . $patron->cardnumber )->status_is(200)->json_has('/0/restricted')
151
                    . $patron->cardnumber )
149
                ->json_is( '/0/restricted' => Mojo::JSON->true )->json_has('/0/expired')
152
                ->status_is(200)
150
                ->json_is( '/0/expired'    => Mojo::JSON->false )->json_hasnt('/1');
153
                ->json_has('/0/restricted')
154
                ->json_is( '/0/restricted' => Mojo::JSON->true )
155
                ->json_has('/0/expired')
156
                ->json_is( '/0/expired' => Mojo::JSON->false )
157
                ->json_hasnt('/1');
151
158
152
            $patron->dateexpiry( dt_from_string->subtract( days => 2 ) )->store;
159
            $patron->dateexpiry( dt_from_string->subtract( days => 2 ) )->store;
153
            $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )->status_is(200)
160
            $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
154
                ->json_has('/expired')->json_is( '/expired' => Mojo::JSON->true );
161
                ->status_is(200)
162
                ->json_has('/expired')
163
                ->json_is( '/expired' => Mojo::JSON->true );
155
164
156
            $t->get_ok( "//$userid:$password@/api/v1/patrons?"
165
            $t->get_ok( "//$userid:$password@/api/v1/patrons?"
157
                    . 'q={"extended_attributes.type":"CODE"}' => { 'x-koha-embed' => 'extended_attributes' } )
166
                    . 'q={"extended_attributes.type":"CODE"}' => { 'x-koha-embed' => 'extended_attributes' } )
Lines 180-192 subtest 'list() tests' => sub { Link Here
180
            $t->get_ok( "//$userid:$password@/api/v1/patrons?date_of_birth="
189
            $t->get_ok( "//$userid:$password@/api/v1/patrons?date_of_birth="
181
                    . $date_of_birth
190
                    . $date_of_birth
182
                    . "&cardnumber="
191
                    . "&cardnumber="
183
                    . $patron->cardnumber )->status_is(200)
192
                    . $patron->cardnumber )
193
                ->status_is(200)
184
                ->json_is( '/0/patron_id' => $patron->id, 'Filtering by date works' );
194
                ->json_is( '/0/patron_id' => $patron->id, 'Filtering by date works' );
185
195
186
            $t->get_ok( "//$userid:$password@/api/v1/patrons?last_seen="
196
            $t->get_ok( "//$userid:$password@/api/v1/patrons?last_seen="
187
                    . $last_seen_rfc3339
197
                    . $last_seen_rfc3339
188
                    . "&cardnumber="
198
                    . "&cardnumber="
189
                    . $patron->cardnumber )->status_is(200)
199
                    . $patron->cardnumber )
200
                ->status_is(200)
190
                ->json_is( '/0/patron_id' => $patron->id, 'Filtering by date-time works' );
201
                ->json_is( '/0/patron_id' => $patron->id, 'Filtering by date-time works' );
191
202
192
            my $q = encode_json(
203
            my $q = encode_json(
Lines 196-202 subtest 'list() tests' => sub { Link Here
196
                }
207
                }
197
            );
208
            );
198
209
199
            $t->get_ok("//$userid:$password@/api/v1/patrons?q=$q")->status_is(200)
210
            $t->get_ok("//$userid:$password@/api/v1/patrons?q=$q")
211
                ->status_is(200)
200
                ->json_is( '/0/patron_id' => $patron->id, 'Filtering by date works' );
212
                ->json_is( '/0/patron_id' => $patron->id, 'Filtering by date works' );
201
213
202
            $q = encode_json(
214
            $q = encode_json(
Lines 206-212 subtest 'list() tests' => sub { Link Here
206
                }
218
                }
207
            );
219
            );
208
220
209
            $t->get_ok("//$userid:$password@/api/v1/patrons?q=$q")->status_is(200)
221
            $t->get_ok("//$userid:$password@/api/v1/patrons?q=$q")
222
                ->status_is(200)
210
                ->json_is( '/0/patron_id' => $patron->id, 'Filtering by date-time works' );
223
                ->json_is( '/0/patron_id' => $patron->id, 'Filtering by date-time works' );
211
        };
224
        };
212
225
Lines 250-265 subtest 'list() tests' => sub { Link Here
250
        my $userid = $librarian->userid;
263
        my $userid = $librarian->userid;
251
264
252
        $t->get_ok( "//$userid:$password@/api/v1/patrons?_order_by=patron_id&q="
265
        $t->get_ok( "//$userid:$password@/api/v1/patrons?_order_by=patron_id&q="
253
                . encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )->status_is(200)
266
                . encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )
254
            ->json_is( '/0/patron_id' => $patron_1->id )->json_is( '/1/patron_id' => $patron_2->id )
267
            ->status_is(200)
268
            ->json_is( '/0/patron_id' => $patron_1->id )
269
            ->json_is( '/1/patron_id' => $patron_2->id )
255
            ->json_is( '/2/patron_id' => $patron_3->id );
270
            ->json_is( '/2/patron_id' => $patron_3->id );
256
271
257
        @libraries_where_can_see_patrons = ( $library_2->id );
272
        @libraries_where_can_see_patrons = ( $library_2->id );
258
273
259
        my $res =
274
        my $res =
260
            $t->get_ok( "//$userid:$password@/api/v1/patrons?_order_by=patron_id&q="
275
            $t->get_ok( "//$userid:$password@/api/v1/patrons?_order_by=patron_id&q="
261
                . encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )->status_is(200)
276
                . encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )
262
            ->json_is( '/0/patron_id' => $patron_3->id, 'Returns the only allowed patron' )->tx->res->json;
277
            ->status_is(200)
278
            ->json_is( '/0/patron_id' => $patron_3->id, 'Returns the only allowed patron' )
279
            ->tx->res->json;
263
280
264
        is( scalar @{$res}, 1, 'Only one patron returned' );
281
        is( scalar @{$res}, 1, 'Only one patron returned' );
265
282
Lines 322-329 subtest 'get() tests' => sub { Link Here
322
339
323
        $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id )
340
        $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id )
324
            ->status_is( 200, 'list_borrowers permission makes patron visible' )
341
            ->status_is( 200, 'list_borrowers permission makes patron visible' )
325
            ->json_is( '/patron_id' => $patron->id )->json_is( '/category_id' => $patron->categorycode )
342
            ->json_is( '/patron_id'        => $patron->id )
326
            ->json_is( '/surname'   => $patron->surname )->json_is( '/patron_card_lost' => Mojo::JSON->false );
343
            ->json_is( '/category_id'      => $patron->categorycode )
344
            ->json_is( '/surname'          => $patron->surname )
345
            ->json_is( '/patron_card_lost' => Mojo::JSON->false );
327
346
328
        $schema->storage->txn_rollback;
347
        $schema->storage->txn_rollback;
329
    };
348
    };
Lines 365-382 subtest 'get() tests' => sub { Link Here
365
        $librarian->set_password( { password => $password, skip_validation => 1 } );
384
        $librarian->set_password( { password => $password, skip_validation => 1 } );
366
        my $userid = $librarian->userid;
385
        my $userid = $librarian->userid;
367
386
368
        $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_1->id )->status_is(200)
387
        $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_1->id )
388
            ->status_is(200)
369
            ->json_is( '/patron_id' => $patron_1->id );
389
            ->json_is( '/patron_id' => $patron_1->id );
370
390
371
        $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->id )->status_is(200)
391
        $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->id )
392
            ->status_is(200)
372
            ->json_is( '/patron_id' => $patron_2->id );
393
            ->json_is( '/patron_id' => $patron_2->id );
373
394
374
        @libraries_where_can_see_patrons = ( $library_1->id );
395
        @libraries_where_can_see_patrons = ( $library_1->id );
375
396
376
        $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_1->id )->status_is(200)
397
        $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_1->id )
398
            ->status_is(200)
377
            ->json_is( '/patron_id' => $patron_1->id );
399
            ->json_is( '/patron_id' => $patron_1->id );
378
400
379
        $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->id )->status_is(404)
401
        $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->id )
402
            ->status_is(404)
380
            ->json_is( '/error' => 'Patron not found' );
403
            ->json_is( '/error' => 'Patron not found' );
381
404
382
        $schema->storage->txn_rollback;
405
        $schema->storage->txn_rollback;
Lines 473-479 subtest 'add() tests' => sub { Link Here
473
        $newpatron->{library_id} = $deleted_library_id;
496
        $newpatron->{library_id} = $deleted_library_id;
474
497
475
        # Test duplicate userid constraint
498
        # Test duplicate userid constraint
476
        $t->post_ok( "//$userid:$password@/api/v1/patrons" => json => $newpatron )->status_is(400)
499
        $t->post_ok( "//$userid:$password@/api/v1/patrons" => json => $newpatron )
500
            ->status_is(400)
477
            ->json_is( '/error' => "Problem with " . $newpatron->{userid} );
501
            ->json_is( '/error' => "Problem with " . $newpatron->{userid} );
478
502
479
        $newpatron->{library_id} = $patron->branchcode;
503
        $newpatron->{library_id} = $patron->branchcode;
Lines 481-487 subtest 'add() tests' => sub { Link Here
481
        # Test duplicate cardnumber constraint
505
        # Test duplicate cardnumber constraint
482
        $newpatron->{userid} = undef;    # force regeneration
506
        $newpatron->{userid} = undef;    # force regeneration
483
        warning_like {
507
        warning_like {
484
            $t->post_ok( "//$userid:$password@/api/v1/patrons" => json => $newpatron )->status_is(409)
508
            $t->post_ok( "//$userid:$password@/api/v1/patrons" => json => $newpatron )
509
                ->status_is(409)
485
                ->json_has( '/error', 'Fails when trying to POST duplicate cardnumber' )
510
                ->json_has( '/error', 'Fails when trying to POST duplicate cardnumber' )
486
                ->json_like( '/conflict' => qr/(borrowers\.)?cardnumber/ );
511
                ->json_like( '/conflict' => qr/(borrowers\.)?cardnumber/ );
487
        }
512
        }
Lines 496-502 subtest 'add() tests' => sub { Link Here
496
521
497
        $newpatron->{category_id} = $deleted_category_id;    # Test invalid patron category
522
        $newpatron->{category_id} = $deleted_category_id;    # Test invalid patron category
498
523
499
        $t->post_ok( "//$userid:$password@/api/v1/patrons" => json => $newpatron )->status_is(400)
524
        $t->post_ok( "//$userid:$password@/api/v1/patrons" => json => $newpatron )
525
            ->status_is(400)
500
            ->json_is( '/error' => "Given category_id does not exist" );
526
            ->json_is( '/error' => "Given category_id does not exist" );
501
        $newpatron->{category_id} = $patron->categorycode;
527
        $newpatron->{category_id} = $patron->categorycode;
502
528
Lines 527-537 subtest 'add() tests' => sub { Link Here
527
        $letter_enqueued = 0;
553
        $letter_enqueued = 0;
528
        $t->post_ok(
554
        $t->post_ok(
529
            "//$userid:$password@/api/v1/patrons" => { 'x-koha-override' => 'welcome_yes' } => json => $newpatron )
555
            "//$userid:$password@/api/v1/patrons" => { 'x-koha-override' => 'welcome_yes' } => json => $newpatron )
530
            ->status_is( 201, 'Patron created successfully' )->header_like(
556
            ->status_is( 201, 'Patron created successfully' )
557
            ->header_like(
531
            Location => qr|^\/api\/v1\/patrons/\d*|,
558
            Location => qr|^\/api\/v1\/patrons/\d*|,
532
            'REST3.4.1'
559
            'REST3.4.1'
533
        )->json_has( '/patron_id', 'got a patron_id' )->json_is( '/cardnumber' => $newpatron->{cardnumber} )
560
            )
534
            ->json_is( '/surname'       => $newpatron->{surname} )->json_is( '/firstname' => $newpatron->{firstname} )
561
            ->json_has( '/patron_id', 'got a patron_id' )
562
            ->json_is( '/cardnumber'    => $newpatron->{cardnumber} )
563
            ->json_is( '/surname'       => $newpatron->{surname} )
564
            ->json_is( '/firstname'     => $newpatron->{firstname} )
535
            ->json_is( '/date_of_birth' => $newpatron->{date_of_birth}, 'Date field set (Bug 28585)' )
565
            ->json_is( '/date_of_birth' => $newpatron->{date_of_birth}, 'Date field set (Bug 28585)' )
536
            ->json_is( '/last_seen'     => $newpatron->{last_seen},     'Date-time field set (Bug 28585)' );
566
            ->json_is( '/last_seen'     => $newpatron->{last_seen},     'Date-time field set (Bug 28585)' );
537
567
Lines 658-664 subtest 'add() tests' => sub { Link Here
658
                    "city"        => "Konstanz",
688
                    "city"        => "Konstanz",
659
                    "library_id"  => "MPL"
689
                    "library_id"  => "MPL"
660
                }
690
                }
661
            )->status_is(400)
691
                )
692
                ->status_is(400)
662
                ->json_is( '/error' => "Tried to add more than one non-repeatable attributes. type=$code value=$attr" );
693
                ->json_is( '/error' => "Tried to add more than one non-repeatable attributes. type=$code value=$attr" );
663
694
664
            is( Koha::Patrons->search->count, $patrons_count, 'No patron added' );
695
            is( Koha::Patrons->search->count, $patrons_count, 'No patron added' );
Lines 673-679 subtest 'add() tests' => sub { Link Here
673
                    "city"        => "Konstanz",
704
                    "city"        => "Konstanz",
674
                    "library_id"  => "MPL"
705
                    "library_id"  => "MPL"
675
                }
706
                }
676
            )->status_is(400)
707
                )
708
                ->status_is(400)
677
                ->json_is(
709
                ->json_is(
678
                '/error' => "Your action breaks a unique constraint on the attribute. type=$code value=$attr" );
710
                '/error' => "Your action breaks a unique constraint on the attribute. type=$code value=$attr" );
679
711
Lines 834-840 subtest 'add() tests' => sub { Link Here
834
                    "city"        => "Bigtown",
866
                    "city"        => "Bigtown",
835
                    "library_id"  => "MPL",
867
                    "library_id"  => "MPL",
836
                }
868
                }
837
            )->status_is( 201, 'Patron added with EnhancedMessagingPreferences disabled' )
869
                )
870
                ->status_is( 201, 'Patron added with EnhancedMessagingPreferences disabled' )
838
                ->tx->res->json->{patron_id};
871
                ->tx->res->json->{patron_id};
839
872
840
            # No messaging preferences should be set
873
            # No messaging preferences should be set
Lines 893-899 subtest 'update() tests' => sub { Link Here
893
        delete $newpatron->{expired};
926
        delete $newpatron->{expired};
894
        delete $newpatron->{anonymized};
927
        delete $newpatron->{anonymized};
895
928
896
        $t->put_ok( "//$userid:$password@/api/v1/patrons/-1" => json => $newpatron )->status_is(404)
929
        $t->put_ok( "//$userid:$password@/api/v1/patrons/-1" => json => $newpatron )
930
            ->status_is(404)
897
            ->json_has( '/error', 'Fails when trying to PUT nonexistent patron' );
931
            ->json_has( '/error', 'Fails when trying to PUT nonexistent patron' );
898
932
899
        # Create a library just to make sure its ID doesn't exist on the DB
933
        # Create a library just to make sure its ID doesn't exist on the DB
Lines 907-913 subtest 'update() tests' => sub { Link Here
907
        $newpatron->{category_id} = $deleted_category_id;
941
        $newpatron->{category_id} = $deleted_category_id;
908
942
909
        $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
943
        $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
910
            ->status_is(400)->json_is( '/error' => "Given category_id does not exist" );
944
            ->status_is(400)
945
            ->json_is( '/error' => "Given category_id does not exist" );
911
946
912
        # Restore the valid category
947
        # Restore the valid category
913
        $newpatron->{category_id} = $patron_2->categorycode;
948
        $newpatron->{category_id} = $patron_2->categorycode;
Lines 924-930 subtest 'update() tests' => sub { Link Here
924
959
925
        warning_like {
960
        warning_like {
926
            $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
961
            $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
927
                ->status_is(400)->json_is( '/error' => "Given library_id does not exist" );
962
                ->status_is(400)
963
                ->json_is( '/error' => "Given library_id does not exist" );
928
        }
964
        }
929
        qr/DBD::mysql::st execute failed: Cannot add or update a child row: a foreign key constraint fails/;
965
        qr/DBD::mysql::st execute failed: Cannot add or update a child row: a foreign key constraint fails/;
930
966
Lines 935-941 subtest 'update() tests' => sub { Link Here
935
        $newpatron->{falseproperty} = "Non existent property";
971
        $newpatron->{falseproperty} = "Non existent property";
936
972
937
        $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
973
        $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
938
            ->status_is(400)->json_is( '/errors/0/message' => 'Properties not allowed: falseproperty.' );
974
            ->status_is(400)
975
            ->json_is( '/errors/0/message' => 'Properties not allowed: falseproperty.' );
939
976
940
        # Get rid of the invalid attribute
977
        # Get rid of the invalid attribute
941
        delete $newpatron->{falseproperty};
978
        delete $newpatron->{falseproperty};
Lines 945-951 subtest 'update() tests' => sub { Link Here
945
        $newpatron->{userid}     = $patron_1->userid;
982
        $newpatron->{userid}     = $patron_1->userid;
946
983
947
        $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
984
        $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
948
            ->status_is(400)->json_has( '/error', "Problem with userid " . $patron_1->userid );
985
            ->status_is(400)
986
            ->json_has( '/error', "Problem with userid " . $patron_1->userid );
949
987
950
        $newpatron->{cardnumber} = $patron_1->id . $patron_2->id;
988
        $newpatron->{cardnumber} = $patron_1->id . $patron_2->id;
951
        $newpatron->{userid}     = "user" . $patron_1->id . $patron_2->id;
989
        $newpatron->{userid}     = "user" . $patron_1->id . $patron_2->id;
Lines 1029-1035 subtest 'update() tests' => sub { Link Here
1029
            ->status_is(
1067
            ->status_is(
1030
            403,
1068
            403,
1031
            "Non-superlibrarian user change of superlibrarian secondary_email to undefined forbidden"
1069
            "Non-superlibrarian user change of superlibrarian secondary_email to undefined forbidden"
1032
        )->json_is( { error => "Not enough privileges to change a superlibrarian's email" } );
1070
            )->json_is( { error => "Not enough privileges to change a superlibrarian's email" } );
1033
1071
1034
        $newpatron->{secondary_email}  = $superlibrarian->emailpro;
1072
        $newpatron->{secondary_email}  = $superlibrarian->emailpro;
1035
        $newpatron->{altaddress_email} = 'nonsense@no.no';
1073
        $newpatron->{altaddress_email} = 'nonsense@no.no';
Lines 1045-1051 subtest 'update() tests' => sub { Link Here
1045
            ->status_is(
1083
            ->status_is(
1046
            403,
1084
            403,
1047
            "Non-superlibrarian user change of superlibrarian altaddress_email to undefined forbidden"
1085
            "Non-superlibrarian user change of superlibrarian altaddress_email to undefined forbidden"
1048
        )->json_is( { error => "Not enough privileges to change a superlibrarian's email" } );
1086
            )->json_is( { error => "Not enough privileges to change a superlibrarian's email" } );
1049
1087
1050
        # update patron without sending email
1088
        # update patron without sending email
1051
        delete $newpatron->{email};
1089
        delete $newpatron->{email};
Lines 1116-1128 subtest 'update() tests' => sub { Link Here
1116
                    "city"        => "Konstanz",
1154
                    "city"        => "Konstanz",
1117
                    "library_id"  => "MPL"
1155
                    "library_id"  => "MPL"
1118
                }
1156
                }
1119
            )->status_is(400)
1157
                )
1158
                ->status_is(400)
1120
                ->json_is(
1159
                ->json_is(
1121
                '/error' => "Missing mandatory extended attribute (type=" . $attr_type_mandatory->code . ")" );
1160
                '/error' => "Missing mandatory extended attribute (type=" . $attr_type_mandatory->code . ")" );
1122
1161
1123
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1162
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1124
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1163
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1125
                    $newpatron )->status_is(400)
1164
                    $newpatron )
1165
                ->status_is(400)
1126
                ->json_is( '/error'      => 'Tried to use an invalid attribute type. type=' . $deleted_attr_code )
1166
                ->json_is( '/error'      => 'Tried to use an invalid attribute type. type=' . $deleted_attr_code )
1127
                ->json_is( '/error_code' => 'invalid_attribute_type' );
1167
                ->json_is( '/error_code' => 'invalid_attribute_type' );
1128
1168
Lines 1139-1149 subtest 'update() tests' => sub { Link Here
1139
1179
1140
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1180
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1141
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1181
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1142
                    $newpatron )->status_is(400)
1182
                    $newpatron )
1183
                ->status_is(400)
1143
                ->json_is( '/error' => 'Your action breaks a unique constraint on the attribute. type='
1184
                ->json_is( '/error' => 'Your action breaks a unique constraint on the attribute. type='
1144
                    . $attr_type_unique->code
1185
                    . $attr_type_unique->code
1145
                    . ' value='
1186
                    . ' value='
1146
                    . $unique_attr->attribute )->json_is( '/error_code' => 'attribute_not_unique' );
1187
                    . $unique_attr->attribute )
1188
                ->json_is( '/error_code' => 'attribute_not_unique' );
1147
1189
1148
            $newpatron->{extended_attributes} = [
1190
            $newpatron->{extended_attributes} = [
1149
                { type => $attr_type_repeatable->code, value => 'a' },
1191
                { type => $attr_type_repeatable->code, value => 'a' },
Lines 1154-1164 subtest 'update() tests' => sub { Link Here
1154
1196
1155
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1197
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1156
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1198
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1157
                    $newpatron )->status_is(400)
1199
                    $newpatron )
1200
                ->status_is(400)
1158
                ->json_is( '/error' => 'Your action breaks a unique constraint on the attribute. type='
1201
                ->json_is( '/error' => 'Your action breaks a unique constraint on the attribute. type='
1159
                    . $attr_type_unique->code
1202
                    . $attr_type_unique->code
1160
                    . ' value='
1203
                    . ' value='
1161
                    . $unique_attr->attribute )->json_is( '/error_code' => 'attribute_not_unique' );
1204
                    . $unique_attr->attribute )
1205
                ->json_is( '/error_code' => 'attribute_not_unique' );
1162
1206
1163
            $newpatron->{extended_attributes} = [
1207
            $newpatron->{extended_attributes} = [
1164
                { type => $attr_type_repeatable->code, value => 'a' },
1208
                { type => $attr_type_repeatable->code, value => 'a' },
Lines 1168-1177 subtest 'update() tests' => sub { Link Here
1168
1212
1169
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1213
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1170
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1214
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1171
                    $newpatron )->status_is(400)
1215
                    $newpatron )
1216
                ->status_is(400)
1172
                ->json_is( '/error' => 'Tried to add more than one non-repeatable attributes. type='
1217
                ->json_is( '/error' => 'Tried to add more than one non-repeatable attributes. type='
1173
                    . $attr_type_mandatory->code
1218
                    . $attr_type_mandatory->code
1174
                    . ' value=pong' )->json_is( '/error_code' => 'non_repeatable_attribute' );
1219
                    . ' value=pong' )
1220
                ->json_is( '/error_code' => 'non_repeatable_attribute' );
1175
1221
1176
            my $unique_value = $unique_attr->attribute;
1222
            my $unique_value = $unique_attr->attribute;
1177
            $unique_attr->delete;
1223
            $unique_attr->delete;
Lines 1230-1236 subtest 'delete() tests' => sub { Link Here
1230
1276
1231
        t::lib::Mocks::mock_preference( 'AnonymousPatron', $patron->borrowernumber );
1277
        t::lib::Mocks::mock_preference( 'AnonymousPatron', $patron->borrowernumber );
1232
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1278
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1233
            ->status_is( 409, 'Anonymous patron cannot be deleted' )->json_is(
1279
            ->status_is( 409, 'Anonymous patron cannot be deleted' )
1280
            ->json_is(
1234
            {
1281
            {
1235
                error      => 'Anonymous patron cannot be deleted',
1282
                error      => 'Anonymous patron cannot be deleted',
1236
                error_code => 'is_anonymous_patron'
1283
                error_code => 'is_anonymous_patron'
Lines 1252-1258 subtest 'delete() tests' => sub { Link Here
1252
        $guarantee->add_guarantor( { guarantor_id => $patron->id, relationship => 'parent' } );
1299
        $guarantee->add_guarantor( { guarantor_id => $patron->id, relationship => 'parent' } );
1253
1300
1254
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1301
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1255
            ->status_is( 409, 'Patron with checkouts cannot be deleted' )->json_is(
1302
            ->status_is( 409, 'Patron with checkouts cannot be deleted' )
1303
            ->json_is(
1256
            {
1304
            {
1257
                error      => 'Pending checkouts prevent deletion',
1305
                error      => 'Pending checkouts prevent deletion',
1258
                error_code => 'has_checkouts'
1306
                error_code => 'has_checkouts'
Lines 1263-1269 subtest 'delete() tests' => sub { Link Here
1263
        $checkout->delete;
1311
        $checkout->delete;
1264
1312
1265
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1313
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1266
            ->status_is( 409, 'Patron with debt cannot be deleted' )->json_is(
1314
            ->status_is( 409, 'Patron with debt cannot be deleted' )
1315
            ->json_is(
1267
            {
1316
            {
1268
                error      => 'Pending debts prevent deletion',
1317
                error      => 'Pending debts prevent deletion',
1269
                error_code => 'has_debt'
1318
                error_code => 'has_debt'
Lines 1274-1280 subtest 'delete() tests' => sub { Link Here
1274
        $patron->account->pay( { amount => 10, debits => [$debit] } );
1323
        $patron->account->pay( { amount => 10, debits => [$debit] } );
1275
1324
1276
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1325
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1277
            ->status_is( 409, 'Patron with guarantees cannot be deleted' )->json_is(
1326
            ->status_is( 409, 'Patron with guarantees cannot be deleted' )
1327
            ->json_is(
1278
            {
1328
            {
1279
                error      => 'Patron is a guarantor and it prevents deletion',
1329
                error      => 'Patron is a guarantor and it prevents deletion',
1280
                error_code => 'has_guarantees'
1330
                error_code => 'has_guarantees'
Lines 1287-1293 subtest 'delete() tests' => sub { Link Here
1287
        $patron->protected(1)->store();
1337
        $patron->protected(1)->store();
1288
1338
1289
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1339
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1290
            ->status_is( 409, 'Protected patron cannot be deleted' )->json_is(
1340
            ->status_is( 409, 'Protected patron cannot be deleted' )
1341
            ->json_is(
1291
            {
1342
            {
1292
                error      => 'Protected patrons cannot be deleted',
1343
                error      => 'Protected patrons cannot be deleted',
1293
                error_code => 'is_protected'
1344
                error_code => 'is_protected'
Lines 1297-1303 subtest 'delete() tests' => sub { Link Here
1297
        $patron->protected(0)->store();
1348
        $patron->protected(0)->store();
1298
1349
1299
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1350
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1300
            ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
1351
            ->status_is( 204, 'REST3.2.4' )
1352
            ->content_is( '', 'REST3.3.4' );
1301
1353
1302
        my $deleted_patrons = Koha::Old::Patrons->search( { borrowernumber => $patron->borrowernumber } );
1354
        my $deleted_patrons = Koha::Old::Patrons->search( { borrowernumber => $patron->borrowernumber } );
1303
        is( $deleted_patrons->count, 1, 'The patron has been moved to the vault' );
1355
        is( $deleted_patrons->count, 1, 'The patron has been moved to the vault' );
Lines 1329-1339 subtest 'guarantors_can_see_charges() tests' => sub { Link Here
1329
    )->status_is(401)->json_is( { error => "Authentication failure." } );
1381
    )->status_is(401)->json_is( { error => "Authentication failure." } );
1330
1382
1331
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$other_patron_id/guarantors/can_see_charges" => json =>
1383
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$other_patron_id/guarantors/can_see_charges" => json =>
1332
            { allowed => Mojo::JSON->true } )->status_is(403)
1384
            { allowed => Mojo::JSON->true } )
1385
        ->status_is(403)
1333
        ->json_is( { error => "Unprivileged user cannot access another user's resources" } );
1386
        ->json_is( { error => "Unprivileged user cannot access another user's resources" } );
1334
1387
1335
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/guarantors/can_see_charges" => json =>
1388
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/guarantors/can_see_charges" => json =>
1336
            { allowed => Mojo::JSON->true } )->status_is(403)
1389
            { allowed => Mojo::JSON->true } )
1390
        ->status_is(403)
1337
        ->json_is( '/error', 'The current configuration doesn\'t allow the requested action.' );
1391
        ->json_is( '/error', 'The current configuration doesn\'t allow the requested action.' );
1338
1392
1339
    t::lib::Mocks::mock_preference( 'AllowPatronToSetFinesVisibilityForGuarantor', 1 );
1393
    t::lib::Mocks::mock_preference( 'AllowPatronToSetFinesVisibilityForGuarantor', 1 );
Lines 1371-1383 subtest 'guarantors_can_see_checkouts() tests' => sub { Link Here
1371
            { allowed => Mojo::JSON->true } )->status_is(401)->json_is( { error => "Authentication failure." } );
1425
            { allowed => Mojo::JSON->true } )->status_is(401)->json_is( { error => "Authentication failure." } );
1372
1426
1373
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$other_patron_id/guarantors/can_see_checkouts" => json =>
1427
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$other_patron_id/guarantors/can_see_checkouts" => json =>
1374
            { allowed => Mojo::JSON->true } )->status_is(403)
1428
            { allowed => Mojo::JSON->true } )
1429
        ->status_is(403)
1375
        ->json_is( { error => "Unprivileged user cannot access another user's resources" } );
1430
        ->json_is( { error => "Unprivileged user cannot access another user's resources" } );
1376
1431
1377
    t::lib::Mocks::mock_preference( 'AllowPatronToSetCheckoutsVisibilityForGuarantor', 0 );
1432
    t::lib::Mocks::mock_preference( 'AllowPatronToSetCheckoutsVisibilityForGuarantor', 0 );
1378
1433
1379
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/guarantors/can_see_checkouts" => json =>
1434
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/guarantors/can_see_checkouts" => json =>
1380
            { allowed => Mojo::JSON->true } )->status_is(403)
1435
            { allowed => Mojo::JSON->true } )
1436
        ->status_is(403)
1381
        ->json_is( '/error', 'The current configuration doesn\'t allow the requested action.' );
1437
        ->json_is( '/error', 'The current configuration doesn\'t allow the requested action.' );
1382
1438
1383
    t::lib::Mocks::mock_preference( 'AllowPatronToSetCheckoutsVisibilityForGuarantor', 1 );
1439
    t::lib::Mocks::mock_preference( 'AllowPatronToSetCheckoutsVisibilityForGuarantor', 1 );
Lines 1420-1426 sub unauthorized_access_tests { Link Here
1420
        $unauthorized_patron->set_password( { password => $password, skip_validation => 1 } );
1476
        $unauthorized_patron->set_password( { password => $password, skip_validation => 1 } );
1421
        my $unauth_userid = $unauthorized_patron->userid;
1477
        my $unauth_userid = $unauthorized_patron->userid;
1422
1478
1423
        $t->$verb_ok( "//$unauth_userid:$password\@$endpoint" => json => $json )->status_is(403)
1479
        $t->$verb_ok( "//$unauth_userid:$password\@$endpoint" => json => $json )
1480
            ->status_is(403)
1424
            ->json_has('/required_permissions');
1481
            ->json_has('/required_permissions');
1425
    };
1482
    };
1426
}
1483
}
(-)a/t/db_dependent/api/v1/patrons_accounts.t (-15 / +29 lines)
Lines 89-96 subtest 'get_balance() tests' => sub { Link Here
89
    )->store();
89
    )->store();
90
    $debit_2->discard_changes;
90
    $debit_2->discard_changes;
91
91
92
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")->status_is(200)
92
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
93
        ->or( sub { diag $t->tx->res->body } )->json_is(
93
        ->status_is(200)
94
        ->or( sub { diag $t->tx->res->body } )
95
        ->json_is(
94
        {
96
        {
95
            balance            => 100.01,
97
            balance            => 100.01,
96
            outstanding_debits => {
98
            outstanding_debits => {
Lines 212-221 subtest 'add_credit() tests' => sub { Link Here
212
214
213
    my $ret =
215
    my $ret =
214
        $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit )
216
        $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit )
215
        ->status_is(201)->header_is(
217
        ->status_is(201)
218
        ->header_is(
216
        'Location' => "/api/v1/patrons/$patron_id/account/credits/" . $t->tx->res->json->{account_line_id},
219
        'Location' => "/api/v1/patrons/$patron_id/account/credits/" . $t->tx->res->json->{account_line_id},
217
        "REST3.4.1"
220
        "REST3.4.1"
218
    )->tx->res->json;
221
        )->tx->res->json;
219
222
220
    is_deeply(
223
    is_deeply(
221
        $ret,
224
        $ret,
Lines 224-230 subtest 'add_credit() tests' => sub { Link Here
224
    );
227
    );
225
228
226
    my $outstanding_credits = $account->outstanding_credits;
229
    my $outstanding_credits = $account->outstanding_credits;
227
    is( $outstanding_credits->count,             1 );
230
    is( $outstanding_credits->count,              1 );
228
    is( $outstanding_credits->total_outstanding, -100 );
231
    is( $outstanding_credits->total_outstanding, -100 );
229
232
230
    my $debit_1 = $account->add_debit(
233
    my $debit_1 = $account->add_debit(
Lines 249-256 subtest 'add_credit() tests' => sub { Link Here
249
    is( $account->outstanding_debits->total_outstanding, 25 );
252
    is( $account->outstanding_debits->total_outstanding, 25 );
250
    $credit->{library_id} = $library->id;
253
    $credit->{library_id} = $library->id;
251
254
252
    $ret = $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit )
255
    $ret =
253
        ->status_is(201)->tx->res->json;
256
        $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit )
257
        ->status_is(201)
258
        ->tx->res->json;
254
259
255
    is_deeply(
260
    is_deeply(
256
        $ret,
261
        $ret,
Lines 284-291 subtest 'add_credit() tests' => sub { Link Here
284
        account_lines_ids => [ $debit_1->id, $debit_2->id, $debit_3->id ]
289
        account_lines_ids => [ $debit_1->id, $debit_2->id, $debit_3->id ]
285
    };
290
    };
286
291
287
    $ret = $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit )
292
    $ret =
288
        ->status_is(201)->tx->res->json;
293
        $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit )
294
        ->status_is(201)
295
        ->tx->res->json;
289
296
290
    is_deeply(
297
    is_deeply(
291
        $ret,
298
        $ret,
Lines 422-429 subtest 'add_debit() tests' => sub { Link Here
422
        library_id  => $library->id,
429
        library_id  => $library->id,
423
    };
430
    };
424
431
425
    my $ret = $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $debit )
432
    my $ret =
426
        ->status_is(201)->json_is( '/user_id' => $librarian_x->id, 'Passed user_id is stored' )->tx->res->json;
433
        $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $debit )
434
        ->status_is(201)
435
        ->json_is( '/user_id' => $librarian_x->id, 'Passed user_id is stored' )
436
        ->tx->res->json;
427
    my $account_line = Koha::Account::Debits->find( $ret->{account_line_id} );
437
    my $account_line = Koha::Account::Debits->find( $ret->{account_line_id} );
428
438
429
    is_deeply( $ret, $account_line->to_api, 'Line returned correctly' );
439
    is_deeply( $ret, $account_line->to_api, 'Line returned correctly' );
Lines 458-464 subtest 'add_debit() tests' => sub { Link Here
458
468
459
    my $account_line_id = $ret->{account_line_id};
469
    my $account_line_id = $ret->{account_line_id};
460
470
461
    $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $debit )->status_is(201)
471
    $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $debit )
472
        ->status_is(201)
462
        ->header_is(
473
        ->header_is(
463
        'Location' => "/api/v1/patrons/$patron_id/account/debits/" . $t->tx->res->json->{account_line_id},
474
        'Location' => "/api/v1/patrons/$patron_id/account/debits/" . $t->tx->res->json->{account_line_id},
464
        "REST3.4.1"
475
        "REST3.4.1"
Lines 480-492 subtest 'add_debit() tests' => sub { Link Here
480
        library_id  => $library->id,
491
        library_id  => $library->id,
481
    };
492
    };
482
493
483
    $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $payout )->status_is(400)
494
    $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $payout )
495
        ->status_is(400)
484
        ->json_is( '/error' => 'Account transaction requires a cash register' );
496
        ->json_is( '/error' => 'Account transaction requires a cash register' );
485
497
486
    my $register = $builder->build_object( { class => 'Koha::Cash::Registers', } );
498
    my $register = $builder->build_object( { class => 'Koha::Cash::Registers', } );
487
    $payout->{cash_register_id} = $register->id;
499
    $payout->{cash_register_id} = $register->id;
488
    my $res = $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $payout )
500
    my $res =
489
        ->status_is(201)->tx->res->json;
501
        $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $payout )
502
        ->status_is(201)
503
        ->tx->res->json;
490
504
491
    is( $res->{user_id}, $librarian->id, 'If not passed, the session user ID is picked' );
505
    is( $res->{user_id}, $librarian->id, 'If not passed, the session user ID is picked' );
492
506
(-)a/t/db_dependent/api/v1/patrons_checkouts.t (-4 / +8 lines)
Lines 67-80 subtest 'Patron checkouts list() tests' => sub { Link Here
67
    my $issue1 = C4::Circulation::AddIssue( $patron, $item1->barcode, $date_due );
67
    my $issue1 = C4::Circulation::AddIssue( $patron, $item1->barcode, $date_due );
68
    my $issue2 = C4::Circulation::AddIssue( $patron, $item2->barcode, $date_due );
68
    my $issue2 = C4::Circulation::AddIssue( $patron, $item2->barcode, $date_due );
69
69
70
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/checkouts' )->status_is(200)
70
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/checkouts' )
71
        ->json_is( '/0/item_id' => $item1->itemnumber )->json_is( '/1/item_id' => $item2->itemnumber );
71
        ->status_is(200)
72
        ->json_is( '/0/item_id' => $item1->itemnumber )
73
        ->json_is( '/1/item_id' => $item2->itemnumber );
72
74
73
    my $non_existent_patron    = $builder->build_object( { class => 'Koha::Patrons' } );
75
    my $non_existent_patron    = $builder->build_object( { class => 'Koha::Patrons' } );
74
    my $non_existent_patron_id = $non_existent_patron->id;
76
    my $non_existent_patron_id = $non_existent_patron->id;
75
    $non_existent_patron->delete;
77
    $non_existent_patron->delete;
76
78
77
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $non_existent_patron_id . '/checkouts' )->status_is(404)
79
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $non_existent_patron_id . '/checkouts' )
80
        ->status_is(404)
78
        ->json_is( '/error' => 'Patron not found' );
81
        ->json_is( '/error' => 'Patron not found' );
79
82
80
    my $unauthorized_patron = $builder->build_object(
83
    my $unauthorized_patron = $builder->build_object(
Lines 89-93 subtest 'Patron checkouts list() tests' => sub { Link Here
89
    my $unauthorized_userid = $unauthorized_patron->userid;
92
    my $unauthorized_userid = $unauthorized_patron->userid;
90
93
91
    $t->get_ok( "//$unauthorized_userid:$unauthorized_password@/api/v1/patrons/" . $patron->id . '/checkouts' )
94
    $t->get_ok( "//$unauthorized_userid:$unauthorized_password@/api/v1/patrons/" . $patron->id . '/checkouts' )
92
        ->status_is(403)->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
95
        ->status_is(403)
96
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
93
    }
97
    }
(-)a/t/db_dependent/api/v1/patrons_extended_attributes.t (-16 / +32 lines)
Lines 50-56 subtest 'list_patron_attributes() tests' => sub { Link Here
50
    my $userid = $patron->userid;
50
    my $userid = $patron->userid;
51
51
52
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/extended_attributes' )
52
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/extended_attributes' )
53
        ->status_is( 200, 'REST3.2.2' )->json_is( [] );
53
        ->status_is( 200, 'REST3.2.2' )
54
        ->json_is( [] );
54
55
55
    # Let's add 3 attributes
56
    # Let's add 3 attributes
56
    foreach my $i ( 1 .. 5 ) {
57
    foreach my $i ( 1 .. 5 ) {
Lines 68-74 subtest 'list_patron_attributes() tests' => sub { Link Here
68
    $non_existent_patron->delete;
69
    $non_existent_patron->delete;
69
70
70
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $non_existent_patron_id . '/extended_attributes' )
71
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $non_existent_patron_id . '/extended_attributes' )
71
        ->status_is(404)->json_is( '/error' => 'Patron not found' );
72
        ->status_is(404)
73
        ->json_is( '/error' => 'Patron not found' );
72
74
73
    subtest 'nullable value' => sub {
75
    subtest 'nullable value' => sub {
74
76
Lines 86-92 subtest 'list_patron_attributes() tests' => sub { Link Here
86
        );
88
        );
87
89
88
        $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $user->id . '/extended_attributes' )
90
        $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $user->id . '/extended_attributes' )
89
            ->status_is( 200, 'REST3.2.2' )->json_is(
91
            ->status_is( 200, 'REST3.2.2' )
92
            ->json_is(
90
            '' => $user->extended_attributes->to_api,
93
            '' => $user->extended_attributes->to_api,
91
            'Extended attributes retrieved correctly'
94
            'Extended attributes retrieved correctly'
92
            );
95
            );
Lines 155-167 subtest 'add() tests' => sub { Link Here
155
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
158
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
156
            . $non_existent_patron_id
159
            . $non_existent_patron_id
157
            . '/extended_attributes' => json => { type => $repeatable_attr_type->code, value => 'something' } )
160
            . '/extended_attributes' => json => { type => $repeatable_attr_type->code, value => 'something' } )
158
        ->status_is(404)->json_is( '/error' => 'Patron not found' );
161
        ->status_is(404)
162
        ->json_is( '/error' => 'Patron not found' );
159
163
160
    my $response =
164
    my $response =
161
        $t->post_ok( "//$userid:$password@/api/v1/patrons/"
165
        $t->post_ok( "//$userid:$password@/api/v1/patrons/"
162
            . $patron->id
166
            . $patron->id
163
            . '/extended_attributes' => json => { type => $repeatable_attr_type->code, value => 'something' } )
167
            . '/extended_attributes' => json => { type => $repeatable_attr_type->code, value => 'something' } )
164
        ->status_is(201)->tx->res->json;
168
        ->status_is(201)
169
        ->tx->res->json;
165
170
166
    is_deeply(
171
    is_deeply(
167
        Koha::Patron::Attributes->find( $response->{extended_attribute_id} )->to_api,
172
        Koha::Patron::Attributes->find( $response->{extended_attribute_id} )->to_api,
Lines 210-216 subtest 'add() tests' => sub { Link Here
210
215
211
        $t->post_ok( "//$userid:$password@/api/v1/patrons/"
216
        $t->post_ok( "//$userid:$password@/api/v1/patrons/"
212
                . $patron->id
217
                . $patron->id
213
                . '/extended_attributes' => json => { type => $invalid_type, value => 'blah' } )->status_is(400)
218
                . '/extended_attributes' => json => { type => $invalid_type, value => 'blah' } )
219
            ->status_is(400)
214
            ->json_is( '/error' => "Tried to use an invalid attribute type. type=$invalid_type" );
220
            ->json_is( '/error' => "Tried to use an invalid attribute type. type=$invalid_type" );
215
    };
221
    };
216
222
Lines 281-291 subtest 'overwrite() tests' => sub { Link Here
281
    $t->put_ok( "//$userid:$password@/api/v1/patrons/"
287
    $t->put_ok( "//$userid:$password@/api/v1/patrons/"
282
            . $non_existent_patron_id
288
            . $non_existent_patron_id
283
            . '/extended_attributes' => json => [ { type => $repeatable_attr_type->code, value => 'something' } ] )
289
            . '/extended_attributes' => json => [ { type => $repeatable_attr_type->code, value => 'something' } ] )
284
        ->status_is(404)->json_is( '/error' => 'Patron not found' );
290
        ->status_is(404)
291
        ->json_is( '/error' => 'Patron not found' );
285
292
286
    $t->put_ok( "//$userid:$password@/api/v1/patrons/"
293
    $t->put_ok( "//$userid:$password@/api/v1/patrons/"
287
            . $patron->id
294
            . $patron->id
288
            . '/extended_attributes' => json => [ { type => $invalid_type, value => 'something' } ] )->status_is(400)
295
            . '/extended_attributes' => json => [ { type => $invalid_type, value => 'something' } ] )
296
        ->status_is(400)
289
        ->json_is( '/error' => "Tried to use an invalid attribute type. type=$invalid_type" );
297
        ->json_is( '/error' => "Tried to use an invalid attribute type. type=$invalid_type" );
290
298
291
    my $unique_value = 'The only one!';
299
    my $unique_value = 'The only one!';
Lines 308-314 subtest 'overwrite() tests' => sub { Link Here
308
            { type => $unique_attr_type->code, value => $value_1 },
316
            { type => $unique_attr_type->code, value => $value_1 },
309
            { type => $unique_attr_type->code, value => $value_2 }
317
            { type => $unique_attr_type->code, value => $value_2 }
310
        ]
318
        ]
311
    )->status_is(409)
319
        )
320
        ->status_is(409)
312
        ->json_is( '/error' => "Tried to add more than one non-repeatable attributes. type="
321
        ->json_is( '/error' => "Tried to add more than one non-repeatable attributes. type="
313
            . $unique_attr_type->code
322
            . $unique_attr_type->code
314
            . " value=$value_2" );
323
            . " value=$value_2" );
Lines 349-362 subtest 'overwrite() tests' => sub { Link Here
349
358
350
    $t->put_ok(
359
    $t->put_ok(
351
        "//$userid:$password@/api/v1/patrons/" . $patron->id . '/extended_attributes' => json => $updated_attributes )
360
        "//$userid:$password@/api/v1/patrons/" . $patron->id . '/extended_attributes' => json => $updated_attributes )
352
        ->status_is(200)->json_is( '/0/type' => $updated_attributes->[0]->{type} )
361
        ->status_is(200)
362
        ->json_is( '/0/type'  => $updated_attributes->[0]->{type} )
353
        ->json_is( '/0/value' => $updated_attributes->[0]->{value} )
363
        ->json_is( '/0/value' => $updated_attributes->[0]->{value} )
354
        ->json_is( '/1/type'  => $updated_attributes->[1]->{type} )
364
        ->json_is( '/1/type'  => $updated_attributes->[1]->{type} )
355
        ->json_is( '/1/value' => $updated_attributes->[1]->{value} )
365
        ->json_is( '/1/value' => $updated_attributes->[1]->{value} )
356
        ->json_is( '/2/type'  => $updated_attributes->[2]->{type} )
366
        ->json_is( '/2/type'  => $updated_attributes->[2]->{type} )
357
        ->json_is( '/2/value' => $updated_attributes->[2]->{value} )
367
        ->json_is( '/2/value' => $updated_attributes->[2]->{value} )
358
        ->json_is( '/3/type'  => $updated_attributes->[3]->{type} )
368
        ->json_is( '/3/type'  => $updated_attributes->[3]->{type} )
359
        ->json_is( '/3/value' => $updated_attributes->[3]->{value} )->json_hasnt('/4');
369
        ->json_is( '/3/value' => $updated_attributes->[3]->{value} )
370
        ->json_hasnt('/4');
360
371
361
    $schema->storage->txn_rollback;
372
    $schema->storage->txn_rollback;
362
};
373
};
Lines 394-408 subtest 'delete() tests' => sub { Link Here
394
    my $attr = $dummy_patron->add_extended_attribute( { code => $attr_type->code, attribute => 'blah' } );
405
    my $attr = $dummy_patron->add_extended_attribute( { code => $attr_type->code, attribute => 'blah' } );
395
406
396
    $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $dummy_patron->id . '/extended_attributes/' . $attr->id )
407
    $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $dummy_patron->id . '/extended_attributes/' . $attr->id )
397
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
408
        ->status_is( 204, 'REST3.2.4' )
409
        ->content_is( '', 'REST3.3.4' );
398
410
399
    $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $dummy_patron->id . '/extended_attributes/' . $attr->id )
411
    $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $dummy_patron->id . '/extended_attributes/' . $attr->id )
400
        ->status_is(404)->json_is( '/error' => 'Attribute not found' );
412
        ->status_is(404)
413
        ->json_is( '/error' => 'Attribute not found' );
401
414
402
    $dummy_patron->delete;
415
    $dummy_patron->delete;
403
416
404
    $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $dummy_patron->id . '/extended_attributes/' . $attr->id )
417
    $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $dummy_patron->id . '/extended_attributes/' . $attr->id )
405
        ->status_is(404)->json_is( '/error' => 'Patron not found' );
418
        ->status_is(404)
419
        ->json_is( '/error' => 'Patron not found' );
406
420
407
    $schema->storage->txn_rollback;
421
    $schema->storage->txn_rollback;
408
};
422
};
Lines 478-484 subtest 'update() tests' => sub { Link Here
478
    $t->patch_ok( "//$userid:$password@/api/v1/patrons/"
492
    $t->patch_ok( "//$userid:$password@/api/v1/patrons/"
479
            . $patron->id
493
            . $patron->id
480
            . '/extended_attributes/'
494
            . '/extended_attributes/'
481
            . $non_existent_attribute_id => json => { value => 'something' } )->status_is(404)
495
            . $non_existent_attribute_id => json => { value => 'something' } )
496
        ->status_is(404)
482
        ->json_is( '/error' => 'Attribute not found' );
497
        ->json_is( '/error' => 'Attribute not found' );
483
498
484
    my $response =
499
    my $response =
Lines 506-512 subtest 'update() tests' => sub { Link Here
506
    $t->patch_ok( "//$userid:$password@/api/v1/patrons/"
521
    $t->patch_ok( "//$userid:$password@/api/v1/patrons/"
507
            . $patron->id
522
            . $patron->id
508
            . '/extended_attributes/'
523
            . '/extended_attributes/'
509
            . $unique_attribute->id => json => { value => $unique_value } )->status_is(409)
524
            . $unique_attribute->id => json => { value => $unique_value } )
525
        ->status_is(409)
510
        ->json_is( '/error' => "Your action breaks a unique constraint on the attribute. type="
526
        ->json_is( '/error' => "Your action breaks a unique constraint on the attribute. type="
511
            . $unique_attr_type->code
527
            . $unique_attr_type->code
512
            . " value=$unique_value" );
528
            . " value=$unique_value" );
(-)a/t/db_dependent/api/v1/patrons_holds.t (-8 / +16 lines)
Lines 50-56 subtest 'list() tests' => sub { Link Here
50
    $patron->set_password( { password => $password, skip_validation => 1 } );
50
    $patron->set_password( { password => $password, skip_validation => 1 } );
51
    my $userid = $patron->userid;
51
    my $userid = $patron->userid;
52
52
53
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds' )->status_is( 200, 'REST3.2.2' )
53
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds' )
54
        ->status_is( 200, 'REST3.2.2' )
54
        ->json_is( [] );
55
        ->json_is( [] );
55
56
56
    my $hold_1 = $builder->build_object( { class => 'Koha::Holds', value => { borrowernumber => $patron->id } } );
57
    my $hold_1 = $builder->build_object( { class => 'Koha::Holds', value => { borrowernumber => $patron->id } } );
Lines 65-71 subtest 'list() tests' => sub { Link Here
65
    $hold_3->fill;
66
    $hold_3->fill;
66
67
67
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?_order_by=+me.hold_id' )
68
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?_order_by=+me.hold_id' )
68
        ->status_is( 200, 'REST3.2.2' )->json_is( '' => [ $hold_2->to_api ], 'Only current holds retrieved' );
69
        ->status_is( 200, 'REST3.2.2' )
70
        ->json_is( '' => [ $hold_2->to_api ], 'Only current holds retrieved' );
69
71
70
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?old=1&_order_by=+me.hold_id' )
72
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?old=1&_order_by=+me.hold_id' )
71
        ->status_is( 200, 'REST3.2.2' )
73
        ->status_is( 200, 'REST3.2.2' )
Lines 76-89 subtest 'list() tests' => sub { Link Here
76
    $old_hold_1->pickup_library->delete;
78
    $old_hold_1->pickup_library->delete;
77
79
78
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?old=1&_order_by=+me.hold_id' )
80
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?old=1&_order_by=+me.hold_id' )
79
        ->status_is( 200, 'REST3.2.2' )->json_is(
81
        ->status_is( 200, 'REST3.2.2' )
82
        ->json_is(
80
        '' => [ $old_hold_1->get_from_storage->to_api, $hold_3->to_api ],
83
        '' => [ $old_hold_1->get_from_storage->to_api, $hold_3->to_api ],
81
        'Old holds even after item and library removed'
84
        'Old holds even after item and library removed'
82
        );
85
        );
83
86
84
    $old_hold_1->biblio->delete;
87
    $old_hold_1->biblio->delete;
85
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?old=1&_order_by=+me.hold_id' )
88
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?old=1&_order_by=+me.hold_id' )
86
        ->status_is( 200, 'REST3.2.2' )->json_is(
89
        ->status_is( 200, 'REST3.2.2' )
90
        ->json_is(
87
        '' => [ $old_hold_1->get_from_storage->to_api, $hold_3->to_api ],
91
        '' => [ $old_hold_1->get_from_storage->to_api, $hold_3->to_api ],
88
        'Old holds even after biblio removed'
92
        'Old holds even after biblio removed'
89
        );
93
        );
Lines 94-100 subtest 'list() tests' => sub { Link Here
94
    # get rid of the patron
98
    # get rid of the patron
95
    $non_existent_patron->delete;
99
    $non_existent_patron->delete;
96
100
97
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $non_existent_patron_id . '/holds' )->status_is(404)
101
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $non_existent_patron_id . '/holds' )
102
        ->status_is(404)
98
        ->json_is( '/error' => 'Patron not found' );
103
        ->json_is( '/error' => 'Patron not found' );
99
104
100
    $schema->storage->txn_rollback;
105
    $schema->storage->txn_rollback;
Lines 122-128 subtest 'delete_public() tests' => sub { Link Here
122
    my $deleted_hold_id = $hold_to_delete->id;
127
    my $deleted_hold_id = $hold_to_delete->id;
123
    $hold_to_delete->delete;
128
    $hold_to_delete->delete;
124
129
125
    $t->delete_ok( "/api/v1/public/patrons/" . $patron->id . '/holds/' . $deleted_hold_id )->status_is(401)
130
    $t->delete_ok( "/api/v1/public/patrons/" . $patron->id . '/holds/' . $deleted_hold_id )
131
        ->status_is(401)
126
        ->json_is( { error => 'Authentication failure.' } );
132
        ->json_is( { error => 'Authentication failure.' } );
127
133
128
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/" . $patron->id . '/holds/' . $deleted_hold_id )
134
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/" . $patron->id . '/holds/' . $deleted_hold_id )
Lines 151-157 subtest 'delete_public() tests' => sub { Link Here
151
    );
157
    );
152
158
153
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/" . $patron->id . '/holds/' . $non_waiting_hold->id )
159
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/" . $patron->id . '/holds/' . $non_waiting_hold->id )
154
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
160
        ->status_is( 204, 'REST3.2.4' )
161
        ->content_is( '', 'REST3.3.4' );
155
162
156
    my $cancellation_requestable;
163
    my $cancellation_requestable;
157
164
Lines 173-179 subtest 'delete_public() tests' => sub { Link Here
173
    $cancellation_requestable = 0;
180
    $cancellation_requestable = 0;
174
181
175
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/" . $patron->id . '/holds/' . $waiting_hold->id )
182
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/" . $patron->id . '/holds/' . $waiting_hold->id )
176
        ->status_is(403)->json_is( { error => 'Cancellation forbidden' } );
183
        ->status_is(403)
184
        ->json_is( { error => 'Cancellation forbidden' } );
177
185
178
    $cancellation_requestable = 1;
186
    $cancellation_requestable = 1;
179
187
(-)a/t/db_dependent/api/v1/patrons_password.t (-7 / +14 lines)
Lines 59-101 subtest 'set() (authorized user tests)' => sub { Link Here
59
59
60
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
60
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
61
            . $patron->id
61
            . $patron->id
62
            . "/password" => json => { password => $new_password, password_2 => $new_password } )->status_is(200)
62
            . "/password" => json => { password => $new_password, password_2 => $new_password } )
63
        ->status_is(200)
63
        ->json_is('');
64
        ->json_is('');
64
65
65
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
66
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
66
            . $patron->id
67
            . $patron->id
67
            . "/password" => json => { password => $new_password, password_2 => 'cde' } )->status_is(400)
68
            . "/password" => json => { password => $new_password, password_2 => 'cde' } )
69
        ->status_is(400)
68
        ->json_is( { error => 'Passwords don\'t match' } );
70
        ->json_is( { error => 'Passwords don\'t match' } );
69
71
70
    t::lib::Mocks::mock_preference( 'minPasswordLength', 5 );
72
    t::lib::Mocks::mock_preference( 'minPasswordLength', 5 );
71
73
72
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
74
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
73
            . $patron->id
75
            . $patron->id
74
            . "/password" => json => { password => $new_password, password_2 => $new_password } )->status_is(400)
76
            . "/password" => json => { password => $new_password, password_2 => $new_password } )
77
        ->status_is(400)
75
        ->json_is( { error => 'Password length (3) is shorter than required (5)' } );
78
        ->json_is( { error => 'Password length (3) is shorter than required (5)' } );
76
79
77
    $new_password = 'abc   ';
80
    $new_password = 'abc   ';
78
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
81
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
79
            . $patron->id
82
            . $patron->id
80
            . "/password" => json => { password => $new_password, password_2 => $new_password } )->status_is(400)
83
            . "/password" => json => { password => $new_password, password_2 => $new_password } )
84
        ->status_is(400)
81
        ->json_is( { error => '[Password contains leading/trailing whitespace character(s)]' } );
85
        ->json_is( { error => '[Password contains leading/trailing whitespace character(s)]' } );
82
86
83
    $new_password = 'abcdefg';
87
    $new_password = 'abcdefg';
84
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
88
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
85
            . $patron->id
89
            . $patron->id
86
            . "/password" => json => { password => $new_password, password_2 => $new_password } )->status_is(200)
90
            . "/password" => json => { password => $new_password, password_2 => $new_password } )
91
        ->status_is(200)
87
        ->json_is('');
92
        ->json_is('');
88
93
89
    t::lib::Mocks::mock_preference( 'RequireStrongPassword', 1 );
94
    t::lib::Mocks::mock_preference( 'RequireStrongPassword', 1 );
90
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
95
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
91
            . $patron->id
96
            . $patron->id
92
            . "/password" => json => { password => $new_password, password_2 => $new_password } )->status_is(400)
97
            . "/password" => json => { password => $new_password, password_2 => $new_password } )
98
        ->status_is(400)
93
        ->json_is( { error => '[Password is too weak]' } );
99
        ->json_is( { error => '[Password is too weak]' } );
94
100
95
    $new_password = 'ABcde123%&';
101
    $new_password = 'ABcde123%&';
96
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
102
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
97
            . $patron->id
103
            . $patron->id
98
            . "/password" => json => { password => $new_password, password_2 => $new_password } )->status_is(200)
104
            . "/password" => json => { password => $new_password, password_2 => $new_password } )
105
        ->status_is(200)
99
        ->json_is('');
106
        ->json_is('');
100
107
101
    $schema->storage->txn_rollback;
108
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/patrons_password_expiration.t (-2 / +4 lines)
Lines 60-71 subtest 'basic tests' => sub { Link Here
60
60
61
    $t->put_ok( "//$userid:$password@/api/v1/patrons/"
61
    $t->put_ok( "//$userid:$password@/api/v1/patrons/"
62
            . $patron->id
62
            . $patron->id
63
            . "/password/expiration_date" => json => { expiration_date => '01/13/2021' } )->status_is(400)
63
            . "/password/expiration_date" => json => { expiration_date => '01/13/2021' } )
64
        ->status_is(400)
64
        ->json_is( '/errors/0/message' => 'Does not match date format.' );
65
        ->json_is( '/errors/0/message' => 'Does not match date format.' );
65
66
66
    $t->put_ok( "//$userid:$password@/api/v1/patrons/"
67
    $t->put_ok( "//$userid:$password@/api/v1/patrons/"
67
            . $patron->id
68
            . $patron->id
68
            . "/password/expiration_date" => json => { expiration_date => '13/01/2021' } )->status_is(400)
69
            . "/password/expiration_date" => json => { expiration_date => '13/01/2021' } )
70
        ->status_is(400)
69
        ->json_is( '/errors/0/message' => 'Does not match date format.' );
71
        ->json_is( '/errors/0/message' => 'Does not match date format.' );
70
72
71
    $privileged_patron->flags(0)->store();
73
    $privileged_patron->flags(0)->store();
(-)a/t/db_dependent/api/v1/patrons_recalls.t (-5 / +10 lines)
Lines 49-55 subtest 'list() tests' => sub { Link Here
49
    $patron->set_password( { password => $password, skip_validation => 1 } );
49
    $patron->set_password( { password => $password, skip_validation => 1 } );
50
    my $userid = $patron->userid;
50
    my $userid = $patron->userid;
51
51
52
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/recalls' )->status_is( 200, 'REST3.2.2' )
52
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/recalls' )
53
        ->status_is( 200, 'REST3.2.2' )
53
        ->json_is( [] );
54
        ->json_is( [] );
54
55
55
    my $recall_1 = $builder->build_object( { class => 'Koha::Recalls', value => { patron_id => $patron->id } } );
56
    my $recall_1 = $builder->build_object( { class => 'Koha::Recalls', value => { patron_id => $patron->id } } );
Lines 60-74 subtest 'list() tests' => sub { Link Here
60
    my $recall_3 = $builder->build_object( { class => 'Koha::Recalls', value => { patron_id => $patron_2->id } } );
61
    my $recall_3 = $builder->build_object( { class => 'Koha::Recalls', value => { patron_id => $patron_2->id } } );
61
62
62
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/recalls?_order_by=+me.recall_id' )
63
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/recalls?_order_by=+me.recall_id' )
63
        ->status_is( 200, 'REST3.2.2' )->json_is( '' => [ $recall_1->to_api, $recall_2->to_api ], 'Recalls retrieved' );
64
        ->status_is( 200, 'REST3.2.2' )
65
        ->json_is( '' => [ $recall_1->to_api, $recall_2->to_api ], 'Recalls retrieved' );
64
66
65
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->id . '/recalls?_order_by=+me.recall_id' )
67
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->id . '/recalls?_order_by=+me.recall_id' )
66
        ->status_is( 200, 'REST3.2.2' )->json_is( '' => [ $recall_3->to_api ], 'Recalls retrieved' );
68
        ->status_is( 200, 'REST3.2.2' )
69
        ->json_is( '' => [ $recall_3->to_api ], 'Recalls retrieved' );
67
70
68
    $recall_3->delete;
71
    $recall_3->delete;
69
72
70
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->id . '/recalls?_order_by=+me.recall_id' )
73
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->id . '/recalls?_order_by=+me.recall_id' )
71
        ->status_is( 200, 'REST3.2.2' )->json_is( [] );
74
        ->status_is( 200, 'REST3.2.2' )
75
        ->json_is( [] );
72
76
73
    my $non_existent_patron    = $builder->build_object( { class => 'Koha::Patrons' } );
77
    my $non_existent_patron    = $builder->build_object( { class => 'Koha::Patrons' } );
74
    my $non_existent_patron_id = $non_existent_patron->id;
78
    my $non_existent_patron_id = $non_existent_patron->id;
Lines 76-82 subtest 'list() tests' => sub { Link Here
76
    # get rid of the patron
80
    # get rid of the patron
77
    $non_existent_patron->delete;
81
    $non_existent_patron->delete;
78
82
79
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $non_existent_patron_id . '/recalls' )->status_is(404)
83
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $non_existent_patron_id . '/recalls' )
84
        ->status_is(404)
80
        ->json_is( '/error' => 'Patron not found' );
85
        ->json_is( '/error' => 'Patron not found' );
81
86
82
    $schema->storage->txn_rollback;
87
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/preservation_Processings.t (-11 / +21 lines)
Lines 72-78 subtest 'list() tests' => sub { Link Here
72
    );
72
    );
73
73
74
    # One processing created, should get returned
74
    # One processing created, should get returned
75
    $t->get_ok("//$userid:$password@/api/v1/preservation/processings")->status_is(200)
75
    $t->get_ok("//$userid:$password@/api/v1/preservation/processings")
76
        ->status_is(200)
76
        ->json_is( [ $processing->to_api ] );
77
        ->json_is( [ $processing->to_api ] );
77
78
78
    # Unauthorized access
79
    # Unauthorized access
Lines 122-133 subtest 'get() tests' => sub { Link Here
122
    my $unauth_userid = $patron->userid;
123
    my $unauth_userid = $patron->userid;
123
124
124
    # This processing exists, should get returned
125
    # This processing exists, should get returned
125
    $t->get_ok( "//$userid:$password@/api/v1/preservation/processings/" . $processing->processing_id )->status_is(200)
126
    $t->get_ok( "//$userid:$password@/api/v1/preservation/processings/" . $processing->processing_id )
127
        ->status_is(200)
126
        ->json_is( $processing->to_api );
128
        ->json_is( $processing->to_api );
127
129
128
    # Return one processing with attributes
130
    # Return one processing with attributes
129
    $t->get_ok( "//$userid:$password@/api/v1/preservation/processings/"
131
    $t->get_ok( "//$userid:$password@/api/v1/preservation/processings/"
130
            . $processing->processing_id => { 'x-koha-embed' => 'attributes' } )->status_is(200)
132
            . $processing->processing_id => { 'x-koha-embed' => 'attributes' } )
133
        ->status_is(200)
131
        ->json_is( { %{ $processing->to_api }, attributes => $attributes->to_api } );
134
        ->json_is( { %{ $processing->to_api }, attributes => $attributes->to_api } );
132
135
133
    # Unauthorized access
136
    # Unauthorized access
Lines 139-145 subtest 'get() tests' => sub { Link Here
139
    my $non_existent_id      = $processing_to_delete->processing_id;
142
    my $non_existent_id      = $processing_to_delete->processing_id;
140
    $processing_to_delete->delete;
143
    $processing_to_delete->delete;
141
144
142
    $t->get_ok("//$userid:$password@/api/v1/preservation/processings/$non_existent_id")->status_is(404)
145
    $t->get_ok("//$userid:$password@/api/v1/preservation/processings/$non_existent_id")
146
        ->status_is(404)
143
        ->json_is( '/error' => 'Processing not found' );
147
        ->json_is( '/error' => 'Processing not found' );
144
148
145
    $schema->storage->txn_rollback;
149
    $schema->storage->txn_rollback;
Lines 186-192 subtest 'add() tests' => sub { Link Here
186
    };
190
    };
187
191
188
    $t->post_ok( "//$userid:$password@/api/v1/preservation/processings" => json => $processing_with_invalid_field )
192
    $t->post_ok( "//$userid:$password@/api/v1/preservation/processings" => json => $processing_with_invalid_field )
189
        ->status_is(400)->json_is(
193
        ->status_is(400)
194
        ->json_is(
190
        "/errors" => [
195
        "/errors" => [
191
            {
196
            {
192
                message => "Properties not allowed: blah.",
197
                message => "Properties not allowed: blah.",
Lines 198-216 subtest 'add() tests' => sub { Link Here
198
    # Authorized attempt to write
203
    # Authorized attempt to write
199
    my $processing_id =
204
    my $processing_id =
200
        $t->post_ok( "//$userid:$password@/api/v1/preservation/processings" => json => $processing )
205
        $t->post_ok( "//$userid:$password@/api/v1/preservation/processings" => json => $processing )
201
        ->status_is( 201, 'REST3.2.1' )->header_like(
206
        ->status_is( 201, 'REST3.2.1' )
207
        ->header_like(
202
        Location => qr|^/api/v1/preservation/processings/\d*|,
208
        Location => qr|^/api/v1/preservation/processings/\d*|,
203
        'REST3.4.1'
209
        'REST3.4.1'
204
    )->json_is( '/name' => $processing->{name} )->tx->res->json->{processing_id};
210
        )->json_is( '/name' => $processing->{name} )->tx->res->json->{processing_id};
205
211
206
    # Authorized attempt to create with null id
212
    # Authorized attempt to create with null id
207
    $processing->{processing_id} = undef;
213
    $processing->{processing_id} = undef;
208
    $t->post_ok( "//$userid:$password@/api/v1/preservation/processings" => json => $processing )->status_is(400)
214
    $t->post_ok( "//$userid:$password@/api/v1/preservation/processings" => json => $processing )
215
        ->status_is(400)
209
        ->json_has('/errors');
216
        ->json_has('/errors');
210
217
211
    # Authorized attempt to create with existing id
218
    # Authorized attempt to create with existing id
212
    $processing->{processing_id} = $processing_id;
219
    $processing->{processing_id} = $processing_id;
213
    $t->post_ok( "//$userid:$password@/api/v1/preservation/processings" => json => $processing )->status_is(400)
220
    $t->post_ok( "//$userid:$password@/api/v1/preservation/processings" => json => $processing )
221
        ->status_is(400)
214
        ->json_is(
222
        ->json_is(
215
        "/errors" => [
223
        "/errors" => [
216
            {
224
            {
Lines 259-265 subtest 'update() tests' => sub { Link Here
259
    my $processing_with_missing_field = {};
267
    my $processing_with_missing_field = {};
260
268
261
    $t->put_ok( "//$userid:$password@/api/v1/preservation/processings/$processing_id" => json =>
269
    $t->put_ok( "//$userid:$password@/api/v1/preservation/processings/$processing_id" => json =>
262
            $processing_with_missing_field )->status_is(400)
270
            $processing_with_missing_field )
271
        ->status_is(400)
263
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
272
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
264
273
265
    my $default_processing = $builder->build_object( { class => 'Koha::Preservation::Processings' } );
274
    my $default_processing = $builder->build_object( { class => 'Koha::Preservation::Processings' } );
Lines 337-343 subtest 'delete() tests' => sub { Link Here
337
    $t->delete_ok("//$unauth_userid:$password@/api/v1/preservation/processings/$processing_id")->status_is(403);
346
    $t->delete_ok("//$unauth_userid:$password@/api/v1/preservation/processings/$processing_id")->status_is(403);
338
347
339
    # Delete existing processing
348
    # Delete existing processing
340
    $t->delete_ok("//$userid:$password@/api/v1/preservation/processings/$processing_id")->status_is( 204, 'REST3.2.4' )
349
    $t->delete_ok("//$userid:$password@/api/v1/preservation/processings/$processing_id")
350
        ->status_is( 204, 'REST3.2.4' )
341
        ->content_is( '', 'REST3.3.4' );
351
        ->content_is( '', 'REST3.3.4' );
342
352
343
    # Attempt to delete non-existent processing
353
    # Attempt to delete non-existent processing
(-)a/t/db_dependent/api/v1/preservation_Trains.t (-19 / +40 lines)
Lines 110-121 subtest 'get() tests' => sub { Link Here
110
    my $unauth_userid = $patron->userid;
110
    my $unauth_userid = $patron->userid;
111
111
112
    # This train exists, should get returned
112
    # This train exists, should get returned
113
    $t->get_ok( "//$userid:$password@/api/v1/preservation/trains/" . $train->train_id )->status_is(200)
113
    $t->get_ok( "//$userid:$password@/api/v1/preservation/trains/" . $train->train_id )
114
        ->status_is(200)
114
        ->json_is( $train->to_api );
115
        ->json_is( $train->to_api );
115
116
116
    # Return one train with some embeds
117
    # Return one train with some embeds
117
    $t->get_ok( "//$userid:$password@/api/v1/preservation/trains/"
118
    $t->get_ok( "//$userid:$password@/api/v1/preservation/trains/"
118
            . $train->train_id => { 'x-koha-embed' => 'items,default_processing' } )->status_is(200)
119
            . $train->train_id => { 'x-koha-embed' => 'items,default_processing' } )
120
        ->status_is(200)
119
        ->json_is( { %{ $train->to_api }, items => [], default_processing => $default_processing->unblessed } );
121
        ->json_is( { %{ $train->to_api }, items => [], default_processing => $default_processing->unblessed } );
120
122
121
    # Return one train with all embeds
123
    # Return one train with all embeds
Lines 140-146 subtest 'get() tests' => sub { Link Here
140
    my $non_existent_id = $train_to_delete->train_id;
142
    my $non_existent_id = $train_to_delete->train_id;
141
    $train_to_delete->delete;
143
    $train_to_delete->delete;
142
144
143
    $t->get_ok("//$userid:$password@/api/v1/preservation/trains/$non_existent_id")->status_is(404)
145
    $t->get_ok("//$userid:$password@/api/v1/preservation/trains/$non_existent_id")
146
        ->status_is(404)
144
        ->json_is( '/error' => 'Train not found' );
147
        ->json_is( '/error' => 'Train not found' );
145
148
146
    $schema->storage->txn_rollback;
149
    $schema->storage->txn_rollback;
Lines 190-196 subtest 'add() tests' => sub { Link Here
190
    };
193
    };
191
194
192
    $t->post_ok( "//$userid:$password@/api/v1/preservation/trains" => json => $train_with_invalid_field )
195
    $t->post_ok( "//$userid:$password@/api/v1/preservation/trains" => json => $train_with_invalid_field )
193
        ->status_is(400)->json_is(
196
        ->status_is(400)
197
        ->json_is(
194
        "/errors" => [
198
        "/errors" => [
195
            {
199
            {
196
                message => "Properties not allowed: blah.",
200
                message => "Properties not allowed: blah.",
Lines 202-217 subtest 'add() tests' => sub { Link Here
202
    # Authorized attempt to write
206
    # Authorized attempt to write
203
    my $train_id =
207
    my $train_id =
204
        $t->post_ok( "//$userid:$password@/api/v1/preservation/trains" => json => $train )
208
        $t->post_ok( "//$userid:$password@/api/v1/preservation/trains" => json => $train )
205
        ->status_is( 201, 'REST3.2.1' )->header_like(
209
        ->status_is( 201, 'REST3.2.1' )
210
        ->header_like(
206
        Location => qr|^/api/v1/preservation/trains/\d*|,
211
        Location => qr|^/api/v1/preservation/trains/\d*|,
207
        'REST3.4.1'
212
        'REST3.4.1'
208
    )->json_is( '/name' => $train->{name} )->json_is( '/description' => $train->{description} )
213
        )
214
        ->json_is( '/name'                  => $train->{name} )
215
        ->json_is( '/description'           => $train->{description} )
209
        ->json_is( '/default_processing_id' => $train->{default_processing_id} )
216
        ->json_is( '/default_processing_id' => $train->{default_processing_id} )
210
        ->json_is( '/not_for_loan'          => $train->{not_for_loan} )->tx->res->json->{train_id};
217
        ->json_is( '/not_for_loan'          => $train->{not_for_loan} )
218
        ->tx->res->json->{train_id};
211
219
212
    # Authorized attempt to create with null id
220
    # Authorized attempt to create with null id
213
    $train->{train_id} = undef;
221
    $train->{train_id} = undef;
214
    $t->post_ok( "//$userid:$password@/api/v1/preservation/trains" => json => $train )->status_is(400)
222
    $t->post_ok( "//$userid:$password@/api/v1/preservation/trains" => json => $train )
223
        ->status_is(400)
215
        ->json_has('/errors');
224
        ->json_has('/errors');
216
225
217
    # Authorized attempt to create with existing id
226
    # Authorized attempt to create with existing id
Lines 264-270 subtest 'update() tests' => sub { Link Here
264
    my $train_with_missing_field = {};
273
    my $train_with_missing_field = {};
265
274
266
    $t->put_ok( "//$userid:$password@/api/v1/preservation/trains/$train_id" => json => $train_with_missing_field )
275
    $t->put_ok( "//$userid:$password@/api/v1/preservation/trains/$train_id" => json => $train_with_missing_field )
267
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
276
        ->status_is(400)
277
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
268
278
269
    my $default_processing = $builder->build_object( { class => 'Koha::Preservation::Processings' } );
279
    my $default_processing = $builder->build_object( { class => 'Koha::Preservation::Processings' } );
270
280
Lines 277-283 subtest 'update() tests' => sub { Link Here
277
    };
287
    };
278
288
279
    $t->put_ok( "//$userid:$password@/api/v1/preservation/trains/$train_id" => json => $train_with_updated_field )
289
    $t->put_ok( "//$userid:$password@/api/v1/preservation/trains/$train_id" => json => $train_with_updated_field )
280
        ->status_is(200)->json_is( '/name' => 'New name' );
290
        ->status_is(200)
291
        ->json_is( '/name' => 'New name' );
281
292
282
    # Authorized attempt to write invalid data
293
    # Authorized attempt to write invalid data
283
    my $train_with_invalid_field = {
294
    my $train_with_invalid_field = {
Lines 286-292 subtest 'update() tests' => sub { Link Here
286
    };
297
    };
287
298
288
    $t->put_ok( "//$userid:$password@/api/v1/preservation/trains/$train_id" => json => $train_with_invalid_field )
299
    $t->put_ok( "//$userid:$password@/api/v1/preservation/trains/$train_id" => json => $train_with_invalid_field )
289
        ->status_is(400)->json_is(
300
        ->status_is(400)
301
        ->json_is(
290
        "/errors" => [
302
        "/errors" => [
291
            {
303
            {
292
                message => "Properties not allowed: blah.",
304
                message => "Properties not allowed: blah.",
Lines 345-351 subtest 'delete() tests' => sub { Link Here
345
    $t->delete_ok("//$unauth_userid:$password@/api/v1/preservation/trains/$train_id")->status_is(403);
357
    $t->delete_ok("//$unauth_userid:$password@/api/v1/preservation/trains/$train_id")->status_is(403);
346
358
347
    # Delete existing train
359
    # Delete existing train
348
    $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id")->status_is( 204, 'REST3.2.4' )
360
    $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id")
361
        ->status_is( 204, 'REST3.2.4' )
349
        ->content_is( '', 'REST3.3.4' );
362
        ->content_is( '', 'REST3.3.4' );
350
363
351
    # Attempt to delete non-existent train
364
    # Attempt to delete non-existent train
Lines 436-444 subtest '*_item() tests' => sub { Link Here
436
    ];
449
    ];
437
    my $train_item_id =
450
    my $train_item_id =
438
        $t->post_ok( "//$userid:$password@/api/v1/preservation/trains/$train_id/items" => json =>
451
        $t->post_ok( "//$userid:$password@/api/v1/preservation/trains/$train_id/items" => json =>
439
            { item_id => $item_1->itemnumber, attributes => $item_attributes } )->status_is( 201, 'REST3.2.1' )
452
            { item_id => $item_1->itemnumber, attributes => $item_attributes } )
440
        ->json_is( '/item_id' => $item_1->itemnumber )->json_is( '/processing_id' => $train->default_processing_id )
453
        ->status_is( 201, 'REST3.2.1' )
441
        ->json_has('/added_on')->tx->res->json->{train_item_id};
454
        ->json_is( '/item_id'       => $item_1->itemnumber )
455
        ->json_is( '/processing_id' => $train->default_processing_id )
456
        ->json_has('/added_on')
457
        ->tx->res->json->{train_item_id};
442
    my $train_item = Koha::Preservation::Train::Items->find($train_item_id);
458
    my $train_item = Koha::Preservation::Train::Items->find($train_item_id);
443
459
444
    $t->get_ok( "//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id" =>
460
    $t->get_ok( "//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id" =>
Lines 471-478 subtest '*_item() tests' => sub { Link Here
471
487
472
    $item_3->notforloan($not_for_loan_waiting_list_in)->store;
488
    $item_3->notforloan($not_for_loan_waiting_list_in)->store;
473
    $t->post_ok( "//$userid:$password@/api/v1/preservation/trains/$train_id/items/batch" => json =>
489
    $t->post_ok( "//$userid:$password@/api/v1/preservation/trains/$train_id/items/batch" => json =>
474
            [ { item_id => $item_3->itemnumber } ] )->status_is(201)->json_is( '/0/item_id' => $item_3->itemnumber )
490
            [ { item_id => $item_3->itemnumber } ] )
475
        ->json_is( '/0/processing_id' => $train->default_processing_id )->json_has('/0/added_on');
491
        ->status_is(201)
492
        ->json_is( '/0/item_id'       => $item_3->itemnumber )
493
        ->json_is( '/0/processing_id' => $train->default_processing_id )
494
        ->json_has('/0/added_on');
476
495
477
    # Update item
496
    # Update item
478
    my $new_item_attributes = [
497
    my $new_item_attributes = [
Lines 502-511 subtest '*_item() tests' => sub { Link Here
502
521
503
    # Delete existing item
522
    # Delete existing item
504
    $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id")
523
    $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id")
505
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
524
        ->status_is( 204, 'REST3.2.4' )
525
        ->content_is( '', 'REST3.3.4' );
506
526
507
    # Delete non existing item
527
    # Delete non existing item
508
    $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id")->status_is(404)
528
    $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id")
529
        ->status_is(404)
509
        ->json_is( '/error' => 'Train item not found' );
530
        ->json_is( '/error' => 'Train item not found' );
510
531
511
    $schema->storage->txn_rollback;
532
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/public/lists.t (-1 / +2 lines)
Lines 75-81 subtest 'list_public() tests' => sub { Link Here
75
    );
75
    );
76
76
77
    # anonymous
77
    # anonymous
78
    $t->get_ok("/api/v1/public/lists?q=$q")->status_is( 200, "Anonymous users can only fetch public lists" )
78
    $t->get_ok("/api/v1/public/lists?q=$q")
79
        ->status_is( 200, "Anonymous users can only fetch public lists" )
79
        ->json_is( [ $list_1->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ) ] );
80
        ->json_is( [ $list_1->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ) ] );
80
81
81
    $t->get_ok("/api/v1/public/lists?q=$q&only_public=1")
82
    $t->get_ok("/api/v1/public/lists?q=$q&only_public=1")
(-)a/t/db_dependent/api/v1/query.t (-6 / +12 lines)
Lines 82-94 subtest 'q handling tests' => sub { Link Here
82
    my $q_empty_list = "q=[]";
82
    my $q_empty_list = "q=[]";
83
83
84
    $cities =
84
    $cities =
85
        $t->get_ok("//$userid:$password@/api/v1/cities?$q_ends_with_a&$q_starts_with_a&$q_empty_list")->status_is(200)
85
        $t->get_ok("//$userid:$password@/api/v1/cities?$q_ends_with_a&$q_starts_with_a&$q_empty_list")
86
        ->status_is(200)
86
        ->tx->res->json;
87
        ->tx->res->json;
87
88
88
    is( scalar @{$cities}, 1, 'empty list as trailing query, 1 city retrieved' );
89
    is( scalar @{$cities}, 1, 'empty list as trailing query, 1 city retrieved' );
89
90
90
    $cities =
91
    $cities =
91
        $t->get_ok("//$userid:$password@/api/v1/cities?$q_empty_list&$q_ends_with_a&$q_starts_with_a")->status_is(200)
92
        $t->get_ok("//$userid:$password@/api/v1/cities?$q_empty_list&$q_ends_with_a&$q_starts_with_a")
93
        ->status_is(200)
92
        ->tx->res->json;
94
        ->tx->res->json;
93
95
94
    is( scalar @{$cities}, 1, 'empty list as first query, 1 city retrieved' );
96
    is( scalar @{$cities}, 1, 'empty list as first query, 1 city retrieved' );
Lines 143-161 subtest 'q in body handling tests' => sub { Link Here
143
145
144
    $cities =
146
    $cities =
145
        $t->get_ok( "//$userid:$password@/api/v1/cities?q=$q_starts_with_a_str" => json => $q_ends_with_a )
147
        $t->get_ok( "//$userid:$password@/api/v1/cities?q=$q_starts_with_a_str" => json => $q_ends_with_a )
146
        ->status_is(200)->tx->res->json;
148
        ->status_is(200)
149
        ->tx->res->json;
147
150
148
    is( scalar @{$cities}, 1, 'Mixing query parameter and body, 1 city retrieved' );
151
    is( scalar @{$cities}, 1, 'Mixing query parameter and body, 1 city retrieved' );
149
152
150
    $cities =
153
    $cities =
151
        $t->get_ok( "//$userid:$password@/api/v1/cities?q=$q_ends_with_a_str" => json => $q_starts_with_a )
154
        $t->get_ok( "//$userid:$password@/api/v1/cities?q=$q_ends_with_a_str" => json => $q_starts_with_a )
152
        ->status_is(200)->tx->res->json;
155
        ->status_is(200)
156
        ->tx->res->json;
153
157
154
    is( scalar @{$cities}, 1, 'Mixing query parameter and body (flipped), 1 city retrieved' );
158
    is( scalar @{$cities}, 1, 'Mixing query parameter and body (flipped), 1 city retrieved' );
155
159
156
    $cities =
160
    $cities =
157
        $t->get_ok( "//$userid:$password@/api/v1/cities" => json => { "-and" => [ $q_ends_with_a, $q_starts_with_a ] } )
161
        $t->get_ok( "//$userid:$password@/api/v1/cities" => json => { "-and" => [ $q_ends_with_a, $q_starts_with_a ] } )
158
        ->status_is(200)->tx->res->json;
162
        ->status_is(200)
163
        ->tx->res->json;
159
164
160
    is( scalar @{$cities}, 1, 'Body query is passed through, 1 city retrieved' );
165
    is( scalar @{$cities}, 1, 'Body query is passed through, 1 city retrieved' );
161
166
Lines 189-195 subtest 'x-koha-embed tests' => sub { Link Here
189
            { 'x-koha-embed' => 'extended_attributes,custom_bad_embed,another_bad_embed' } )->status_is(400);
194
            { 'x-koha-embed' => 'extended_attributes,custom_bad_embed,another_bad_embed' } )->status_is(400);
190
195
191
    $res =
196
    $res =
192
        $t->get_ok( "//$userid:$password@/api/v1/cities" => { 'x-koha-embed' => 'any_embed' } )->status_is(400)
197
        $t->get_ok( "//$userid:$password@/api/v1/cities" => { 'x-koha-embed' => 'any_embed' } )
198
        ->status_is(400)
193
        ->tx->res->json;
199
        ->tx->res->json;
194
200
195
    is( $res, 'Embedding objects is not allowed on this endpoint.', 'Correct error message is returned' );
201
    is( $res, 'Embedding objects is not allowed on this endpoint.', 'Correct error message is returned' );
(-)a/t/db_dependent/api/v1/record_sources.t (-14 / +29 lines)
Lines 66-72 subtest 'list() tests' => sub { Link Here
66
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
66
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
67
    my $userid = $nonprivilegedpatron->userid;
67
    my $userid = $nonprivilegedpatron->userid;
68
68
69
    $t->get_ok("//$userid:$password@/api/v1/record_sources")->status_is(403)
69
    $t->get_ok("//$userid:$password@/api/v1/record_sources")
70
        ->status_is(403)
70
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
71
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
71
72
72
    $patron->set_password( { password => $password, skip_validation => 1 } );
73
    $patron->set_password( { password => $password, skip_validation => 1 } );
Lines 79-90 subtest 'list() tests' => sub { Link Here
79
    is( $response_count, 10, 'The API returns 10 sources' );
80
    is( $response_count, 10, 'The API returns 10 sources' );
80
81
81
    my $id = $source->record_source_id;
82
    my $id = $source->record_source_id;
82
    $t->get_ok("//$userid:$password@/api/v1/record_sources?q={\"record_source_id\": $id}")->status_is(200)
83
    $t->get_ok("//$userid:$password@/api/v1/record_sources?q={\"record_source_id\": $id}")
84
        ->status_is(200)
83
        ->json_is( '' => [ $source->to_api ], 'REST3.3.2' );
85
        ->json_is( '' => [ $source->to_api ], 'REST3.3.2' );
84
86
85
    $source->delete;
87
    $source->delete;
86
88
87
    $t->get_ok("//$userid:$password@/api/v1/record_sources?q={\"record_source_id\": $id}")->status_is(200)
89
    $t->get_ok("//$userid:$password@/api/v1/record_sources?q={\"record_source_id\": $id}")
90
        ->status_is(200)
88
        ->json_is( '' => [] );
91
        ->json_is( '' => [] );
89
92
90
    $schema->storage->txn_rollback;
93
    $schema->storage->txn_rollback;
Lines 118-135 subtest 'get() tests' => sub { Link Here
118
121
119
    my $id = $source->record_source_id;
122
    my $id = $source->record_source_id;
120
123
121
    $t->get_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is(403)
124
    $t->get_ok("//$userid:$password@/api/v1/record_sources/$id")
125
        ->status_is(403)
122
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
126
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
123
127
124
    $patron->set_password( { password => $password, skip_validation => 1 } );
128
    $patron->set_password( { password => $password, skip_validation => 1 } );
125
    $userid = $patron->userid;
129
    $userid = $patron->userid;
126
130
127
    $t->get_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is( 200, 'REST3.2.2' )
131
    $t->get_ok("//$userid:$password@/api/v1/record_sources/$id")
132
        ->status_is( 200, 'REST3.2.2' )
128
        ->json_is( '' => $source->to_api, 'REST3.3.2' );
133
        ->json_is( '' => $source->to_api, 'REST3.3.2' );
129
134
130
    $source->delete;
135
    $source->delete;
131
136
132
    $t->get_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is(404)
137
    $t->get_ok("//$userid:$password@/api/v1/record_sources/$id")
138
        ->status_is(404)
133
        ->json_is( '/error' => 'Record source not found' );
139
        ->json_is( '/error' => 'Record source not found' );
134
140
135
    $schema->storage->txn_rollback;
141
    $schema->storage->txn_rollback;
Lines 163-176 subtest 'delete() tests' => sub { Link Here
163
169
164
    my $id = $source->record_source_id;
170
    my $id = $source->record_source_id;
165
171
166
    $t->delete_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is(403)
172
    $t->delete_ok("//$userid:$password@/api/v1/record_sources/$id")
173
        ->status_is(403)
167
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
174
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
168
175
169
    $patron->set_password( { password => $password, skip_validation => 1 } );
176
    $patron->set_password( { password => $password, skip_validation => 1 } );
170
    $userid = $patron->userid;
177
    $userid = $patron->userid;
171
178
172
    $source->delete();
179
    $source->delete();
173
    $t->delete_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is( 404, 'REST4.3' )
180
    $t->delete_ok("//$userid:$password@/api/v1/record_sources/$id")
181
        ->status_is( 404, 'REST4.3' )
174
        ->json_is( { error => q{Record source not found}, error_code => q{not_found} } );
182
        ->json_is( { error => q{Record source not found}, error_code => q{not_found} } );
175
183
176
    $source = $builder->build_object( { class => 'Koha::RecordSources' } );
184
    $source = $builder->build_object( { class => 'Koha::RecordSources' } );
Lines 184-190 subtest 'delete() tests' => sub { Link Here
184
192
185
    $biblio->delete();
193
    $biblio->delete();
186
194
187
    $t->delete_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is( 204, 'REST3.2.4' )
195
    $t->delete_ok("//$userid:$password@/api/v1/record_sources/$id")
196
        ->status_is( 204, 'REST3.2.4' )
188
        ->content_is( q{}, 'REST3.3.4' );
197
        ->content_is( q{}, 'REST3.3.4' );
189
198
190
    my $deleted_source = Koha::RecordSources->search( { record_source_id => $id } );
199
    my $deleted_source = Koha::RecordSources->search( { record_source_id => $id } );
Lines 220-226 subtest 'add() tests' => sub { Link Here
220
    my $userid    = $nonprivilegedpatron->userid;
229
    my $userid    = $nonprivilegedpatron->userid;
221
    my $patron_id = $nonprivilegedpatron->borrowernumber;
230
    my $patron_id = $nonprivilegedpatron->borrowernumber;
222
231
223
    $t->post_ok( "//$userid:$password@/api/v1/record_sources" => json => { name => 'test1' } )->status_is(403)
232
    $t->post_ok( "//$userid:$password@/api/v1/record_sources" => json => { name => 'test1' } )
233
        ->status_is(403)
224
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
234
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
225
235
226
    $patron->set_password( { password => $password, skip_validation => 1 } );
236
    $patron->set_password( { password => $password, skip_validation => 1 } );
Lines 228-234 subtest 'add() tests' => sub { Link Here
228
238
229
    my $source_id =
239
    my $source_id =
230
        $t->post_ok( "//$userid:$password@/api/v1/record_sources" => json => { name => 'test1' } )
240
        $t->post_ok( "//$userid:$password@/api/v1/record_sources" => json => { name => 'test1' } )
231
        ->status_is( 201, 'REST3.2.2' )->json_is( '/name', 'test1' )->json_is( '/can_be_edited', 0 )
241
        ->status_is( 201, 'REST3.2.2' )
242
        ->json_is( '/name',          'test1' )
243
        ->json_is( '/can_be_edited', 0 )
232
        ->tx->res->json->{record_source_id};
244
        ->tx->res->json->{record_source_id};
233
245
234
    my $created_source = Koha::RecordSources->find($source_id);
246
    my $created_source = Koha::RecordSources->find($source_id);
Lines 275-281 subtest 'update() tests' => sub { Link Here
275
    my $source_with_missing_field = {};
287
    my $source_with_missing_field = {};
276
288
277
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_missing_field )
289
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_missing_field )
278
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
290
        ->status_is(400)
291
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
279
292
280
    # Full object update on PUT
293
    # Full object update on PUT
281
    my $source_with_updated_field = {
294
    my $source_with_updated_field = {
Lines 283-289 subtest 'update() tests' => sub { Link Here
283
    };
296
    };
284
297
285
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_updated_field )
298
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_updated_field )
286
        ->status_is(200)->json_is( '/name' => $source_with_updated_field->{name} );
299
        ->status_is(200)
300
        ->json_is( '/name' => $source_with_updated_field->{name} );
287
301
288
    # Authorized attempt to write invalid data
302
    # Authorized attempt to write invalid data
289
    my $source_with_invalid_field = {
303
    my $source_with_invalid_field = {
Lines 292-298 subtest 'update() tests' => sub { Link Here
292
    };
306
    };
293
307
294
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_invalid_field )
308
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_invalid_field )
295
        ->status_is(400)->json_is(
309
        ->status_is(400)
310
        ->json_is(
296
        "/errors" => [
311
        "/errors" => [
297
            {
312
            {
298
                message => "Properties not allowed: potato.",
313
                message => "Properties not allowed: potato.",
(-)a/t/db_dependent/api/v1/return_claims.t (-2 / +4 lines)
Lines 291-303 subtest 'delete() tests' => sub { Link Here
291
    );
291
    );
292
292
293
    # Test deleting a return claim
293
    # Test deleting a return claim
294
    $t->delete_ok( "//$userid:$password@/api/v1/return_claims/" . $claim->id )->status_is( 204, 'REST3.2.4' )
294
    $t->delete_ok( "//$userid:$password@/api/v1/return_claims/" . $claim->id )
295
        ->status_is( 204, 'REST3.2.4' )
295
        ->content_is( '', 'REST3.3.4' );
296
        ->content_is( '', 'REST3.3.4' );
296
297
297
    my $THE_claim = Koha::Checkouts::ReturnClaims->find( $claim->id );
298
    my $THE_claim = Koha::Checkouts::ReturnClaims->find( $claim->id );
298
    isnt( $THE_claim, "Return claim was deleted" );
299
    isnt( $THE_claim, "Return claim was deleted" );
299
300
300
    $t->delete_ok( "//$userid:$password@/api/v1/return_claims/" . $claim->id )->status_is(404)
301
    $t->delete_ok( "//$userid:$password@/api/v1/return_claims/" . $claim->id )
302
        ->status_is(404)
301
        ->json_is( '/error' => 'Claim not found' );
303
        ->json_is( '/error' => 'Claim not found' );
302
304
303
    $schema->storage->txn_rollback;
305
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/search_filters.t (-7 / +15 lines)
Lines 103-110 subtest 'list() tests' => sub { Link Here
103
    );
103
    );
104
104
105
    # Make sure we are returned with the correct amount of macros
105
    # Make sure we are returned with the correct amount of macros
106
    $t->get_ok("//$userid:$password@/api/v1/search_filters")->status_is( 200, 'REST3.2.2' )
106
    $t->get_ok("//$userid:$password@/api/v1/search_filters")
107
        ->json_has('/0/search_filter_id')->json_has('/1/search_filter_id')->json_has('/2/search_filter_id')
107
        ->status_is( 200, 'REST3.2.2' )
108
        ->json_has('/0/search_filter_id')
109
        ->json_has('/1/search_filter_id')
110
        ->json_has('/2/search_filter_id')
108
        ->json_has('/3/search_filter_id');
111
        ->json_has('/3/search_filter_id');
109
112
110
    $schema->storage->txn_rollback;
113
    $schema->storage->txn_rollback;
Lines 131-142 subtest 'get() tests' => sub { Link Here
131
    my $search_filter_3 = $builder->build_object( { class => 'Koha::SearchFilters' } );
134
    my $search_filter_3 = $builder->build_object( { class => 'Koha::SearchFilters' } );
132
135
133
    $t->get_ok( "//$userid:$password@/api/v1/search_filters/" . $search_filter_1->id )
136
    $t->get_ok( "//$userid:$password@/api/v1/search_filters/" . $search_filter_1->id )
134
        ->status_is( 200, 'Filter retrieved correctly' )->json_is( $search_filter_1->to_api );
137
        ->status_is( 200, 'Filter retrieved correctly' )
138
        ->json_is( $search_filter_1->to_api );
135
139
136
    my $non_existent_code = $search_filter_1->id;
140
    my $non_existent_code = $search_filter_1->id;
137
    $search_filter_1->delete;
141
    $search_filter_1->delete;
138
142
139
    $t->get_ok( "//$userid:$password@/api/v1/search_filters/" . $non_existent_code )->status_is(404)
143
    $t->get_ok( "//$userid:$password@/api/v1/search_filters/" . $non_existent_code )
144
        ->status_is(404)
140
        ->json_is( '/error' => 'Search filter not found' );
145
        ->json_is( '/error' => 'Search filter not found' );
141
146
142
    $patron->flags(4)->store;
147
    $patron->flags(4)->store;
Lines 196-202 subtest 'add() tests' => sub { Link Here
196
    $search_filter_with_invalid_field->{'coffee_filter'} = 'Chemex';
201
    $search_filter_with_invalid_field->{'coffee_filter'} = 'Chemex';
197
202
198
    $t->post_ok( "//$auth_userid:$password@/api/v1/search_filters" => json => $search_filter_with_invalid_field )
203
    $t->post_ok( "//$auth_userid:$password@/api/v1/search_filters" => json => $search_filter_with_invalid_field )
199
        ->status_is(400)->json_is(
204
        ->status_is(400)
205
        ->json_is(
200
        "/errors" => [
206
        "/errors" => [
201
            {
207
            {
202
                message => "Properties not allowed: coffee_filter.",
208
                message => "Properties not allowed: coffee_filter.",
Lines 207-213 subtest 'add() tests' => sub { Link Here
207
213
208
    # Authorized attempt to write
214
    # Authorized attempt to write
209
    $t->post_ok( "//$auth_userid:$password@/api/v1/search_filters" => json => $search_filter_values )
215
    $t->post_ok( "//$auth_userid:$password@/api/v1/search_filters" => json => $search_filter_values )
210
        ->status_is( 201, 'REST3.2.1' )->json_has( '/search_filter_id', 'We generated a new id' )
216
        ->status_is( 201, 'REST3.2.1' )
217
        ->json_has( '/search_filter_id', 'We generated a new id' )
211
        ->json_is( '/name'         => $search_filter_values->{name},         'The name matches what we supplied' )
218
        ->json_is( '/name'         => $search_filter_values->{name},         'The name matches what we supplied' )
212
        ->json_is( '/query'        => $search_filter_values->{query},        'The query matches what we supplied' )
219
        ->json_is( '/query'        => $search_filter_values->{query},        'The query matches what we supplied' )
213
        ->json_is( '/limits'       => $search_filter_values->{limits},       'The limits match what we supplied' )
220
        ->json_is( '/limits'       => $search_filter_values->{limits},       'The limits match what we supplied' )
Lines 221-227 subtest 'add() tests' => sub { Link Here
221
    # Authorized attempt to create with existing id
228
    # Authorized attempt to create with existing id
222
    $search_filter_values->{search_filter_id} = $search_filter_id;
229
    $search_filter_values->{search_filter_id} = $search_filter_id;
223
230
224
    $t->post_ok( "//$auth_userid:$password@/api/v1/search_filters" => json => $search_filter_values )->status_is(400)
231
    $t->post_ok( "//$auth_userid:$password@/api/v1/search_filters" => json => $search_filter_values )
232
        ->status_is(400)
225
        ->json_is(
233
        ->json_is(
226
        '/errors' => [
234
        '/errors' => [
227
            {
235
            {
(-)a/t/db_dependent/api/v1/smtp_servers.t (-13 / +27 lines)
Lines 73-79 subtest 'list() tests' => sub { Link Here
73
    my $another_smtp_server = $builder->build_object( { class => 'Koha::SMTP::Servers' } );
73
    my $another_smtp_server = $builder->build_object( { class => 'Koha::SMTP::Servers' } );
74
74
75
    # Two SMTP servers created, they should both be returned
75
    # Two SMTP servers created, they should both be returned
76
    $t->get_ok("//$userid:$password@/api/v1/config/smtp_servers")->status_is(200)
76
    $t->get_ok("//$userid:$password@/api/v1/config/smtp_servers")
77
        ->status_is(200)
77
        ->json_is( [ $smtp_server->to_api, $another_smtp_server->to_api, ] );
78
        ->json_is( [ $smtp_server->to_api, $another_smtp_server->to_api, ] );
78
79
79
    # Unauthorized access
80
    # Unauthorized access
Lines 109-115 subtest 'get() tests' => sub { Link Here
109
    $patron->set_password( { password => $password, skip_validation => 1 } );
110
    $patron->set_password( { password => $password, skip_validation => 1 } );
110
    my $unauth_userid = $patron->userid;
111
    my $unauth_userid = $patron->userid;
111
112
112
    $t->get_ok( "//$userid:$password@/api/v1/config/smtp_servers/" . $smtp_server->id )->status_is(200)
113
    $t->get_ok( "//$userid:$password@/api/v1/config/smtp_servers/" . $smtp_server->id )
114
        ->status_is(200)
113
        ->json_is( $smtp_server->to_api );
115
        ->json_is( $smtp_server->to_api );
114
116
115
    $t->get_ok( "//$unauth_userid:$password@/api/v1/config/smtp_servers/" . $smtp_server->id )->status_is(403);
117
    $t->get_ok( "//$unauth_userid:$password@/api/v1/config/smtp_servers/" . $smtp_server->id )->status_is(403);
Lines 118-124 subtest 'get() tests' => sub { Link Here
118
    my $non_existent_id       = $smtp_server_to_delete->id;
120
    my $non_existent_id       = $smtp_server_to_delete->id;
119
    $smtp_server_to_delete->delete;
121
    $smtp_server_to_delete->delete;
120
122
121
    $t->get_ok("//$userid:$password@/api/v1/config/smtp_servers/$non_existent_id")->status_is(404)
123
    $t->get_ok("//$userid:$password@/api/v1/config/smtp_servers/$non_existent_id")
124
        ->status_is(404)
122
        ->json_is( '/error' => 'SMTP server not found' );
125
        ->json_is( '/error' => 'SMTP server not found' );
123
126
124
    $schema->storage->txn_rollback;
127
    $schema->storage->txn_rollback;
Lines 168-174 subtest 'add() tests' => sub { Link Here
168
    };
171
    };
169
172
170
    $t->post_ok( "//$userid:$password@/api/v1/config/smtp_servers" => json => $smtp_server_with_invalid_field )
173
    $t->post_ok( "//$userid:$password@/api/v1/config/smtp_servers" => json => $smtp_server_with_invalid_field )
171
        ->status_is(400)->json_is(
174
        ->status_is(400)
175
        ->json_is(
172
        "/errors" => [
176
        "/errors" => [
173
            {
177
            {
174
                message => "Properties not allowed: blah.",
178
                message => "Properties not allowed: blah.",
Lines 180-200 subtest 'add() tests' => sub { Link Here
180
    # Authorized attempt to write
184
    # Authorized attempt to write
181
    my $smtp_server_id =
185
    my $smtp_server_id =
182
        $t->post_ok( "//$userid:$password@/api/v1/config/smtp_servers" => json => $smtp_server_data )
186
        $t->post_ok( "//$userid:$password@/api/v1/config/smtp_servers" => json => $smtp_server_data )
183
        ->status_is( 201, 'REST3.2.1' )->header_like(
187
        ->status_is( 201, 'REST3.2.1' )
188
        ->header_like(
184
        Location => qr|^\/api\/v1\/config\/smtp_servers\/\d*|,
189
        Location => qr|^\/api\/v1\/config\/smtp_servers\/\d*|,
185
        'REST3.4.1'
190
        'REST3.4.1'
186
    )->json_is( '/name' => $smtp_server_data->{name} )->json_is( '/state' => $smtp_server_data->{state} )
191
        )
192
        ->json_is( '/name'        => $smtp_server_data->{name} )
193
        ->json_is( '/state'       => $smtp_server_data->{state} )
187
        ->json_is( '/postal_code' => $smtp_server_data->{postal_code} )
194
        ->json_is( '/postal_code' => $smtp_server_data->{postal_code} )
188
        ->json_is( '/country'     => $smtp_server_data->{country} )->tx->res->json->{smtp_server_id};
195
        ->json_is( '/country'     => $smtp_server_data->{country} )
196
        ->tx->res->json->{smtp_server_id};
189
197
190
    # Authorized attempt to create with null id
198
    # Authorized attempt to create with null id
191
    $smtp_server_data->{smtp_server_id} = undef;
199
    $smtp_server_data->{smtp_server_id} = undef;
192
    $t->post_ok( "//$userid:$password@/api/v1/config/smtp_servers" => json => $smtp_server_data )->status_is(400)
200
    $t->post_ok( "//$userid:$password@/api/v1/config/smtp_servers" => json => $smtp_server_data )
201
        ->status_is(400)
193
        ->json_has('/errors');
202
        ->json_has('/errors');
194
203
195
    # Authorized attempt to create with existing id
204
    # Authorized attempt to create with existing id
196
    $smtp_server_data->{smtp_server_id} = $smtp_server_id;
205
    $smtp_server_data->{smtp_server_id} = $smtp_server_id;
197
    $t->post_ok( "//$userid:$password@/api/v1/config/smtp_servers" => json => $smtp_server_data )->status_is(400)
206
    $t->post_ok( "//$userid:$password@/api/v1/config/smtp_servers" => json => $smtp_server_data )
207
        ->status_is(400)
198
        ->json_is(
208
        ->json_is(
199
        "/errors" => [
209
        "/errors" => [
200
            {
210
            {
Lines 247-260 subtest 'update() tests' => sub { Link Here
247
257
248
    $t->put_ok(
258
    $t->put_ok(
249
        "//$userid:$password@/api/v1/config/smtp_servers/$smtp_server_id" => json => $smtp_server_with_missing_field )
259
        "//$userid:$password@/api/v1/config/smtp_servers/$smtp_server_id" => json => $smtp_server_with_missing_field )
250
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
260
        ->status_is(400)
261
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
251
262
252
    # Full object update on PUT
263
    # Full object update on PUT
253
    my $smtp_server_with_updated_field = { name => "Some name", };
264
    my $smtp_server_with_updated_field = { name => "Some name", };
254
265
255
    $t->put_ok(
266
    $t->put_ok(
256
        "//$userid:$password@/api/v1/config/smtp_servers/$smtp_server_id" => json => $smtp_server_with_updated_field )
267
        "//$userid:$password@/api/v1/config/smtp_servers/$smtp_server_id" => json => $smtp_server_with_updated_field )
257
        ->status_is(200)->json_is( '/name' => 'Some name' );
268
        ->status_is(200)
269
        ->json_is( '/name' => 'Some name' );
258
270
259
    # Authorized attempt to write invalid data
271
    # Authorized attempt to write invalid data
260
    my $smtp_server_with_invalid_field = {
272
    my $smtp_server_with_invalid_field = {
Lines 264-270 subtest 'update() tests' => sub { Link Here
264
276
265
    $t->put_ok(
277
    $t->put_ok(
266
        "//$userid:$password@/api/v1/config/smtp_servers/$smtp_server_id" => json => $smtp_server_with_invalid_field )
278
        "//$userid:$password@/api/v1/config/smtp_servers/$smtp_server_id" => json => $smtp_server_with_invalid_field )
267
        ->status_is(400)->json_is(
279
        ->status_is(400)
280
        ->json_is(
268
        "/errors" => [
281
        "/errors" => [
269
            {
282
            {
270
                message => "Properties not allowed: blah.",
283
                message => "Properties not allowed: blah.",
Lines 322-328 subtest 'delete() tests' => sub { Link Here
322
    # Unauthorized attempt to delete
335
    # Unauthorized attempt to delete
323
    $t->delete_ok("//$unauth_userid:$password@/api/v1/config/smtp_servers/$smtp_server_id")->status_is(403);
336
    $t->delete_ok("//$unauth_userid:$password@/api/v1/config/smtp_servers/$smtp_server_id")->status_is(403);
324
337
325
    $t->delete_ok("//$userid:$password@/api/v1/config/smtp_servers/$smtp_server_id")->status_is( 204, 'REST3.2.4' )
338
    $t->delete_ok("//$userid:$password@/api/v1/config/smtp_servers/$smtp_server_id")
339
        ->status_is( 204, 'REST3.2.4' )
326
        ->content_is( '', 'REST3.3.4' );
340
        ->content_is( '', 'REST3.3.4' );
327
341
328
    $t->delete_ok("//$userid:$password@/api/v1/config/smtp_servers/$smtp_server_id")->status_is(404);
342
    $t->delete_ok("//$userid:$password@/api/v1/config/smtp_servers/$smtp_server_id")->status_is(404);
(-)a/t/db_dependent/api/v1/stockrotation_rotas.t (-10 / +21 lines)
Lines 86-99 subtest 'list() tests' => sub { Link Here
86
86
87
    # Filtering works, two rotas are active
87
    # Filtering works, two rotas are active
88
    my $api_filter = encode_json( { 'me.active' => Mojo::JSON->true } );
88
    my $api_filter = encode_json( { 'me.active' => Mojo::JSON->true } );
89
    $t->get_ok("//$userid:$password@/api/v1/rotas?q=$api_filter")->status_is(200)
89
    $t->get_ok("//$userid:$password@/api/v1/rotas?q=$api_filter")
90
        ->status_is(200)
90
        ->json_is( [ $active_rota->to_api, $another_active_rota->to_api ] );
91
        ->json_is( [ $active_rota->to_api, $another_active_rota->to_api ] );
91
92
92
    $api_filter = encode_json( { 'me.title' => $active_rota->title } );
93
    $api_filter = encode_json( { 'me.title' => $active_rota->title } );
93
    $t->get_ok("//$userid:$password@/api/v1/rotas?q=$api_filter")->status_is(200)->json_is( [ $active_rota->to_api ] );
94
    $t->get_ok("//$userid:$password@/api/v1/rotas?q=$api_filter")->status_is(200)->json_is( [ $active_rota->to_api ] );
94
95
95
    # Warn on unsupported query parameter
96
    # Warn on unsupported query parameter
96
    $t->get_ok( "//$userid:$password@/api/v1/rotas?title=" . $active_rota->title )->status_is(400)
97
    $t->get_ok( "//$userid:$password@/api/v1/rotas?title=" . $active_rota->title )
98
        ->status_is(400)
97
        ->json_is( [ { path => '/query/title', message => 'Malformed query string' } ] );
99
        ->json_is( [ { path => '/query/title', message => 'Malformed query string' } ] );
98
100
99
    # Unauthorized access
101
    # Unauthorized access
Lines 137-143 subtest 'get() tests' => sub { Link Here
137
    my $non_existent_id = $rota_to_delete->id;
139
    my $non_existent_id = $rota_to_delete->id;
138
    $rota_to_delete->delete;
140
    $rota_to_delete->delete;
139
141
140
    $t->get_ok("//$userid:$password@/api/v1/rotas/$non_existent_id")->status_is(404)
142
    $t->get_ok("//$userid:$password@/api/v1/rotas/$non_existent_id")
143
        ->status_is(404)
141
        ->json_is( '/error' => 'Rota not found' );
144
        ->json_is( '/error' => 'Rota not found' );
142
145
143
    $schema->storage->txn_rollback;
146
    $schema->storage->txn_rollback;
Lines 198-209 subtest 'add() tests' => sub { Link Here
198
201
199
    # Authorized attempt to write
202
    # Authorized attempt to write
200
    my $rota_id =
203
    my $rota_id =
201
        $t->post_ok( "//$userid:$password@/api/v1/rotas" => json => $rota )->status_is( 201, 'REST3.2.1' )
204
        $t->post_ok( "//$userid:$password@/api/v1/rotas" => json => $rota )
205
        ->status_is( 201, 'REST3.2.1' )
202
        ->header_like(
206
        ->header_like(
203
        Location => qr|^\/api\/v1\/rotas/\d*|,
207
        Location => qr|^\/api\/v1\/rotas/\d*|,
204
        'REST3.4.1'
208
        'REST3.4.1'
205
    )->json_is( '/title' => $rota->{title} )->json_is( '/description' => $rota->{description} )
209
        )
206
        ->json_is( '/active' => $rota->{active} )->json_is( '/cyclical' => $rota->{cyclical} )
210
        ->json_is( '/title'       => $rota->{title} )
211
        ->json_is( '/description' => $rota->{description} )
212
        ->json_is( '/active'      => $rota->{active} )
213
        ->json_is( '/cyclical'    => $rota->{cyclical} )
207
        ->tx->res->json->{rota_id};
214
        ->tx->res->json->{rota_id};
208
215
209
    # Authorized attempt to create with null id
216
    # Authorized attempt to create with null id
Lines 264-270 subtest 'update() tests' => sub { Link Here
264
        cyclical    => Mojo::JSON->false
271
        cyclical    => Mojo::JSON->false
265
    };
272
    };
266
273
267
    $t->put_ok( "//$userid:$password@/api/v1/rotas/$rota_id" => json => $rota_with_missing_field )->status_is(400)
274
    $t->put_ok( "//$userid:$password@/api/v1/rotas/$rota_id" => json => $rota_with_missing_field )
275
        ->status_is(400)
268
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/active" } ] );
276
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/active" } ] );
269
277
270
    # Full object update on PUT
278
    # Full object update on PUT
Lines 275-281 subtest 'update() tests' => sub { Link Here
275
        cyclical    => Mojo::JSON->false
283
        cyclical    => Mojo::JSON->false
276
    };
284
    };
277
285
278
    $t->put_ok( "//$userid:$password@/api/v1/rotas/$rota_id" => json => $rota_with_updated_field )->status_is(200)
286
    $t->put_ok( "//$userid:$password@/api/v1/rotas/$rota_id" => json => $rota_with_updated_field )
287
        ->status_is(200)
279
        ->json_is( '/title' => 'London' );
288
        ->json_is( '/title' => 'London' );
280
289
281
    # Authorized attempt to write invalid data
290
    # Authorized attempt to write invalid data
Lines 286-292 subtest 'update() tests' => sub { Link Here
286
        cyclical    => Mojo::JSON->false
295
        cyclical    => Mojo::JSON->false
287
    };
296
    };
288
297
289
    $t->put_ok( "//$userid:$password@/api/v1/rotas/$rota_id" => json => $rota_with_invalid_field )->status_is(400)
298
    $t->put_ok( "//$userid:$password@/api/v1/rotas/$rota_id" => json => $rota_with_invalid_field )
299
        ->status_is(400)
290
        ->json_is(
300
        ->json_is(
291
        "/errors" => [
301
        "/errors" => [
292
            {
302
            {
Lines 342-348 subtest 'delete() tests' => sub { Link Here
342
    # Unauthorized attempt to delete
352
    # Unauthorized attempt to delete
343
    $t->delete_ok("//$unauth_userid:$password@/api/v1/rotas/$rota_id")->status_is(403);
353
    $t->delete_ok("//$unauth_userid:$password@/api/v1/rotas/$rota_id")->status_is(403);
344
354
345
    $t->delete_ok("//$userid:$password@/api/v1/rotas/$rota_id")->status_is( 204, 'REST3.2.4' )
355
    $t->delete_ok("//$userid:$password@/api/v1/rotas/$rota_id")
356
        ->status_is( 204, 'REST3.2.4' )
346
        ->content_is( '', 'REST3.3.4' );
357
        ->content_is( '', 'REST3.3.4' );
347
358
348
    $t->delete_ok("//$userid:$password@/api/v1/rotas/$rota_id")->status_is(404);
359
    $t->delete_ok("//$userid:$password@/api/v1/rotas/$rota_id")->status_is(404);
(-)a/t/db_dependent/api/v1/stockrotationstage.t (-4 / +8 lines)
Lines 88-107 subtest 'move() tests' => sub { Link Here
88
88
89
    # Invalid attempt to move a stage on a non-existent rota
89
    # Invalid attempt to move a stage on a non-existent rota
90
    $t->put_ok( "//$auth_userid:$password@/api/v1/rotas/99999999/stages/$stage1_id/position" => json => 2 )
90
    $t->put_ok( "//$auth_userid:$password@/api/v1/rotas/99999999/stages/$stage1_id/position" => json => 2 )
91
        ->status_is(404)->json_is( '/error' => "Rota not found" );
91
        ->status_is(404)
92
        ->json_is( '/error' => "Rota not found" );
92
93
93
    # Invalid attempt to move an non-existent stage
94
    # Invalid attempt to move an non-existent stage
94
    $t->put_ok( "//$auth_userid:$password@/api/v1/rotas/$rota_id/stages/999999999/position" => json => 2 )
95
    $t->put_ok( "//$auth_userid:$password@/api/v1/rotas/$rota_id/stages/999999999/position" => json => 2 )
95
        ->status_is(404)->json_is( '/error' => "Stage not found" );
96
        ->status_is(404)
97
        ->json_is( '/error' => "Stage not found" );
96
98
97
    # Invalid attempt to move stage to current position
99
    # Invalid attempt to move stage to current position
98
    my $curr_position = $stage1->{position};
100
    my $curr_position = $stage1->{position};
99
    $t->put_ok( "//$auth_userid:$password@/api/v1/rotas/$rota_id/stages/$stage1_id/position" => json => $curr_position )
101
    $t->put_ok( "//$auth_userid:$password@/api/v1/rotas/$rota_id/stages/$stage1_id/position" => json => $curr_position )
100
        ->status_is(400)->json_is( '/error' => "Bad request - new position invalid" );
102
        ->status_is(400)
103
        ->json_is( '/error' => "Bad request - new position invalid" );
101
104
102
    # Invalid attempt to move stage to invalid position
105
    # Invalid attempt to move stage to invalid position
103
    $t->put_ok( "//$auth_userid:$password@/api/v1/rotas/$rota_id/stages/$stage1_id/position" => json => 99999999 )
106
    $t->put_ok( "//$auth_userid:$password@/api/v1/rotas/$rota_id/stages/$stage1_id/position" => json => 99999999 )
104
        ->status_is(400)->json_is( '/error' => "Bad request - new position invalid" );
107
        ->status_is(400)
108
        ->json_is( '/error' => "Bad request - new position invalid" );
105
109
106
    # Valid, authorised move
110
    # Valid, authorised move
107
    $t->put_ok( "//$auth_userid:$password@/api/v1/rotas/$rota_id/stages/$stage1_id/position" => json => 2 )
111
    $t->put_ok( "//$auth_userid:$password@/api/v1/rotas/$rota_id/stages/$stage1_id/position" => json => 2 )
(-)a/t/db_dependent/api/v1/suggestions.t (-18 / +34 lines)
Lines 63-69 subtest 'list() tests' => sub { Link Here
63
63
64
    ## Authorized user tests
64
    ## Authorized user tests
65
    # No suggestions by patron, so empty array should be returned
65
    # No suggestions by patron, so empty array should be returned
66
    $t->get_ok("//$userid:$password@/api/v1/suggestions?q={\"suggested_by\":\"$patron_id\"}")->status_is(200)
66
    $t->get_ok("//$userid:$password@/api/v1/suggestions?q={\"suggested_by\":\"$patron_id\"}")
67
        ->status_is(200)
67
        ->json_is( [] );
68
        ->json_is( [] );
68
69
69
    my $suggestion_1 = $builder->build_object(
70
    my $suggestion_1 = $builder->build_object(
Lines 74-80 subtest 'list() tests' => sub { Link Here
74
    );
75
    );
75
76
76
    # One suggestion created, should get returned
77
    # One suggestion created, should get returned
77
    $t->get_ok("//$userid:$password@/api/v1/suggestions?q={\"suggested_by\":\"$patron_id\"}")->status_is(200)
78
    $t->get_ok("//$userid:$password@/api/v1/suggestions?q={\"suggested_by\":\"$patron_id\"}")
79
        ->status_is(200)
78
        ->json_is( [ $suggestion_1->to_api ] );
80
        ->json_is( [ $suggestion_1->to_api ] );
79
81
80
    my $suggestion_2 = $builder->build_object(
82
    my $suggestion_2 = $builder->build_object(
Lines 85-91 subtest 'list() tests' => sub { Link Here
85
    );
87
    );
86
88
87
    # Two SMTP servers created, they should both be returned
89
    # Two SMTP servers created, they should both be returned
88
    $t->get_ok("//$userid:$password@/api/v1/suggestions?q={\"suggested_by\":\"$patron_id\"}")->status_is(200)
90
    $t->get_ok("//$userid:$password@/api/v1/suggestions?q={\"suggested_by\":\"$patron_id\"}")
91
        ->status_is(200)
89
        ->json_is( [ $suggestion_1->to_api, $suggestion_2->to_api, ] );
92
        ->json_is( [ $suggestion_1->to_api, $suggestion_2->to_api, ] );
90
93
91
    # Unauthorized access
94
    # Unauthorized access
Lines 128-134 subtest 'get() tests' => sub { Link Here
128
        }
131
        }
129
    );
132
    );
130
133
131
    $t->get_ok( "//$userid:$password@/api/v1/suggestions/" . $suggestion->id )->status_is(200)
134
    $t->get_ok( "//$userid:$password@/api/v1/suggestions/" . $suggestion->id )
135
        ->status_is(200)
132
        ->json_is( $suggestion->to_api );
136
        ->json_is( $suggestion->to_api );
133
137
134
    my $authorised_value = Koha::AuthorisedValue->new(
138
    my $authorised_value = Koha::AuthorisedValue->new(
Lines 139-145 subtest 'get() tests' => sub { Link Here
139
    )->store;
143
    )->store;
140
    $suggestion->STATUS('FREDERIC')->store->discard_changes;
144
    $suggestion->STATUS('FREDERIC')->store->discard_changes;
141
145
142
    $t->get_ok( "//$userid:$password@/api/v1/suggestions/" . $suggestion->id )->status_is(200)
146
    $t->get_ok( "//$userid:$password@/api/v1/suggestions/" . $suggestion->id )
147
        ->status_is(200)
143
        ->json_is( $suggestion->to_api );
148
        ->json_is( $suggestion->to_api );
144
149
145
    $t->get_ok( "//$unauth_userid:$password@/api/v1/suggestions/" . $suggestion->id )->status_is(403);
150
    $t->get_ok( "//$unauth_userid:$password@/api/v1/suggestions/" . $suggestion->id )->status_is(403);
Lines 148-154 subtest 'get() tests' => sub { Link Here
148
    my $non_existent_id      = $suggestion_to_delete->id;
153
    my $non_existent_id      = $suggestion_to_delete->id;
149
    $suggestion_to_delete->delete;
154
    $suggestion_to_delete->delete;
150
155
151
    $t->get_ok("//$userid:$password@/api/v1/suggestions/$non_existent_id")->status_is(404)
156
    $t->get_ok("//$userid:$password@/api/v1/suggestions/$non_existent_id")
157
        ->status_is(404)
152
        ->json_is( '/error' => 'Suggestion not found' );
158
        ->json_is( '/error' => 'Suggestion not found' );
153
159
154
    $schema->storage->txn_rollback;
160
    $schema->storage->txn_rollback;
Lines 198-204 subtest 'add() tests' => sub { Link Here
198
    # Authorized attempt to write invalid data
204
    # Authorized attempt to write invalid data
199
    my $suggestion_with_invalid_field = { blah => 'blah' };
205
    my $suggestion_with_invalid_field = { blah => 'blah' };
200
206
201
    $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_with_invalid_field )->status_is(400)
207
    $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_with_invalid_field )
208
        ->status_is(400)
202
        ->json_is(
209
        ->json_is(
203
        "/errors" => [
210
        "/errors" => [
204
            {
211
            {
Lines 211-220 subtest 'add() tests' => sub { Link Here
211
    # Authorized attempt to write
218
    # Authorized attempt to write
212
    my $generated_suggestion =
219
    my $generated_suggestion =
213
        $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_data )
220
        $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_data )
214
        ->status_is( 201, 'REST3.2.1' )->header_like(
221
        ->status_is( 201, 'REST3.2.1' )
222
        ->header_like(
215
        Location => qr|^\/api\/v1\/suggestions\/\d*|,
223
        Location => qr|^\/api\/v1\/suggestions\/\d*|,
216
        'REST3.4.1'
224
        'REST3.4.1'
217
    )->tx->res->json;
225
        )->tx->res->json;
218
226
219
    my $suggestion_id = $generated_suggestion->{suggestion_id};
227
    my $suggestion_id = $generated_suggestion->{suggestion_id};
220
    is_deeply(
228
    is_deeply(
Lines 225-231 subtest 'add() tests' => sub { Link Here
225
233
226
    # Authorized attempt to create with null id
234
    # Authorized attempt to create with null id
227
    $suggestion_data->{suggestion_id} = undef;
235
    $suggestion_data->{suggestion_id} = undef;
228
    $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_data )->status_is(400)
236
    $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_data )
237
        ->status_is(400)
229
        ->json_has('/errors');
238
        ->json_has('/errors');
230
239
231
    # Authorized attempt to create with existing id
240
    # Authorized attempt to create with existing id
Lines 266-278 subtest 'add() tests' => sub { Link Here
266
        $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_data )
275
        $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_data )
267
            ->status_is( 201, 'Second pending suggestion' );
276
            ->status_is( 201, 'Second pending suggestion' );
268
277
269
        $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_data )->status_is(400)
278
        $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_data )
279
            ->status_is(400)
270
            ->json_is( '/error_code' => 'max_pending_reached' );
280
            ->json_is( '/error_code' => 'max_pending_reached' );
271
281
272
        $t->post_ok( "//$userid:$password@/api/v1/suggestions" => { 'x-koha-override' => 'max_pending' } => json =>
282
        $t->post_ok( "//$userid:$password@/api/v1/suggestions" => { 'x-koha-override' => 'max_pending' } => json =>
273
                $suggestion_data )->status_is( 201, 'max_pending override does the job' );
283
                $suggestion_data )->status_is( 201, 'max_pending override does the job' );
274
284
275
        $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_data )->status_is(400)
285
        $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_data )
286
            ->status_is(400)
276
            ->json_is( '/error_code' => 'max_total_reached' );
287
            ->json_is( '/error_code' => 'max_total_reached' );
277
288
278
        $t->post_ok(
289
        $t->post_ok(
Lines 324-330 subtest 'update() tests' => sub { Link Here
324
    my $suggestion_with_updated_field = { reason => "Some reason", };
335
    my $suggestion_with_updated_field = { reason => "Some reason", };
325
336
326
    $t->put_ok( "//$userid:$password@/api/v1/suggestions/$suggestion_id" => json => $suggestion_with_updated_field )
337
    $t->put_ok( "//$userid:$password@/api/v1/suggestions/$suggestion_id" => json => $suggestion_with_updated_field )
327
        ->status_is(200)->json_is( '/reason' => 'Some reason' );
338
        ->status_is(200)
339
        ->json_is( '/reason' => 'Some reason' );
328
340
329
    # Authorized attempt to write invalid data
341
    # Authorized attempt to write invalid data
330
    my $suggestion_with_invalid_field = {
342
    my $suggestion_with_invalid_field = {
Lines 333-339 subtest 'update() tests' => sub { Link Here
333
    };
345
    };
334
346
335
    $t->put_ok( "//$userid:$password@/api/v1/suggestions/$suggestion_id" => json => $suggestion_with_invalid_field )
347
    $t->put_ok( "//$userid:$password@/api/v1/suggestions/$suggestion_id" => json => $suggestion_with_invalid_field )
336
        ->status_is(400)->json_is(
348
        ->status_is(400)
349
        ->json_is(
337
        "/errors" => [
350
        "/errors" => [
338
            {
351
            {
339
                message => "Properties not allowed: blah.",
352
                message => "Properties not allowed: blah.",
Lines 389-395 subtest 'delete() tests' => sub { Link Here
389
    # Unauthorized attempt to delete
402
    # Unauthorized attempt to delete
390
    $t->delete_ok("//$unauth_userid:$password@/api/v1/suggestions/$suggestion_id")->status_is(403);
403
    $t->delete_ok("//$unauth_userid:$password@/api/v1/suggestions/$suggestion_id")->status_is(403);
391
404
392
    $t->delete_ok("//$userid:$password@/api/v1/suggestions/$suggestion_id")->status_is( 204, 'REST3.2.4' )
405
    $t->delete_ok("//$userid:$password@/api/v1/suggestions/$suggestion_id")
406
        ->status_is( 204, 'REST3.2.4' )
393
        ->content_is( q{}, 'REST3.3.4' );
407
        ->content_is( q{}, 'REST3.3.4' );
394
408
395
    $t->delete_ok("//$userid:$password@/api/v1/suggestions/$suggestion_id")->status_is(404);
409
    $t->delete_ok("//$userid:$password@/api/v1/suggestions/$suggestion_id")->status_is(404);
Lines 448-457 subtest 'Permissions tests' => sub { Link Here
448
    # Authorized attempt to write
462
    # Authorized attempt to write
449
    my $generated_suggestion =
463
    my $generated_suggestion =
450
        $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_data )
464
        $t->post_ok( "//$userid:$password@/api/v1/suggestions" => json => $suggestion_data )
451
        ->status_is( 201, 'REST3.2.1' )->header_like(
465
        ->status_is( 201, 'REST3.2.1' )
466
        ->header_like(
452
        Location => qr|^\/api\/v1\/suggestions\/\d*|,
467
        Location => qr|^\/api\/v1\/suggestions\/\d*|,
453
        'REST3.4.1'
468
        'REST3.4.1'
454
    )->tx->res->json;
469
        )->tx->res->json;
455
470
456
    my $suggestion_id = $generated_suggestion->{suggestion_id};
471
    my $suggestion_id = $generated_suggestion->{suggestion_id};
457
    is_deeply(
472
    is_deeply(
Lines 473-479 subtest 'Permissions tests' => sub { Link Here
473
        }
488
        }
474
    );
489
    );
475
490
476
    $t->delete_ok("//$userid:$password@/api/v1/suggestions/$suggestion_id")->status_is( 204, 'REST3.2.4' )
491
    $t->delete_ok("//$userid:$password@/api/v1/suggestions/$suggestion_id")
492
        ->status_is( 204, 'REST3.2.4' )
477
        ->content_is( q{}, 'REST3.3.4' );
493
        ->content_is( q{}, 'REST3.3.4' );
478
494
479
    $schema->storage->txn_rollback;
495
    $schema->storage->txn_rollback;
(-)a/t/db_dependent/api/v1/ticket_updates.t (-22 / +52 lines)
Lines 77-83 subtest 'list_updates() tests' => sub { Link Here
77
    );
77
    );
78
78
79
    # One ticket update added, should get returned
79
    # One ticket update added, should get returned
80
    $t->get_ok("//$userid:$password@/api/v1/tickets/$ticket_id/updates")->status_is(200)
80
    $t->get_ok("//$userid:$password@/api/v1/tickets/$ticket_id/updates")
81
        ->status_is(200)
81
        ->json_is( [ $update->to_api ] );
82
        ->json_is( [ $update->to_api ] );
82
83
83
    my $update_2 = $builder->build_object(
84
    my $update_2 = $builder->build_object(
Lines 94-100 subtest 'list_updates() tests' => sub { Link Here
94
    );
95
    );
95
96
96
    # Two ticket updates added, they should both be returned
97
    # Two ticket updates added, they should both be returned
97
    $t->get_ok("//$userid:$password@/api/v1/tickets/$ticket_id/updates")->status_is(200)
98
    $t->get_ok("//$userid:$password@/api/v1/tickets/$ticket_id/updates")
99
        ->status_is(200)
98
        ->json_is( [ $update->to_api, $update_2->to_api, $update_3->to_api, ] );
100
        ->json_is( [ $update->to_api, $update_2->to_api, $update_3->to_api, ] );
99
101
100
    # Warn on unsupported query parameter
102
    # Warn on unsupported query parameter
Lines 163-173 subtest 'add_update() tests' => sub { Link Here
163
    # Authorized attempt to write
165
    # Authorized attempt to write
164
    my $update_id =
166
    my $update_id =
165
        $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )
167
        $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )
166
        ->status_is( 201, 'REST3.2.1' )->header_like(
168
        ->status_is( 201, 'REST3.2.1' )
169
        ->header_like(
167
        Location => qr|^\/api\/v1\/tickets/\d*|,
170
        Location => qr|^\/api\/v1\/tickets/\d*|,
168
        'REST3.4.1'
171
        'REST3.4.1'
169
    )->json_is( '/message' => $update->{message} )->json_is( '/public' => $update->{public} )
172
        )
170
        ->json_is( '/status' => undef )->json_is( '/assignee_id' => undef )->json_is( '/user_id' => $librarian->id )
173
        ->json_is( '/message'     => $update->{message} )
174
        ->json_is( '/public'      => $update->{public} )
175
        ->json_is( '/status'      => undef )
176
        ->json_is( '/assignee_id' => undef )
177
        ->json_is( '/user_id'     => $librarian->id )
171
        ->tx->res->json->{update_id};
178
        ->tx->res->json->{update_id};
172
179
173
    # Check that notice trigger didn't fire for non-public update
180
    # Check that notice trigger didn't fire for non-public update
Lines 179-190 subtest 'add_update() tests' => sub { Link Here
179
186
180
    # Authorized attempt to create with null id
187
    # Authorized attempt to create with null id
181
    $update->{update_id} = undef;
188
    $update->{update_id} = undef;
182
    $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )->status_is(400)
189
    $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )
190
        ->status_is(400)
183
        ->json_has('/errors');
191
        ->json_has('/errors');
184
192
185
    # Authorized attempt to create with existing id
193
    # Authorized attempt to create with existing id
186
    $update->{update_id} = $update_id;
194
    $update->{update_id} = $update_id;
187
    $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )->status_is(400)
195
    $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )
196
        ->status_is(400)
188
        ->json_is(
197
        ->json_is(
189
        "/errors" => [
198
        "/errors" => [
190
            {
199
            {
Lines 199-205 subtest 'add_update() tests' => sub { Link Here
199
    my $update_with_missing_field = { message => "Another ticket update" };
208
    my $update_with_missing_field = { message => "Another ticket update" };
200
209
201
    $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update_with_missing_field )
210
    $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update_with_missing_field )
202
        ->status_is(400)->json_is(
211
        ->status_is(400)
212
        ->json_is(
203
        "/errors" => [
213
        "/errors" => [
204
            {
214
            {
205
                message => "Missing property.",
215
                message => "Missing property.",
Lines 212-222 subtest 'add_update() tests' => sub { Link Here
212
    $update->{public} = Mojo::JSON->true;
222
    $update->{public} = Mojo::JSON->true;
213
    $update_id =
223
    $update_id =
214
        $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )
224
        $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )
215
        ->status_is( 201, 'REST3.2.1' )->header_like(
225
        ->status_is( 201, 'REST3.2.1' )
226
        ->header_like(
216
        Location => qr|^\/api\/v1\/tickets/\d*|,
227
        Location => qr|^\/api\/v1\/tickets/\d*|,
217
        'REST3.4.1'
228
        'REST3.4.1'
218
    )->json_is( '/message' => $update->{message} )->json_is( '/public' => $update->{public} )
229
        )
219
        ->json_is( '/status' => undef )->json_is( '/assignee_id' => undef )->json_is( '/user_id' => $librarian->id )
230
        ->json_is( '/message'     => $update->{message} )
231
        ->json_is( '/public'      => $update->{public} )
232
        ->json_is( '/status'      => undef )
233
        ->json_is( '/assignee_id' => undef )
234
        ->json_is( '/user_id'     => $librarian->id )
220
        ->tx->res->json->{update_id};
235
        ->tx->res->json->{update_id};
221
236
222
    $notices = Koha::Notice::Messages->search( { borrowernumber => $patron->id } );
237
    $notices = Koha::Notice::Messages->search( { borrowernumber => $patron->id } );
Lines 235-245 subtest 'add_update() tests' => sub { Link Here
235
    $update->{state} = 'resolved';
250
    $update->{state} = 'resolved';
236
    $update_id =
251
    $update_id =
237
        $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )
252
        $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )
238
        ->status_is( 201, 'REST3.2.1' )->header_like(
253
        ->status_is( 201, 'REST3.2.1' )
254
        ->header_like(
239
        Location => qr|^\/api\/v1\/tickets/\d*|,
255
        Location => qr|^\/api\/v1\/tickets/\d*|,
240
        'REST3.4.1'
256
        'REST3.4.1'
241
    )->json_is( '/message' => $update->{message} )->json_is( '/public' => $update->{public} )
257
        )
242
        ->json_is( '/status' => undef )->json_is( '/assignee_id' => undef )->json_is( '/user_id' => $librarian->id )
258
        ->json_is( '/message'     => $update->{message} )
259
        ->json_is( '/public'      => $update->{public} )
260
        ->json_is( '/status'      => undef )
261
        ->json_is( '/assignee_id' => undef )
262
        ->json_is( '/user_id'     => $librarian->id )
243
        ->tx->res->json->{update_id};
263
        ->tx->res->json->{update_id};
244
264
245
    $notices = Koha::Notice::Messages->search( { borrowernumber => $patron->id } );
265
    $notices = Koha::Notice::Messages->search( { borrowernumber => $patron->id } );
Lines 268-279 subtest 'add_update() tests' => sub { Link Here
268
    $update->{status} = 'TEST';
288
    $update->{status} = 'TEST';
269
    $update_id =
289
    $update_id =
270
        $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )
290
        $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )
271
        ->status_is( 201, 'REST3.2.1' )->header_like(
291
        ->status_is( 201, 'REST3.2.1' )
292
        ->header_like(
272
        Location => qr|^\/api\/v1\/tickets/\d*|,
293
        Location => qr|^\/api\/v1\/tickets/\d*|,
273
        'REST3.4.1'
294
        'REST3.4.1'
274
    )->json_is( '/message' => $update->{message} )->json_is( '/public' => $update->{public} )
295
        )
275
        ->json_is( '/status'  => $update->{status} )->json_is( '/assignee_id' => undef )
296
        ->json_is( '/message'     => $update->{message} )
276
        ->json_is( '/user_id' => $librarian->id )->tx->res->json->{update_id};
297
        ->json_is( '/public'      => $update->{public} )
298
        ->json_is( '/status'      => $update->{status} )
299
        ->json_is( '/assignee_id' => undef )
300
        ->json_is( '/user_id'     => $librarian->id )
301
        ->tx->res->json->{update_id};
277
302
278
    $ticket = $ticket->get_from_storage;
303
    $ticket = $ticket->get_from_storage;
279
    is(
304
    is(
Lines 287-298 subtest 'add_update() tests' => sub { Link Here
287
    $update->{assignee_id} = $librarian->id;
312
    $update->{assignee_id} = $librarian->id;
288
    $update_id =
313
    $update_id =
289
        $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )
314
        $t->post_ok( "//$userid:$password@/api/v1/tickets/$ticket_id/updates" => json => $update )
290
        ->status_is( 201, 'REST3.2.1' )->header_like(
315
        ->status_is( 201, 'REST3.2.1' )
316
        ->header_like(
291
        Location => qr|^\/api\/v1\/tickets/\d*|,
317
        Location => qr|^\/api\/v1\/tickets/\d*|,
292
        'REST3.4.1'
318
        'REST3.4.1'
293
    )->json_is( '/message' => $update->{message} )->json_is( '/public' => $update->{public} )
319
        )
294
        ->json_is( '/status'  => $update->{status} )->json_is( '/assignee_id' => $update->{assignee_id} )
320
        ->json_is( '/message'     => $update->{message} )
295
        ->json_is( '/user_id' => $librarian->id )->tx->res->json->{update_id};
321
        ->json_is( '/public'      => $update->{public} )
322
        ->json_is( '/status'      => $update->{status} )
323
        ->json_is( '/assignee_id' => $update->{assignee_id} )
324
        ->json_is( '/user_id'     => $librarian->id )
325
        ->tx->res->json->{update_id};
296
326
297
    $ticket = $ticket->get_from_storage;
327
    $ticket = $ticket->get_from_storage;
298
    is(
328
    is(
(-)a/t/db_dependent/api/v1/tickets.t (-14 / +31 lines)
Lines 132-138 subtest 'get() tests' => sub { Link Here
132
    my $non_existent_id  = $ticket_to_delete->id;
132
    my $non_existent_id  = $ticket_to_delete->id;
133
    $ticket_to_delete->delete;
133
    $ticket_to_delete->delete;
134
134
135
    $t->get_ok("//$userid:$password@/api/v1/tickets/$non_existent_id")->status_is(404)
135
    $t->get_ok("//$userid:$password@/api/v1/tickets/$non_existent_id")
136
        ->status_is(404)
136
        ->json_is( '/error' => 'Ticket not found' );
137
        ->json_is( '/error' => 'Ticket not found' );
137
138
138
    $schema->storage->txn_rollback;
139
    $schema->storage->txn_rollback;
Lines 184-190 subtest 'add() tests' => sub { Link Here
184
        body      => "Test ticket details",
185
        body      => "Test ticket details",
185
    };
186
    };
186
187
187
    $t->post_ok( "//$userid:$password@/api/v1/tickets" => json => $ticket_with_invalid_field )->status_is(400)
188
    $t->post_ok( "//$userid:$password@/api/v1/tickets" => json => $ticket_with_invalid_field )
189
        ->status_is(400)
188
        ->json_is(
190
        ->json_is(
189
        "/errors" => [
191
        "/errors" => [
190
            {
192
            {
Lines 196-207 subtest 'add() tests' => sub { Link Here
196
198
197
    # Authorized attempt to write
199
    # Authorized attempt to write
198
    my $ticket_id =
200
    my $ticket_id =
199
        $t->post_ok( "//$userid:$password@/api/v1/tickets" => json => $ticket )->status_is( 201, 'REST3.2.1' )
201
        $t->post_ok( "//$userid:$password@/api/v1/tickets" => json => $ticket )
202
        ->status_is( 201, 'REST3.2.1' )
200
        ->header_like(
203
        ->header_like(
201
        Location => qr|^\/api\/v1\/tickets/\d*|,
204
        Location => qr|^\/api\/v1\/tickets/\d*|,
202
        'REST3.4.1'
205
        'REST3.4.1'
203
    )->json_is( '/biblio_id' => $ticket->{biblio_id} )->json_is( '/title' => $ticket->{title} )
206
        )
204
        ->json_is( '/body' => $ticket->{body} )->json_is( '/reporter_id' => $librarian->id )
207
        ->json_is( '/biblio_id'   => $ticket->{biblio_id} )
208
        ->json_is( '/title'       => $ticket->{title} )
209
        ->json_is( '/body'        => $ticket->{body} )
210
        ->json_is( '/reporter_id' => $librarian->id )
205
        ->tx->res->json->{ticket_id};
211
        ->tx->res->json->{ticket_id};
206
212
207
    # Authorized attempt to create with null id
213
    # Authorized attempt to create with null id
Lines 226-232 subtest 'add() tests' => sub { Link Here
226
        body      => "Test ticket details",
232
        body      => "Test ticket details",
227
    };
233
    };
228
234
229
    $t->post_ok( "//$userid:$password@/api/v1/tickets" => json => $ticket_with_missing_field )->status_is(400)
235
    $t->post_ok( "//$userid:$password@/api/v1/tickets" => json => $ticket_with_missing_field )
236
        ->status_is(400)
230
        ->json_is(
237
        ->json_is(
231
        "/errors" => [
238
        "/errors" => [
232
            {
239
            {
Lines 246-256 subtest 'add() tests' => sub { Link Here
246
253
247
        $ticket_id =
254
        $ticket_id =
248
            $t->post_ok( "//$useridp:$password@/api/v1/public/tickets" => json => $ticket )
255
            $t->post_ok( "//$useridp:$password@/api/v1/public/tickets" => json => $ticket )
249
            ->status_is( 201, 'REST3.2.1' )->header_like(
256
            ->status_is( 201, 'REST3.2.1' )
257
            ->header_like(
250
            Location => qr|^\/api\/v1\/public\/tickets/\d*|,
258
            Location => qr|^\/api\/v1\/public\/tickets/\d*|,
251
            'REST3.4.1'
259
            'REST3.4.1'
252
        )->json_is( '/biblio_id' => $ticket->{biblio_id} )->json_is( '/title' => $ticket->{title} )
260
            )
253
            ->json_is( '/body' => $ticket->{body} )->json_is( '/reporter_id' => $patron->id )
261
            ->json_is( '/biblio_id'   => $ticket->{biblio_id} )
262
            ->json_is( '/title'       => $ticket->{title} )
263
            ->json_is( '/body'        => $ticket->{body} )
264
            ->json_is( '/reporter_id' => $patron->id )
254
            ->tx->res->json->{ticket_id};
265
            ->tx->res->json->{ticket_id};
255
266
256
    };
267
    };
Lines 299-305 subtest 'update() tests' => sub { Link Here
299
    };
310
    };
300
311
301
    $t->put_ok( "//$userid:$password@/api/v1/tickets/$ticket_id" => json => $ticket_with_missing_field )
312
    $t->put_ok( "//$userid:$password@/api/v1/tickets/$ticket_id" => json => $ticket_with_missing_field )
302
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/title" } ] );
313
        ->status_is(400)
314
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/title" } ] );
303
315
304
    # Full object update on PUT
316
    # Full object update on PUT
305
    my $ticket_with_updated_field = {
317
    my $ticket_with_updated_field = {
Lines 309-320 subtest 'update() tests' => sub { Link Here
309
    };
321
    };
310
322
311
    $t->put_ok( "//$userid:$password@/api/v1/tickets/$ticket_id" => json => $ticket_with_updated_field )
323
    $t->put_ok( "//$userid:$password@/api/v1/tickets/$ticket_id" => json => $ticket_with_updated_field )
312
        ->status_is(200)->json_is( '/title' => 'Test ticket update' );
324
        ->status_is(200)
325
        ->json_is( '/title' => 'Test ticket update' );
313
326
314
    # Set the assignee on PUT
327
    # Set the assignee on PUT
315
    $ticket_with_updated_field->{assignee_id} = $librarian->id;
328
    $ticket_with_updated_field->{assignee_id} = $librarian->id;
316
    $t->put_ok( "//$userid:$password@/api/v1/tickets/$ticket_id" => json => $ticket_with_updated_field )
329
    $t->put_ok( "//$userid:$password@/api/v1/tickets/$ticket_id" => json => $ticket_with_updated_field )
317
        ->status_is(200)->json_is( '/title' => 'Test ticket update' )->json_is( '/assignee_id' => $librarian->id );
330
        ->status_is(200)
331
        ->json_is( '/title'       => 'Test ticket update' )
332
        ->json_is( '/assignee_id' => $librarian->id );
318
333
319
    my $updates = $ticket->updates;
334
    my $updates = $ticket->updates;
320
    is( $updates->count, 1, "Ticket update added for assignee change" );
335
    is( $updates->count, 1, "Ticket update added for assignee change" );
Lines 328-334 subtest 'update() tests' => sub { Link Here
328
    };
343
    };
329
344
330
    $t->put_ok( "//$userid:$password@/api/v1/tickets/$ticket_id" => json => $ticket_with_invalid_field )
345
    $t->put_ok( "//$userid:$password@/api/v1/tickets/$ticket_id" => json => $ticket_with_invalid_field )
331
        ->status_is(400)->json_is(
346
        ->status_is(400)
347
        ->json_is(
332
        "/errors" => [
348
        "/errors" => [
333
            {
349
            {
334
                message => "Properties not allowed: blah.",
350
                message => "Properties not allowed: blah.",
Lines 384-390 subtest 'delete() tests' => sub { Link Here
384
    # Unauthorized attempt to delete
400
    # Unauthorized attempt to delete
385
    $t->delete_ok("//$unauth_userid:$password@/api/v1/tickets/$ticket_id")->status_is(403);
401
    $t->delete_ok("//$unauth_userid:$password@/api/v1/tickets/$ticket_id")->status_is(403);
386
402
387
    $t->delete_ok("//$userid:$password@/api/v1/tickets/$ticket_id")->status_is( 204, 'REST3.2.4' )
403
    $t->delete_ok("//$userid:$password@/api/v1/tickets/$ticket_id")
404
        ->status_is( 204, 'REST3.2.4' )
388
        ->content_is( '', 'REST3.3.4' );
405
        ->content_is( '', 'REST3.3.4' );
389
406
390
    $t->delete_ok("//$userid:$password@/api/v1/tickets/$ticket_id")->status_is(404);
407
    $t->delete_ok("//$userid:$password@/api/v1/tickets/$ticket_id")->status_is(404);
(-)a/t/db_dependent/api/v1/transfer_limits.t (-15 / +30 lines)
Lines 56-62 subtest 'list() tests' => sub { Link Here
56
56
57
    my $limit = $builder->build_object( { class => 'Koha::Item::Transfer::Limits' } );
57
    my $limit = $builder->build_object( { class => 'Koha::Item::Transfer::Limits' } );
58
58
59
    $t->get_ok("//$userid:$password@/api/v1/transfer_limits")->status_is( 200, 'REST3.2.2' )
59
    $t->get_ok("//$userid:$password@/api/v1/transfer_limits")
60
        ->status_is( 200, 'REST3.2.2' )
60
        ->json_is( [ $limit->to_api ] );
61
        ->json_is( [ $limit->to_api ] );
61
62
62
    $schema->storage->txn_rollback;
63
    $schema->storage->txn_rollback;
Lines 99-105 subtest 'add() tests' => sub { Link Here
99
    my $limit_with_invalid_field = { 'invalid' => 'invalid' };
100
    my $limit_with_invalid_field = { 'invalid' => 'invalid' };
100
101
101
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits" => json => $limit_with_invalid_field )
102
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits" => json => $limit_with_invalid_field )
102
        ->status_is(400)->json_is(
103
        ->status_is(400)
104
        ->json_is(
103
        "/errors" => [
105
        "/errors" => [
104
            {
106
            {
105
                message => "Properties not allowed: invalid.",
107
                message => "Properties not allowed: invalid.",
Lines 110-120 subtest 'add() tests' => sub { Link Here
110
112
111
    # Authorized attempt to write
113
    # Authorized attempt to write
112
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits" => json => $limit_hashref )
114
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits" => json => $limit_hashref )
113
        ->status_is( 201, 'REST3.2.1' )->json_has( '' => $limit_hashref, 'REST3.3.1' )
115
        ->status_is( 201, 'REST3.2.1' )
116
        ->json_has( '' => $limit_hashref, 'REST3.3.1' )
114
        ->header_is( 'Location' => '/api/v1/transfer_limits/' . $t->tx->res->json->{limit_id}, 'REST3.4.1' );
117
        ->header_is( 'Location' => '/api/v1/transfer_limits/' . $t->tx->res->json->{limit_id}, 'REST3.4.1' );
115
118
116
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits" => json => $limit_hashref )
119
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits" => json => $limit_hashref )
117
        ->status_is( 409, 'Conflict creating the resource' )->json_is(
120
        ->status_is( 409, 'Conflict creating the resource' )
121
        ->json_is(
118
        {
122
        {
119
            error =>
123
            error =>
120
                qq{Exception 'Koha::Exceptions::TransferLimit::Duplicate' thrown 'A transfer limit with the given parameters already exists!'\n}
124
                qq{Exception 'Koha::Exceptions::TransferLimit::Duplicate' thrown 'A transfer limit with the given parameters already exists!'\n}
Lines 154-160 subtest 'delete() tests' => sub { Link Here
154
    # Unauthorized attempt to delete
158
    # Unauthorized attempt to delete
155
    $t->delete_ok("//$unauth_userid:$password@/api/v1/transfer_limits/$limit_id")->status_is(403);
159
    $t->delete_ok("//$unauth_userid:$password@/api/v1/transfer_limits/$limit_id")->status_is(403);
156
160
157
    $t->delete_ok("//$auth_userid:$password@/api/v1/transfer_limits/$limit_id")->status_is( 204, 'REST3.2.4' )
161
    $t->delete_ok("//$auth_userid:$password@/api/v1/transfer_limits/$limit_id")
162
        ->status_is( 204, 'REST3.2.4' )
158
        ->content_is( '', 'REST3.3.4' );
163
        ->content_is( '', 'REST3.3.4' );
159
164
160
    $t->delete_ok("//$auth_userid:$password@/api/v1/transfer_limits/$limit_id")->status_is(404);
165
    $t->delete_ok("//$auth_userid:$password@/api/v1/transfer_limits/$limit_id")->status_is(404);
Lines 205-211 subtest 'batch_add() and batch_delete() tests' => sub { Link Here
205
    my $limit_with_invalid_field = { 'invalid' => 'invalid' };
210
    my $limit_with_invalid_field = { 'invalid' => 'invalid' };
206
211
207
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_with_invalid_field )
212
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_with_invalid_field )
208
        ->status_is(400)->json_is(
213
        ->status_is(400)
214
        ->json_is(
209
        "/errors" => [
215
        "/errors" => [
210
            {
216
            {
211
                message => "Properties not allowed: invalid.",
217
                message => "Properties not allowed: invalid.",
Lines 216-239 subtest 'batch_add() and batch_delete() tests' => sub { Link Here
216
222
217
    # Create all combinations of to/from libraries
223
    # Create all combinations of to/from libraries
218
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json =>
224
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json =>
219
            { item_type => 'X', collection_code => 'Y' } )->status_is(400)
225
            { item_type => 'X', collection_code => 'Y' } )
226
        ->status_is(400)
220
        ->json_is( '/error' => "You can only pass 'item_type' or 'collection_code' at a time" );
227
        ->json_is( '/error' => "You can only pass 'item_type' or 'collection_code' at a time" );
221
228
222
    t::lib::Mocks::mock_preference( 'BranchTransferLimitsType', 'ccode' );
229
    t::lib::Mocks::mock_preference( 'BranchTransferLimitsType', 'ccode' );
223
230
224
    # Create all combinations of to/from libraries
231
    # Create all combinations of to/from libraries
225
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => { item_type => 'X' } )
232
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => { item_type => 'X' } )
226
        ->status_is(409)->json_is( '/error' => "You passed 'item_type' but configuration expects 'collection_code'" );
233
        ->status_is(409)
234
        ->json_is( '/error' => "You passed 'item_type' but configuration expects 'collection_code'" );
227
235
228
    t::lib::Mocks::mock_preference( 'BranchTransferLimitsType', 'itemtype' );
236
    t::lib::Mocks::mock_preference( 'BranchTransferLimitsType', 'itemtype' );
229
237
230
    # Create all combinations of to/from libraries
238
    # Create all combinations of to/from libraries
231
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => { collection_code => 'X' } )
239
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => { collection_code => 'X' } )
232
        ->status_is(409)->json_is( '/error' => "You passed 'collection_code' but configuration expects 'item_type'" );
240
        ->status_is(409)
241
        ->json_is( '/error' => "You passed 'collection_code' but configuration expects 'item_type'" );
233
242
234
    # Create all combinations of to/from libraries
243
    # Create all combinations of to/from libraries
235
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_hashref )
244
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_hashref )
236
        ->status_is( 201, 'REST3.2.1' )->json_has( '' => $limit_hashref, 'REST3.3.1' );
245
        ->status_is( 201, 'REST3.2.1' )
246
        ->json_has( '' => $limit_hashref, 'REST3.3.1' );
237
247
238
    my $limits = Koha::Item::Transfer::Limits->search;
248
    my $limits = Koha::Item::Transfer::Limits->search;
239
249
Lines 242-248 subtest 'batch_add() and batch_delete() tests' => sub { Link Here
242
252
243
    # Delete all combinations of to/from libraries
253
    # Delete all combinations of to/from libraries
244
    $t->delete_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_hashref )
254
    $t->delete_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_hashref )
245
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
255
        ->status_is( 204, 'REST3.2.4' )
256
        ->content_is( '', 'REST3.3.4' );
246
257
247
    $limits = Koha::Item::Transfer::Limits->search;
258
    $limits = Koha::Item::Transfer::Limits->search;
248
259
Lines 251-257 subtest 'batch_add() and batch_delete() tests' => sub { Link Here
251
    # Create all combinations of 'to' libraries
262
    # Create all combinations of 'to' libraries
252
    $limit_hashref->{to_library_id} = $library->id;
263
    $limit_hashref->{to_library_id} = $library->id;
253
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_hashref )
264
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_hashref )
254
        ->status_is( 201, 'REST3.2.1' )->json_has( '' => $limit_hashref, 'REST3.3.1' );
265
        ->status_is( 201, 'REST3.2.1' )
266
        ->json_has( '' => $limit_hashref, 'REST3.3.1' );
255
267
256
    $limits = Koha::Item::Transfer::Limits->search;
268
    $limits = Koha::Item::Transfer::Limits->search;
257
269
Lines 259-265 subtest 'batch_add() and batch_delete() tests' => sub { Link Here
259
271
260
    # Delete all combinations of 'to' libraries
272
    # Delete all combinations of 'to' libraries
261
    $t->delete_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_hashref )
273
    $t->delete_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_hashref )
262
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
274
        ->status_is( 204, 'REST3.2.4' )
275
        ->content_is( '', 'REST3.3.4' );
263
276
264
    $limits = Koha::Item::Transfer::Limits->search;
277
    $limits = Koha::Item::Transfer::Limits->search;
265
278
Lines 271-277 subtest 'batch_add() and batch_delete() tests' => sub { Link Here
271
    delete $limit_hashref->{to_library_id};
284
    delete $limit_hashref->{to_library_id};
272
    $limit_hashref->{from_library_id} = $library->id;
285
    $limit_hashref->{from_library_id} = $library->id;
273
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_hashref )
286
    $t->post_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_hashref )
274
        ->status_is( 201, 'REST3.2.1' )->json_has( '' => $limit_hashref, 'REST3.3.1' );
287
        ->status_is( 201, 'REST3.2.1' )
288
        ->json_has( '' => $limit_hashref, 'REST3.3.1' );
275
289
276
    $limits = Koha::Item::Transfer::Limits->search;
290
    $limits = Koha::Item::Transfer::Limits->search;
277
291
Lines 280-286 subtest 'batch_add() and batch_delete() tests' => sub { Link Here
280
294
281
    # Delete all combinations of 'from' libraries
295
    # Delete all combinations of 'from' libraries
282
    $t->delete_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_hashref )
296
    $t->delete_ok( "//$auth_userid:$password@/api/v1/transfer_limits/batch" => json => $limit_hashref )
283
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
297
        ->status_is( 204, 'REST3.2.4' )
298
        ->content_is( '', 'REST3.3.4' );
284
299
285
    $limits = Koha::Item::Transfer::Limits->search;
300
    $limits = Koha::Item::Transfer::Limits->search;
286
301
(-)a/t/db_dependent/mojo/csrf.t (-6 / +12 lines)
Lines 19-32 subtest 'CSRF - Intranet' => sub { Link Here
19
    subtest 'Without a CSRF token' => sub {
19
    subtest 'Without a CSRF token' => sub {
20
        plan tests => 3;
20
        plan tests => 3;
21
21
22
        $t->post_ok('/cgi-bin/koha/mainpage.pl')->status_is(403)
22
        $t->post_ok('/cgi-bin/koha/mainpage.pl')
23
            ->status_is(403)
23
            ->content_like( qr/Wrong CSRF token/, 'Body contains "Wrong CSRF token"' );
24
            ->content_like( qr/Wrong CSRF token/, 'Body contains "Wrong CSRF token"' );
24
    };
25
    };
25
26
26
    subtest 'With a wrong CSRF token' => sub {
27
    subtest 'With a wrong CSRF token' => sub {
27
        plan tests => 3;
28
        plan tests => 3;
28
29
29
        $t->post_ok( '/cgi-bin/koha/mainpage.pl', form => { csrf_token => 'BAD', op => 'cud-login' } )->status_is(403)
30
        $t->post_ok( '/cgi-bin/koha/mainpage.pl', form => { csrf_token => 'BAD', op => 'cud-login' } )
31
            ->status_is(403)
30
            ->content_like( qr/Wrong CSRF token/, 'Body contains "Wrong CSRF token"' );
32
            ->content_like( qr/Wrong CSRF token/, 'Body contains "Wrong CSRF token"' );
31
    };
33
    };
32
34
Lines 38-44 subtest 'CSRF - Intranet' => sub { Link Here
38
        my $csrf_token = $t->tx->res->dom('input[name="csrf_token"]')->map( attr => 'value' )->first;
40
        my $csrf_token = $t->tx->res->dom('input[name="csrf_token"]')->map( attr => 'value' )->first;
39
41
40
        $t->post_ok( '/cgi-bin/koha/mainpage.pl', form => { csrf_token => $csrf_token, op => 'cud-login' } )
42
        $t->post_ok( '/cgi-bin/koha/mainpage.pl', form => { csrf_token => $csrf_token, op => 'cud-login' } )
41
            ->status_is(200)->content_like( qr/Please log in again/, 'Login failed but CSRF test passed' );
43
            ->status_is(200)
44
            ->content_like( qr/Please log in again/, 'Login failed but CSRF test passed' );
42
    };
45
    };
43
46
44
    subtest 'GETting what should be POSTed should fail' => sub {
47
    subtest 'GETting what should be POSTed should fail' => sub {
Lines 71-84 subtest 'CSRF - OPAC' => sub { Link Here
71
    subtest 'Without a CSRF token' => sub {
74
    subtest 'Without a CSRF token' => sub {
72
        plan tests => 3;
75
        plan tests => 3;
73
76
74
        $t->post_ok('/cgi-bin/koha/opac-user.pl')->status_is(403)
77
        $t->post_ok('/cgi-bin/koha/opac-user.pl')
78
            ->status_is(403)
75
            ->content_like( qr/Wrong CSRF token/, 'Body contains "Wrong CSRF token"' );
79
            ->content_like( qr/Wrong CSRF token/, 'Body contains "Wrong CSRF token"' );
76
    };
80
    };
77
81
78
    subtest 'With a wrong CSRF token' => sub {
82
    subtest 'With a wrong CSRF token' => sub {
79
        plan tests => 3;
83
        plan tests => 3;
80
84
81
        $t->post_ok( '/cgi-bin/koha/opac-user.pl', form => { csrf_token => 'BAD', op => 'cud-login' } )->status_is(403)
85
        $t->post_ok( '/cgi-bin/koha/opac-user.pl', form => { csrf_token => 'BAD', op => 'cud-login' } )
86
            ->status_is(403)
82
            ->content_like( qr/Wrong CSRF token/, 'Body contains "Wrong CSRF token"' );
87
            ->content_like( qr/Wrong CSRF token/, 'Body contains "Wrong CSRF token"' );
83
    };
88
    };
84
89
Lines 90-96 subtest 'CSRF - OPAC' => sub { Link Here
90
        my $csrf_token = $t->tx->res->dom('input[name="csrf_token"]')->map( attr => 'value' )->first;
95
        my $csrf_token = $t->tx->res->dom('input[name="csrf_token"]')->map( attr => 'value' )->first;
91
96
92
        $t->post_ok( '/cgi-bin/koha/opac-user.pl', form => { csrf_token => $csrf_token, op => 'cud-login' } )
97
        $t->post_ok( '/cgi-bin/koha/opac-user.pl', form => { csrf_token => $csrf_token, op => 'cud-login' } )
93
            ->status_is(200)->content_like( qr/Log in to your account/, 'Login failed but CSRF test passed' );
98
            ->status_is(200)
99
            ->content_like( qr/Log in to your account/, 'Login failed but CSRF test passed' );
94
    };
100
    };
95
101
96
    subtest 'GETting what should be POSTed should fail' => sub {
102
    subtest 'GETting what should be POSTed should fail' => sub {
(-)a/t/db_dependent/mojo/rest-auth.t (-4 / +10 lines)
Lines 29-38 sub rest_auth_subtest { Link Here
29
29
30
        my $t = Test::Mojo->new($app);
30
        my $t = Test::Mojo->new($app);
31
31
32
        $t->post_ok('/api/v1/oauth/token')->status_is(400)->json_is( '/errors/0/message', 'Missing property.' )
32
        $t->post_ok('/api/v1/oauth/token')
33
            ->json_is( '/errors/0/path', '/grant_type' );
33
            ->status_is(400)
34
            ->json_is( '/errors/0/message', 'Missing property.' )
35
            ->json_is( '/errors/0/path',    '/grant_type' );
34
36
35
        $t->post_ok( '/api/v1/oauth/token', form => { grant_type => 'client_credentials' } )->status_is(403)
37
        $t->post_ok( '/api/v1/oauth/token', form => { grant_type => 'client_credentials' } )
38
            ->status_is(403)
36
            ->json_is( '/error', 'unauthorized_client' );
39
            ->json_is( '/error', 'unauthorized_client' );
37
40
38
        my $patron = $builder->build_object(
41
        my $patron = $builder->build_object(
Lines 50-56 sub rest_auth_subtest { Link Here
50
        $t->post_ok(
53
        $t->post_ok(
51
            '/api/v1/oauth/token',
54
            '/api/v1/oauth/token',
52
            form => { grant_type => 'client_credentials', client_id => $client_id, client_secret => $client_secret }
55
            form => { grant_type => 'client_credentials', client_id => $client_id, client_secret => $client_secret }
53
        )->status_is(200)->json_is( '/expires_in' => 3600 )->json_is( '/token_type' => 'Bearer' )
56
            )
57
            ->status_is(200)
58
            ->json_is( '/expires_in' => 3600 )
59
            ->json_is( '/token_type' => 'Bearer' )
54
            ->json_has('/access_token');
60
            ->json_has('/access_token');
55
61
56
        $schema->storage->txn_rollback;
62
        $schema->storage->txn_rollback;
(-)a/t/db_dependent/selenium/regressions.t (-2 / +2 lines)
Lines 108-115 subtest 'OPAC - borrowernumber, branchcode and categorycode as html attributes' Link Here
108
        $elt->get_attribute( 'data-branchcode', 1 ), $patron->library->branchcode,
108
        $elt->get_attribute( 'data-branchcode', 1 ), $patron->library->branchcode,
109
        "Since bug 20921 span.loggedinusername should contain data-branchcode"
109
        "Since bug 20921 span.loggedinusername should contain data-branchcode"
110
110
111
            # No idea why we need the second param of get_attribute(). As
111
        # No idea why we need the second param of get_attribute(). As
112
            # data-branchcode is still there after page finished loading.
112
        # data-branchcode is still there after page finished loading.
113
    );
113
    );
114
    is(
114
    is(
115
        $elt->get_attribute( 'data-borrowernumber', 1 ), $patron->borrowernumber,
115
        $elt->get_attribute( 'data-borrowernumber', 1 ), $patron->borrowernumber,
(-)a/t/lib/QA/TemplateFilters.pm (-2 / +2 lines)
Lines 172-185 sub process_tt_block { Link Here
172
        ? $pre_chomp =~ m|-|
172
        ? $pre_chomp =~ m|-|
173
            ? q|- |
173
            ? q|- |
174
            : $pre_chomp =~ m|~| ? q|~ |
174
            : $pre_chomp =~ m|~| ? q|~ |
175
        : q| |
175
            : q| |
176
        : q| |;
176
        : q| |;
177
    $post_chomp =
177
    $post_chomp =
178
          $post_chomp
178
          $post_chomp
179
        ? $post_chomp =~ m|-|
179
        ? $post_chomp =~ m|-|
180
            ? q| -|
180
            ? q| -|
181
            : $post_chomp =~ m|~| ? q| ~|
181
            : $post_chomp =~ m|~| ? q| ~|
182
        : q| |
182
            : q| |
183
        : q| |;
183
        : q| |;
184
184
185
    if (   $tt_block =~ m{\s?\|\s?\$KohaDates[^\|]*\|.*$}
185
    if (   $tt_block =~ m{\s?\|\s?\$KohaDates[^\|]*\|.*$}
(-)a/tags/review.pl (-1 / +1 lines)
Lines 110-116 if ( $op eq 'cud-approve' ) { Link Here
110
    $template->param(
110
    $template->param(
111
        test_term => $tag,
111
        test_term => $tag,
112
        (
112
        (
113
              $check >= 1  ? 'verdict_ok'
113
              $check >=  1 ? 'verdict_ok'
114
            : $check <= -1 ? 'verdict_rej'
114
            : $check <= -1 ? 'verdict_rej'
115
            :                'verdict_indeterminate'
115
            :                'verdict_indeterminate'
116
        ) => 1,
116
        ) => 1,
(-)a/tools/stockrotation.pl (-1 / +3 lines)
Lines 473-479 sub process_rota { Link Here
473
473
474
    if ($rota) {
474
    if ($rota) {
475
475
476
        $rota->title( $sub_rota->{title} )->cyclical( $sub_rota->{cyclical} )->description( $sub_rota->{description} )
476
        $rota->title( $sub_rota->{title} )
477
            ->cyclical( $sub_rota->{cyclical} )
478
            ->description( $sub_rota->{description} )
477
            ->store;
479
            ->store;
478
480
479
    } else {
481
    } else {
(-)a/xt/find-license-problems.t (-2 / +1 lines)
Lines 35-41 my @files = map { Link Here
35
        || $name =~ m{xt/find-license-problems|xt/fix-old-fsf-address|misc/translator/po2json}
35
        || $name =~ m{xt/find-license-problems|xt/fix-old-fsf-address|misc/translator/po2json}
36
        || $name =~ m[t/mock_templates/intranet-tmpl/prog]
36
        || $name =~ m[t/mock_templates/intranet-tmpl/prog]
37
        || !-f $name )
37
        || !-f $name )
38
        ? $_
38
    ? $_
39
        : ()
39
        : ()
40
} `git ls-tree -r HEAD --name-only`;    # only files part of git
40
} `git ls-tree -r HEAD --name-only`;    # only files part of git
41
41
42
- 

Return to bug 41076