Watin - Element caching - c#

I am using C# and Watin.
Imagine the following scenario:
I search for an element using it's innerHTML/Find.ByText.
return Document.Element(Find.ByText(Localisation.CommandHeader));
CommandHeader.SetAttributeValue("Innerhtml", "Save Template");
CommandHeader.SetAttributeValue("onclick", "..");
I then change the elements text, and want to add a onclick event on it using Element.setAttributeValue.
Now Watin throws an Exception, telling me it can't find the element with criteria Innerhtml(..).
Saving the Element to a local variable did not help.
What I also tried, is adding CommandHeader.Refresh() between the two commands.
By the time of writing I came up with the idea of first assigning an id to the element, and then access it by only using that as selector afterwards. However, I didn't test it yet.
Is there a better way? Any help appreciated, thank you.

Related

Testing with Selenium in C# - Website which I need to test changes XPath

I need to create a testing automation tool in selenium with c# to test the website of my company. Everything works fine, except one thing: everytime when I reload a task on the website (like "create new user"), the XPath of some fields change. The first name field is as example not "//*[#id=\"0FirstName\"]" anymore, the new xpath would be "//*[#id=\"2FirstName\"]" and selenium does not recognize that field anymore like before -> program stops working
Is there a way to make a dynamic function to ignore the number before the email?
driver.FindElement(By.XPath("//*[#id=\"0FirstName\"]")).SendKeys("Selenium");
You can use XPath contains() function like:
//*[contains(#id,'FirstName')]
If for some reason it doesn't work, i.e. returns multiple matches you can also implement some form of ends-with() function by using combination of substring() and string-length() functions like:
//*[substring(#id, string-length(#id) - string-length('FirstName')+ 1, string-length(#id))= 'FirstName']
More information: XPath Operators & Functions
You can change your xpath as following:
driver.FindElement(By.Xpath("//*[contains(#id,'FirstName')]"));
you can use contains()
driver.FindElement(By.XPath("//*[contains(#id,'FirstName')]")).SendKeys("Selenium");

How do I find one element after using Findelements in Selenium?

I'm trying to create this global method that click on this link called "Categories". The ID (t_166) is dynamic, Xpath (//*[#id="t_166"]) and "copy selector" (#t_166) use the id number also so they won't work.
So, I'm left with the html:
I figured class would be a good candidate. So... to start:
var categorymenu = driver.instance.findelement(by.classname("fontMediumBigColorGrey navigatorLinkClicked z-label")
And then I want it to find the category one and click on it, something like:
categorymenu.getattribute(category).click();
Two problems.
Problem 1: The link's class changes depending if you've visited it previously, or the "linkclicked" part in it. It becomes "fontMediumBigColorGrey z-label" if you haven't been on it. Question: it won't be able to find categories if the class is different. How would I handle this?
Problem 2: There are many other links (like users) that use the same classes, so shouldn't I be using findelements and then isolate it by an attribute (category is this case) But findelements doesn't seem to be able to use getattribute (because there are many of them) so how do I cover that part?
Thanks!
You can use search by XPath to find your element:
var categorymenu = driver.instance.findelement(by.xpath("//span[text()='Categories']")
In code above you search for span element with "Categories" as its text value
Also you can try to ignore dynamically changing part of id attribute in following way:
var categorymenu = driver.instance.findelement(by.xpath("//div[starts-with(#id, 't_')][substring-after(#id, '-')='cave']/span")
Above code should search for span that is child of div with id="t_XXXX-cave" where XXXX is ignored part
Note You should also be aware that you will not be able to complete categorymenu.getattribute(category).click(); as categorymenu.getattribute(category) (actually categorymenu.GetAttribute(category)) returns just a string value
In case you want to see if the span has the fontMediumBigColorGrey class:
var categorymenu = driver.instance.findelement(by.xpath("//span[contains(#class, 'fontMediumBigColorGrey')]")
In case you want to see if the text is equal to "Categories":
var categorymenu = driver.instance.findelement(by.xpath("//span[text()='Categories']")
A trick that I sometimes use, and could be useful for you too - if you're using Chrome, open the console and edit the HTML in such a way that you delete the "id" tag. Then, right click and choose 'Copy > Copy XPath'. This will copy the XPath but neglect the ID (because you can't use it since it's dynamic).

How to set drop down list control in Word document using c#?

I am having issues with setting a drop down list control in ms word document using Novacode-Docx. e.g. Gender from drop down list.
I have got some text replacement but that's easy. I have done that. Just the drop down list I am struggling with.
If there is any solution in c# other than using Novacode-Docx I am happy to implement that.
I haven't included any code for the reason that I don't know how to set or get the drop down list values from Ms word document using c#. I have tried google but didn't get any thing related to drop down list.
Here is a sample DropDown.
I have used Drop down list from Developer option and used the properties to add items to it.
Here is the actual List
To access the list of a content control dropdown use the Add method. I have no idea whether the library you're using provides access to that. The following code sample is standard C#:
object oLstEntryValue = "1";
object oLstEntryIndex = 1;
ContentControl.DropdownListEntries.Add("entry caption", ref oLstEntryValue, ref oLstEntryIndex);
The last two parameters are optional, so you can also pass Type.Missing if you don't want/need to specify them.

Find all elements by xpath attribute (aria-required = true) .//*[#aria-required='true']

I'm trying to get a list of IwebElements that contain the attribute aria-required. Reason why I'm trying to get this list, is so that i can check if all required fields are necessary for the user to fill out, before he can continue to the next page.
So far after 2 days of searching I'm still convinced that it shouldn't be that hard. I'm using the expression:
".//*[#aria-required='true']"
From my research that would mean that it will search for ALL the elements starting from the root of my webdriver.
[TestMethod]
public void CreateProjectWithoutRequiredFields()
{
GoToProjectPage();
tracking = CM.GoToNewlyCreatedFrameAfterClickButton("ftbNew", tracking, theDriver);
CM.Wait(2000);
bool succesSave = false;
CM.LogToFile("Create project whitout required fields", tracking);
foreach (IWebElement e in theDriver.FindElements(By.XPath(".//*[#aria-required='true']")))
{
FillDataInNewProjectPage();
e.Clear();
CM.GetDynamicElementById("btnSave", theDriver).Click();
try
{
CM.GetDynamicElementById("titel", theDriver).Click();
}
catch (Exception)
{
succesSave = true;
NUnit.Framework.Assert.IsFalse(succesSave, "The page is saved with succes, without entering text in the following required fields : " + e.GetAttribute("id").ToString());
}
CM.Wait(1000);
}
}
I will try to explain what i did here:
First i went to a overview page with all my existing projects. On this page i clicked the ftbNew button to create a new project. The driver is automatically switch to the correct frame (i now the right frame is selected because i used this line on other page's.)
then the line
foreach (IWebElement e in theDriver.FindElements(By.XPath(".//*[#aria-required='true']")))
{
should normaly find a the elements in my driver with an attribute "aria-required='true'"
Then it would fill in the page with data, clear the first element that is found from its data en try to save it.
if the element titel is found on the page, than we are still on the same page en the save action wasn't successful ( <- so this is good)
so next we again overwrite every field on the page and clear this time the second element that is found.
en so on...
What I'm guessing, that xpath has difficulty finding the 'old' aria-required attribute... When i try to validate my expression using firebug and other xpath checkers, the aria-required attribute isn't always present. Sometimes it finds the input field sometimes it doesn't.
source code page
As you can see in the firebug console not all attributes are loaded, account-manager has a aria-required attribute, but project leader doesn't. If i inspect the element again, but this time click project leader. The attribute will be loaded. Very strange....
Extra info: I am using frame's and i know a lot can go wrong if you are situated in the wrong frame, but i am sure that he is looking in the correct frame. Especially because i can't find the elements using firebug with the above expression. If i change my expression to .//input, it will find the elements but also selects input fields that aren't required.
In advance i want to thank everybody that want to look into my problem :)
Adriaan
Based on your description of the behavior on the page, you cannot rely on the aria-required attribute to indicate a required field. I think that you should go back to the developers of the site to ask them to give you a reliable handle. It may be as simple as looking for the "*" as the last character of the label associated with the input field, but that's kind of annoying to have to deal with.
As an aside, you should consider catching a more specific exception for your success case. Right now, if ANY exception happens, you'll declare success, but that may not be what you really want to do.

How to move through different records in C#

I made a form that basically displays information about different vendors from an XML file that I was given. The XML file is retrieved from a class that I created, called VendorsDB.cs. On my form, I have a Previous and Next button that I want to display the next vendor or the previous vendor (Vendor1, Vendor2...) but I have no idea what method to use. I know I have to use a loop but I'm not sure as to how to code the loop. I've just started programming with C# so I'm really lost. Any help would be greatly appreciated!
Your question is missing alot of information, but what im seeing is that you need to do some work with XML.
I suggest you look into Linq To XML which enabled you to query tags and attributes with query syntax.
A very simple query good look like this:
// Load the xml from the specified path
var xml = XDocument.Load(#"LocationOfXml");
// Query the first element with a "MyXmlTag" as name
var someAttribute = xml.Descendants().FirstOrDefault(x => x.Name == "MyXmlTag");
The query language is far richer than this simple query. Read up and im sure you'll be able to get it working asap.

Categories

Resources