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

(-)a/Koha/REST/V1/RecordSources.pm (+141 lines)
Line 0 Link Here
1
package Koha::REST::V1::RecordSources;
2
3
# Copyright 2023 Theke Solutions
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Mojo::Base 'Mojolicious::Controller';
23
24
use Koha::RecordSources;
25
26
use Try::Tiny qw( catch try );
27
28
=head1 API
29
30
=head2 Methods
31
32
=head3 list
33
34
=cut
35
36
sub list {
37
    my $c = shift->openapi->valid_input or return;
38
39
    return try {
40
        my $sources = $c->objects->search( Koha::RecordSources->new );
41
        return $c->render( status => 200, openapi => $sources );
42
    } catch {
43
        $c->unhandled_exception($_);
44
    };
45
}
46
47
=head3 get
48
49
=cut
50
51
sub get {
52
    my $c = shift->openapi->valid_input or return;
53
54
    return try {
55
        my $source = $c->objects->find( Koha::RecordSources->new, $c->param('record_source_id') );
56
        unless ($source) {
57
            return $c->render(
58
                status  => 404,
59
                openapi => { error => "Object not found" }
60
            );
61
        }
62
63
        return $c->render( status => 200, openapi => $source );
64
    } catch {
65
        $c->unhandled_exception($_);
66
    };
67
}
68
69
=head3 add
70
71
=cut
72
73
sub add {
74
    my $c = shift->openapi->valid_input or return;
75
76
    return try {
77
        my $source = Koha::RecordSource->new_from_api( $c->req->json );
78
        $source->store;
79
        $c->res->headers->location( $c->req->url->to_string . '/' . $source->record_source_id );
80
        return $c->render(
81
            status  => 201,
82
            openapi => $c->objects->to_api($source)
83
        );
84
    } catch {
85
        $c->unhandled_exception($_);
86
    };
87
}
88
89
=head3 update
90
91
=cut
92
93
sub update {
94
    my $c = shift->openapi->valid_input or return;
95
96
    my $source = $c->objects->find_rs( Koha::RecordSources->new, $c->param('record_source_id') );
97
98
    unless ($source) {
99
        return $c->render(
100
            status  => 404,
101
            openapi => { error => "Object not found" }
102
        );
103
    }
104
105
    return try {
106
        $source->set_from_api( $c->req->json )->store;
107
        $source->discard_changes;
108
        return $c->render( status => 200, openapi => $c->objects->to_api($source) );
109
    } catch {
110
        $c->unhandled_exception($_);
111
    };
112
}
113
114
=head3 delete
115
116
=cut
117
118
sub delete {
119
    my $c = shift->openapi->valid_input or return;
120
121
    my $source = $c->objects->find_rs( Koha::RecordSources->new, $c->param('record_source_id') );
122
123
    unless ($source) {
124
        return $c->render(
125
            status  => 404,
126
            openapi => { error => "Object not found" }
127
        );
128
    }
129
130
    return try {
131
        $source->delete;
132
        return $c->render(
133
            status  => 204,
134
            openapi => q{}
135
        );
136
    } catch {
137
        $c->unhandled_exception($_);
138
    };
139
}
140
141
1;
(-)a/api/v1/swagger/definitions/record_source.yaml (+21 lines)
Line 0 Link Here
1
---
2
type: object
3
properties:
4
  record_source_id:
5
    type: integer
6
    description: internally assigned record source identifier
7
    readOnly: true
8
  name:
9
    description: record source name
10
    type: string
11
  patron_id:
12
    description: linked patron identifier
13
    type: integer
14
  api_token:
15
    description: A token for identifying record sources on API interactions
16
    type: string
17
    readOnly: true
18
additionalProperties: false
19
required:
20
  - name
21
  - patron_id
(-)a/api/v1/swagger/paths/record_sources.yaml (+256 lines)
Line 0 Link Here
1
/record_sources:
2
  get:
3
    x-mojo-to: RecordSources#list
4
    operationId: listRecordSources
5
    summary: List record sources
6
    tags:
7
      - record_sources
8
    parameters:
9
      - $ref: "../swagger.yaml#/parameters/match"
10
      - $ref: "../swagger.yaml#/parameters/order_by"
11
      - $ref: "../swagger.yaml#/parameters/page"
12
      - $ref: "../swagger.yaml#/parameters/per_page"
13
      - $ref: "../swagger.yaml#/parameters/q_param"
14
      - $ref: "../swagger.yaml#/parameters/q_body"
15
      - $ref: "../swagger.yaml#/parameters/request_id_header"
16
      - name: x-koha-embed
17
        in: header
18
        required: false
19
        description: Embed list sent as a request header
20
        type: array
21
        items:
22
          type: string
23
          enum:
24
            - patron
25
        collectionFormat: csv
26
    consumes:
27
      - application/json
28
    produces:
29
      - application/json
30
    responses:
31
      "200":
32
        description: A list of record sources
33
        schema:
34
          type: array
35
          items:
36
            $ref: "../swagger.yaml#/definitions/record_source"
37
      "400":
38
        description: Missing or wrong parameters
39
        schema:
40
          $ref: "../swagger.yaml#/definitions/error"
41
      "401":
42
        description: Authentication required
43
        schema:
44
          $ref: "../swagger.yaml#/definitions/error"
45
      "403":
46
        description: Not allowed
47
        schema:
48
          $ref: "../swagger.yaml#/definitions/error"
49
      "500":
50
        description: |
51
          Internal server error. Possible `error_code` attribute values:
52
53
          * `internal_server_error`
54
        schema:
55
          $ref: "../swagger.yaml#/definitions/error"
56
      "503":
57
        description: Under maintenance
58
        schema:
59
          $ref: "../swagger.yaml#/definitions/error"
60
    x-koha-authorization:
61
      permissions:
62
        parameters: manage_record_sources
63
  post:
64
    x-mojo-to: RecordSources#add
65
    operationId: addRecordSources
66
    summary: Add a record source
67
    tags:
68
      - record_sources
69
    parameters:
70
      - name: body
71
        in: body
72
        description: A JSON object containing informations about the new record source
73
        required: true
74
        schema:
75
          $ref: "../swagger.yaml#/definitions/record_source"
76
    consumes:
77
      - application/json
78
    produces:
79
      - application/json
80
    responses:
81
      "201":
82
        description: A record source
83
        schema:
84
          $ref: "../swagger.yaml#/definitions/record_source"
85
      "400":
86
        description: Missing or wrong parameters
87
        schema:
88
          $ref: "../swagger.yaml#/definitions/error"
89
      "401":
90
        description: Authentication required
91
        schema:
92
          $ref: "../swagger.yaml#/definitions/error"
93
      "403":
94
        description: Not allowed
95
        schema:
96
          $ref: "../swagger.yaml#/definitions/error"
97
      "500":
98
        description: |
99
          Internal server error. Possible `error_code` attribute values:
100
101
          * `internal_server_error`
102
        schema:
103
          $ref: "../swagger.yaml#/definitions/error"
104
      "503":
105
        description: Under maintenance
106
        schema:
107
          $ref: "../swagger.yaml#/definitions/error"
108
    x-koha-authorization:
109
      permissions:
110
        parameters: manage_record_sources
111
"/record_sources/{record_source_id}":
112
  get:
113
    x-mojo-to: RecordSources#get
114
    operationId: getRecordSources
115
    summary: Get a record source
116
    tags:
117
      - record_sources
118
    parameters:
119
      - $ref: "../swagger.yaml#/parameters/record_source_id_pp"
120
    consumes:
121
      - application/json
122
    produces:
123
      - application/json
124
    responses:
125
      "200":
126
        description: A record source
127
        schema:
128
          $ref: "../swagger.yaml#/definitions/record_source"
129
      "400":
