Bug 42772: Cypress.env => cy.env

Warning: The allowCypressEnv configuration option is enabled. This allows any browser code to read values from Cypress.env(). This is insecure and will be removed in a future major version.

1. Replace Cypress.env() calls with cy.env() (for sensitive values) or Cypress.expose() (for public configuration)
2. Set allowCypressEnv: false in your Cypress configuration to disable Cypress.env()

Learn more: https://on.cypress.io/cypress-env-migration

Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This commit is contained in:
Jonathan Druart 2026-06-08 14:51:01 +02:00 committed by Pedro Amorim
parent 7b307694fa
commit f89e68c220
No known key found for this signature in database
GPG Key ID: 06B75BA7F3894D55
4 changed files with 178 additions and 156 deletions

View File

@ -12,11 +12,14 @@ export default defineConfig({
setupNodeEvents(on, config) { setupNodeEvents(on, config) {
return require("./t/cypress/plugins/index.js")(on, config); return require("./t/cypress/plugins/index.js")(on, config);
}, },
allowCypressEnv: false,
baseUrl: process.env.KOHA_INTRANET_URL || "http://localhost:8081", baseUrl: process.env.KOHA_INTRANET_URL || "http://localhost:8081",
specPattern: "t/cypress/integration/**/*.*", specPattern: "t/cypress/integration/**/*.*",
supportFile: "t/cypress/support/e2e.js", supportFile: "t/cypress/support/e2e.js",
env: { env: {
opacBaseUrl: process.env.KOHA_OPAC_URL || "http://localhost:8080", opacBaseUrl: process.env.KOHA_OPAC_URL || "http://localhost:8080",
kohaUsername: process.env.KOHA_USER || "koha",
kohaPassword: process.env.KOHA_PASS || "koha",
apiUsername: process.env.KOHA_USER || "koha", apiUsername: process.env.KOHA_USER || "koha",
apiPassword: process.env.KOHA_PASS || "koha", apiPassword: process.env.KOHA_PASS || "koha",
}, },

View File

@ -55,18 +55,20 @@ describe("Patron self-renewal", () => {
}); });
it("should verify that the patron wants to renew their account", function () { it("should verify that the patron wants to renew their account", function () {
cy.visitOpac("/cgi-bin/koha/opac-user.pl"); cy.visitOpac("/cgi-bin/koha/opac-user.pl");
cy.intercept( cy.env(["opacBaseUrl"]).then(({ opacBaseUrl }) => {
"GET", cy.intercept(
Cypress.env("opacBaseUrl") + "GET",
"/api/v1/public/patrons/*/self_renewal?_per_page=-1", opacBaseUrl +
{ "/api/v1/public/patrons/*/self_renewal?_per_page=-1",
self_renewal_settings: { {
opac_patron_details: "0", self_renewal_settings: {
self_renewal_failure_message: opac_patron_details: "0",
"Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.", self_renewal_failure_message:
}, "Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.",
} },
).as("renewalConfig"); }
).as("renewalConfig");
});
cy.get("#patronSelfRenewal", { timeout: 10000 }); cy.get("#patronSelfRenewal", { timeout: 10000 });
cy.get("#self_renewal_available a").click(); cy.get("#self_renewal_available a").click();
cy.wait("@renewalConfig"); cy.wait("@renewalConfig");
@ -76,33 +78,36 @@ describe("Patron self-renewal", () => {
}); });
it("should renew a patron's account", function () { it("should renew a patron's account", function () {
cy.visitOpac("/cgi-bin/koha/opac-user.pl"); cy.visitOpac("/cgi-bin/koha/opac-user.pl");
cy.intercept( cy.env(["opacBaseUrl"]).then(({ opacBaseUrl }) => {
"GET", cy.intercept(
Cypress.env("opacBaseUrl") + "GET",
"/api/v1/public/patrons/*/self_renewal?_per_page=-1", opacBaseUrl +
{ "/api/v1/public/patrons/*/self_renewal?_per_page=-1",
self_renewal_settings: { {
opac_patron_details: "0", self_renewal_settings: {
self_renewal_failure_message: opac_patron_details: "0",
"Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.", self_renewal_failure_message:
}, "Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.",
} },
).as("renewalConfig"); }
).as("renewalConfig");
});
cy.get("#patronSelfRenewal", { timeout: 10000 }); cy.get("#patronSelfRenewal", { timeout: 10000 });
cy.get("#self_renewal_available a").click(); cy.get("#self_renewal_available a").click();
cy.wait("@renewalConfig"); cy.wait("@renewalConfig");
cy.intercept( cy.env(["opacBaseUrl"]).then(({ opacBaseUrl }) => {
"POST", cy.intercept(
Cypress.env("opacBaseUrl") + "POST",
"/api/v1/public/patrons/*/self_renewal", opacBaseUrl + "/api/v1/public/patrons/*/self_renewal",
{ {
statusCode: 201, statusCode: 201,
body: { body: {
expiry_date: "2099-01-01", expiry_date: "2099-01-01",
confirmation_sent: true, confirmation_sent: true,
}, },
} }
).as("submitRenewal"); ).as("submitRenewal");
});
cy.get("#patronSelfRenewal .verification_actions") cy.get("#patronSelfRenewal .verification_actions")
.contains("Yes") .contains("Yes")
.click(); .click();
@ -113,34 +118,39 @@ describe("Patron self-renewal", () => {
}); });
it("should display an information message step", function () { it("should display an information message step", function () {
cy.visitOpac("/cgi-bin/koha/opac-user.pl"); cy.visitOpac("/cgi-bin/koha/opac-user.pl");
cy.intercept( cy.env(["opacBaseUrl"]).then(({ opacBaseUrl }) => {
"GET", cy.intercept(
Cypress.env("opacBaseUrl") + "GET",
"/api/v1/public/patrons/*/self_renewal?_per_page=-1", opacBaseUrl +
{ "/api/v1/public/patrons/*/self_renewal?_per_page=-1",
self_renewal_settings: { {
opac_patron_details: "0", self_renewal_settings: {
self_renewal_failure_message: opac_patron_details: "0",
"Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.", self_renewal_failure_message:
self_renewal_information_messages: ["This should be shown"], "Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.",
}, self_renewal_information_messages: [
} "This should be shown",
).as("renewalConfig"); ],
},
}
).as("renewalConfig");
});
cy.get("#patronSelfRenewal", { timeout: 10000 }); cy.get("#patronSelfRenewal", { timeout: 10000 });
cy.get("#self_renewal_available a").click(); cy.get("#self_renewal_available a").click();
cy.wait("@renewalConfig"); cy.wait("@renewalConfig");
cy.intercept( cy.env(["opacBaseUrl"]).then(({ opacBaseUrl }) => {
"POST", cy.intercept(
Cypress.env("opacBaseUrl") + "POST",
"/api/v1/public/patrons/*/self_renewal", opacBaseUrl + "/api/v1/public/patrons/*/self_renewal",
{ {
statusCode: 201, statusCode: 201,
body: { body: {
expiry_date: "2099-01-01", expiry_date: "2099-01-01",
confirmation_sent: true, confirmation_sent: true,
}, },
} }
).as("submitRenewal"); ).as("submitRenewal");
});
cy.get("#patronSelfRenewal .verification_question").contains( cy.get("#patronSelfRenewal .verification_question").contains(
"This should be shown" "This should be shown"
); );
@ -158,18 +168,20 @@ describe("Patron self-renewal", () => {
}); });
it("should confirm patron details if required", function () { it("should confirm patron details if required", function () {
cy.visitOpac("/cgi-bin/koha/opac-user.pl"); cy.visitOpac("/cgi-bin/koha/opac-user.pl");
cy.intercept( cy.env(["opacBaseUrl"]).then(({ opacBaseUrl }) => {
"GET", cy.intercept(
Cypress.env("opacBaseUrl") + "GET",
"/api/v1/public/patrons/*/self_renewal?_per_page=-1", opacBaseUrl +
{ "/api/v1/public/patrons/*/self_renewal?_per_page=-1",
self_renewal_settings: { {
opac_patron_details: "1", self_renewal_settings: {
self_renewal_failure_message: opac_patron_details: "1",
"Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.", self_renewal_failure_message:
}, "Your self-renewal can't be processed at this time. Please visit your local branch to complete your renewal.",
} },
).as("renewalConfig"); }
).as("renewalConfig");
});
cy.get("#patronSelfRenewal", { timeout: 10000 }); cy.get("#patronSelfRenewal", { timeout: 10000 });
cy.get("#self_renewal_available a").click(); cy.get("#self_renewal_available a").click();
cy.wait("@renewalConfig"); cy.wait("@renewalConfig");
@ -183,18 +195,19 @@ describe("Patron self-renewal", () => {
cy.get("#update-account div.alert.alert-info").contains( cy.get("#update-account div.alert.alert-info").contains(
"Please verify your details to proceed with your self-renewal" "Please verify your details to proceed with your self-renewal"
); );
cy.intercept( cy.env(["opacBaseUrl"]).then(({ opacBaseUrl }) => {
"POST", cy.intercept(
Cypress.env("opacBaseUrl") + "POST",
"/api/v1/public/patrons/*/self_renewal", opacBaseUrl + "/api/v1/public/patrons/*/self_renewal",
{ {
statusCode: 201, statusCode: 201,
body: { body: {
expiry_date: "2099-01-01", expiry_date: "2099-01-01",
confirmation_sent: true, confirmation_sent: true,
}, },
} }
).as("submitRenewal"); ).as("submitRenewal");
});
cy.get("#update-account fieldset.action input[type='submit']") cy.get("#update-account fieldset.action input[type='submit']")
.contains("Submit renewal request") .contains("Submit renewal request")
.click(); .click();

View File

@ -3,46 +3,58 @@ describe("SCO", () => {
// cy.request() — no browser navigation, so no cross-origin issues. // cy.request() — no browser navigation, so no cross-origin issues.
function setSyspref(variable: string, value: string) { function setSyspref(variable: string, value: string) {
// Step 1: GET the login page to get an anonymous session + its CSRF token // Step 1: GET the login page to get an anonymous session + its CSRF token
cy.request("/cgi-bin/koha/mainpage.pl?logout.x=1").then(loginPage => { cy.env(["apiUsername", "apiPassword"]).then(
const csrfForLogin = (loginPage.body as string).match( ({ apiUsername, apiPassword }) => {
/<meta name="csrf-token" content="([^"]+)"/ cy.request("/cgi-bin/koha/mainpage.pl?logout.x=1").then(
)?.[1]; loginPage => {
if (!csrfForLogin) const csrfForLogin = (loginPage.body as string).match(
throw new Error("CSRF token not found on login page"); /<meta name="csrf-token" content="([^"]+)"/
)?.[1];
if (!csrfForLogin)
throw new Error(
"CSRF token not found on login page"
);
// Step 2: POST credentials — Koha authenticates and redirects to the // Step 2: POST credentials — Koha authenticates and redirects to the
// logged-in mainpage whose body contains the new session's CSRF token // logged-in mainpage whose body contains the new session's CSRF token
cy.request({ cy.request({
method: "POST", method: "POST",
url: "/cgi-bin/koha/mainpage.pl", url: "/cgi-bin/koha/mainpage.pl",
headers: { headers: {
"Content-Type": "application/x-www-form-urlencoded", "Content-Type":
}, "application/x-www-form-urlencoded",
body: [ },
`login_userid=${encodeURIComponent(Cypress.env("apiUsername"))}`, body: [
`login_password=${encodeURIComponent(Cypress.env("apiPassword"))}`, `login_userid=${encodeURIComponent(apiUsername)}`,
`csrf_token=${encodeURIComponent(csrfForLogin)}`, `login_password=${encodeURIComponent(apiPassword)}`,
`login_op=cud-login`, `csrf_token=${encodeURIComponent(csrfForLogin)}`,
].join("&"), `login_op=cud-login`,
}).then(mainPage => { ].join("&"),
const csrfForSvc = (mainPage.body as string).match( }).then(mainPage => {
/<meta name="csrf-token" content="([^"]+)"/ const csrfForSvc = (mainPage.body as string).match(
)?.[1]; /<meta name="csrf-token" content="([^"]+)"/
if (!csrfForSvc) )?.[1];
throw new Error("CSRF token not found on main page"); if (!csrfForSvc)
throw new Error(
"CSRF token not found on main page"
);
// Step 3: POST to svc endpoint — session cookie sent automatically // Step 3: POST to svc endpoint — session cookie sent automatically
cy.request({ cy.request({
method: "POST", method: "POST",
url: "/cgi-bin/koha/svc/config/systempreferences", url: "/cgi-bin/koha/svc/config/systempreferences",
headers: { headers: {
"Content-Type": "application/x-www-form-urlencoded", "Content-Type":
"CSRF-TOKEN": csrfForSvc, "application/x-www-form-urlencoded",
}, "CSRF-TOKEN": csrfForSvc,
body: `pref_${encodeURIComponent(variable)}=${encodeURIComponent(value)}`, },
}); body: `pref_${encodeURIComponent(variable)}=${encodeURIComponent(value)}`,
}); });
}); });
}
);
}
);
} }
beforeEach(() => { beforeEach(() => {

View File

@ -75,46 +75,40 @@ Cypress.on("uncaught:exception", err => {
} }
}); });
function get_fallback_login_value(param) {
var env_var = param == "username" ? "KOHA_USER" : "KOHA_PASS";
return typeof Cypress.env(env_var) === "undefined"
? "koha"
: Cypress.env(env_var);
}
Cypress.Commands.add("visitOpac", path => { Cypress.Commands.add("visitOpac", path => {
cy.visit(Cypress.env("opacBaseUrl") + path); cy.env(["opacBaseUrl"]).then(({ opacBaseUrl }) =>
cy.visit(opacBaseUrl + path)
);
}); });
Cypress.Commands.add("login", (username, password) => { Cypress.Commands.add("login", (username, password) => {
var user = cy.env(["kohaUsername", "kohaPassword"]).then(
typeof username === "undefined" ({ kohaUsername, kohaPassword }) => {
? get_fallback_login_value("username") var user =
: username; typeof username === "undefined" ? kohaUsername : username;
var pass = var pass =
typeof password === "undefined" typeof password === "undefined" ? kohaPassword : password;
? get_fallback_login_value("password") cy.visit("/cgi-bin/koha/mainpage.pl?logout.x=1");
: password; cy.get("#userid").type(user);
cy.visit("/cgi-bin/koha/mainpage.pl?logout.x=1"); cy.get("#password").type(pass);
cy.get("#userid").type(user); cy.get("#submit-button").click();
cy.get("#password").type(pass); }
cy.get("#submit-button").click(); );
}); });
Cypress.Commands.add("loginOpac", (username, password) => { Cypress.Commands.add("loginOpac", (username, password) => {
var user = cy.env(["kohaUsername", "kohaPassword"]).then(
typeof username === "undefined" ({ kohaUsername, kohaPassword }) => {
? get_fallback_login_value("username") var user =
: username; typeof username === "undefined" ? kohaUsername : username;
var pass = var pass =
typeof password === "undefined" typeof password === "undefined" ? kohaPassword : password;
? get_fallback_login_value("password") cy.visitOpac("/cgi-bin/koha/opac-main.pl?logout.x=1");
: password; cy.get("#userid").type(user);
cy.visitOpac("/cgi-bin/koha/opac-main.pl?logout.x=1"); cy.get("#password").type(pass);
cy.get("#userid").type(user); cy.get("#auth .action").contains("Log in").click();
cy.get("#password").type(pass); }
cy.get("#auth .action").contains("Log in").click(); );
}); });
Cypress.Commands.add("left_menu_active_item_is", label => { Cypress.Commands.add("left_menu_active_item_is", label => {