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

(-)a/C4/Auth.pm (-1 / +1 lines)
Lines 1236-1242 sub checkauth { Link Here
1236
                            : Koha::Cash::Registers->search(
1236
                            : Koha::Cash::Registers->search(
1237
                            { branch => $branchcode, branch_default => 1 },
1237
                            { branch => $branchcode, branch_default => 1 },
1238
                            { rows   => 1 }
1238
                            { rows   => 1 }
1239
                        )->single;
1239
                            )->single;
1240
                        $register_id   = $register->id   if ($register);
1240
                        $register_id   = $register->id   if ($register);
1241
                        $register_name = $register->name if ($register);
1241
                        $register_name = $register->name if ($register);
1242
                    }
1242
                    }
(-)a/C4/Biblio.pm (-1 / +1 lines)
Lines 1562-1568 sub GetAuthorisedValueDesc { Link Here
1562
                    Koha::AuthorisedValues->search(
1562
                    Koha::AuthorisedValues->search(
1563
                    { category => $category },
1563
                    { category => $category },
1564
                    { columns  => [ 'authorised_value', 'lib_opac', 'lib' ] }
1564
                    { columns  => [ 'authorised_value', 'lib_opac', 'lib' ] }
1565
                )->as_list
1565
                    )->as_list
1566
            };
1566
            };
1567
            $cache->set_in_cache( $cache_key, $av_descriptions );
1567
            $cache->set_in_cache( $cache_key, $av_descriptions );
1568
        }
1568
        }
