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

(-)a/Koha/REST/V1/Patrons/Categories.pm (+20 lines)
Lines 50-53 sub list { Link Here
50
    };
50
    };
51
}
51
}
52
52
53
=head3 add
54
55
=cut
56
57
sub add {
58
    my $c = shift->openapi->valid_input or return;
59
60
    return try {
61
        my $category = Koha::Patron::Category->new_from_api( $c->req->json );
62
        $category->store;
63
        $c->res->headers->location( $c->req->url->to_string . '/' . $category->categorycode );
64
        return $c->render(
65
            status  => 201,
66
            openapi => $c->objects->to_api($category),
67
        );
68
    } catch {
69
        $c->unhandled_exception($_);
70
    };
71
}
72
53
1;
73
1;
(-)a/t/cypress/integration/Islands/SelfRenewal.ts (+206 lines)
Line 0 Link Here
1
describe("Patron self-renewal", () => {
2
    beforeEach(() => {
3
        cy.task("buildSampleObject", {
4
            object: "patron_category",
5
            values: {
6
                self_renewal_enabled: 1,
7
                self_renewal_availability_start: 10,
8
                self_renewal_if_expired: 10,
9
                self_renewal_failure_message: "This cypress renewal has failed",
10
                self_renewal_information_message:
11
                    "This should display before renewal",
12
                self_renewal_fines_block: 0,
13
            },
14
        }).then(patron_category => {
15
            cy.task("insertObject", {
16
                type: "category",
17
                object: patron_category,
18
            }).then(patron_category => {
19
                cy.wrap(patron_category).as("patron_category");
20
                cy.task("insertSamplePatron", {
21
                    patron_category,
22
                    patronValues: {
23
                        password: "Cypress1234",
24
                        email: "test@email.com",
25
                        secondary_email: "test@email.com",
26
                        altaddress_email: "test@email.com",
27
                    },
28
                }).then(objects_patron => {
29
                    cy.wrap(objects_patron).as("objects_patron");
30
                    cy.loginOpac(
31
                        objects_patron.patron.cardnumber,
32
                        "Cypress1234"
33
                    );
34
                });
35
            });
36
        });
37
    });
38
39
    afterEach(function () {
40
        this.objects_patron.category = this.patron_category;
41
        cy.task("deleteSampleObjects", this.objects_patron);
42
    });
43
44
    it("should display a message that self renewal is available", function () {
45
        cy.visitOpac("/cgi-bin/koha/opac-user.pl");
46
        cy.get("#self_renewal_available").contains(
47
            "You are eligible for self-renewal. Please click here to renew your account"
48
        );
49
    });
50
    it("should open the modal for self-renewal", function () {
51
        cy.visitOpac("/cgi-bin/koha/opac-user.pl");
52
        cy.get("#patronSelfRenewal", { timeout: 10000 });
53
        cy.get("#self_renewal_available a").click();
54
        cy.get("#patronSelfRenewal").should("be.visible");
55
    });
56
    it("should verify that the patron wants to renew their account", function () {
57
        cy.visitOpac("/cgi-bin/koha/opac-user.pl");
58
        cy.intercept(
59
            "GET",
60
            Cypress.env("opacBaseUrl") +
61
                "/api/v1/public/patrons/*/self_renewal?_per_page=-1",
62
            {
63
                self_renewal_settings: {
64
                    opac_patron_details: "0",
65
                    self_renewal_failure_message:
66
                        "Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.",
67
                },
68
            }
69
        ).as("renewalConfig");
70
        cy.get("#patronSelfRenewal", { timeout: 10000 });
71
        cy.get("#self_renewal_available a").click();
72
        cy.wait("@renewalConfig");
73
        cy.get("#patronSelfRenewal .verification_question").contains(
74
            "Are you sure you want to renew your account?"
75
        );
76
    });
77
    it("should renew a patron's account", function () {
78
        cy.visitOpac("/cgi-bin/koha/opac-user.pl");
79
        cy.intercept(
80
            "GET",
81
            Cypress.env("opacBaseUrl") +
82
                "/api/v1/public/patrons/*/self_renewal?_per_page=-1",
83
            {
84
                self_renewal_settings: {
85
                    opac_patron_details: "0",
86
                    self_renewal_failure_message:
87
                        "Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.",
88
                },
89
            }
90
        ).as("renewalConfig");
91
        cy.get("#patronSelfRenewal", { timeout: 10000 });
92
        cy.get("#self_renewal_available a").click();
93
        cy.wait("@renewalConfig");
94
        cy.intercept(
95
            "POST",
96
            Cypress.env("opacBaseUrl") +
97
                "/api/v1/public/patrons/*/self_renewal",
98
            {
99
                statusCode: 201,
100
                body: {
101
                    expiry_date: "2099-01-01",
102
                    confirmation_sent: true,
103
                },
104
            }
105
        ).as("submitRenewal");
106
        cy.get("#patronSelfRenewal .verification_actions")
107
            .contains("Yes")
108
            .click();
109
        cy.wait("@submitRenewal");
110
        cy.get("#self_renewal_success").contains(
111
            "Your account has been successfully renewed"
112
        );
113
    });
114
    it("should display an information message step", function () {
115
        cy.visitOpac("/cgi-bin/koha/opac-user.pl");
116
        cy.intercept(
117
            "GET",
118
            Cypress.env("opacBaseUrl") +
119
                "/api/v1/public/patrons/*/self_renewal?_per_page=-1",
120
            {
121
                self_renewal_settings: {
122
                    opac_patron_details: "0",
123
                    self_renewal_failure_message:
124
                        "Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.",
125
                    self_renewal_information_message: "This should be shown",
126
                },
127
            }
128
        ).as("renewalConfig");
129
        cy.get("#patronSelfRenewal", { timeout: 10000 });
130
        cy.get("#self_renewal_available a").click();
131
        cy.wait("@renewalConfig");
132
        cy.intercept(
133
            "POST",
134
            Cypress.env("opacBaseUrl") +
135
                "/api/v1/public/patrons/*/self_renewal",
136
            {
137
                statusCode: 201,
138
                body: {
139
                    expiry_date: "2099-01-01",
140
                    confirmation_sent: true,
141
                },
142
            }
143
        ).as("submitRenewal");
144
        cy.get("#patronSelfRenewal .verification_question").contains(
145
            "This should be shown"
146
        );
147
        cy.get("#patronSelfRenewal .verification_actions")
148
            .contains("Yes")
149
            .click();
150
151
        cy.get("#patronSelfRenewal .verification_actions")
152
            .contains("Yes")
153
            .click();
154
        cy.wait("@submitRenewal");
155
        cy.get("#self_renewal_success").contains(
156
            "Your account has been successfully renewed"
157
        );
158
    });
159
    it("should confirm patron details if required", function () {
160
        cy.visitOpac("/cgi-bin/koha/opac-user.pl");
161
        cy.intercept(
162
            "GET",
163
            Cypress.env("opacBaseUrl") +
164
                "/api/v1/public/patrons/*/self_renewal?_per_page=-1",
165
            {
166
                self_renewal_settings: {
167
                    opac_patron_details: "1",
168
                    self_renewal_failure_message:
169
                        "Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.",
170
                },
171
            }
172
        ).as("renewalConfig");
173
        cy.get("#patronSelfRenewal", { timeout: 10000 });
174
        cy.get("#self_renewal_available a").click();
175
        cy.wait("@renewalConfig");
176
177
        cy.get("#patronSelfRenewal legend").contains(
178
            "Confirm your account details"
179
        );
180
        cy.get("#patronSelfRenewal button").contains("Continue").click();
181
182
        cy.get("h1").contains("Your personal details");
183
        cy.get("#update-account div.alert.alert-info").contains(
184
            "Please verify your details to proceed with your self-renewal"
185
        );
186
        cy.intercept(
187
            "POST",
188
            Cypress.env("opacBaseUrl") +
189
                "/api/v1/public/patrons/*/self_renewal",
190
            {
191
                statusCode: 201,
192
                body: {
193
                    expiry_date: "2099-01-01",
194
                    confirmation_sent: true,
195
                },
196
            }
197
        ).as("submitRenewal");
198
        cy.get("#update-account fieldset.action input[type='submit']")
199
            .contains("Submit renewal request")
200
            .click();
201
        cy.wait("@submitRenewal");
202
        cy.get("#self_renewal_success").contains(
203
            "Your account has been successfully renewed"
204
        );
205
    });
206
});
(-)a/t/cypress/plugins/insertData.js (-1 / +27 lines)
Lines 388-393 const insertSampleCheckout = async ({ patron, baseUrl, authHeader }) => { Link Here
388
const insertSamplePatron = async ({
388
const insertSamplePatron = async ({
389
    library,
389
    library,
390
    patron_category,
390
    patron_category,
391
    patronValues,
391
    baseUrl,
392
    baseUrl,
392
    authHeader,
393
    authHeader,
393
}) => {
394
}) => {
Lines 427-432 const insertSamplePatron = async ({ Link Here
427
            category_id: patron_category.patron_category_id,
428
            category_id: patron_category.patron_category_id,
428
            incorrect_address: null,
429
            incorrect_address: null,
429
            patron_card_lost: null,
430
            patron_card_lost: null,
431
            ...patronValues,
430
        },
432
        },
431
    });
433
    });
