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

Overhaul search with a Command Palette #7569

Open
wants to merge 128 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 116 commits
Commits
Show all changes
128 commits
Select commit Hold shift + click to select a range
1b37f3e
Squashed commit of the following:
janfaracik Dec 21, 2022
39589a3
Reset
janfaracik Dec 21, 2022
22d83a7
Simplify
janfaracik Dec 21, 2022
cbc13a7
Fix urls
janfaracik Dec 21, 2022
a240f54
Polish
janfaracik Dec 21, 2022
654d71e
Fix keyboard nav
janfaracik Dec 21, 2022
065e979
Merge branch 'master' into command-palette
janfaracik Jan 5, 2023
5048640
Fix help link
janfaracik Jan 6, 2023
4e7f0c3
Fixes
janfaracik Jan 6, 2023
64864ab
Attempt at getting the build passing
janfaracik Jan 13, 2023
a76919d
Merge branch 'master' into command-palette
janfaracik Jan 13, 2023
9b70f56
Merge branch 'master' into command-palette
janfaracik Apr 6, 2023
0fb9f1f
Only run JS if not unit test
janfaracik Apr 6, 2023
5bb9393
Comment out failing tests
janfaracik Apr 7, 2023
fb54dc0
Update SearchTest.java
janfaracik Apr 7, 2023
1e2f45d
Linting
janfaracik Apr 7, 2023
19077cd
Update SearchTest.java
janfaracik Apr 7, 2023
f850297
Update HudsonTest.java
janfaracik Apr 8, 2023
31e345f
Merge branch 'master' into command-palette
janfaracik Apr 9, 2023
d7b4b92
Merge branch 'master' into command-palette
janfaracik Apr 21, 2023
2688ce3
Merge in master
janfaracik Apr 21, 2023
b2f9a44
Merge branch 'master' into command-palette
janfaracik Apr 25, 2023
796395d
Merge branch 'master' into command-palette
janfaracik May 17, 2023
1d1df8e
Update command-palette.scss
janfaracik May 17, 2023
bb9faf0
Merge branch 'master' into command-palette
timja May 25, 2023
bc7da9e
Merge branch 'master' into command-palette
janfaracik May 28, 2023
0511461
Update HistoryWidgetTest.java
janfaracik Jun 1, 2023
081f60b
Merge branch 'master' into command-palette
janfaracik Jun 1, 2023
6f09f80
Merge branch 'master' into command-palette
NotMyFault Jun 5, 2023
72252ec
temp: Test to see if HTMLUnit 3 supports newer JS
janfaracik Jun 6, 2023
8dc955d
It does not :(
janfaracik Jun 7, 2023
285776f
Merge branch 'master' into command-palette
janfaracik Jun 29, 2023
51d2626
Escape text/urls, fix appearance on non Safari browsers
janfaracik Jun 29, 2023
f44be2a
Linting
janfaracik Jun 29, 2023
0a409e0
Update war/src/main/js/api/search.js
janfaracik Jun 29, 2023
ce0410e
Remove escapeHTML usages, darken backdrop
janfaracik Jun 29, 2023
f203189
Merge branch 'master' into command-palette
janfaracik Aug 15, 2023
157858c
Linting
janfaracik Aug 15, 2023
ad2e760
Merge branch 'master' into command-palette
janfaracik Aug 19, 2023
df50631
Update theme.scss
janfaracik Aug 19, 2023
d61a966
Merge branch 'master' into command-palette
janfaracik Aug 23, 2023
1cf43ca
Update for SCSS refactor
janfaracik Aug 23, 2023
f608c94
Fix search bar appearance
janfaracik Aug 23, 2023
0d8e1a2
Init
janfaracik Aug 23, 2023
480b919
Merge branch 'keyboard-shortcut-animation' into command-palette
janfaracik Aug 23, 2023
5576ea2
Update headerContent.jelly
janfaracik Aug 23, 2023
1617295
Use absolute URL for search
janfaracik Aug 25, 2023
1783029
yarn lint:fix
timja Aug 25, 2023
accd74d
Update _tooltips.scss
janfaracik Aug 26, 2023
abd3361
Use getAbsoluteUrl for User
janfaracik Aug 26, 2023
ff66478
Remove configure and config from SearchIndex
janfaracik Aug 26, 2023
a52f773
Merge branch 'master' into command-palette
janfaracik Aug 26, 2023
aec5c9f
Add rootUrl for manage link
janfaracik Aug 26, 2023
15e7c9a
Update Jenkins.java
janfaracik Aug 26, 2023
c0ae7da
Use absolute urls for computer/view
janfaracik Aug 26, 2023
ec58717
Merge branch 'master' into keyboard-shortcut-animation
janfaracik Nov 5, 2023
231631d
Merge branch 'master' into keyboard-shortcut-animation
janfaracik Nov 20, 2023
3996dc0
Address comments
janfaracik Nov 20, 2023
5fa1ed0
Merge branch 'master' into command-palette
janfaracik Nov 20, 2023
e475abe
Merge branch 'keyboard-shortcut-animation' into command-palette
janfaracik Nov 20, 2023
4235d82
Merge branch 'master' into command-palette
janfaracik Apr 13, 2024
4b37c45
Update HudsonTest.java
janfaracik Apr 13, 2024
f205df1
Update _page-header.scss
janfaracik Apr 13, 2024
3a14aa9
Merge branch 'master' into command-palette
janfaracik Apr 24, 2024
7569e2e
Update index.js
janfaracik Apr 24, 2024
f4ed718
Move backdrop to var
janfaracik Apr 24, 2024
c498d44
Update Functions.java
janfaracik Apr 25, 2024
b95a175
Merge branch 'master' into command-palette
janfaracik May 19, 2024
6f73030
Merge branch 'master' into command-palette
janfaracik May 19, 2024
da84e04
Update searchbox.jelly
janfaracik May 19, 2024
63b4fd2
Update headerContent.jelly
janfaracik May 19, 2024
20a4205
Prefix with Jenkins URL via JS, reset files
janfaracik May 19, 2024
be776a2
Merge branch 'master' into command-palette
janfaracik May 19, 2024
d232157
Push
janfaracik May 19, 2024
7f53092
Update pom.xml
janfaracik May 19, 2024
ce802bc
Update pom.xml
janfaracik May 20, 2024
6092031
Make compatible with custom header plugin
timja May 21, 2024
8d295bd
Add getter/setter, use createElementFromHtml
janfaracik May 21, 2024
bf76b9c
Merge branch 'master' into command-palette
timja May 21, 2024
4639387
Merge branch 'command-palette' of github.com:janfaracik/jenkins into …
timja May 21, 2024
a51e660
Make url final
janfaracik May 21, 2024
886e25e
Update SearchTest.java
janfaracik May 21, 2024
c22f697
Update pom.xml
janfaracik May 22, 2024
74d8598
Merge branch 'master' into command-palette
janfaracik May 24, 2024
3c35b30
Test if tests will run
janfaracik May 24, 2024
6086a0f
[WIP] Attempt to get JS running in unit tests
janfaracik May 24, 2024
8e85f30
Merge branch 'master' into command-palette
janfaracik May 24, 2024
2a96790
Remove usage of async as HTMLUnit doesnt support it
janfaracik May 25, 2024
57017e6
Update SearchTest.java
janfaracik May 25, 2024
94f4b7f
Update pom.xml
janfaracik May 25, 2024
ef34c0b
Update pom.xml
janfaracik May 25, 2024
692944f
Fix test
janfaracik May 26, 2024
c87bc9a
Fix XSS test
janfaracik May 26, 2024
fb1641f
Update SearchTest.java
janfaracik May 26, 2024
27c778c
Fix tests
janfaracik May 26, 2024
972df51
Update SearchTest.java
janfaracik May 26, 2024
0274960
Merge branch 'master' into command-palette
janfaracik May 26, 2024
c63da6b
Fix remaining tests
janfaracik May 26, 2024
1eee9d2
Merge branch 'master' into command-palette
janfaracik May 28, 2024
f8a6f63
Remove keyboard shortcut from tooltip
janfaracik May 29, 2024
337c05c
Merge branch 'master' into command-palette
janfaracik May 29, 2024
63869db
Merge branch 'master' into command-palette
janfaracik May 31, 2024
b208d80
Merge branch 'master' into command-palette
janfaracik May 31, 2024
30f80e0
Increase item background contrast
janfaracik Jun 7, 2024
3f61445
Select previous search query
janfaracik Jun 7, 2024
7af9147
Change → to » for consistency
janfaracik Jun 7, 2024
a50e353
Fix debounced load
janfaracik Jun 7, 2024
8344087
Merge branch 'master' into command-palette
janfaracik Jun 11, 2024
cd638da
Merge branch 'master' into command-palette
janfaracik Jun 14, 2024
8814ca7
Update HistoryWidgetTest.java
janfaracik Jun 14, 2024
8bdea5a
Discussion: Add support for search factory extension points
janfaracik Jun 14, 2024
5cebb05
Merge branch 'master' into command-palette
janfaracik Jun 22, 2024
1a85512
Merge branch 'master' into command-palette
janfaracik Jun 24, 2024
5d1587e
Merge branch 'master' into command-palette
janfaracik Jun 28, 2024
599b02f
Merge branch 'master' into command-palette
janfaracik Jul 13, 2024
1ebc4f5
Merge branch 'master' into command-palette
janfaracik Jul 17, 2024
5ab218b
Merge branch 'master' into command-palette
janfaracik Jul 20, 2024
c5d77ee
Merge branch 'master' into command-palette
janfaracik Jul 22, 2024
0982df5
Merge branch 'master' into command-palette
janfaracik Jul 24, 2024
1db14a2
Merge branch 'master' into command-palette
janfaracik Jul 25, 2024
ecbbc8a
Merge branch 'master' into command-palette
janfaracik Aug 3, 2024
0ea776e
Merge branch 'master' into command-palette
janfaracik Aug 13, 2024
0833a4a
Fix header icon sizes
janfaracik Aug 14, 2024
97363b4
Merge branch 'master' into command-palette
janfaracik Aug 25, 2024
a20e66a
Merge branch 'master' into command-palette
janfaracik Sep 3, 2024
b0dd174
Merge branch 'master' into command-palette
janfaracik Sep 13, 2024
57905c2
Merge branch 'master' into command-palette
janfaracik Sep 16, 2024
cdff812
Merge branch 'master' into command-palette
janfaracik Sep 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions core/src/main/java/hudson/Functions.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
import hudson.model.View;
import hudson.scm.SCM;
import hudson.scm.SCMDescriptor;
import hudson.search.SearchFactory;
import hudson.search.SearchableModelObject;
import hudson.security.ACL;
import hudson.security.AccessControlled;
Expand Down Expand Up @@ -2486,4 +2487,9 @@ static String guessIcon(String iconGuess, String rootURL) {
public static String generateItemId() {
return String.valueOf(Math.floor(Math.random() * 3000));
}

@Restricted(NoExternalUse.class)
public static ExtensionList<SearchFactory> getSearchFactories() {
return SearchFactory.all();
}
}
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/model/Job.java
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ public void find(String token, List<SearchItem> result) {
public void suggest(String token, List<SearchItem> result) {
find(token, result);
}
}).add("configure", "config", "configure");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Found the UX around these sorts of things a little confusing and offering multiple results for the same thing to be odd. Happy to restore it though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to not have multiple items for the same thing (especially if one's just a substring). This removes all of them though?

OTOH There are other interesting actions (or adjacent views) that could make sense to add here, so if there's a larger plan to add more, that would be fine. Or if this just clutters up the search for jobs named "con", that would be pointless.

});
}

