Skip to content

Conversation

vicky-iv
Copy link
Contributor

@vicky-iv vicky-iv commented Aug 20, 2025

User description

🔗 Related Issues

[🚀 Feature]: Unifying Select Class Across All Bindings #15265

💥 What does this PR do?

I implemented unifying the Select class across all bindings for the Java package.
I also extended the unit tests to cover this functionality by shadowing PR for python #15135

🔧 Implementation Notes

The selectByContainsVisibleText method already had the necessary implementation, so I just added the missing exception throwing for the selectByVisibleText method.

All tests from the following packages are passed locally:
//java/test/org/openqa/selenium/support/ui/...

💡 Additional Considerations

No

🔄 Types of changes

Bug fix (backwards compatible)


PR Type

Bug fix


Description

  • Fix selectByVisibleText to throw exception for hidden options

  • Add visibility checks to prevent selecting invisible elements

  • Enhance test coverage for hidden option scenarios

  • Update Java language level to JDK 17


Diagram Walkthrough

flowchart LR
  A["selectByVisibleText method"] --> B["Add visibility check"]
  B --> C["Throw NoSuchElementException"]
  C --> D["Enhanced test coverage"]
  E["Java language level"] --> F["Update to JDK 17"]
Loading

File Walkthrough

Relevant files
Bug fix
Select.java
Add visibility validation to selectByVisibleText                 

java/src/org/openqa/selenium/support/ui/Select.java

  • Add assertSelectIsVisible() call to selectByVisibleText method
  • Add visibility checks using hasCssPropertyAndVisible() for options
  • Throw NoSuchElementException when trying to select invisible options
+5/-0     
Tests
SelectElementTest.java
Enhance tests for hidden option validation                             

java/test/org/openqa/selenium/support/ui/SelectElementTest.java

  • Update existing test to use selectByVisibleText instead of
    selectByContainsVisibleText
  • Add new test shouldThrowExceptionOnSelectByVisibleTextIfOptionHidden
  • Test multiple hidden options using Arrays.asList
+20/-2   
Configuration changes
misc.xml
Update IntelliJ project to JDK 17                                               

.idea/misc.xml

  • Update ProjectRootManager languageLevel from JDK_11 to JDK_17
  • Update project-jdk-name from "11" to "17"
+2/-2     
java.iml
Update module language level to JDK 17                                     

java/java.iml

  • Update NewModuleRootManager LANGUAGE_LEVEL from JDK_11 to JDK_17
+1/-1     

@CLAassistant
Copy link

CLAassistant commented Aug 20, 2025

CLA assistant check
All committers have signed the CLA.

@selenium-ci selenium-ci added C-java Java Bindings B-support Issue or PR related to support classes labels Aug 20, 2025
Copy link
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Exception Semantics

Throwing NoSuchElementException for hidden options changes behavior; confirm this aligns with established Selenium API semantics and does not mask other cases (e.g., disabled vs hidden) or break backward compatibility across bindings.

assertSelectIsEnabled();
assertSelectIsVisible();

// try to find the option via XPATH ...
List<WebElement> options =
    element.findElements(
        By.xpath(".//option[normalize-space(.) = " + Quotes.escape(text) + "]"));

for (WebElement option : options) {
  if (!hasCssPropertyAndVisible(option))
    throw new NoSuchElementException("Invisible option with text: " + text);
  setSelected(option, true);
  if (!isMultiple()) {
    return;
  }
Visibility Check

Validate that hasCssPropertyAndVisible(option) accurately reflects visibility for CSS-hidden options and shadow DOM cases, and that it is performant when iterating over multiple options.

      element.findElements(
          By.xpath(".//option[contains(., " + Quotes.escape(subStringWithoutSpace) + ")]"));
}

String trimmed = text.trim();

