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

(-)a/t/cypress/integration/Display/Displays_spec.ts (+453 lines)
Line 0 Link Here
1
const dayjs = require("dayjs"); /* Cannot use our calendar JS code, it's in an include file (!)
2
                                   Also note that moment.js is deprecated */
3
4
const dates = {
5
    today_iso: dayjs().format("YYYY-MM-DD"),
6
    today_us: dayjs().format("MM/DD/YYYY"),
7
    tomorrow_iso: dayjs().add(1, "day").format("YYYY-MM-DD"),
8
    tomorrow_us: dayjs().add(1, "day").format("MM/DD/YYYY"),
9
};
10
11
describe("Displays - CRUD operations", () => {
12
    beforeEach(() => {
13
        cy.login();
14
        cy.title().should("eq", "Koha staff interface");
15
        cy.intercept(
16
            "GET",
17
            "/api/v1/displays/config",
18
            '{"settings":{"enabled":"1"}}'
19
        );
20
    });
21
22
    it("Add display", () => {
23
        cy.intercept("GET", /\/api\/v1\/displays.(?!config).*/, []);
24
        cy.visit("/cgi-bin/koha/display/display-home.pl");
25
26
        let display = cy.getDisplay();
27
        let displays = [display];
28
29
        cy.contains("New display").click();
30
        cy.get("#display_name").type(display.display_name);
31
        cy.get("#display_branch .vs__search").type("centerville" + "{enter}", {
32
            force: true,
33
        });
34
        cy.get("#display_holding_branch .vs__search").type(
35
            "centerville" + "{enter}",
36
            {
37
                force: true,
38
            }
39
        );
40
        cy.get("#display_location .vs__search").type(
41
            "general stacks" + "{enter}",
42
            {
43
                force: true,
44
            }
45
        );
46
        cy.get("#display_code .vs__search").type("reference" + "{enter}", {
47
            force: true,
48
        });
49
        cy.get("#display_itype .vs__search").type("books" + "{enter}", {
50
            force: true,
51
        });
52
        cy.get("#display_return_over .vs__search").type(
53
            "yes, any library" + "{enter}",
54
            {
55
                force: true,
56
            }
57
        );
58
        cy.get("#start_date")
59
            .invoke("attr", "value", display.start_date)
60
            .should("have.attr", "value", display.start_date);
61
        cy.get("#end_date")
62
            .invoke("attr", "value", display.start_date)
63
            .should("have.attr", "value", display.start_date);
64
        cy.get("#display_days").type(display.display_days);
65
        cy.get("#staff_note").type(display.staff_note);
66
        cy.get("#public_note").type(display.public_note);
67
        cy.get("#enabled_yes").click();
68
69
        // Submit the form, get 500
70
        cy.intercept("POST", "/api/v1/displays", {
71
            statusCode: 500,
72
            error: "Something went wrong",
73
        });
74
        cy.get("#displays_add").contains("Save").click();
75
        cy.get("main div[class='alert alert-warning']").contains(
76
            "Something went wrong: Error: Internal Server Error"
77
        );
78
79
        // Submit the form, success!
80
        cy.intercept("POST", "/api/v1/displays", {
81
            statusCode: 201,
82
            body: display,
83
        });
84
        cy.get("#displays_add").contains("Save").click();
85
        cy.get("main div[class='alert alert-info']").contains(
86
            "Display created"
87
        );
88
    });
89
90
    it("List displays", () => {
91
        // GET displays returns 500
92
        cy.intercept("GET", /\/api\/v1\/displays.(?!config).*/, {
93
            statusCode: 500,
94
        });
95
        cy.visit("/cgi-bin/koha/display/display-home.pl");
96
        cy.get(".sidebar_menu a").contains("Displays").click();
97
        cy.get("main div[class='alert alert-warning']").contains(
98
            "Something went wrong: Error: Internal Server Error"
99
        );
100
101
        // GET displays returns empty list
102
        cy.intercept("GET", /\/api\/v1\/displays.(?!config).*/, []);
103
        cy.visit("/cgi-bin/koha/display/displays");
104
        cy.get("#displays_list").contains("There are no displays defined");
105
106
        // GET displays returns something
107
        let display = cy.getDisplay();
108
        let displays = [display];
109
110
        cy.intercept("GET", /\/api\/v1\/displays.(?!config).*/, {
111
            statusCode: 200,
112
            body: displays,
113
            headers: {
114
                "X-Base-Total-Count": "1",
115
                "X-Total-Count": "1",
116
            },
117
        });
118
        cy.visit("/cgi-bin/koha/display/displays");
119
        cy.get("#displays_list").contains("Showing 1 to 1 of 1 entries");
120
    });
121
122
    it("Show display", () => {
123
        let display = cy.getDisplay();
124
        let displays = [display];
125
        let item = cy.getItem();
126
127
        // Click the "name" link from the list
128
        cy.intercept("GET", /\/api\/v1\/displays.(?!config).*/, {
129
            statusCode: 200,
130
            body: displays,
131
            headers: {
132
                "X-Base-Total-Count": "1",
133
                "X-Total-Count": "1",
134
            },
135
        }).as("get-displays");
136
        cy.intercept("GET", /\/api\/v1\/displays\/\d+/, display).as(
137
            "get-display"
138
        );
139
        cy.intercept("GET", /\/api\/v1\/items\/\d+/, {
140
            statusCode: 200,
141
            body: item,
142
        }).as("get-item");
143
144
        cy.visit("/cgi-bin/koha/display/displays");
145
        cy.wait("@get-displays");
146
        let id_cell = cy.get("#displays_list table tbody tr:first td:first");
147
        id_cell.contains(display.display_id);
148
149
        let name_link = cy
150
            .get("#displays_list table tbody tr:first td")
151
            .eq(1)
152
            .find("a");
153
        name_link.should("have.text", display.display_name);
154
        name_link.click();
155
        cy.wait("@get-item");
156
        cy.get("#displays_show h2").contains("Display #" + display.display_id);
157
        cy.left_menu_active_item_is("Displays");
158
    });
159
160
    it("Edit display", () => {
161
        let display = cy.getDisplay();
162
        let displays = [display];
163
        let item = cy.getItem();
164
165
        // Click the 'Edit' button from the list
166
        cy.intercept("GET", /\/api\/v1\/displays.(?!config).*/, {
167
            statusCode: 200,
168
            body: displays,
169
            headers: {
170
                "X-Base-Total-Count": "1",
171
                "X-Total-Count": "1",
172
            },
173
        }).as("get-displays");
174
        cy.intercept("GET", /\/api\/v1\/displays\/\d+/, display).as(
175
            "get-display"
176
        );
177
        cy.intercept("GET", /\/api\/v1\/items\/\d+/, {
178
            statusCode: 200,
179
            body: item,
180
        }).as("get-item");
181
182
        cy.visit("/cgi-bin/koha/display/displays");
183
        cy.wait("@get-displays");
184
        cy.get("#displays_list table tbody tr:first").contains("Edit").click();
185
        cy.wait("@get-item");
186
        cy.get("#displays_add h2").contains("Edit display");
187
        cy.left_menu_active_item_is("Displays");
188
189
        // Form has been correctly filled in
190
        cy.get("#display_name").should("have.value", display.display_name);
191
192
        cy.get("#display_holding_branch .vs__selected").contains("Centerville");
193
        cy.get("#display_code .vs__selected").contains("Reference");
194
        cy.get("#start_date").invoke("val").should("eq", "2025-01-01");
195
        cy.get("#end_date").invoke("val").should("eq", "2036-12-31");
196
        cy.get("#public_note").invoke("val").should("eq", "A public note");
197
198
        // Test related item
199
        cy.get("#display_items_barcode_0")
200
            .invoke("val")
201
            .should("eq", item.external_id);
202
203
        // Submit the form, get 500
204
        cy.intercept("PUT", "/api/v1/displays/*", {
205
            statusCode: 500,
206
        });
207
        cy.get("#displays_add").contains("Save").click();
208
        cy.get("main div[class='alert alert-warning']").contains(
209
            "Something went wrong: Error: Internal Server Error"
210
        );
211
212
        // Submit the form, success!
213
        cy.intercept("PUT", "/api/v1/displays/*", {
214
            statusCode: 200,
215
            body: display,
216
        });
217
        cy.get("#displays_add").contains("Save").click();
218
        cy.get("main div[class='alert alert-info']").contains(
219
            "Display updated"
220
        );
221
    });
222
223
    it("Delete display", () => {
224
        let display = cy.getDisplay();
225
        let displays = [display];
226
        let item = cy.getItem();
227
228
        // Click the 'Delete' button from the list
229
        cy.intercept("GET", /\/api\/v1\/displays.(?!config).*/, {
230
            statusCode: 200,
231
            body: displays,
232
            headers: {
233
                "X-Base-Total-Count": "1",
234
                "X-Total-Count": "1",
235
            },
236
        });
237
        cy.intercept("GET", /\/api\/v1\/displays\/\d+/, display);
238
        cy.visit("/cgi-bin/koha/display/displays");
239
240
        cy.get("#displays_list table tbody tr:first")
241
            .contains("Delete")
242
            .click();
243
        cy.get(".alert-warning.confirmation h1").contains(
244
            "remove this display"
245
        );
246
        cy.contains(display.display_name);
247
248
        // Accept the confirmation dialog, get 500
249
        cy.intercept("DELETE", "/api/v1/displays/*", {
250
            statusCode: 500,
251
        });
252
        cy.contains("Yes, delete").click();
253
        cy.get("main div[class='alert alert-warning']").contains(
254
            "Something went wrong: Error: Internal Server Error"
255
        );
256
257
        // Accept the confirmation dialog, success!
258
        cy.intercept("DELETE", "/api/v1/displays/*", {
259
            statusCode: 204,
260
            body: null,
261
        });
262
        cy.get("#displays_list table tbody tr:first")
263
            .contains("Delete")
264
            .click();
265
        cy.get(".alert-warning.confirmation h1").contains(
266
            "remove this display"
267
        );
268
        cy.contains("Yes, delete").click();
269
        cy.get("main div[class='alert alert-info']")
270
            .contains("Display")
271
            .contains("deleted");
272
273
        // Delete from show
274
        // Click the "name" link from the list
275
        cy.intercept("GET", /\/api\/v1\/displays.(?!config).*/, {
276
            statusCode: 200,
277
            body: displays,
278
            headers: {
279
                "X-Base-Total-Count": "1",
280
                "X-Total-Count": "1",
281
            },
282
        }).as("get-displays");
283
        cy.intercept("GET", /\/api\/v1\/displays\/\d+/, display).as(
284
            "get-display"
285
        );
286
        cy.intercept("GET", /\/api\/v1\/items\/\d+/, {
287
            statusCode: 200,
288
            body: item,
289
        }).as("get-item");
290
291
        cy.visit("/cgi-bin/koha/display/displays");
292
        cy.wait("@get-displays");
293
        let id_cell = cy.get("#displays_list table tbody tr:first td:first");
294
        id_cell.contains(display.display_id);
295
296
        let name_link = cy
297
            .get("#displays_list table tbody tr:first td")
298
            .eq(1)
299
            .find("a");
300
        name_link.should("have.text", display.display_name);
301
        name_link.click();
302
        cy.wait("@get-display");
303
        cy.get("#displays_show h2").contains("Display #" + display.display_id);
304
305
        cy.get("#displays_show #toolbar").contains("Delete").click();
306
        cy.get(".alert-warning.confirmation h1").contains(
307
            "remove this display"
308
        );
309
        cy.contains("Yes, delete").click();
310
311
        //Make sure we return to list after deleting from show
312
        cy.get("#displays_list table tbody tr:first");
313
    });
314
315
    it("Batch add items", () => {
316
        let display = cy.getDisplay();
317
        let displays = [display];
318
        let batch = {
319
            job_id: 1,
320
            message: "Batch add operation queued",
321
        };
322
        let batches = [batch];
323
        let item = cy.getItem();
324
325
        // Click the "batch add" link from the list
326
        cy.intercept("GET", /\/api\/v1\/displays.(?!config).*/, {
327
            statusCode: 200,
328
            body: displays,
329
            headers: {
330
                "X-Base-Total-Count": "1",
331
                "X-Total-Count": "1",
332
            },
333
        }).as("get-displays");
334
        cy.intercept("GET", /\/api\/v1\/displays\/\d+/, display).as(
335
            "get-display"
336
        );
337
        cy.intercept("GET", /\/api\/v1\/items\/\d+/, {
338
            statusCode: 200,
339
            body: item,
340
        }).as("get-item");
341
342
        cy.visit("/cgi-bin/koha/display/display-home.pl");
343
        cy.contains("Batch add items from list").click();
344
345
        cy.get("#barcodes").type("39999000002355\n39999000002331\n\n");
346
        cy.get("#display_id .vs__search").type(
347
            display.display_name + "{enter}",
348
            {
349
                force: true,
350
            }
351
        );
352
        cy.get("#date_remove")
353
            .invoke("attr", "value", display.end_date)
354
            .should("have.attr", "value", display.end_date);
355
356
        // Submit the form, get 500
357
        cy.intercept("POST", "/api/v1/display/items/batch", {
358
            statusCode: 500,
359
            error: "Something went wrong",
360
        });
361
        cy.get("#list").contains("Save").click();
362
        cy.get("main div[class='alert alert-warning']").contains(
363
            "Internal Server Error. Please check the browser console for diagnostic information."
364
        );
365
366
        cy.get("#barcodes").type("39999000002355\n39999000002331\n\n");
367
        cy.get("#display_id .vs__search").type(
368
            display.display_name + "{enter}",
369
            {
370
                force: true,
371
            }
372
        );
373
        cy.get("#date_remove")
374
            .invoke("attr", "value", display.end_date)
375
            .should("have.attr", "value", display.end_date);
376
377
        // Submit the form, success!
378
        cy.intercept("POST", "/api/v1/display/items/batch", {
379
            statusCode: 202,
380
            body: batch,
381
        });
382
        cy.get("#list").contains("Save").click();
383
        cy.get("main div[class='alert alert-info']").contains(
384
            "Batch job successfully queued"
385
        );
386
    });
387
388
    it("Batch delete items", () => {
389
        let display = cy.getDisplay();
390
        let displays = [display];
391
        let batch = {
392
            job_id: 2,
393
            message: "Batch add operation queued",
394
        };
395
        let batches = [batch];
396
        let item = cy.getItem();
397
398
        // Click the "batch add" link from the list
399
        cy.intercept("GET", /\/api\/v1\/displays.(?!config).*/, {
400
            statusCode: 200,
401
            body: displays,
402
            headers: {
403
                "X-Base-Total-Count": "1",
404
                "X-Total-Count": "1",
405
            },
406
        }).as("get-displays");
407
        cy.intercept("GET", /\/api\/v1\/displays\/\d+/, display).as(
408
            "get-display"
409
        );
410
        cy.intercept("GET", /\/api\/v1\/items\/\d+/, {
411
            statusCode: 200,
412
            body: item,
413
        }).as("get-item");
414
415
        cy.visit("/cgi-bin/koha/display/display-home.pl");
416
        cy.contains("Batch remove items from list").click();
417
418
        cy.get("#barcodes").type("39999000002355\n39999000002331\n\n");
419
        cy.get("#display_id .vs__search").type(
420
            display.display_name + "{enter}",
421
            {
422
                force: true,
423
            }
424
        );
425
426
        // Submit the form, get 500
427
        cy.intercept("DELETE", "/api/v1/display/items/batch", {
428
            statusCode: 500,
429
        });
430
        cy.get("#list").contains("Save").click();
431
        cy.get("main div[class='alert alert-warning']").contains(
432
            "Internal Server Error. Please check the browser console for diagnostic information."
433
        );
434
435
        cy.get("#barcodes").type("39999000002355\n39999000002331\n\n");
436
        cy.get("#display_id .vs__search").type(
437
            display.display_name + "{enter}",
438
            {
439
                force: true,
440
            }
441
        );
442
443
        // Submit the form, success!
444
        cy.intercept("DELETE", "/api/v1/display/items/batch", {
445
            statusCode: 202,
446
            body: batch,
447
        });
448
        cy.get("#list").contains("Save").click();
449
        cy.get("main div[class='alert alert-info']").contains(
450
            "Batch job successfully queued"
451
        );
452
    });
453
});
(-)a/t/cypress/integration/Display/Main.ts (+39 lines)
Line 0 Link Here
1
describe("Main component - pref off", () => {
2
    beforeEach(() => {
3
        cy.login();
4
        cy.title().should("eq", "Koha staff interface");
5
        cy.intercept(
6
            "GET",
7
            "/api/v1/displays/config",
8
            '{"settings":{"enabled":"0"}}'
9
        );
10
    });
11
12
    it("Home", () => {
13
        cy.visit("/cgi-bin/koha/display/display-home.pl");
14
        cy.get(".main .sidebar_menu").should("not.exist");
15
        cy.get(".main div[class='alert alert-warning']").contains(
16
            "The displays module is disabled, turn on UseDisplayModule to use it"
17
        );
18
        cy.get(".main div[class='alert alert-warning'] a").click();
19
        cy.url().should("match", /\/cgi-bin\/koha\/admin\/preferences.pl/);
20
    });
21
});
22
23
describe("Main component - pref on", () => {
24
    beforeEach(() => {
25
        cy.login();
26
        cy.title().should("eq", "Koha staff interface");
27
        cy.intercept(
28
            "GET",
29
            "/api/v1/displays/config",
30
            '{"settings":{"enabled":"1"}}'
31
        );
32
    });
33
34
    it("Home", () => {
35
        cy.visit("/cgi-bin/koha/display/display-home.pl");
36
        cy.get(".main .sidebar_menu").should("exist");
37
        cy.get(".main div[class='alert alert-warning']").should("not.exist");
38
    });
39
});
(-)a/t/cypress/support/e2e.js (-1 / +134 lines)
Lines 1963-1968 cy.getSIP2Institution = () => { Link Here
1963
    };
