Skip to content
Advertisement

React.js How to define a custom id, rather than showing react-select-1–value in html

How do I change the React.js application to stop randomly allocating inputIds, so that Selenium will work consistently?

I’m working with Selenium and a React.js application. The application is constantly under development. I have a Selenium method working to randomly select the react dropdowns using a single, reusable method, but the ids of the react dropdowns keep changing for some reason, perhaps each time the application is built, so this creates rework for the Selenium testing.

Selenium Method: (in JAVA)

Other than those react-select inputIds changing, this method works to randomly select options in the react dropdowns, but it needs to be cleaned up. It will select an option whether or not there is already an option selected by navigating away, then back to the dropdown.

public String RandomSelect(WebDriver mydriver, String myid)
{
try{
Actions actions = new Actions(mydriver);
actions.pause(300);
WebElement dropdown = mydriver.findElement(By.id(myid));
String scrollElementIntoMiddle = "var viewPortHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);" +"var elementTop = arguments[0].getBoundingClientRect().top;"+"window.scrollBy(0, elementTop-(viewPortHeight/2));";
((JavascriptExecutor) mydriver).executeScript(scrollElementIntoMiddle, dropdown);

//((JavascriptExecutor) mydriver).executeScript(
// "arguments[0].scrollIntoView();", dropdown); 

actions.moveToElement(dropdown).click().build().perform();
actions.pause(1000);
actions.sendKeys(Keys.DELETE).build().perform();
actions.pause(1000);
actions.sendKeys(Keys.TAB).build().perform();
actions.pause(1000);
actions.moveToElement(dropdown).click().build().perform();
actions.pause(1000);
//  actions.pause(3000);
//actions.sendKeys(Keys.DELETE);
WebDriverWait wait = new WebDriverWait(mydriver, 10);
wait.until(ExpectedConditions.elementToBeClickable(By.className("Select-option")));
List<WebElement> options = mydriver.findElements(By.className("Select-option"));
List<String> stroptions = new ArrayList<>();
System.out.println(options.size());
for (WebElement option: options) {
    stroptions.add(option.getText());
    System.out.println(option.getText());
}
Random rand = new Random();
int randomNum = rand.nextInt((options.size()));
String randomoption = stroptions.get(randomNum).toString();
actions.sendKeys(randomoption+Keys.RETURN).click().build().perform();
System.out.println("Random Option Is: "+ randomoption);
//  mydriver.findElement(By.className("main-container"));

options.clear();
return randomoption;

}
catch (Exception ex)
{
    System.out.println("React Select Error: "  + ex.toString());
    return null;
}

}  

Using the Selenium Method:

Doing something like this 100’s of times is easier than typing all the Selenium methods 100’s of times.

WebDriver driver;
driver = new EdgeDriver();
ReactDropdown mydropdown = new ReactDropdown();
mydropdown.RandomSelect(driver, "react-select-1--value");

How can I remove the dynamically assigned “react-select-1–value” and define the id as something more intuitive like “mydropdown–value”, so that each time the application builds the id is maintained?

This is an example of the rendered html:

React.js html output

<div class="prop-row">
    <div class="dropdown field mydropdown ">
        <div class="field-label">
            <label for="mydropdown">mydropdownlabel</label>
        </div>
        <div class="Select mydropdown undefined is-searchable Select--single">
            <div class="Select-control">
                <span class="Select-multi-value-wrapper" id="react-select-1--value">
                    <div class="Select-placeholder">Select...</div>

Getting rid of that ugly:

id="react-select-1--value" 

and changing it to

id="mydropdown--value" 

so that it is the same, detailed, and predictable every time would be ideal for testing. There’s more than 15 dropdowns on one page and without an intuitive id, I need to either change my Selenium method, or the developers need to add better ids to the application. We want our Selenium tests to run in a pipeline using TestNG, and that will never work until this is resolved. Going with changing the react inputId’s seems more Configuration Management(CM) friendly anyway to me. All those inputs should be managed through CM.

I just started with react, and it’s not the most intuitive to me, yet…

Advertisement

Answer

I found a solution on my own, inputId is the key to make a unique id and to remove that react-select ugly. Here is an example….

import React from 'react';
import Select from 'react-select';

const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
];

export class Counter extends React.Component {
state = {
    selectedOption: null,
}
handleChange = (selectedOption) => {
    this.setState({ selectedOption });
    console.log(`Option selected:`, selectedOption);
}
render() {
    const { selectedOption } = this.state;

    return (
        <Select
            value={selectedOption}
            inputId="mydropdown"
            onChange={this.handleChange}
            options={options}
        />


    );
}
}

After an inputId is statically defined, my Selenium method seems to work better.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement