diff --git a/core/src/main/java/hudson/Functions.java b/core/src/main/java/hudson/Functions.java
index 391ed0389ea7..08c1cce3c327 100644
--- a/core/src/main/java/hudson/Functions.java
+++ b/core/src/main/java/hudson/Functions.java
@@ -86,6 +86,7 @@
import hudson.tasks.Publisher;
import hudson.tasks.UserAvatarResolver;
import hudson.util.Area;
+import hudson.util.FormApply;
import hudson.util.FormValidation.CheckMethod;
import hudson.util.HudsonIsLoading;
import hudson.util.HudsonIsRestarting;
@@ -217,6 +218,11 @@ public class Functions {
public Functions() {
}
+ @Restricted(NoExternalUse.class)
+ public @CheckForNull FormApply.Notification getFormApplyNotification() {
+ return FormApply.getAndClearNotification(Stapler.getCurrentRequest2());
+ }
+
/**
* Generates an unique ID.
*/
diff --git a/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java b/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java
index ae90b0428c7b..d1fd4bdcca6d 100644
--- a/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java
+++ b/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java
@@ -108,7 +108,7 @@ public synchronized void doConfigure(StaplerRequest2 req, StaplerResponse2 rsp)
boolean result = configure(req, json);
LOGGER.log(Level.FINE, "security saved: " + result);
Jenkins.get().save();
- FormApply.success(req.getContextPath() + "/manage").generateResponse(req, rsp, null);
+ FormApply.success(req.getContextPath() + "/manage/" + getUrlName()).generateResponse(req, rsp, null);
} catch (JSONException x) {
LOGGER.warning(() -> "Bad JSON:\n" + json.toString(2));
throw x;
diff --git a/core/src/main/java/hudson/util/FormApply.java b/core/src/main/java/hudson/util/FormApply.java
index 3d5f458ec126..ed6d63931288 100644
--- a/core/src/main/java/hudson/util/FormApply.java
+++ b/core/src/main/java/hudson/util/FormApply.java
@@ -24,8 +24,10 @@
package hudson.util;
+import edu.umd.cs.findbugs.annotations.CheckForNull;
import hudson.Functions;
import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpSession;
import java.io.IOException;
import jenkins.model.Jenkins;
import org.kohsuke.stapler.HttpResponses.HttpResponseException;
@@ -40,6 +42,9 @@
* @since 1.453
*/
public class FormApply {
+ private static final String NOTIFICATION_MESSAGE_SESSION_ATTRIBUTE = FormApply.class.getName() + ".notificationMessage";
+ private static final String NOTIFICATION_TYPE_SESSION_ATTRIBUTE = FormApply.class.getName() + ".notificationType";
+
/**
* Generates the response for the form submission in such a way that it handles the "apply" button
* correctly.
@@ -56,6 +61,7 @@ public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object n
showNotification(Messages.HttpResponses_Saved(), NotificationType.SUCCESS)
.generateResponse(req, rsp, node);
} else {
+ setNotificationInSession(req, Messages.HttpResponses_Saved(), NotificationType.SUCCESS);
rsp.sendRedirect(destination);
}
}
@@ -127,6 +133,52 @@ public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object n
};
}
+ private static void setNotificationInSession(StaplerRequest2 req, String message, NotificationType notificationType) {
+ HttpSession session = req.getSession();
+ session.setAttribute(NOTIFICATION_MESSAGE_SESSION_ATTRIBUTE, message);
+ session.setAttribute(NOTIFICATION_TYPE_SESSION_ATTRIBUTE, notificationType.name());
+ }
+
+ public static @CheckForNull Notification getAndClearNotification(StaplerRequest2 req) {
+ HttpSession session = req.getSession(false);
+ if (session == null) {
+ return null;
+ }
+
+ String message = (String) session.getAttribute(NOTIFICATION_MESSAGE_SESSION_ATTRIBUTE);
+ String notificationType = (String) session.getAttribute(NOTIFICATION_TYPE_SESSION_ATTRIBUTE);
+ session.removeAttribute(NOTIFICATION_MESSAGE_SESSION_ATTRIBUTE);
+ session.removeAttribute(NOTIFICATION_TYPE_SESSION_ATTRIBUTE);
+
+ if (message == null || notificationType == null) {
+ return null;
+ }
+
+ try {
+ return new Notification(message, NotificationType.valueOf(notificationType));
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+
+ public static final class Notification {
+ private final String message;
+ private final NotificationType notificationType;
+
+ private Notification(String message, NotificationType notificationType) {
+ this.message = message;
+ this.notificationType = notificationType;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public NotificationType getNotificationType() {
+ return notificationType;
+ }
+ }
+
/**
* Corresponds to types declared in index.js
diff --git a/core/src/main/java/jenkins/agents/CloudSet.java b/core/src/main/java/jenkins/agents/CloudSet.java
index cbd5cc975d89..d458d7ac549c 100644
--- a/core/src/main/java/jenkins/agents/CloudSet.java
+++ b/core/src/main/java/jenkins/agents/CloudSet.java
@@ -285,7 +285,7 @@ public void doReorder(StaplerRequest2 req, StaplerResponse2 rsp) throws IOExcept
var clouds = new ArrayList<>(Jenkins.get().clouds);
clouds.sort(Comparator.comparingInt(c -> getIndexOf(namesList, c)));
Jenkins.get().clouds.replaceBy(clouds);
- FormApply.success(req.getContextPath() + "/manage").generateResponse(req, rsp, null);
+ FormApply.success(req.getContextPath() + "/manage/" + getUrlName()).generateResponse(req, rsp, null);
}
private static int getIndexOf(List namesList, Cloud cloud) {
diff --git a/core/src/main/java/jenkins/appearance/AppearanceGlobalConfiguration.java b/core/src/main/java/jenkins/appearance/AppearanceGlobalConfiguration.java
index 1208043b60cd..33d764d0cc04 100644
--- a/core/src/main/java/jenkins/appearance/AppearanceGlobalConfiguration.java
+++ b/core/src/main/java/jenkins/appearance/AppearanceGlobalConfiguration.java
@@ -101,7 +101,7 @@ public Category getCategory() {
public synchronized void doConfigure(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException, Descriptor.FormException {
boolean result = configure(req, req.getSubmittedForm());
LOGGER.log(Level.FINE, "appearance saved: " + result);
- FormApply.success(req.getContextPath() + "/manage").generateResponse(req, rsp, null);
+ FormApply.success(req.getContextPath() + "/manage/" + getUrlName()).generateResponse(req, rsp, null);
}
private boolean configure(StaplerRequest2 req, JSONObject json) throws Descriptor.FormException, IOException {
diff --git a/core/src/main/java/jenkins/model/Jenkins.java b/core/src/main/java/jenkins/model/Jenkins.java
index 7cfac6f3b3c6..f4c009f9e397 100644
--- a/core/src/main/java/jenkins/model/Jenkins.java
+++ b/core/src/main/java/jenkins/model/Jenkins.java
@@ -4045,7 +4045,7 @@ public synchronized void doConfigSubmit(StaplerRequest2 req, StaplerResponse2 rs
save();
updateComputers(this);
if (result)
- FormApply.success(req.getContextPath() + '/').generateResponse(req, rsp, null);
+ FormApply.success(req.getContextPath() + "/manage/configure").generateResponse(req, rsp, null);
else
FormApply.success("configure").generateResponse(req, rsp, null); // back to config
diff --git a/core/src/main/java/jenkins/model/experimentalflags/NewManageJenkinsUserExperimentalFlag.java b/core/src/main/java/jenkins/model/experimentalflags/NewManageJenkinsUserExperimentalFlag.java
index e04f7c60314a..7528aa512cb8 100644
--- a/core/src/main/java/jenkins/model/experimentalflags/NewManageJenkinsUserExperimentalFlag.java
+++ b/core/src/main/java/jenkins/model/experimentalflags/NewManageJenkinsUserExperimentalFlag.java
@@ -24,6 +24,7 @@
package jenkins.model.experimentalflags;
+import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import hudson.Extension;
import org.kohsuke.accmod.Restricted;
@@ -46,4 +47,9 @@ public String getDisplayName() {
public String getShortDescription() {
return "Enables a sidebar for the Manage Jenkins pages for easier navigation.";
}
+
+ @Override
+ public @NonNull Boolean getDefaultValue() {
+ return true;
+ }
}
diff --git a/core/src/main/java/jenkins/tools/GlobalToolConfiguration.java b/core/src/main/java/jenkins/tools/GlobalToolConfiguration.java
index 47208f942958..d00906363b09 100644
--- a/core/src/main/java/jenkins/tools/GlobalToolConfiguration.java
+++ b/core/src/main/java/jenkins/tools/GlobalToolConfiguration.java
@@ -84,7 +84,7 @@ public Category getCategory() {
public synchronized void doConfigure(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException, Descriptor.FormException {
boolean result = configure(req, req.getSubmittedForm());
LOGGER.log(Level.FINE, "tools saved: " + result);
- FormApply.success(req.getContextPath() + "/manage").generateResponse(req, rsp, null);
+ FormApply.success(req.getContextPath() + "/manage/" + getUrlName()).generateResponse(req, rsp, null);
}
private boolean configure(StaplerRequest2 req, JSONObject json) throws Descriptor.FormException, IOException {
diff --git a/core/src/main/resources/lib/layout/layout.jelly b/core/src/main/resources/lib/layout/layout.jelly
index 0e2dac0f47e8..399aade7341e 100644
--- a/core/src/main/resources/lib/layout/layout.jelly
+++ b/core/src/main/resources/lib/layout/layout.jelly
@@ -91,6 +91,7 @@ THE SOFTWARE.
+
${h.advertiseHeaders(response2)}
@@ -155,7 +156,9 @@ THE SOFTWARE.
+ data-search-help-url="${%searchBox.url}"
+ data-notification-message="${formApplyNotification.message}"
+ data-notification-type="${formApplyNotification.notificationType}">
diff --git a/core/src/main/resources/lib/layout/settings-subpage.jelly b/core/src/main/resources/lib/layout/settings-subpage.jelly
index f77a06e7ddd3..747fa0757228 100644
--- a/core/src/main/resources/lib/layout/settings-subpage.jelly
+++ b/core/src/main/resources/lib/layout/settings-subpage.jelly
@@ -101,13 +101,13 @@ THE SOFTWARE.
+
+
-
-
@@ -139,28 +139,7 @@ THE SOFTWARE.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/src/main/js/app.js b/src/main/js/app.js
index c21991f6e826..819374500744 100644
--- a/src/main/js/app.js
+++ b/src/main/js/app.js
@@ -9,11 +9,25 @@ import ConfirmationLink from "@/components/confirmation-link";
import Dialogs from "@/components/dialogs";
import Defer from "@/components/defer";
+function showPageLoadNotification() {
+ const { notificationMessage, notificationType } = document.body.dataset;
+ if (!notificationMessage) {
+ return;
+ }
+
+ const options =
+ (notificationType && window.notificationBar[notificationType]) || undefined;
+ window.notificationBar.show(notificationMessage, options);
+ delete document.body.dataset.notificationMessage;
+ delete document.body.dataset.notificationType;
+}
+
AppBar.init();
Dropdowns.init();
CommandPalette.init();
Defer.init();
Notifications.init();
+showPageLoadNotification();
SearchBar.init();
Tooltips.init();
StopButtonLink.init();
diff --git a/src/main/js/components/search-bar/index.js b/src/main/js/components/search-bar/index.js
index e9499571dd84..ac184ea6f565 100644
--- a/src/main/js/components/search-bar/index.js
+++ b/src/main/js/components/search-bar/index.js
@@ -7,74 +7,91 @@ const SELECTED_CLASS = "jenkins-dropdown__item--selected";
function init() {
const searchBarInputs = document.querySelectorAll(".jenkins-search__input");
- Array.from(searchBarInputs)
- .filter((searchBar) => searchBar.suggestions)
- .forEach((searchBar) => {
- const searchWrapper = searchBar.parentElement.parentElement;
- const searchResultsContainer = createElementFromHtml(
- ``,
+ Array.from(searchBarInputs).forEach((searchBar) => {
+ let suggestions = searchBar.suggestions;
+ let initialized = false;
+ let searchWrapper;
+ let searchResultsContainer;
+ let searchResults;
+
+ function showResultsContainer() {
+ searchResultsContainer.classList.add(
+ "jenkins-search__results-container--visible",
);
- searchWrapper.appendChild(searchResultsContainer);
- const searchResults = createElementFromHtml(
- ``,
- );
- searchResultsContainer.appendChild(searchResults);
+ }
- searchBar.addEventListener("input", () => {
- const query = searchBar.value.toLowerCase();
+ function hideResultsContainer() {
+ searchResultsContainer.classList.remove(
+ "jenkins-search__results-container--visible",
+ );
+ searchResultsContainer.style.height = "1px";
+ }
+
+ function appendResults(container, results) {
+ results.forEach((item, index) => {
+ container.appendChild(
+ createElementFromHtml(
+ `${item.icon}
${xmlEscape(item.label)}`,
+ ),
+ );
+ });
- // Hide the suggestions if the search query is empty
- if (query.length === 0) {
- hideResultsContainer();
- return;
- }
+ if (results.length === 0 && container === searchResults) {
+ container.appendChild(
+ createElementFromHtml(
+ `No results
`,
+ ),
+ );
+ }
+ }
- showResultsContainer();
-
- function appendResults(container, results) {
- results.forEach((item, index) => {
- container.appendChild(
- createElementFromHtml(
- `${item.icon}
${xmlEscape(item.label)}`,
- ),
- );
- });
-
- if (results.length === 0 && container === searchResults) {
- container.appendChild(
- createElementFromHtml(
- `No results
`,
- ),
- );
- }
- }
+ function refreshResults() {
+ if (!initialized) {
+ return;
+ }
- // Filter results
- const results = searchBar
- .suggestions()
- .filter((item) => item.label.toLowerCase().includes(query))
- .slice(0, 5);
+ const query = searchBar.value.toLowerCase();
+ // Hide the suggestions if the search query is empty
+ if (query.length === 0 || typeof searchBar.suggestions !== "function") {
searchResults.innerHTML = "";
- appendResults(searchResults, results);
- searchResultsContainer.style.height = searchResults.offsetHeight + "px";
- });
-
- function showResultsContainer() {
- searchResultsContainer.classList.add(
- "jenkins-search__results-container--visible",
- );
+ hideResultsContainer();
+ return;
}
- function hideResultsContainer() {
- searchResultsContainer.classList.remove(
- "jenkins-search__results-container--visible",
- );
- searchResultsContainer.style.height = "1px";
+ showResultsContainer();
+
+ // Filter results
+ const results = searchBar
+ .suggestions()
+ .filter((item) => item.label.toLowerCase().includes(query))
+ .slice(0, 5);
+
+ searchResults.innerHTML = "";
+ appendResults(searchResults, results);
+ searchResultsContainer.style.height = searchResults.offsetHeight + "px";
+ }
+
+ function initializeSearchBar() {
+ if (initialized || typeof searchBar.suggestions !== "function") {
+ return;
}
+ initialized = true;
+ searchWrapper = searchBar.parentElement.parentElement;
+ searchResultsContainer = createElementFromHtml(
+ ``,
+ );
+ searchWrapper.appendChild(searchResultsContainer);
+ searchResults = createElementFromHtml(
+ ``,
+ );
+ searchResultsContainer.appendChild(searchResults);
+
+ searchBar.addEventListener("input", refreshResults);
+
searchBar.addEventListener("keydown", (e) => {
if (e.key === "ArrowUp" || e.key === "ArrowDown") {
e.preventDefault();
@@ -90,7 +107,7 @@ function init() {
// Workaround: Firefox doesn't update the dropdown height correctly so
// let's bind the container's height to it's child
// Disabled in HtmlUnit
- if (!window.isRunAsTest) {
+ if (!document.head.getAttribute("data-unit-test")) {
new ResizeObserver(() => {
searchResultsContainer.style.height =
searchResults.offsetHeight + "px";
@@ -99,9 +116,7 @@ function init() {
searchBar.addEventListener("focusin", () => {
if (searchBar.value.length !== 0) {
- searchResultsContainer.style.height =
- searchResults.offsetHeight + "px";
- showResultsContainer();
+ refreshResults();
}
});
@@ -112,7 +127,23 @@ function init() {
hideResultsContainer();
});
+ }
+
+ Object.defineProperty(searchBar, "suggestions", {
+ configurable: true,
+ enumerable: true,
+ get() {
+ return suggestions;
+ },
+ set(value) {
+ suggestions = value;
+ initializeSearchBar();
+ refreshResults();
+ },
});
+
+ initializeSearchBar();
+ });
}
export default { init };
diff --git a/src/main/js/pages/manage-jenkins/index.js b/src/main/js/pages/manage-jenkins/index.js
index d2e3a6fc8045..498a2113990e 100644
--- a/src/main/js/pages/manage-jenkins/index.js
+++ b/src/main/js/pages/manage-jenkins/index.js
@@ -1,74 +1,81 @@
-const searchBarInput = document.querySelector("#settings-search-bar");
-
-searchBarInput.suggestions = function () {
- return Array.from(
- document.querySelectorAll(
- ".jenkins-section__item, #tasks .task-link-wrapper",
- ),
- )
- .map((item) => ({
- url: item.querySelector("a").href,
- icon: item.querySelector(
- ".jenkins-section__item__icon svg, .jenkins-section__item__icon img, .task-icon-link svg, .task-icon-link img",
- ).outerHTML,
- label: (
- item.querySelector("dt") ||
- item.querySelector(".task-link-text") ||
- item.querySelector(".task-link")
- ).textContent,
- }))
- .filter((item) => !item.url.endsWith("#"));
-};
-
document.addEventListener("DOMContentLoaded", function () {
- const messagesContainer = document.querySelector(".manage-messages");
- if (!messagesContainer) {
- return;
- }
+ function initSearchBar() {
+ const searchBarInput = document.querySelector("#settings-search-bar");
- const updateLastVisibleMessageMargin = () => {
- const messageDivs = Array.from(messagesContainer.children).filter(
- (el) => el.tagName === "DIV",
- );
+ searchBarInput.suggestions = function () {
+ return Array.from(
+ document.querySelectorAll(
+ ".jenkins-section__item, #tasks .task-link-wrapper",
+ ),
+ )
+ .map((item) => ({
+ url: item.querySelector("a").href,
+ icon: item.querySelector(
+ ".jenkins-section__item__icon svg, .jenkins-section__item__icon img, .task-icon-link svg, .task-icon-link img",
+ ).outerHTML,
+ label: (
+ item.querySelector("dt") ||
+ item.querySelector(".task-link-text") ||
+ item.querySelector(".task-link")
+ ).textContent,
+ }))
+ .filter((item) => !item.url.endsWith("#"));
+ };
+ }
- messageDivs.forEach((el) => {
- el.style.marginBottom = "";
- });
+ function initMessages() {
+ const messagesContainer = document.querySelector(".manage-messages");
+ if (!messagesContainer) {
+ return;
+ }
- const visibleDivs = messageDivs.filter((el) => {
- const style = window.getComputedStyle(el);
- return (
- style.display !== "none" &&
- style.visibility !== "hidden" &&
- !el.hasAttribute("hidden") &&
- el.getClientRects().length > 0
+ const updateLastVisibleMessageMargin = () => {
+ const messageDivs = Array.from(messagesContainer.children).filter(
+ (el) => el.tagName === "DIV",
);
- });
- const lastVisible = visibleDivs[visibleDivs.length - 1];
- if (lastVisible) {
- lastVisible.style.marginBottom = "var(--section-padding)";
- }
- };
+ messageDivs.forEach((el) => {
+ el.style.marginBottom = "";
+ });
- let rafId = null;
- const scheduleUpdate = () => {
- if (rafId !== null) {
- return;
- }
- rafId = requestAnimationFrame(() => {
- rafId = null;
- updateLastVisibleMessageMargin();
- });
- };
+ const visibleDivs = messageDivs.filter((el) => {
+ const style = window.getComputedStyle(el);
+ return (
+ style.display !== "none" &&
+ style.visibility !== "hidden" &&
+ !el.hasAttribute("hidden") &&
+ el.getClientRects().length > 0
+ );
+ });
+
+ const lastVisible = visibleDivs[visibleDivs.length - 1];
+ if (lastVisible) {
+ lastVisible.style.marginBottom = "var(--section-padding)";
+ }
+ };
- updateLastVisibleMessageMargin();
+ let rafId = null;
+ const scheduleUpdate = () => {
+ if (rafId !== null) {
+ return;
+ }
+ rafId = requestAnimationFrame(() => {
+ rafId = null;
+ updateLastVisibleMessageMargin();
+ });
+ };
+
+ updateLastVisibleMessageMargin();
+
+ const observer = new MutationObserver(scheduleUpdate);
+ observer.observe(messagesContainer, {
+ childList: true,
+ subtree: true,
+ attributes: true,
+ attributeFilter: ["style", "class", "hidden", "aria-hidden"],
+ });
+ }
- const observer = new MutationObserver(scheduleUpdate);
- observer.observe(messagesContainer, {
- childList: true,
- subtree: true,
- attributes: true,
- attributeFilter: ["style", "class", "hidden", "aria-hidden"],
- });
+ initSearchBar();
+ initMessages();
});
diff --git a/test/src/test/java/hudson/AboutJenkinsTest.java b/test/src/test/java/hudson/AboutJenkinsTest.java
index 16c72540b76c..905ddf0335d2 100644
--- a/test/src/test/java/hudson/AboutJenkinsTest.java
+++ b/test/src/test/java/hudson/AboutJenkinsTest.java
@@ -94,7 +94,7 @@ void onlyAdminOrManageOrSystemReadCanReadAbout() throws Exception {
wc.login(ADMIN);
HtmlPage page = wc.goTo("about/");
assertEquals(HttpURLConnection.HTTP_OK, page.getWebResponse().getStatusCode());
- assertThat(page.getWebResponse().getContentAsString(), containsString("Mavenized dependencies"));
+ assertThat(page.querySelector("body").asXml(), containsString("Mavenized dependencies"));
}
{ // manager can access it
diff --git a/test/src/test/java/hudson/model/ManagementLinkTest.java b/test/src/test/java/hudson/model/ManagementLinkTest.java
index 70ba5a7ff125..d7836c31a427 100644
--- a/test/src/test/java/hudson/model/ManagementLinkTest.java
+++ b/test/src/test/java/hudson/model/ManagementLinkTest.java
@@ -27,8 +27,8 @@
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.util.List;
-import org.htmlunit.html.DomNodeUtil;
+import org.htmlunit.html.DomNode;
+import org.htmlunit.html.DomNodeList;
import org.htmlunit.html.HtmlAnchor;
import org.htmlunit.html.HtmlPage;
import org.junit.jupiter.api.BeforeEach;
@@ -60,14 +60,15 @@ void setUp(JenkinsRule rule) {
@WithTimeout(300)
void links() throws Exception {
WebClient wc = j.createWebClient();
+ HtmlPage page = wc.goTo("manage");
- for (int i = 0; ; i++) {
- HtmlPage page = wc.goTo("manage");
- List> anchors = DomNodeUtil.selectNodes(page, "//div[contains(@class,'jenkins-section__item')]/a[not(contains(@class,'confirmation-link'))]");
- assertTrue(anchors.size() >= 8);
- if (i == anchors.size()) return; // done
+ DomNodeList anchors = page.querySelectorAll("a.task-link:not(.confirmation-link)");
+ assertTrue(anchors.size() >= 8);
- ((HtmlAnchor) anchors.get(i)).click();
+ String prefix = j.contextPath + '/';
+ for (DomNode anchor : anchors) {
+ System.out.println(((HtmlAnchor) anchor).getHrefAttribute());
+ wc.goTo(((HtmlAnchor) anchor).getHrefAttribute().substring(prefix.length()), null);
}
}
diff --git a/test/src/test/java/jenkins/bugs/Jenkins64991Test.java b/test/src/test/java/jenkins/bugs/Jenkins64991Test.java
index 7ff236736224..1a4bd4a457e7 100644
--- a/test/src/test/java/jenkins/bugs/Jenkins64991Test.java
+++ b/test/src/test/java/jenkins/bugs/Jenkins64991Test.java
@@ -85,7 +85,7 @@ void test403Redirect() throws Exception {
final Page redirectedPage = HtmlFormUtil.submit(loginPage.getFormByName("login"));
assertTrue(redirectedPage.isHtmlPage());
- assertEquals(j.getURL() + "manage/", redirectedPage.getUrl().toExternalForm());
+ assertEquals(j.getURL() + "manage/configure", redirectedPage.getUrl().toExternalForm());
assertThat(redirectedPage.getWebResponse().getContentAsString(), containsStringIgnoringCase(Messages.GlobalSecurityConfiguration_DisplayName()));
}
diff --git a/test/src/test/java/jenkins/security/csp/impl/CspHeaderDeciderTest.java b/test/src/test/java/jenkins/security/csp/impl/CspHeaderDeciderTest.java
index 67e41556506d..7c76c7843d26 100644
--- a/test/src/test/java/jenkins/security/csp/impl/CspHeaderDeciderTest.java
+++ b/test/src/test/java/jenkins/security/csp/impl/CspHeaderDeciderTest.java
@@ -42,7 +42,7 @@ public void testDefaultInTest(JenkinsRule j) {
final HtmlPage htmlPage = webClient.goTo("configureSecurity");
assertThat(
- htmlPage.getWebResponse().getContentAsString(),
+ htmlPage.querySelector("body").asXml(),
hasBlurb(jellyResource(DevelopmentHeaderDecider.class, "message.properties")));
assertThat(htmlPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy"), not(nullValue()));
assertThat(htmlPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy-Report-Only"), nullValue());
@@ -67,7 +67,7 @@ public void testDefaultWithSystemPropertyEnforce(JenkinsRule j) throws IOExcepti
final HtmlPage htmlPage = webClient.goTo("configureSecurity");
assertThat(
- htmlPage.getWebResponse().getContentAsString().replace("Content-Security-Policy", "{0}"),
+ htmlPage.querySelector("body").asXml().replace("Content-Security-Policy", "{0}"),
hasBlurb(jellyResource(SystemPropertyHeaderDecider.class, "message.properties")));
assertThat(htmlPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy"), not(nullValue()));
assertThat(htmlPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy-Report-Only"), nullValue());
@@ -92,7 +92,7 @@ public void testDefaultWithSystemPropertyUnenforce(JenkinsRule j) throws IOExcep
final HtmlPage htmlPage = webClient.goTo("configureSecurity");
assertThat(
- htmlPage.getWebResponse().getContentAsString().replace("Content-Security-Policy-Report-Only", "{0}"),
+ htmlPage.querySelector("body").asXml().replace("Content-Security-Policy-Report-Only", "{0}"),
hasBlurb(jellyResource(SystemPropertyHeaderDecider.class, "message.properties")));
assertThat(htmlPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy"), nullValue());
assertThat(htmlPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy-Report-Only"), not(nullValue()));
@@ -117,7 +117,7 @@ public void testDefaultWithSystemPropertyNone(JenkinsRule j) throws IOException,
final HtmlPage htmlPage = webClient.goTo("configureSecurity");
assertThat(
- htmlPage.getWebResponse().getContentAsString(),
+ htmlPage.querySelector("body").asXml(),
hasMessage(jellyResource(SystemPropertyHeaderDecider.class, "message.properties"), "blurbUnset"));
assertThat(htmlPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy"), nullValue());
assertThat(htmlPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy-Report-Only"), nullValue());
@@ -142,7 +142,7 @@ public void testDefaultWithSystemPropertyWrong(JenkinsRule j) throws IOException
final HtmlPage htmlPage = webClient.goTo("configureSecurity");
assertThat(
- htmlPage.getWebResponse().getContentAsString(),
+ htmlPage.querySelector("body").asXml(),
allOf(
hasBlurb(jellyResource(DevelopmentHeaderDecider.class, "message.properties")),
not(hasBlurb(jellyResource(SystemPropertyHeaderDecider.class, "message.properties")))));
@@ -172,7 +172,7 @@ public void testFallback(JenkinsRule j) throws IOException, SAXException {
final HtmlPage htmlPage = webClient.goTo("configureSecurity");
assertThat(
// Workaround to placeholder for context path in this string
- htmlPage.getWebResponse().getContentAsString().replace("/jenkins/", "{0}/"),
+ htmlPage.querySelector("body").asXml().replace("/jenkins/", "{0}/"),
hasBlurb(jellyResource(FallbackDecider.class, "message.properties")));
assertThat(htmlPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy"), nullValue());
assertThat(htmlPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy-Report-Only"), not(nullValue()));
@@ -220,7 +220,7 @@ public void testFallbackAdminMonitorAndSetup(JenkinsRule j) throws IOException,
assertFalse(ExtensionList.lookupSingleton(CspRecommendation.class).isActivated());
// We can see the checkbox now
- assertThat(setupPage.getWebResponse().getContentAsString(), containsString("Enforce Content Security Policy"));
+ assertThat(setupPage.querySelector("body").asXml(), containsString("Enforce Content Security Policy"));
assertThat(setupPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy"), nullValue());
assertThat(setupPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy-Report-Only"), not(nullValue()));
@@ -234,7 +234,8 @@ public void testFallbackAdminMonitorAndSetup(JenkinsRule j) throws IOException,
final Page afterSavingPage = HtmlFormUtil.submit(setupPage.getFormByName("config"), setupPage.getFormByName("config").getButtonByName("Submit"));
assertThat(afterSavingPage, instanceOf(HtmlPage.class));
- assertThat(afterSavingPage.getUrl().getPath(), is(j.contextPath + "/manage/"));
+ // TODO - investigate if this is correct? should admin monitors redirect configSecurity (no?!)
+ assertThat(afterSavingPage.getUrl().getPath(), is(j.contextPath + "/manage/configureSecurity/"));
assertThat(afterSavingPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy"), not(nullValue()));
assertThat(afterSavingPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy-Report-Only"), nullValue());