1963
    };
1964
};
1964
};
1965
1965
1966
cy.getItem = () => {
1967
    return {
1968
        acquisition_date: "2014-09-04",
1969
        acquisition_source: null,
1970
        biblio_id: 58,
1971
        bookable: false,
1972
        call_number_sort: "_",
1973
        call_number_source: null,
1974
        callnumber: null,
1975
        checked_out_date: null,
1976
        checkouts_count: null,
1977
        coded_location_qualifier: null,
1978
        collection_code: "REF",
1979
        copy_number: null,
1980
        damaged_date: null,
1981
        damaged_status: 0,
1982
        effective_bookable: false,
1983
        effective_collection_code: "REF",
1984
        effective_holding_library_id: "CPL",
1985
        effective_home_library_id: "CPL",
1986
        effective_item_type_id: "BK",
1987
        effective_location: "GEN",
1988
        effective_not_for_loan_status: 0,
1989
        exclude_from_local_holds_priority: false,
1990
        extended_subfields: null,
1991
        external_id: "39999000002355",
1992
        holding_library_id: "CPL",
1993
        holds_count: null,
1994
        home_library_id: "CPL",
1995
        internal_notes: null,
1996
        inventory_number: null,
1997
        item_id: 125,
1998
        item_type_id: "BK",
1999
        last_checkout_date: null,
2000
        last_seen_date: "2014-09-04T00:00:00+00:00",
2001
        localuse: null,
2002
        location: "GEN",
2003
        lost_date: null,
2004
        lost_status: 0,
2005
        materials_notes: null,
2006
        new_status: null,
2007
        not_for_loan_status: 0,
2008
        permanent_location: "GEN",
2009
        public_notes: null,
2010
        purchase_price: null,
2011
        renewals_count: null,
2012
        replacement_price: null,
2013
        replacement_price_date: "2014-09-04",
2014
        restricted_status: null,
2015
        serial_issue_number: null,
2016
        shelving_control_number: null,
2017
        timestamp: "2020-01-29T13:06:19+00:00",
2018
        uri: null,
2019
        withdrawn: 0,
2020
        withdrawn_date: null,
2021
    };
2022
};
2023
1966
cy.getItemTypes = () => {
2024
cy.getItemTypes = () => {
1967
    return [
2025
    return [
1968
        {
2026
        {
Lines 2144-2149 cy.getItemTypes = () => { Link Here
2144
    ];
2202
    ];
2145
};
2203
};
2146
2204
2205
cy.getDisplay = () => {
2206
    return {
2207
        display_branch: "CPL",
2208
        display_code: "REF",
2209
        display_days: 4382,
2210
        display_holding_branch: "CPL",
2211
        display_id: 1,
2212
        display_items: [
2213
            {
2214
                biblionumber: 58,
2215
                date_added: null,
2216
                date_remove: "2036-12-31",
2217
                display_id: 1,
2218
                display_item_id: 1,
2219
                itemnumber: 125,
2220
            },
2221
        ],
2222
        display_itype: "BK",
2223
        display_location: "GEN",
2224
        display_name: "Test display #1",
2225
        display_return_over: "yes - any library",
2226
        enabled: true,
2227
        end_date: "2036-12-31",
2228
        item_type: {
2229
            automatic_checkin: false,
2230
            bookable: false,
2231
            checkin_message: null,
2232
            checkin_message_type: "message",
2233
            checkprevcheckout: "inherit",
2234
            daily_rental_charge: null,
2235
            daily_rental_charge_calendar: true,
2236
            default_replacement_cost: null,
2237
            description: "Books",
2238
            hide_in_opac: false,
2239
            hourly_rental_charge: null,
2240
            hourly_rental_charge_calendar: true,
2241
            image_url: "bridge/book.png",
2242
            item_type_id: "BK",
2243
            not_for_loan_status: false,
2244
            parent_type: null,
2245
            process_fee: null,
2246
            rentalcharge: 0.0,
2247
            searchcategory: null,
2248
            sip_media_type: null,
2249
            summary: "",
2250
        },
2251
        library: {
2252
            address1: "Jefferson Summit",
2253
            address2: null,
2254
            address3: null,
2255
            city: null,
2256
            country: null,
2257
            email: null,
2258
            fax: null,
2259
            geolocation: null,
2260
            ill_email: null,
2261
            ip: null,
2262
            library_id: "CPL",
2263
            marc_org_code: null,
2264
            name: "Centerville",
2265
            notes: null,
2266
            phone: null,
2267
            pickup_location: true,
2268
            postal_code: null,
2269
            public: true,
2270
            reply_to_email: null,
2271
            return_path_email: null,
2272
            state: null,
2273
            url: null,
2274
        },
2275
        public_note: "A public note",
2276
        staff_note: "A staff-only note",
2277
        start_date: "2025-01-01",
2278
    };
2279
};
2280
2147
Cypress.Commands.add("set_syspref", (variable, value) => {
2281
Cypress.Commands.add("set_syspref", (variable, value) => {
2148
    cy.window().then(win => {
2282
    cy.window().then(win => {
2149
        const client = win.APIClient.sysprefs;
2283
        const client = win.APIClient.sysprefs;
2150
- 

Return to bug 14962