I am trying to write functional tests for a Vue form that benefits from the FlatPickr date control. When I click on the element, it shows an additional element and from this the calendar appears. I'm struggling to select the input to activate the drop down.
<flat-pickr id="DateOfBirth" v-model="request.name.dateofbirth" :config="config" class="form-control" placeholder="Select date" name="date" size="sm" aria-label="Your date of birth">
</flat-pickr>
I don't really care what date is selected and so far I have tried this to just select the 3rd day/date but the calendar doesn't show:
var datePickr = webDriver.FindElement(By.XPath("//input[#placeholder='Select date']"));
var jsExecutor = (IJavaScriptExecutor)webDriver;
jsExecutor.ExecuteScript("arguments[0].setAttribute(arguments[1], arguments[2]);", datePickr, "readonly", "");
datePickr.Click();
var days = webDriver.FindElements(By.ClassName("flatpickr-day "));
days[3].Click();
The objective is to find the element, click it, select any date.
NB: if I try
var datePickr = webDriver.FindElement(By.Id("DateOfBirth"));
Then the expression fails as this element is hidden when rendered and something else triggers it (hidden by FlatPickr, not my code).
Any ideas? Thanks
Related
I am trying to make a selection in a dropdown using selenium.
The selectbox is not a html type of 'select' but is using angular so it is a 'mat-select' html-tag.
I simplified my code to get this to work but could not get it to work, this is my code right now:
var q = driver.FindElement(By.TagName("mat-select"));
new SelectElement(q).SelectByText("My List Value");
When I run this code I get:
Element should have been select but was mat-select
How do I solve this? I tried using SendKeys but since "My List Value" has spaces, the space triggers the selectbox to open or close and it won't select the correct value. Then I read about SelectByText but that seems to require a normal '' but I only have a ''.
Here is the html of the select:
<div class="mat-form-field-infix">
<mat-select _ngcontent-qpv-c46="" class="mat-select ng-tns-c12-118 ng-pristine ng-valid mat-select-empty ng-star-inserted ng-touched" role="listbox" id="mat-select-5" tabindex="0" aria-labelledby="mat-form-field-label-41" aria-required="false" aria-disabled="false" aria-invalid="false" aria-multiselectable="false">
<div class="mat-select-trigger" aria-hidden="true" cdk-overlay-origin="">
<div class="mat-select-value">
<!---->
<span class="mat-select-placeholder ng-tns-c12-118 ng-star-inserted"> </span>
<!---->
</div>
<div class="mat-select-arrow-wrapper">
<div class="mat-select-arrow"></div>
</div>
</div>
<!---->
</mat-select>
<span class="mat-form-field-label-wrapper">
<!---->
<label class="mat-form-field-label ng-tns-c24-117 mat-empty mat-form-field-empty ng-star-inserted" id="mat-form-field-label-41" for="mat-select-5" aria-owns="mat-select-5">
<!----><!---->
<mat-label _ngcontent-qpv-c46="" class="ng-star-inserted">Properties</mat-label>
<!----><!---->
</label>
</span>
</div>
All the options are missing in the html? I know c# but not angular so this looks a bit funny to me. Have not tried to click because I don't know how to find them when I can't even see them myself.
When I click on the select all items appear in some magical angular way...
The reason you got the error is because SelectElement() can only be used with an HTML SELECT element. The mat-select (and some other elements) may be formatted to look like a dropdown but they are not SELECT dropdown elements. Because of this, we aren't going to be able to use SelectElement() but there are ways around this.
The simplest way I've found is to find the mat-select element (typically by ID) and click it to open the dropdown. Then click the desired option using an XPath that contains the expected string. The code below shows this but the second locator is a guess because the HTML you provided didn't show the dropdown options. If you update the HTML to show this, I can update and test the locator but even if you don't, this should point you in the right direction.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.ElementToBeClickable(By.Id("mat-select-5"))).Click();
wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("//span[contains(text(),'My List Value')]"))).Click();
I added waits just to be safe. They may not be needed.
driver.FindElement(By.Id("mat-select-5")).Click();
driver.FindElement(By.XPath("//span[contains(text(),'My List Value')]")).Click();
I'm assuming you are going to use this more than once. In that case, I would write a method that takes in the desired option and selects it.
public void SelectProperty(string propertyName)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.ElementToBeClickable(By.Id("mat-select-5"))).Click();
wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath($"//span[contains(text(),'{propertyName}')]"))).Click();
}
and call it like...
SelectProperty("My List Value");
Selenium doesn't provide methods for interacting with mat-select. You need to write a custom program for Selenium to interact with a mat-select.
Here is an example of how to select a mat-select option with Selenium using C#:
IWebElement field = driver.FindElement(By.cssSelector('mat-select'));
// Click to open the dropdown.
field.Click();
// Query for options in the DOM. These exist outside of the mat-select component.
IReadOnlyList<WebElement> options = driver.FindElements(By.cssSelector("mat-option"));
// Find the option with the text that matches the one you are looking for.
options.First(element => element.GetText() == "My List Value")
// Click it to select it.
.Click();
You will probably want to wrap this up in a re-usable method of some sort.
How can i get element from below dropdwon, i have used Select command to select dropdowns, but here type is input.
<input class="tp-select-input" autocapitalize="none" autocorrect="off" autocomplete="off" spellcheck="false" data-testid="register-country" value="">
As dropdown you want to select value from is not a select type tag, Selenium Select method wont work on it. You have to follow below steps:
Click on Dropdown / or Arrow
Locate webelement you want to select from dropdown
Use java script executioner to click the option you want to select
Since you have not given complete HTML, below is the dummy code:
driver.FindElement(By.XPath("//input[#data-testid='register-country']")).Click() // Click on dropdown
IJavaScriptExecutor executor = (IJavaScriptExecutor)driver;
executor.ExecuteScript("arguments[0].click();", driver.FindElement(By.XPath("//*[text()='Austria']"))); //You can give more accurate xpath for country you want to select based on other HTML attributes
You can also try with below code
IWebElement element = driver.FindElement(By.ClassName("tp-select-input")); driver.FindElement(By.XPath("//span[text()='Australia']")); element.SendKeys(OpenQA.Selenium.Keys.Down); element.SendKeys(OpenQA.Selenium.Keys.Return);
The product which I am trying to automate has a customized combo box control from .Net.
The control is of type <input> and I will be able to type n search with the starting letter only.
When I try to access the <select> element using WebDriver , it says that the operation cannot be performed on an <input> field.
When i try to do a .Sendkeys on the iWebElement it will only be able to select values with starting text.
Is there any way to use WebDriver to select the combo box value using the whole text?
Sample DOM is in below format
<input name="icombobox_Text" tabIndex="7" title="Click to select theValue" class="ComboBox_Normal TxtBox_Css" id="icombobox_Text" accessKey="L" onkeydown="return C28.KeyDown();" onkeyup="return C28.KeyUp();" onkeypress="return C28.KeyPress();" onclick="$_('C28','TextClick')" onfocus="$_('C28','Focus')" onblur="$_('C28','Blur')" onselectstart="$_('C28','SelectStart')" onpaste="return false" oncontextmenu="return C28.KeyRightClick()" type="text" maxLength="255" maxSize="10" minSize="5" AUTOCOMPLETE="off"/>
There are 4 items in the combo..How to select a particular value.?
I got the answer.
Concept:
The Combo Control is having Text Box + List (Drop Down image).
So first find the element of the drop down image by clicking it.
Then use “SelectElement” Class to select the value from the list.
Sample Code:
IWebElement iWebelement = driver.FindElement(By.Id("combobox_Text")); //Getting the element of the Text Box
IWebElement iWebelementList = driver.FindElement(By.Id("combobox_List")); //Getting the elements of List/Drop down Box
SelectElement selected = new SelectElement(iWebelementList); //Parsing the list
iWebelement.SendKeys(Keys.ArrowDown); // Clicking the drop down image
selected.SelectByText("January"); // Use select element class to select the value
Use the following below code, to select an Option from Drop Down:
IWebElement iwe = Driver.FindElement(By.XPath("//li[contains(#class,'..item...') and contains(text(),'"+text+"')]"));
Thread.Sleep(500);
Actions action = new Actions(Driver);
Thread.Sleep(500);
action.MoveToElement(iwe).Click().Perform();
Following the code on Angular UI, I was able to integrate the Radio & Uncheckable Radio buttons into my solution. I have 2 radio buttons, both of which can be toggled and then I have an asp:Label to display the output.
I would prefer setting the label's visibility to false in the long run but for now it is visible.
By setting the asp:Label Text property to {{radioModel || 'null'}} I can see the value of the selected radio button on the client side page and viewing the page's source. Problem is, when I post back to the server, specifically attempting to store the value in a database, I only see the {{radioModel || 'null'}} declaration, rather than the value of my selection.
I'm new to Angular but the idea seemed pretty straight forward. I just need to figure out how to retain the label control value when storing to a database.
Here is my asp.net code with the angular declaration within the label.
<div ng-controller="EmployeeTypeChoiceRadios">
<div class="btn-group">
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Employee'">Employee</label>
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Contractor'">Contractor</label>
<!-- Pull Results from this label on form submit -->
<asp:Label ID="EmployeeTypeChoiceLabel" runat="server" Visible="false" Text="{{radioModel || 'null'}}" />
</div>
</div>
Here is how I have my JavaScript set up. I think this has more to do with the default radio selection however
// New Form - Employee Type Employee/Contractor - Radio Button
var EmployeeTypeChoiceRadios = function ($scope) {
$scope.radioModel = 'Employee';
$scope.checkModel = {
employee: true,
contractor: false
};
};
Finally, here is how I am collecting the label's data - Really just adding to a stored procedure parameter.
newformsqlCmd.Parameters.AddWithValue("#empEmpType", EmployeeTypeChoiceLabel.Text); // Employee Type choice
For the record, I've also tried basic HTML inputs (Labels) and to get their values like this..
BasicHtmlInputLabel.Value
I appreciate it in advance.
ngModel is only supported on the following elements:
input
text
checkbox
radio
number
email
url
date
dateTimeLocal
time
month
week
select
textarea
Using one of them instead of a label should solve the problem.
I'm using Selenium in C#, and I need to be able to specify which radio button on a website to click based on the text of the label that is associated with that radio button. I need to be able to pass that text in as a parameter. Here is a sample of what the code for the radio buttons looks like (this is for three buttons):
<input id="radSelect152_222_1369" class="bgRadioNotChecked" type="radio" onclick="BGQ.Ajax.SelectAnswer(this, '152','1369','3', '547');" value="1369" onfocus="BGQ.View.setLastElement(true);" name="radSelect152_222">
<label class="inline" for="radSelect152_222_1369">Watermelon</label>
<input id="radSelect152_222_1370" class="bgRadioNotChecked" type="radio" onclick="BGQ.Ajax.SelectAnswer(this, '152','1370','3', '547');" value="1370" onfocus="BGQ.View.setLastElement(true);" name="radSelect152_222">
<label class="inline" for="radSelect152_222_1370">Papaya</label>
<input id="radSelect152_222_1371" class="bgRadioNotChecked" type="radio" onclick="BGQ.Ajax.SelectAnswer(this, '152','1371','3', '547');" value="1371" onfocus="BGQ.View.setLastElement(true);" name="radSelect152_222">
<label class="inline" for="radSelect152_222_1371">Mango</label>
I want to be able to specify "Mango" in an Excel input file (I have all the file input stuff working fine) and have Selenium click the associated radio button. One approach that I read that I've been trying is to do the following:
Find the element that has the target text ("Mango") as its text
Get the FOR attribute from that element
Find the input that has an id equal to that FOR attribute
Click that input element.
Problem is, I'm pretty new to Selenium and can't quite figure the syntax for how to do these four steps. Can someone show me the way, with specific code examples? Also, or alternatively, is there a better/smarter way to do this? If so, please be specific.
I've included here the method I've started to write, in which I pass in the target text. I know it's wrong (especially in the By.XPath part).
public void ClickRadioButtonByLabelText(string labelText)
{
// (1) Find the element that has the label text as its text
IWebElement labelForButton = commondriver.FindElement(By.XPath(//label[text()='labelText']));
// (2) Get the FOR attribute from that element
string forAttribute
// (3) Find the input that has an id equal to that FOR attribute
// (4) Click that input element
}
Thanks.
You have two options.
Option 1 - do it all within a single XPath query
The XPath query would be:
//input[#id=//label[text()='TestCheckBox']/#for]
That is, get input that has an id which comes from the for attribute from a label that has the text of "TestCheckBox"
Option 2 - get the attribute from the label and then find the element in seperate steps
public void ClickRadioButtonByLabelText(string labelText)
{
// (1) Find the element that has the label text as its text
IWebElement labelForButton = commondriver.FindElement(By.XPath("//label[text()='labelText']"));
// (2) Get the FOR attribute from that element
string forAttribute = labelForButton.GetAttribute("for");
// (3) Find the input that has an id equal to that FOR attribute
IWebElement radioElement = commondriver.FindElement(By.Id(forAttribute));
// (4) Click that input element
radioElement.Click();
}