From 3d00e747d44ba2aedd153dfec2912a5704e3c1c8 Mon Sep 17 00:00:00 2001 From: Matt Blenkinsop Date: Wed, 21 Jan 2026 09:47:01 +0000 Subject: [PATCH] Bug 26355: Add cypress tests --- t/cypress/integration/Islands/SelfRenewal.ts | 215 +++++++++++++++++++ t/cypress/plugins/insertData.js | 27 +++ 2 files changed, 242 insertions(+) create mode 100644 t/cypress/integration/Islands/SelfRenewal.ts diff --git a/t/cypress/integration/Islands/SelfRenewal.ts b/t/cypress/integration/Islands/SelfRenewal.ts new file mode 100644 index 00000000000..1e091c85896 --- /dev/null +++ b/t/cypress/integration/Islands/SelfRenewal.ts @@ -0,0 +1,215 @@ +describe("Patron self-renewal", () => { + beforeEach(() => { + cy.task("buildSampleObject", { + object: "patron_category", + values: { + self_renewal_enabled: 1, + self_renewal_availability_start: 10, + self_renewal_if_expired: 10, + self_renewal_failure_message: "This cypress renewal has failed", + self_renewal_fines_block: 0, + }, + }).then(patron_category => { + cy.task("insertObject", { + type: "category", + object: patron_category, + }).then(patron_category => { + cy.wrap(patron_category).as("patron_category"); + cy.task("insertSamplePatron", { + patron_category, + patronValues: { + password: "Cypress1234", + email: "test@email.com", + secondary_email: "test@email.com", + altaddress_email: "test@email.com", + }, + }).then(objects_patron => { + cy.wrap(objects_patron).as("objects_patron"); + cy.loginOpac( + objects_patron.patron.cardnumber, + "Cypress1234" + ); + }); + }); + }); + }); + + afterEach(function () { + this.objects_patron.category = this.patron_category; + cy.task("deleteSampleObjects", this.objects_patron); + }); + + it("should display a message that self renewal is available", function () { + cy.visitOpac("/cgi-bin/koha/opac-user.pl"); + cy.get("#self_renewal_available").contains( + "You are eligible for self-renewal. Please click here to renew your account" + ); + }); + it("should open the modal for self-renewal", function () { + cy.visitOpac("/cgi-bin/koha/opac-user.pl"); + cy.get("#patronSelfRenewal", { timeout: 10000 }); + cy.get("#self_renewal_available a").click(); + cy.get("#patronSelfRenewal").should("be.visible"); + }); + it("should verify that the patron wants to renew their account", function () { + cy.visitOpac("/cgi-bin/koha/opac-user.pl"); + cy.intercept( + "GET", + Cypress.env("opacBaseUrl") + + "/api/v1/public/patrons/self_renewal?_per_page=-1", + { + self_renewal_settings: { + opac_patron_details: "0", + self_renewal_failure_message: + "Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.", + }, + verification_checks: [], + } + ).as("renewalConfig"); + cy.get("#patronSelfRenewal", { timeout: 10000 }); + cy.get("#self_renewal_available a").click(); + cy.wait("@renewalConfig"); + cy.get("#patronSelfRenewal .verification_question").contains( + "Are you sure you want to renew your account?" + ); + }); + it("should renew a patron's account", function () { + cy.visitOpac("/cgi-bin/koha/opac-user.pl"); + cy.intercept( + "GET", + Cypress.env("opacBaseUrl") + + "/api/v1/public/patrons/self_renewal?_per_page=-1", + { + self_renewal_settings: { + opac_patron_details: "0", + self_renewal_failure_message: + "Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.", + }, + verification_checks: [], + } + ).as("renewalConfig"); + cy.get("#patronSelfRenewal", { timeout: 10000 }); + cy.get("#self_renewal_available a").click(); + cy.wait("@renewalConfig"); + cy.intercept( + "POST", + Cypress.env("opacBaseUrl") + "/api/v1/public/patrons/self_renewal", + { + statusCode: 201, + body: { + expiry_date: "2099-01-01", + confirmation_sent: true, + }, + } + ).as("submitRenewal"); + cy.get("#patronSelfRenewal .verification_actions") + .contains("Yes") + .click(); + cy.wait("@submitRenewal"); + cy.get("#self_renewal_success").contains( + "Your account has been successfully renewed" + ); + }); + it("should handle verification steps", function () { + cy.visitOpac("/cgi-bin/koha/opac-user.pl"); + cy.intercept( + "GET", + Cypress.env("opacBaseUrl") + + "/api/v1/public/patrons/self_renewal?_per_page=-1", + { + self_renewal_settings: { + opac_patron_details: "0", + self_renewal_failure_message: + "Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.", + }, + verification_checks: [ + { description: "This is step 1" }, + { description: "This is step 2" }, + ], + } + ).as("renewalConfig"); + cy.get("#patronSelfRenewal", { timeout: 10000 }); + cy.get("#self_renewal_available a").click(); + cy.wait("@renewalConfig"); + cy.intercept( + "POST", + Cypress.env("opacBaseUrl") + "/api/v1/public/patrons/self_renewal", + { + statusCode: 201, + body: { + expiry_date: "2099-01-01", + confirmation_sent: true, + }, + } + ).as("submitRenewal"); + cy.get("#patronSelfRenewal legend").contains("Verification step 1"); + cy.get("#patronSelfRenewal .verification_question").contains( + "This is step 1" + ); + cy.get("#patronSelfRenewal .verification_actions") + .contains("Yes") + .click(); + cy.get("#patronSelfRenewal legend").contains("Verification step 2"); + cy.get("#patronSelfRenewal .verification_question").contains( + "This is step 2" + ); + cy.get("#patronSelfRenewal .verification_actions") + .contains("Yes") + .click(); + + cy.get("#patronSelfRenewal .verification_actions") + .contains("Yes") + .click(); + cy.wait("@submitRenewal"); + cy.get("#self_renewal_success").contains( + "Your account has been successfully renewed" + ); + }); + it("should confirm patron details if required", function () { + cy.visitOpac("/cgi-bin/koha/opac-user.pl"); + cy.intercept( + "GET", + Cypress.env("opacBaseUrl") + + "/api/v1/public/patrons/self_renewal?_per_page=-1", + { + self_renewal_settings: { + opac_patron_details: "1", + self_renewal_failure_message: + "Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.", + }, + verification_checks: [], + } + ).as("renewalConfig"); + cy.get("#patronSelfRenewal", { timeout: 10000 }); + cy.get("#self_renewal_available a").click(); + cy.wait("@renewalConfig"); + + cy.get("#patronSelfRenewal legend").contains( + "Confirm your account details" + ); + cy.get("#patronSelfRenewal button").contains("Continue").click(); + + cy.get("h1").contains("Your personal details"); + cy.get("#update-account div.alert.alert-info").contains( + "Please verify your details to proceed with your self-renewal" + ); + cy.intercept( + "POST", + Cypress.env("opacBaseUrl") + "/api/v1/public/patrons/self_renewal", + { + statusCode: 201, + body: { + expiry_date: "2099-01-01", + confirmation_sent: true, + }, + } + ).as("submitRenewal"); + cy.get("#update-account fieldset.action input[type='submit']") + .contains("Submit renewal request") + .click(); + cy.wait("@submitRenewal"); + cy.get("#self_renewal_success").contains( + "Your account has been successfully renewed" + ); + }); +}); diff --git a/t/cypress/plugins/insertData.js b/t/cypress/plugins/insertData.js index a784245dc60..d757425b33b 100644 --- a/t/cypress/plugins/insertData.js +++ b/t/cypress/plugins/insertData.js @@ -388,6 +388,7 @@ const insertSampleCheckout = async ({ patron, baseUrl, authHeader }) => { const insertSamplePatron = async ({ library, patron_category, + patronValues, baseUrl, authHeader, }) => { @@ -427,6 +428,7 @@ const insertSamplePatron = async ({ category_id: patron_category.patron_category_id, incorrect_address: null, patron_card_lost: null, + ...patronValues, }, }); @@ -443,6 +445,7 @@ const insertSamplePatron = async ({ lang, login_attempts, sms_provider_id, + self_renewal_available, ...patron } = generatedPatron; delete patron.library; @@ -454,6 +457,16 @@ const insertSamplePatron = async ({ authHeader, }); + if (patronValues.hasOwnProperty("password")) { + const password = patronValues.password; + await apiPost({ + endpoint: `/api/v1/patrons/${patron.patron_id}/password`, + body: { password, password_2: password }, + baseUrl, + authHeader, + }); + } + return { patron, ...(generatedLibrary ? { library } : {}), @@ -563,6 +576,12 @@ const deleteSampleObjects = async allObjects => { table: "erm_eholdings_titles", whereColumn: "title_id", }, + category: { + plural: "categories", + table: "categories", + whereColumn: "categorycode", + idField: "patron_category_id", + }, }; // Merge by type const mergedObjects = {}; @@ -594,6 +613,7 @@ const deleteSampleObjects = async allObjects => { "item_types", "erm_agreements", "erm_eholdings_titles", + "categories", ]; const matchTypeToObjectMap = type => { const matchingKey = Object.keys(objectsMap).find( @@ -858,6 +878,13 @@ const insertObject = async ({ type, object, baseUrl, authHeader }) => { baseUrl, authHeader, }); + } else if (type === "category") { + return apiPost({ + endpoint: "/api/v1/patron_categories", + body: object, + baseUrl, + authHeader, + }); } else { throw Error(`Unsupported object type '${type}' to insert`); } -- 2.39.5