Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
feb3597
Add Selenium-based test harness for the AngularJS Admin UI
janhoy Aug 13, 2026
7131cbf
Add test plan document for Admin UI browser tests
janhoy Aug 13, 2026
a350a2a
Slim the Selenium dependency footprint
janhoy Aug 13, 2026
5b8cada
Admin UI tests: smoke-test navigation of all screens
janhoy Aug 13, 2026
6f5e108
Upgrade byte-buddy to 1.18.11 project-wide
janhoy Aug 13, 2026
ae76824
Admin UI tests: node-level screen display assertions
janhoy Aug 13, 2026
565a3c8
Admin UI tests: per-collection screens and write actions
janhoy Aug 13, 2026
93d5699
Add changelog entry
janhoy Aug 13, 2026
cb78e4f
Fix forbidden API usage in Admin UI test harness
janhoy Aug 13, 2026
d1c848d
Fix Error Prone UnnecessarilyFullyQualified warnings
janhoy Aug 13, 2026
70abb58
Admin UI test harness: fixture/wait helpers, security.json hook, cons…
janhoy Aug 13, 2026
8c86f7a
Admin UI tests: Collections screen incl. alias, replica and reload ac…
janhoy Aug 13, 2026
fcfe638
Admin UI tests: Query, Documents and Paramsets screen classes
janhoy Aug 13, 2026
16f70a2
Admin UI tests: Schema screen incl. field add/delete, and Schema Desi…
janhoy Aug 13, 2026
6e3fab7
Admin UI tests: Logging, Core Admin, Stream and Replication screens
janhoy Aug 13, 2026
6fbacbc
Admin UI tests: finish feature-based regrouping; cloud graph/zkstatus…
janhoy Aug 13, 2026
26d5022
Admin UI tests: BasicAuth login and Security screen (nightly)
janhoy Aug 13, 2026
621ca01
Update Admin UI test plan doc: per-screen coverage and skipped items
janhoy Aug 13, 2026
957c0ee
Admin UI tests: stabilize designer/logging tests, track UI bugs in pl…
janhoy Aug 13, 2026
08b215d
Admin UI tests: query screen paramsets dropdown, edismax toggles, raw…
janhoy Aug 13, 2026
c20f68e
Admin UI tests: security screen add-role and add-permission dialogs
janhoy Aug 13, 2026
f3c1d6c
Admin UI tests: SQL screen, with the sql module as a test dependency
janhoy Aug 13, 2026
852ef5d
Admin UI tests: standalone-mode harness and Core Admin write actions
janhoy Aug 13, 2026
e874a15
Admin UI tests: replication screen actions on a standalone leader/fol…
janhoy Aug 13, 2026
2b1aa89
Admin UI tests: drop Nightly from schema designer test, update plan doc
janhoy Aug 13, 2026
9e8f069
Address Copilot review: EnvUtils for sysprop read, start cluster befo…
janhoy Aug 14, 2026
c6c89ad
Less fragile test fixes flakyness.
epugh Aug 14, 2026
975b5ec
Indent license-file first line
janhoy Aug 14, 2026
3678753
Lift bug section into SOLR-18347
janhoy Aug 14, 2026
3871a99
Change awaitsFix URL of AdminUiSchemaDesignerTest to point to SOLR-18347
janhoy Aug 14, 2026
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
8 changes: 8 additions & 0 deletions changelog/unreleased/admin-ui-selenium-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
title: >
Added Selenium-based JUnit test coverage for the Admin UI, driving a headless Chrome against a test cluster.
type: other
authors:
- name: Jan Høydahl
links:
- name: SOLR-8474
url: https://issues.apache.org/jira/browse/SOLR-8474
177 changes: 177 additions & 0 deletions dev-docs/admin-ui-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

# Admin UI (AngularJS) Browser Test Plan

This document tracks browser-based test coverage of the old AngularJS Admin UI
(`solr/webapp/web/`), driven by Selenium WebDriver with headless Chrome.

## How the tests work

- Tests live in `solr/webapp/src/test/org/apache/solr/webapp/` and extend
`AdminUiTestBase`, which starts a 2-node `MiniSolrCloudCluster` whose Jetty
nodes also serve the Admin UI (opt-in `JettyConfig.Builder#enableAdminUi`),
then starts a headless Chrome via Selenium WebDriver.
- A locally installed Chrome/Chromium is required; without one, tests skip via
`Assume`. Override discovery with `-Dtests.ui.chrome.binary=/path/to/chrome`.
The matching chromedriver is provisioned (and cached) by Selenium Manager.
- Display assertions compare UI text against live JSON from the same node's
admin APIs — never hardcoded values.
- Tests are grouped per screen/feature, so each screen's display and write
tests live in the same class.
- Most tests run against a 2-node cloud cluster; `AdminUiStandaloneTestBase`
additionally supports standalone (user-managed, no ZooKeeper) nodes, whose
UI differs (no Cloud/Collections/Schema Designer menus; the per-core menu
offers query/replication etc. directly).
- On failure, a screenshot, the page source and the browser console log are
saved into the test temp dir.
- Run with: `./gradlew :solr:webapp:test`

## Coverage by screen

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this docs, while nice to see in hte PR< I don't think need to stay long term?

I wish you coul dlabel content "Here for hte life of the PR, but once merged to main it goes away"!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't. thinks this is useful... this just looks like a lot of content that isn't helpful to me, and will be out of date. Now, if we think AI needs this to understand the tests, but I don't think that either... Also, i wondered if this was a checked in "lets work our way through all the screens", but since everythign has a checked checkbox, i dont' think it's that either.


### Smoke navigation — `AdminUiSmokeTest`
- [x] Every node-level route (`/`, `~logging`, `~logging/level`,
`~cloud?view=nodes|tree|zkstatus|graph`, `~cores`, `~collections`,
`~schema-designer`, `~security`, `~java-properties`, `~threads`, `login`),
every per-collection route and the per-core routes render their main
content element without severe browser console errors.

### Dashboard — `AdminUiDashboardTest`
- [x] Versions, JVM info and memory bars vs `/admin/info/system`; security
warning when security is disabled.

### Node-level screens — `AdminUiNodeScreensTest`
- [x] Java Properties: `java.version` value matches `/admin/info/properties`
- [x] Thread Dump: thread list non-empty, Jetty worker thread shown
- [x] Cloud > Nodes: one row per live node, ports match the cluster
- [x] Cloud > Tree: `live_nodes` and `collections` znodes shown
- [x] Cloud > Graph: d3 SVG renders circles for collection/shard/replicas
- [x] Cloud > ZK Status: status green, ensemble size shown
- [x] Security screen: "not enabled" warning without auth
- [x] Login screen: authentication info page without auth

### Collections screen — `AdminUiCollectionsScreenTest`
- [x] Collection detail display (shards)
- [x] Create + delete collection via the dialogs (verified via API)
- [x] Create + delete alias via the dialogs (verified via LISTALIASES)
- [x] Add + delete replica via the shard detail (verified via cluster state)
- [x] Reload collection (verified via core start time reset)

### Query screen — `AdminUiQueryScreenTest`
- [x] `*:*` and `id:` queries via the form, `numFound` in the response
- [x] `rows` and `fl` parameters affect the returned documents
- [x] Paramsets dropdown applies a paramset created via the API
- [x] defType dismax/edismax toggles reveal their parameter fields; edismax
query with `qf` returns the expected results
- [x] Raw query parameters (e.g. an extra `fq`) are applied

### Documents screen — `AdminUiDocumentsScreenTest`
- [x] Form renders with JSON/XML/CSV document types
- [x] Index a JSON document via the form; becomes searchable

### Schema screen — `AdminUiSchemaScreenTest`
- [x] Field list browsable, editable-schema action buttons shown
- [x] Field detail shows flags matching `/schema/fields`; term info loads
- [x] Add + delete a field via the dialogs (verified via `/schema/fields`)

### Paramsets screen — `AdminUiParamsetsScreenTest`
- [x] Form renders
- [x] Create + delete a paramset via the form (verified via `/config/params`)

### Logging screens — `AdminUiLoggingScreenTest`
- [x] Logger level tree renders
- [x] Set + unset a logger level via the tree (verified via API)
- [x] Events viewer shows a WARN event logged in the server JVM (skips itself
when the node's log watcher is blind due to shared-JVM log4j state, see
Known limitations)

### Core Admin screen — `AdminUiCoreAdminScreenTest` (cloud) and
### `AdminUiCoreAdminStandaloneTest` (standalone)
- [x] Hosted core listed, matching `/admin/cores`
- [x] Reload core via the button (success indicator)
- [x] Standalone-mode menu differences (no cloud menus; core menu offers
query/replication)
- [x] Add core via the dialog (pre-created instance dir)
- [x] Rename core via the dialog
- [x] Swap cores via the dialog (verified by the indexes exchanging)
- [x] Unload core, accepting the native confirm dialog

### Per-collection display screens — `AdminUiCollectionScreensTest`
- [x] Analysis: `text_general` tokenizes and lowercases entered text
- [x] Files: tree lists `solrconfig.xml`, file content renders
- [x] Segments: at least one segment rendered after commit
- [x] Plugins/Stats: searcher stats present (needs `metricsEnabled=true`)
- [x] Collection overview: shard info; Core overview: numDocs

### Stream screen — `AdminUiStreamScreenTest`
- [x] A `search(...)` streaming expression executes and renders all docs

### SQL screen — `AdminUiSqlScreenTest`
- [x] A SQL query executes through the form and the result grid lists the
documents (the sql module is a test-only dependency of `solr:webapp`)

### Replication screen — `AdminUiReplicationScreenTest` (cloud) and
### `AdminUiReplicationStandaloneTest` (standalone leader/follower)
- [x] Renders index version info in cloud mode
- [x] Follower screen shows the leader's info
- [x] Disable polling, index on the leader, replicate-now transfers the
index, re-enable polling — verified via the replication API

### Security with BasicAuth — `AdminUiSecurityAuthTest`
- [x] Unauthenticated visit redirects to login; login form authenticates
- [x] Security screen shows authn/authz plugins, users, roles, permissions
- [x] Add a user through the dialog (verified via `/admin/authentication`)
- [x] Add a role for the user through the dialog (verified via API)
- [x] Grant a predefined permission to the role (verified via API)

