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

[js] Ensure 'selectVisibleByText' method is same as other languages #13899

Merged
merged 1 commit into from
May 2, 2024

Conversation

pujagani
Copy link
Contributor

@pujagani pujagani commented May 2, 2024

User description

Thanks for contributing to Selenium!
A PR well described will help maintainers to quickly review and merge it

Before submitting your PR, please check our contributing guidelines.
Avoid large PRs, help reviewers by making them as simple and short as possible.

Description

selectVisibleByText was implemented differently than other language bindings of Selenium. It did not account for text with spaces. The changes made here fix that.

Motivation and Context

Ensure language parity regarding this particular feature.

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.

Type

Enhancement, Bug fix


Description

  • Enhanced selectByVisibleText in select.js to handle text with spaces and special characters more accurately.
  • Added new utility functions escapeQuotes and getLongestSubstringWithoutSpace to aid in XPath query generation.
  • Introduced caching for the 'multiple' attribute of select elements to optimize performance.
  • Added new test cases in select_test.js to ensure the robustness of the updated selectByVisibleText method.
  • Included a new test HTML page select_space.html to facilitate testing of the new selection capabilities.

Changes walkthrough

Relevant files
Enhancement
select.js
Enhance selectByVisibleText and Support Special Characters

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

  • Added handling for multiple attribute initialization in the
    constructor.
  • Enhanced selectByVisibleText to handle options with spaces and special
    characters more robustly.
  • Added escapeQuotes and getLongestSubstringWithoutSpace helper
    functions.
  • Modified isMultiple method to use a cached value of the multiple
    attribute.
  • +81/-23 
    fileserver.js
    Add New Test Page for Select Element                                         

    javascript/node/selenium-webdriver/lib/test/fileserver.js

  • Added a new test page 'select_space.html' to the file server for
    testing.
  • +1/-0     
    select_space.html
    New HTML Test Page for Select Element                                       

    common/src/web/select_space.html

  • Created a new HTML page with a select element to test selection
    functionality.
  • +14/-0   
    Tests
    select_test.js
    Extend Tests for New selectByVisibleText Logic                     

    javascript/node/selenium-webdriver/test/select_test.js

  • Added tests for selecting options with spaces.
  • Added tests for the escapeQuotes function handling different quote
    scenarios.
  • +37/-0   

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

    Copy link

    PR Description updated to latest commit (79b6650)

    Copy link

    PR Review

    ⏱️ Estimated effort to review [1-5]

    3, because the PR involves changes across multiple files including core functionality, utility functions, and tests. The logic for handling quotes and string manipulations is non-trivial and requires careful review to ensure correctness and efficiency.

    🧪 Relevant tests

    Yes

    🔍 Possible issues

    Possible Bug: The implementation assumes that the multiple attribute's value can only be 'false' or null when not set. However, according to HTML standards, any non-empty string including 'false' should be treated as true. This could lead to incorrect behavior in isMultiple() method.

    Performance Concern: The method selectByVisibleText could be inefficient for large select lists as it potentially iterates through all options multiple times to match text values, especially when fallback logic is triggered.

    🔒 Security concerns

    No


    ✨ Review tool usage guide:

    Overview:
    The review tool scans the PR code changes, and generates a PR review which includes several types of feedbacks, such as possible PR issues, security threats and relevant test in the PR. More feedbacks can be added by configuring the tool.

    The tool can be triggered automatically every time a new PR is opened, or can be invoked manually by commenting on any PR.

    • When commenting, to edit configurations related to the review tool (pr_reviewer section), use the following template:
    /review --pr_reviewer.some_config1=... --pr_reviewer.some_config2=...
    
    [pr_reviewer]
    some_config1=...
    some_config2=...
    

    See the review usage page for a comprehensive guide on using this tool.

    Copy link

    PR Code Suggestions

    CategorySuggestions                                                                                                                                                       
    Enhancement
    Add error handling for promise rejection in getAttribute method.

    Consider handling the promise rejection in the getAttribute method to avoid unhandled
    promise rejections, which can lead to application crashes or unexpected behavior. Use a
    try-catch block to handle potential errors.

    javascript/node/selenium-webdriver/lib/select.js [157-159]

    -this.element.getAttribute('multiple').then((multiple) => {
    -  this.multiple = multiple !== null && multiple !== 'false'
    -})
    +try {
    +  this.element.getAttribute('multiple').then((multiple) => {
    +    this.multiple = multiple !== null && multiple !== 'false'
    +  })
    +} catch (error) {
    +  console.error('Failed to get attribute:', error);
    +}
     
    Maintainability
    Use template literals to improve readability in escapeQuotes.

    Refactor the escapeQuotes function to use template literals for better readability and
    maintainability of the code.

    javascript/node/selenium-webdriver/lib/select.js [492-494]

    -result += `"${substrings[i]}"`
    -result += i === substrings.length - 1 ? (quoteIsLast ? `, '"')` : `)`) : `, '"', `
    +result += `"${substrings[i]}"${i === substrings.length - 1 ? (quoteIsLast ? `, '"'` : `)`) : `, '"', `}
     
    Performance
    Optimize finding the longest substring without space using reduce.

    Optimize the getLongestSubstringWithoutSpace function by using built-in JavaScript methods
    to find the longest word, reducing the complexity of the function.

    javascript/node/selenium-webdriver/lib/select.js [508-513]

    -let words = text.split(' ')
    -let longestString = ''
    -for (let word of words) {
    -  if (word.length > longestString.length) {
    -    longestString = word
    -  }
    -}
    +const longestString = text.split(' ').reduce((longest, word) => word.length > longest.length ? word : longest, '');
     
    Add early exit for no options found in selectByVisibleText to enhance performance.

    Ensure that the selectByVisibleText method handles cases where no options are found before
    proceeding to check for spaces in the text, which can prevent unnecessary processing.

    javascript/node/selenium-webdriver/lib/select.js [272-274]

     let matched = Array.isArray(options) && options.length > 0
    -if (!matched && text.includes(' ')) {
    +if (!matched) {
    +  throw new Error(`Cannot locate option with text: ${text}`)
    +}
    +if (text.includes(' ')) {
       const subStringWithoutSpace = getLongestSubstringWithoutSpace(text)
       ...
     
    Best practice
    Use const for unmodified variables to enhance code safety.

    Use const for variables that are not reassigned to ensure they cannot be accidentally
    changed elsewhere in the code, enhancing code safety and clarity.

    javascript/node/selenium-webdriver/lib/select.js [287-294]

    -let optionText = await option.getText()
    +const optionText = await option.getText()
     if (trimmed === optionText.trim()) {
       await this.setSelected(option)
       if (!(await this.isMultiple())) {
         return
       }
       matched = true
     }
     

    ✨ Improve tool usage guide:

    Overview:
    The improve tool scans the PR code changes, and automatically generates suggestions for improving the PR code. The tool can be triggered automatically every time a new PR is opened, or can be invoked manually by commenting on a PR.

    • When commenting, to edit configurations related to the improve tool (pr_code_suggestions section), use the following template:
    /improve --pr_code_suggestions.some_config1=... --pr_code_suggestions.some_config2=...
    
    [pr_code_suggestions]
    some_config1=...
    some_config2=...
    

    See the improve usage page for a comprehensive guide on using this tool.

    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, @pujagani!

    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.

    None yet

    2 participants