Unable to locate Xpath for dynamic text - java

I'm writing some Selenium UI automation tests and I'm currently working on a section where multiple validation messages can appear depending on the response from source system. I have several different messages to trigger.
Every time the error message is shown on the UI it will sit in the following element but the text string changes each time depending on what the message is while the id and class remain the same:
<span id="lblErrorText" class="validationError">
"My error message will appear here"
</span>
In my page object class I am defining my fields before I use them in a method. So I have the following:
By errorMessage = By.xpath("//span[#class='validationError']");
I then use errorMessage in a method to return it as a boolean to enable me to assert against. As follows:
public boolean getInvalidRefNumberErrorMessage(){
return driver.findElements(errorMessage).contains("My error message will");
}
But every time I run my test I see that method getInvalidRefNumberErrorMessage is returning a FALSE.
I've tried using the id instead but no luck. I've never had to validate a dynamic message before so I'm a bit stuck here.

Seems your code has some wrong places if they are not copy/paste mistake.
Should use findElement, not findElements which return a List.
Should call getText() to return the message content as String, then call String.contains()
public boolean getInvalidRefNumberErrorMessage(){
return driver.findElement(errorMessage).getText()
.contains("My error message will");
}

Related

Wicket IFormValidator - Mark multiple FormComponents as invalid

I have an IFormValidator that checks if the values of multiple FormComponents are coherent.
Now if validation fails, I'd like to highlight all related FormComponents and respective HTML label tags, just like it happens with Validators, that are responsible for only a single FormComponent (e.g. StringValidator).
My first try was calling FormComponent#invalid() on all related FormComponents, but that doesn't seem to do the trick, since it just calls FormComponent#onInvalid(), which does nothing by default.
The second thing I tried was calling FormComponent#error(String) on each component but that of course generates an additional error message for each FormComponent, which is not the desired behaviour. But at least it does highlight the individual invalid FormComponents.
What would be the correct way to do this? Is there a simple way I'm overlooking, since the IFormValidator#getDependentFormComponents() method, which I'm supposed to implement, already tells the Validator, which FormComponents will be invalid as a result failing the validation?
Here is a stripped down example of what I tried with Wicket 8.3:
wicketForm.add(new IFormValidator() {
#Override
public FormComponent<?>[] getDependentFormComponents() {
return new FormComponent<?>[] {formComponent1, formComponent2, formComponent3};
}
#Override
public void validate(Form<?> form) {
if (/*values of formComponent1-3 are not coherent*/) {
form.error("<error message>");
/* No highlighting at all */
formComponent1.invalid();
formComponent2.invalid();
formComponent3.invalid();
/* Highlighting works, but obviously produces same error message multiple times */
formComponent1.error("<error message>");
formComponent2.error("<error message>");
formComponent3.error("<error message>");
}
}
}
);
A FormComponent is deemed as invalid only when its #error() methods are called - see org.apache.wicket.markup.html.form.FormComponent#isValid().
If you want to show only the error feedback message of the Form then you need to instantiate your FeedbackPanel as:
new FencedFeedbackPanel("id", new ComponentFeedbackMessageFilter(form));
This way it will render the feedback messages only of the Form.
You can use the feedback messages of the form components to show their specific errors next to the respective HTML form element (input, select, etc.)

isDisplayed always returns false for the specific element

I'm using Selenium to check if error message shown when user sent form with empty fields. Error message block is attached to the DOM all the time, but when there is no errors it has "display: none;" style attribute. So, when I push the "save" button, I check if this block visible this way:
Assert.assertTrue("There is no validation error!", driver.findElement(By.id("validationModal")).isDisplayed());
And this works. But when I'm trying to check that messages in this block are showed, isDisplayed method always returns "false". When I use just this:
driver.findElement(By.id("validationModal")).findElement(By.tagName("ul"))
.findElement(By.xpath("//*[contains(text(),'Empty app name field')]"));
it goes fine, but it's wrong because it wouldn't throw an exception when this text will be not visible, but will be in page code. If I write this:
Assert.assertTrue(driver.findElement(By.id("validationModal")).findElement(By.tagName("ul"))
.findElement(By.xpath("//*[contains(text(),'Empty app name field')]")).isDisplayed());
it always fails. And I don't really understand why and how I can check, that text of error message is shown, right way.
UPD:
I've found the source of problem. This string finds not element inside "validationModal" block, but inside tag, which contains text we have to find.
driver.findElement(By.id("validationModal")).findElement(By.tagName("ul"))
.findElement(By.xpath("//*[contains(text(),'Empty app name field')]")).isDisplayed()
But I still not understand why it happens, because I specify the element where it should be searched for.
It seems that you are trying to interact with some modal frame.
Generally to interact with modal element you should change driver context first.
driver.switchTo().frame("ModelFrameTitle");
or
driver.switchTo().activeElement()
Find or check elements and then come back to main frame
driver.switchTo().defaultContent()
Try this :
Assert.assertTrue("Element is not displayed",driver.findElement(By.xpath("//*[contains(text(),'Empty app name field')]")).isDisplayed());
There was an error in xpath.
Wrong string was:
findElement(By.xpath("//*[contains(text(),'Empty app name field')]"))
And right is:
findElement(By.xpath("//li[contains(text(),'Empty app name field')]"))

Selenium WebDriver -- How can I know a certain line has executed successfully?

I am testing a web application and my sample test case has three steps:
Enter Username
Enter Password
Click 'Login'
driver.findElement(By.id("username")).sendKeys(username);
driver.findElement(By.id("password")).sendKeys(password);
driver.findElement(By.id("LoginButton")).click();
I need to generate a report which specifies which steps passed and which failed. Is there some mechanism by which I can know that each of those lines executed successfully? Does Selenium have some kind of inbuilt Activity/Event Listener?
If you want log all basic steps like click, navigate, on find element, etc
I recommend you add some event listener. You can use the class EventFiringWebDriver.
An example:
EventFiringWebDriver events = new EventFiringWebDriver(this._driver);
events.Navigated += new EventHandler<WebDriverNavigationEventArgs>(eventAfterNavigate);
and you can define the event handler as
private void eventAfterNavigate(object sender, WebDriverNavigationEventArgs e)
{
Log("URL visited: " + e.Driver.Url); // Call to your favourite log method
}
You can find more possible event handlers in the Webdriver API reference: http://selenium.googlecode.com/svn/trunk/docs/api/dotnet/html/AllMembers_T_OpenQA_Selenium_Support_Events_EventFiringWebDriver.htm
You may use either Verify or Assert to be sure that something is present or absent on the page. Verify will return you Boolean and continue running while Assert on false will stop you test(s).
In this particular case you may verify that you typed username into element with id=username. So your code could look like this:
driver.findElement(By.id("username")).sendKeys(username); // this will enter username
assertEquals(selenium.getValue("id=username"), username); // this will check that text in your username field is 'username' (also you may use Assert.IsTrue)
As far as I know there is verifyTextPresent in Selenium 2 Webdriver, so you may use this:
try
{
assertEquals(selenium.getValue("id=username"), username); // put message into your log: success
}
catch (Exception)
{
// put message into your log: failed
}
I suggest to verify Button click but waiting for some notification that you logged in: e.g. text "Hello, {username}" might appear, or new element (absent before log in) might appear as well. So if this element is present - you are definitely logged in.
If you want to see if each step is successful, then I put some asserts (depending on your unit testing framework) to verify that the steps succeeded.
For example, to check that the username field actually received input, you could immediately verify that the username field has the text of whatever the username is that was typed in.
Some pseudo code:
IWebElement element = driver.findElement(By.id("username"));
element.sendKeys(username);
assertsEquals(username, element.text);
Likewise, to verify that a click was successful, you could check and assert that an element that is expected on the next page exists, which would then indicate that the login was successful.
If Selenium dose not throw Exception then lines are executed successfully.
But question is how do you define success? I would check site that was loaded after click on LoginButton to be sure that behavior of web application is like you expect.

Struts 1.1: ActionErrors between different Actions

I have a form (form.jsp) and a connected FormAction ActionA. ActionA does validations and stores ActionErrors and the form.jsp will print them using <html:errors../> tag.
All this is working fine.
I then wanted to add some on-the-fly server side validation on onblur event on one of the form fields (fieldA). I do this using jQuery's $.post. It goes to a different Action class (ActionB) which will return a value, that I can print in a div under fieldA. This also works fine.
The problem is to combine the two. I use saveErrors method in ActionA and need to reset it with the new errors I get in ActionB.
Example: If fieldA was value "A" and fieldB was "#$" and my ActionA returned errors "No capitals for fieldA" and "No symbols for fieldB" on pressing Submit, then when user changes fieldA to "123" and presses tab, the errors shown should be "No numbers for fieldA" and "No symbols for fieldB" i.e. first error gets removed.
But how do I access the errors, if it isn't in the request!
Ok I worked it out. I just used jQuery to make the entire div with the error (class="globalError") not show (display:none) and then added my new errors in a similar div under that.. so, it just looks like the errors section changes :-). Thanks for the help.

selenium web driver test web element has been updated

How would you go about checking to see if a particular WebElement has been updated?
I have a test that performs a form save and then the UI returns a success/error message.
I am doing a series of saves and I need to test and see if the message is what is expected.
Selenium goes so fast that the browser does not have a chance to catch up.
This is the code that I have for testing for an error message (There is an equivalent success message function as well)
public void assertErrorMessage(String errorMsg) {
// set the wait time a bit so the page can load.
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
List<WebElement> results = driver.findElements(By.xpath("//div[#id='lift__noticesContainer__']/descendant::*"));
boolean success = false;
String message = "";
for (WebElement result : results) {
String id = result.getAttribute("id");
if (id.contains("___error")) {
success = true;
}
if (result.getTagName().equals("li")) {
message += result.getText().trim();
}
}
Assert.assertTrue(success, "No error message generated");
Assert.assertTrue(message.equals(errorMsg), "Expecting message: \"" + errorMsg + "\" but got \"" + message + "\"");
}
As this is written, this looks for the presence of a particular <div> and checks to see if contains certain attributes. If it does, get the message.
The thing is, this will always be true and hence my tests are failing since the message is different than the previous one, but the UI hasn't caught up to where selenium is.
My solution so far to force a Thread.sleep(2000) to just pause a bit to allow for the UI to catch up. I know that it is frowned upon to use Thread.sleep().
i.e. (pseudo-code)
page.setField("value");
page.save();
Thread.sleep(2000);
page.assertErrorMessage("Error message");
Is there any way let me check to see if a WebElement has been updated? If so, I could use the Selenium waits to test for that.
Or perhaps someone else has a suggestion for how to do this?
Thanks in advance.
If the result displayed keeps getting every time you perform page.save().
The best way to make sure that your code waits for the browser to update the message is by using the WebDriverWait object.
A simple example would be -
new WebDriverWait(driver, 10).until(ExpectedConditions.textToBePresentInElement(By.xpath("xpath"), "message"));
You can check if that particular element has the message you are looking for. If that message is not present even after 10 seconds then a TimedOutException will be thrown.
You can check out more variations on the ExpectedConditions as suitable in your situation. Hope this helps you.

Categories