130
        description: Missing or wrong parameters
131
        schema:
132
          $ref: "../swagger.yaml#/definitions/error"
133
      "401":
134
        description: Authentication required
135
        schema:
136
          $ref: "../swagger.yaml#/definitions/error"
137
      "403":
138
        description: Not allowed
139
        schema:
140
          $ref: "../swagger.yaml#/definitions/error"
141
      "404":
142
        description: Not found
143
        schema:
144
          $ref: "../swagger.yaml#/definitions/error"
145
      "500":
146
        description: |
147
          Internal server error. Possible `error_code` attribute values:
148
149
          * `internal_server_error`
150
        schema:
151
          $ref: "../swagger.yaml#/definitions/error"
152
      "503":
153
        description: Under maintenance
154
        schema:
155
          $ref: "../swagger.yaml#/definitions/error"
156
    x-koha-authorization:
157
      permissions:
158
        parameters: manage_record_sources
159
  put:
160
    x-mojo-to: RecordSources#update
161
    operationId: updateRecordSources
162
    summary: Update a record source
163
    tags:
164
      - record_sources
165
    parameters:
166
      - $ref: "../swagger.yaml#/parameters/record_source_id_pp"
167
      - name: body
168
        in: body
169
        description: A JSON object containing informations about the new record source
170
        required: true
171
        schema:
172
          $ref: "../swagger.yaml#/definitions/record_source"
173
    consumes:
174
      - application/json
175
    produces:
176
      - application/json
177
    responses:
178
      "200":
179
        description: A record source
180
        schema:
181
          $ref: "../swagger.yaml#/definitions/record_source"
182
      "400":
183
        description: Missing or wrong parameters
184
        schema:
185
          $ref: "../swagger.yaml#/definitions/error"
186
      "401":
187
        description: Authentication required
188
        schema:
189
          $ref: "../swagger.yaml#/definitions/error"
190
      "403":
191
        description: Not allowed
192
        schema:
193
          $ref: "../swagger.yaml#/definitions/error"
194
      "404":
195
        description: Not found
196
        schema:
197
          $ref: "../swagger.yaml#/definitions/error"
198
      "500":
199
        description: |
200
          Internal server error. Possible `error_code` attribute values:
201
202
          * `internal_server_error`
203
        schema:
204
          $ref: "../swagger.yaml#/definitions/error"
205
      "503":
206
        description: Under maintenance
207
        schema:
208
          $ref: "../swagger.yaml#/definitions/error"
209
    x-koha-authorization:
210
      permissions:
211
        parameters: manage_record_sources
212
  delete:
213
    x-mojo-to: RecordSources#delete
214
    operationId: deleteRecordSources
215
    summary: Delete a record source
216
    tags:
217
      - record_sources
218
    parameters:
219
      - $ref: "../swagger.yaml#/parameters/record_source_id_pp"
220
    consumes:
221
      - application/json
222
    produces:
223
      - application/json
224
    responses:
225
      "204":
226
        description: Deleted
227
      "400":
228
        description: Missing or wrong parameters
229
        schema:
230
          $ref: "../swagger.yaml#/definitions/error"
231
      "401":
232
        description: Authentication required
233
        schema:
234
          $ref: "../swagger.yaml#/definitions/error"
235
      "403":
236
        description: Not allowed
237
        schema:
238
          $ref: "../swagger.yaml#/definitions/error"
239
      "404":
240
        description: Not found
241
        schema:
242
          $ref: "../swagger.yaml#/definitions/error"
243
      "500":
244
        description: |
245
          Internal server error. Possible `error_code` attribute values:
246
247
          * `internal_server_error`
248
        schema:
249
          $ref: "../swagger.yaml#/definitions/error"
250
      "503":
251
        description: Under maintenance
252
        schema:
253
          $ref: "../swagger.yaml#/definitions/error"
254
    x-koha-authorization:
255
      permissions:
256
        parameters: manage_record_sources
(-)a/api/v1/swagger/swagger.yaml (+15 lines)
Lines 70-75 definitions: Link Here
70
    $ref: ./definitions/import_batch_profiles.yaml
70
    $ref: ./definitions/import_batch_profiles.yaml
71
  import_record_match:
71
  import_record_match:
72
    $ref: ./definitions/import_record_match.yaml
72
    $ref: ./definitions/import_record_match.yaml
73
  record_source:
74
    $ref: ./definitions/record_source.yaml
73
  invoice:
75
  invoice:
74
    $ref: ./definitions/invoice.yaml
76
    $ref: ./definitions/invoice.yaml
75
  item:
77
  item:
Lines 275-280 paths: Link Here
275
    $ref: ./paths/import_batch_profiles.yaml#/~1import_batch_profiles
277
    $ref: ./paths/import_batch_profiles.yaml#/~1import_batch_profiles
276
  "/import_batch_profiles/{import_batch_profile_id}":
278
  "/import_batch_profiles/{import_batch_profile_id}":
277
    $ref: "./paths/import_batch_profiles.yaml#/~1import_batch_profiles~1{import_batch_profile_id}"
279
    $ref: "./paths/import_batch_profiles.yaml#/~1import_batch_profiles~1{import_batch_profile_id}"
280
  /record_sources:
281
    $ref: ./paths/record_sources.yaml#/~1record_sources
282
  "/record_sources/{record_source_id}":
283
    $ref: ./paths/record_sources.yaml#/~1record_sources~1{record_source_id}
278
  /items:
284
  /items:
279
    $ref: ./paths/items.yaml#/~1items
285
    $ref: ./paths/items.yaml#/~1items
280
  "/items/{item_id}":
286
  "/items/{item_id}":
Lines 533-538 parameters: Link Here
533
    name: import_record_id
539
    name: import_record_id
534
    required: true
540
    required: true
535
    type: integer
541
    type: integer
542
  record_source_id_pp:
543
    description: Internal record source identifier
544
    in: path
545
    name: record_source_id
546
    required: true
547
    type: integer
536
  item_id_pp:
548
  item_id_pp:
537
    description: Internal item identifier
549
    description: Internal item identifier
538
    in: path
550
    in: path
Lines 860-865 tags: Link Here
860
  - description: "Manage item groups\n"
872
  - description: "Manage item groups\n"
861
    name: item_groups
873
    name: item_groups
862
    x-displayName: Item groups
874
    x-displayName: Item groups
875
  - description: "Manage record sources\n"
876
    name: record_sources
877
    x-displayName: Record source
863
  - description: "Manage items\n"
878
  - description: "Manage items\n"
864
    name: items
879
    name: items
865
    x-displayName: Items
880
    x-displayName: Items
(-)a/t/db_dependent/api/v1/record_sources.t (-1 / +303 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
# Copyright 2023 Theke Solutions
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Test::More tests => 5;
23
use Test::Mojo;
24
25
use t::lib::TestBuilder;
26
use t::lib::Mocks;
27
28
use Koha::RecordSources;
29
use Koha::Database;
30
31
my $schema  = Koha::Database->new->schema;
32
my $builder = t::lib::TestBuilder->new;
33
34
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
35
36
my $t = Test::Mojo->new('Koha::REST::V1');
37
38
subtest 'list() tests' => sub {
39
40
    plan tests => 12;
41
42
    $schema->storage->txn_begin;
43
44
    my $source = $builder->build_object( { class => 'Koha::RecordSources' } );
45
    my $patron = $builder->build_object(
46
        {
47
            class => 'Koha::Patrons',
48
            value => { flags => 3 }
49
        }
50
    );
51
52
    for ( 1 .. 10 ) {
53
        $builder->build_object( { class => 'Koha::RecordSources' } );
54
    }
55
56
    my $nonprivilegedpatron = $builder->build_object(
57
        {
58
            class => 'Koha::Patrons',
59
            value => { flags => 0 }
60
        }
61
    );
62
63
    my $password = 'thePassword123';
64
65
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
66
    my $userid = $nonprivilegedpatron->userid;
67
68
    $t->get_ok("//$userid:$password@/api/v1/record_sources")->status_is(403)
69
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
70
71
    $patron->set_password( { password => $password, skip_validation => 1 } );
72
    $userid = $patron->userid;
73
74
    $t->get_ok("//$userid:$password@/api/v1/record_sources?_per_page=10")->status_is( 200, 'SWAGGER3.2.2' );
75
76
    my $response_count = scalar @{ $t->tx->res->json };
77
78
    is( $response_count, 10, 'The API returns 10 sources' );
79
80
    my $id = $source->record_source_id;
81
    $t->get_ok("//$userid:$password@/api/v1/record_sources?q={\"record_source_id\": $id}")->status_is(200)
82
        ->json_is( '' => [ $source->to_api ], 'SWAGGER3.3.2' );
83
84
    $source->delete;
85
86
    $t->get_ok("//$userid:$password@/api/v1/record_sources?q={\"record_source_id\": $id}")->status_is(200)
87
        ->json_is( '' => [] );
88
89
    $schema->storage->txn_rollback;
90
};
91
92
subtest 'get() tests' => sub {
93
94
    plan tests => 9;
95
96
    $schema->storage->txn_begin;
97
98
    my $source = $builder->build_object( { class => 'Koha::RecordSources' } );
99
    my $patron = $builder->build_object(
100
        {
101
            class => 'Koha::Patrons',
102
            value => { flags => 3 }
103
        }
104
    );
105
106
    my $nonprivilegedpatron = $builder->build_object(
107
        {
108
            class => 'Koha::Patrons',
109
            value => { flags => 0 }
110
        }
111
    );
112
113
    my $password = 'thePassword123';
114
115
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
116
    my $userid = $nonprivilegedpatron->userid;
117
118
    my $id = $source->record_source_id;
119
120
    $t->get_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is(403)
121
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
122
123
    $patron->set_password( { password => $password, skip_validation => 1 } );
124
    $userid = $patron->userid;
125
126
    $t->get_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is( 200, 'SWAGGER3.2.2' )
127
        ->json_is( '' => $source->to_api, 'SWAGGER3.3.2' );
128
129
    $source->delete;
130
131
    $t->get_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is(404)
132
        ->json_is( '/error' => 'Object not found' );
133
134
    $schema->storage->txn_rollback;
135
};
136
137
subtest 'delete() tests' => sub {
138
139
    plan tests => 6;
140
141
    $schema->storage->txn_begin;
142
143
    my $source = $builder->build_object( { class => 'Koha::RecordSources' } );
144
    my $patron = $builder->build_object(
145
        {
146
            class => 'Koha::Patrons',
147
            value => { flags => 3 }
148
        }
149
    );
150
151
    my $nonprivilegedpatron = $builder->build_object(
152
        {
153
            class => 'Koha::Patrons',
154
            value => { flags => 0 }
155
        }
156
    );
157
158
    my $password = 'thePassword123';
159
160
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
161
    my $userid = $nonprivilegedpatron->userid;
162
163
    my $id = $source->record_source_id;
164
165
    $t->delete_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is(403)
166
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
167
168
    $patron->set_password( { password => $password, skip_validation => 1 } );
169
    $userid = $patron->userid;
170
171
    $t->delete_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is( 204, 'SWAGGER3.2.2' );
172
173
    my $deleted_source = Koha::RecordSources->search( { record_source_id => $id } );
174
175
    is( $deleted_source->count, 0, 'No record source found' );
176
177
    $schema->storage->txn_rollback;
178
};
179
180
subtest 'add() tests' => sub {
181
182
    plan tests => 8;
183
184
    $schema->storage->txn_begin;
185
186
    my $patron = $builder->build_object(
187
        {
188
            class => 'Koha::Patrons',
189
            value => { flags => 3 }
190
        }
191
    );
192
193
    my $nonprivilegedpatron = $builder->build_object(
194
        {
195
            class => 'Koha::Patrons',
196
            value => { flags => 0 }
197
        }
198
    );
199
200
    my $password = 'thePassword123';
201
202
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
203
    my $userid    = $nonprivilegedpatron->userid;
204
    my $patron_id = $nonprivilegedpatron->borrowernumber;
205
206
    $t->post_ok( "//$userid:$password@/api/v1/record_sources" => json => { name => 'test1', patron_id => $patron_id } )
207
        ->status_is(403)->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
208
209
    $patron->set_password( { password => $password, skip_validation => 1 } );
210
    $userid = $patron->userid;
211
212
    my $source_id = $t->post_ok(
213
        "//$userid:$password@/api/v1/record_sources" => json => { name => 'test1', patron_id => $patron_id } )
214
        ->status_is( 201, 'SWAGGER3.2.2' )->json_is( '/name', 'test1' )->json_is( '/patron_id', $patron_id )
215
        ->tx->res->json->{record_source_id};
216
217
    my $created_source = Koha::RecordSources->find($source_id);
218
219
    is( $created_source->name, 'test1', 'Record source found' );
220
221
    $schema->storage->txn_rollback;
222
};
223
224
subtest 'update() tests' => sub {
225
226
    plan tests => 15;
227
228
    $schema->storage->txn_begin;
229
230
    my $librarian = $builder->build_object(
231
        {
232
            class => 'Koha::Patrons',
233
            value => { flags => 2**3 }    # parameters flag = 2
234
        }
235
    );
236
    my $password = 'thePassword123';
237
    $librarian->set_password( { password => $password, skip_validation => 1 } );
238
    my $userid = $librarian->userid;
239
240
    my $patron = $builder->build_object(
241
        {
242
            class => 'Koha::Patrons',
243
            value => { flags => 0 }
244
        }
245
    );
246
247
    $patron->set_password( { password => $password, skip_validation => 1 } );
248
    my $unauth_userid = $patron->userid;
249
250
    my $source    = Koha::RecordSource->new( { name => 'old_name', patron_id => $patron->id } )->store;
251
    my $source_id = $source->id;
252
253
    # Unauthorized attempt to update
254
    $t->put_ok( "//$unauth_userid:$password@/api/v1/record_sources/$source_id" => json =>
255
            { name => 'New unauthorized name change' } )->status_is(403);
256
257
    # Attempt partial update on a PUT
258
    my $source_with_missing_field = { patron_id => $source->patron_id };
259
260
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_missing_field )
261
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
262
263
    # Full object update on PUT
264
    my $source_with_updated_field = {
265
        name      => "new_name",
266
        patron_id => $source->patron_id,
267
    };
268
269
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_updated_field )
270
        ->status_is(200)->json_is( '/name' => $source_with_updated_field->{name} );
271
272
    # Authorized attempt to write invalid data
273
    my $source_with_invalid_field = {
274
        name      => "blah",
275
        patron_id => $source->patron_id,
276
        potato    => "yeah",
277
    };
278
279
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_invalid_field )
280
        ->status_is(400)->json_is(
281
        "/errors" => [
282
            {
283
                message => "Properties not allowed: potato.",
284
                path    => "/body"
285
            }
286
        ]
287
        );
288
289
    my $source_to_delete = $builder->build_object( { class => 'Koha::RecordSources' } );
290
    my $non_existent_id  = $source_to_delete->id;
291
    $source_to_delete->delete;
292
293
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$non_existent_id" => json => $source_with_updated_field )
294
        ->status_is(404);
295
296
    # Wrong method (POST)
297
    $source_with_updated_field->{record_source_id} = 2;
298
299
    $t->post_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_updated_field )
300
        ->status_is(404);
301
302
    $schema->storage->txn_rollback;
303
};

Return to bug 32607