Require help in identifying element in testcafe - testing

I am new to automation testing and coding. I am using testcafe in one of my project to automate the functional testing.
In one of the webpage there is a field which only accept numeric values and gives error message if any alphanumeric values are entered.
As a part of my validation I need to capture this error message.
Issue which I am facing here is I am not able to determine which element it is in DOM.
For example gmail user name can be considered for this and error message that we get while we try to enter invalid user message.
This is how the DOM looks like for the field
<div class="flex-content space-100 space-large-reset ">
<label for="uid">Unique ID Number</label>
<input type="password" id="uid" maxlength="9" value="123js" class="abyss-textinput abyss-form-invalid">
<div class="abyss-error-message">Please enter a valid Unique ID Number.</div></div>
Value ="123js" is the incorrect value which i entered which generated error message mentioned in next line.
Thanks in advance.

Firstly, I'll confess I'm no authority on testcafe, just learning myself.
That being said I've assertions which work as follows:
await t.expect(Selector('h2').withText('Some text').exists).ok();
In you case if there's no id/class you can use to narrow the search it could be fairly inefficient (there are likely a lot of divs/spans in your app). Could you provide some info about the dom used to display the errors ?

As a #Iain_b said, you can use a Selector and the ok() assertion to check presence of the error message. You can use Adjacent sibling combinator to select the error's <div> tag. However the element can be inserted into the DOM tree after validation is failed, or be there since page loading and just become visible after validation is failed.
So for the first case you should use something like:
await t.expect(Selector('#uid + .abyss-error-message').withText('Please enter a valid Unique ID Number').exists).notOk();
await t.typeText('#uid', '#$dfgh');
await t.expect(Selector('#uid + .abyss-error-message').withText('Please enter a valid Unique ID Number').exists).notOk();
and for the second:
await t.expect(Selector('#uid + .abyss-error-message').withText('Please enter a valid Unique ID Number').visible).notOk();
await t.typeText('#uid', '#$dfgh');
await t.expect(Selector('#uid + .abyss-error-message').withText('Please enter a valid Unique ID Number').visible).notOk();

Thanks for the help guys..
I was able to find the element using below mentioned condition
Selector ('.abyss-error-message').withText('Please enter a valid UID')

Related

What can i use to interact with the search bar on this website using cypress

I am trying to complete a test case that involved opening propertypal.com, entering some values and validating the responses using the software cypress. I've never used cypress before but the company asking me to do this test want me to utilise it.
This is the website i'm testing https://www.propertypal.com/
I want to type bt6 into that text box, but I cant work out the correct locator to use. Everything I try either returns multiple elements or doesn't find anything.
Below are some of the things I tried with no success. The main things I have been honing in on are the placeholder text, the ID and element name.
I'm very new to this type of automation so any help would be amazing.
cy.get('query').type('bt6')
cy.get('input:first').should('have.attr', 'placeholder', 'Search Area, Address, Agent').click()
cy.get('search-form-textbox').type('bt6')
With this element
<input id="query"
type="text"
name="q"
class="search-form-textbox"
autocorrect="off"
spellcheck="false"
value=""
placeholder="Search Area, Address, Agent">
Using the id="query" should be best,
cy.get('input#query') // should only be one id "query" on the page
.type('bt6');
If there's multiple id's "query" and you want to flag it,
cy.get('input#query')
.then($els => {
expect($els.length).to.eq(1) // assert there's only one id found, otherwise fail
})
.type('bt6');
If there's multiple id's "query" and you don't really care, you can select the third which is the visible one.
cy.get('input#query')
.eq(2) // take the third, which is at center of the page
.type('bt6');
Taking the "nth" element found is always a bit fragile, but placeholder text is pretty good instead (provided the page isn't multi-lingual)
cy.get('input[placeholder="Search Area, Address, Agent"]') // easier with attribute in selector
.eq(1) // take the second, as the are two of these
.type('bt6');
Class is not so good, as can often be applied to multiple elements, but in this case it's pretty good because it's specific to the role,
cy.get('input.search-form-textbox') // prefix class with "."
.eq(2) // take the third, which is at center of the page
.type('bt6')
Web pages can often have multiple elements with the same selector, for example cy.get('input#query') has three elements with this id.
What happens is the developer creates a component, adds an id like <input id="query"> then adds the component in several places, so the page actually ends up with multiple ids of the same name.
When the page is complex with hidden sections, to find the element you want start by testing with a console.log
cy.get('input#query') // finds 3 elements
.then(console.log) // log them to dev tools
Open dev tools, click open the object printed and you can see the list of elements selected.
Now you can hover each element, and the corresponding element on the page is highlighted.
In this case the first two are hidden behind menu items, but the third is the one we need.
So now we can add an .eq(2) to select the third element
cy.get('input#query') // finds 3 elements
.eq(2) // take the third element
.type('bt6');
So when I ran the cypress Test for your website, I got an uncaught exception that is originating from your Application. This is something that should be analyzed and is possibly fixed.
If this is something that is not going to be fixed, then you can add the below in your test, so that cypress ignores the exception and doesn't throw an error.
Cypress.on('uncaught:exception', (err, runnable) => {
return false
})
Now I tried using the locator id(#query) to input the test, as it is always good to use id because it's unique, but unfortunately, it gave me an error as the element is not visible. Unfortunately adding {force: true} also didn't help me solve the issue.
cy.get('#query').type('bt6')
1.So, the locator that worked for me was .search-ctrl. So your Final Test will look like this:
cy.visit('https://www.propertypal.com/')
Cypress.on('uncaught:exception', (err, runnable) => {
return false
})
cy.get('.search-ctrl').type('bt6')
2.Now, if you want to globally handle the exception, then go to cypress/support/index.js and then write there:
Cypress.on('uncaught:exception', (err, runnable) => {
return false
})
And then in this case your test will just have:
cy.visit('https://www.propertypal.com/')
cy.get('.search-ctrl').type('bt6')

Validating form data that uses a selector with Selenium

I am attempting to automate checking the values of a form. I figured out how to check the values submitted via send_keys, but anything submitted via a selector is giving me trouble. I'm a n00b when it comes to automation.
This works:
driver.find_element_by_xpath("//*[#name='CurrentAddress.LineOne'][#value='123 Something Lane']")
This does not:
driver.find_element_by_xpath("//*[#name='CurrentAddress.StateAbbrev'][#value='TX']")
The code that governs the CurrentAddress.StateAbbrev is
<select class="form-control" data-val="true" data-val-required="* State is required" id="CurrentAddress_StateAbbrev" name="CurrentAddress.StateAbbrev"><option value=""></option>
When I try to validate the State, I get this:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[#name='CurrentAddress.StateAbbrev'][#value='TX']"}
The form value stores the input as 'TX' but the page shows the State as 'TEXAS'. I've tried looking for either, but it still cannot locate the element. Attempting to locate it via either #name or #id doesn't change the outcome.
I haven't tested this code, but it should work.
//Rather than creating the object of WebElement create object of Select
Select stateDropdown = new Select(driver.findElement(By.xpath("//select[#class='form-control']"));
//To select by visible text, pass the text
stateDropdown.selectByVisibleText("");
//Get text of first selected option
String selectedValue = stateDropdown.getFirstSelectedOption().getText();
This ended up working for me:
driver.find_element_by_xpath("//*[#class='form-control']/option[text()='TEXAS']")

How to find value of email field using Selenium2Library

I am writing regression tests for a web application using robot framework and the Selenium2Library library. I have a simple test which changes all of the fields of an "account settings" type form (think username, password, email, etc.), then revisits the page and makes sure all of the data was saved. Like so:
*** Test Cases ***
Sample Test
Change All Account Details
New Account Details Should Be Saved
*** Keywords ***
Change All Account Details
Navigate to Account Page
Input Text accountSettingFrom_firstname Test
Input Text accountSettingFrom_lastname Dummy
Input Text accountSettingFrom_email new_email#example.com
# etc etc, eventually save the form
New Account Details Should Be Saved
Go To ${ACCOUNT_URL}
Textfield Value Should Be accountSettingFrom_firstname Test
Textfield Value Should Be accountSettingFrom_lastname Dummy
Textfield Value Should Be accountSettingFrom_email new_email#example.com
I get the following error on the final step (Textfield Value Should Be accountSettingFrom_email new_email#example.com) when running this test: Value of text field 'accountSettingFrom_email' should have been 'new_email#example.com' but was 'None'
I have taken screenshots the moment before that step runs, and I have added a pause and manually confirmed that the value attribute of 'accountSettingFrom_email' is indeed 'new_email#example.com'. HTML of the element at time the check occurs:
<input type="email" name="accountSettingFrom[email]" value="new_email#example.com" class="foo bar" required="required" tabindex="3" maxlength="128" url="/foo/bar" userid="foobar" id="accountSettingFrom_email">
You'll notice that the first two Textfield Value Should Be keywords pass. The only difference I can discern between the three elements is that 'accountSettingFrom_email' is type="email" instead of type="text", but if the the keyword is successfully locating the element, then why can't it grab the value of the value attribute?
So am I doing something wrong? I feel like this or some similar keyword must exist to test this, without having to resort to writing a custom library.
You have hit some bugs in Selenium2Library. When Selenium2Library was created, HTML5 was not ratified. Internally the library is filtering out your element because it has a type other than 'text' (made sense before HTML5). Textfield Value Should Be can only find your element if it has tag name input and attribute value 'text' for type.
See https://github.com/robotframework/Selenium2Library/issues/546
Also due to how Textfield Value Should Be is implemented, the error you are getting makes you think the element was found when in fact it was not because it was filtered out.
See https://github.com/robotframework/Selenium2Library/issues/547
In contrast, Input Text and Input Password have never filtered on element tag or attribute.
I would try Get Element Attribute instead to get the attribute named value instead. According to the API it should be
accountSettingFrom_email#value

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.

How to create Test cases in Automation tool TestComplete

How can I create test cases according to my requirement.
Example:
I have a form with many fields. There is one field name Father's Name, now I want that the user should insert only string in this field, no numeric values should be accepted.
I wanna carry out such cases and do testing using the tool. How can I do this in TestComplete?
So, you want to validate that the tested application correctly handles the situation when forbidden characters are entered in the field, right? If so, then the exact solution depends on what the application does when a forbidden character is entered:
1) The app shows an error box. In this case, make your test enter a forbidden char and check for the error box existence using the appropriate Wait* method (WaitWindow, WaitNamedChild, etc.). Short example from the top of my head (did not run the code):
var TextToEnter="First 123Name";
EditBox.Keys(TextToEnter);
// As a rule, validationg is performed when the focus changes
EditBox.Keys("[Tab]");
var ErrorBox = MainWnd.WaitNamedChild("wndErrorDlg", 5000);
if (ErrorBox.Exists)
Log.Message("Succeeded - the error box is shown");
else
Log.Error("Failed - no error box detected");
2) The app does not show any error, but just ignores the forbidden chars making them not to appear in the edit box. In this case, just compare the actual text against the expected text. Something like this:
var TextToEnter="First 123Name";
var TextToExpect="First Name";
EditBox.Keys(TextToEnter);
if (EditBox.wText == TextToExpect)
Log.Message("Succeeded");
else
Log.Error("Failed");
I hope this helps.