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

(-)a/t/cypress/integration/KohaTable/Holdings_spec.ts (-2 / +2 lines)
Lines 24-30 describe("catalogue/detail/holdings_table with items", () => { Link Here
24
    });
24
    });
25
25
26
    afterEach(function () {
26
    afterEach(function () {
27
        cy.task("deleteSampleObjects", this.objects);
27
        cy.task("deleteSampleObjects", [this.objects]);
28
        cy.set_syspref(
28
        cy.set_syspref(
29
            "AlwaysShowHoldingsTableFilters",
29
            "AlwaysShowHoldingsTableFilters",
30
            this.syspref_AlwaysShowHoldingsTableFilters
30
            this.syspref_AlwaysShowHoldingsTableFilters
Lines 279-285 describe("catalogue/detail/holdings_table without items", () => { Link Here
279
    });
279
    });
280
280
281
    afterEach(function () {
281
    afterEach(function () {
282
        cy.task("deleteSampleObjects", this.objects);
282
        cy.task("deleteSampleObjects", [this.objects]);
283
        cy.set_syspref(
283
        cy.set_syspref(
284
            "AlwaysShowHoldingsTableFilters",
284
            "AlwaysShowHoldingsTableFilters",
285
            this.syspref_AlwaysShowHoldingsTableFilters
285
            this.syspref_AlwaysShowHoldingsTableFilters
(-)a/t/cypress/integration/KohaTable/PendingHolds_spec.ts (+49 lines)
Line 0 Link Here
1
describe("circ/pendingreserves/holdst", () => {
2
    const table_id = "holdst";
3
    beforeEach(() => {
4
        cy.login();
5
        cy.title().should("eq", "Koha staff interface");
6
        cy.task("insertSampleBiblio", { item_count: 1 }).then(
7
            objects_biblio_1 => {
8
                cy.wrap(objects_biblio_1).as("objects_biblio_1");
9
                cy.task("insertSampleHold", {
10
                    item: objects_biblio_1.items[0],
11
                }).then(objects_hold_1 => {
12
                    cy.wrap(objects_hold_1).as("objects_hold_1");
13
                });
14
15
                cy.task("insertSampleHold", {
16
                    item: objects_biblio_1.items[0],
17
                }).then(objects_hold_2 => {
18
                    cy.wrap(objects_hold_2).as("objects_hold_2");
19
                });
20
            }
21
        );
22
        cy.task("insertSampleBiblio", { item_count: 1 }).then(
23
            objects_biblio_2 => {
24
                cy.wrap(objects_biblio_2).as("objects_biblio_2");
25
                cy.task("insertSampleHold", {
26
                    item: objects_biblio_2.items[0],
27
                }).then(objects_hold_3 => {
28
                    cy.wrap(objects_hold_3).as("objects_hold_3");
29
                });
30
            }
31
        );
32
    });
33
34
    afterEach(function () {
35
        cy.task("deleteSampleObjects", [
36
            this.objects_hold_1,
37
            this.objects_hold_2,
38
            this.objects_hold_3,
39
            this.objects_biblio_2,
40
            this.objects_biblio_1,
41
        ]);
42
    });
43
44
    it("test", function () {
45
        cy.visit(
46
            "/cgi-bin/koha/circ/pendingreserves.pl?from=2000-01-01&to=2999-12-31&run_report=Submit"
47
        );
48
    });
49
});
(-)a/t/cypress/integration/t/insertData.ts (-5 / +7 lines)
Lines 1-11 Link Here
1
const { query } = require("./../../plugins/db.js");
1
const { query } = require("./../../plugins/db.js");
2
2
3
describe("insertSampleBiblio", () => {
3
describe("insertSampleBiblio", () => {
4
    it("should generate library and item type", () => {
4
    it("insertSampleBiblio - should generate library and item type", () => {
5
        cy.task("insertSampleBiblio", { item_count: 3 }).then(objects => {
5
        cy.task("insertSampleBiblio", { item_count: 3 }).then(objects => {
6
            const biblio_id = objects.biblio.biblio_id;
6
            expect(typeof objects.biblio.biblio_id).to.be.equal("number");
7
            expect(typeof objects.biblio.title).to.be.equal("string");
8
            expect(typeof objects.biblio.author).to.be.equal("string");
7
9
8
            expect(typeof biblio_id).to.be.equal("number");
10
            const biblio_id = objects.biblio.biblio_id;
9
11
10
            cy.task("query", {
12
            cy.task("query", {
11
                sql: "SELECT COUNT(*) as count FROM biblio WHERE biblionumber=?",
13
                sql: "SELECT COUNT(*) as count FROM biblio WHERE biblionumber=?",
Lines 30-36 describe("insertSampleBiblio", () => { Link Here
30
32
31
            cy.task("query", {
33
            cy.task("query", {
32
                sql: "SELECT COUNT(*) as count FROM branches WHERE branchcode=?",
34
                sql: "SELECT COUNT(*) as count FROM branches WHERE branchcode=?",
33
                values: [objects.library.library_id],
35
                values: [objects.libraries[0].library_id],
34
            }).then(result => {
36
            }).then(result => {
35
                expect(result[0].count).to.be.equal(1);
37
                expect(result[0].count).to.be.equal(1);
36
            });
38
            });
Lines 60-66 describe("insertSampleBiblio", () => { Link Here
60
62
61
            cy.task("query", {
63
            cy.task("query", {
62
                sql: "SELECT COUNT(*) as count FROM branches WHERE branchcode=?",
64
                sql: "SELECT COUNT(*) as count FROM branches WHERE branchcode=?",
63
                values: [objects.library.library_id],
65
                values: [objects.libraries[0].library_id],
64
            }).then(result => {
66
            }).then(result => {
65
                expect(result[0].count).to.be.equal(0);
67
                expect(result[0].count).to.be.equal(0);
66
            });
68
            });
(-)a/t/cypress/plugins/index.js (-4 / +8 lines)
Lines 4-9 const { buildSampleObject, buildSampleObjects } = require("./mockData.js"); Link Here
4
4
5
const {
5
const {
6
    insertSampleBiblio,
6
    insertSampleBiblio,
7
    insertSampleHold,
7
    insertObject,
8
    insertObject,
8
    deleteSampleObjects,
9
    deleteSampleObjects,
9
} = require("./insertData.js");
10
} = require("./insertData.js");
Lines 36-46 module.exports = (on, config) => { Link Here
36
        },
37
        },
37
        buildSampleObject,
38
        buildSampleObject,
38
        buildSampleObjects,
39
        buildSampleObjects,
39
        insertSampleBiblio({ item_count }) {
40
        insertSampleBiblio(args) {
40
            return insertSampleBiblio(item_count, baseUrl, authHeader);
41
            return insertSampleBiblio({ ...args, baseUrl, authHeader });
41
        },
42
        },
42
        insertObject({ type, object }) {
43
        insertSampleHold(args) {
43
            return insertObject(type, object, baseUrl, authHeader);
44
            return insertSampleHold({ ...args, baseUrl, authHeader });
45
        },
46
        insertObject(args) {
47
            return insertObject({ ...args, baseUrl, authHeader });
44
        },
48
        },
45
        deleteSampleObjects,
49
        deleteSampleObjects,
46
        query,
50
        query,
(-)a/t/cypress/plugins/insertData.js (-71 / +212 lines)
Lines 3-29 const { query } = require("./db.js"); Link Here
3
3
4
const { apiGet, apiPost } = require("./api-client.js");
4
const { apiGet, apiPost } = require("./api-client.js");
5
5
6
const insertSampleBiblio = async (item_count, baseUrl, authHeader) => {
6
const insertSampleBiblio = async ({
7
    let generated_objects = {};
7
    item_count,
8
    const objects = [{ object: "library" }, { object: "item_type" }];
8
    options,
9
    for (const { object } of objects) {
9
    baseUrl,
10
        const attributes = await buildSampleObject({ object });
10
    authHeader,
11
        generated_objects[object] = attributes;
11
}) => {
12
    }
13
12
14
    const library = await insertObject(
13
    const generatedItemType = await buildSampleObject({ object: "item_type" });
15
        "library",
14
    const item_type = await insertObject({
16
        generated_objects["library"],
15
        type: "item_type",
16
        object: generatedItemType,
17
        baseUrl,
17
        baseUrl,
18
        authHeader
18
        authHeader,
19
    );
19
    });
20
    const item_type = await insertObject(
21
        "item_type",
22
        generated_objects["item_type"],
23
        baseUrl,
24
        authHeader
25
    );
26
20
21
    let title = "Some boring read";
22
    let author = "Some boring author";
27
    let biblio = {
23
    let biblio = {
28
        leader: "     nam a22     7a 4500",
24
        leader: "     nam a22     7a 4500",
29
        fields: [
25
        fields: [
Lines 32-45 const insertSampleBiblio = async (item_count, baseUrl, authHeader) => { Link Here
32
                245: {
28
                245: {
33
                    ind1: "",
29
                    ind1: "",
34
                    ind2: "",
30
                    ind2: "",
35
                    subfields: [{ a: "Some boring read" }],
31
                    subfields: [{ a: title }],
36
                },
32
                },
37
            },
33
            },
38
            {
34
            {
39
                100: {
35
                100: {
40
                    ind1: "",
36
                    ind1: "",
41
                    ind2: "",
37
                    ind2: "",
42
                    subfields: [{ c: "Some boring author" }],
38
                    subfields: [{ c: author }],
43
                },
39
                },
44
            },
40
            },
45
            {
41
            {
Lines 66-71 const insertSampleBiblio = async (item_count, baseUrl, authHeader) => { Link Here
66
    // We might need to refine that in the future
62
    // We might need to refine that in the future
67
    biblio = {
63
    biblio = {
68
        biblio_id,
64
        biblio_id,
65
        title,
66
        author,
69
    };
67
    };
70
68
71
    let items = buildSampleObjects({
69
    let items = buildSampleObjects({
Lines 80-88 const insertSampleBiblio = async (item_count, baseUrl, authHeader) => { Link Here
80
            restricted_status: 0,
78
            restricted_status: 0,
81
            new_status: null,
79
            new_status: null,
82
            issues: 0,
80
            issues: 0,
81
            checked_out_date: null,
83
            item_type_id: item_type.item_type_id,
82
            item_type_id: item_type.item_type_id,
84
            home_library_id: library.library_id,
85
            holding_library_id: library.library_id,
86
        },
83
        },
87
    });
84
    });
88
    items = items.map(
85
    items = items.map(
Lines 123-181 const insertSampleBiblio = async (item_count, baseUrl, authHeader) => { Link Here
123
        }) => rest
120
        }) => rest
124
    );
121
    );
125
    let createdItems = [];
122
    let createdItems = [];
126
    for (const item of items) {
123
    let libraries = [];
127
        await apiPost({
124
    let commonLibrary;
128
            endpoint: `/api/v1/biblios/${biblio_id}/items`,
125
    if (!options || !options.different_libraries) {
129
            body: item,
126
        const generatedLibrary = await buildSampleObject({ object: "library" });
127
        commonLibrary = await insertObject({
128
            type: "library",
129
            object: generatedLibrary,
130
            baseUrl,
130
            baseUrl,
131
            authHeader,
131
            authHeader,
132
        }).then(i => createdItems.push(i));
132
        });
133
        libraries.push(commonLibrary);
133
    }
134
    }
134
    return { biblio, items: createdItems, library, item_type };
135
    for (const item of items) {
136
        if (options?.different_libraries) {
137
            const generatedLibrary = await buildSampleObject({
138
                object: "library",
139
            });
140
            const library = await insertObject({
141
                type: "library",
142
                object: generatedLibrary,
143
                baseUrl,
144
                authHeader,
145
            });
146
            libraries.push(library);
147
            item.home_library_id = library.library_id;
148
            item.holding_library_id = library.library_id;
149
        } else {
150
            item.home_library_id = commonLibrary.library_id;
151
            item.holding_library_id = commonLibrary.library_id;
152
        }
153
154
        await apiPost({
155
                endpoint: `/api/v1/biblios/${biblio_id}/items`,
156
                body: item,
157
                baseUrl,
158
                authHeader,
159
            })
160
            .then(i => createdItems.push(i));
161
    }
162
    return { biblio, items: createdItems, libraries, item_type };
163
};
164
165
const insertSampleHold = async ({
166
    item,
167
    biblio,
168
    library_id,
169
    baseUrl,
170
    authHeader,
171
}) => {
172
173
    library_id ||= item.home_library_id;
174
    const generatedPatron = await buildSampleObject({
175
        object: "patron",
176
        values: { library_id },
177
    });
178
179
    const patron = await insertObject({
180
        type: "patron",
181
        object: generatedPatron,
182
        baseUrl,
183
        authHeader,
184
    });
185
186
    const generatedHold = buildSampleObject({
187
        object: "hold",
188
        values: {
189
            patron_id: patron.patron_id,
190
            biblio_id: item?.biblio_id || biblio.biblio_id,
191
            pickup_library_id: library_id,
192
            item_id: item?.item_id || null,
193
        },
194
    });
195
    const hold = await insertObject({
196
        type: "hold",
197
        object: generatedHold,
198
        baseUrl,
199
        authHeader,
200
    });
201
    return { hold, patron };
135
};
202
};
136
203
137
const deleteSampleObjects = async objects => {
204
const deleteSampleObjects = async allObjects => {
138
    const deletionOrder = ["items", "biblio", "library", "item_type"];
205
    if (!Array.isArray(allObjects)) {
206
        allObjects = [allObjects];
207
    }
208
209
    const deletionOrder = [
210
        "hold",
211
        "patron",
212
        "item",
213
        "items",
214
        "biblio",
215
        "library",
216
        "libraries",
217
        "item_type",
218
    ];
219
139
    for (const type of deletionOrder) {
220
    for (const type of deletionOrder) {
140
        if (!objects.hasOwnProperty(type)) {
221
        for (const objects of allObjects) {
141
            continue;
222
            if (!objects.hasOwnProperty(type)) {
142
        }
223
                continue;
143
        if (Array.isArray(objects[type]) && objects[type].length == 0) {
224
            }
144
            // Empty array
225
            if (Array.isArray(objects[type]) && objects[type].length == 0) {
145
            continue;
226
                // Empty array
146
        }
227
                continue;
147
        switch (type) {
228
            }
148
            case "biblio":
229
            switch (type) {
149
                await query({
230
                case "biblio":
150
                    sql: "DELETE FROM biblio WHERE biblionumber=?",
231
                    await query({
151
                    values: [objects[type].biblio_id],
232
                        sql: "DELETE FROM biblio WHERE biblionumber=?",
152
                });
233
                        values: [objects[type].biblio_id],
153
                break;
234
                    });
154
            case "items":
235
                    break;
155
                let item_ids = objects[type].map(i => i.item_id);
236
                case "items":
156
                await query({
237
                    let item_ids = objects[type].map(i => i.item_id);
157
                    sql: `DELETE FROM items WHERE itemnumber IN (${item_ids.map(() => "?").join(",")})`,
238
                    await query({
158
                    values: item_ids,
239
                        sql: `DELETE FROM items WHERE itemnumber IN (${item_ids.map(() => "?").join(",")})`,
159
                });
240
                        values: item_ids,
160
                break;
241
                    });
161
            case "item":
242
                    break;
162
                await query({
243
                case "item":
163
                    sql: "DELETE FROM items WHERE itemnumber = ?",
244
                    await query({
164
                    values: [objects[type].item_id],
245
                        sql: "DELETE FROM items WHERE itemnumber = ?",
165
                });
246
                        values: [objects[type].item_id],
166
                break;
247
                    });
167
            case "library":
248
                    break;
168
                await query({
249
                case "library":
169
                    sql: "DELETE FROM branches WHERE branchcode = ?",
250
                    await query({
170
                    values: [objects[type].library_id],
251
                        sql: "DELETE FROM branches WHERE branchcode = ?",
171
                });
252
                        values: [objects[type].library_id],
172
                break;
253
                    });
173
            case "item_type":
254
                    break;
174
                await query({
255
                case "libraries":
175
                    sql: "DELETE FROM itemtypes WHERE itemtype = ?",
256
                    let library_ids = objects[type].map(i => i.library_id);
176
                    values: [objects[type].item_type_id],
257
                    await query({
177
                });
258
                        sql: `DELETE FROM branches WHERE branchcode IN (${library_ids.map(() => "?").join(",")})`,
178
                break;
259
                        values: library_ids,
260
                    });
261
                    break;
262
                case "hold":
263
                    await query({
264
                        sql: "DELETE FROM reserves WHERE reserve_id = ?",
265
                        values: [objects[type].hold_id],
266
                    });
267
                    break;
268
                case "item_type":
269
                    await query({
270
                        sql: "DELETE FROM itemtypes WHERE itemtype = ?",
271
                        values: [objects[type].item_type_id],
272
                    });
273
                    break;
274
                case "patron":
275
                    await query({
276
                        sql: "DELETE FROM borrowers WHERE borrowernumber = ?",
277
                        values: [objects[type].patron_id],
278
                    });
279
                    break;
280
                default:
281
                    console.log(
282
                        `Not implemented yet: cannot deleted object '${type}'`
283
                    );
284
            }
179
        }
285
        }
180
    }
286
    }
181
    return true;
287
    return true;
Lines 199-205 const insertLibrary = async (library, baseUrl, authHeader) => { Link Here
199
    });
305
    });
200
};
306
};
201
307
202
const insertObject = async (type, object, baseUrl, authHeader) => {
308
const insertObject = async ({ type, object, baseUrl, authHeader }) => {
203
    if (type == "patron") {
309
    if (type == "patron") {
204
        await query({
310
        await query({
205
            sql: "SELECT COUNT(*) AS count FROM branches WHERE branchcode = ?",
311
            sql: "SELECT COUNT(*) AS count FROM branches WHERE branchcode = ?",
Lines 274-279 const insertObject = async (type, object, baseUrl, authHeader) => { Link Here
274
                });
380
                });
275
            })
381
            })
276
            .then(item_types => item_types[0]);
382
            .then(item_types => item_types[0]);
383
    } else if (type == "hold") {
384
        const {
385
            hold_id,
386
            deleted_biblio_id,
387
            item_group_id,
388
            desk_id,
389
            cancellation_date,
390
            cancellation_reason,
391
            notes,
392
            priority,
393
            status,
394
            timestamp,
395
            waiting_date,
396
            expiration_date,
397
            lowest_priority,
398
            suspended,
399
            suspended_until,
400
            non_priority,
401
            item_type,
402
            item_level,
403
            cancellation_requested,
404
            biblio,
405
            deleted_biblio,
406
            item,
407
            pickup_library,
408
            hold_date,
409
            ...hold
410
        } = object;
411
412
        return apiPost({
413
            endpoint: `/api/v1/holds`,
414
            body: hold,
415
    baseUrl,
416
    authHeader,
417
        });
277
    } else {
418
    } else {
278
        return false;
419
        return false;
279
    }
420
    }
Lines 283-288 const insertObject = async (type, object, baseUrl, authHeader) => { Link Here
283
424
284
module.exports = {
425
module.exports = {
285
    insertSampleBiblio,
426
    insertSampleBiblio,
427
    insertSampleHold,
286
    insertObject,
428
    insertObject,
287
    deleteSampleObjects,
429
    deleteSampleObjects,
288
};
430
};
289
- 

Return to bug 40180