for (WebElement option : candidates) {
  if (trimmed.equals(option.getText().trim())) {
    if (!hasCssPropertyAndVisible(option))
      throw new NoSuchElementException("Invisible option with text: " + text);
    setSelected(option, true);
    if (!isMultiple()) {
      return;
    }

Copy link
Contributor

qodo-merge-pro bot commented Aug 20, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Avoid IDE and JDK bumps

This PR mixes behavioral changes with IDE-specific files and a Java language
level bump to 17, which can unintentionally force build/toolchain upgrades for
all consumers. Separate the Select behavior change and tests from project
configuration changes, and ensure the runtime/source compatibility remains
aligned with the repository’s supported JDK matrix to prevent breaking
downstream users.

Examples:

.idea/misc.xml [6]
  <component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK">
java/java.iml [6]
  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_17">

Solution Walkthrough:

Before:

// PR includes both logic and configuration changes
- src/org/openqa/selenium/support/ui/Select.java
- test/org/openqa/selenium/support/ui/SelectElementTest.java
- .idea/misc.xml
- java/java.iml

After:

// PR 1: Logic change
- src/org/openqa/selenium/support/ui/Select.java
- test/org/openqa/selenium/support/ui/SelectElementTest.java

// PR 2: JDK/IDE bump (if approved)
- .idea/misc.xml
- java/java.iml
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies that the PR improperly bundles a functional change with a significant JDK version bump and IDE configuration changes, which can break downstream builds.

High
Possible issue
Use correct exception type

Selecting an invisible option should signal an operation not permitted, not that
the element does not exist. Replace the thrown exception with an
UnsupportedOperationException to align with the existing disabled-option
behavior and avoid misleading error handling. Keep the message explicit about
invisibility.

java/src/org/openqa/selenium/support/ui/Select.java [133-165]

 for (WebElement option : options) {
-  if (!hasCssPropertyAndVisible(option))
-    throw new NoSuchElementException("Invisible option with text: " + text);
+  if (!hasCssPropertyAndVisible(option)) {
+    throw new UnsupportedOperationException("You may not select an invisible option with text: " + text);
+  }
   setSelected(option, true);
   if (!isMultiple()) {
     return;
   }
 ...
   for (WebElement option : candidates) {
     if (trimmed.equals(option.getText().trim())) {
-      if (!hasCssPropertyAndVisible(option))
-        throw new NoSuchElementException("Invisible option with text: " + text);
+      if (!hasCssPropertyAndVisible(option)) {
+        throw new UnsupportedOperationException("You may not select an invisible option with text: " + text);
+      }
       setSelected(option, true);
       if (!isMultiple()) {
         return;
       }

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out that throwing UnsupportedOperationException for an invisible option is more consistent with existing behavior for disabled options, improving API design.

Medium
  • Update

@vicky-iv vicky-iv changed the title [java]Java unifying select class [java] Unifying select class Aug 20, 2025
@diemol diemol reopened this Aug 20, 2025
Copy link
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Exception Semantics

Throwing NoSuchElementException for invisible options changes behavior; confirm this aligns with contract across bindings and does not mask cases where options exist but are not interactable. Ensure message includes enough context (value/text) and consider a dedicated exception or consistent type with other selection paths.

for (WebElement option : options) {
  if (!hasCssPropertyAndVisible(option))
    throw new NoSuchElementException("Invisible option with text: " + text);
  setSelected(option, true);
Duplicate Visibility Checks

Visibility checks are performed in both the exact-text and fallback loops; consider extracting to a helper to avoid duplication and ensure consistent messaging and behavior between branches.

for (WebElement option : candidates) {
  if (trimmed.equals(option.getText().trim())) {
    if (!hasCssPropertyAndVisible(option))
      throw new NoSuchElementException("Invisible option with text: " + text);
    setSelected(option, true);
    if (!isMultiple()) {
      return;
    }

@SeleniumHQ SeleniumHQ deleted a comment from selenium-ci Aug 20, 2025
Copy link
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Skip invisible options before failing

Avoid throwing on the first invisible match; instead, skip invisible options and
only throw if no visible option matched. This aligns with typical selection
semantics and avoids breaking cases where duplicates exist with only some
visible.

java/src/org/openqa/selenium/support/ui/Select.java [133-140]

+boolean matchedVisible = false;
 for (WebElement option : options) {
-  if (!hasCssPropertyAndVisible(option))
-    throw new NoSuchElementException("Invisible option with text: " + text);
+  if (!hasCssPropertyAndVisible(option)) {
+    continue;
+  }
   setSelected(option, true);
+  matchedVisible = true;
   if (!isMultiple()) {
     return;
   }
 }
+if (!matchedVisible) {
+  throw new NoSuchElementException("No visible option with text: " + text);
+}
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: This suggestion correctly identifies a significant flaw in the PR's logic; throwing an exception on the first invisible option is incorrect if other visible options with the same text exist, and this change fixes the behavior to correctly handle such cases.

High
Consistent invisible-option skipping in fallback

Mirror the same skip-then-fail logic for the fallback exact-text comparison
loop. This ensures consistent behavior across both XPath and manual text
matching paths.

java/src/org/openqa/selenium/support/ui/Select.java [158-165]

+boolean matchedVisibleFallback = false;
 for (WebElement option : candidates) {
   if (trimmed.equals(option.getText().trim())) {
-    if (!hasCssPropertyAndVisible(option))
-      throw new NoSuchElementException("Invisible option with text: " + text);
+    if (!hasCssPropertyAndVisible(option)) {
+      continue;
+    }
     setSelected(option, true);
+    matchedVisibleFallback = true;
     if (!isMultiple()) {
       return;
     }
   }
 }
+if (!matchedVisibleFallback) {
+  throw new NoSuchElementException("No visible option with text: " + text);
+}

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 9

__

Why: This suggestion correctly identifies a significant flaw in the PR's logic for the fallback text matching and proposes a fix that aligns with the expected behavior of selecting a visible option if one exists, thus preventing incorrect exceptions.

High
High-level
Avoid IDE config changes

This PR updates IntelliJ project files to JDK 17, which can unintentionally
affect contributors’ environments and CI without aligning the entire repo’s
build tooling (Gradle/Maven, toolchains) and release matrix. Move the Java
version bump to the build system and repo-wide policy first, then drop
IDE-specific files from the PR to prevent configuration drift.

Examples:

.idea/misc.xml [6-9]
  <component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK">
    <output url="file://$PROJECT_DIR$/build" />
  </component>
</project>
java/java.iml [6-7]
  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_17">
    <output url="file://$MODULE_DIR$/build/production" />

Solution Walkthrough:

Before:

// PR includes changes to IDE-specific configuration files
// to update the Java version.

// .idea/misc.xml
<component name="ProjectRootManager" languageLevel="JDK_17" ...>

// java/java.iml
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_17">

After:

// IDE configuration files are removed from the PR.
// The Java version update should be handled in the
// project's central build file (e.g., pom.xml, build.gradle)
// in a separate, dedicated PR.

// This PR should only contain the logic changes:
// java/src/org/openqa/selenium/support/ui/Select.java
// java/test/org/openqa/selenium/support/ui/SelectElementTest.java
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that IDE-specific configuration files like .idea/misc.xml and java.iml should not be versioned, as this can cause inconsistencies for contributors; such changes should be managed centrally in build configuration files.

Medium
  • More

Copy link
Member

@diemol diemol left a comment

Choose a reason for hiding this comment

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

Could you please run ./scripts/format.sh?

@cgoldberg
Copy link
Contributor

@vicky-iv can you also remove the changes in the 2 files that change JDK_11 to JDK_17?

I don't know who uses those specific files, but we still support JDK11 and probably should leave those as they were.

@vicky-iv
Copy link
Contributor Author

@diemol @cgoldberg done and done, thanks for your comments

Copy link
Member

@diemol diemol left a comment

Choose a reason for hiding this comment

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

Thank you, @vicky-iv! Looking forward to future contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-support Issue or PR related to support classes C-java Java Bindings Review effort 2/5
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants