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

Straight relative-by locators #14482

Open
wants to merge 12 commits into
base: trunk
Choose a base branch
from
Open

Conversation

AdamPDotty
Copy link
Contributor

@AdamPDotty AdamPDotty commented Sep 10, 2024

User description

Description

I added four functions to relative locators in JS, Java, and Python.
Analogue to the existing functions above, below, leftOf, rightOf there are now straightAbove, straightBelow, straightLeftOf, and straightRightOf.
It also fixes instances where the two elements share a border.

Motivation and Context

With the relativeBy locators alreay existent you find elements relative to an given one. Whereas "below" just means lower than the given element. Often you want an element straight below another. Like in a table where you find row and column and then want an exact match to those both.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • I have read the contributing document.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

PR Type

Enhancement, Tests


Description

  • Implemented new straight direction locators (straightAbove, straightBelow, straightLeftOf, straightRightOf) in JavaScript and Java.
  • Added corresponding test cases in Java, JavaScript, and Python to ensure the new locators work as expected.
  • Updated HTML files used for testing to include new element IDs and structures.
  • Refactored existing locator functions for consistency and added new proximity functions for straight locators.
  • Updated test dependency paths and added an autogenerated dependency file for JavaScript tests.

Changes walkthrough 📝

Relevant files
Tests
RelativeLocatorTest.java
Add tests for straight direction locators in Java               

java/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java

  • Added tests for new straight direction locators.
  • Updated existing tests to use new element IDs.
  • Added combination tests for straight locators.
  • +154/-46
    relative_by_tests.py
    Add tests for straight direction locators in Python           

    py/test/selenium/webdriver/support/relative_by_tests.py

  • Added tests for straight direction locators.
  • Updated existing tests with new element IDs.
  • +124/-21
    relative_locators.html
    Update HTML for locator tests with new IDs                             

    common/src/web/relative_locators.html

  • Updated HTML structure for testing locators.
  • Added new IDs for elements in the test page.
  • +72/-29 
    relative_locator_test.html
    Update HTML for JS locator tests with new IDs                       

    javascript/atoms/test/relative_locator_test.html

  • Updated HTML structure for JavaScript locator tests.
  • Added new IDs and sections for testing.
  • +248/-185
    Enhancement
    relative.js
    Implement straight direction locators in JavaScript           

    javascript/atoms/locators/relative.js

  • Implemented straight direction locators.
  • Refactored existing locator functions for consistency.
  • Added new proximity functions for straight locators.
  • +103/-19
    by.js
    Add straight direction locator methods                                     

    javascript/node/selenium-webdriver/lib/by.js

    • Added methods for straight direction locators.
    +54/-2   
    Configuration changes
    deps.js
    Add autogenerated dependency file for JS tests                     

    javascript/atoms/test/deps.js

    • Added autogenerated dependency file for JavaScript tests.
    +62/-0   
    test_bootstrap.js
    Update test dependency paths in bootstrap                               

    javascript/atoms/test/test_bootstrap.js

    • Updated file paths for test dependencies.
    +2/-2     

    💡 PR-Agent usage:
    Comment /help on the PR to get a list of all available PR-Agent tools and their descriptions

    @CLAassistant
    Copy link

    CLAassistant commented Sep 10, 2024

    CLA assistant check
    All committers have signed the CLA.

    Copy link
    Contributor

    PR Reviewer Guide 🔍

    ⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Key issues to review

    Code Duplication
    There is some code duplication in the test methods for different locator types. Consider refactoring to reduce redundancy.

    Performance Concern
    The new straight direction locators might have performance implications for complex DOM structures. Consider adding a performance test.

    Copy link
    Contributor

    codiumai-pr-agent-pro bot commented Sep 10, 2024

    PR Code Suggestions ✨

    CategorySuggestion                                                                                                                                    Score
    Bug fix
    ✅ Use the correct method to check the length of a list
    Suggestion Impact:The commit replaced the use of ids.count() with len(ids) to correctly check the length of the list.

    code diff:

         ids = [el.get_attribute("id") for el in elements]
    -    assert ids.count() == 1
    +    assert len(ids) == 1
         assert "bottomRight" in ids

    Use assert len(ids) == 1 instead of assert ids.count() == 1 to check the length of
    the list. The count() method is used to count occurrences of a specific element, not
    the length of the list.

    py/test/selenium/webdriver/support/relative_by_tests.py [136-138]

     ids = [el.get_attribute("id") for el in elements]
    -assert ids.count() == 1
    +assert len(ids) == 1
     assert "bottomRight" in ids
     
    • Apply this suggestion
    Suggestion importance[1-10]: 9

    Why: The suggestion correctly identifies a misuse of the count() method for checking list length, which is a bug. Replacing it with len() is crucial for the test's accuracy.

    9
    ✅ Use the correct method to check the number of elements in a list
    Suggestion Impact:The commit replaced the incorrect use of ids.count() with len(ids) to correctly check the number of elements in the list.

    code diff:

    +    elements = driver.find_elements(with_tag_name("td").above({By.ID: "center"}))
    +
    +    ids = [el.get_attribute("id") for el in elements]
    +    assert len(ids) == 3

    Replace assert ids.count() == 3 with assert len(ids) == 3 to correctly check the
    number of elements in the list.

    py/test/selenium/webdriver/support/relative_by_tests.py [214-218]

     ids = [el.get_attribute("id") for el in elements]
    -assert ids.count() == 3
    +assert len(ids) == 3
     assert "top" in ids
     assert "topLeft" in ids
     assert "topRight" in ids
     
    • Apply this suggestion
    Suggestion importance[1-10]: 9

    Why: This suggestion addresses a bug by replacing the incorrect use of count() with len(), ensuring the test accurately checks the number of elements.

    9
    Maintainability
    ✅ Ensure consistent variable naming for clarity and correctness
    Suggestion Impact:The variable name 'el' was changed to 'elements' in multiple instances of find_elements calls, aligning with the suggestion to ensure consistent variable naming.

    code diff:

    -    el = driver.find_elements(with_tag_name("td").above({By.ID: "center"}))
    +    elements = driver.find_elements(with_tag_name("td").above({By.ID: "center"}))
     
         ids = [el.get_attribute("id") for el in elements]
         assert ids.count() == 3
    @@ -221,7 +229,7 @@
     def test_should_find_elements_below_another(driver, pages):
         pages.load("relative_locators.html")
     
    -    el = driver.find_elements(with_tag_name("td").below({By.ID: "center"}))
    +    elements = driver.find_elements(with_tag_name("td").below({By.ID: "center"}))
     
         ids = [el.get_attribute("id") for el in elements]
         assert ids.count() == 3
    @@ -233,7 +241,7 @@
     def test_should_find_elements_left_of_another(driver, pages):
         pages.load("relative_locators.html")
     
    -    el = driver.find_elements(with_tag_name("td").to_left_of({By.ID: "center"}))
    +    elements = driver.find_elements(with_tag_name("td").to_left_of({By.ID: "center"}))
     
         ids = [el.get_attribute("id") for el in elements]
         assert ids.count() == 3
    @@ -245,7 +253,7 @@
     def test_should_find_elements_right_of_another(driver, pages):
         pages.load("relative_locators.html")
     
    -    el = driver.find_elements(with_tag_name("td").to_right_of({By.ID: "center"}))
    +    elements = driver.find_elements(with_tag_name("td").to_right_of({By.ID: "center"}))
     
         ids = [el.get_attribute("id") for el in elements]
         assert ids.count() == 3
    @@ -257,7 +265,7 @@
     def test_should_find_elements_straight_above_another(driver, pages):
         pages.load("relative_locators.html")
     
    -    el = driver.find_elements(with_tag_name("td").above({By.ID: "bottom"}))
    +    elements = driver.find_elements(with_tag_name("td").above({By.ID: "bottom"}))
     
         ids = [el.get_attribute("id") for el in elements]
         assert ids.count() == 2
    @@ -268,7 +276,7 @@
     def test_should_find_elements_straight_below_another(driver, pages):
         pages.load("relative_locators.html")
     
    -    el = driver.find_elements(with_tag_name("td").below({By.ID: "top"}))
    +    elements = driver.find_elements(with_tag_name("td").below({By.ID: "top"}))
     
         ids = [el.get_attribute("id") for el in elements]
         assert ids.count() == 2
    @@ -279,7 +287,7 @@
     def test_should_find_elements_straight_left_of_another(driver, pages):
         pages.load("relative_locators.html")
     
    -    el = driver.find_elements(with_tag_name("td").to_left_of({By.ID: "right"}))
    +    elements = driver.find_elements(with_tag_name("td").to_left_of({By.ID: "right"}))
     
         ids = [el.get_attribute("id") for el in elements]
         assert ids.count() == 2
    @@ -290,7 +298,7 @@
     def test_should_find_elements_straight_right_of_another(driver, pages):
         pages.load("relative_locators.html")
     
    -    el = driver.find_elements(with_tag_name("td").to_right_of({By.ID: "left"}))
    +    elements = driver.find_elements(with_tag_name("td").to_right_of({By.ID: "left"}))

    Rename the variable el to elements in the find_elements calls to match the usage in
    the subsequent lines.

    py/test/selenium/webdriver/support/relative_by_tests.py [212-214]

    -el = driver.find_elements(with_tag_name("td").above({By.ID: "center"}))
    +elements = driver.find_elements(with_tag_name("td").above({By.ID: "center"}))
     
     ids = [el.get_attribute("id") for el in elements]
     
    • Apply this suggestion
    Suggestion importance[1-10]: 8

    Why: The suggestion improves code readability and maintainability by ensuring consistent variable naming, which is important for understanding and maintaining the code.

    8
    Improve variable naming for better code readability

    Consider using a more descriptive variable name instead of rect1_bigger. For
    example, expandedRect would better convey its purpose.

    javascript/atoms/locators/relative.js [241-246]

    -var rect1_bigger = new goog.math.Rect(
    -  rect1.left-distance,
    -  rect1.top-distance,
    -  rect1.width+distance*2,
    -  rect1.height+distance*2
    +var expandedRect = new goog.math.Rect(
    +  rect1.left - distance,
    +  rect1.top - distance,
    +  rect1.width + distance * 2,
    +  rect1.height + distance * 2
     );
     
    • Apply this suggestion
    Suggestion importance[1-10]: 7

    Why: The suggestion to rename rect1_bigger to expandedRect enhances code readability and maintainability by providing a more descriptive name that conveys the purpose of the variable more clearly.

    7
    Improve function parameter naming for better code clarity

    Consider using a more descriptive parameter name for the by parameter in the
    locateWith function. For example, locator or searchCriteria would be more
    informative.

    javascript/node/selenium-webdriver/lib/by.js [276]

    -function locateWith(by) {
    +function locateWith(locator) {
     
    • Apply this suggestion
    Suggestion importance[1-10]: 6

    Why: Renaming the by parameter to locator improves clarity by providing a more descriptive name, which helps in understanding the purpose of the parameter.

    6
    Enhancement
    Add JSDoc descriptions for new methods to improve code documentation

    Consider adding a brief JSDoc description for the straightToLeftOf and
    straightToRightOf methods to maintain consistency with other similar methods in the
    class.

    javascript/node/selenium-webdriver/lib/by.js [388-407]

    +/**
    + * Look for elements directly to the left of the root element passed in
    + * @param {string|WebElement} locatorOrElement
    + * @return {!RelativeBy} Return this object
    + */
     straightToLeftOf(locatorOrElement) {
       this.filters.push({
         kind: 'straightLeft',
         args: [getLocator(locatorOrElement)],
       })
       return this
     }
     
    +/**
    + * Look for elements directly to the right of the root element passed in
    + * @param {string|WebElement} locatorOrElement
    + * @return {!RelativeBy} Return this object
    + */
     straightToRightOf(locatorOrElement) {
       this.filters.push({
         kind: 'straightRight',
         args: [getLocator(locatorOrElement)],
       })
       return this
     }
     
    • Apply this suggestion
    Suggestion importance[1-10]: 8

    Why: Adding JSDoc descriptions for the straightToLeftOf and straightToRightOf methods enhances the documentation and consistency of the code, making it easier for developers to understand and use these methods.

    8
    Performance
    Use a set for more efficient element presence checks

    Consider using a set instead of a list for ids to improve performance when checking
    for element presence.

    py/test/selenium/webdriver/support/relative_by_tests.py [214-218]

    -ids = [el.get_attribute("id") for el in elements]
    +ids = {el.get_attribute("id") for el in elements}
     assert len(ids) == 3
     assert "top" in ids
     assert "topLeft" in ids
     assert "topRight" in ids
     
    • Apply this suggestion
    Suggestion importance[1-10]: 7

    Why: Using a set improves performance for membership checks, which is beneficial but not critical. The suggestion is a good optimization for performance.

    7
    Best practice
    Improve code formatting by adding spaces around operators

    Consider adding spaces around operators for better readability and consistency with
    JavaScript style guidelines.

    javascript/atoms/locators/relative.js [241-246]

     var rect1_bigger = new goog.math.Rect(
    -  rect1.left-distance,
    -  rect1.top-distance,
    -  rect1.width+distance*2,
    -  rect1.height+distance*2
    +  rect1.left - distance,
    +  rect1.top - distance,
    +  rect1.width + distance * 2,
    +  rect1.height + distance * 2
     );
     
    • Apply this suggestion
    Suggestion importance[1-10]: 6

    Why: Adding spaces around operators improves code readability and aligns with JavaScript style guidelines, making the code easier to read and maintain.

    6

    @pujagani
    Copy link
    Contributor

    pujagani commented Oct 8, 2024

    @diemol Are we open to changes in the support packages?

    @diemol
    Copy link
    Member

    diemol commented Oct 9, 2024

    I believe relative locators are the exception. Ideally the improvement should be implemented in all bindings.

    @AdamPDotty
    Copy link
    Contributor Author

    @diemol I am a bit at a loss here. If I understand it correctly there are .net tests failing. Could be my fault if they use the changed bindings, but I do not really see how.
    I did not succeed to run the tests locally (besides JS).
    Basically I am not sure whether I messed up there and what to do next.
    Any help appreciated.

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    4 participants