简体   繁体   中英

selenium - generic function to enter test data in webpage using nested linkedhashmap - how to handle radio buttons

I am using Selenium with Java in POM based hybrid framework. I am trying to develop a generic function to enter data in the webpage. The function accepts a linkedhashmap with key(weblement) and value (testdata to enter) pairs. It works properly so far. But I am stuck at how to handle radio buttons. Radio buttons are List of Web elements and I do not know how to pass them to this generic function.

for ex if my radio button has following dom:

<div class='radio'>
  <label>
  <input type='radio' name='hosting' value='yes'> "Yes"
  </label>
</div>
<div class='radio'>
  <label>
  <input type='radio' name='hosting' value='no'> "No"
  </label>
</div>

In normal circumstances, I would create a List of WebElements, iterate through them and perform actions on them. But since I am writing a generic function which accepts a LinkedHashMap how do I pass this list of WebElements to it? when we create map, key is always unique. Here key will be repeated for a set of objects with different values.

following is the code of my generic function.

package seleniumeasy.qa.Util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
import org.testng.ITestContext;
import org.testng.Reporter;
import org.testng.annotations.DataProvider;

import io.qameta.allure.Allure;
import seleniumeasy.qa.Base.Base;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class commonUtil extends Base {
    
    public static String sConfigPath = "\\src\\main\\java\\seleniumeasy\\qa\\Config\\config.properties";
    public static String sScreenShotFolderPath = "\\Screenshots";
    
    public static int iImplicitWait = 30;
    
    
    public static void EnterData(LinkedHashMap<WebElement, String> sEnterDataList)
    {
        //Map<String,String> sData = nsew HashMap<String,String>();
        
        for(Entry<WebElement, String> element:sEnterDataList.entrySet())
        {
            System.out.println("Element key is: " + element.getKey().toString());
            if(element.getKey().toString().contains("Select"))
            {
                Select comboSelect = new Select(element.getKey());
                comboSelect.selectByVisibleText(element.getValue());
            }
            if(element.getKey().toString().contains("radio"))
            {
                Select comboSelect = new Select(element.getKey());
                comboSelect.selectByVisibleText(element.getValue());
            }
            else
            {
                element.getKey().sendKeys(element.getValue());
            }
        }
        
    }


}

Following is the code in my Page class where I am calling my EnterData function.

package seleniumeasy.qa.Page;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.Select;

import io.qameta.allure.Allure;
import io.qameta.allure.Step;
import seleniumeasy.qa.Base.Base;

public class InputFormValidationPage extends Base
{
    @FindBy(name="first_name")
    static WebElement txtFirstName;
    
    @FindBy(name="last_name")
    static WebElement txtLastName;
    
    @FindBy(name="email")
    static WebElement txtEmail;
    
    @FindBy(name="phone")
    static WebElement txtPhone;
    
    @FindBy(name="address")
    static WebElement txtAddress;
    
    @FindBy(name="city")
    static WebElement txtCity;
    
    @FindBy(css="Select[name='state']")
    static WebElement comboSelect;
    
    @FindBy(name="zip")
    static WebElement txtZip;
    
    @FindBy(name="website")
    static WebElement txtWebsite;
    
    @FindBy(css="input[type='radio']")
    static List<WebElement> selectHosting;

    @FindBy(name="comment")
    static WebElement txtComment;

    @FindBy(css="button[type='submit']")
    static WebElement btnSubmit;
    
    public InputFormValidationPage()
    {
        PageFactory.initElements(driver, this);
    }
    
    @Step("Insert data")
    public void submitInputForm(String sTestCaseNo,String sFirstName,String sLastName,String sEmail,String sPhone,String sAddress,String sCity,String sState,String sZip,String sWebsite,String sHosting,String sComment)
    {
        
        Map<WebElement,String> sEnterDataList = new LinkedHashMap<WebElement,String>();
                
        
        /*txtFirstName.sendKeys(sFirstName);
        txtLastName.sendKeys(sLastName);
        txtEmail.sendKeys(sEmail);
        txtPhone.sendKeys(sPhone);
        txtAddress.sendKeys(sAddress);
        txtCity.sendKeys(sCity);*/
        
        //System.out.println("The type of State Combo is: " + comboSelect.getAttribute("type"));
        //Select sComboSelect = new Select(driver.findElement(By.cssSelector("Select[name='state']")));
        
        /*sComboSelect.selectByVisibleText(sState);
        //comboState.selectByVisibleText(sState);
        txtZip.sendKeys(sZip);;
        txtWebsite.sendKeys(sWebsite);;
        for(WebElement element:selectHosting)
        {
            if(element.getText().equalsIgnoreCase(sHosting))
                if(!element.isSelected())
                    element.click();
        }
        txtComment.sendKeys(sComment);;
        Allure.step("Click Submit After Adding Data");
        btnSubmit.click();
        
        */

        sEnterDataList.put(txtFirstName, sFirstName);
        sEnterDataList.put(txtLastName, sLastName);
        sEnterDataList.put(txtEmail, sEmail);
        sEnterDataList.put(txtPhone, sPhone);
        sEnterDataList.put(txtAddress, sAddress);
        sEnterDataList.put(txtCity, sCity);
        sEnterDataList.put(comboSelect, sState);
        sEnterDataList.put(txtZip, sZip);
        sEnterDataList.put(txtWebsite, sWebsite);
        //sEnterDataList.put((WebElement) selectHosting, sHosting);
        //sEnterDataList.put((WebElement) selectHosting, sHosting);
        sEnterDataList.put(txtComment, sComment);
        sEnterDataList.put(btnSubmit, "");
        seleniumeasy.qa.Util.commonUtil.EnterData((LinkedHashMap<WebElement, String>) sEnterDataList);
    }
}

Here is my test page which uses DataProvider to connect to my excel database and fetch records which are then passed as testdata to my Page class.

package seleniumeasy.test.Tests;

import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;

import io.qameta.allure.Allure;
import io.qameta.allure.Description;
import junit.framework.TestListener;
import seleniumeasy.qa.Base.Base;
import seleniumeasy.qa.Page.InputFormValidationPage;
import seleniumeasy.qa.Page.managePopupWindowPage;
import seleniumeasy.qa.Util.excelDataUtil;

//@Listeners(seleniumeasy.qa.Util.TestListener.class)
public class InputFormValidationTest extends Base{

    InputFormValidationPage obj;
    managePopupWindowPage mObj;
    
    @BeforeMethod
    public void setUP()
    {
        Init();
        
        mObj = new managePopupWindowPage();
        obj = mObj.clickInputFormSubmitMenu();      
    }
    @Description("Data Driven Test to insert new records - Excel")
    @Test(dataProvider="getInputData",description="Data driven test using excel to insert records in the system")
    public void validateInputForm(String sTestCaseNo,String sFirstName,String sLastName,String sEmail,String sPhone,String sAddress,String sCity,String sState,String sZip,String sWebsite,String sHosting,String sComment)
    {
        
        //System.out.println(sTestCaseNo + "-" + sFirstName + "-" + sLastName+ "-"+ sEmail+ "-" + sPhone+ "-" +sAddress + "-" +sCity + "-" + sState + "-" +  sZip + "-" +  sWebsite + "-" +  sHosting + "-" +  sComment);
        obj.submitInputForm(sTestCaseNo, sFirstName, sLastName, sEmail, sPhone, sAddress, sCity, sState, sZip, sWebsite, sHosting, sComment);
        Allure.step("Verification after insertion of record");
    }
    @AfterMethod
    public void tearDown()
    {
        driver.close();
        driver.quit();
    }
    
    @DataProvider
    public Object[][] getInputData()
    {
        Object data[][] = excelDataUtil.readExcelFile("InputFormValidationData");
        //System.out.println("Data inside data provider is as followes:");
        //System.out.println(data.toString());
        return data;
    }
    
    
}

Please note that as of now this is working fine as I commented on the code where radio button is added to the list. It works fine for textfield, textarea and combobox objects. I just do not know how do I handle radio button which will have common key but different values. Maps accepts only unique key.

Is it possible to send list of web elements as part of LinkedHashMap?

suggestions please

Instead of passing a LinkedHashMap of element values directly, I would rather pass a wrapper class that would encapsulate the LinkedHashMap so it could overload LinkedHashMap.put() method with List<WebElement> and WebElement parameters. This would, in general, allow you to have a more robust code with easy adjustments for each WebElement types.

The void put(WebElement webElement, String value) method would directly save the values while the void put(List<WebElement> webElements, String value) method would (in case of radio elements) save only the WebElement which contains the given String value.

Example:

class FormData {

    private Map<WebElement, String> map;

    public FormData() {
        this.map = new LinkedHashMap<WebElement, String>();
    }
    
    public FormData(final LinkedHashMap<WebElement, String> map) {
        this.map = map;
    }
    
    public void put(final WebElement webElement, final String value) {
        this.map.put(webElement, value);
    }
    
    public void put(final List<WebElement> webElements, final String value) throws Exception {
        /* You might want to restrict this block of code to only radio buttons */
        WebElement element = this.map
                                 .stream()
                                 .filter((key, val) -> value.equals(val))
                                 .findFirst()
                                 .orElseThrow(new Exception("Radio with value: " + value + " not found!"));
        this.put(element, value);
    }
    
    // getters and setters omitted

}

And then in your submitInputForm method:

FormData sEnterDataList = new FormData();
// ...
sEnterDataList.put(selectHosting, sHosting);
seleniumeasy.qa.Util.commonUtil.EnterData(sEnterDataList);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM