Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update search function for Command palette #772

Merged
merged 14 commits into from
May 26, 2024
30 changes: 27 additions & 3 deletions src/main/java/org/jvnet/hudson/test/HudsonTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.jvnet.hudson.test.QueryUtils.waitUntilElementIsPresent;
import static org.jvnet.hudson.test.QueryUtils.waitUntilStringIsNotPresent;

import com.google.inject.Injector;
import edu.umd.cs.findbugs.annotations.NonNull;
Expand Down Expand Up @@ -167,6 +169,7 @@
import org.htmlunit.cssparser.parser.CSSParseException;
import org.htmlunit.html.DomNode;
import org.htmlunit.html.DomNodeUtil;
import org.htmlunit.html.HtmlAnchor;
import org.htmlunit.html.HtmlButton;
import org.htmlunit.html.HtmlElement;
import org.htmlunit.html.HtmlForm;
Expand Down Expand Up @@ -1593,9 +1596,30 @@ public void run() {

public HtmlPage search(String q) throws IOException, SAXException {
HtmlPage top = goTo("");
HtmlForm search = top.getFormByName("search");
search.getInputByName("q").setValue(q);
return (HtmlPage)HtmlFormUtil.submit(search, null);
HtmlButton button = top.querySelector("#button-open-command-palette");

// Legacy versions of Jenkins
if (button == null) {
HtmlForm search = top.getFormByName("search");
search.getInputByName("q").setValue(q);
return (HtmlPage) HtmlFormUtil.submit(search, null);
}

button.click();
HtmlInput search = top.querySelector("#command-bar");
search.setValue(q);
top.executeJavaScript("document.querySelector('#command-bar').dispatchEvent(new Event(\"input\"))");

// We need to wait for the 'Get help using Jenkins search' item to no longer be visible
waitUntilStringIsNotPresent(top, "Get help using Jenkins search");
HtmlAnchor firstResult = (HtmlAnchor) waitUntilElementIsPresent(top, ".jenkins-command-palette__results__item");

if (firstResult == null) {
System.out.println("Couldn't find result for query '" + q + "'");
return null;
}

return firstResult.click();
}

/**
Expand Down
30 changes: 27 additions & 3 deletions src/main/java/org/jvnet/hudson/test/JenkinsRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.jvnet.hudson.test.QueryUtils.waitUntilElementIsPresent;
import static org.jvnet.hudson.test.QueryUtils.waitUntilStringIsNotPresent;

import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
Expand Down Expand Up @@ -207,6 +209,7 @@
import org.htmlunit.cssparser.parser.CSSParseException;
import org.htmlunit.html.DomNode;
import org.htmlunit.html.DomNodeUtil;
import org.htmlunit.html.HtmlAnchor;
import org.htmlunit.html.HtmlButton;
import org.htmlunit.html.HtmlElement;
import org.htmlunit.html.HtmlElementUtil;
Expand Down Expand Up @@ -2624,9 +2627,30 @@ public void run() {

public HtmlPage search(String q) throws IOException, SAXException {
HtmlPage top = goTo("");
HtmlForm search = top.getFormByName("search");
search.getInputByName("q").setValue(q);
return (HtmlPage)HtmlFormUtil.submit(search, null);
HtmlButton button = top.querySelector("#button-open-command-palette");

// Legacy versions of Jenkins
if (button == null) {
HtmlForm search = top.getFormByName("search");
search.getInputByName("q").setValue(q);
return (HtmlPage) HtmlFormUtil.submit(search, null);
}

button.click();
HtmlInput search = top.querySelector("#command-bar");
search.setValue(q);
top.executeJavaScript("document.querySelector('#command-bar').dispatchEvent(new Event(\"input\"))");

// We need to wait for the 'Get help using Jenkins search' item to no longer be visible
waitUntilStringIsNotPresent(top, "Get help using Jenkins search");
HtmlAnchor firstResult = (HtmlAnchor) waitUntilElementIsPresent(top, ".jenkins-command-palette__results__item");

if (firstResult == null) {
System.out.println("Couldn't find result for query '" + q + "'");
return null;
}

return firstResult.click();
}

/**
Expand Down
96 changes: 96 additions & 0 deletions src/main/java/org/jvnet/hudson/test/QueryUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package org.jvnet.hudson.test;

import org.htmlunit.html.HtmlElement;
import org.htmlunit.html.HtmlPage;

import java.util.concurrent.TimeUnit;

public final class QueryUtils {

private QueryUtils() {}

/**
* Waits until the given string is visible on the page, otherwise throws an exception
* @param page the page
* @param value the value to find
* @throws RuntimeException if string is not present after three seconds
*/
public static void waitUntilStringIsPresent(HtmlPage page, String value) {
long maxWaitTime = TimeUnit.SECONDS.toMillis(3);
long startTime = System.currentTimeMillis();

while (System.currentTimeMillis() - startTime < maxWaitTime) {
if (page.querySelector("*").getVisibleText().contains(value)) {
System.out.println("Took '" + (System.currentTimeMillis() - startTime) + "ms' " +
"until string '" + value + "' was present");
return;
} else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

throw new RuntimeException("String '" + value + "' was not present '" + value + "' after '" + maxWaitTime + "s'");
}

/**
* Waits until the given string is not visible on the page, otherwise throws an exception
* @param page the page
* @param value the value to not find
* @throws RuntimeException if string is present after three seconds
*/
public static void waitUntilStringIsNotPresent(HtmlPage page, String value) {
long maxWaitTime = TimeUnit.SECONDS.toMillis(3);
long startTime = System.currentTimeMillis();

while (System.currentTimeMillis() - startTime < maxWaitTime) {
if (page.querySelector("*").getVisibleText().contains(value)) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
System.out.println("Took '" + (System.currentTimeMillis() - startTime) + "ms' " +
"until string '" + value + "' was no longer present");
return;
}
}

throw new RuntimeException("String '" + value + "' is still present '" + value + "' after '" + maxWaitTime + "s'");
}

/**
* Waits until the given query selector is visible on the page, otherwise returns null
* @param page the page
* @param query the query selector for the element
*/
public static HtmlElement waitUntilElementIsPresent(HtmlPage page, String query) {
long maxWaitTime = TimeUnit.SECONDS.toMillis(3);
long startTime = System.currentTimeMillis();

// Loop until the element is found or timeout occurs
HtmlElement element = null;
while (element == null && System.currentTimeMillis() - startTime < maxWaitTime) {
// Try to find the element
try {
element = page.querySelector(query);
} catch (Exception ignored) {
System.out.println("Looking again for element: " + query);
}

// If the element is not found, wait for a short interval before trying again
if (element == null) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
return element;
}
}