(-)a/C4/Circulation.pm (-1 / +1 lines)
Lines 3307-3313 sub CanBookBeRenewed { Link Here
3307
                        unless CanItemBeReserved(
3307
                        unless CanItemBeReserved(
3308
                        $patron_with_reserve, $other_item, undef,
3308
                        $patron_with_reserve, $other_item, undef,
3309
                        { ignore_hold_counts => 1 }
3309
                        { ignore_hold_counts => 1 }
3310
                    )->{status} eq 'OK';
3310
                        )->{status} eq 'OK';
3311
3311
3312
                    # NOTE: At checkin we call 'CheckReserves' which checks hold 'policy'
3312
                    # NOTE: At checkin we call 'CheckReserves' which checks hold 'policy'
3313
                    # CanItemBeReserved checks 'rules' and 'policies' which means
3313
                    # CanItemBeReserved checks 'rules' and 'policies' which means
(-)a/C4/InstallAuth.pm (-1 / +1 lines)
Lines 352-358 sub checkauth { Link Here
352
    # else we have a problem...
352
    # else we have a problem...
353
    # get the inputs from the incoming query
353
    # get the inputs from the incoming query
354
    my @inputs = ();
354
    my @inputs = ();
355
    foreach my $name ( param $query) {
355
    foreach my $name ( param $query ) {
356
        (next) if ( $name eq 'userid' || $name eq 'password' );
356
        (next) if ( $name eq 'userid' || $name eq 'password' );
357
        my $value = $query->param($name);
357
        my $value = $query->param($name);
358
        push @inputs, { name => $name, value => $value };
358
        push @inputs, { name => $name, value => $value };
(-)a/C4/Letters.pm (-3 / +3 lines)
Lines 214-221 sub GetLettersAvailableForALibrary { Link Here
214
    }
214
    }
215
215
216
    return [
216
    return [
217
        map      { $letters{$_} }
217
        map  { $letters{$_} }
218
            sort { $letters{$a}->{name} cmp $letters{$b}->{name} }
218
        sort { $letters{$a}->{name} cmp $letters{$b}->{name} }
219
            keys %letters
219
            keys %letters
220
    ];
220
    ];
221
221
Lines 1211-1217 sub GetQueuedMessages { Link Here
1211
    my $params = shift;
1211
    my $params = shift;
1212
1212
1213
    my $dbh       = C4::Context->dbh();
1213
    my $dbh       = C4::Context->dbh();
1214
    my $statement = << 'ENDSQL';
1214
    my $statement = <<'ENDSQL';
1215
SELECT message_id, borrowernumber, subject, content, message_transport_type, status, time_queued, updated_on, failure_code, from_address, to_address, cc_address
1215
SELECT message_id, borrowernumber, subject, content, message_transport_type, status, time_queued, updated_on, failure_code, from_address, to_address, cc_address
1216
FROM message_queue
1216
FROM message_queue
1217
ENDSQL
1217
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 1525-1532 sub columns_to_str { Link Here
1525
              $subfield
1525
              $subfield
1526
            ? $subfield->{authorised_value}
1526
            ? $subfield->{authorised_value}
1527
                ? C4::Biblio::GetAuthorisedValueDesc(
1527
                ? C4::Biblio::GetAuthorisedValueDesc(
1528
                    $itemtagfield,
1528
                $itemtagfield,
1529
                    $subfield->{tagsubfield}, $value, '', $tagslib
1529
                $subfield->{tagsubfield}, $value, '', $tagslib
1530
                )
1530
                )
1531
                : $value
1531
                : $value
1532
            : $value;
1532
            : $value;
Lines 1750-1756 sub _set_found_trigger { Link Here
1750
                            if ($lost_fee_payment) {
1750
                            if ($lost_fee_payment) {
1751
                                my $today = dt_from_string();
1751
                                my $today = dt_from_string();
1752
                                my $payment_age_in_days =
1752
                                my $payment_age_in_days =
1753
                                    dt_from_string( $lost_fee_payment->created_on )->delta_days($today)
1753
                                    dt_from_string( $lost_fee_payment->created_on )
1754
                                    ->delta_days($today)
1754
                                    ->in_units('days');
1755
                                    ->in_units('days');
1755
                                if ( $payment_age_in_days > $no_refund_if_lost_fee_paid_age ) {
1756
                                if ( $payment_age_in_days > $no_refund_if_lost_fee_paid_age ) {
1756
                                    $self->add_message(
1757
                                    $self->add_message(
(-)a/Koha/List/Patron.pm (-2 / +5 lines)
Lines 213-220 sub DelPatronsFromList { Link Here
213
213
214
    return unless ( $list && $patron_list_patrons );
214
    return unless ( $list && $patron_list_patrons );
215
215
216
    return Koha::Database->new()->schema()->resultset('PatronListPatron')
216
    return Koha::Database->new()
217
        ->search( { patron_list_patron_id => { 'IN' => $patron_list_patrons } } )->delete();
217
        ->schema()
218
        ->resultset('PatronListPatron')
219
        ->search( { patron_list_patron_id => { 'IN' => $patron_list_patrons } } )
220
        ->delete();
218
}
221
}
219
222
220
=head1 AUTHOR
223
=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 1088-1094 sub set_password { Link Here
1088
                    module      => 'members',
1088
                    module      => 'members',
1089
                    letter_code => 'PASSWORD_CHANGE',
1089
                    letter_code => 'PASSWORD_CHANGE',
1090
                    branchcode  => $self_from_storage->branchcode,
1090
                    branchcode  => $self_from_storage->branchcode,
1091
                    ,
1091
1092
                    lang   => $self_from_storage->lang || 'default',
1092
                    lang   => $self_from_storage->lang || 'default',
1093
                    tables => {
1093
                    tables => {
1094
                        'branches'  => $self_from_storage->branchcode,
1094
                        'branches'  => $self_from_storage->branchcode,
(-)a/Koha/Patrons/Import.pm (-1 / +1 lines)
Lines 518-524 LINE: while ( my $borrowerline = <$handle> ) { Link Here
518
                    my $letter = GetPreparedLetter(
518
                    my $letter = GetPreparedLetter(
519
                        module      => 'members',
519
                        module      => 'members',
520
                        letter_code => 'WELCOME',
520
                        letter_code => 'WELCOME',
521
                        branchcode  => $patron->branchcode,,
521
                        branchcode  => $patron->branchcode,
522
                        lang        => $patron->lang || 'default',
522
                        lang        => $patron->lang || 'default',
523
                        tables      => {
523
                        tables      => {
524
                            'branches'  => $patron->branchcode,
524
                            '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 368-385 my $target_map = { Link Here
368
    './skel/var/log/koha'                              => { target => 'LOG_DIR',        trimdir => -1 },
368
    './skel/var/log/koha'                              => { target => 'LOG_DIR',        trimdir => -1 },
369
    './skel/var/spool/koha'                            => { target => 'BACKUP_DIR',     trimdir => -1 },
369
    './skel/var/spool/koha'                            => { target => 'BACKUP_DIR',     trimdir => -1 },
370
    './skel/var/run/koha/zebradb'                      => { target => 'ZEBRA_RUN_DIR',  trimdir => -1 },
370
    './skel/var/run/koha/zebradb'                      => { target => 'ZEBRA_RUN_DIR',  trimdir => -1 },
371
    './skel/var/lock/koha/zebradb/authorities'         => { target => 'ZEBRA_LOCK_DIR', trimdir => 6 },
371
    './skel/var/lock/koha/zebradb/authorities'         => { target => 'ZEBRA_LOCK_DIR', trimdir =>  6 },
372
    './skel/var/lib/koha/zebradb/authorities/key'      => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
372
    './skel/var/lib/koha/zebradb/authorities/key'      => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
373
    './skel/var/lib/koha/zebradb/authorities/register' => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
373
    './skel/var/lib/koha/zebradb/authorities/register' => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
374
    './skel/var/lib/koha/zebradb/authorities/shadow'   => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
374
    './skel/var/lib/koha/zebradb/authorities/shadow'   => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
375
    './skel/var/lib/koha/zebradb/authorities/tmp'      => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
375
    './skel/var/lib/koha/zebradb/authorities/tmp'      => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
376
    './skel/var/lock/koha/zebradb/biblios'             => { target => 'ZEBRA_LOCK_DIR', trimdir => 6 },
376
    './skel/var/lock/koha/zebradb/biblios'             => { target => 'ZEBRA_LOCK_DIR', trimdir =>  6 },
377
    './skel/var/lib/koha/zebradb/biblios/key'          => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
377
    './skel/var/lib/koha/zebradb/biblios/key'          => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
378
    './skel/var/lib/koha/zebradb/biblios/register'     => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
378
    './skel/var/lib/koha/zebradb/biblios/register'     => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
379
    './skel/var/lib/koha/zebradb/biblios/shadow'       => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
379
    './skel/var/lib/koha/zebradb/biblios/shadow'       => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
380
    './skel/var/lib/koha/zebradb/biblios/tmp'          => { target => 'ZEBRA_DATA_DIR', trimdir => 6 },
380
    './skel/var/lib/koha/zebradb/biblios/tmp'          => { target => 'ZEBRA_DATA_DIR', trimdir =>  6 },
381
    './skel/var/lock/koha/zebradb/rebuild'             => { target => 'ZEBRA_LOCK_DIR', trimdir => 6 },
381
    './skel/var/lock/koha/zebradb/rebuild'             => { target => 'ZEBRA_LOCK_DIR', trimdir =>  6 },
382
    './skel/var/lib/koha/plugins'                      => { target => 'PLUGINS_DIR',    trimdir => 6 },
382
    './skel/var/lib/koha/plugins'                      => { target => 'PLUGINS_DIR',    trimdir =>  6 },
383
    './sms'                                            => 'INTRANET_CGI_DIR',
383
    './sms'                                            => 'INTRANET_CGI_DIR',
384
    './suggestion'                                     => 'INTRANET_CGI_DIR',
384
    './suggestion'                                     => 'INTRANET_CGI_DIR',
385
    './svc'                                            => 'INTRANET_CGI_DIR',
385
    './svc'                                            => 'INTRANET_CGI_DIR',
(-)a/acqui/basketheader.pl (-3 / +5 lines)
Lines 178-186 if ( $op eq 'add_form' ) { Link Here
178
178
179
                # This basket was created from an EDI order/quote
179
                # This basket was created from an EDI order/quote
180
                # Check if the vendor EDI account is configured to use purchase order numbers
180
                # Check if the vendor EDI account is configured to use purchase order numbers
181
                my $schema             = Koha::Database->new()->schema();
181
                my $schema = Koha::Database->new()->schema();
182
                my $vendor_edi_account = $schema->resultset('VendorEdiAccount')
182
                my $vendor_edi_account =
183
                    ->search( { vendor_id => scalar $input->param('basketbooksellerid') } )->first;
183
                    $schema->resultset('VendorEdiAccount')
184
                    ->search( { vendor_id => scalar $input->param('basketbooksellerid') } )
185
                    ->first;
184
186
185
                if ( $vendor_edi_account && $vendor_edi_account->po_is_basketname ) {
187
                if ( $vendor_edi_account && $vendor_edi_account->po_is_basketname ) {
186
188
(-)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 (-2 / +3 lines)
Lines 302-308 if ( ( $op eq 'cud-save' || $op eq 'cud-insert' ) && $guarantors_to_be_validated Link Here
302
                # If $patron's categorycode is about to change, check guarantor requirements against
302
                # If $patron's categorycode is about to change, check guarantor requirements against
303
                # the new category but keep the original $patron object intact
303
                # the new category but keep the original $patron object intact
304
                # (this clone()s the $patron)
304
                # (this clone()s the $patron)
305
                ( bless {%$patron}, ref $patron )->categorycode($categorycode)
305
                ( bless {%$patron}, ref $patron )
306
                    ->categorycode($categorycode)
306
                    ->can_be_guaranteed_by($guarantors_to_be_validated);
307
                    ->can_be_guaranteed_by($guarantors_to_be_validated);
307
            }
308
            }
308
        } else {
309
        } else {
Lines 517-523 if ( ( !$nok ) and $nodouble and ( $op eq 'cud-insert' or $op eq 'cud-save' ) ) Link Here
517
                    my $letter = GetPreparedLetter(
518
                    my $letter = GetPreparedLetter(
518
                        module      => 'members',
519
                        module      => 'members',
519
                        letter_code => 'WELCOME',
520
                        letter_code => 'WELCOME',
520
                        branchcode  => $patron->branchcode,,
521
                        branchcode  => $patron->branchcode,
521
                        lang        => $patron->lang || 'default',
522
                        lang        => $patron->lang || 'default',
522
                        tables      => {
523
                        tables      => {
523
                            'branches'  => $patron->branchcode,
524
                            '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 277-283 if ( $op eq 'cud-create' ) { Link Here
277
                            my $letter = GetPreparedLetter(
277
                            my $letter = GetPreparedLetter(
278
                                module      => 'members',
278
                                module      => 'members',
279
                                letter_code => 'WELCOME',
279
                                letter_code => 'WELCOME',
280
                                branchcode  => $patron->branchcode,,
280
                                branchcode  => $patron->branchcode,
281
                                lang        => $patron->lang || 'default',
281
                                lang        => $patron->lang || 'default',
282
                                tables      => {
282
                                tables      => {
283
                                    'branches'  => $patron->branchcode,
283
                                    '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 341-347 if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) Link Here
341
341
342
    if ( $patron && $multi_hold ) {
342
    if ( $patron && $multi_hold ) {
343
        my @multi_pickup_locations =
343
        my @multi_pickup_locations =
344
            Koha::Biblios->search( { biblionumber => \@biblionumbers } )->pickup_locations( { patron => $patron } )
344
            Koha::Biblios->search( { biblionumber => \@biblionumbers } )
345
            ->pickup_locations( { patron => $patron } )
345
            ->as_list;
346
            ->as_list;
346
        $template->param( multi_pickup_locations => \@multi_pickup_locations );
347
        $template->param( multi_pickup_locations => \@multi_pickup_locations );
347
    }
348
    }
(-)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/Edifact.t (-1 / +1 lines)
Lines 224-230 my $mock_line_data = { Link Here
224
            sub_location_code => 'REFERENCE',    # LSL field
224
            sub_location_code => 'REFERENCE',    # LSL field
225
            branch            => 'BRANCH2'
225
            branch            => 'BRANCH2'
226
226
227
                # sequence_code missing for this item
227
            # sequence_code missing for this item
228
        }
228
        }
229
    ]
229
    ]
230
};
230
};
(-)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 2020-2026 subtest "GetUpcomingDueIssues" => sub { Link Here
2020
    my $a_borrower                = Koha::Patrons->find($a_borrower_borrowernumber);
2020
    my $a_borrower                = Koha::Patrons->find($a_borrower_borrowernumber);
2021
2021
2022
    my $yesterday      = DateTime->today( time_zone => C4::Context->tz() )->add( days => -1 );
2022
    my $yesterday      = DateTime->today( time_zone => C4::Context->tz() )->add( days => -1 );
2023
    my $two_days_ahead = DateTime->today( time_zone => C4::Context->tz() )->add( days => 2 );
2023
    my $two_days_ahead = DateTime->today( time_zone => C4::Context->tz() )->add( days =>  2 );
2024
    my $today          = DateTime->today( time_zone => C4::Context->tz() );
2024
    my $today          = DateTime->today( time_zone => C4::Context->tz() );
2025
2025
2026
    my $issue    = AddIssue( $a_borrower, $item_1->barcode, $yesterday );
2026
    my $issue    = AddIssue( $a_borrower, $item_1->barcode, $yesterday );
Lines 3932-3938 subtest 'AddReturn | is_overdue' => sub { Link Here
3932
        is( $line->status,                'RETURNED', "Overdue fine is fixed" );
3932
        is( $line->status,                'RETURNED', "Overdue fine is fixed" );
3933
        $line = $lines->next;
3933
        $line = $lines->next;
3934
        is( $line->amount + 0,            -2, "Original payment amount remains as 2" );
3934
        is( $line->amount + 0,            -2, "Original payment amount remains as 2" );
3935
        is( $line->amountoutstanding + 0, 0,  "Original payment remains applied" );
3935
        is( $line->amountoutstanding + 0,  0, "Original payment remains applied" );
3936
        $line = $lines->next;
3936
        $line = $lines->next;
3937
        is( $line->amount + 0,            -1, "Refund amount correctly set to 1" );
3937
        is( $line->amount + 0,            -1, "Refund amount correctly set to 1" );
3938
        is( $line->amountoutstanding + 0, -1, "Refund amount outstanding unspent" );
3938
        is( $line->amountoutstanding + 0, -1, "Refund amount outstanding unspent" );
Lines 4886-4892 subtest '_FixOverduesOnReturn' => sub { Link Here
4886
    my $credit = $offset->credit;
4886
    my $credit = $offset->credit;
4887
    is( ref $credit,                    "Koha::Account::Line", "Found matching credit for fine forgiveness" );
4887
    is( ref $credit,                    "Koha::Account::Line", "Found matching credit for fine forgiveness" );
4888
    is( $credit->amount + 0,            -99,                   "Credit amount is set correctly" );
4888
    is( $credit->amount + 0,            -99,                   "Credit amount is set correctly" );
4889
    is( $credit->amountoutstanding + 0, 0,                     "Credit amountoutstanding is correctly set to 0" );
4889
    is( $credit->amountoutstanding + 0,  0,                    "Credit amountoutstanding is correctly set to 0" );
4890
4890
4891
    # Bug 25417 - Only forgive fines where there is an amount outstanding to forgive
4891
    # Bug 25417 - Only forgive fines where there is an amount outstanding to forgive
4892
    $accountline->set(
4892
    $accountline->set(
Lines 7637-7643 subtest 'NoRefundOnLostFinesPaidAge' => sub { Link Here
7637
        {
7637
        {
7638
            borrowernumber    => $patron->id,
7638
            borrowernumber    => $patron->id,
7639
            date              => '1970-01-01 14:00:01',
7639
            date              => '1970-01-01 14:00:01',
7640
            amountoutstanding => 0,
7640
            amountoutstanding =>  0,
7641
            amount            => -5,
7641
            amount            => -5,
7642
            interface         => 'commandline',
7642
            interface         => 'commandline',
7643
            credit_type_code  => 'PAYMENT'
7643
            credit_type_code  => 'PAYMENT'
Lines 7693-7699 subtest 'NoRefundOnLostFinesPaidAge' => sub { Link Here
7693
            borrowernumber    => $patron2->id,
7693
            borrowernumber    => $patron2->id,
7694
            date              => '1970-01-01 14:00:01',
7694
            date              => '1970-01-01 14:00:01',
7695
            amount            => -5,
7695
            amount            => -5,
7696
            amountoutstanding => 0,
7696
            amountoutstanding =>  0,
7697
            interface         => 'commandline',
7697
            interface         => 'commandline',
7698
            credit_type_code  => 'PAYMENT'
7698
            credit_type_code  => 'PAYMENT'
7699
        }
7699
        }
(-)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 (-4 / +8 lines)
Lines 358-364 subtest "delete() tests" => sub { Link Here
358
358
359
    my $number_of_logs =
359
    my $number_of_logs =
360
        $schema->resultset('ActionLog')
360
        $schema->resultset('ActionLog')
361
        ->search( { module => 'HOLDS', action => 'DELETE', object => $hold->{reserve_id} } )->count;
361
        ->search( { module => 'HOLDS', action => 'DELETE', object => $hold->{reserve_id} } )
362
        ->count;
362
    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' );
363
364
364
    # Enable logging
365
    # Enable logging
Lines 379-385 subtest "delete() tests" => sub { Link Here
379
380
380
    $number_of_logs =
381
    $number_of_logs =
381
        $schema->resultset('ActionLog')
382
        $schema->resultset('ActionLog')
382
        ->search( { module => 'HOLDS', action => 'DELETE', object => $hold->{reserve_id} } )->count;
383
        ->search( { module => 'HOLDS', action => 'DELETE', object => $hold->{reserve_id} } )
384
        ->count;
383
    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' );
384
386
385
    $schema->storage->txn_rollback();
387
    $schema->storage->txn_rollback();
Lines 471-477 subtest 'suspend() tests' => sub { Link Here
471
    t::lib::Mocks::mock_preference( 'HoldsLog', 1 );
473
    t::lib::Mocks::mock_preference( 'HoldsLog', 1 );
472
474
473
    my $logs_count =
475
    my $logs_count =
474
        $schema->resultset('ActionLog')->search( { module => 'HOLDS', action => 'SUSPEND', object => $hold->id } )
476
        $schema->resultset('ActionLog')
477
        ->search( { module => 'HOLDS', action => 'SUSPEND', object => $hold->id } )
475
        ->count;
478
        ->count;
476
479
477
    $hold = $builder->build_object(
480
    $hold = $builder->build_object(
Lines 483-489 subtest 'suspend() tests' => sub { Link Here
483
486
484
    $hold->suspend_hold;
487
    $hold->suspend_hold;
485
    my $new_logs_count =
488
    my $new_logs_count =
486
        $schema->resultset('ActionLog')->search( { module => 'HOLDS', action => 'SUSPEND', object => $hold->id } )
489
        $schema->resultset('ActionLog')
490
        ->search( { module => 'HOLDS', action => 'SUSPEND', object => $hold->id } )
487
        ->count;
491
        ->count;
488
492
489
    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/ILL/Requests.t (-1 / +1 lines)
Lines 1011-1017 subtest 'Backend core methods' => sub { Link Here
1011
    );
1011
    );
1012
1012
1013
    Koha::AdditionalContents->search->delete;
1013
    Koha::AdditionalContents->search->delete;
1014
    my $tomorrow  = dt_from_string->add( days => 1 );
1014
    my $tomorrow  = dt_from_string->add( days =>  1 );
1015
    my $yesterday = dt_from_string->add( days => -1 );
1015
    my $yesterday = dt_from_string->add( days => -1 );
1016
1016
1017
    my $library_additional_contents = $builder->build_object(
1017
    my $library_additional_contents = $builder->build_object(
(-)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 1254-1260 subtest "filter_by_last_update" => sub { Link Here
1254
                class => 'Koha::Patrons',
1254
                class => 'Koha::Patrons',
1255
                value => { updated_on => $now->clone->subtract( days => $i ) }
1255
                value => { updated_on => $now->clone->subtract( days => $i ) }
1256
            }
1256
            }
1257
        )->borrowernumber;
1257
            )->borrowernumber;
1258
    }
1258
    }
1259
1259
1260
    my $patrons = Koha::Patrons->search( { borrowernumber => { -in => \@borrowernumbers } } );
1260
    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_baskets.t (-3 / +8 lines)
Lines 133-139 subtest 'add() tests' => sub { Link Here
133
133
134
    $t->post_ok( $url, json => {} )->status_is(400);
134
    $t->post_ok( $url, json => {} )->status_is(400);
135
135
136
    $t->post_ok( $url, json => { vendor_id => $vendor->id } )->status_is(201)->json_has('/basket_id')
136
    $t->post_ok( $url, json => { vendor_id => $vendor->id } )
137
        ->status_is(201)
138
        ->json_has('/basket_id')
137
        ->json_is( '/vendor_id', $vendor->id );
139
        ->json_is( '/vendor_id', $vendor->id );
138
140
139
    my $basket = {
141
    my $basket = {
Lines 141-148 subtest 'add() tests' => sub { Link Here
141
        name        => 'Basket #1',
143
        name        => 'Basket #1',
142
        vendor_note => 'Vendor note',
144
        vendor_note => 'Vendor note',
143
    };
145
    };
144
    $t->post_ok( $url, json => $basket )->status_is(201)->json_has('/basket_id')
146
    $t->post_ok( $url, json => $basket )
145
        ->json_is( '/vendor_id',   $basket->{vendor_id} )->json_is( '/name', $basket->{name} )
147
        ->status_is(201)
148
        ->json_has('/basket_id')
149
        ->json_is( '/vendor_id',   $basket->{vendor_id} )
150
        ->json_is( '/name',        $basket->{name} )
146
        ->json_is( '/vendor_note', $basket->{vendor_note} );
151
        ->json_is( '/vendor_note', $basket->{vendor_note} );
147
152
148
    $schema->storage->txn_rollback;
153
    $schema->storage->txn_rollback;
(-)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 456-462 subtest 'get_public() tests' => sub { Link Here
456
    $biblio->delete;
471
    $biblio->delete;
457
    $t->get_ok(
472
    $t->get_ok(
458
        "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'application/marc' } )
473
        "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber => { Accept => 'application/marc' } )
459
        ->status_is(404)->json_is( '/error', 'Bibliographic record not found' );
474
        ->status_is(404)
475
        ->json_is( '/error', 'Bibliographic record not found' );
460
476
461
    $schema->storage->txn_rollback;
477
    $schema->storage->txn_rollback;
462
};
478
};
Lines 581-587 subtest 'pickup_locations() tests' => sub { Link Here
581
                . "patron_id="
597
                . "patron_id="
582
                . $patron->id
598
                . $patron->id
583
                . "&_order_by=marc_org_code"
599
                . "&_order_by=marc_org_code"
584
                . "&_per_page=1" )->json_is( [$library_1_api] )
600
                . "&_per_page=1" )
601
            ->json_is( [$library_1_api] )
585
            ->header_is( 'X-Total-Count',      '4', '4 is the count for libraries with pickup_location=1' )
602
            ->header_is( 'X-Total-Count',      '4', '4 is the count for libraries with pickup_location=1' )
586
            ->header_is( 'X-Base-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
603
            ->header_is( 'X-Base-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
587
            ->header_unlike( 'Link', qr|rel="prev"| )
604
            ->header_unlike( 'Link', qr|rel="prev"| )
Lines 612-619 subtest 'pickup_locations() tests' => sub { Link Here
612
                . "patron_id="
629
                . "patron_id="
613
                . $patron->id
630
                . $patron->id
614
                . "&_order_by=marc_org_code"
631
                . "&_order_by=marc_org_code"
615
                . "&_per_page=1" )->json_is( [$library_1_api] )->header_is( 'X-Total-Count', '2' )
632
                . "&_per_page=1" )
616
            ->header_is( 'X-Base-Total-Count', '2' )->header_unlike( 'Link', qr|rel="prev"| )
633
            ->json_is( [$library_1_api] )
634
            ->header_is( 'X-Total-Count',      '2' )
635
            ->header_is( 'X-Base-Total-Count', '2' )
636
            ->header_unlike( 'Link', qr|rel="prev"| )
617
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1.*)>\; rel="next"# )
637
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1.*)>\; rel="next"# )
618
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=1.*|_page=1.*\&_per_page=1).*>\; rel="first"# )
638
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=1.*|_page=1.*\&_per_page=1).*>\; rel="first"# )
619
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1).*>\; rel="last"# );
639
            ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1).*>\; rel="last"# );
Lines 633-639 subtest 'pickup_locations() tests' => sub { Link Here
633
653
634
    $t->get_ok(
654
    $t->get_ok(
635
        "//$userid:$password@/api/v1/biblios/" . $biblio->id . "/pickup_locations?" . "patron_id=" . $patron->id )
655
        "//$userid:$password@/api/v1/biblios/" . $biblio->id . "/pickup_locations?" . "patron_id=" . $patron->id )
636
        ->status_is(404)->json_is( '/error' => 'Bibliographic record not found' );
656
        ->status_is(404)
657
        ->json_is( '/error' => 'Bibliographic record not found' );
637
658
638
    $schema->storage->txn_rollback;
659
    $schema->storage->txn_rollback;
639
};
660
};
Lines 672-684 subtest 'get_items_public() tests' => sub { Link Here
672
693
673
    my $biblio = $builder->build_sample_biblio();
694
    my $biblio = $builder->build_sample_biblio();
674
695
675
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->id . "/items" )->status_is(200)
696
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->id . "/items" )
697
        ->status_is(200)
676
        ->json_is( '' => [], 'No items on the biblio' );
698
        ->json_is( '' => [], 'No items on the biblio' );
677
699
678
    my $item_1 = $builder->build_sample_item( { biblionumber => $biblio->id } );
700
    my $item_1 = $builder->build_sample_item( { biblionumber => $biblio->id } );
679
    my $item_2 = $builder->build_sample_item( { biblionumber => $biblio->id, withdrawn => 1 } );
701
    my $item_2 = $builder->build_sample_item( { biblionumber => $biblio->id, withdrawn => 1 } );
680
702
681
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/items" )->status_is(200)
703
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/items" )
704
        ->status_is(200)
682
        ->json_is(
705
        ->json_is(
683
        '' => [
706
        '' => [
684
            $item_1->to_api( { public => 1 } ),
707
            $item_1->to_api( { public => 1 } ),
Lines 689-695 subtest 'get_items_public() tests' => sub { Link Here
689
712
690
    $rules = { withdrawn => ['1'] };
713
    $rules = { withdrawn => ['1'] };
691
714
692
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/items" )->status_is(200)
715
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/items" )
716
        ->status_is(200)
693
        ->json_is(
717
        ->json_is(
694
        '' => [ $item_1->to_api( { public => 1 } ) ],
718
        '' => [ $item_1->to_api( { public => 1 } ) ],
695
        'The items are returned, hidden one is not returned'
719
        'The items are returned, hidden one is not returned'
Lines 702-708 subtest 'get_items_public() tests' => sub { Link Here
702
726
703
    $override_hidden_items = 1;
727
    $override_hidden_items = 1;
704
728
705
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/items" )->status_is(200)
729
    $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/items" )
730
        ->status_is(200)
706
        ->json_is(
731
        ->json_is(
707
        '' => [
732
        '' => [
708
            $item_1->to_api( { public => 1 } ),
733
            $item_1->to_api( { public => 1 } ),
Lines 755-761 subtest 'get_bookings() tests' => sub { Link Here
755
780
756
    $t->get_ok( "//$unauth_userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )->status_is(403);
781
    $t->get_ok( "//$unauth_userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )->status_is(403);
757
782
758
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )->status_is(200)
783
    $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )
784
        ->status_is(200)
759
        ->json_is( '' => [], 'No bookings on the biblio' );
785
        ->json_is( '' => [], 'No bookings on the biblio' );
760
786
761
    # One booking
787
    # One booking
Lines 773-779 subtest 'get_bookings() tests' => sub { Link Here
773
        }
799
        }
774
    );
800
    );
775
801
776
    my $ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )->status_is(200)
802
    my $ret =
803
        $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )
804
        ->status_is(200)
777
        ->tx->res->json;
805
        ->tx->res->json;
778
806
779
    is_deeply( $ret, [ $booking_0->to_api ] );
807
    is_deeply( $ret, [ $booking_0->to_api ] );
Lines 846-852 subtest 'get_checkouts() tests' => sub { Link Here
846
    AddIssue( $patron, $item_2->barcode );
874
    AddIssue( $patron, $item_2->barcode );
847
875
848
    my $ret =
876
    my $ret =
849
        $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts" )->status_is(200)
877
        $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts" )
878
        ->status_is(200)
850
        ->tx->res->json;
879
        ->tx->res->json;
851
880
852
    my $checkout_1 = Koha::Checkouts->find( { itemnumber => $item_1->id } );
881
    my $checkout_1 = Koha::Checkouts->find( { itemnumber => $item_1->id } );
Lines 856-868 subtest 'get_checkouts() tests' => sub { Link Here
856
885
857
    AddReturn( $item_1->barcode );
886
    AddReturn( $item_1->barcode );
858
887
859
    $ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts" )->status_is(200)
888
    $ret =
889
        $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts" )
890
        ->status_is(200)
860
        ->tx->res->json;
891
        ->tx->res->json;
861
892
862
    is_deeply( $ret, [ $checkout_2->to_api ] );
893
    is_deeply( $ret, [ $checkout_2->to_api ] );
863
894
864
    $ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts?checked_in=1" )
895
    $ret =
865
        ->status_is(200)->tx->res->json;
896
        $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts?checked_in=1" )
897
        ->status_is(200)
898
        ->tx->res->json;
866
899
867
    my $old_checkout_1 = Koha::Old::Checkouts->find( $checkout_1->id );
900
    my $old_checkout_1 = Koha::Old::Checkouts->find( $checkout_1->id );
868
901
Lines 894-905 subtest 'set_rating() tests' => sub { Link Here
894
927
895
    $t->post_ok(
928
    $t->post_ok(
896
        "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/ratings" => json => { rating => 3 } )
929
        "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/ratings" => json => { rating => 3 } )
897
        ->status_is(200)->json_is( '/rating', '3' )->json_is( '/average', '3' )->json_is( '/count', '1' );
930
        ->status_is(200)
931
        ->json_is( '/rating',  '3' )
932
        ->json_is( '/average', '3' )
933
        ->json_is( '/count',   '1' );
898
934
899
    $t->post_ok( "//$userid:$password@/api/v1/public/biblios/"
935
    $t->post_ok( "//$userid:$password@/api/v1/public/biblios/"
900
            . $biblio->biblionumber
936
            . $biblio->biblionumber
901
            . "/ratings" => json => { rating => undef } )->status_is(200)->json_is( '/rating', undef )
937
            . "/ratings" => json => { rating => undef } )
902
        ->json_is( '/average', '0' )->json_is( '/count', '0' );
938
        ->status_is(200)
939
        ->json_is( '/rating',  undef )
940
        ->json_is( '/average', '0' )
941
        ->json_is( '/count',   '0' );
903
942
904
    $schema->storage->txn_rollback;
943
    $schema->storage->txn_rollback;
905
944
Lines 1325-1331 subtest 'add() tests' => sub { Link Here
1325
1364
1326
    $t->post_ok( "//$userid:$password@/api/v1/biblios" =>
1365
    $t->post_ok( "//$userid:$password@/api/v1/biblios" =>
1327
            { 'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode } => $marcxml )
1366
            { 'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode } => $marcxml )
1328
        ->status_is(200)->json_has('/id')
1367
        ->status_is(200)
1368
        ->json_has('/id')
1329
        ->header_is( 'Location' => "/api/v1/biblios/" . $t->tx->res->json->{id}, "REST3.4.1" );
1369
        ->header_is( 'Location' => "/api/v1/biblios/" . $t->tx->res->json->{id}, "REST3.4.1" );
1330
1370
1331
    $t->post_ok(
1371
    $t->post_ok(
Lines 1336-1342 subtest 'add() tests' => sub { Link Here
1336
    )->status_is(200)->json_has('/id');
1376
    )->status_is(200)->json_has('/id');
1337
1377
1338
    $t->post_ok( "//$userid:$password@/api/v1/biblios" =>
1378
    $t->post_ok( "//$userid:$password@/api/v1/biblios" =>
1339
            { 'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode } => $marc )->status_is(200)
1379
            { 'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode } => $marc )
1380
        ->status_is(200)
1340
        ->json_has('/id');
1381
        ->json_has('/id');
1341
1382
1342
    subtest 'x-record-source-id header tests' => sub {
1383
    subtest 'x-record-source-id header tests' => sub {
Lines 1380-1386 subtest 'add() tests' => sub { Link Here
1380
    $mock_biblio->mock( 'AddBiblio', sub { return ( undef, undef ); } );
1421
    $mock_biblio->mock( 'AddBiblio', sub { return ( undef, undef ); } );
1381
1422
1382
    $t->post_ok( "//$userid:$password@/api/v1/biblios" =>
1423
    $t->post_ok( "//$userid:$password@/api/v1/biblios" =>
1383
            { 'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode } => $marc )->status_is(400)
1424
            { 'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode } => $marc )
1425
        ->status_is(400)
1384
        ->json_is(
1426
        ->json_is(
1385
        {
1427
        {
1386
            error      => 'Error creating record',
1428
            error      => 'Error creating record',
Lines 1808-1814 subtest 'put() tests' => sub { Link Here
1808
1850
1809
    $t->put_ok( "//$userid:$password@/api/v1/biblios/$biblionumber" =>
1851
    $t->put_ok( "//$userid:$password@/api/v1/biblios/$biblionumber" =>
1810
            { 'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode } => $marcxml )
1852
            { 'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode } => $marcxml )
1811
        ->status_is(200)->json_has('/id');
1853
        ->status_is(200)
1854
        ->json_has('/id');
1812
1855
1813
    $biblio = Koha::Biblios->find($biblionumber);
1856
    $biblio = Koha::Biblios->find($biblionumber);
1814
1857
Lines 1816-1829 subtest 'put() tests' => sub { Link Here
1816
1859
1817
    $t->put_ok( "//$userid:$password@/api/v1/biblios/$biblionumber" =>
1860
    $t->put_ok( "//$userid:$password@/api/v1/biblios/$biblionumber" =>
1818
            { 'Content-Type' => 'application/marc-in-json', 'x-framework-id' => $frameworkcode } => $mij )
1861
            { 'Content-Type' => 'application/marc-in-json', 'x-framework-id' => $frameworkcode } => $mij )
1819
        ->status_is(200)->json_has('/id');
1862
        ->status_is(200)
1863
        ->json_has('/id');
1820
1864
1821
    $biblio = Koha::Biblios->find($biblionumber);
1865
    $biblio = Koha::Biblios->find($biblionumber);
1822
1866
1823
    is( $biblio->title, 'Introduction to Attic Greek  (Using mij) /' );
1867
    is( $biblio->title, 'Introduction to Attic Greek  (Using mij) /' );
1824
1868
1825
    $t->put_ok( "//$userid:$password@/api/v1/biblios/$biblionumber" =>
1869
    $t->put_ok( "//$userid:$password@/api/v1/biblios/$biblionumber" =>
1826
            { 'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode } => $marc )->status_is(200)
1870
            { 'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode } => $marc )
1871
        ->status_is(200)
1827
        ->json_has('/id');
1872
        ->json_has('/id');
1828
1873
1829
    $biblio = Koha::Biblios->find($biblionumber);
1874
    $biblio = Koha::Biblios->find($biblionumber);
Lines 1880-1887 subtest 'list() tests' => sub { Link Here
1880
1925
1881
    $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/json' } )->status_is(200);
1926
    $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/json' } )->status_is(200);
1882
1927
1883
    my $result = $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/marcxml+xml' } )
1928
    my $result =
1884
        ->status_is(200)->tx->res->body;
1929
        $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/marcxml+xml' } )
1930
        ->status_is(200)
1931
        ->tx->res->body;
1885
1932
1886
    my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
1933
    my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
1887
    like( $result, qr/\Q$encoded_title/, "The title is not double encoded" );
1934
    like( $result, qr/\Q$encoded_title/, "The title is not double encoded" );
Lines 1909-1915 subtest 'list() tests' => sub { Link Here
1909
1956
1910
    $query = encode_json( { biblio_id => $biblio->id } );
1957
    $query = encode_json( { biblio_id => $biblio->id } );
1911
1958
1912
    $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/json' } )->status_is(200)
1959
    $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/json' } )
1960
        ->status_is(200)
1913
        ->json_is( '/0/timestamp' =>
1961
        ->json_is( '/0/timestamp' =>
1914
            output_pref( { dt => $fixed_date, dateformat => 'rfc3339' }, 'biblio table timestamp takes precedence' ) );
1962
            output_pref( { dt => $fixed_date, dateformat => 'rfc3339' }, 'biblio table timestamp takes precedence' ) );
1915
1963
Lines 2273-2279 subtest 'merge() tests' => sub { Link Here
2273
    my $result =
2321
    my $result =
2274
        $t->post_ok( "//$userid:$password@/api/v1/biblios/$biblio_id1/merge" =>
2322
        $t->post_ok( "//$userid:$password@/api/v1/biblios/$biblio_id1/merge" =>
2275
            { 'Content-Type' => 'application/json', 'Accept' => 'application/marc-in-json' } => $json_input1 )
2323
            { 'Content-Type' => 'application/json', 'Accept' => 'application/marc-in-json' } => $json_input1 )
2276
        ->status_is(200)->tx->res->body;
2324
        ->status_is(200)
2325
        ->tx->res->body;
2277
    like( $result, qr/$title_1/, "Merged record has the correct title" );
2326
    like( $result, qr/$title_1/, "Merged record has the correct title" );
2278
    unlike( $result, qr/$title_2/, "Merged record doesn't have the wrong title" );
2327
    unlike( $result, qr/$title_2/, "Merged record doesn't have the wrong title" );
2279
2328
Lines 2285-2291 subtest 'merge() tests' => sub { Link Here
2285
    $result =
2334
    $result =
2286
        $t->post_ok( "//$userid:$password@/api/v1/biblios/$biblio_id1/merge" =>
2335
        $t->post_ok( "//$userid:$password@/api/v1/biblios/$biblio_id1/merge" =>
2287
            { 'Content-Type' => 'application/json', 'Accept' => 'application/marc-in-json' } => $json_input2 )
2336
            { 'Content-Type' => 'application/json', 'Accept' => 'application/marc-in-json' } => $json_input2 )
2288
        ->status_is(200)->tx->res->body;
2337
        ->status_is(200)
2338
        ->tx->res->body;
2289
    like( $result, qr/Using mij/, "Update with Marc-in-json record" );
2339
    like( $result, qr/Using mij/, "Update with Marc-in-json record" );
2290
    unlike( $result, qr/$title_1/, "Change all record with dat in the 'datarecord' field" );
2340
    unlike( $result, qr/$title_1/, "Change all record with dat in the 'datarecord' field" );
2291
2341
(-)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 (-19 / +39 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
Lines 510-516 subtest 'extended_attributes() tests' => sub { Link Here
510
    # Test with list endpoint
529
    # Test with list endpoint
511
    $response =
530
    $response =
512
        $t->get_ok( "//$userid:$password@/api/v1/erm/agreements" => { 'x-koha-embed' => 'extended_attributes' } )
531
        $t->get_ok( "//$userid:$password@/api/v1/erm/agreements" => { 'x-koha-embed' => 'extended_attributes' } )
513
        ->status_is(200)->tx->res->json;
532
        ->status_is(200)
533
        ->tx->res->json;
514
534
515
    # Verify record_table is still not present in list endpoint
535
    # Verify record_table is still not present in list endpoint
516
    my $found = 0;
536
    my $found = 0;
(-)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( "/errors" =>
222
        ->json_is( "/errors" =>
217
            [ { message => "Not in enum list: license, agreement, package, title.", path => "/resource_type" } ] );
223
            [ { message => "Not in enum list: license, agreement, package, title.", 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/file_transports.t (-10 / +20 lines)
Lines 78-84 subtest 'list() tests' => sub { Link Here
78
    );
78
    );
79
79
80
    # One file transport created, should get returned
80
    # One file transport created, should get returned
81
    $t->get_ok("//$userid:$password@/api/v1/config/file_transports")->status_is(200)
81
    $t->get_ok("//$userid:$password@/api/v1/config/file_transports")
82
        ->status_is(200)
82
        ->json_is( [ $file_transport->to_api ] );
83
        ->json_is( [ $file_transport->to_api ] );
83
84
84
    my $another_file_transport = $builder->build_object(
85
    my $another_file_transport = $builder->build_object(
Lines 94-100 subtest 'list() tests' => sub { Link Here
94
    );
95
    );
95
96
96
    # Two File transports created, they should both be returned
97
    # Two File transports created, they should both be returned
97
    $t->get_ok("//$userid:$password@/api/v1/config/file_transports")->status_is(200)
98
    $t->get_ok("//$userid:$password@/api/v1/config/file_transports")
99
        ->status_is(200)
98
        ->json_is( [ $file_transport->to_api, $another_file_transport->to_api, ] );
100
        ->json_is( [ $file_transport->to_api, $another_file_transport->to_api, ] );
99
101
100
    # Unauthorized access
102
    # Unauthorized access
Lines 140-146 subtest 'get() tests' => sub { Link Here
140
    $patron->set_password( { password => $password, skip_validation => 1 } );
142
    $patron->set_password( { password => $password, skip_validation => 1 } );
141
    my $unauth_userid = $patron->userid;
143
    my $unauth_userid = $patron->userid;
142
144
143
    $t->get_ok( "//$userid:$password@/api/v1/config/file_transports/" . $file_transport->id )->status_is(200)
145
    $t->get_ok( "//$userid:$password@/api/v1/config/file_transports/" . $file_transport->id )
146
        ->status_is(200)
144
        ->json_is( $file_transport->to_api );
147
        ->json_is( $file_transport->to_api );
145
148
146
    $t->get_ok( "//$unauth_userid:$password@/api/v1/config/file_transports/" . $file_transport->id )->status_is(403);
149
    $t->get_ok( "//$unauth_userid:$password@/api/v1/config/file_transports/" . $file_transport->id )->status_is(403);
Lines 159-165 subtest 'get() tests' => sub { Link Here
159
    my $non_existent_id = $file_transport_to_delete->id;
162
    my $non_existent_id = $file_transport_to_delete->id;
160
    $file_transport_to_delete->delete;
163
    $file_transport_to_delete->delete;
161
164
162
    $t->get_ok("//$userid:$password@/api/v1/config/file_transports/$non_existent_id")->status_is(404)
165
    $t->get_ok("//$userid:$password@/api/v1/config/file_transports/$non_existent_id")
166
        ->status_is(404)
163
        ->json_is( '/error' => 'File transport not found' );
167
        ->json_is( '/error' => 'File transport not found' );
164
168
165
    $schema->storage->txn_rollback;
169
    $schema->storage->txn_rollback;
Lines 219-225 subtest 'add() tests' => sub { Link Here
219
    };
223
    };
220
224
221
    $t->post_ok( "//$userid:$password@/api/v1/config/file_transports" => json => $file_transport_with_invalid_field )
225
    $t->post_ok( "//$userid:$password@/api/v1/config/file_transports" => json => $file_transport_with_invalid_field )
222
        ->status_is(400)->json_is(
226
        ->status_is(400)
227
        ->json_is(
223
        "/errors" => [
228
        "/errors" => [
224
            {
229
            {
225
                message => "Properties not allowed: blah.",
230
                message => "Properties not allowed: blah.",
Lines 233-248 subtest 'add() tests' => sub { Link Here
233
        $t->post_ok( "//$userid:$password@/api/v1/config/file_transports" => json => $file_transport_data )
238
        $t->post_ok( "//$userid:$password@/api/v1/config/file_transports" => json => $file_transport_data )
234
        ->status_is( 201, 'SWAGGER3.2.1' )
239
        ->status_is( 201, 'SWAGGER3.2.1' )
235
        ->header_like( Location => qr|^\/api\/v1\/config\/file_transports\/\d*|, 'SWAGGER3.4.1' )
240
        ->header_like( Location => qr|^\/api\/v1\/config\/file_transports\/\d*|, 'SWAGGER3.4.1' )
236
        ->json_is( '/name' => $file_transport_data->{name} )->tx->res->json->{file_transport_id};
241
        ->json_is( '/name' => $file_transport_data->{name} )
242
        ->tx->res->json->{file_transport_id};
237
243
238
    # Authorized attempt to create with null id
244
    # Authorized attempt to create with null id
239
    $file_transport_data->{file_transport_id} = undef;
245
    $file_transport_data->{file_transport_id} = undef;
240
    $t->post_ok( "//$userid:$password@/api/v1/config/file_transports" => json => $file_transport_data )->status_is(400)
246
    $t->post_ok( "//$userid:$password@/api/v1/config/file_transports" => json => $file_transport_data )
247
        ->status_is(400)
241
        ->json_has('/errors');
248
        ->json_has('/errors');
242
249
243
    # Authorized attempt to create with existing id
250
    # Authorized attempt to create with existing id
244
    $file_transport_data->{file_transport_id} = $file_transport_id;
251
    $file_transport_data->{file_transport_id} = $file_transport_id;
245
    $t->post_ok( "//$userid:$password@/api/v1/config/file_transports" => json => $file_transport_data )->status_is(400)
252
    $t->post_ok( "//$userid:$password@/api/v1/config/file_transports" => json => $file_transport_data )
253
        ->status_is(400)
246
        ->json_is(
254
        ->json_is(
247
        "/errors" => [
255
        "/errors" => [
248
            {
256
            {
Lines 304-310 subtest 'update() tests' => sub { Link Here
304
    };
312
    };
305
313
306
    $t->put_ok( "//$userid:$password@/api/v1/config/file_transports/$file_transport_id" => json =>
314
    $t->put_ok( "//$userid:$password@/api/v1/config/file_transports/$file_transport_id" => json =>
307
            $file_transport_with_missing_field )->status_is(400)
315
            $file_transport_with_missing_field )
316
        ->status_is(400)
308
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
317
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
309
318
310
    # Full object update on PUT
319
    # Full object update on PUT
Lines 400-406 subtest 'delete() tests' => sub { Link Here
400
    $t->delete_ok("//$unauth_userid:$password@/api/v1/config/file_transports/$file_transport_id")->status_is(403);
409
    $t->delete_ok("//$unauth_userid:$password@/api/v1/config/file_transports/$file_transport_id")->status_is(403);
401
410
402
    $t->delete_ok("//$userid:$password@/api/v1/config/file_transports/$file_transport_id")
411
    $t->delete_ok("//$userid:$password@/api/v1/config/file_transports/$file_transport_id")
403
        ->status_is( 204, 'SWAGGER3.2.4' )->content_is( '', 'SWAGGER3.3.4' );
412
        ->status_is( 204, 'SWAGGER3.2.4' )
413
        ->content_is( '', 'SWAGGER3.3.4' );
404
414
405
    $t->delete_ok("//$userid:$password@/api/v1/config/file_transports/$file_transport_id")->status_is(404);
415
    $t->delete_ok("//$userid:$password@/api/v1/config/file_transports/$file_transport_id")->status_is(404);
406
416
(-)a/t/db_dependent/api/v1/holds.t (-55 / +110 lines)
Lines 209-234 subtest "Test endpoints with permission" => sub { Link Here
209
209
210
    $t->get_ok("//$userid_1:$password@/api/v1/holds")->status_is(200)->json_has('/0')->json_has('/1')->json_hasnt('/2');
210
    $t->get_ok("//$userid_1:$password@/api/v1/holds")->status_is(200)->json_has('/0')->json_has('/1')->json_hasnt('/2');
211
211
212
    $t->get_ok("//$userid_1:$password@/api/v1/holds?priority=2")->status_is(200)
212
    $t->get_ok("//$userid_1:$password@/api/v1/holds?priority=2")
213
        ->json_is( '/0/patron_id', $patron_2->borrowernumber )->json_hasnt('/1');
213
        ->status_is(200)
214
        ->json_is( '/0/patron_id', $patron_2->borrowernumber )
215
        ->json_hasnt('/1');
214
216
215
    $t->delete_ok("//$userid_3:$password@/api/v1/holds/$reserve_id")->status_is( 204, 'REST3.2.4' )
217
    $t->delete_ok("//$userid_3:$password@/api/v1/holds/$reserve_id")
218
        ->status_is( 204, 'REST3.2.4' )
216
        ->content_is( '', 'REST3.3.4' );
219
        ->content_is( '', 'REST3.3.4' );
217
220
218
    $t->patch_ok( "//$userid_3:$password@/api/v1/holds/$reserve_id" => json => $patch_data )->status_is(404)
221
    $t->patch_ok( "//$userid_3:$password@/api/v1/holds/$reserve_id" => json => $patch_data )
222
        ->status_is(404)
219
        ->json_has('/error');
223
        ->json_has('/error');
220
224
221
    $t->delete_ok("//$userid_3:$password@/api/v1/holds/$reserve_id")->status_is(404)->json_has('/error');
225
    $t->delete_ok("//$userid_3:$password@/api/v1/holds/$reserve_id")->status_is(404)->json_has('/error');
222
226
223
    $t->get_ok( "//$userid_3:$password@/api/v1/holds?patron_id=" . $patron_1->borrowernumber )->status_is(200)
227
    $t->get_ok( "//$userid_3:$password@/api/v1/holds?patron_id=" . $patron_1->borrowernumber )
228
        ->status_is(200)
224
        ->json_is( [] );
229
        ->json_is( [] );
225
230
226
    my $inexisting_borrowernumber = $patron_2->borrowernumber * 2;
231
    my $inexisting_borrowernumber = $patron_2->borrowernumber * 2;
227
    $t->get_ok("//$userid_1:$password@/api/v1/holds?patron_id=$inexisting_borrowernumber")->status_is(200)
232
    $t->get_ok("//$userid_1:$password@/api/v1/holds?patron_id=$inexisting_borrowernumber")
233
        ->status_is(200)
228
        ->json_is( [] );
234
        ->json_is( [] );
229
235
230
    $t->delete_ok( "//$userid_3:$password@/api/v1/holds/$reserve_id2" => json => "Cancellation reason" )
236
    $t->delete_ok( "//$userid_3:$password@/api/v1/holds/$reserve_id2" => json => "Cancellation reason" )
231
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
237
        ->status_is( 204, 'REST3.2.4' )
238
        ->content_is( '', 'REST3.3.4' );
232
239
233
    # Make sure pickup location checks doesn't get in the middle
240
    # Make sure pickup location checks doesn't get in the middle
234
    my $mock_biblio = Test::MockModule->new('Koha::Biblio');
241
    my $mock_biblio = Test::MockModule->new('Koha::Biblio');
Lines 236-259 subtest "Test endpoints with permission" => sub { Link Here
236
    my $mock_item = Test::MockModule->new('Koha::Item');
243
    my $mock_item = Test::MockModule->new('Koha::Item');
237
    $mock_item->mock( 'pickup_locations', sub { return Koha::Libraries->search } );
244
    $mock_item->mock( 'pickup_locations', sub { return Koha::Libraries->search } );
238
245
239
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )->status_is(201)->json_has('/hold_id')
246
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )
247
        ->status_is(201)
248
        ->json_has('/hold_id')
240
        ->header_is( 'Location' => '/api/v1/holds/' . $t->tx->res->json->{hold_id}, "REST3.4.1" );
249
        ->header_is( 'Location' => '/api/v1/holds/' . $t->tx->res->json->{hold_id}, "REST3.4.1" );
241
250
242
    # Get id from response
251
    # Get id from response
243
    $reserve_id = $t->tx->res->json->{hold_id};
252
    $reserve_id = $t->tx->res->json->{hold_id};
244
253
245
    $t->get_ok( "//$userid_1:$password@/api/v1/holds?patron_id=" . $patron_1->borrowernumber )->status_is(200)
254
    $t->get_ok( "//$userid_1:$password@/api/v1/holds?patron_id=" . $patron_1->borrowernumber )
255
        ->status_is(200)
246
        ->json_is( '/0/hold_id',         $reserve_id )
256
        ->json_is( '/0/hold_id',         $reserve_id )
247
        ->json_is( '/0/expiration_date', output_pref( { dt => $expiration_date, dateformat => 'iso', dateonly => 1 } ) )
257
        ->json_is( '/0/expiration_date', output_pref( { dt => $expiration_date, dateformat => 'iso', dateonly => 1 } ) )
248
        ->json_is( '/0/pickup_library_id', $branchcode );
258
        ->json_is( '/0/pickup_library_id', $branchcode );
249
259
250
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )->status_is(403)
260
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )
261
        ->status_is(403)
251
        ->json_like( '/error', qr/itemAlreadyOnHold/ );
262
        ->json_like( '/error', qr/itemAlreadyOnHold/ );
252
263
253
    $post_data->{biblio_id} = $biblio_2->biblionumber;
264
    $post_data->{biblio_id} = $biblio_2->biblionumber;
254
    $post_data->{item_id}   = $item_2->itemnumber;
265
    $post_data->{item_id}   = $item_2->itemnumber;
255
266
256
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )->status_is(403)
267
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )
268
        ->status_is(403)
257
        ->json_like( '/error', qr/Hold cannot be placed. Reason: tooManyReserves/ );
269
        ->json_like( '/error', qr/Hold cannot be placed. Reason: tooManyReserves/ );
258
270
259
    my $to_delete_patron  = $builder->build_object( { class => 'Koha::Patrons' } );
271
    my $to_delete_patron  = $builder->build_object( { class => 'Koha::Patrons' } );
Lines 262-268 subtest "Test endpoints with permission" => sub { Link Here
262
274
263
    my $tmp_patron_id = $post_data->{patron_id};
275
    my $tmp_patron_id = $post_data->{patron_id};
264
    $post_data->{patron_id} = $deleted_patron_id;
276
    $post_data->{patron_id} = $deleted_patron_id;
265
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )->status_is(400)
277
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )
278
        ->status_is(400)
266
        ->json_is( { error => 'patron_id not found' } );
279
        ->json_is( { error => 'patron_id not found' } );
267
280
268
    # Restore the original patron_id as it is expected by the next subtest
281
    # Restore the original patron_id as it is expected by the next subtest
Lines 280-286 subtest 'Reserves with itemtype' => sub { Link Here
280
        item_type_id      => $itemtype,
293
        item_type_id      => $itemtype,
281
    };
294
    };
282
295
283
    $t->delete_ok("//$userid_3:$password@/api/v1/holds/$reserve_id")->status_is( 204, 'REST3.2.4' )
296
    $t->delete_ok("//$userid_3:$password@/api/v1/holds/$reserve_id")
297
        ->status_is( 204, 'REST3.2.4' )
284
        ->content_is( '', 'REST3.3.4' );
298
        ->content_is( '', 'REST3.3.4' );
285
299
286
    # Make sure pickup location checks doesn't get in the middle
300
    # Make sure pickup location checks doesn't get in the middle
Lines 293-300 subtest 'Reserves with itemtype' => sub { Link Here
293
307
294
    $reserve_id = $t->tx->res->json->{hold_id};
308
    $reserve_id = $t->tx->res->json->{hold_id};
295
309
296
    $t->get_ok( "//$userid_1:$password@/api/v1/holds?patron_id=" . $patron_1->borrowernumber )->status_is(200)
310
    $t->get_ok( "//$userid_1:$password@/api/v1/holds?patron_id=" . $patron_1->borrowernumber )
297
        ->json_is( '/0/hold_id', $reserve_id )->json_is( '/0/item_type_id', $itemtype );
311
        ->status_is(200)
312
        ->json_is( '/0/hold_id',      $reserve_id )
313
        ->json_is( '/0/item_type_id', $itemtype );
298
};
314
};
299
315
300
subtest 'test AllowHoldDateInFuture' => sub {
316
subtest 'test AllowHoldDateInFuture' => sub {
Lines 326-332 subtest 'test AllowHoldDateInFuture' => sub { Link Here
326
    my $mock_item = Test::MockModule->new('Koha::Item');
342
    my $mock_item = Test::MockModule->new('Koha::Item');
327
    $mock_item->mock( 'pickup_locations', sub { return Koha::Libraries->search } );
343
    $mock_item->mock( 'pickup_locations', sub { return Koha::Libraries->search } );
328
344
329
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )->status_is(201)
345
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )
346
        ->status_is(201)
330
        ->json_is( '/hold_date', output_pref( { dt => $future_hold_date, dateformat => 'iso', dateonly => 1 } ) );
347
        ->json_is( '/hold_date', output_pref( { dt => $future_hold_date, dateformat => 'iso', dateonly => 1 } ) );
331
};
348
};
332
349
Lines 385-391 subtest 'x-koha-override and AllowHoldPolicyOverride tests' => sub { Link Here
385
402
386
    $can_item_be_reserved_result = { status => 'ageRestricted' };
403
    $can_item_be_reserved_result = { status => 'ageRestricted' };
387
404
388
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $post_data )->status_is(403)
405
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $post_data )
406
        ->status_is(403)
389
        ->json_is( '/error' => "Hold cannot be placed. Reason: ageRestricted" );
407
        ->json_is( '/error' => "Hold cannot be placed. Reason: ageRestricted" );
390
408
391
    # x-koha-override doesn't override if AllowHoldPolicyOverride not set
409
    # x-koha-override doesn't override if AllowHoldPolicyOverride not set
Lines 396-402 subtest 'x-koha-override and AllowHoldPolicyOverride tests' => sub { Link Here
396
414
397
    $can_item_be_reserved_result = { status => 'pickupNotInHoldGroup' };
415
    $can_item_be_reserved_result = { status => 'pickupNotInHoldGroup' };
398
416
399
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $post_data )->status_is(403)
417
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $post_data )
418
        ->status_is(403)
400
        ->json_is( '/error' => "Hold cannot be placed. Reason: pickupNotInHoldGroup" );
419
        ->json_is( '/error' => "Hold cannot be placed. Reason: pickupNotInHoldGroup" );
401
420
402
    # x-koha-override overrides the status
421
    # x-koha-override overrides the status
Lines 494-500 subtest 'suspend and resume tests' => sub { Link Here
494
        'Hold suspension has correct end date'
513
        'Hold suspension has correct end date'
495
    );
514
    );
496
515
497
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id . "/suspension" )->status_is( 204, 'REST3.2.4' )
516
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id . "/suspension" )
517
        ->status_is( 204, 'REST3.2.4' )
498
        ->content_is( '', 'REST3.3.4' );
518
        ->content_is( '', 'REST3.3.4' );
499
519
500
    # Pass a an expiration date for the suspension
520
    # Pass a an expiration date for the suspension
Lines 503-514 subtest 'suspend and resume tests' => sub { Link Here
503
            . $hold->id
523
            . $hold->id
504
            . "/suspension" => json =>
524
            . "/suspension" => json =>
505
            { end_date => output_pref( { dt => $date, dateformat => 'iso', dateonly => 1 } ) } )
525
            { end_date => output_pref( { dt => $date, dateformat => 'iso', dateonly => 1 } ) } )
506
        ->status_is( 201, 'Hold suspension created' )->json_is(
526
        ->status_is( 201, 'Hold suspension created' )
527
        ->json_is(
507
        '/end_date',
528
        '/end_date',
508
        output_pref( { dt => $date, dateformat => 'iso', dateonly => 1 } )
529
        output_pref( { dt => $date, dateformat => 'iso', dateonly => 1 } )
509
    )->header_is( Location => "/api/v1/holds/" . $hold->id . "/suspension", 'The Location header is set' );
530
        )->header_is( Location => "/api/v1/holds/" . $hold->id . "/suspension", 'The Location header is set' );
510
531
511
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id . "/suspension" )->status_is( 204, 'REST3.2.4' )
532
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id . "/suspension" )
533
        ->status_is( 204, 'REST3.2.4' )
512
        ->content_is( '', 'REST3.3.4' );
534
        ->content_is( '', 'REST3.3.4' );
513
535
514
    $hold->set_waiting->discard_changes;
536
    $hold->set_waiting->discard_changes;
Lines 694-707 subtest 'PUT /holds/{hold_id}/priority tests' => sub { Link Here
694
716
695
    $t->put_ok( "//$userid_np:$password@/api/v1/holds/" . $hold_3->id . "/priority" => json => 1 )->status_is(403);
717
    $t->put_ok( "//$userid_np:$password@/api/v1/holds/" . $hold_3->id . "/priority" => json => 1 )->status_is(403);
696
718
697
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $hold_3->id . "/priority" => json => 1 )->status_is(200)
719
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $hold_3->id . "/priority" => json => 1 )
720
        ->status_is(200)
698
        ->json_is(1);
721
        ->json_is(1);
699
722
700
    is( $hold_1->discard_changes->priority, 2, 'Priority adjusted correctly' );
723
    is( $hold_1->discard_changes->priority, 2, 'Priority adjusted correctly' );
701
    is( $hold_2->discard_changes->priority, 3, 'Priority adjusted correctly' );
724
    is( $hold_2->discard_changes->priority, 3, 'Priority adjusted correctly' );
702
    is( $hold_3->discard_changes->priority, 1, 'Priority adjusted correctly' );
725
    is( $hold_3->discard_changes->priority, 1, 'Priority adjusted correctly' );
703
726
704
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $hold_3->id . "/priority" => json => 3 )->status_is(200)
727
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $hold_3->id . "/priority" => json => 3 )
728
        ->status_is(200)
705
        ->json_is(3);
729
        ->json_is(3);
706
730
707
    is( $hold_1->discard_changes->priority, 1, 'Priority adjusted correctly' );
731
    is( $hold_1->discard_changes->priority, 1, 'Priority adjusted correctly' );
Lines 881-887 subtest 'add() + can_place_holds() tests' => sub { Link Here
881
        my $hold_id =
905
        my $hold_id =
882
            $t->post_ok(
906
            $t->post_ok(
883
            "//$userid:$password@/api/v1/holds" => { 'x-koha-override' => 'debt_limit' } => json => $post_data )
907
            "//$userid:$password@/api/v1/holds" => { 'x-koha-override' => 'debt_limit' } => json => $post_data )
884
            ->status_is( 201, "Override works for 'debt_limit'" )->tx->res->json->{hold_id};
908
            ->status_is( 201, "Override works for 'debt_limit'" )
909
            ->tx->res->json->{hold_id};
885
910
886
        Koha::Holds->find($hold_id)->delete();
911
        Koha::Holds->find($hold_id)->delete();
887
912
Lines 1004-1010 subtest 'add() + can_place_holds() tests' => sub { Link Here
1004
1029
1005
        my $hold_id = $t->post_ok(
1030
        my $hold_id = $t->post_ok(
1006
            "//$userid:$password@/api/v1/holds" => { 'x-koha-override' => 'hold_limit' } => json => $post_data )
1031
            "//$userid:$password@/api/v1/holds" => { 'x-koha-override' => 'hold_limit' } => json => $post_data )
1007
            ->status_is( 201, "Override works for 'hold_limit'" )->tx->res->json->{hold_id};
1032
            ->status_is( 201, "Override works for 'hold_limit'" )
1033
            ->tx->res->json->{hold_id};
1008
1034
1009
        Koha::Holds->find($hold_id)->delete();
1035
        Koha::Holds->find($hold_id)->delete();
1010
1036
Lines 1284-1303 subtest 'edit() tests' => sub { Link Here
1284
    };
1310
    };
1285
1311
1286
    $t->patch_ok( "//$userid:$password@/api/v1/holds/" . $biblio_hold->id => json => $biblio_hold_data )
1312
    $t->patch_ok( "//$userid:$password@/api/v1/holds/" . $biblio_hold->id => json => $biblio_hold_data )
1287
        ->status_is(400)->json_is( { error => 'The supplied pickup location is not valid' } );
1313
        ->status_is(400)
1314
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1288
1315
1289
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $biblio_hold->id => json => $biblio_hold_data )->status_is(400)
1316
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $biblio_hold->id => json => $biblio_hold_data )
1317
        ->status_is(400)
1290
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1318
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1291
1319
1292
    $biblio_hold->discard_changes;
1320
    $biblio_hold->discard_changes;
1293
    is( $biblio_hold->branchcode, $library_3->branchcode, 'branchcode remains untouched' );
1321
    is( $biblio_hold->branchcode, $library_3->branchcode, 'branchcode remains untouched' );
1294
1322
1295
    $t->patch_ok( "//$userid:$password@/api/v1/holds/"
1323
    $t->patch_ok( "//$userid:$password@/api/v1/holds/"
1296
            . $biblio_hold->id => { 'x-koha-override' => 'any' } => json => $biblio_hold_data )->status_is(200)
1324
            . $biblio_hold->id => { 'x-koha-override' => 'any' } => json => $biblio_hold_data )
1325
        ->status_is(200)
1297
        ->json_has( '/pickup_library_id' => $library_1->id );
1326
        ->json_has( '/pickup_library_id' => $library_1->id );
1298
1327
1299
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1328
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1300
            . $biblio_hold->id => { 'x-koha-override' => 'any' } => json => $biblio_hold_data )->status_is(200)
1329
            . $biblio_hold->id => { 'x-koha-override' => 'any' } => json => $biblio_hold_data )
1330
        ->status_is(200)
1301
        ->json_has( '/pickup_library_id' => $library_1->id );
1331
        ->json_has( '/pickup_library_id' => $library_1->id );
1302
1332
1303
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
1333
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
Lines 1347-1367 subtest 'edit() tests' => sub { Link Here
1347
        priority          => $item_hold_api_data->{priority}
1377
        priority          => $item_hold_api_data->{priority}
1348
    };
1378
    };
1349
1379
1350
    $t->patch_ok( "//$userid:$password@/api/v1/holds/" . $item_hold->id => json => $item_hold_data )->status_is(400)
1380
    $t->patch_ok( "//$userid:$password@/api/v1/holds/" . $item_hold->id => json => $item_hold_data )
1381
        ->status_is(400)
1351
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1382
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1352
1383
1353
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $item_hold->id => json => $item_hold_data )->status_is(400)
1384
    $t->put_ok( "//$userid:$password@/api/v1/holds/" . $item_hold->id => json => $item_hold_data )
1385
        ->status_is(400)
1354
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1386
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1355
1387
1356
    $item_hold->discard_changes;
1388
    $item_hold->discard_changes;
1357
    is( $item_hold->branchcode, $library_3->branchcode, 'branchcode remains untouched' );
1389
    is( $item_hold->branchcode, $library_3->branchcode, 'branchcode remains untouched' );
1358
1390
1359
    $t->patch_ok( "//$userid:$password@/api/v1/holds/"
1391
    $t->patch_ok( "//$userid:$password@/api/v1/holds/"
1360
            . $item_hold->id => { 'x-koha-override' => 'any' } => json => $item_hold_data )->status_is(200)
1392
            . $item_hold->id => { 'x-koha-override' => 'any' } => json => $item_hold_data )
1393
        ->status_is(200)
1361
        ->json_has( '/pickup_library_id' => $library_1->id );
1394
        ->json_has( '/pickup_library_id' => $library_1->id );
1362
1395
1363
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1396
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1364
            . $item_hold->id => { 'x-koha-override' => 'any' } => json => $item_hold_data )->status_is(200)
1397
            . $item_hold->id => { 'x-koha-override' => 'any' } => json => $item_hold_data )
1398
        ->status_is(200)
1365
        ->json_has( '/pickup_library_id' => $library_1->id );
1399
        ->json_has( '/pickup_library_id' => $library_1->id );
1366
1400
1367
    $item_hold_data->{pickup_library_id} = $library_2->branchcode;
1401
    $item_hold_data->{pickup_library_id} = $library_2->branchcode;
Lines 1484-1490 subtest 'add() tests' => sub { Link Here
1484
        pickup_library_id => $library_1->branchcode,
1518
        pickup_library_id => $library_1->branchcode,
1485
    };
1519
    };
1486
1520
1487
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $biblio_hold_data )->status_is(400)
1521
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $biblio_hold_data )
1522
        ->status_is(400)
1488
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1523
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1489
1524
1490
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
1525
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
Lines 1513-1519 subtest 'add() tests' => sub { Link Here
1513
        pickup_library_id => $library_1->branchcode,
1548
        pickup_library_id => $library_1->branchcode,
1514
    };
1549
    };
1515
1550
1516
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $biblio_hold_data )->status_is(400)
1551
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $biblio_hold_data )
1552
        ->status_is(400)
1517
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1553
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1518
1554
1519
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
1555
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
Lines 1541-1547 subtest 'add() tests' => sub { Link Here
1541
        pickup_library_id => $library_1->branchcode,
1577
        pickup_library_id => $library_1->branchcode,
1542
    };
1578
    };
1543
1579
1544
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $item_hold_data )->status_is(400)
1580
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $item_hold_data )
1581
        ->status_is(400)
1545
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1582
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1546
1583
1547
    $can_item_be_reserved   = 'notReservable';
1584
    $can_item_be_reserved   = 'notReservable';
Lines 1566-1572 subtest 'add() tests' => sub { Link Here
1566
        }
1603
        }
1567
    );
1604
    );
1568
1605
1569
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $biblio_hold_data )->status_is(400)
1606
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $biblio_hold_data )
1607
        ->status_is(400)
1570
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1608
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1571
1609
1572
    # empty cases
1610
    # empty cases
Lines 1577-1583 subtest 'add() tests' => sub { Link Here
1577
        }
1615
        }
1578
    );
1616
    );
1579
1617
1580
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $item_hold_data )->status_is(400)
1618
    $t->post_ok( "//$userid:$password@/api/v1/holds" => json => $item_hold_data )
1619
        ->status_is(400)
1581
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1620
        ->json_is( { error => 'The supplied pickup location is not valid' } );
1582
1621
1583
    $schema->storage->txn_rollback;
1622
    $schema->storage->txn_rollback;
Lines 1637-1650 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1637
1676
1638
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1677
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1639
            . $hold->id
1678
            . $hold->id
1640
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )->status_is(200)
1679
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )
1680
        ->status_is(200)
1641
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1681
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1642
1682
1643
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library adjusted correctly' );
1683
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library adjusted correctly' );
1644
1684
1645
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1685
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1646
            . $hold->id
1686
            . $hold->id
1647
            . "/pickup_location" => json => { pickup_library_id => $library_3->branchcode } )->status_is(400)
1687
            . "/pickup_location" => json => { pickup_library_id => $library_3->branchcode } )
1688
        ->status_is(400)
1648
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1689
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1649
1690
1650
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library unchanged' );
1691
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library unchanged' );
Lines 1665-1671 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1665
    # Attempt to use an invalid pickup locations ends in 400
1706
    # Attempt to use an invalid pickup locations ends in 400
1666
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1707
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1667
            . $hold->id
1708
            . $hold->id
1668
            . "/pickup_location" => json => { pickup_library_id => $library_3->branchcode } )->status_is(400)
1709
            . "/pickup_location" => json => { pickup_library_id => $library_3->branchcode } )
1710
        ->status_is(400)
1669
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1711
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1670
1712
1671
    is( $hold->discard_changes->branchcode, $library_1->branchcode, 'pickup library unchanged' );
1713
    is( $hold->discard_changes->branchcode, $library_1->branchcode, 'pickup library unchanged' );
Lines 1676-1682 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1676
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1718
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1677
            . $hold->id
1719
            . $hold->id
1678
            . "/pickup_location" => { 'x-koha-override' => 'any' } => json =>
1720
            . "/pickup_location" => { 'x-koha-override' => 'any' } => json =>
1679
            { pickup_library_id => $library_2->branchcode } )->status_is(200)
1721
            { pickup_library_id => $library_2->branchcode } )
1722
        ->status_is(200)
1680
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1723
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1681
1724
1682
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library changed' );
1725
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library changed' );
Lines 1685-1698 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1685
1728
1686
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1729
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1687
            . $hold->id
1730
            . $hold->id
1688
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )->status_is(200)
1731
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )
1732
        ->status_is(200)
1689
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1733
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1690
1734
1691
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library adjusted correctly' );
1735
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'pickup library adjusted correctly' );
1692
1736
1693
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1737
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1694
            . $hold->id
1738
            . $hold->id
1695
            . "/pickup_location" => json => { pickup_library_id => $library_3->branchcode } )->status_is(400)
1739
            . "/pickup_location" => json => { pickup_library_id => $library_3->branchcode } )
1740
        ->status_is(400)
1696
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1741
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1697
1742
1698
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'invalid pickup library not used' );
1743
    is( $hold->discard_changes->branchcode, $library_2->branchcode, 'invalid pickup library not used' );
Lines 1700-1706 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1700
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1745
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1701
            . $hold->id
1746
            . $hold->id
1702
            . "/pickup_location" => { 'x-koha-override' => 'any' } => json =>
1747
            . "/pickup_location" => { 'x-koha-override' => 'any' } => json =>
1703
            { pickup_library_id => $library_3->branchcode } )->status_is(400)
1748
            { pickup_library_id => $library_3->branchcode } )
1749
        ->status_is(400)
1704
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1750
        ->json_is( { error => '[The supplied pickup location is not valid]' } );
1705
1751
1706
    is(
1752
    is(
Lines 1714-1730 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1714
1760
1715
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1761
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1716
            . $waiting_hold->id
1762
            . $waiting_hold->id
1717
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )->status_is(409)
1763
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )
1764
        ->status_is(409)
1718
        ->json_is( { error => q{Cannot change pickup location}, error_code => 'hold_waiting' } );
1765
        ->json_is( { error => q{Cannot change pickup location}, error_code => 'hold_waiting' } );
1719
1766
1720
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1767
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1721
            . $in_processing_hold->id
1768
            . $in_processing_hold->id
1722
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )->status_is(409)
1769
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )
1770
        ->status_is(409)
1723
        ->json_is( { error => q{Cannot change pickup location}, error_code => 'hold_in_processing' } );
1771
        ->json_is( { error => q{Cannot change pickup location}, error_code => 'hold_in_processing' } );
1724
1772
1725
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1773
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1726
            . $in_transit_hold->id
1774
            . $in_transit_hold->id
1727
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )->status_is(200)
1775
            . "/pickup_location" => json => { pickup_library_id => $library_2->branchcode } )
1776
        ->status_is(200)
1728
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1777
        ->json_is( { pickup_library_id => $library_2->branchcode } );
1729
1778
1730
    $schema->storage->txn_rollback;
1779
    $schema->storage->txn_rollback;
Lines 1778-1784 subtest 'delete() tests' => sub { Link Here
1778
        )
1827
        )
1779
    );
1828
    );
1780
1829
1781
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id )->status_is( 204, 'REST3.2.4' )
1830
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id )
1831
        ->status_is( 204, 'REST3.2.4' )
1782
        ->content_is( '', 'REST3.3.4' );
1832
        ->content_is( '', 'REST3.3.4' );
1783
1833
1784
    $hold = Koha::Holds->find(
1834
    $hold = Koha::Holds->find(
Lines 1794-1800 subtest 'delete() tests' => sub { Link Here
1794
    );
1844
    );
1795
1845
1796
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id => { 'x-koha-override' => q{} } )
1846
    $t->delete_ok( "//$userid:$password@/api/v1/holds/" . $hold->id => { 'x-koha-override' => q{} } )
1797
        ->status_is( 204, 'Same behavior if header not set' )->content_is('');
1847
        ->status_is( 204, 'Same behavior if header not set' )
1848
        ->content_is('');
1798
1849
1799
    $hold = Koha::Holds->find(
1850
    $hold = Koha::Holds->find(
1800
        AddReserve(
1851
        AddReserve(
Lines 1810-1816 subtest 'delete() tests' => sub { Link Here
1810
1861
1811
    $t->delete_ok(
1862
    $t->delete_ok(
1812
        "//$userid:$password@/api/v1/holds/" . $hold->id => { 'x-koha-override' => q{cancellation-request-flow} } )
1863
        "//$userid:$password@/api/v1/holds/" . $hold->id => { 'x-koha-override' => q{cancellation-request-flow} } )
1813
        ->status_is( 204, 'Same behavior if header set but hold not waiting' )->content_is('');
1864
        ->status_is( 204, 'Same behavior if header set but hold not waiting' )
1865
        ->content_is('');
1814
1866
1815
    $hold = Koha::Holds->find(
1867
    $hold = Koha::Holds->find(
1816
        AddReserve(
1868
        AddReserve(
Lines 1886-1892 subtest 'delete_bulk) tests' => sub { Link Here
1886
    );
1938
    );
1887
1939
1888
    $t->delete_ok( "//$userid:$password@/api/v1/holds/cancellation_bulk" => json => { hold_ids => [ $hold->id ] } )
1940
    $t->delete_ok( "//$userid:$password@/api/v1/holds/cancellation_bulk" => json => { hold_ids => [ $hold->id ] } )
1889
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
1941
        ->status_is( 204, 'REST3.2.4' )
1942
        ->content_is( '', 'REST3.3.4' );
1890
1943
1891
    is( $hold->get_from_storage, undef, "Hold has been successfully deleted" );
1944
    is( $hold->get_from_storage, undef, "Hold has been successfully deleted" );
1892
1945
Lines 1907-1913 subtest 'delete_bulk) tests' => sub { Link Here
1907
    $mock_letters->mock( 'GetPreparedLetter', sub { return } );
1960
    $mock_letters->mock( 'GetPreparedLetter', sub { return } );
1908
1961
1909
    $t->delete_ok( "//$userid:$password@/api/v1/holds/cancellation_bulk" => json =>
1962
    $t->delete_ok( "//$userid:$password@/api/v1/holds/cancellation_bulk" => json =>
1910
            { hold_ids => [ $hold_2->id ], cancellation_reason => 'DAMAGED' } )->status_is( 204, 'REST3.2.4' )
1963
            { hold_ids => [ $hold_2->id ], cancellation_reason => 'DAMAGED' } )
1964
        ->status_is( 204, 'REST3.2.4' )
1911
        ->content_is( '', 'REST3.3.4' );
1965
        ->content_is( '', 'REST3.3.4' );
1912
1966
1913
    my $old_hold_2 = Koha::Old::Holds->find( $hold_2->id );
1967
    my $old_hold_2 = Koha::Old::Holds->find( $hold_2->id );
Lines 2027-2033 subtest 'Bug 40866: API hold creation with override logs confirmations' => sub { Link Here
2027
    # Create hold with override
2081
    # Create hold with override
2028
    my $hold_id =
2082
    my $hold_id =
2029
        $t->post_ok( "//$userid:$password@/api/v1/holds" => { 'x-koha-override' => 'any' } => json => $post_data )
2083
        $t->post_ok( "//$userid:$password@/api/v1/holds" => { 'x-koha-override' => 'any' } => json => $post_data )
2030
        ->status_is(201)->tx->res->json->{hold_id};
2084
        ->status_is(201)
2085
        ->tx->res->json->{hold_id};
2031
2086
2032
    ok( $hold_id, 'Hold created via API with override' );
2087
    ok( $hold_id, 'Hold created via API with override' );
2033
2088
(-)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 (-58 / +116 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 464-470 subtest 'add() tests' => sub { Link Here
464
        my $userid = $librarian->userid;
487
        my $userid = $librarian->userid;
465
        t::lib::Mocks::mock_preference( 'PatronDuplicateMatchingAddFields', 'firstname|surname|dateofbirth' );
488
        t::lib::Mocks::mock_preference( 'PatronDuplicateMatchingAddFields', 'firstname|surname|dateofbirth' );
466
489
467
        $t->post_ok( "//$userid:$password@/api/v1/patrons" => json => $newpatron )->status_is(409)
490
        $t->post_ok( "//$userid:$password@/api/v1/patrons" => json => $newpatron )
491
            ->status_is(409)
468
            ->json_is( '/error' => "A patron record matching these details already exists" );
492
            ->json_is( '/error' => "A patron record matching these details already exists" );
469
493
470
        # Create a library just to make sure its ID doesn't exist on the DB
494
        # Create a library just to make sure its ID doesn't exist on the DB
Lines 478-484 subtest 'add() tests' => sub { Link Here
478
502
479
        # Test duplicate userid constraint
503
        # Test duplicate userid constraint
480
        $t->post_ok( "//$userid:$password@/api/v1/patrons" => { 'x-confirm-not-duplicate' => 1 } => json => $newpatron )
504
        $t->post_ok( "//$userid:$password@/api/v1/patrons" => { 'x-confirm-not-duplicate' => 1 } => json => $newpatron )
481
            ->status_is(400)->json_is( '/error' => "Problem with " . $newpatron->{userid} );
505
            ->status_is(400)
506
            ->json_is( '/error' => "Problem with " . $newpatron->{userid} );
482
507
483
        $newpatron->{library_id} = $patron->branchcode;
508
        $newpatron->{library_id} = $patron->branchcode;
484
509
Lines 487-493 subtest 'add() tests' => sub { Link Here
487
        warning_like {
512
        warning_like {
488
            $t->post_ok(
513
            $t->post_ok(
489
                "//$userid:$password@/api/v1/patrons" => { 'x-confirm-not-duplicate' => 1 } => json => $newpatron )
514
                "//$userid:$password@/api/v1/patrons" => { 'x-confirm-not-duplicate' => 1 } => json => $newpatron )
490
                ->status_is(409)->json_has( '/error', 'Fails when trying to POST duplicate cardnumber' )
515
                ->status_is(409)
516
                ->json_has( '/error', 'Fails when trying to POST duplicate cardnumber' )
491
                ->json_like( '/conflict' => qr/(borrowers\.)?cardnumber/ );
517
                ->json_like( '/conflict' => qr/(borrowers\.)?cardnumber/ );
492
        }
518
        }
493
        qr/DBD::mysql::st execute failed: Duplicate entry '(.*?)' for key '(borrowers\.)?cardnumber'/;
519
        qr/DBD::mysql::st execute failed: Duplicate entry '(.*?)' for key '(borrowers\.)?cardnumber'/;
Lines 502-508 subtest 'add() tests' => sub { Link Here
502
        $newpatron->{category_id} = $deleted_category_id;    # Test invalid patron category
528
        $newpatron->{category_id} = $deleted_category_id;    # Test invalid patron category
503
529
504
        $t->post_ok( "//$userid:$password@/api/v1/patrons" => { 'x-confirm-not-duplicate' => 1 } => json => $newpatron )
530
        $t->post_ok( "//$userid:$password@/api/v1/patrons" => { 'x-confirm-not-duplicate' => 1 } => json => $newpatron )
505
            ->status_is(400)->json_is( '/error' => "Given category_id does not exist" );
531
            ->status_is(400)
532
            ->json_is( '/error' => "Given category_id does not exist" );
506
        $newpatron->{category_id} = $patron->categorycode;
533
        $newpatron->{category_id} = $patron->categorycode;
507
534
508
        $newpatron->{falseproperty} = "Non existent property";
535
        $newpatron->{falseproperty} = "Non existent property";
Lines 532-542 subtest 'add() tests' => sub { Link Here
532
        $letter_enqueued = 0;
559
        $letter_enqueued = 0;
533
        $t->post_ok(
560
        $t->post_ok(
534
            "//$userid:$password@/api/v1/patrons" => { 'x-koha-override' => 'welcome_yes' } => json => $newpatron )
561
            "//$userid:$password@/api/v1/patrons" => { 'x-koha-override' => 'welcome_yes' } => json => $newpatron )
535
            ->status_is( 201, 'Patron created successfully' )->header_like(
562
            ->status_is( 201, 'Patron created successfully' )
563
            ->header_like(
536
            Location => qr|^\/api\/v1\/patrons/\d*|,
564
            Location => qr|^\/api\/v1\/patrons/\d*|,
537
            'REST3.4.1'
565
            'REST3.4.1'
538
        )->json_has( '/patron_id', 'got a patron_id' )->json_is( '/cardnumber' => $newpatron->{cardnumber} )
566
            )
539
            ->json_is( '/surname'       => $newpatron->{surname} )->json_is( '/firstname' => $newpatron->{firstname} )
567
            ->json_has( '/patron_id', 'got a patron_id' )
568
            ->json_is( '/cardnumber'    => $newpatron->{cardnumber} )
569
            ->json_is( '/surname'       => $newpatron->{surname} )
570
            ->json_is( '/firstname'     => $newpatron->{firstname} )
540
            ->json_is( '/date_of_birth' => $newpatron->{date_of_birth}, 'Date field set (Bug 28585)' )
571
            ->json_is( '/date_of_birth' => $newpatron->{date_of_birth}, 'Date field set (Bug 28585)' )
541
            ->json_is( '/last_seen'     => $newpatron->{last_seen},     'Date-time field set (Bug 28585)' );
572
            ->json_is( '/last_seen'     => $newpatron->{last_seen},     'Date-time field set (Bug 28585)' );
542
573
Lines 663-669 subtest 'add() tests' => sub { Link Here
663
                    "city"        => "Konstanz",
694
                    "city"        => "Konstanz",
664
                    "library_id"  => "MPL"
695
                    "library_id"  => "MPL"
665
                }
696
                }
666
            )->status_is(400)
697
                )
698
                ->status_is(400)
667
                ->json_is( '/error' => "Tried to add more than one non-repeatable attributes. type=$code value=$attr" );
699
                ->json_is( '/error' => "Tried to add more than one non-repeatable attributes. type=$code value=$attr" );
668
700
669
            is( Koha::Patrons->search->count, $patrons_count, 'No patron added' );
701
            is( Koha::Patrons->search->count, $patrons_count, 'No patron added' );
Lines 678-684 subtest 'add() tests' => sub { Link Here
678
                    "city"        => "Konstanz",
710
                    "city"        => "Konstanz",
679
                    "library_id"  => "MPL"
711
                    "library_id"  => "MPL"
680
                }
712
                }
681
            )->status_is(400)
713
                )
714
                ->status_is(400)
682
                ->json_is(
715
                ->json_is(
683
                '/error' => "Your action breaks a unique constraint on the attribute. type=$code value=$attr" );
716
                '/error' => "Your action breaks a unique constraint on the attribute. type=$code value=$attr" );
684
717
Lines 839-845 subtest 'add() tests' => sub { Link Here
839
                    "city"        => "Bigtown",
872
                    "city"        => "Bigtown",
840
                    "library_id"  => "MPL",
873
                    "library_id"  => "MPL",
841
                }
874
                }
842
            )->status_is( 201, 'Patron added with EnhancedMessagingPreferences disabled' )
875
                )
876
                ->status_is( 201, 'Patron added with EnhancedMessagingPreferences disabled' )
843
                ->tx->res->json->{patron_id};
877
                ->tx->res->json->{patron_id};
844
878
845
            # No messaging preferences should be set
879
            # No messaging preferences should be set
Lines 898-904 subtest 'update() tests' => sub { Link Here
898
        delete $newpatron->{expired};
932
        delete $newpatron->{expired};
899
        delete $newpatron->{anonymized};
933
        delete $newpatron->{anonymized};
900
934
901
        $t->put_ok( "//$userid:$password@/api/v1/patrons/-1" => json => $newpatron )->status_is(404)
935
        $t->put_ok( "//$userid:$password@/api/v1/patrons/-1" => json => $newpatron )
936
            ->status_is(404)
902
            ->json_has( '/error', 'Fails when trying to PUT nonexistent patron' );
937
            ->json_has( '/error', 'Fails when trying to PUT nonexistent patron' );
903
938
904
        # Create a library just to make sure its ID doesn't exist on the DB
939
        # Create a library just to make sure its ID doesn't exist on the DB
Lines 912-918 subtest 'update() tests' => sub { Link Here
912
        $newpatron->{category_id} = $deleted_category_id;
947
        $newpatron->{category_id} = $deleted_category_id;
913
948
914
        $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
949
        $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
915
            ->status_is(400)->json_is( '/error' => "Given category_id does not exist" );
950
            ->status_is(400)
951
            ->json_is( '/error' => "Given category_id does not exist" );
916
952
917
        # Restore the valid category
953
        # Restore the valid category
918
        $newpatron->{category_id} = $patron_2->categorycode;
954
        $newpatron->{category_id} = $patron_2->categorycode;
Lines 929-935 subtest 'update() tests' => sub { Link Here
929
965
930
        warning_like {
966
        warning_like {
931
            $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
967
            $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
932
                ->status_is(400)->json_is( '/error' => "Given library_id does not exist" );
968
                ->status_is(400)
969
                ->json_is( '/error' => "Given library_id does not exist" );
933
        }
970
        }
934
        qr/DBD::mysql::st execute failed: Cannot add or update a child row: a foreign key constraint fails/;
971
        qr/DBD::mysql::st execute failed: Cannot add or update a child row: a foreign key constraint fails/;
935
972
Lines 940-946 subtest 'update() tests' => sub { Link Here
940
        $newpatron->{falseproperty} = "Non existent property";
977
        $newpatron->{falseproperty} = "Non existent property";
941
978
942
        $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
979
        $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
943
            ->status_is(400)->json_is( '/errors/0/message' => 'Properties not allowed: falseproperty.' );
980
            ->status_is(400)
981
            ->json_is( '/errors/0/message' => 'Properties not allowed: falseproperty.' );
944
982
945
        # Get rid of the invalid attribute
983
        # Get rid of the invalid attribute
946
        delete $newpatron->{falseproperty};
984
        delete $newpatron->{falseproperty};
Lines 950-956 subtest 'update() tests' => sub { Link Here
950
        $newpatron->{userid}     = $patron_1->userid;
988
        $newpatron->{userid}     = $patron_1->userid;
951
989
952
        $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
990
        $t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
953
            ->status_is(400)->json_has( '/error', "Problem with userid " . $patron_1->userid );
991
            ->status_is(400)
992
            ->json_has( '/error', "Problem with userid " . $patron_1->userid );
954
993
955
        $newpatron->{cardnumber} = $patron_1->id . $patron_2->id;
994
        $newpatron->{cardnumber} = $patron_1->id . $patron_2->id;
956
        $newpatron->{userid}     = "user" . $patron_1->id . $patron_2->id;
995
        $newpatron->{userid}     = "user" . $patron_1->id . $patron_2->id;
Lines 1034-1040 subtest 'update() tests' => sub { Link Here
1034
            ->status_is(
1073
            ->status_is(
1035
            403,
1074
            403,
1036
            "Non-superlibrarian user change of superlibrarian secondary_email to undefined forbidden"
1075
            "Non-superlibrarian user change of superlibrarian secondary_email to undefined forbidden"
1037
        )->json_is( { error => "Not enough privileges to change a superlibrarian's email" } );
1076
            )->json_is( { error => "Not enough privileges to change a superlibrarian's email" } );
1038
1077
1039
        $newpatron->{secondary_email}  = $superlibrarian->emailpro;
1078
        $newpatron->{secondary_email}  = $superlibrarian->emailpro;
1040
        $newpatron->{altaddress_email} = 'nonsense@no.no';
1079
        $newpatron->{altaddress_email} = 'nonsense@no.no';
Lines 1050-1056 subtest 'update() tests' => sub { Link Here
1050
            ->status_is(
1089
            ->status_is(
1051
            403,
1090
            403,
1052
            "Non-superlibrarian user change of superlibrarian altaddress_email to undefined forbidden"
1091
            "Non-superlibrarian user change of superlibrarian altaddress_email to undefined forbidden"
1053
        )->json_is( { error => "Not enough privileges to change a superlibrarian's email" } );
1092
            )->json_is( { error => "Not enough privileges to change a superlibrarian's email" } );
1054
1093
1055
        # update patron without sending email
1094
        # update patron without sending email
1056
        delete $newpatron->{email};
1095
        delete $newpatron->{email};
Lines 1121-1133 subtest 'update() tests' => sub { Link Here
1121
                    "city"        => "Konstanz",
1160
                    "city"        => "Konstanz",
1122
                    "library_id"  => "MPL"
1161
                    "library_id"  => "MPL"
1123
                }
1162
                }
1124
            )->status_is(400)
1163
                )
1164
                ->status_is(400)
1125
                ->json_is(
1165
                ->json_is(
1126
                '/error' => "Missing mandatory extended attribute (type=" . $attr_type_mandatory->code . ")" );
1166
                '/error' => "Missing mandatory extended attribute (type=" . $attr_type_mandatory->code . ")" );
1127
1167
1128
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1168
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1129
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1169
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1130
                    $newpatron )->status_is(400)
1170
                    $newpatron )
1171
                ->status_is(400)
1131
                ->json_is( '/error'      => 'Tried to use an invalid attribute type. type=' . $deleted_attr_code )
1172
                ->json_is( '/error'      => 'Tried to use an invalid attribute type. type=' . $deleted_attr_code )
1132
                ->json_is( '/error_code' => 'invalid_attribute_type' );
1173
                ->json_is( '/error_code' => 'invalid_attribute_type' );
1133
1174
Lines 1144-1154 subtest 'update() tests' => sub { Link Here
1144
1185
1145
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1186
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1146
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1187
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1147
                    $newpatron )->status_is(400)
1188
                    $newpatron )
1189
                ->status_is(400)
1148
                ->json_is( '/error' => 'Your action breaks a unique constraint on the attribute. type='
1190
                ->json_is( '/error' => 'Your action breaks a unique constraint on the attribute. type='
1149
                    . $attr_type_unique->code
1191
                    . $attr_type_unique->code
1150
                    . ' value='
1192
                    . ' value='
1151
                    . $unique_attr->attribute )->json_is( '/error_code' => 'attribute_not_unique' );
1193
                    . $unique_attr->attribute )
1194
                ->json_is( '/error_code' => 'attribute_not_unique' );
1152
1195
1153
            $newpatron->{extended_attributes} = [
1196
            $newpatron->{extended_attributes} = [
1154
                { type => $attr_type_repeatable->code, value => 'a' },
1197
                { type => $attr_type_repeatable->code, value => 'a' },
Lines 1159-1169 subtest 'update() tests' => sub { Link Here
1159
1202
1160
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1203
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1161
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1204
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1162
                    $newpatron )->status_is(400)
1205
                    $newpatron )
1206
                ->status_is(400)
1163
                ->json_is( '/error' => 'Your action breaks a unique constraint on the attribute. type='
1207
                ->json_is( '/error' => 'Your action breaks a unique constraint on the attribute. type='
1164
                    . $attr_type_unique->code
1208
                    . $attr_type_unique->code
1165
                    . ' value='
1209
                    . ' value='
1166
                    . $unique_attr->attribute )->json_is( '/error_code' => 'attribute_not_unique' );
1210
                    . $unique_attr->attribute )
1211
                ->json_is( '/error_code' => 'attribute_not_unique' );
1167
1212
1168
            $newpatron->{extended_attributes} = [
1213
            $newpatron->{extended_attributes} = [
1169
                { type => $attr_type_repeatable->code, value => 'a' },
1214
                { type => $attr_type_repeatable->code, value => 'a' },
Lines 1173-1182 subtest 'update() tests' => sub { Link Here
1173
1218
1174
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1219
            $t->put_ok( "//$userid:$password@/api/v1/patrons/"
1175
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1220
                    . $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
1176
                    $newpatron )->status_is(400)
1221
                    $newpatron )
1222
                ->status_is(400)
1177
                ->json_is( '/error' => 'Tried to add more than one non-repeatable attributes. type='
1223
                ->json_is( '/error' => 'Tried to add more than one non-repeatable attributes. type='
1178
                    . $attr_type_mandatory->code
1224
                    . $attr_type_mandatory->code
1179
                    . ' value=pong' )->json_is( '/error_code' => 'non_repeatable_attribute' );
1225
                    . ' value=pong' )
1226
                ->json_is( '/error_code' => 'non_repeatable_attribute' );
1180
1227
1181
            my $unique_value = $unique_attr->attribute;
1228
            my $unique_value = $unique_attr->attribute;
1182
            $unique_attr->delete;
1229
            $unique_attr->delete;
Lines 1235-1241 subtest 'delete() tests' => sub { Link Here
1235
1282
1236
        t::lib::Mocks::mock_preference( 'AnonymousPatron', $patron->borrowernumber );
1283
        t::lib::Mocks::mock_preference( 'AnonymousPatron', $patron->borrowernumber );
1237
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1284
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1238
            ->status_is( 409, 'Anonymous patron cannot be deleted' )->json_is(
1285
            ->status_is( 409, 'Anonymous patron cannot be deleted' )
1286
            ->json_is(
1239
            {
1287
            {
1240
                error      => 'Anonymous patron cannot be deleted',
1288
                error      => 'Anonymous patron cannot be deleted',
1241
                error_code => 'is_anonymous_patron'
1289
                error_code => 'is_anonymous_patron'
Lines 1257-1263 subtest 'delete() tests' => sub { Link Here
1257
        $guarantee->add_guarantor( { guarantor_id => $patron->id, relationship => 'parent' } );
1305
        $guarantee->add_guarantor( { guarantor_id => $patron->id, relationship => 'parent' } );
1258
1306
1259
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1307
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1260
            ->status_is( 409, 'Patron with checkouts cannot be deleted' )->json_is(
1308
            ->status_is( 409, 'Patron with checkouts cannot be deleted' )
1309
            ->json_is(
1261
            {
1310
            {
1262
                error      => 'Pending checkouts prevent deletion',
1311
                error      => 'Pending checkouts prevent deletion',
1263
                error_code => 'has_checkouts'
1312
                error_code => 'has_checkouts'
Lines 1268-1274 subtest 'delete() tests' => sub { Link Here
1268
        $checkout->delete;
1317
        $checkout->delete;
1269
1318
1270
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1319
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1271
            ->status_is( 409, 'Patron with debt cannot be deleted' )->json_is(
1320
            ->status_is( 409, 'Patron with debt cannot be deleted' )
1321
            ->json_is(
1272
            {
1322
            {
1273
                error      => 'Pending debts prevent deletion',
1323
                error      => 'Pending debts prevent deletion',
1274
                error_code => 'has_debt'
1324
                error_code => 'has_debt'
Lines 1279-1285 subtest 'delete() tests' => sub { Link Here
1279
        $patron->account->pay( { amount => 10, debits => [$debit] } );
1329
        $patron->account->pay( { amount => 10, debits => [$debit] } );
1280
1330
1281
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1331
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1282
            ->status_is( 409, 'Patron with guarantees cannot be deleted' )->json_is(
1332
            ->status_is( 409, 'Patron with guarantees cannot be deleted' )
1333
            ->json_is(
1283
            {
1334
            {
1284
                error      => 'Patron is a guarantor and it prevents deletion',
1335
                error      => 'Patron is a guarantor and it prevents deletion',
1285
                error_code => 'has_guarantees'
1336
                error_code => 'has_guarantees'
Lines 1292-1298 subtest 'delete() tests' => sub { Link Here
1292
        $patron->protected(1)->store();
1343
        $patron->protected(1)->store();
1293
1344
1294
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1345
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1295
            ->status_is( 409, 'Protected patron cannot be deleted' )->json_is(
1346
            ->status_is( 409, 'Protected patron cannot be deleted' )
1347
            ->json_is(
1296
            {
1348
            {
1297
                error      => 'Protected patrons cannot be deleted',
1349
                error      => 'Protected patrons cannot be deleted',
1298
                error_code => 'is_protected'
1350
                error_code => 'is_protected'
Lines 1302-1308 subtest 'delete() tests' => sub { Link Here
1302
        $patron->protected(0)->store();
1354
        $patron->protected(0)->store();
1303
1355
1304
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1356
        $t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
1305
            ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
1357
            ->status_is( 204, 'REST3.2.4' )
1358
            ->content_is( '', 'REST3.3.4' );
1306
1359
1307
        my $deleted_patrons = Koha::Old::Patrons->search( { borrowernumber => $patron->borrowernumber } );
1360
        my $deleted_patrons = Koha::Old::Patrons->search( { borrowernumber => $patron->borrowernumber } );
1308
        is( $deleted_patrons->count, 1, 'The patron has been moved to the vault' );
1361
        is( $deleted_patrons->count, 1, 'The patron has been moved to the vault' );
Lines 1334-1344 subtest 'guarantors_can_see_charges() tests' => sub { Link Here
1334
    )->status_is(401)->json_is( { error => "Authentication failure." } );
1387
    )->status_is(401)->json_is( { error => "Authentication failure." } );
1335
1388
1336
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$other_patron_id/guarantors/can_see_charges" => json =>
1389
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$other_patron_id/guarantors/can_see_charges" => json =>
1337
            { allowed => Mojo::JSON->true } )->status_is(403)
1390
            { allowed => Mojo::JSON->true } )
1391
        ->status_is(403)
1338
        ->json_is( { error => "Unprivileged user cannot access another user's resources" } );
1392
        ->json_is( { error => "Unprivileged user cannot access another user's resources" } );
1339
1393
1340
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/guarantors/can_see_charges" => json =>
1394
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/guarantors/can_see_charges" => json =>
1341
            { allowed => Mojo::JSON->true } )->status_is(403)
1395
            { allowed => Mojo::JSON->true } )
1396
        ->status_is(403)
1342
        ->json_is( '/error', 'The current configuration doesn\'t allow the requested action.' );
1397
        ->json_is( '/error', 'The current configuration doesn\'t allow the requested action.' );
1343
1398
1344
    t::lib::Mocks::mock_preference( 'AllowPatronToSetFinesVisibilityForGuarantor', 1 );
1399
    t::lib::Mocks::mock_preference( 'AllowPatronToSetFinesVisibilityForGuarantor', 1 );
Lines 1376-1388 subtest 'guarantors_can_see_checkouts() tests' => sub { Link Here
1376
            { allowed => Mojo::JSON->true } )->status_is(401)->json_is( { error => "Authentication failure." } );
1431
            { allowed => Mojo::JSON->true } )->status_is(401)->json_is( { error => "Authentication failure." } );
1377
1432
1378
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$other_patron_id/guarantors/can_see_checkouts" => json =>
1433
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$other_patron_id/guarantors/can_see_checkouts" => json =>
1379
            { allowed => Mojo::JSON->true } )->status_is(403)
1434
            { allowed => Mojo::JSON->true } )
1435
        ->status_is(403)
1380
        ->json_is( { error => "Unprivileged user cannot access another user's resources" } );
1436
        ->json_is( { error => "Unprivileged user cannot access another user's resources" } );
1381
1437
1382
    t::lib::Mocks::mock_preference( 'AllowPatronToSetCheckoutsVisibilityForGuarantor', 0 );
1438
    t::lib::Mocks::mock_preference( 'AllowPatronToSetCheckoutsVisibilityForGuarantor', 0 );
1383
1439
1384
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/guarantors/can_see_checkouts" => json =>
1440
    $t->put_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/guarantors/can_see_checkouts" => json =>
1385
            { allowed => Mojo::JSON->true } )->status_is(403)
1441
            { allowed => Mojo::JSON->true } )
1442
        ->status_is(403)
1386
        ->json_is( '/error', 'The current configuration doesn\'t allow the requested action.' );
1443
        ->json_is( '/error', 'The current configuration doesn\'t allow the requested action.' );
1387
1444
1388
    t::lib::Mocks::mock_preference( 'AllowPatronToSetCheckoutsVisibilityForGuarantor', 1 );
1445
    t::lib::Mocks::mock_preference( 'AllowPatronToSetCheckoutsVisibilityForGuarantor', 1 );
Lines 1425-1431 sub unauthorized_access_tests { Link Here
1425
        $unauthorized_patron->set_password( { password => $password, skip_validation => 1 } );
1482
        $unauthorized_patron->set_password( { password => $password, skip_validation => 1 } );
1426
        my $unauth_userid = $unauthorized_patron->userid;
1483
        my $unauth_userid = $unauthorized_patron->userid;
1427
1484
1428
        $t->$verb_ok( "//$unauth_userid:$password\@$endpoint" => json => $json )->status_is(403)
1485
        $t->$verb_ok( "//$unauth_userid:$password\@$endpoint" => json => $json )
1486
            ->status_is(403)
1429
            ->json_has('/required_permissions');
1487
            ->json_has('/required_permissions');
1430
    };
1488
    };
1431
}
1489
}
(-)a/t/db_dependent/api/v1/patrons_accounts.t (-27 / +53 lines)
Lines 90-97 subtest 'get_balance() tests' => sub { Link Here
90
    )->store();
90
    )->store();
91
    $debit_2->discard_changes;
91
    $debit_2->discard_changes;
92
92
93
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")->status_is(200)
93
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
94
        ->or( sub { diag $t->tx->res->body } )->json_is(
94
        ->status_is(200)
95
        ->or( sub { diag $t->tx->res->body } )
96
        ->json_is(
95
        {
97
        {
96
            balance            => 100.01,
98
            balance            => 100.01,
97
            outstanding_debits => {
99
            outstanding_debits => {
Lines 213-222 subtest 'add_credit() tests' => sub { Link Here
213
215
214
    my $ret =
216
    my $ret =
215
        $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit )
217
        $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit )
216
        ->status_is(201)->header_is(
218
        ->status_is(201)
219
        ->header_is(
217
        'Location' => "/api/v1/patrons/$patron_id/account/credits/" . $t->tx->res->json->{account_line_id},
220
        'Location' => "/api/v1/patrons/$patron_id/account/credits/" . $t->tx->res->json->{account_line_id},
218
        "REST3.4.1"
221
        "REST3.4.1"
219
    )->tx->res->json;
222
        )->tx->res->json;
220
223
221
    is_deeply(
224
    is_deeply(
222
        $ret,
225
        $ret,
Lines 225-231 subtest 'add_credit() tests' => sub { Link Here
225
    );
228
    );
226
229
227
    my $outstanding_credits = $account->outstanding_credits;
230
    my $outstanding_credits = $account->outstanding_credits;
228
    is( $outstanding_credits->count,             1 );
231
    is( $outstanding_credits->count,              1 );
229
    is( $outstanding_credits->total_outstanding, -100 );
232
    is( $outstanding_credits->total_outstanding, -100 );
230
233
231
    my $debit_1 = $account->add_debit(
234
    my $debit_1 = $account->add_debit(
Lines 250-257 subtest 'add_credit() tests' => sub { Link Here
250
    is( $account->outstanding_debits->total_outstanding, 25 );
253
    is( $account->outstanding_debits->total_outstanding, 25 );
251
    $credit->{library_id} = $library->id;
254
    $credit->{library_id} = $library->id;
252
255
253
    $ret = $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit )
256
    $ret =
254
        ->status_is(201)->tx->res->json;
257
        $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit )
258
        ->status_is(201)
259
        ->tx->res->json;
255
260
256
    is_deeply(
261
    is_deeply(
257
        $ret,
262
        $ret,
Lines 285-292 subtest 'add_credit() tests' => sub { Link Here
285
        account_lines_ids => [ $debit_1->id, $debit_2->id, $debit_3->id ]
290
        account_lines_ids => [ $debit_1->id, $debit_2->id, $debit_3->id ]
286
    };
291
    };
287
292
288
    $ret = $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit )
293
    $ret =
289
        ->status_is(201)->tx->res->json;
294
        $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit )
295
        ->status_is(201)
296
        ->tx->res->json;
290
297
291
    is_deeply(
298
    is_deeply(
292
        $ret,
299
        $ret,
Lines 328-347 subtest 'get_credit() tests' => sub { Link Here
328
    );
335
    );
329
    my $credit_id = $credit->id;
336
    my $credit_id = $credit->id;
330
337
331
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/credits/$credit_id")->status_is(200)
338
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/credits/$credit_id")
332
        ->json_is( '/account_line_id' => $credit_id )->json_is( '/patron_id' => $patron_id );
339
        ->status_is(200)
340
        ->json_is( '/account_line_id' => $credit_id )
341
        ->json_is( '/patron_id'       => $patron_id );
333
342
334
    $credit->delete();
343
    $credit->delete();
335
344
336
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/credits/$credit_id")->status_is(404)
345
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/credits/$credit_id")
337
        ->json_is( '/error_code' => 'not_found' )->json_is( '/error' => 'Credit not found' );
346
        ->status_is(404)
347
        ->json_is( '/error_code' => 'not_found' )
348
        ->json_is( '/error'      => 'Credit not found' );
338
349
339
    my $deleted_patron    = $builder->build_object( { class => 'Koha::Patrons' } );
350
    my $deleted_patron    = $builder->build_object( { class => 'Koha::Patrons' } );
340
    my $deleted_patron_id = $deleted_patron->id;
351
    my $deleted_patron_id = $deleted_patron->id;
341
    $deleted_patron->delete();
352
    $deleted_patron->delete();
342
353
343
    $t->get_ok("//$userid:$password@/api/v1/patrons/$deleted_patron_id/account/credits/$credit_id")->status_is(404)
354
    $t->get_ok("//$userid:$password@/api/v1/patrons/$deleted_patron_id/account/credits/$credit_id")
344
        ->json_is( '/error_code' => 'not_found' )->json_is( '/error' => 'Patron not found' );
355
        ->status_is(404)
356
        ->json_is( '/error_code' => 'not_found' )
357
        ->json_is( '/error'      => 'Patron not found' );
345
358
346
    $schema->storage->txn_rollback;
359
    $schema->storage->txn_rollback;
347
};
360
};
Lines 413-432 subtest 'get_debit() tests' => sub { Link Here
413
    );
426
    );
414
    my $debit_id = $debit->id;
427
    my $debit_id = $debit->id;
415
428
416
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/debits/$debit_id")->status_is(200)
429
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/debits/$debit_id")
417
        ->json_is( '/account_line_id' => $debit_id )->json_is( '/patron_id' => $patron_id );
430
        ->status_is(200)
431
        ->json_is( '/account_line_id' => $debit_id )
432
        ->json_is( '/patron_id'       => $patron_id );
418
433
419
    $debit->delete();
434
    $debit->delete();
420
435
421
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/debits/$debit_id")->status_is(404)
436
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/debits/$debit_id")
422
        ->json_is( '/error_code' => 'not_found' )->json_is( '/error' => 'Debit not found' );
437
        ->status_is(404)
438
        ->json_is( '/error_code' => 'not_found' )
439
        ->json_is( '/error'      => 'Debit not found' );
423
440
424
    my $deleted_patron    = $builder->build_object( { class => 'Koha::Patrons' } );
441
    my $deleted_patron    = $builder->build_object( { class => 'Koha::Patrons' } );
425
    my $deleted_patron_id = $deleted_patron->id;
442
    my $deleted_patron_id = $deleted_patron->id;
426
    $deleted_patron->delete();
443
    $deleted_patron->delete();
427
444
428
    $t->get_ok("//$userid:$password@/api/v1/patrons/$deleted_patron_id/account/debits/$debit_id")->status_is(404)
445
    $t->get_ok("//$userid:$password@/api/v1/patrons/$deleted_patron_id/account/debits/$debit_id")
429
        ->json_is( '/error_code' => 'not_found' )->json_is( '/error' => 'Patron not found' );
446
        ->status_is(404)
447
        ->json_is( '/error_code' => 'not_found' )
448
        ->json_is( '/error'      => 'Patron not found' );
430
449
431
    $schema->storage->txn_rollback;
450
    $schema->storage->txn_rollback;
432
};
451
};
Lines 513-520 subtest 'add_debit() tests' => sub { Link Here
513
        library_id  => $library->id,
532
        library_id  => $library->id,
514
    };
533
    };
515
534
516
    my $ret = $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $debit )
535
    my $ret =
517
        ->status_is(201)->json_is( '/user_id' => $librarian_x->id, 'Passed user_id is stored' )->tx->res->json;
536
        $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $debit )
537
        ->status_is(201)
538
        ->json_is( '/user_id' => $librarian_x->id, 'Passed user_id is stored' )
539
        ->tx->res->json;
518
    my $account_line = Koha::Account::Debits->find( $ret->{account_line_id} );
540
    my $account_line = Koha::Account::Debits->find( $ret->{account_line_id} );
519
541
520
    is_deeply( $ret, $account_line->to_api, 'Line returned correctly' );
542
    is_deeply( $ret, $account_line->to_api, 'Line returned correctly' );
Lines 549-555 subtest 'add_debit() tests' => sub { Link Here
549
571
550
    my $account_line_id = $ret->{account_line_id};
572
    my $account_line_id = $ret->{account_line_id};
551
573
552
    $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $debit )->status_is(201)
574
    $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $debit )
575
        ->status_is(201)
553
        ->header_is(
576
        ->header_is(
554
        'Location' => "/api/v1/patrons/$patron_id/account/debits/" . $t->tx->res->json->{account_line_id},
577
        'Location' => "/api/v1/patrons/$patron_id/account/debits/" . $t->tx->res->json->{account_line_id},
555
        "REST3.4.1"
578
        "REST3.4.1"
Lines 571-583 subtest 'add_debit() tests' => sub { Link Here
571
        library_id  => $library->id,
594
        library_id  => $library->id,
572
    };
595
    };
573
596
574
    $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $payout )->status_is(400)
597
    $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $payout )
598
        ->status_is(400)
575
        ->json_is( '/error' => 'Account transaction requires a cash register' );
599
        ->json_is( '/error' => 'Account transaction requires a cash register' );
576
600
577
    my $register = $builder->build_object( { class => 'Koha::Cash::Registers', } );
601
    my $register = $builder->build_object( { class => 'Koha::Cash::Registers', } );
578
    $payout->{cash_register_id} = $register->id;
602
    $payout->{cash_register_id} = $register->id;
579
    my $res = $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $payout )
603
    my $res =
580
        ->status_is(201)->tx->res->json;
604
        $t->post_ok( "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" => json => $payout )
605
        ->status_is(201)
606
        ->tx->res->json;
581
607
582
    is( $res->{user_id}, $librarian->id, 'If not passed, the session user ID is picked' );
608
    is( $res->{user_id}, $librarian->id, 'If not passed, the session user ID is picked' );
583
609
(-)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_hold_groups.t (-6 / +12 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 . '/hold_groups' )->status_is( 200, 'REST3.2.2' )
53
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/hold_groups' )
54
        ->status_is( 200, 'REST3.2.2' )
54
        ->json_is( [] );
55
        ->json_is( [] );
55
56
56
    my $hold_group_1 = $builder->build_object(
57
    my $hold_group_1 = $builder->build_object(
Lines 79-85 subtest 'list() tests' => sub { Link Here
79
    );
80
    );
80
81
81
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/hold_groups' => { 'x-koha-embed' => 'holds' } )
82
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/hold_groups' => { 'x-koha-embed' => 'holds' } )
82
        ->status_is( 200, 'REST3.2.2' )->json_has( "/0/holds", "holds object correctly embedded" );
83
        ->status_is( 200, 'REST3.2.2' )
84
        ->json_has( "/0/holds", "holds object correctly embedded" );
83
85
84
    $schema->storage->txn_rollback;
86
    $schema->storage->txn_rollback;
85
};
87
};
Lines 133-139 subtest 'add() tests' => sub { Link Here
133
135
134
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
136
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
135
            . $other_patron->id
137
            . $other_patron->id
136
            . "/hold_groups" => json => { hold_ids => [ $hold_3->reserve_id ] } )->status_is( 400, 'REST3.2.1' )
138
            . "/hold_groups" => json => { hold_ids => [ $hold_3->reserve_id ] } )
139
        ->status_is( 400, 'REST3.2.1' )
137
        ->json_is(
140
        ->json_is(
138
        {
141
        {
139
            error      => 'One or more holds have already been found: ' . $hold_3->item->barcode,
142
            error      => 'One or more holds have already been found: ' . $hold_3->item->barcode,
Lines 143-149 subtest 'add() tests' => sub { Link Here
143
146
144
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
147
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
145
            . $patron->id
148
            . $patron->id
146
            . "/hold_groups" => json => { hold_ids => [ $hold_3->reserve_id ] } )->status_is( 400, 'REST3.2.1' )
149
            . "/hold_groups" => json => { hold_ids => [ $hold_3->reserve_id ] } )
150
        ->status_is( 400, 'REST3.2.1' )
147
        ->json_is(
151
        ->json_is(
148
        {
152
        {
149
            error      => 'One or more holds do not belong to patron: ' . $hold_3->reserve_id,
153
            error      => 'One or more holds do not belong to patron: ' . $hold_3->reserve_id,
Lines 154-165 subtest 'add() tests' => sub { Link Here
154
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
158
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
155
            . $patron->id
159
            . $patron->id
156
            . "/hold_groups" => json => { hold_ids => [ $hold_1->reserve_id, $hold_2->reserve_id ] } )
160
            . "/hold_groups" => json => { hold_ids => [ $hold_1->reserve_id, $hold_2->reserve_id ] } )
157
        ->status_is( 201, 'REST3.2.1' )->json_has( "/holds", "holds object correctly embedded" );
161
        ->status_is( 201, 'REST3.2.1' )
162
        ->json_has( "/holds", "holds object correctly embedded" );
158
163
159
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
164
    $t->post_ok( "//$userid:$password@/api/v1/patrons/"
160
            . $patron->id
165
            . $patron->id
161
            . "/hold_groups" => json => { hold_ids => [ $hold_1->reserve_id, $hold_2->reserve_id ] } )
166
            . "/hold_groups" => json => { hold_ids => [ $hold_1->reserve_id, $hold_2->reserve_id ] } )
162
        ->status_is( 400, 'REST3.2.1' )->json_is(
167
        ->status_is( 400, 'REST3.2.1' )
168
        ->json_is(
163
        {
169
        {
164
                  error => "One or more holds already belong to a hold group: "
170
                  error => "One or more holds already belong to a hold group: "
165
                . $hold_1->reserve_id . ", "
171
                . $hold_1->reserve_id . ", "
(-)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(
57
    my $hold_1 = $builder->build_object(
Lines 68-74 subtest 'list() tests' => sub { Link Here
68
    $hold_3->fill;
69
    $hold_3->fill;
69
70
70
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?_order_by=+me.hold_id' )
71
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?_order_by=+me.hold_id' )
71
        ->status_is( 200, 'REST3.2.2' )->json_is( '' => [ $hold_2->to_api ], 'Only current holds retrieved' );
72
        ->status_is( 200, 'REST3.2.2' )
73
        ->json_is( '' => [ $hold_2->to_api ], 'Only current holds retrieved' );
72
74
73
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?old=1&_order_by=+me.hold_id' )
75
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?old=1&_order_by=+me.hold_id' )
74
        ->status_is( 200, 'REST3.2.2' )
76
        ->status_is( 200, 'REST3.2.2' )
Lines 79-92 subtest 'list() tests' => sub { Link Here
79
    $old_hold_1->pickup_library->delete;
81
    $old_hold_1->pickup_library->delete;
80
82
81
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?old=1&_order_by=+me.hold_id' )
83
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?old=1&_order_by=+me.hold_id' )
82
        ->status_is( 200, 'REST3.2.2' )->json_is(
84
        ->status_is( 200, 'REST3.2.2' )
85
        ->json_is(
83
        '' => [ $old_hold_1->get_from_storage->to_api, $hold_3->to_api ],
86
        '' => [ $old_hold_1->get_from_storage->to_api, $hold_3->to_api ],
84
        'Old holds even after item and library removed'
87
        'Old holds even after item and library removed'
85
        );
88
        );
86
89
87
    $old_hold_1->biblio->delete;
90
    $old_hold_1->biblio->delete;
88
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?old=1&_order_by=+me.hold_id' )
91
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id . '/holds?old=1&_order_by=+me.hold_id' )
89
        ->status_is( 200, 'REST3.2.2' )->json_is(
92
        ->status_is( 200, 'REST3.2.2' )
93
        ->json_is(
90
        '' => [ $old_hold_1->get_from_storage->to_api, $hold_3->to_api ],
94
        '' => [ $old_hold_1->get_from_storage->to_api, $hold_3->to_api ],
91
        'Old holds even after biblio removed'
95
        'Old holds even after biblio removed'
92
        );
96
        );
Lines 97-103 subtest 'list() tests' => sub { Link Here
97
    # get rid of the patron
101
    # get rid of the patron
98
    $non_existent_patron->delete;
102
    $non_existent_patron->delete;
99
103
100
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $non_existent_patron_id . '/holds' )->status_is(404)
104
    $t->get_ok( "//$userid:$password@/api/v1/patrons/" . $non_existent_patron_id . '/holds' )
105
        ->status_is(404)
101
        ->json_is( '/error' => 'Patron not found' );
106
        ->json_is( '/error' => 'Patron not found' );
102
107
103
    $schema->storage->txn_rollback;
108
    $schema->storage->txn_rollback;
Lines 125-131 subtest 'delete_public() tests' => sub { Link Here
125
    my $deleted_hold_id = $hold_to_delete->id;
130
    my $deleted_hold_id = $hold_to_delete->id;
126
    $hold_to_delete->delete;
131
    $hold_to_delete->delete;
127
132
128
    $t->delete_ok( "/api/v1/public/patrons/" . $patron->id . '/holds/' . $deleted_hold_id )->status_is(401)
133
    $t->delete_ok( "/api/v1/public/patrons/" . $patron->id . '/holds/' . $deleted_hold_id )
134
        ->status_is(401)
129
        ->json_is( { error => 'Authentication failure.' } );
135
        ->json_is( { error => 'Authentication failure.' } );
130
136
131
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/" . $patron->id . '/holds/' . $deleted_hold_id )
137
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/" . $patron->id . '/holds/' . $deleted_hold_id )
Lines 154-160 subtest 'delete_public() tests' => sub { Link Here
154
    );
160
    );
155
161
156
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/" . $patron->id . '/holds/' . $non_waiting_hold->id )
162
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/" . $patron->id . '/holds/' . $non_waiting_hold->id )
157
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
163
        ->status_is( 204, 'REST3.2.4' )
164
        ->content_is( '', 'REST3.3.4' );
158
165
159
    my $cancellation_requestable;
166
    my $cancellation_requestable;
160
167
Lines 176-182 subtest 'delete_public() tests' => sub { Link Here
176
    $cancellation_requestable = 0;
183
    $cancellation_requestable = 0;
177
184
178
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/" . $patron->id . '/holds/' . $waiting_hold->id )
185
    $t->delete_ok( "//$userid:$password@/api/v1/public/patrons/" . $patron->id . '/holds/' . $waiting_hold->id )
179
        ->status_is(403)->json_is( { error => 'Cancellation forbidden' } );
186
        ->status_is(403)
187
        ->json_is( { error => 'Cancellation forbidden' } );
180
188
181
    $cancellation_requestable = 1;
189
    $cancellation_requestable = 1;
182
190
(-)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/sip2_accounts.t (-14 / +28 lines)
Lines 87-98 subtest 'list() tests' => sub { Link Here
87
87
88
    # Filtering works, single account with queried sip_account_id
88
    # Filtering works, single account with queried sip_account_id
89
    $t->get_ok( "//$userid:$password@/api/v1/sip2/accounts?sip_account_id=" . $another_account->sip_account_id )
89
    $t->get_ok( "//$userid:$password@/api/v1/sip2/accounts?sip_account_id=" . $another_account->sip_account_id )
90
        ->status_is(200)->json_is( [ $another_account->to_api ] );
90
        ->status_is(200)
91
        ->json_is( [ $another_account->to_api ] );
91
92
92
    # Attempt to search by login_id like 'ko'
93
    # Attempt to search by login_id like 'ko'
93
    $account->delete;
94
    $account->delete;
94
    $another_account->delete;
95
    $another_account->delete;
95
    $t->get_ok(qq~//$userid:$password@/api/v1/sip2/accounts?q=[{"me.login_id":{"like":"%ko%"}}]~)->status_is(200)
96
    $t->get_ok(qq~//$userid:$password@/api/v1/sip2/accounts?q=[{"me.login_id":{"like":"%ko%"}}]~)
97
        ->status_is(200)
96
        ->json_is( [] );
98
        ->json_is( [] );
97
99
98
    my $account_to_search = $builder->build_object(
100
    my $account_to_search = $builder->build_object(
Lines 105-115 subtest 'list() tests' => sub { Link Here
105
    );
107
    );
106
108
107
    # Search works, searching for login_id like 'ko'
109
    # Search works, searching for login_id like 'ko'
108
    $t->get_ok(qq~//$userid:$password@/api/v1/sip2/accounts?q=[{"me.login_id":{"like":"%ko%"}}]~)->status_is(200)
110
    $t->get_ok(qq~//$userid:$password@/api/v1/sip2/accounts?q=[{"me.login_id":{"like":"%ko%"}}]~)
111
        ->status_is(200)
109
        ->json_is( [ $account_to_search->to_api ] );
112
        ->json_is( [ $account_to_search->to_api ] );
110
113
111
    # Warn on unsupported query parameter
114
    # Warn on unsupported query parameter
112
    $t->get_ok("//$userid:$password@/api/v1/sip2/accounts?blah=blah")->status_is(400)
115
    $t->get_ok("//$userid:$password@/api/v1/sip2/accounts?blah=blah")
116
        ->status_is(400)
113
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
117
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
114
118
115
    # Unauthorized access
119
    # Unauthorized access
Lines 146-152 subtest 'get() tests' => sub { Link Here
146
    my $unauth_userid = $patron->userid;
150
    my $unauth_userid = $patron->userid;
147
151
148
    # This account exists, should get returned
152
    # This account exists, should get returned
149
    $t->get_ok( "//$userid:$password@/api/v1/sip2/accounts/" . $account->sip_account_id )->status_is(200)
153
    $t->get_ok( "//$userid:$password@/api/v1/sip2/accounts/" . $account->sip_account_id )
154
        ->status_is(200)
150
        ->json_is( $account->to_api );
155
        ->json_is( $account->to_api );
151
156
152
    # Unauthorized access
157
    # Unauthorized access
Lines 157-163 subtest 'get() tests' => sub { Link Here
157
    my $non_existent_id   = $account_to_delete->sip_account_id;
162
    my $non_existent_id   = $account_to_delete->sip_account_id;
158
    $account_to_delete->delete;
163
    $account_to_delete->delete;
159
164
160
    $t->get_ok("//$userid:$password@/api/v1/sip2/accounts/$non_existent_id")->status_is(404)
165
    $t->get_ok("//$userid:$password@/api/v1/sip2/accounts/$non_existent_id")
166
        ->status_is(404)
161
        ->json_is( '/error' => 'Account not found' );
167
        ->json_is( '/error' => 'Account not found' );
162
168
163
    $schema->storage->txn_rollback;
169
    $schema->storage->txn_rollback;
Lines 205-211 subtest 'add() tests' => sub { Link Here
205
        sip_institution_id => $account->{sip_institution_id},
211
        sip_institution_id => $account->{sip_institution_id},
206
    };
212
    };
207
213
208
    $t->post_ok( "//$userid:$password@/api/v1/sip2/accounts" => json => $account_with_invalid_field )->status_is(400)
214
    $t->post_ok( "//$userid:$password@/api/v1/sip2/accounts" => json => $account_with_invalid_field )
215
        ->status_is(400)
209
        ->json_is(
216
        ->json_is(
210
        "/errors" => [
217
        "/errors" => [
211
            {
218
            {
Lines 217-228 subtest 'add() tests' => sub { Link Here
217
224
218
    # Authorized attempt to write
225
    # Authorized attempt to write
219
    my $sip_account_id =
226
    my $sip_account_id =
220
        $t->post_ok( "//$userid:$password@/api/v1/sip2/accounts" => json => $account )->status_is( 201, 'REST3.2.1' )
227
        $t->post_ok( "//$userid:$password@/api/v1/sip2/accounts" => json => $account )
228
        ->status_is( 201, 'REST3.2.1' )
221
        ->header_like(
229
        ->header_like(
222
        Location => qr|^/api/v1/sip2/accounts/\d*|,
230
        Location => qr|^/api/v1/sip2/accounts/\d*|,
223
        'REST3.4.1'
231
        'REST3.4.1'
224
    )->json_is( '/login_id' => $account->{login_id} )
232
        )
225
        ->json_is( '/sip_institution_id' => $account->{sip_institution_id} )->tx->res->json->{sip_account_id};
233
        ->json_is( '/login_id'           => $account->{login_id} )
234
        ->json_is( '/sip_institution_id' => $account->{sip_institution_id} )
235
        ->tx->res->json->{sip_account_id};
226
236
227
    # Authorized attempt to create with null id
237
    # Authorized attempt to create with null id
228
    $account->{sip_account_id} = undef;
238
    $account->{sip_account_id} = undef;
Lines 283-289 subtest 'update() tests' => sub { Link Here
283
    };
293
    };
284
294
285
    $t->put_ok( "//$userid:$password@/api/v1/sip2/accounts/$sip_account_id" => json => $account_with_missing_field )
295
    $t->put_ok( "//$userid:$password@/api/v1/sip2/accounts/$sip_account_id" => json => $account_with_missing_field )
286
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/login_id" } ] );
296
        ->status_is(400)
297
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/login_id" } ] );
287
298
288
    # Full object update on PUT
299
    # Full object update on PUT
289
    my $account_with_updated_field = {
300
    my $account_with_updated_field = {
Lines 292-298 subtest 'update() tests' => sub { Link Here
292
    };
303
    };
293
304
294
    $t->put_ok( "//$userid:$password@/api/v1/sip2/accounts/$sip_account_id" => json => $account_with_updated_field )
305
    $t->put_ok( "//$userid:$password@/api/v1/sip2/accounts/$sip_account_id" => json => $account_with_updated_field )
295
        ->status_is(200)->json_is( '/login_id' => 'new koha' );
306
        ->status_is(200)
307
        ->json_is( '/login_id' => 'new koha' );
296
308
297
    # Authorized attempt to write invalid data
309
    # Authorized attempt to write invalid data
298
    my $account_with_invalid_field = {
310
    my $account_with_invalid_field = {
Lines 302-308 subtest 'update() tests' => sub { Link Here
302
    };
314
    };
303
315
304
    $t->put_ok( "//$userid:$password@/api/v1/sip2/accounts/$sip_account_id" => json => $account_with_invalid_field )
316
    $t->put_ok( "//$userid:$password@/api/v1/sip2/accounts/$sip_account_id" => json => $account_with_invalid_field )
305
        ->status_is(400)->json_is(
317
        ->status_is(400)
318
        ->json_is(
306
        "/errors" => [
319
        "/errors" => [
307
            {
320
            {
308
                message => "Properties not allowed: blah.",
321
                message => "Properties not allowed: blah.",
Lines 360-366 subtest 'delete() tests' => sub { Link Here
360
    $t->delete_ok("//$unauth_userid:$password@/api/v1/sip2/accounts/$sip_account_id")->status_is(403);
373
    $t->delete_ok("//$unauth_userid:$password@/api/v1/sip2/accounts/$sip_account_id")->status_is(403);
361
374
362
    # Delete existing account
375
    # Delete existing account
363
    $t->delete_ok("//$userid:$password@/api/v1/sip2/accounts/$sip_account_id")->status_is( 204, 'REST3.2.4' )
376
    $t->delete_ok("//$userid:$password@/api/v1/sip2/accounts/$sip_account_id")
377
        ->status_is( 204, 'REST3.2.4' )
364
        ->content_is( '', 'REST3.3.4' );
378
        ->content_is( '', 'REST3.3.4' );
365
379
366
    # Attempt to delete non-existent account
380
    # Attempt to delete non-existent account
(-)a/t/db_dependent/api/v1/sip2_institutions.t (-15 / +31 lines)
Lines 86-98 subtest 'list() tests' => sub { Link Here
86
    );
86
    );
87
87
88
    # Filtering works, single institution with queried implementation
88
    # Filtering works, single institution with queried implementation
89
    $t->get_ok("//$userid:$password@/api/v1/sip2/institutions?implementation=ILS")->status_is(200)
89
    $t->get_ok("//$userid:$password@/api/v1/sip2/institutions?implementation=ILS")
90
        ->status_is(200)
90
        ->json_is( [ $another_institution->to_api ] );
91
        ->json_is( [ $another_institution->to_api ] );
91
92
92
    # Attempt to search by name like 'ko'
93
    # Attempt to search by name like 'ko'
93
    $institution->delete;
94
    $institution->delete;
94
    $another_institution->delete;
95
    $another_institution->delete;
95
    $t->get_ok(qq~//$userid:$password@/api/v1/sip2/institutions?q=[{"me.name":{"like":"%ko%"}}]~)->status_is(200)
96
    $t->get_ok(qq~//$userid:$password@/api/v1/sip2/institutions?q=[{"me.name":{"like":"%ko%"}}]~)
97
        ->status_is(200)
96
        ->json_is( [] );
98
        ->json_is( [] );
97
99
98
    my $institution_to_search = $builder->build_object(
100
    my $institution_to_search = $builder->build_object(
Lines 105-115 subtest 'list() tests' => sub { Link Here
105
    );
107
    );
106
108
107
    # Search works, searching for name like 'ko'
109
    # Search works, searching for name like 'ko'
108
    $t->get_ok(qq~//$userid:$password@/api/v1/sip2/institutions?q=[{"me.name":{"like":"%ko%"}}]~)->status_is(200)
110
    $t->get_ok(qq~//$userid:$password@/api/v1/sip2/institutions?q=[{"me.name":{"like":"%ko%"}}]~)
111
        ->status_is(200)
109
        ->json_is( [ $institution_to_search->to_api ] );
112
        ->json_is( [ $institution_to_search->to_api ] );
110
113
111
    # Warn on unsupported query parameter
114
    # Warn on unsupported query parameter
112
    $t->get_ok("//$userid:$password@/api/v1/sip2/institutions?blah=blah")->status_is(400)
115
    $t->get_ok("//$userid:$password@/api/v1/sip2/institutions?blah=blah")
116
        ->status_is(400)
113
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
117
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
114
118
115
    # Unauthorized access
119
    # Unauthorized access
Lines 146-152 subtest 'get() tests' => sub { Link Here
146
    my $unauth_userid = $patron->userid;
150
    my $unauth_userid = $patron->userid;
147
151
148
    # This institution exists, should get returned
152
    # This institution exists, should get returned
149
    $t->get_ok( "//$userid:$password@/api/v1/sip2/institutions/" . $institution->sip_institution_id )->status_is(200)
153
    $t->get_ok( "//$userid:$password@/api/v1/sip2/institutions/" . $institution->sip_institution_id )
154
        ->status_is(200)
150
        ->json_is( $institution->to_api );
155
        ->json_is( $institution->to_api );
151
156
152
    # Unauthorized access
157
    # Unauthorized access
Lines 158-164 subtest 'get() tests' => sub { Link Here
158
    my $non_existent_id       = $institution_to_delete->sip_institution_id;
163
    my $non_existent_id       = $institution_to_delete->sip_institution_id;
159
    $institution_to_delete->delete;
164
    $institution_to_delete->delete;
160
165
161
    $t->get_ok("//$userid:$password@/api/v1/sip2/institutions/$non_existent_id")->status_is(404)
166
    $t->get_ok("//$userid:$password@/api/v1/sip2/institutions/$non_existent_id")
167
        ->status_is(404)
162
        ->json_is( '/error' => 'Institution not found' );
168
        ->json_is( '/error' => 'Institution not found' );
163
169
164
    $schema->storage->txn_rollback;
170
    $schema->storage->txn_rollback;
Lines 210-216 subtest 'add() tests' => sub { Link Here
210
    };
216
    };
211
217
212
    $t->post_ok( "//$userid:$password@/api/v1/sip2/institutions" => json => $institution_with_invalid_field )
218
    $t->post_ok( "//$userid:$password@/api/v1/sip2/institutions" => json => $institution_with_invalid_field )
213
        ->status_is(400)->json_is(
219
        ->status_is(400)
220
        ->json_is(
214
        "/errors" => [
221
        "/errors" => [
215
            {
222
            {
216
                message => "Properties not allowed: blah.",
223
                message => "Properties not allowed: blah.",
Lines 222-237 subtest 'add() tests' => sub { Link Here
222
    # Authorized attempt to write
229
    # Authorized attempt to write
223
    my $sip_institution_id =
230
    my $sip_institution_id =
224
        $t->post_ok( "//$userid:$password@/api/v1/sip2/institutions" => json => $institution )
231
        $t->post_ok( "//$userid:$password@/api/v1/sip2/institutions" => json => $institution )
225
        ->status_is( 201, 'REST3.2.1' )->header_like(
232
        ->status_is( 201, 'REST3.2.1' )
233
        ->header_like(
226
        Location => qr|^/api/v1/sip2/institutions/\d*|,
234
        Location => qr|^/api/v1/sip2/institutions/\d*|,
227
        'REST3.4.1'
235
        'REST3.4.1'
228
    )->json_is( '/name' => $institution->{name} )->json_is( '/implementation' => $institution->{implementation} )
236
        )
229
        ->json_is( '/retries' => $institution->{retries} )->json_is( '/timeout' => $institution->{timeout} )
237
        ->json_is( '/name'           => $institution->{name} )
238
        ->json_is( '/implementation' => $institution->{implementation} )
239
        ->json_is( '/retries'        => $institution->{retries} )
240
        ->json_is( '/timeout'        => $institution->{timeout} )
230
        ->tx->res->json->{sip_institution_id};
241
        ->tx->res->json->{sip_institution_id};
231
242
232
    # Authorized attempt to create with null id
243
    # Authorized attempt to create with null id
233
    $institution->{sip_institution_id} = undef;
244
    $institution->{sip_institution_id} = undef;
234
    $t->post_ok( "//$userid:$password@/api/v1/sip2/institutions" => json => $institution )->status_is(400)
245
    $t->post_ok( "//$userid:$password@/api/v1/sip2/institutions" => json => $institution )
246
        ->status_is(400)
235
        ->json_has('/errors');
247
        ->json_has('/errors');
236
248
237
    # Authorized attempt to create with existing id
249
    # Authorized attempt to create with existing id
Lines 290-296 subtest 'update() tests' => sub { Link Here
290
302
291
    $t->put_ok(
303
    $t->put_ok(
292
        "//$userid:$password@/api/v1/sip2/institutions/$sip_institution_id" => json => $institution_with_missing_field )
304
        "//$userid:$password@/api/v1/sip2/institutions/$sip_institution_id" => json => $institution_with_missing_field )
293
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
305
        ->status_is(400)
306
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
294
307
295
    # Full object update on PUT
308
    # Full object update on PUT
296
    my $institution_with_updated_field = {
309
    my $institution_with_updated_field = {
Lines 302-308 subtest 'update() tests' => sub { Link Here
302
315
303
    $t->put_ok(
316
    $t->put_ok(
304
        "//$userid:$password@/api/v1/sip2/institutions/$sip_institution_id" => json => $institution_with_updated_field )
317
        "//$userid:$password@/api/v1/sip2/institutions/$sip_institution_id" => json => $institution_with_updated_field )
305
        ->status_is(200)->json_is( '/name' => 'New institution name' );
318
        ->status_is(200)
319
        ->json_is( '/name' => 'New institution name' );
306
320
307
    # Authorized attempt to write invalid data
321
    # Authorized attempt to write invalid data
308
    my $institution_with_invalid_field = {
322
    my $institution_with_invalid_field = {
Lines 315-321 subtest 'update() tests' => sub { Link Here
315
329
316
    $t->put_ok(
330
    $t->put_ok(
317
        "//$userid:$password@/api/v1/sip2/institutions/$sip_institution_id" => json => $institution_with_invalid_field )
331
        "//$userid:$password@/api/v1/sip2/institutions/$sip_institution_id" => json => $institution_with_invalid_field )
318
        ->status_is(400)->json_is(
332
        ->status_is(400)
333
        ->json_is(
319
        "/errors" => [
334
        "/errors" => [
320
            {
335
            {
321
                message => "Properties not allowed: blah.",
336
                message => "Properties not allowed: blah.",
Lines 375-381 subtest 'delete() tests' => sub { Link Here
375
    $t->delete_ok("//$unauth_userid:$password@/api/v1/sip2/institutions/$sip_institution_id")->status_is(403);
390
    $t->delete_ok("//$unauth_userid:$password@/api/v1/sip2/institutions/$sip_institution_id")->status_is(403);
376
391
377
    # Delete existing institution
392
    # Delete existing institution
378
    $t->delete_ok("//$userid:$password@/api/v1/sip2/institutions/$sip_institution_id")->status_is( 204, 'REST3.2.4' )
393
    $t->delete_ok("//$userid:$password@/api/v1/sip2/institutions/$sip_institution_id")
394
        ->status_is( 204, 'REST3.2.4' )
379
        ->content_is( '', 'REST3.3.4' );
395
        ->content_is( '', 'REST3.3.4' );
380
396
381
    # Attempt to delete non-existent institution
397
    # Attempt to delete non-existent institution
(-)a/t/db_dependent/api/v1/sip2_system_preference_overrides.t (-13 / +26 lines)
Lines 68-74 subtest 'list() tests' => sub { Link Here
68
    my $sys_pref_override = $builder->build_object( { class => 'Koha::SIP2::SystemPreferenceOverrides' } );
68
    my $sys_pref_override = $builder->build_object( { class => 'Koha::SIP2::SystemPreferenceOverrides' } );
69
69
70
    # One system preference override created, should get returned
70
    # One system preference override created, should get returned
71
    $t->get_ok("//$userid:$password@/api/v1/sip2/system_preference_overrides")->status_is(200)
71
    $t->get_ok("//$userid:$password@/api/v1/sip2/system_preference_overrides")
72
        ->status_is(200)
72
        ->json_is( [ $sys_pref_override->to_api ] );
73
        ->json_is( [ $sys_pref_override->to_api ] );
73
74
74
    my $another_system_preference_override = $builder->build_object(
75
    my $another_system_preference_override = $builder->build_object(
Lines 90-96 subtest 'list() tests' => sub { Link Here
90
    $sys_pref_override->delete;
91
    $sys_pref_override->delete;
91
    $another_system_preference_override->delete;
92
    $another_system_preference_override->delete;
92
    $t->get_ok(qq~//$userid:$password@/api/v1/sip2/system_preference_overrides?q=[{"me.variable":{"like":"%ko%"}}]~)
93
    $t->get_ok(qq~//$userid:$password@/api/v1/sip2/system_preference_overrides?q=[{"me.variable":{"like":"%ko%"}}]~)
93
        ->status_is(200)->json_is( [] );
94
        ->status_is(200)
95
        ->json_is( [] );
94
96
95
    my $system_preference_override_to_search = $builder->build_object(
97
    my $system_preference_override_to_search = $builder->build_object(
96
        {
98
        {
Lines 103-112 subtest 'list() tests' => sub { Link Here
103
105
104
    # Search works, searching for name like 'ko'
106
    # Search works, searching for name like 'ko'
105
    $t->get_ok(qq~//$userid:$password@/api/v1/sip2/system_preference_overrides?q=[{"me.variable":{"like":"%ko%"}}]~)
107
    $t->get_ok(qq~//$userid:$password@/api/v1/sip2/system_preference_overrides?q=[{"me.variable":{"like":"%ko%"}}]~)
106
        ->status_is(200)->json_is( [ $system_preference_override_to_search->to_api ] );
108
        ->status_is(200)
109
        ->json_is( [ $system_preference_override_to_search->to_api ] );
107
110
108
    # Warn on unsupported query parameter
111
    # Warn on unsupported query parameter
109
    $t->get_ok("//$userid:$password@/api/v1/sip2/system_preference_overrides?blah=blah")->status_is(400)
112
    $t->get_ok("//$userid:$password@/api/v1/sip2/system_preference_overrides?blah=blah")
113
        ->status_is(400)
110
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
114
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
111
115
112
    # Unauthorized access
116
    # Unauthorized access
Lines 144-150 subtest 'get() tests' => sub { Link Here
144
148
145
    # This system preference override exists, should get returned
149
    # This system preference override exists, should get returned
146
    $t->get_ok( "//$userid:$password@/api/v1/sip2/system_preference_overrides/"
150
    $t->get_ok( "//$userid:$password@/api/v1/sip2/system_preference_overrides/"
147
            . $sys_pref_override->sip_system_preference_override_id )->status_is(200)
151
            . $sys_pref_override->sip_system_preference_override_id )
152
        ->status_is(200)
148
        ->json_is( $sys_pref_override->to_api );
153
        ->json_is( $sys_pref_override->to_api );
149
154
150
    # Unauthorized access
155
    # Unauthorized access
Lines 157-163 subtest 'get() tests' => sub { Link Here
157
    my $non_existent_id = $system_preference_override_to_delete->sip_system_preference_override_id;
162
    my $non_existent_id = $system_preference_override_to_delete->sip_system_preference_override_id;
158
    $system_preference_override_to_delete->delete;
163
    $system_preference_override_to_delete->delete;
159
164
160
    $t->get_ok("//$userid:$password@/api/v1/sip2/system_preference_overrides/$non_existent_id")->status_is(404)
165
    $t->get_ok("//$userid:$password@/api/v1/sip2/system_preference_overrides/$non_existent_id")
166
        ->status_is(404)
161
        ->json_is( '/error' => 'System preference override not found' );
167
        ->json_is( '/error' => 'System preference override not found' );
162
168
163
    $schema->storage->txn_rollback;
169
    $schema->storage->txn_rollback;
Lines 218-241 subtest 'add() tests' => sub { Link Here
218
    # Authorized attempt to write
224
    # Authorized attempt to write
219
    my $sip_system_preference_override_id =
225
    my $sip_system_preference_override_id =
220
        $t->post_ok( "//$userid:$password@/api/v1/sip2/system_preference_overrides" => json => $sys_pref_override )
226
        $t->post_ok( "//$userid:$password@/api/v1/sip2/system_preference_overrides" => json => $sys_pref_override )
221
        ->status_is( 201, 'REST3.2.1' )->header_like(
227
        ->status_is( 201, 'REST3.2.1' )
228
        ->header_like(
222
        Location => qr|^/api/v1/sip2/system_preference_overrides/\d*|,
229
        Location => qr|^/api/v1/sip2/system_preference_overrides/\d*|,
223
        'REST3.4.1'
230
        'REST3.4.1'
224
    )->json_is( '/name' => $sys_pref_override->{name} )
231
        )
232
        ->json_is( '/name'           => $sys_pref_override->{name} )
225
        ->json_is( '/implementation' => $sys_pref_override->{implementation} )
233
        ->json_is( '/implementation' => $sys_pref_override->{implementation} )
226
        ->json_is( '/retries'        => $sys_pref_override->{retries} )
234
        ->json_is( '/retries'        => $sys_pref_override->{retries} )
227
        ->json_is( '/timeout' => $sys_pref_override->{timeout} )->tx->res->json->{sip_system_preference_override_id};
235
        ->json_is( '/timeout'        => $sys_pref_override->{timeout} )
236
        ->tx->res->json->{sip_system_preference_override_id};
228
237
229
    # Authorized attempt to create with null id
238
    # Authorized attempt to create with null id
230
    $sys_pref_override->{sip_system_preference_override_id} = undef;
239
    $sys_pref_override->{sip_system_preference_override_id} = undef;
231
    $t->post_ok( "//$userid:$password@/api/v1/sip2/system_preference_overrides" => json => $sys_pref_override )
240
    $t->post_ok( "//$userid:$password@/api/v1/sip2/system_preference_overrides" => json => $sys_pref_override )
232
        ->status_is(400)->json_has('/errors');
241
        ->status_is(400)
242
        ->json_has('/errors');
233
243
234
    # Authorized attempt to create with existing id
244
    # Authorized attempt to create with existing id
235
    $sys_pref_override->{sip_system_preference_override_id} = $sip_system_preference_override_id;
245
    $sys_pref_override->{sip_system_preference_override_id} = $sip_system_preference_override_id;
236
246
237
    $t->post_ok( "//$userid:$password@/api/v1/sip2/system_preference_overrides" => json => $sys_pref_override )
247
    $t->post_ok( "//$userid:$password@/api/v1/sip2/system_preference_overrides" => json => $sys_pref_override )
238
        ->status_is(400)->json_is(
248
        ->status_is(400)
249
        ->json_is(
239
        "/errors" => [
250
        "/errors" => [
240
            {
251
            {
241
                message => "Read-only.",
252
                message => "Read-only.",
Lines 289-295 subtest 'update() tests' => sub { Link Here
289
300
290
    $t->put_ok(
301
    $t->put_ok(
291
        "//$userid:$password@/api/v1/sip2/system_preference_overrides/$sip_system_preference_override_id" => json =>
302
        "//$userid:$password@/api/v1/sip2/system_preference_overrides/$sip_system_preference_override_id" => json =>
292
            $system_preference_override_with_missing_field )->status_is(400)
303
            $system_preference_override_with_missing_field )
304
        ->status_is(400)
293
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/value" } ] );
305
        ->json_is( "/errors" => [ { message => "Missing property.", path => "/body/value" } ] );
294
306
295
    # Full object update on PUT
307
    # Full object update on PUT
Lines 376-382 subtest 'delete() tests' => sub { Link Here
376
388
377
    # Delete existing system preference override
389
    # Delete existing system preference override
378
    $t->delete_ok("//$userid:$password@/api/v1/sip2/system_preference_overrides/$sip_system_preference_override_id")
390
    $t->delete_ok("//$userid:$password@/api/v1/sip2/system_preference_overrides/$sip_system_preference_override_id")
379
        ->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
391
        ->status_is( 204, 'REST3.2.4' )
392
        ->content_is( '', 'REST3.3.4' );
380
393
381
    # Attempt to delete non-existent system preference override
394
    # Attempt to delete non-existent system preference override
382
    $t->delete_ok("//$userid:$password@/api/v1/sip2/system_preference_overrides/$sip_system_preference_override_id")
395
    $t->delete_ok("//$userid:$password@/api/v1/sip2/system_preference_overrides/$sip_system_preference_override_id")
(-)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