### Schema Designer — `AdminUiSchemaDesignerTest` (`@AwaitsFix`)
- [x] Create a new schema, paste a sample doc, analyze; derived field shown —
but the designer backend is too flaky under automation
(see [SOLR-18347](https://issues.apache.org/jira/browse/SOLR-18347)),
so the test awaits a fix before running by default

## Deliberately skipped (effort vs value)

- **JWT/OAuth login flows**: require an external identity provider or heavy
mocking; BasicAuth covers the UI's login/session mechanics.
- **Keystroke-level entry in the security dialogs**: native clicks/keystrokes
into the absolutely-positioned dialogs proved unreliable in headless Chrome;
the dialogs are driven via the Angular controller scope instead. Keyboard
entry is covered by the login form and the other screens' forms.

## Known limitations

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

some o fthese items might be resolved in the "migrate to v2" work, jthere were some weaknesses in events identified...


- The generated js-client bundle (`libs/solr/index.js`) only exists inside the
built WAR, not in the source tree tests serve from. `AdminUiTestBase` serves
a minimal stub defining the `solrApi` global (only `reloadCollection` is used
by the AngularJS UI); a future improvement could serve the real bundle when
it has been built.
- Every test cluster in the JVM registers a log-watcher appender under the same
name in the shared log4j config, so a later cluster's watcher can be blind;
the events-viewer test detects this via the API and skips itself.
- The shared menu code logs a benign
`TypeError: Cannot read properties of null (reading 'name')` from
`$scope.showCore` while the per-collection menu resolves (filtered in the
console-error assertion; candidate for a JIRA).
- The core overview ping widget answers 503 when the configset has no

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this item have a seperate JIRA to get fixed?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(thanks for logging the other JS weaknesses as a JIRA)

healthcheck file (allowed in the affected tests).
- The Schema Designer's backend transiently fails its own prep/analyze calls
with "version mismatch, retry" and recovers via its retry dialog; its API
errors are excluded from the console-error assertion.
- ASF Jenkins has no Chrome, so these tests skip there; they run on developer
machines and could run in a GitHub Actions workflow (Chrome preinstalled on
`ubuntu-latest`) as a follow-up.
4 changes: 3 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ benmanes-versions = "0.54.0"
bouncycastle = "1.84"
# @keep Browserify version used in ref-guide
browserify = "17.0.0"
bytebuddy = "1.18.9"
bytebuddy = "1.18.11"
carrot2-core = "4.8.6"
carrotsearch-hppc = "0.10.0"
carrotsearch-randomizedtesting = "2.9.1"
Expand Down Expand Up @@ -187,6 +187,7 @@ owasp-dependencycheck = "13.0.0"
perfmark = "0.27.0"
prometheus-metrics = "1.8.0"
quicktheories = "0.26"
selenium = "4.47.0"
semver4j = "6.0.0"
slf4j = "2.0.17"
spatial4j = "0.8"
Expand Down Expand Up @@ -512,6 +513,7 @@ perfmark-api = { module = "io.perfmark:perfmark-api", version.ref = "perfmark" }
prometheus-metrics-expositionformats = { module = "io.prometheus:prometheus-metrics-exposition-formats", version.ref = "prometheus-metrics" }
prometheus-metrics-model = { module = "io.prometheus:prometheus-metrics-model", version.ref = "prometheus-metrics" }
quicktheories-quicktheories = { module = "org.quicktheories:quicktheories", version.ref = "quicktheories" }
selenium-chromedriver = { module = "org.seleniumhq.selenium:selenium-chrome-driver", version.ref = "selenium" }
semver4j-semver4j = { module = "org.semver4j:semver4j", version.ref = "semver4j" }
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
slf4j-jcloverslf4j = { module = "org.slf4j:jcl-over-slf4j", version.ref = "slf4j" }
Expand Down
2 changes: 1 addition & 1 deletion solr/core/gradle.lockfile
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jakarta.ws.rs:jakarta.ws.rs-api:4.0.0=compileClasspath,compileClasspathCopy,jarV
jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=jarValidation,runtimeClasspath,runtimeClasspathCopy,runtimeLibs,testRuntimeClasspath,testRuntimeClasspathCopy
javax.inject:javax.inject:1=annotationProcessor,errorprone,testAnnotationProcessor
junit:junit:4.13.2=jarValidation,testCompileClasspath,testCompileClasspathCopy,testRuntimeClasspath,testRuntimeClasspathCopy
net.bytebuddy:byte-buddy:1.18.9=jarValidation,testCompileClasspath,testCompileClasspathCopy,testRuntimeClasspath,testRuntimeClasspathCopy
net.bytebuddy:byte-buddy:1.18.11=jarValidation,testCompileClasspath,testCompileClasspathCopy,testRuntimeClasspath,testRuntimeClasspathCopy
org.antlr:antlr4-runtime:4.13.2=jarValidation,runtimeClasspath,runtimeClasspathCopy,runtimeLibs,testRuntimeClasspath,testRuntimeClasspathCopy
org.apache.commons:commons-exec:1.6.0=compileClasspath,compileClasspathCopy,jarValidation,runtimeClasspath,runtimeClasspathCopy,runtimeLibs,testCompileClasspath,testCompileClasspathCopy,testRuntimeClasspath,testRuntimeClasspathCopy
org.apache.commons:commons-lang3:3.20.0=compileClasspath,compileClasspathCopy,jarValidation,runtimeClasspath,runtimeClasspathCopy,runtimeLibs,testCompileClasspath,testCompileClasspathCopy,testRuntimeClasspath,testRuntimeClasspathCopy
Expand Down
4 changes: 2 additions & 2 deletions solr/cross-dc-manager/gradle.lockfile
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ jakarta.ws.rs:jakarta.ws.rs-api:4.0.0=jarValidation,runtimeClasspath,runtimeLibs
jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
javax.inject:javax.inject:1=annotationProcessor,errorprone,testAnnotationProcessor
junit:junit:4.13.2=jarValidation,testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy-agent:1.18.9=jarValidation,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.18.9=jarValidation,testRuntimeClasspath
net.bytebuddy:byte-buddy-agent:1.18.11=jarValidation,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.18.11=jarValidation,testRuntimeClasspath
net.sf.jopt-simple:jopt-simple:5.0.4=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
net.sourceforge.argparse4j:argparse4j:0.7.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
org.antlr:antlr4-runtime:4.13.2=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
Expand Down
1 change: 1 addition & 0 deletions solr/licenses/byte-buddy-1.18.11.jar.sha1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8fcc3779ff85fae5164cd1b977798ca1af388e06
1 change: 0 additions & 1 deletion solr/licenses/byte-buddy-1.18.9.jar.sha1

This file was deleted.

1 change: 1 addition & 0 deletions solr/licenses/byte-buddy-agent-1.18.11.jar.sha1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
82212e5b3633e7a65fca8bec525762cfb6c9bae4
1 change: 0 additions & 1 deletion solr/licenses/byte-buddy-agent-1.18.9.jar.sha1

This file was deleted.

Loading
Loading