Most effective method for waiting for a dropdown to load and choosing a value using Selenium in JavaScript

My current task involves interacting with a website built in React using Selenium to choose a value from a dropdown menu.

Given that the website is built in React, I understand that waiting for the DOM to be ready may not always work as expected, but I still incorporate this step in my process.

Here are the lines of code that I have written and verified to be functional:

  • The first three lines are used to click on the dropdown menu.
  • The last three lines are used to select an item from the dropdown list.
/** Find dropdown and click on it */
await driver.wait(until.elementLocated(By.css('div#discipline')))
const dropdown = await driver.findElement(By.css('div#discipline'))
await dropdown.click()
        
/** Wait for the list, find the element to select, and click on it */
const dropOpts = await driver.wait(until.elementLocated(By.css('div#menu-discipline > div > ul')))
await driver.wait(until.elementLocated(By.xpath('//li[contains(text(),"Infirmary")]'))
const choice = await dropOpts.findElement(By.xpath('//li[contains(text(),"Infirmary")]'))     
await choice.click()
  • My first question pertains to the correctness of the above code. Although it executes successfully, I am unsure if it is truly correct.
  • Secondly, I am questioning whether it is appropriate to FIRST wait for an element and THEN look for it, or vice versa.
  • Finally, my most pressing concern lies with the last three lines of code. Is it best practice to A) wait for the parent element of the dropdown menu, B) wait for the dropdown menu itself to appear using driver.wait, C) locate the element I wish to select using findElement? Or should I reverse the order?

I'm feeling a bit confused about this aspect and would appreciate some clarity.

Answer №1

I developed a set of functions that

  • utilizes elementLocated, as it is used within its own code findElement;
  • employs elementIsVisible, to verify if an element is visible;
  • makes use of elementIsEnabled, to confirm if an element is enabled (these last two checks are a commonly recommended approach to ensure that an element is indeed present in the DOM, reference courtesy of Louis on Stack Overflow).

Here is the implemented code:

async function waitAndClickElement(driver, selectorType, selector) {
  let element
  try {
    element = await driver.wait(until.elementLocated(By[selectorType](selector)), timeout)
    await driver.wait(until.elementIsVisible(element), timeout)
    await driver.wait(until.elementIsEnabled(element), timeout)
    await element.click()
  } catch (error) {
    console.error('Something went wrong!\n', error.stack, '\n')
    throw error
  }

  return element
}

This method allows for flexibility in selecting your preferred selector by simply inputting selectorType as a string in the parameters.

Moreover, I utilized this function twice: once for identifying the dropdown and another time to select an element:

/** Locate and click on 'test' dropdown */
await waitAndClickElement(driver, 'css', 'div#test')

/** Await the list, find the desired element, then click on it */
await waitAndClickElement(
  driver,
  'xpath',
  `//li[contains(text(),"myText")]`,
)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The EJS is throwing an error because it cannot define the property "round" on an undefined object

I'm currently delving into the realm of Node.js, using the "Secrets of Ninja" book as my guide. I've come across an EJS program in the book that I copied verbatim to run, but I encountered an error despite not making any modifications to the code ...

The Jquery function is failing to retrieve data from the MySQL database

I am currently attempting to retrieve values from phpMyAdmin and populate them into the second select field based on the selection made in the first select field. However, I seem to be encountering an issue as the selected value is not being passed to my P ...

Player-Oriented Online Game: Addressing Target Accuracy Challenges in ctx.setTransform

I'm currently developing a web game and my goal is to ensure that the player remains at the center of the screen. However, as the player moves further away from the center, the accuracy decreases. I've attempted using ctx.setTransform, which work ...

Hover and hover-off functions in navigation menu

html <div class="hidden-nav"> <h4>lorem</h4> <ul class="decor-menu-list"> <li><a href="#">123</a></li> <li><a href="#">123</a></li> <li><a hre ...

Tips for resolving the issue of a Bootstrap dropdown menu overlapping content in its vicinity

I am trying to position a Bootstrap dropdown button on the right-hand side of the page. The dropdown should cover 100% of the page's width and overlay any content when activated. However, there is a large logo on the left-hand side that I want users t ...

The driver encounters an issue with finding elements when there is an empty bar present in the bar chart

I am working on automating and extracting information from a graph based on the tooltip displayed on hover action. The XPath for the SVG area covering the bars is: //div[contains(@class,'commonGraphStyle__CommonGraphStyle')][3]//*[local-name()=& ...

Losing a specific characteristic of data occurs when assigning a JavaScript object

After dedicating a full day to investigating this case, I found myself losing hope. const Tests = (state = INIT_STATE, action) => { switch (action.type) { case GET_TEST_DETAIL: return { ...state, test: {}, error ...

Set up AngularJS routing for accessing the Web API endpoint

I have encountered an issue with my AngularJS application and Asp.net Web Api. Both applications are hosted on port 80 of the IIS server. The problem arises when the web api URL cannot be accessed due to angularjs routing redirecting API calls to the root ...

Python request is fetching a distinct HTML content compared to what is visible in the view

I'm having trouble retrieving the fanfiction content from a specific URL on Archive of Our Own for linguistic analysis using the NLTK library. Despite my efforts to scrape the HTML, I am unable to extract the fanfic itself (and don't need the com ...

Are mutations in Vuex guaranteed to be atomic?

I'm currently investigating the atomicity of mutations in Vuex. The code snippet I'm reviewing has me questioning whether the CHANGE_A mutation could potentially be triggered while CHANGE_B is still in progress: const mutations = { [CHANGE_A]( ...

how can I use jQuery to disable clickable behavior in HTML anchor tags?

Here is the HTML code I am working with: (note -: I included j library on the top of page ) <div class="WIWC_T1"> <a href="javascript:void(0);" onClick="call_levelofcourse();popup('popUpDiv1')">Level of Course</a> </di ...

What is the process for attaching the stack when initializing and throwing errors separately in JavaScript?

In all the documentation I've read, it consistently advises to both throw and initialize errors on the same line. For example: throw new Error("My error"); But what if you were to first initialize the error and then throw it on separate lines? For ...

Trying out the ClientPortal in Next.JS with Jest Testing

I'm currently working with NextJS and I want to run tests on the ClientPortal component. My testing toolkit consists of Jest and React Testing Library. Below is a sample code snippet for the ClientPortal component: import { useEffect, useRef, useStat ...

"Maximizing the slider with jCarousel: A guide to enhancing your carousel experience

I recently added jcarousel to my website and things are looking good so far. Take a peek at how my site is currently set up: check it out! What I'm aiming for now is a feature where if a user clicks on an image to enlarge, it will open in a new tab ...

Switching between different months in the React-Calendar display

I've been working with React-Calendar and I'm facing an issue where the month doesn't change when clicking the navigation arrows in the calendar. Here's a snippet of my code: ... const onActiveStartDateChangeHandler = ({ activeStartDa ...

Is there a way to inform TypeScript that the process is defined rather than undefined?

When I execute the code line below: internalWhiteList = process.env.INTERNAL_IP_WHITELIST.split( ',' ) An error pops up indicating, Object is possibly undefined. The env variables are injected into process.env through the utilization of the mod ...

JQuery validation for phone number format 01x-xxxxxxxx

Currently, I am using jQuery Validate to validate the form. In order to validate the phone number field, I have implemented the following code: The phone number should be written in the format 01x-xxxxxxxx var phonereg = /^[0-9]{3}\-[0-9]{7}$/; H ...

Combining file and JSON data in React and Express: A guide to uploading both simultaneously

I am looking to send both a file and JSON data from a form using my react handle submission method. const formData = new FormData(); formData.append('File', selectedFile); const data = { name: 'vasu', email: 'example@example ...

Waiting for multiple asynchronous calls in Node.js is a common challenge that many developers

I'm facing a dilemma trying to execute multiple MongoDB queries before rendering a Jade template. I am struggling to find a way to ensure that all the Mongo Queries are completed before proceeding with rendering the template. exports.init = funct ...

The tablesorter plugin from Jquery isn't functioning properly on my dynamically loaded ajax table

I am having trouble getting Tablesorter to work with my table. I attempted to use .trigger('update') but it did not have the desired effect for me. Instead, I tried using stupidtable and it worked to some extent, but not perfectly (it did not sor ...