fillField method in codeception not working throwing DOMXPath::query(): Invalid expression - codeception

$I->fillField("username", "test");
On running the acceptance test, get the following error:
Sorry, I couldn't fill field "username","test":
ErrorException: DOMXPath::query(): Invalid expression
the input element is inside a form. I tried adding id to the input and also accessing the element using inpu..but all returned the same error. "see" method is working..but not fillField or seeInField.

You have to tell codeception what element it's looking for.
if username is an id do:
$I->fillField("#username", "test");
and if a class do:
$I->fillField(".username", "test");
or enter the xpath of the element: (eg. search field on google.com)
$I->fillfield('//*[#id="gbqfq"]','my search text test');

Related

Protractor get the second element of an ocurrence

I have an issue and I'm quite new with protractor.
I need to get an element by its text, right now it is not possible to change how the UI is built to use better selectors.
So what I have right now is a span tag with the text Summary inside of it, to retrieve the element using XPath I do the following:
const myElement = element(by.xpath("//span[text()='Summary']"));
That works for the first occurrence when there's only one element on the screen, however, when there are two elements, it fails with the following error:
Failed: element not interactable
Possibly because it is trying to access the first element which is toggled.
So I tried accessing the element index as I read around with:
element(by.xpath("//span[text()='Summary']")[1]);
And got the following error:
Failed: Invalid locator
I read somewhere that the values start on 1 and not on 0 so I tried with:
element(by.xpath("//span[text()='Summary']")[2]);
Yet, I'm still getting the same error:
Failed: Invalid locator
Is there a way I can get to these second element?
When you are using list slicing then there exist more then one elements. So you can try to use elements instead of element
element(by.xpath("(//span[text()='Summary'])[2]");
OR
element(by.xpath("(//span[contains(text(),'Summary')])[2]");
You can try this XPath, it has additional brackets, you have been almost there.
(//span[text()='Summary'])[2]
Reference:
XPath query to get nth instance of an element

behat fillField xpath giving error?

This line of code:
$this->fillField('xpath','//fieldset[#id="address-container"]/input[#name="address_add[0][city]"]', "Toronto");
Is giving me this error
Form field with id|name|label|value|placeholder "xpath" not found. (Behat\Mink\Exception\ElementNotFoundException)
The reason I want to use xpath in my fillField is because there are actually multiple input[#name="address_add[0][city]"] in my html document. I figure an xpath will let me target specifically the field I want to populate.
What's the best way to fill out just the input[#name="address_add[0][city]"] that is a descendant of fieldset[#id="address-container"] ?
You are not using the method in the wright way.
As i see here xpath is taken as selector.
The method expects 2 parameters:
identifier - value of one of attributes 'id|name|label|value'
value - the string you need to set as value
If you want to use css|xpath then you need to use find method first.
For example:
$this->find('xpath', 'your_selector')->setValue('your_string');
Please note that find might return null and using setValue will result in a fatal exception.
You should have something like this:
$field = find('xpath', 'your_selector');
if ($field === null) {
// throw exception
}
$field->setValue('your_string');
Also your selector could be written as:
#address-container input[name*=city] - this with css
or
//fieldset[#id="address-container"]//input[contains(#name, 'city')] - this with xpath
Make sure you take advantage of your IDE editor when you have any doubts using a method and you should find a php doc with what parameters are expected and what the method will return.
If you are using css/xpath a lot you could override find method to detect automatically the type of selector and to use it like $this->find($selector);
Also you could define another method to wait for the element and to handle the exception in one place, for example waitForElement($selector) that could contain a conditional wait up to 10 seconds and that throws exception if not found.

Getting org.openqa.selenium.InvalidSelectorException only for Chrome

I am tring to find a button in a webpage using find elements, the page can contain one of the below button ID's.
driver.findElements(By.xpath("//*[contains(#id,'topBtn')]"))
driver.findElements(By.xpath("//*[contains(#id,'WSMplasticTop')]"))
driver.findElements(By.xpath("//*[contains(#id,'bottomApplyBtn')]"))
The above code is working as expected when i use the Firefox Driver, where as getting the below error when i run in Chrome Driver.
org.openqa.selenium.InvalidSelectorException: invalid selector: Unable to locate an element with the xpath expression //*[contains(#id='bottomApplyBtn')] because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//*[contains(#id='bottomApplyBtn')]' is not a valid XPath expression.
Just wanted to know whether i have done any mistake
Try to use
'//*[contains(#id,'bottomApplyBtn')]'
instead of
'//*[contains(#id='bottomApplyBtn')]'
When you are using contains method in your XPath expression, you basically are using an inbuilt method to find the element.
This method takes 2 parameters.
First the tag you in which you want to search.
Second is the actual text value which you are looking for inside the above tag.
Basically you have to call the method with 2 parameters and that 2 parameters should be comma separated.
So //*[contains(#id='bottomApplyBtn')] is wrong you should instead remove this = sign.
//*[contains(#id, 'bottomApplyBtn')]
|_______|____________________ Parameter 1
|__________________________________Parameter 2
Hope it helps!

Need help regarding Run Keyword if xpath matches and then click element

I am trying to validate xpath expression and if it is true click element .Following is the code that I am trying to do .
Xpath_combined variable returns Boolean : true . Please help me in correcting the syntax or valid expression
Variable
${xpath_combined} //div[text()='00:04:56:AC:41:F6'] AND //div[contains(text(),'Device-77')]
Keyword
Run keyword if ${xpath_combined} == "true" Click Element //i[#class='fa fa-lg fa-file-text-o grow']
Error from console output
Evaluating expression '//div\[text()='00:04:56:AC:41:F6'\] AND //div\[contains(text(),'Gambit-77')\] == "true"' failed: SyntaxError: invalid syntax (<string>, line 1)]
You can create different scenarios how to solve this question. But, you can try this solution:
Xpath = With xpath, find the the parent element which contains both elements. But this depends on your code structure f.e. Try to find body element, with two child elements containing specific text conditions:
xpath=//body[//div[text()='00:04:56:AC:41:F6'] AND //div[contains(text(),'Device-77')]]
Set variable the right way or use scalar. Note: we will use Get Matching Xpath Keyword, so we don't need to use 'xpath=' prefix
${xpath_combined}= Set Variable //body[//div[text()='00:04:56:AC:41:F6'] AND //div[contains(text(),'Device-77')]]
Get Matching Xpath Count It will return 1 occurence of xpath. There is only one body element which passes the xpath expression
${count}= Get Matching Xpath Count ${xpath_combined}
Run Keyword If If the xpath count is exactly 1 time, the elements are present on the page and you are allowed to click on icon. Note: don't forget to add xpath= prefix to Click Element locator
Run keyword if ${count} == 1 Click Element xpath=//i[#class='fa fa-lg fa-file-text-o grow']
Though the other solution is fully viable one, here's an alternative which is an it more universal.
It combines two keywords - Get Webelement which returns a selenium object if it exists, and Run Keyword And Return Status - which returns True if a keyword succeeds, False otherwise:
${locator}= Set Variable //body[//div[text()='00:04:56:AC:41:F6'] AND //div[contains(text(),'Device-77')]]
${target}= Set Variable //i[#class='fa fa-lg fa-file-text-o grow']
${the element is present}= Run Keyword And Return Status Get Webelement ${locator}
Run Keyword If ${the element is present} Click Element ${target}
Another benefit is that you are not constrained by an xpath locator - it'll work with css, id or whatever other strategy.
Alternatively, one could use Element Should Be Visible instead of Get Webelement, but that works only for elements actuaĺly visible, not just present in the DOM.

WebDriverException Element must be user-editable in order to clear it

I am trying to run test cases to perform reset password and I am facing this issue.
WebDriverException Element must be user-editable in order to clear it.
Basically i am accessing the page for entering the new password and doing this:
browser.$("#newPassword").text("password");
where execution of the above line throws the error.
I had the same problem and it was because there was another element with the same id which was not an input field so it could not be cleared.
We can try the following:
WebElement.sendKeys(Keys.DELETE);
WebElement.sendKeys("Test");
It might be a case of using the wrong method for the input type.
In CodeCeption at least, fillField should be used on input elements and selectOption should be used on select elements and mixing them up will give invalid element state: Element must be user-editable in order to clear it.
I had this problem with a Primefaces autoComplete element. Primefaces 6.0 renders a span with the ID you pass, and within that an input with a "_input" appended to the ID. If you just use the ID you added in your source code, you tell Selenium to enter into the span (which fails with the "element must be user-editable" error). Add the "_input" to the ID if you select by ID in selenium.