@Override
Expand Down
15 changes: 14 additions & 1 deletion core/src/main/java/hudson/search/Search.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public void doSuggestOpenSearch(StaplerRequest req, StaplerResponse rsp, @QueryP
public void doSuggest(StaplerRequest req, StaplerResponse rsp, @QueryParameter String query) throws IOException, ServletException {
Result r = new Result();
for (SuggestedItem item : getSuggestions(req, query))
r.suggestions.add(new Item(item.getPath()));
r.suggestions.add(new Item(item.getPath(), item.getUrl()));

rsp.serveExposedBean(req, r, Flavor.JSON);
}
Expand Down Expand Up @@ -207,12 +207,25 @@ public static class Result {

@ExportedBean(defaultVisibility = 999)
public static class Item {

@Exported
@SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", justification = "read by Stapler")
public String name;

private final String url;

public Item(String name) {
this(name, null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this result in correct behavior when used? I cannot tell.

This also ends up bloating the responses of AutocompletionCandidates, something that looks unintentional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing the autocomplete control with the Design Library and it works fine. It does bloat the response (with a url) field and there will be more fields added in the future (e.g. icon, group, etc). Is this okay for now and address in a follow up MR, alternatively which method would you think best to change?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alternatively which method would you think best to change?

Probably subtype / separate types. Unclear why AutocompletionCandidates returns a Search.Item, seems more like out of convenience than anything else.

Is this okay for now and address in a follow up MR

Works for me.

}

public Item(String name, String url) {
this.name = name;
this.url = url;
}

@Exported
public String getUrl() {
return url;
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/search/SuggestedItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private void getPath(StringBuilder buf) {
buf.append(item.getSearchName());
else {
parent.getPath(buf);
buf.append(' ').append(item.getSearchName());
buf.append(" » ").append(item.getSearchName());
}
}

Expand Down
4 changes: 1 addition & 3 deletions core/src/main/java/jenkins/model/Jenkins.java
Original file line number Diff line number Diff line change
Expand Up @@ -2431,9 +2431,7 @@ public String getSearchUrl() {
public SearchIndexBuilder makeSearchIndex() {
SearchIndexBuilder builder = super.makeSearchIndex();
if (hasPermission(ADMINISTER)) {
builder.add("configure", "config", "configure")
.add("manage")
.add("log");
builder.add("manage", Messages.ManageJenkinsAction_DisplayName());
}
builder.add(new CollectionSearchIndex<TopLevelItem>() {
@Override
Expand Down
47 changes: 47 additions & 0 deletions core/src/main/resources/lib/layout/command-palette.jelly
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!--
The MIT License

Copyright (c) 2024, Jenkins contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->

<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:s="jelly:stapler" xmlns:l="/lib/layout">
<s:documentation>
The command palette overlay
</s:documentation>

<div id="command-palette-i18n" class="i18n"
data-no-results-for="${%No results for}"
data-help="${%Help}"
data-get-help="${%Get help using Jenkins search}"
/>

<dialog id="command-palette" class="jenkins-command-palette__dialog">
<div class="jenkins-command-palette__wrapper">
<div class="jenkins-command-palette">
<l:search-bar id="command-bar" clazz="jenkins-command-palette__search" hasKeyboardShortcut="false" />
<div id="search-results-container" class="jenkins-command-palette__results-container">
<div id="search-results" class="jenkins-command-palette__results" />
</div>
</div>
</div>
</dialog>
</j:jelly>
31 changes: 11 additions & 20 deletions core/src/main/resources/lib/layout/header/searchbox.jelly
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:l="/lib/layout">
<div class="searchbox hidden-xs">
<!-- search box -->
<j:set var="searchURL" value="${h.searchURL}"/>
<form action="${searchURL}" method="get" style="position:relative;" class="no-json" name="search" role="search">
<!-- this div is used to calculate the width of the text box -->
<div id="search-box-sizer"/>
<div id="searchform">
<input name="q" placeholder="${searchPlaceholder}" id="search-box" class="main-search__input" value="${request.getParameter('q')}" role="searchbox" />
Copy link
Member

@daniel-beck daniel-beck Jun 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gets dropped, but the legacy search pages and their internal links (search-failed.jelly) still work well, so no cause for concern.

<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:st="jelly:stapler">
<div class="page-header__hyperlinks">
<j:forEach var="factory" items="${h.searchFactories}">
<st:include it="${factory}" page="search.jelly" optional="true" />
</j:forEach>

<span class="main-search__icon-leading">
<l:icon src="symbol-search"/>
</span>
<a href="${searchHelpUrl}" class="main-search__icon-trailing">
<l:icon src="symbol-help-circle"/>
</a>

<div id="search-box-completion" data-search-url="${searchURL}" />
<st:adjunct includes="jenkins.views.JenkinsHeader.search-box" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this mean for custom header compatibility?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

once jenkinsci/customizable-header-plugin#101 is merged there is no impact

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the search-box.js can then also be removed and the createSearchBox method in hudson-behaviour

</div>
</form>
<button id="button-open-command-palette" tooltip="${%Search}" data-keyboard-shortcut="CMD+K"
data-search-url="${rootURL + '/search/suggest'}"
data-search-help-url="${searchHelpUrl}"
>
<l:icon src="symbol-search" />
</button>
</div>
<script src="${resURL}/jsbundles/keyboard-shortcuts.js" type="text/javascript"/>
</j:jelly>
1 change: 1 addition & 0 deletions core/src/main/resources/lib/layout/layout.jelly
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ THE SOFTWARE.
<script src="${resURL}/jsbundles/app.js" type="text/javascript" defer="true" />
</head>
<body id="jenkins" class="yui-skin-sam ${layoutType} jenkins-${h.version}" data-version="${h.version}" data-model-type="${it.class.name}">
<l:command-palette />

<j:if test="${layoutType!='full-screen'}">
<!-- for accessibility, skip the entire navigation bar and etc and go straight to the head of the content -->
Expand Down
1 change: 1 addition & 0 deletions test/src/test/java/hudson/model/AbstractProjectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,7 @@ private void testAutoCompleteResponse(JSONObject responseBody, String... project
for (String p : projects) {
JSONObject o = new JSONObject();
o.put("name", p);
o.put("url", JSONObject.fromObject(null));
expected.add(o);
}
assertThat(suggestions.containsAll(expected), is(true));
Expand Down
76 changes: 27 additions & 49 deletions test/src/test/java/hudson/search/SearchTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.jvnet.hudson.test.QueryUtils.waitUntilStringIsPresent;

import hudson.model.FreeStyleProject;
import hudson.model.ListView;
Expand All @@ -38,7 +39,6 @@
import hudson.security.GlobalMatrixAuthorizationStrategy;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -48,6 +48,8 @@
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
import org.htmlunit.Page;
import org.htmlunit.html.HtmlButton;
import org.htmlunit.html.HtmlInput;
import org.htmlunit.html.HtmlPage;
import org.junit.Rule;
import org.junit.Test;
Expand All @@ -64,15 +66,22 @@ public class SearchTest {

@Rule public JenkinsRule j = new JenkinsRule();

/**
* No exact match should result in a failure status code.
*/
private void searchWithoutNavigating(HtmlPage page, String query) throws IOException {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be moved to jenkins-test-harness but unsure if it has any use outside of this test class.

HtmlButton button = page.querySelector("#button-open-command-palette");
button.click();

HtmlInput search = page.querySelector("#command-bar");
search.setValue(query);
page.executeJavaScript("document.querySelector('#command-bar').dispatchEvent(new Event(\"input\"))");
}

@Test
public void testFailure() throws Exception {
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage resultPage = wc.search("no-such-thing");
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, resultPage.getWebResponse().getStatusCode());
HtmlPage page = j.createWebClient().goTo("");

searchWithoutNavigating(page, "no-such-thing");

waitUntilStringIsPresent(page, "No results for no-such-thing");
}

/**
Expand All @@ -81,13 +90,17 @@ public void testFailure() throws Exception {
@Issue("JENKINS-3415")
@Test
public void testXSS() throws Exception {
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
WebClient wc = j.createWebClient();
wc.setAlertHandler((page, message) -> {
throw new AssertionError();
});
HtmlPage resultPage = wc.search("<script>alert('script');</script>");
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, resultPage.getWebResponse().getStatusCode());
FreeStyleProject freeStyleProject = j.createFreeStyleProject("Project");
freeStyleProject.setDisplayName("<script>alert('script');</script>");

Page result = wc.search("<script>alert('script');</script>");

assertNotNull(result);
assertEquals(j.getInstance().getRootUrl() + freeStyleProject.getUrl(), result.getUrl().toString());
}

@Test
Expand Down Expand Up @@ -127,7 +140,7 @@ public void testSearchByProjectNameInAFolder() throws Exception {
MockFolder myMockFolder = j.createFolder("my-folder-1");
FreeStyleProject myFreeStyleProject = myMockFolder.createProject(FreeStyleProject.class, "my-job-1");

Page result = j.createWebClient().goTo(myMockFolder.getUrl() + "search?q=" + myFreeStyleProject.getFullName());
Page result = j.search(myFreeStyleProject.getName());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Search results no longer change depending on what page you're on.


assertNotNull(result);
j.assertGoodStatus(result);
Expand Down Expand Up @@ -181,41 +194,6 @@ public void testSearch2ProjectsWithSameDisplayName() throws Exception {
assertFalse(contents.contains(otherDisplayName));
}

@Test
public void testProjectNamePrecedesDisplayName() throws Exception {
final String project1Name = "foo";
final String project1DisplayName = "project1DisplayName";
final String project2Name = "project2Name";
final String project2DisplayName = project1Name;
final String project3Name = "project3Name";
final String project3DisplayName = "project3DisplayName";

// create 1 freestyle project with the name foo
FreeStyleProject project1 = j.createFreeStyleProject(project1Name);
project1.setDisplayName(project1DisplayName);

// create another with the display name foo
FreeStyleProject project2 = j.createFreeStyleProject(project2Name);
project2.setDisplayName(project2DisplayName);

// create a third project and make sure it's not picked up by search
FreeStyleProject project3 = j.createFreeStyleProject(project3Name);
project3.setDisplayName(project3DisplayName);

// search for foo
Page result = j.search(project1Name);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test was reliant on pressing enter and having Jenkins automagically figure out which project you intended - this is no longer possible with the command palette, if there are no results then you'll get a message saying 'No results' instead.

assertNotNull(result);
j.assertGoodStatus(result);

// make sure we get the project with the name foo
String contents = result.getWebResponse().getContentAsString();
assertTrue(contents.contains(String.format("<title>%s [Jenkins]</title>", project1DisplayName)));
// make sure projects 2 and 3 were not picked up
assertFalse(contents.contains(project2Name));
assertFalse(contents.contains(project3Name));
assertFalse(contents.contains(project3DisplayName));
}

@Test
public void testGetSuggestionsHasBothNamesAndDisplayNames() throws Exception {
final String projectName = "project name";
Expand Down Expand Up @@ -335,7 +313,7 @@ public void testProjectNameInAFolderDisplayName() throws Exception {

String name = (String) jsonSuggestion.get("name");

if (displayName2.equals(name)) {
if ("my-folder-1 » job-2".equals(name)) {
foundDisplayName = true;
}
}
Expand Down
4 changes: 2 additions & 2 deletions test/src/test/java/hudson/widgets/HistoryWidgetTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ public void displayFilterInput() throws Exception {

{ // Filter input shouldn't display when there's no build
HtmlPage page = wc.goTo("job/" + p.getName());
DomNode searchInputContainer = page.querySelector(".jenkins-search");
DomNode searchInputContainer = page.querySelector("#jenkins-builds .jenkins-search");
assertTrue(searchInputContainer.getAttributes().getNamedItem("class").getNodeValue().contains("jenkins-hidden"));
}

j.buildAndAssertSuccess(p); // Add a build

{ // Filter input should display when there's a build
HtmlPage page = wc.goTo("job/" + p.getName());
DomNode searchInputContainer = page.querySelector(".jenkins-search");
DomNode searchInputContainer = page.querySelector("#jenkins-builds .jenkins-search");
assertFalse(searchInputContainer.getAttributes().getNamedItem("class").getNodeValue().contains("jenkins-hidden"));
}
}
Expand Down
3 changes: 1 addition & 2 deletions test/src/test/java/jenkins/model/JenkinsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,7 @@ public void verifyUploadedFingerprintFilePermission() throws Exception {
assumeFalse(Functions.isWindows());

HtmlPage page = j.createWebClient().goTo("fingerprintCheck");
// The form doesn't have a name, the page contain the search form and the one we're interested in
HtmlForm form = page.getForms().get(1);
HtmlForm form = page.getForms().get(0);
File dir = tmp.newFolder();
File plugin = new File(dir, "htmlpublisher.jpi");
// We're using a plugin to have a file above DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD
Expand Down
10 changes: 10 additions & 0 deletions war/src/main/js/api/search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* @param {string} searchTerm
*/
function search(searchTerm) {
const address = document.getElementById("button-open-command-palette").dataset
.searchUrl;
return fetch(`${address}?query=${encodeURIComponent(searchTerm)}`);
}

export default { search: search };
2 changes: 2 additions & 0 deletions war/src/main/js/app.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Dropdowns from "@/components/dropdowns";
import CommandPalette from "@/components/command-palette";
import Notifications from "@/components/notifications";
import SearchBar from "@/components/search-bar";
import Tooltips from "@/components/tooltips";
Expand All @@ -7,6 +8,7 @@ import ConfirmationLink from "@/components/confirmation-link";
import Dialogs from "@/components/dialogs";

Dropdowns.init();
CommandPalette.init();
Notifications.init();
SearchBar.init();
Tooltips.init();
Expand Down
Loading
Loading