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

(-)a/t/cypress/integration/Preservation/Settings.ts (+254 lines)
Line 0 Link Here
1
import { mount } from "@cypress/vue";
2
3
function get_attributes() {
4
    return [
5
        {
6
            processing_attribute_id: 1,
7
            processing_id: 1,
8
            name: "Country",
9
            type: "authorised_value",
10
            option_source: "COUNTRY",
11
        },
12
        {
13
            processing_attribute_id: 1,
14
            processing_id: 1,
15
            name: "DB",
16
            type: "db_column",
17
            option_source: "biblio.title",
18
        },
19
        {
20
            processing_attribute_id: 1,
21
            processing_id: 1,
22
            name: "Height",
23
            type: "free_text",
24
            option_source: null,
25
        },
26
    ];
27
}
28
function get_processing() {
29
    return {
30
        name: "test processing",
31
        processing_id: 1,
32
        attributes: get_attributes(),
33
    };
34
}
35
describe("Processings", () => {
36
    beforeEach(() => {
37
        cy.login();
38
        cy.title().should("eq", "Koha staff interface");
39
        cy.intercept(
40
            "GET",
41
            "/cgi-bin/koha/svc/config/systempreferences/?pref=PreservationModule",
42
            '{"value":"1"}'
43
        );
44
        cy.intercept(
45
            "GET",
46
            "/cgi-bin/koha/svc/config/systempreferences/?pref=PreservationNotForLoanWaitingListIn",
47
            '{"value":"24"}'
48
        );
49
        cy.intercept(
50
            "GET",
51
            "/cgi-bin/koha/svc/config/systempreferences/?pref=PreservationNotForLoanDefaultTrainIn",
52
            '{"value":"42"}'
53
        );
54
        cy.intercept(
55
            "GET",
56
            "/api/v1/authorised_value_categories/NOT_LOAN/authorised_values",
57
            [
58
                {
59
                    category_name: "NOT_LOAN",
60
                    description: "Ordered",
61
                    value: "-1",
62
                },
63
                {
64
                    category_name: "NOT_LOAN",
65
                    description: "Not for loan",
66
                    value: "1",
67
                },
68
                {
69
                    category_name: "NOT_LOAN",
70
                    description: "Staff collection",
71
                    value: "2",
72
                },
73
                {
74
                    category_name: "NOT_LOAN",
75
                    description: "Added to bundle",
76
                    value: "3",
77
                },
78
                {
79
                    category_name: "NOT_LOAN",
80
                    description: "In preservation",
81
                    value: "24",
82
                },
83
                {
84
                    category_name: "NOT_LOAN",
85
                    description: "In preservation external",
86
                    value: "42",
87
                },
88
            ]
89
        );
90
    });
91
92
    it("Settings", () => {
93
        cy.visit("/cgi-bin/koha/preservation/home.pl");
94
        cy.get("#navmenulist").contains("Settings").click();
95
        cy.get("#not_for_loan_waiting_list_in .vs__selected").contains(
96
            "In preservation"
97
        );
98
        cy.get("#not_for_loan_default_train_in .vs__selected").contains(
99
            "In preservation external"
100
        );
101
    });
102
    it("List processing", () => {
103
        cy.intercept("GET", "/api/v1/preservation/processings*", []);
104
        cy.visit("/cgi-bin/koha/preservation/settings");
105
        cy.get("#processing_0").should("not.exist");
106
        cy.intercept("GET", "/api/v1/preservation/processings*", [
107
            get_processing(),
108
        ]);
109
        cy.visit("/cgi-bin/koha/preservation/settings");
110
        cy.get("#processing_0").should("exist");
111
    });
112
113
    it("Add processing", () => {
114
        cy.intercept("GET", "/api/v1/preservation/processings*", []);
115
        cy.visit("/cgi-bin/koha/preservation/settings");
116
        let processing = get_processing();
117
        cy.contains("Add new processing").click();
118
        cy.get("#processing_name").type(processing.name);
119
        cy.contains("Add new attribute").click();
120
        let attribute = processing.attributes[0];
121
        cy.get("#attribute_name_0").type(attribute.name);
122
        cy.get("#attribute_type_0 .vs__search").type("Authorized{enter}", {
123
            force: true,
124
        });
125
        cy.get("#attribute_option_0 .vs__search").type(
126
            attribute.option_source + "{enter}",
127
            { force: true }
128
        );
129
        cy.contains("Add new attribute").click();
130
        attribute = processing.attributes[1];
131
        cy.get("#attribute_name_1").type(attribute.name);
132
        cy.get("#attribute_type_1 .vs__search").type("Database{enter}", {
133
            force: true,
134
        });
135
        cy.get("#attribute_option_1 .vs__search").type(
136
            attribute.option_source + "{enter}",
137
            { force: true }
138
        );
139
        cy.contains("Add new attribute").click();
140
        attribute = processing.attributes[2];
141
        cy.get("#attribute_name_2").type(attribute.name);
142
        cy.get("#attribute_type_2 .vs__search").type("Free{enter}", {
143
            force: true,
144
        });
145
146
        // Submit the form, get 500
147
        cy.intercept("POST", "/api/v1/preservation/processings", {
148
            statusCode: 500,
149
            error: "Something went wrong",
150
        });
151
        cy.get("#processings_add").contains("Submit").click();
152
        cy.get("main div[class='dialog alert']").contains(
153
            "Something went wrong: Error: Internal Server Error"
154
        );
155
156
        // Submit the form, success!
157
        cy.intercept("POST", "/api/v1/preservation/processings", {
158
            statusCode: 201,
159
            body: processing,
160
        });
161
        cy.intercept("GET", "/api/v1/preservation/processings*", {
162
            statusCode: 200,
163
            body: [processing],
164
        });
165
        cy.get("#processings_add").contains("Submit").click();
166
        cy.get("main div[class='dialog message']").contains(
167
            "Processing created"
168
        );
169
        cy.get("#processing_0").contains(processing.name);
170
    });
171
172
    it("Edit processing", () => {
173
        let processing = get_processing();
174
        cy.intercept("GET", "/api/v1/preservation/processings/*", {
175
            statusCode: 200,
176
            body: processing,
177
        });
178
        cy.intercept("GET", "/api/v1/preservation/processings*", {
179
            statusCode: 200,
180
            body: [processing],
181
        });
182
        cy.visit("/cgi-bin/koha/preservation/settings");
183
        cy.get("#processing_0").contains(processing.name);
184
        cy.get("#processing_0").contains("Edit this processing").click();
185
        cy.get("#processing_name").should("have.value", processing.name);
186
        let attribute = processing.attributes[0];
187
        cy.get("#attribute_name_0").should("have.value", attribute.name);
188
        cy.get("#attribute_type_0 .vs__selected").contains("Authorized value");
189
        cy.get("#attribute_option_0 .vs__selected").contains(
190
            attribute.option_source
191
        );
192
        attribute = processing.attributes[1];
193
        cy.get("#attribute_name_1").should("have.value", attribute.name);
194
        cy.get("#attribute_type_1 .vs__selected").contains("Database column");
195
        cy.get("#attribute_option_1 .vs__selected").contains(
196
            attribute.option_source
197
        );
198
        attribute = processing.attributes[2];
199
        cy.get("#attribute_name_2").should("have.value", attribute.name);
200
        cy.get("#attribute_type_2 .vs__selected").contains("Free text");
201
        cy.get("#attribute_option_2").should("not.exist");
202
203
        // Submit the form, get 500
204
        cy.intercept("PUT", "/api/v1/preservation/processings/*", {
205
            statusCode: 500,
206
            error: "Something went wrong",
207
        });
208
        cy.get("#processings_add").contains("Submit").click();
209
        cy.get("main div[class='dialog alert']").contains(
210
            "Something went wrong: Error: Internal Server Error"
211
        );
212
213
        // Submit the form, success!
214
        cy.intercept("PUT", "/api/v1/preservation/processings/*", {
215
            statusCode: 200,
216
            body: processing,
217
        });
218
        cy.get("#processings_add").contains("Submit").click();
219
        cy.get("main div[class='dialog message']").contains(
220
            "Processing updated"
221
        );
222
    });
223
224
    it("Delete processing", () => {
225
        let processing = get_processing();
226
        cy.intercept("GET", "/api/v1/preservation/processings*", {
227
            statusCode: 200,
228
            body: [processing],
229
        });
230
231
        // Submit the form, get 500
232
        cy.intercept("DELETE", "/api/v1/preservation/processings/*", {
233
            statusCode: 500,
234
            error: "Something went wrong",
235
        });
236
        cy.visit("/cgi-bin/koha/preservation/settings");
237
        cy.get("#processing_0").contains("Remove this processing").click();
238
        cy.contains("Yes, delete").click();
239
        cy.get("main div[class='dialog alert']").contains(
240
            "Something went wrong: Error: Internal Server Error"
241
        );
242
243
        // Submit the form, success!
244
        cy.intercept("DELETE", "/api/v1/preservation/processings/*", {
245
            statusCode: 204,
246
            body: null,
247
        });
248
        cy.get("#processing_0").contains("Remove this processing").click();
249
        cy.contains("Yes, delete").click();
250
        cy.get("main div[class='dialog message']").contains(
251
            `Processing ${processing.name} deleted`
252
        );
253
    });
254
});
(-)a/t/cypress/integration/Preservation/Trains.ts (+593 lines)
Line 0 Link Here
1
import { mount } from "@cypress/vue";
2
3
function get_attributes() {
4
    return [
5
        {
6
            processing_attribute_id: 1,
7
            processing_id: 1,
8
            name: "Country",
9
            type: "authorised_value",
10
            option_source: "COUNTRY",
11
        },
12
        {
13
            processing_attribute_id: 2,
14
            processing_id: 1,
15
            name: "DB",
16
            type: "db_column",
17
            option_source: "biblio.title",
18
        },
19
        {
20
            processing_attribute_id: 3,
21
            processing_id: 1,
22
            name: "Height",
23
            type: "free_text",
24
            option_source: null,
25
        },
26
    ];
27
}
28
function get_other_attributes() {
29
    return [
30
        {
31
            processing_attribute_id: 4,
32
            processing_id: 2,
33
            name: "Country",
34
            type: "authorised_value",
35
            option_source: "COUNTRY",
36
        },
37
        {
38
            processing_attribute_id: 5,
39
            processing_id: 2,
40
            name: "Width",
41
            type: "free_text",
42
            option_source: null,
43
        },
44
    ];
45
}
46
47
function get_processings() {
48
    return [
49
        {
50
            name: "new processing",
51
            processing_id: 1,
52
            attributes: get_attributes(),
53
        },
54
        {
55
            name: "an other processing",
56
            processing_id: 2,
57
            attributes: get_other_attributes(),
58
        },
59
    ];
60
}
61
62
function get_items() {
63
    // This is not a full item but it contains the info we are using
64
    return [
65
        {
66
            biblio: {
67
                biblio_id: 1,
68
                title: "a biblio title",
69
            },
70
            external_id: "bc_1",
71
            item_id: 1,
72
        },
73
        {
74
            biblio: {
75
                biblio_id: 2,
76
                title: "an other biblio title",
77
            },
78
            external_id: "bc_2",
79
            item_id: 2,
80
        },
81
        {
82
            biblio: {
83
                biblio_id: 3,
84
                title: "yet an other biblio title",
85
            },
86
            external_id: "bc_3",
87
            item_id: 3,
88
        },
89
    ];
90
}
91
92
function get_train_items() {
93
    let train_item_1 = get_items()[0];
94
    let processing_attributes = get_attributes();
95
    train_item_1.attributes = [
96
        {
97
            processing_attribute: processing_attributes[0],
98
            processing_attribute_id:
99
                processing_attributes[0].processing_attribute_id,
100
            value: "Argentina",
101
        },
102
        {
103
            processing_attribute: processing_attributes[1],
104
            processing_attribute_id:
105
                processing_attributes[1].processing_attribute_id,
106
            value: "a biblio title modified",
107
        },
108
        {
109
            processing_attribute: processing_attributes[2],
110
            processing_attribute_id:
111
                processing_attributes[2].processing_attribute_id,
112
            value: "12cm",
113
        },
114
    ];
115
    train_item_1.added_on = "2023-03-31T12:23:34+00:00";
116
    train_item_1.processing_id = 1;
117
    train_item_1.item_id = 1;
118
119
    let train_item_2 = get_items()[1];
120
    let processing_attributes = get_attributes();
121
    train_item_2.attributes = [
122
        {
123
            processing_attribute: processing_attributes[0],
124
            processing_attribute_id:
125
                processing_attributes[0].processing_attribute_id,
126
            value: "Uruguay",
127
        },
128
        {
129
            processing_attribute: processing_attributes[1],
130
            processing_attribute_id:
131
                processing_attributes[1].processing_attribute_id,
132
            value: "an other modified title",
133
        },
134
        {
135
            processing_attribute: processing_attributes[2],
136
            processing_attribute_id:
137
                processing_attributes[2].processing_attribute_id,
138
            value: "34cm",
139
        },
140
    ];
141
    train_item_2.added_on = "2023-04-01T12:34:56+00:00";
142
    train_item_2.processing_id = 1;
143
    train_item_2.item_id = 2;
144
145
    let train_item_3 = get_items()[0];
146
    let processing_attributes = get_other_attributes();
147
    train_item_3.attributes = [
148
        {
149
            processing_attribute: processing_attributes[0],
150
            processing_attribute_id:
151
                processing_attributes[0].processing_attribute_id,
152
            value: "Bolivia",
153
        },
154
        {
155
            processing_attribute: processing_attributes[1],
156
            processing_attribute_id:
157
                processing_attributes[1].processing_attribute_id,
158
            value: "W 123cm",
159
        },
160
    ];
161
    train_item_3.added_on = "2023-04-02T12:34:56+00:00";
162
    train_item_3.processing_id = 2;
163
    train_item_3.item_id = 3;
164
165
    return [train_item_1, train_item_2, train_item_3];
166
}
167
168
function get_train() {
169
    let processings = get_processings();
170
    return {
171
        train_id: 1,
172
        name: "My train",
173
        description: "Just a train",
174
        default_processing_id: processings[0].processing_id,
175
        not_for_loan: "42",
176
        created_on: "2023-04-05T10:16:27+00:00",
177
        closed_on: null,
178
        sent_on: null,
179
        received_on: null,
180
        items: [],
181
        default_processing: processings[0],
182
    };
183
}
184
185
describe("Trains", () => {
186
    beforeEach(() => {
187
        cy.login();
188
        cy.title().should("eq", "Koha staff interface");
189
        cy.intercept(
190
            "GET",
191
            "/cgi-bin/koha/svc/config/systempreferences/?pref=PreservationModule",
192
            '{"value":"1"}'
193
        );
194
        cy.intercept(
195
            "GET",
196
            "/cgi-bin/koha/svc/config/systempreferences/?pref=PreservationNotForLoanWaitingListIn",
197
            '{"value":"24"}'
198
        );
199
        cy.intercept(
200
            "GET",
201
            "/cgi-bin/koha/svc/config/systempreferences/?pref=PreservationNotForLoanDefaultTrainIn",
202
            '{"value":"42"}'
203
        );
204
        cy.intercept(
205
            "GET",
206
            "/api/v1/authorised_value_categories/NOT_LOAN/authorised_values",
207
            [
208
                {
209
                    category_name: "NOT_LOAN",
210
                    description: "Ordered",
211
                    value: "-1",
212
                },
213
                {
214
                    category_name: "NOT_LOAN",
215
                    description: "Not for loan",
216
                    value: "1",
217
                },
218
                {
219
                    category_name: "NOT_LOAN",
220
                    description: "Staff collection",
221
                    value: "2",
222
                },
223
                {
224
                    category_name: "NOT_LOAN",
225
                    description: "Added to bundle",
226
                    value: "3",
227
                },
228
                {
229
                    category_name: "NOT_LOAN",
230
                    description: "In preservation",
231
                    value: "24",
232
                },
233
                {
234
                    category_name: "NOT_LOAN",
235
                    description: "In preservation external",
236
                    value: "42",
237
                },
238
                {
239
                    category_name: "NOT_LOAN",
240
                    description: "In preservation other",
241
                    value: "43",
242
                },
243
            ]
244
        );
245
    });
246
247
    it("List trains", () => {
248
        // GET trains returns 500
249
        cy.intercept("GET", "/api/v1/preservation/trains*", {
250
            statusCode: 500,
251
            error: "Something went wrong",
252
        });
253
        cy.visit("/cgi-bin/koha/preservation/home.pl");
254
        cy.get("#navmenulist").contains("Trains").click();
255
        cy.get("main div[class='dialog alert']").contains(
256
            /Something went wrong/
257
        );
258
259
        // GET trains returns empty list
260
        cy.intercept("GET", "/api/v1/*", []);
261
        cy.visit("/cgi-bin/koha/preservation/trains");
262
        cy.get("#trains_list").contains("There are no trains defined");
263
264
        // GET trains returns something
265
        let train = get_train();
266
        let trains = [train];
267
268
        cy.intercept("GET", "/api/v1/preservation/trains*", {
269
            statusCode: 200,
270
            body: trains,
271
            headers: {
272
                "X-Base-Total-Count": "1",
273
                "X-Total-Count": "1",
274
            },
275
        });
276
        cy.intercept("GET", "/api/v1/preservation/trains/*", train);
277
        cy.visit("/cgi-bin/koha/preservation/trains");
278
        cy.get("#trains_list").contains("Showing 1 to 1 of 1 entries");
279
    });
280
281
    it("Add train", () => {
282
        cy.intercept("GET", "/api/v1/preservation/trains", []);
283
        cy.intercept(
284
            "GET",
285
            "/api/v1/preservation/processings",
286
            get_processings()
287
        );
288
        cy.visit("/cgi-bin/koha/preservation/trains");
289
        let train = get_train();
290
        cy.contains("New train").click();
291
        cy.get("#train_name").type(train.name);
292
        cy.get("#train_description").type(train.description);
293
        // Confirm that the default not_for_loan is selected
294
        cy.get("#not_for_loan .vs__selected").contains(
295
            "In preservation external"
296
        );
297
        // Change it
298
        cy.get("#not_for_loan .vs__search").type(
299
            "In preservation other{enter}"
300
        );
301
        cy.get("#train_default_processing .vs__search").type(
302
            "new processing{enter}"
303
        );
304
305
        // Submit the form, get 500
306
        cy.intercept("POST", "/api/v1/preservation/trains", {
307
            statusCode: 500,
308
            error: "Something went wrong",
309
        });
310
        cy.get("#trains_add").contains("Submit").click();
311
        cy.get("main div[class='dialog alert']").contains(
312
            "Something went wrong: Error: Internal Server Error"
313
        );
314
315
        // Submit the form, success!
316
        cy.intercept("POST", "/api/v1/preservation/trains", {
317
            statusCode: 201,
318
            body: train,
319
        });
320
        cy.get("#trains_add").contains("Submit").click();
321
        cy.get("main div[class='dialog message']").contains("Train created");
322
    });
323
324
    it("Edit train", () => {
325
        let train = get_train();
326
        let processings = get_processings();
327
        cy.intercept("GET", "/api/v1/preservation/trains/*", train);
328
        cy.intercept("GET", "/api/v1/preservation/trains", [train]);
329
        cy.intercept("GET", "/api/v1/preservation/processings*", processings);
330
        cy.visit("/cgi-bin/koha/preservation/trains");
331
        cy.get("#trains_list table tbody tr:first").contains("Edit").click();
332
        cy.get("#train_name").should("have.value", train.name);
333
        cy.get("#train_description").should("have.value", train.description);
334
        cy.get("#not_for_loan .vs__selected").contains(
335
            "In preservation external"
336
        );
337
        cy.get("#train_default_processing .vs__selected").contains(
338
            train.default_processing.name
339
        );
340
341
        // Submit the form, get 500
342
        cy.intercept("PUT", "/api/v1/preservation/trains/*", {
343
            statusCode: 500,
344
            error: "Something went wrong",
345
        });
346
        cy.get("#trains_add").contains("Submit").click();
347
        cy.get("main div[class='dialog alert']").contains(
348
            "Something went wrong: Error: Internal Server Error"
349
        );
350
351
        // Submit the form, success!
352
        cy.intercept("PUT", "/api/v1/preservation/trains/*", {
353
            statusCode: 200,
354
            body: train,
355
        });
356
        cy.intercept("GET", "/api/v1/preservation/trains", {
357
            statusCode: 200,
358
            body: [train],
359
        });
360
        cy.get("#trains_add").contains("Submit").click();
361
        cy.get("main div[class='dialog message']").contains("Train updated");
362
    });
363
364
    it("Simple show train", () => {
365
        let train = get_train();
366
        let trains = [train];
367
368
        cy.intercept("GET", "/api/v1/preservation/trains*", {
369
            statusCode: 200,
370
            body: trains,
371
            headers: {
372
                "X-Base-Total-Count": "1",
373
                "X-Total-Count": "1",
374
            },
375
        });
376
        cy.intercept("GET", "/api/v1/preservation/trains/*", train);
377
        cy.visit("/cgi-bin/koha/preservation/trains");
378
        let name_link = cy.get("#trains_list table tbody tr:first td:first a");
379
        name_link.should(
380
            "have.text",
381
            train.name + " (#" + train.train_id + ")"
382
        );
383
        name_link.click();
384
        cy.get("#trains_show h2").contains("Train #" + train.train_id);
385
386
        cy.contains("Name:" + train.name);
387
        cy.contains("Description:" + train.description);
388
        cy.contains(
389
            "Status for item added to this train:" + "In preservation external"
390
        );
391
        cy.contains("Default processing:" + train.default_processing.name);
392
    });
393
394
    it("Show train close, send, receive", () => {
395
        let train = get_train();
396
        cy.intercept("GET", "/api/v1/preservation/trains/" + train.train_id, {
397
            statusCode: 200,
398
            body: train,
399
        }).as("get-train");
400
        cy.visit("/cgi-bin/koha/preservation/trains/" + train.train_id);
401
        cy.wait("@get-train");
402
        cy.contains("Closed on:").should("not.exist");
403
        cy.contains("Sent on:").should("not.exist");
404
        cy.contains("Received on:").should("not.exist");
405
406
        let closed_train = Object.assign({}, train);
407
        closed_train.closed_on = "2022-10-27 12:34:56";
408
        cy.intercept("PUT", "/api/v1/preservation/trains/" + train.train_id, {
409
            statusCode: 201,
410
            body: closed_train,
411
        }).as("set-train");
412
        cy.intercept("GET", "/api/v1/preservation/trains/" + train.train_id, {
413
            statusCode: 200,
414
            body: closed_train,
415
        }).as("get-train");
416
        cy.get("#toolbar").contains("Close").click();
417
        cy.wait("@get-train");
418
        cy.contains("Closed on:").should("exist");
419
        cy.contains("Sent on:").should("not.exist");
420
        cy.contains("Received on:").should("not.exist");
421
422
        let sent_train = Object.assign({}, closed_train);
423
        sent_train.sent_on = "2022-10-28 12:34:56";
424
        cy.intercept("PUT", "/api/v1/preservation/trains/" + train.train_id, {
425
            statusCode: 201,
426
            body: sent_train,
427
        }).as("set-train");
428
        cy.intercept("GET", "/api/v1/preservation/trains/" + train.train_id, {
429
            statusCode: 200,
430
            body: sent_train,
431
        }).as("get-train");
432
        cy.get("#toolbar").contains("Send").click();
433
        cy.wait("@get-train");
434
        cy.contains("Closed on:").should("exist");
435
        cy.contains("Sent on:").should("exist");
436
        cy.contains("Received on:").should("not.exist");
437
438
        let received_train = Object.assign({}, sent_train);
439
        received_train.received_on = "2022-10-29 12:34:56";
440
        cy.intercept("PUT", "/api/v1/preservation/trains/" + train.train_id, {
441
            statusCode: 201,
442
            body: received_train,
443
        }).as("set-train");
444
        cy.intercept("GET", "/api/v1/preservation/trains/" + train.train_id, {
445
            statusCode: 200,
446
            body: received_train,
447
        }).as("get-train");
448
        cy.get("#toolbar").contains("Receive").click();
449
        cy.wait("@get-train");
450
        cy.contains("Closed on:").should("exist");
451
        cy.contains("Sent on:").should("exist");
452
        cy.contains("Received on:").should("exist");
453
    });
454
455
    it("Delete train", () => {
456
        let train = get_train();
457
        cy.intercept("GET", "/api/v1/preservation/trains*", {
458
            statusCode: 200,
459
            body: [train],
460
            headers: {
461
                "X-Base-Total-Count": "1",
462
                "X-Total-Count": "1",
463
            },
464
        });
465
        cy.visit("/cgi-bin/koha/preservation/trains");
466
467
        // Submit the form, get 500
468
        cy.intercept(
469
            "DELETE",
470
            "/api/v1/preservation/trains/" + train.train_id,
471
            {
472
                statusCode: 500,
473
                error: "Something went wrong",
474
            }
475
        );
476
        cy.get("#trains_list table tbody tr:first").contains("Delete").click();
477
        cy.contains("Yes, delete").click();
478
        cy.get("main div[class='dialog alert']").contains(
479
            "Something went wrong: Error: Internal Server Error"
480
        );
481
482
        // Submit the form, success!
483
        cy.intercept(
484
            "DELETE",
485
            "/api/v1/preservation/trains/" + train.train_id,
486
            {
487
                statusCode: 201,
488
                body: null,
489
            }
490
        );
491
        cy.get("#trains_list table tbody tr:first").contains("Delete").click();
492
        cy.contains("Yes, delete").click();
493
        cy.get("main div[class='dialog message']").contains(
494
            `Train ${train.name} deleted`
495
        );
496
    });
497
498
    it("Add new item to a train", () => {
499
        let train = get_train();
500
        cy.intercept(
501
            "GET",
502
            "/api/v1/preservation/trains/" + train.train_id,
503
            train
504
        );
505
        let processings = get_processings();
506
        cy.intercept("GET", "/api/v1/preservation/processings*", processings);
507
        cy.intercept(
508
            "GET",
509
            "/api/v1/preservation/processings/" + processings[0].processing_id,
510
            processings[0]
511
        );
512
        cy.visit("/cgi-bin/koha/preservation/trains/" + train.train_id);
513
        cy.contains("Add items").click();
514
        cy.get("#barcode").type("bc_1");
515
        cy.intercept("GET", "/api/v1/preservation/waiting-list/items*", []);
516
        cy.contains("Submit").click();
517
        cy.get("div[class='dialog alert modal']").contains(
518
            "Cannot find item with this barcode. It must be in the waiting list."
519
        );
520
        cy.get("#close_modal").click();
521
522
        let item = get_items()[0];
523
        cy.intercept("GET", "/api/v1/preservation/waiting-list/items*", [item]);
524
        cy.contains("Submit").click();
525
        cy.intercept(
526
            "POST",
527
            `/api/v1/preservation/trains/${train.train_id}/items`,
528
            {
529
                statusCode: 201,
530
                body: item, // Not correct but not important
531
            }
532
        );
533
        cy.contains("Itemnumber:" + item.item_id);
534
        cy.get("#processing .vs__selected").contains(
535
            train.default_processing.name
536
        );
537
        cy.contains("Country:");
538
        cy.get("#attribute_0 .vs__search").type("Argentin{enter}");
539
        cy.contains("DB:");
540
        cy.get("#attribute_1").should("have.value", item.biblio.title);
541
        cy.get("#attribute_1").type(" modified");
542
        cy.contains("Height:");
543
        cy.get("#attribute_2").type("42cm");
544
545
        let train_items = get_train_items();
546
        let train_with_one_item = Object.assign({}, train);
547
        train_with_one_item.items = [train_items[0]];
548
549
        cy.intercept(
550
            "GET",
551
            "/api/v1/preservation/trains/" + train.train_id,
552
            train_with_one_item
553
        );
554
        cy.contains("Submit").click();
555
        cy.get("#trains_show").contains("Showing 1 to 1 of 1 entries");
556
557
        let train_with_2_items = Object.assign({}, train);
558
        train_with_2_items.items = [train_items[0], train_items[1]];
559
        cy.intercept(
560
            "GET",
561
            "/api/v1/preservation/trains/" + train.train_id,
562
            train_with_2_items
563
        );
564
        cy.visit("/cgi-bin/koha/preservation/trains/" + train.train_id);
565
        cy.get("#trains_show table").should("exist");
566
        cy.get("#trains_show").contains("Showing 1 to 2 of 2 entries");
567
        train_with_2_items.items.forEach(train_item => {
568
            train_item.attributes.forEach(attribute => {
569
                cy.get("td").contains(attribute.value);
570
            });
571
        });
572
573
        let train_with_3_items = Object.assign({}, train);
574
        train_with_3_items.items = [
575
            train_items[0],
576
            train_items[1],
577
            train_items[2],
578
        ];
579
        cy.intercept(
580
            "GET",
581
            "/api/v1/preservation/trains/" + train.train_id,
582
            train_with_3_items
583
        );
584
        cy.visit("/cgi-bin/koha/preservation/trains/" + train.train_id);
585
        cy.get("#trains_show table").should("not.exist");
586
        train_with_3_items.items.forEach((train_item, i) => {
587
            train_item.attributes.forEach(attribute => {
588
                let re = new RegExp(attribute.value);
589
                cy.get(`#item_${i}`).contains(re);
590
            });
591
        });
592
    });
593
});
(-)a/t/cypress/integration/Preservation/WaitingList.ts (+185 lines)
Line 0 Link Here
1
import { mount } from "@cypress/vue";
2
3
function get_items() {
4
    // This is not a full item but it contains the info we are using
5
    return [
6
        {
7
            biblio: {
8
                biblio_id: 1,
9
                title: "a biblio title",
10
            },
11
            external_id: "bc_1",
12
            item_id: 1,
13
        },
14
        {
15
            biblio: {
16
                biblio_id: 2,
17
                title: "yet another biblio title",
18
            },
19
            external_id: "bc_3",
20
            item_id: 3,
21
        },
22
    ];
23
}
24
describe("WaitingList", () => {
25
    beforeEach(() => {
26
        cy.login();
27
        cy.title().should("eq", "Koha staff interface");
28
        cy.intercept(
29
            "GET",
30
            "/cgi-bin/koha/svc/config/systempreferences/?pref=PreservationModule",
31
            '{"value":"1"}'
32
        );
33
        cy.intercept(
34
            "GET",
35
            "/cgi-bin/koha/svc/config/systempreferences/?pref=PreservationNotForLoanWaitingListIn",
36
            '{"value":"24"}'
37
        );
38
        cy.intercept(
39
            "GET",
40
            "/cgi-bin/koha/svc/config/systempreferences/?pref=PreservationNotForLoanDefaultTrainIn",
41
            '{"value":"42"}'
42
        );
43
    });
44
45
    it("List", () => {
46
        cy.intercept(
47
            "GET",
48
            "/cgi-bin/koha/svc/config/systempreferences/?pref=PreservationNotForLoanWaitingListIn",
49
            '{"value":""}'
50
        );
51
        cy.visit("/cgi-bin/koha/preservation/home.pl");
52
        cy.intercept("GET", "/api/v1/preservation/waiting-list/items*", []);
53
        cy.get("#navmenulist").contains("Waiting list").click();
54
        cy.get("#waiting-list").contains(
55
            "You need to configure this module first."
56
        );
57
58
        cy.intercept(
59
            "GET",
60
            "/cgi-bin/koha/svc/config/systempreferences/?pref=PreservationNotForLoanWaitingListIn",
61
            '{"value":"42"}'
62
        );
63
        cy.visit("/cgi-bin/koha/preservation/home.pl");
64
        cy.intercept("GET", "/api/v1/preservation/waiting-list/items*", []);
65
        cy.get("#navmenulist").contains("Waiting list").click();
66
        cy.get("#waiting-list").contains(
67
            "There are no items in the waiting list"
68
        );
69
    });
70
71
    it("Add to waiting list", () => {
72
        cy.intercept("GET", "/api/v1/preservation/waiting-list/items*", []);
73
        cy.visit("/cgi-bin/koha/preservation/waiting-list");
74
        cy.intercept("POST", "/api/v1/preservation/waiting-list/items", {
75
            statusCode: 500,
76
            error: "Something went wrong",
77
        });
78
        cy.get("#waiting-list").contains("Add to waiting list").click();
79
        cy.get("#barcode_list").type("bc_1\nbc_2\nbc_3");
80
        cy.contains("Submit").click();
81
        cy.get("main div[class='dialog alert']").contains(
82
            "Something went wrong: Error: Internal Server Error"
83
        );
84
85
        cy.intercept("GET", "/api/v1/preservation/waiting-list/items*", {
86
            statusCode: 200,
87
            body: get_items(),
88
            headers: {
89
                "X-Base-Total-Count": "2",
90
                "X-Total-Count": "2",
91
            },
92
        }).as("get-items");
93
        cy.intercept("POST", "/api/v1/preservation/waiting-list/items", [
94
            { item_id: 1 },
95
            { item_id: 3 },
96
        ]);
97
        cy.get("#waiting-list").contains("Add to waiting list").click();
98
        cy.get("#barcode_list").type("bc_1\nbc_2\nbc_3");
99
        cy.contains("Submit").click();
100
        cy.wait("@get-items");
101
        cy.get("main div[class='dialog message']").contains(
102
            "2 new items added."
103
        );
104
    });
105
106
    it("Add to waiting list then add to a train", () => {
107
        let train = {
108
            description: "yet another train",
109
            name: "a train",
110
            train_id: 1,
111
        };
112
        cy.intercept("GET", "/api/v1/preservation/trains*", [train]);
113
        cy.visit("/cgi-bin/koha/preservation/waiting-list");
114
115
        cy.intercept("GET", "/api/v1/preservation/waiting-list/items*", {
116
            statusCode: 200,
117
            body: get_items(),
118
            headers: {
119
                "X-Base-Total-Count": "2",
120
                "X-Total-Count": "2",
121
            },
122
        }).as("get-items");
123
        cy.intercept("POST", "/api/v1/preservation/waiting-list/items", [
124
            { item_id: 1 },
125
            { item_id: 3 },
126
        ]);
127
        cy.get("#waiting-list").contains("Add to waiting list").click();
128
        cy.get("#barcode_list").type("bc_1\nbc_2\nbc_3");
129
        cy.contains("Submit").click();
130
        cy.wait("@get-items");
131
        cy.get("main div[class='dialog message']").contains(
132
            "2 new items added."
133
        );
134
        cy.contains("Add last 2 items to a train").click();
135
        cy.get("#train_id .vs__search").type(train.name + "{enter}");
136
        cy.intercept(
137
            "POST",
138
            "/api/v1/preservation/trains/" + train.train_id + "/items/batch",
139
            req => {
140
                req.reply({
141
                    statusCode: 201,
142
                    body: req.body,
143
                });
144
            }
145
        );
146
        cy.contains("Submit").click();
147
        cy.get("main div[class='dialog message']").contains(
148
            `2 items have been added to train ${train.train_id}.`
149
        );
150
    });
151
152
    it("Remove item from waiting list", () => {
153
        cy.intercept("GET", "/api/v1/preservation/waiting-list/items*", {
154
            statusCode: 200,
155
            body: get_items(),
156
            headers: {
157
                "X-Base-Total-Count": "2",
158
                "X-Total-Count": "2",
159
            },
160
        }); //.as("get-items")
161
        cy.visit("/cgi-bin/koha/preservation/waiting-list");
162
163
        // Submit the form, get 500
164
        cy.intercept("DELETE", "/api/v1/preservation/waiting-list/items/*", {
165
            statusCode: 500,
166
            error: "Something went wrong",
167
        });
168
        cy.get("#waiting-list table tbody tr:first").contains("Remove").click();
169
        cy.contains("Yes, remove").click();
170
        cy.get("main div[class='dialog alert']").contains(
171
            "Something went wrong: Error: Internal Server Error"
172
        );
173
174
        // Submit the form, success!
175
        cy.intercept("DELETE", "/api/v1/preservation/waiting-list/items/*", {
176
            statusCode: 204,
177
            body: null,
178
        });
179
        cy.get("#waiting-list table tbody tr:first").contains("Remove").click();
180
        cy.contains("Yes, remove").click();
181
        cy.get("main div[class='dialog message']").contains(
182
            `Item removed from the waiting list`
183
        );
184
    });
185
});
(-)a/t/db_dependent/Koha/Preservation/Processings.t (+58 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# This file is part of Koha
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::More tests => 1;
21
use Test::Exception;
22
use Test::Warn;
23
24
use Koha::Preservation::Processings;
25
use Koha::Database;
26
27
use t::lib::TestBuilder;
28
use t::lib::Mocks;
29
30
my $schema  = Koha::Database->new->schema;
31
my $builder = t::lib::TestBuilder->new;
32
33
subtest 'attributes' => sub {
34
35
    plan tests => 4;
36
37
    $schema->storage->txn_begin;
38
39
    my $processing = $builder->build_object( { class => 'Koha::Preservation::Processings' } );
40
41
    my $attributes = [
42
        { name => 'color', type => 'authorised_value', option_source => 'COLORS' },
43
        { name => 'title', type => 'db_column',        option_source => '245$a' },
44
        {
45
            name => 'height',
46
            type => 'free_text'
47
        },
48
    ];
49
    $processing->attributes($attributes);
50
    my $fetched_attributes = $processing->attributes;
51
    is( ref($fetched_attributes),   'Koha::Preservation::Processing::Attributes' );
52
    is( $fetched_attributes->count, 3 );
53
    $processing->attributes( [] );
54
    is( ref($fetched_attributes),   'Koha::Preservation::Processing::Attributes' );
55
    is( $fetched_attributes->count, 0 );
56
57
    $schema->storage->txn_rollback;
58
};
(-)a/t/db_dependent/Koha/Preservation/Trains.t (+102 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# This file is part of Koha
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::More tests => 2;
21
use Test::Exception;
22
use Test::Warn;
23
24
use Koha::Preservation::Trains;
25
use Koha::Database;
26
27
use t::lib::TestBuilder;
28
use t::lib::Mocks;
29
30
my $schema  = Koha::Database->new->schema;
31
my $builder = t::lib::TestBuilder->new;
32
33
subtest 'default_processing' => sub {
34
35
    plan tests => 3;
36
37
    $schema->storage->txn_begin;
38
39
    my $processing         = $builder->build_object( { class => 'Koha::Preservation::Processings' } );
40
    my $another_processing = $builder->build_object( { class => 'Koha::Preservation::Processings' } );
41
42
    my $train = $builder->build_object( { class => 'Koha::Preservation::Trains', value => { default_processing_id => $processing->processing_id } } );
43
44
    my $default_processing = $train->default_processing;
45
    is( ref($default_processing),           'Koha::Preservation::Processing', '->default_processing returns a Koha::Preservation::Processing object' );
46
    is( $default_processing->processing_id, $processing->processing_id,       'correct processing is returned' );
47
    $processing->delete;
48
    $default_processing = $train->get_from_storage->default_processing;
49
    is( $default_processing, undef, 'deleting the processing does not delete the train' );
50
51
    $schema->storage->txn_rollback;
52
};
53
54
subtest 'add_items & items' => sub {
55
    plan tests => 9;
56
57
    $schema->storage->txn_begin;
58
59
    my $not_for_loan_waiting_list_in = 24;
60
    my $not_for_loan_train_in        = 42;
61
    my $train = $builder->build_object(
62
        {
63
            class => 'Koha::Preservation::Trains',
64
            value => {
65
                not_for_loan => $not_for_loan_train_in,
66
                closed_on    => undef,
67
                sent_on      => undef,
68
                received_on  => undef
69
            }
70
        }
71
    );
72
    my $item_1 = $builder->build_sample_item;
73
    my $item_2 = $builder->build_sample_item;
74
    my $item_3 = $builder->build_sample_item;
75
76
    $builder->build_object( { class => 'Koha::AuthorisedValues', value => { category => 'NOT_LOAN', authorised_value => $not_for_loan_waiting_list_in } } );
77
    $item_1->notforloan($not_for_loan_waiting_list_in)->store;
78
    $item_2->notforloan(0)->store;    # item_2 is not in the waiting list
79
    $item_3->notforloan($not_for_loan_waiting_list_in)->store;
80
    t::lib::Mocks::mock_preference( 'PreservationNotForLoanWaitingListIn', $not_for_loan_waiting_list_in );
81
    warning_is {
82
        $train->add_items( [ { item_id => $item_1->itemnumber }, { item_id => $item_2->itemnumber }, { barcode => $item_3->barcode } ] );
83
    }
84
    'Item not added to train: [Cannot add item to train, it is not in the waiting list]';
85
    my $items_train = $train->items;
86
    is( $items_train->count, 2, '2 items added to the train' );
87
    my $item_train_1 = $items_train->find( { item_id => $item_1->itemnumber } );
88
    my $item_train_3 = $items_train->find( { item_id => $item_3->itemnumber } );
89
    my $catalogue_item_1 = $item_train_1->catalogue_item;
90
    is( ref($catalogue_item_1),        'Koha::Item' );
91
    is( $catalogue_item_1->notforloan, $not_for_loan_train_in );
92
93
    my $catalogue_item_3 = $item_train_3->catalogue_item;
94
    is( ref($catalogue_item_3),        'Koha::Item' );
95
    is( $catalogue_item_3->notforloan, $not_for_loan_train_in );
96
97
    is( $item_1->get_from_storage->notforloan, $not_for_loan_train_in );
98
    is( $item_2->get_from_storage->notforloan, 0 );
99
    is( $item_3->get_from_storage->notforloan, $not_for_loan_train_in );
100
101
    $schema->storage->txn_rollback;
102
};
(-)a/t/db_dependent/api/v1/preservation_Processings.t (+369 lines)
Line 0 Link Here
1
#!/usr/bin/env perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::More tests => 5;
21
use Test::Mojo;
22
23
use t::lib::TestBuilder;
24
use t::lib::Mocks;
25
26
use Koha::Preservation::Processings;
27
use Koha::Database;
28
29
my $schema  = Koha::Database->new->schema;
30
my $builder = t::lib::TestBuilder->new;
31
32
my $t = Test::Mojo->new('Koha::REST::V1');
33
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
34
35
subtest 'list() tests' => sub {
36
37
    plan tests => 8;
38
39
    $schema->storage->txn_begin;
40
41
    Koha::Preservation::Processings->search->delete;
42
43
    my $librarian = $builder->build_object(
44
        {
45
            class => 'Koha::Patrons',
46
            value => { flags => 2**30 }
47
        }
48
    );
49
    my $password = 'thePassword123';
50
    $librarian->set_password( { password => $password, skip_validation => 1 } );
51
    my $userid = $librarian->userid;
52
53
    my $patron = $builder->build_object(
54
        {
55
            class => 'Koha::Patrons',
56
            value => { flags => 0 }
57
        }
58
    );
59
60
    $patron->set_password( { password => $password, skip_validation => 1 } );
61
    my $unauth_userid = $patron->userid;
62
63
    ## Authorized user tests
64
    # No processings, so empty array should be returned
65
    $t->get_ok("//$userid:$password@/api/v1/preservation/processings")->status_is(200)
66
      ->json_is( [] );
67
68
    my $processing = $builder->build_object(
69
        {
70
            class => 'Koha::Preservation::Processings',
71
        }
72
    );
73
74
    # One processing created, should get returned
75
    $t->get_ok("//$userid:$password@/api/v1/preservation/processings")->status_is(200)
76
      ->json_is( [ $processing->to_api ] );
77
78
    # Unauthorized access
79
    $t->get_ok("//$unauth_userid:$password@/api/v1/preservation/processings")
80
      ->status_is(403);
81
82
    $schema->storage->txn_rollback;
83
};
84
85
subtest 'get() tests' => sub {
86
87
    plan tests => 11;
88
89
    $schema->storage->txn_begin;
90
91
    my $processing =
92
      $builder->build_object( { class => 'Koha::Preservation::Processings' } );
93
    my $attributes = [
94
        {
95
            name          => 'color',
96
            type          => 'authorised_value',
97
            option_source => 'COLORS'
98
        },
99
        { name => 'title', type => 'db_column', option_source => '245$a' },
100
        {
101
            name => 'height',
102
            type => 'free_text'
103
        },
104
    ];
105
    $attributes = $processing->attributes($attributes);
106
    my $librarian = $builder->build_object(
107
        {
108
            class => 'Koha::Patrons',
109
            value => { flags => 2**30 }
110
        }
111
    );
112
    my $password = 'thePassword123';
113
    $librarian->set_password( { password => $password, skip_validation => 1 } );
114
    my $userid = $librarian->userid;
115
116
    my $patron = $builder->build_object(
117
        {
118
            class => 'Koha::Patrons',
119
            value => { flags => 0 }
120
        }
121
    );
122
123
    $patron->set_password( { password => $password, skip_validation => 1 } );
124
    my $unauth_userid = $patron->userid;
125
126
    # This processing exists, should get returned
127
    $t->get_ok( "//$userid:$password@/api/v1/preservation/processings/"
128
          . $processing->processing_id )->status_is(200)
129
      ->json_is( $processing->to_api );
130
131
    # Return one processing with attributes
132
    $t->get_ok( "//$userid:$password@/api/v1/preservation/processings/"
133
          . $processing->processing_id  => {'x-koha-embed' => 'attributes'} )->status_is(200)
134
      ->json_is( { %{ $processing->to_api }, attributes => $attributes->to_api });
135
136
    # Unauthorized access
137
    $t->get_ok( "//$unauth_userid:$password@/api/v1/preservation/processings/"
138
          . $processing->processing_id )->status_is(403);
139
140
    # Attempt to get non-existent processing
141
    my $processing_to_delete =
142
      $builder->build_object( { class => 'Koha::Preservation::Processings' } );
143
    my $non_existent_id = $processing_to_delete->processing_id;
144
    $processing_to_delete->delete;
145
146
    $t->get_ok("//$userid:$password@/api/v1/preservation/processings/$non_existent_id")
147
      ->status_is(404)->json_is( '/error' => 'Processing not found' );
148
149
    $schema->storage->txn_rollback;
150
};
151
152
subtest 'add() tests' => sub {
153
154
    plan tests => 15;
155
156
    $schema->storage->txn_begin;
157
158
    my $librarian = $builder->build_object(
159
        {
160
            class => 'Koha::Patrons',
161
            value => { flags => 2**30 }
162
        }
163
    );
164
    my $password = 'thePassword123';
165
    $librarian->set_password( { password => $password, skip_validation => 1 } );
166
    my $userid = $librarian->userid;
167
168
    my $patron = $builder->build_object(
169
        {
170
            class => 'Koha::Patrons',
171
            value => { flags => 0 }
172
        }
173
    );
174
175
    $patron->set_password( { password => $password, skip_validation => 1 } );
176
    my $unauth_userid = $patron->userid;
177
178
    my $default_processing = $builder->build_object({class => 'Koha::Preservation::Processings'});
179
    my $processing = {
180
        name             => "processing name",
181
    };
182
183
    # Unauthorized attempt to write
184
    $t->post_ok( "//$unauth_userid:$password@/api/v1/preservation/processings" => json =>
185
          $processing )->status_is(403);
186
187
    # Authorized attempt to write invalid data
188
    my $processing_with_invalid_field = {
189
        blah             => "processing Blah",
190
        %$processing,
191
    };
192
193
    $t->post_ok( "//$userid:$password@/api/v1/preservation/processings" => json =>
194
          $processing_with_invalid_field )->status_is(400)->json_is(
195
        "/errors" => [
196
            {
197
                message => "Properties not allowed: blah.",
198
                path    => "/body"
199
            }
200
        ]
201
          );
202
203
    # Authorized attempt to write
204
    my $processing_id =
205
      $t->post_ok(
206
        "//$userid:$password@/api/v1/preservation/processings" => json => $processing )
207
      ->status_is( 201, 'SWAGGER3.2.1' )->header_like(
208
        Location => qr|^/api/v1/preservation/processings/\d*|,
209
        'SWAGGER3.4.1'
210
    )->json_is( '/name'                   => $processing->{name} )
211
      ->tx->res->json->{processing_id};
212
213
    # Authorized attempt to create with null id
214
    $processing->{processing_id} = undef;
215
    $t->post_ok(
216
        "//$userid:$password@/api/v1/preservation/processings" => json => $processing )
217
      ->status_is(400)->json_has('/errors');
218
219
    # Authorized attempt to create with existing id
220
    $processing->{processing_id} = $processing_id;
221
    $t->post_ok(
222
        "//$userid:$password@/api/v1/preservation/processings" => json => $processing )
223
      ->status_is(400)->json_is(
224
        "/errors" => [
225
            {
226
                message => "Read-only.",
227
                path    => "/body/processing_id"
228
            }
229
        ]
230
      );
231
232
    $schema->storage->txn_rollback;
233
};
234
235
subtest 'update() tests' => sub {
236
237
    plan tests => 15;
238
239
    $schema->storage->txn_begin;
240
241
    my $librarian = $builder->build_object(
242
        {
243
            class => 'Koha::Patrons',
244
            value => { flags => 2**30 }
245
        }
246
    );
247
    my $password = 'thePassword123';
248
    $librarian->set_password( { password => $password, skip_validation => 1 } );
249
    my $userid = $librarian->userid;
250
251
    my $patron = $builder->build_object(
252
        {
253
            class => 'Koha::Patrons',
254
            value => { flags => 0 }
255
        }
256
    );
257
258
    $patron->set_password( { password => $password, skip_validation => 1 } );
259
    my $unauth_userid = $patron->userid;
260
261
    my $processing_id =
262
      $builder->build_object( { class => 'Koha::Preservation::Processings' } )->processing_id;
263
264
    # Unauthorized attempt to update
265
    $t->put_ok(
266
        "//$unauth_userid:$password@/api/v1/preservation/processings/$processing_id" =>
267
          json => { name => 'New unauthorized name change' } )->status_is(403);
268
269
    # Attempt partial update on a PUT
270
    my $processing_with_missing_field = {
271
    };
272
273
    $t->put_ok(
274
        "//$userid:$password@/api/v1/preservation/processings/$processing_id" => json =>
275
          $processing_with_missing_field )->status_is(400)
276
      ->json_is( "/errors" =>
277
          [ { message => "Missing property.", path => "/body/name" } ] );
278
279
    my $default_processing = $builder->build_object({class => 'Koha::Preservation::Processings'});
280
    # Full object update on PUT
281
    my $processing_with_updated_field = {
282
        name => "New name",
283
    };
284
285
    $t->put_ok(
286
        "//$userid:$password@/api/v1/preservation/processings/$processing_id" => json =>
287
          $processing_with_updated_field )->status_is(200)
288
      ->json_is( '/name' => 'New name' );
289
290
    # Authorized attempt to write invalid data
291
    my $processing_with_invalid_field = {
292
        blah             => "processing Blah",
293
        %$processing_with_updated_field,
294
    };
295
296
    $t->put_ok(
297
        "//$userid:$password@/api/v1/preservation/processings/$processing_id" => json =>
298
          $processing_with_invalid_field )->status_is(400)->json_is(
299
        "/errors" => [
300
            {
301
                message => "Properties not allowed: blah.",
302
                path    => "/body"
303
            }
304
        ]
305
          );
306
307
    # Attempt to update non-existent processing
308
    my $processing_to_delete =
309
      $builder->build_object( { class => 'Koha::Preservation::Processings' } );
310
    my $non_existent_id = $processing_to_delete->processing_id;
311
    $processing_to_delete->delete;
312
313
    $t->put_ok( "//$userid:$password@/api/v1/preservation/processings/$non_existent_id" =>
314
          json => $processing_with_updated_field )->status_is(404);
315
316
    # Wrong method (POST)
317
    $processing_with_updated_field->{processing_id} = 2;
318
319
    $t->post_ok(
320
        "//$userid:$password@/api/v1/preservation/processings/$processing_id" => json =>
321
          $processing_with_updated_field )->status_is(404);
322
323
    $schema->storage->txn_rollback;
324
};
325
326
subtest 'delete() tests' => sub {
327
328
    plan tests => 7;
329
330
    $schema->storage->txn_begin;
331
332
    my $librarian = $builder->build_object(
333
        {
334
            class => 'Koha::Patrons',
335
            value => { flags => 2**30 }
336
        }
337
    );
338
    my $password = 'thePassword123';
339
    $librarian->set_password( { password => $password, skip_validation => 1 } );
340
    my $userid = $librarian->userid;
341
342
    my $patron = $builder->build_object(
343
        {
344
            class => 'Koha::Patrons',
345
            value => { flags => 0 }
346
        }
347
    );
348
349
    $patron->set_password( { password => $password, skip_validation => 1 } );
350
    my $unauth_userid = $patron->userid;
351
352
    my $processing_id =
353
      $builder->build_object( { class => 'Koha::Preservation::Processings' } )->processing_id;
354
355
    # Unauthorized attempt to delete
356
    $t->delete_ok(
357
        "//$unauth_userid:$password@/api/v1/preservation/processings/$processing_id")
358
      ->status_is(403);
359
360
    # Delete existing processing
361
    $t->delete_ok("//$userid:$password@/api/v1/preservation/processings/$processing_id")
362
      ->status_is( 204, 'SWAGGER3.2.4' )->content_is( '', 'SWAGGER3.3.4' );
363
364
    # Attempt to delete non-existent processing
365
    $t->delete_ok("//$userid:$password@/api/v1/preservation/processings/$processing_id")
366
      ->status_is(404);
367
368
    $schema->storage->txn_rollback;
369
};
(-)a/t/db_dependent/api/v1/preservation_Trains.t (+525 lines)
Line 0 Link Here
1
#!/usr/bin/env perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::More tests => 6;
21
use Test::Mojo;
22
23
use t::lib::TestBuilder;
24
use t::lib::Mocks;
25
26
use Koha::Preservation::Trains;
27
use Koha::Database;
28
29
my $schema  = Koha::Database->new->schema;
30
my $builder = t::lib::TestBuilder->new;
31
32
my $t = Test::Mojo->new('Koha::REST::V1');
33
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
34
35
subtest 'list() tests' => sub {
36
37
    plan tests => 8;
38
39
    $schema->storage->txn_begin;
40
41
    Koha::Preservation::Trains->search->delete;
42
43
    my $librarian = $builder->build_object(
44
        {
45
            class => 'Koha::Patrons',
46
            value => { flags => 2**30 }
47
        }
48
    );
49
    my $password = 'thePassword123';
50
    $librarian->set_password( { password => $password, skip_validation => 1 } );
51
    my $userid = $librarian->userid;
52
53
    my $patron = $builder->build_object(
54
        {
55
            class => 'Koha::Patrons',
56
            value => { flags => 0 }
57
        }
58
    );
59
60
    $patron->set_password( { password => $password, skip_validation => 1 } );
61
    my $unauth_userid = $patron->userid;
62
63
    ## Authorized user tests
64
    # No trains, so empty array should be returned
65
    $t->get_ok("//$userid:$password@/api/v1/preservation/trains")->status_is(200)
66
      ->json_is( [] );
67
68
    my $train = $builder->build_object(
69
        {
70
            class => 'Koha::Preservation::Trains',
71
        }
72
    );
73
74
    # One train created, should get returned
75
    $t->get_ok("//$userid:$password@/api/v1/preservation/trains")->status_is(200)
76
      ->json_is( [ $train->to_api ] );
77
78
    # Unauthorized access
79
    $t->get_ok("//$unauth_userid:$password@/api/v1/preservation/trains")
80
      ->status_is(403);
81
82
    $schema->storage->txn_rollback;
83
};
84
85
subtest 'get() tests' => sub {
86
87
    plan tests => 14;
88
89
    $schema->storage->txn_begin;
90
91
    my $train =
92
      $builder->build_object( { class => 'Koha::Preservation::Trains' } );
93
    my $default_processing = $train->default_processing;
94
    my $librarian = $builder->build_object(
95
        {
96
            class => 'Koha::Patrons',
97
            value => { flags => 2**30 }
98
        }
99
    );
100
    my $password = 'thePassword123';
101
    $librarian->set_password( { password => $password, skip_validation => 1 } );
102
    my $userid = $librarian->userid;
103
104
    my $patron = $builder->build_object(
105
        {
106
            class => 'Koha::Patrons',
107
            value => { flags => 0 }
108
        }
109
    );
110
111
    $patron->set_password( { password => $password, skip_validation => 1 } );
112
    my $unauth_userid = $patron->userid;
113
114
    # This train exists, should get returned
115
    $t->get_ok( "//$userid:$password@/api/v1/preservation/trains/"
116
          . $train->train_id )->status_is(200)
117
      ->json_is( $train->to_api );
118
119
    # Return one train with some embeds
120
    $t->get_ok( "//$userid:$password@/api/v1/preservation/trains/"
121
          . $train->train_id  => {'x-koha-embed' => 'items,default_processing'} )->status_is(200)
122
      ->json_is( { %{ $train->to_api }, items => [], default_processing => $default_processing->unblessed });
123
124
    # Return one train with all embeds
125
    $t->get_ok( "//$userid:$password@/api/v1/preservation/trains/"
126
          . $train->train_id => { 'x-koha-embed' => 'items,items.attributes,items.attributes.processing_attribute,default_processing,default_processing.attributes' } )
127
      ->status_is(200)->json_is( { %{ $train->to_api }, items => [], default_processing => { %{ $default_processing->unblessed }, attributes => [] } } );
128
129
    # Unauthorized access
130
    $t->get_ok( "//$unauth_userid:$password@/api/v1/preservation/trains/"
131
          . $train->train_id )->status_is(403);
132
133
    # Attempt to get non-existent train
134
    my $train_to_delete =
135
      $builder->build_object( { class => 'Koha::Preservation::Trains' } );
136
    my $non_existent_id = $train_to_delete->train_id;
137
    $train_to_delete->delete;
138
139
    $t->get_ok("//$userid:$password@/api/v1/preservation/trains/$non_existent_id")
140
      ->status_is(404)->json_is( '/error' => 'Train not found' );
141
142
    $schema->storage->txn_rollback;
143
};
144
145
subtest 'add() tests' => sub {
146
147
    plan tests => 18;
148
149
    $schema->storage->txn_begin;
150
151
    my $librarian = $builder->build_object(
152
        {
153
            class => 'Koha::Patrons',
154
            value => { flags => 2**30 }
155
        }
156
    );
157
    my $password = 'thePassword123';
158
    $librarian->set_password( { password => $password, skip_validation => 1 } );
159
    my $userid = $librarian->userid;
160
161
    my $patron = $builder->build_object(
162
        {
163
            class => 'Koha::Patrons',
164
            value => { flags => 0 }
165
        }
166
    );
167
168
    $patron->set_password( { password => $password, skip_validation => 1 } );
169
    my $unauth_userid = $patron->userid;
170
171
    my $default_processing = $builder->build_object({class => 'Koha::Preservation::Processings'});
172
    my $train = {
173
        name             => "train name",
174
        description      => "train description",
175
        default_processing_id => $default_processing->processing_id,
176
        not_for_loan => 42,
177
    };
178
179
    # Unauthorized attempt to write
180
    $t->post_ok( "//$unauth_userid:$password@/api/v1/preservation/trains" => json =>
181
          $train )->status_is(403);
182
183
    # Authorized attempt to write invalid data
184
    my $train_with_invalid_field = {
185
        blah             => "train Blah",
186
        %$train,
187
    };
188
189
    $t->post_ok( "//$userid:$password@/api/v1/preservation/trains" => json =>
190
          $train_with_invalid_field )->status_is(400)->json_is(
191
        "/errors" => [
192
            {
193
                message => "Properties not allowed: blah.",
194
                path    => "/body"
195
            }
196
        ]
197
          );
198
199
    # Authorized attempt to write
200
    my $train_id =
201
      $t->post_ok(
202
        "//$userid:$password@/api/v1/preservation/trains" => json => $train )
203
      ->status_is( 201, 'SWAGGER3.2.1' )->header_like(
204
        Location => qr|^/api/v1/preservation/trains/\d*|,
205
        'SWAGGER3.4.1'
206
    )->json_is( '/name'                   => $train->{name} )
207
      ->json_is( '/description'           => $train->{description} )
208
      ->json_is( '/default_processing_id' => $train->{default_processing_id} )
209
      ->json_is( '/not_for_loan'          => $train->{not_for_loan} )
210
      ->tx->res->json->{train_id};
211
212
    # Authorized attempt to create with null id
213
    $train->{train_id} = undef;
214
    $t->post_ok(
215
        "//$userid:$password@/api/v1/preservation/trains" => json => $train )
216
      ->status_is(400)->json_has('/errors');
217
218
    # Authorized attempt to create with existing id
219
    $train->{train_id} = $train_id;
220
    $t->post_ok(
221
        "//$userid:$password@/api/v1/preservation/trains" => json => $train )
222
      ->status_is(400)->json_is(
223
        "/errors" => [
224
            {
225
                message => "Read-only.",
226
                path    => "/body/train_id"
227
            }
228
        ]
229
      );
230
231
    $schema->storage->txn_rollback;
232
};
233
234
subtest 'update() tests' => sub {
235
236
    plan tests => 15;
237
238
    $schema->storage->txn_begin;
239
240
    my $librarian = $builder->build_object(
241
        {
242
            class => 'Koha::Patrons',
243
            value => { flags => 2**30 }
244
        }
245
    );
246
    my $password = 'thePassword123';
247
    $librarian->set_password( { password => $password, skip_validation => 1 } );
248
    my $userid = $librarian->userid;
249
250
    my $patron = $builder->build_object(
251
        {
252
            class => 'Koha::Patrons',
253
            value => { flags => 0 }
254
        }
255
    );
256
257
    $patron->set_password( { password => $password, skip_validation => 1 } );
258
    my $unauth_userid = $patron->userid;
259
260
    my $train_id =
261
      $builder->build_object( { class => 'Koha::Preservation::Trains' } )->train_id;
262
263
    # Unauthorized attempt to update
264
    $t->put_ok(
265
        "//$unauth_userid:$password@/api/v1/preservation/trains/$train_id" =>
266
          json => { name => 'New unauthorized name change' } )->status_is(403);
267
268
    # Attempt partial update on a PUT
269
    my $train_with_missing_field = {
270
    };
271
272
    $t->put_ok(
273
        "//$userid:$password@/api/v1/preservation/trains/$train_id" => json =>
274
          $train_with_missing_field )->status_is(400)
275
      ->json_is( "/errors" =>
276
          [ { message => "Missing property.", path => "/body/name" } ] );
277
278
    my $default_processing = $builder->build_object({class => 'Koha::Preservation::Processings'});
279
    # Full object update on PUT
280
    my $train_with_updated_field = {
281
        name             => "New name",
282
        description      => "train description",
283
        default_processing_id => $default_processing->processing_id,
284
        not_for_loan => 42,
285
    };
286
287
    $t->put_ok(
288
        "//$userid:$password@/api/v1/preservation/trains/$train_id" => json =>
289
          $train_with_updated_field )->status_is(200)
290
      ->json_is( '/name' => 'New name' );
291
292
    # Authorized attempt to write invalid data
293
    my $train_with_invalid_field = {
294
        blah             => "train Blah",
295
        %$train_with_updated_field,
296
    };
297
298
    $t->put_ok(
299
        "//$userid:$password@/api/v1/preservation/trains/$train_id" => json =>
300
          $train_with_invalid_field )->status_is(400)->json_is(
301
        "/errors" => [
302
            {
303
                message => "Properties not allowed: blah.",
304
                path    => "/body"
305
            }
306
        ]
307
          );
308
309
    # Attempt to update non-existent train
310
    my $train_to_delete =
311
      $builder->build_object( { class => 'Koha::Preservation::Trains' } );
312
    my $non_existent_id = $train_to_delete->train_id;
313
    $train_to_delete->delete;
314
315
    $t->put_ok( "//$userid:$password@/api/v1/preservation/trains/$non_existent_id" =>
316
          json => $train_with_updated_field )->status_is(404);
317
318
    # Wrong method (POST)
319
    $train_with_updated_field->{train_id} = 2;
320
321
    $t->post_ok(
322
        "//$userid:$password@/api/v1/preservation/trains/$train_id" => json =>
323
          $train_with_updated_field )->status_is(404);
324
325
    $schema->storage->txn_rollback;
326
};
327
328
subtest 'delete() tests' => sub {
329
330
    plan tests => 7;
331
332
    $schema->storage->txn_begin;
333
334
    my $librarian = $builder->build_object(
335
        {
336
            class => 'Koha::Patrons',
337
            value => { flags => 2**30 }
338
        }
339
    );
340
    my $password = 'thePassword123';
341
    $librarian->set_password( { password => $password, skip_validation => 1 } );
342
    my $userid = $librarian->userid;
343
344
    my $patron = $builder->build_object(
345
        {
346
            class => 'Koha::Patrons',
347
            value => { flags => 0 }
348
        }
349
    );
350
351
    $patron->set_password( { password => $password, skip_validation => 1 } );
352
    my $unauth_userid = $patron->userid;
353
354
    my $train_id =
355
      $builder->build_object( { class => 'Koha::Preservation::Trains' } )->train_id;
356
357
    # Unauthorized attempt to delete
358
    $t->delete_ok(
359
        "//$unauth_userid:$password@/api/v1/preservation/trains/$train_id")
360
      ->status_is(403);
361
362
    # Delete existing train
363
    $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id")
364
      ->status_is( 204, 'SWAGGER3.2.4' )->content_is( '', 'SWAGGER3.3.4' );
365
366
    # Attempt to delete non-existent train
367
    $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id")
368
      ->status_is(404);
369
370
    $schema->storage->txn_rollback;
371
};
372
373
subtest '*_item() tests' => sub {
374
375
    plan tests => 26;
376
377
    $schema->storage->txn_begin;
378
379
    my $librarian = $builder->build_object(
380
        {
381
            class => 'Koha::Patrons',
382
            value => { flags => 2**30 }
383
        }
384
    );
385
    my $password = 'thePassword123';
386
    $librarian->set_password( { password => $password, skip_validation => 1 } );
387
    my $userid = $librarian->userid;
388
389
    my $not_for_loan_waiting_list_in = 24;
390
    my $not_for_loan_train_in        = 42;
391
392
    t::lib::Mocks::mock_preference( 'PreservationNotForLoanWaitingListIn',
393
        $not_for_loan_waiting_list_in );
394
395
    my $default_processing =
396
      $builder->build_object( { class => 'Koha::Preservation::Processings' } );
397
    my $another_processing =
398
      $builder->build_object( { class => 'Koha::Preservation::Processings' } );
399
400
    my $attributes = [
401
        {
402
            name          => 'color',
403
            type          => 'authorised_value',
404
            option_source => 'COLORS'
405
        },
406
        { name => 'title', type => 'db_column', option_source => '245$a' },
407
        {
408
            name => 'height',
409
            type => 'free_text'
410
        },
411
    ];
412
    my $processing_attributes = $default_processing->attributes($attributes);
413
    my $color_attribute =
414
      $processing_attributes->search( { name => 'color' } )->next;
415
    my $title_attribute =
416
      $processing_attributes->search( { name => 'title' } )->next;
417
    my $height_attribute =
418
      $processing_attributes->search( { name => 'height' } )->next;
419
420
    my $train = $builder->build_object(
421
        {
422
            class => 'Koha::Preservation::Trains',
423
            value => {
424
                not_for_loan          => $not_for_loan_train_in,
425
                default_processing_id => $default_processing->processing_id,
426
                closed_on             => undef,
427
                sent_on               => undef,
428
                received_on           => undef,
429
            }
430
        }
431
    );
432
    my $train_id = $train->train_id;
433
434
    my $item_1 = $builder->build_sample_item;
435
    my $item_2 = $builder->build_sample_item;
436
    my $item_3 = $builder->build_sample_item;
437
438
    # Add item not in waiting list
439
    $t->post_ok(
440
        "//$userid:$password@/api/v1/preservation/trains/$train_id/items" =>
441
          json => { item_id => $item_1->itemnumber } )->status_is(400)
442
      ->json_is( { error => 'Item not in waiting list' } );
443
444
    $item_1->notforloan($not_for_loan_waiting_list_in)->store;
445
446
    # Add item in waiting list
447
    my $item_attributes = [
448
        {
449
            processing_attribute_id => $color_attribute->processing_attribute_id,
450
            value => 'red'
451
        },
452
        {
453
            processing_attribute_id => $title_attribute->processing_attribute_id,
454
            value => 'my title'
455
        },
456
    ];
457
    my $train_item_id =
458
      $t->post_ok(
459
        "//$userid:$password@/api/v1/preservation/trains/$train_id/items" =>
460
          json =>
461
          { item_id => $item_1->itemnumber, attributes => $item_attributes } )
462
      ->status_is( 201, 'SWAGGER3.2.1' )
463
      ->json_is( '/item_id'       => $item_1->itemnumber )
464
      ->json_is( '/processing_id' => $train->default_processing_id )
465
      ->json_has('/added_on')->tx->res->json->{train_item_id};
466
    my $train_item = Koha::Preservation::Train::Items->find($train_item_id);
467
468
    $t->get_ok(
469
        "//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id"
470
          => { 'x-koha-embed' => 'attributes' } )->status_is(200)->json_is(
471
        {
472
            %{ $train_item->to_api },
473
            attributes => $train_item->attributes->to_api
474
        }
475
          );
476
477
    is( $item_1->get_from_storage->notforloan,
478
        $train->not_for_loan,
479
        "Item not for loan has been set to train's not for loan" );
480
481
    # Add deleted item
482
    $item_2->delete;
483
    $t->post_ok(
484
        "//$userid:$password@/api/v1/preservation/trains/$train_id/items" =>
485
          json => { item_id => $item_2->itemnumber } )->status_is(404)
486
      ->json_is( { error => 'Item not found' } );
487
488
    # Update item
489
    my $new_item_attributes = [
490
        {
491
            processing_attribute_id => $title_attribute->processing_attribute_id,
492
            value => 'my new title'
493
        },
494
        {
495
            processing_attribute_id => $height_attribute->processing_attribute_id,
496
            value => '24cm'
497
        },
498
    ];
499
    $t->put_ok(
500
        "//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id"
501
          => json => {
502
            item_id    => $item_1->itemnumber,
503
            attributes => $new_item_attributes,
504
          }
505
    )->status_is(200);
506
507
    $t->get_ok(
508
        "//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id"
509
          => { 'x-koha-embed' => 'attributes' } )->status_is(200)->json_is(
510
        {
511
            %{ $train_item->to_api },
512
            attributes => $train_item->attributes->to_api
513
        }
514
          );
515
516
    # Delete existing item
517
    $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id")
518
      ->status_is( 204, 'SWAGGER3.2.4' )->content_is( '', 'SWAGGER3.3.4' );
519
520
    # Delete non existing item
521
    $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id")
522
      ->status_is(404)->json_is( '/error' => 'Train item not found' );
523
524
    $schema->storage->txn_rollback;
525
};
(-)a/t/db_dependent/api/v1/preservation_WaitingList.t (-1 / +167 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::More tests => 1;
21
use Test::Mojo;
22
use Test::Warn;
23
24
use t::lib::TestBuilder;
25
use t::lib::Mocks;
26
27
use Koha::Preservation::Trains;
28
use Koha::Database;
29
use Koha::DateUtils qw( dt_from_string );
30
31
my $schema  = Koha::Database->new->schema;
32
my $builder = t::lib::TestBuilder->new;
33
34
my $t = Test::Mojo->new('Koha::REST::V1');
35
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
36
37
subtest 'add_item, list, remove_item tests' => sub {
38
39
    plan tests => 34;
40
41
    $schema->storage->txn_begin;
42
43
    my $librarian = $builder->build_object(
44
        {
45
            class => 'Koha::Patrons',
46
            value => { flags => 2**30 }
47
        }
48
    );
49
    my $password = 'thePassword123';
50
    $librarian->set_password( { password => $password, skip_validation => 1 } );
51
    my $userid = $librarian->userid;
52
53
    my $item_1 = $builder->build_sample_item;
54
    my $item_2 = $builder->build_sample_item;
55
    my $item_3 = $builder->build_sample_item;
56
57
    t::lib::Mocks::mock_preference( 'PreservationNotForLoanWaitingListIn', undef );
58
    $t->get_ok("//$userid:$password@/api/v1/preservation/waiting-list/items")
59
      ->status_is(400)->json_is(
60
        {
61
            error     => 'MissingSettings',
62
            parameter => 'PreservationNotForLoanWaitingListIn'
63
        }
64
      );
65
66
    my $not_for_loan_waiting_list_in = 24;
67
    t::lib::Mocks::mock_preference( 'PreservationNotForLoanWaitingListIn',
68
        $not_for_loan_waiting_list_in );
69
70
    $t->get_ok("//$userid:$password@/api/v1/preservation/waiting-list/items")
71
      ->status_is(200)->json_is( [] );
72
73
    # Add items
74
    $t->post_ok(
75
        "//$userid:$password@/api/v1/preservation/waiting-list/items" =>
76
          json => [
77
            { item_id => $item_1->itemnumber },
78
            { barcode => $item_3->barcode }
79
          ]
80
    )->status_is(201)->json_is(
81
        [
82
            { item_id => $item_1->itemnumber },
83
            { item_id => $item_3->itemnumber }
84
        ]
85
    );
86
87
    is( $item_1->get_from_storage->notforloan, $not_for_loan_waiting_list_in );
88
    is( $item_2->get_from_storage->notforloan, 0 );
89
    is( $item_3->get_from_storage->notforloan, $not_for_loan_waiting_list_in );
90
91
    $t->post_ok(
92
        "//$userid:$password@/api/v1/preservation/waiting-list/items" =>
93
          json => [
94
            { item_id => $item_2->itemnumber },
95
            { barcode => $item_3->barcode }
96
          ]
97
    )->status_is(201)->json_is( [ { item_id => $item_2->itemnumber } ] );
98
99
    is( $item_1->get_from_storage->notforloan, $not_for_loan_waiting_list_in );
100
    is( $item_2->get_from_storage->notforloan, $not_for_loan_waiting_list_in );
101
    is( $item_3->get_from_storage->notforloan, $not_for_loan_waiting_list_in );
102
103
    $t->delete_ok(
104
        "//$userid:$password@/api/v1/preservation/waiting-list/items/"
105
          . $item_2->itemnumber )->status_is(204);
106
107
    is( $item_2->get_from_storage->notforloan, 0,
108
        "Item removed from the waiting list has its notforloan status back to 0"
109
    );
110
111
    # Add item_1 to a non-received train
112
    my $train = $builder->build_object(
113
        {
114
            class => 'Koha::Preservation::Trains',
115
            value => {
116
                not_for_loan => 42,
117
                closed_on    => undef,
118
                sent_on      => undef,
119
                received_on  => undef
120
            }
121
        }
122
    );
123
    $train->add_item( { item_id => $item_1->itemnumber } );
124
125
    # And try to add it to the waiting list
126
    warning_like {
127
        $t->post_ok(
128
            "//$userid:$password@/api/v1/preservation/waiting-list/items" =>
129
              json => [ { item_id => $item_1->itemnumber } ] )->status_is(201)
130
          ->json_is( [] );
131
    }
132
    qr[Cannot add item to waiting list, it is already in a non-received train];
133
134
    # Add item_3 to a train, receive the train and add the item to the waiting list
135
    $train = $builder->build_object(
136
        {
137
            class => 'Koha::Preservation::Trains',
138
            value => {
139
                not_for_loan => 42,
140
                closed_on    => undef,
141
                sent_on      => undef,
142
                received_on  => undef
143
            }
144
        }
145
    );
146
    $train->add_item( { item_id => $item_3->itemnumber } );
147
    $train->received_on(dt_from_string)->store;
148
149
    $t->post_ok(
150
        "//$userid:$password@/api/v1/preservation/waiting-list/items" =>
151
          json => [ { item_id => $item_3->itemnumber } ] )->status_is(201)
152
      ->json_is( [ { item_id => $item_3->itemnumber } ] );
153
154
    $t->delete_ok(
155
        "//$userid:$password@/api/v1/preservation/waiting-list/items/"
156
          . $item_2->itemnumber )->status_is(204);
157
158
    $item_2->delete;
159
    $t->delete_ok("//$userid:$password@/api/v1/preservation/waiting-list/items")
160
      ->status_is(404);
161
162
    $t->delete_ok(
163
        "//$userid:$password@/api/v1/preservation/waiting-list/items/"
164
          . $item_2->itemnumber )->status_is(404);
165
166
    $schema->storage->txn_rollback;
167
};

Return to bug 30708