432
434
Lines 443-448 const insertSamplePatron = async ({ Link Here
443
        lang,
445
        lang,
444
        login_attempts,
446
        login_attempts,
445
        sms_provider_id,
447
        sms_provider_id,
448
        self_renewal_available,
446
        ...patron
449
        ...patron
447
    } = generatedPatron;
450
    } = generatedPatron;
448
    delete patron.library;
451
    delete patron.library;
Lines 454-459 const insertSamplePatron = async ({ Link Here
454
        authHeader,
457
        authHeader,
455
    });
458
    });
456
459
460
    if (patronValues.hasOwnProperty("password")) {
461
        const password = patronValues.password;
462
        await apiPost({
463
            endpoint: `/api/v1/patrons/${patron.patron_id}/password`,
464
            body: { password, password_2: password },
465
            baseUrl,
466
            authHeader,
467
        });
468
    }
469
457
    return {
470
    return {
458
        patron,
471
        patron,
459
        ...(generatedLibrary ? { library } : {}),
472
        ...(generatedLibrary ? { library } : {}),
Lines 563-568 const deleteSampleObjects = async allObjects => { Link Here
563
            table: "erm_eholdings_titles",
576
            table: "erm_eholdings_titles",
564
            whereColumn: "title_id",
577
            whereColumn: "title_id",
565
        },
578
        },
579
        category: {
580
            plural: "categories",
581
            table: "categories",
582
            whereColumn: "categorycode",
583
            idField: "patron_category_id",
584
        },
566
    };
585
    };
567
    // Merge by type
586
    // Merge by type
568
    const mergedObjects = {};
587
    const mergedObjects = {};
Lines 594-599 const deleteSampleObjects = async allObjects => { Link Here
594
        "item_types",
613
        "item_types",
595
        "erm_agreements",
614
        "erm_agreements",
596
        "erm_eholdings_titles",
615
        "erm_eholdings_titles",
616
        "categories",
597
    ];
617
    ];
598
    const matchTypeToObjectMap = type => {
618
    const matchTypeToObjectMap = type => {
599
        const matchingKey = Object.keys(objectsMap).find(
619
        const matchingKey = Object.keys(objectsMap).find(
Lines 858-863 const insertObject = async ({ type, object, baseUrl, authHeader }) => { Link Here
858
            baseUrl,
878
            baseUrl,
859
            authHeader,
879
            authHeader,
860
        });
880
        });
881
    } else if (type === "category") {
882
        return apiPost({
883
            endpoint: "/api/v1/patron_categories",
884
            body: object,
885
            baseUrl,
886
            authHeader,
887
        });
861
    } else {
888
    } else {
862
        throw Error(`Unsupported object type '${type}' to insert`);
889
        throw Error(`Unsupported object type '${type}' to insert`);
863
    }
890
    }
864
- 

Return to bug 26355