How to find element - SAP NetWeaver - c#

I'm using SAP NetWeaver (SAP WEB UI) and found it difficult to automate with selenium.
I can say that a big amount of objects' Id's\Names are actually being changed from one-page reloading to another.
So I have tried to use _webDriver.FIndElement(By.Xpath(//*[contains(#id,'foo')]));
But the element cannot be found. While this (find an element by XPath) can work on one object, it won't work for a different one. very frustrating.
It might be that either I'm doing something wrong or the object rendered is problematic.
This is an example for an HTML object :
<input id="grid#28.115#7,1#if" ct="I" lsdata="{0:'grid\x2328.115\x237,1\x23if',2:'100000008',4:10,8:true,9:true,13:'100\x25',14:'FORCEDLEFT',17:true,18:true,19:true,20:'0',25:true,41:false,44:{MaxInputLen:'10'}}" lsevents="{FieldHelpPress:[{ClientAction:'none'},{modalNo:'0',rgv:[{id:'28.115',submit:'X',type:'GuiGridView'}]}]}" type="text" maxlength="10" tabindex="-1" ti="-1" class="lsTblEdf3 lsTblEdf3NoEllipsis urBorderBox lsControl--explicitwidth lsField__input" readonly="true" value="100000008" autocomplete="off" autocorrect="off" name="grid#28.115#7,1#if" style="vertical-align:top;text-align:left;" title="">
That's the way I'm trying to find it , but being failed:
var element = wait.Until(x => x.FindElement(By.XPath("//input[contains(#id,'115#7,1')]")));

You may use ExpectedConditions. See code below.
var elem = wait.Until(ExpectedConditions.ElementExists(By.CssSelector("input[id*='115#7,1']")));

Related

Get informations from long string?

im currently trying to get a online status from a user on a website. Im able to get the website content into a string which shows me the online status of the users :
</path></g></svg><div class="name-2WpE7M">Friends</div></a></div><header>Direct Messages</header><div class="channel-2QD9_O selected-1HYmZZ" style="height: 42px; opacity: 1;"><div class="wrapper-2F3Zv8 small-5Os1Bb forceDarkTheme-2cI4Hb avatar-small"><div user="Dennis" status="online" class="avatar-small stop-animation" style="background-image: url("/assets/322c936a8c8be1b803cd94861bdfa868.png");"></div><div class="online-2S838R status-oxiHuE small-5Os1Bb status"></div></div><span class="name-2WpE7M">Dennis</span><button class="close-3hZ5Ni"></button></div></span></div></div></div><div class="container-2Thooq"><div class="wrapper-2F3Zv8 small-5Os1Bb avatar-small"><div user="halaldi" status="online" class="avatar-3JE4B3 avatar-small stop-animation" style="background-image: url("/assets/0e291f67c9274a1abdddeb3fd919cbaa.png");"></div><div class="online-2S838R status-oxiHuE small-5Os1Bb status status-2kJpnA"></div></div><div class="accountDetails-3k9g4n nameTag-m8r81H"><span
https://pastebin.com/Hb1mp1fq search for status="online" and you will find here 2 users which are online.
But here comes the part where im stuck, whats the best way to get those informations out of the string? I could split the string down until i only have the parts left which i need, but i guess that stupid and not the best way to do it, so i would love to learn a new and better way for this :)
It seems your data is HTML based.
If so you can use HTML parsing library like :
https://www.nuget.org/packages/HtmlAgilityPack
It provies many ways to parse HTML (by tags, css etc).

c# fail to get element in content page with getelementbyid, getelementsbytagname

I have posted the same question but I post it again since I haven't got any answers to that post yet.
I am trying to get some information (such as tagName, id using GetElementsByTagName method or GetElementById method) from a content page in a website using winforms.
as you see the pictures attached, no matter which selection you make (select1, select2, select3 etc) web address stays same. however, contents under those selections are different in content page.
I am trying to access to a tagName(or id) from one of them(not selections but contents under a specific selection).
I have debugged and figured out(or seems like) I can not access to tagName(or id) from any of those contents under a specific selection.
It seems like I can only access tagName(or id) from main page. picture 3 will help better explanation of some terms such as main page, content page.
I tried to explain in detail, if my question seems still not clear, let me know plz.
My code looks like this.
var countGetFile = webBrowser1.Document.GetElementsByTagName("IFRAME");
foreach (HtmlElement l in countGetFile)
{
if (l.GetAttribute("width").Equals("100%"))
{
MessageBox.Show(l.GetAttribute("height").ToString());
MessageBox.Show(l.GetAttribute("outerText").ToString());
}
}
I was not able to grab information under 2 down level of #document from html.
html looks something like
...
<src="..." id="A" ... >
#document
...
<src="..." id="B" ... >
#document
...
<span="C" ...>
...
I could grab span information (third curly brackets) with codes looking like
HtmlWindow frame1 = webBrowser1.Document.GetElementById("A").Document.Window.Frames["A"];
HtmlWindow frame2 = frame1.Document.GetElementById("B").Document.Window.Frames["B"];
foreach (HtmlElement elm in frame2.Document.All)
{
if (elm.GetAttribute("tagName").Equals("C"))
{
// your command
}
}
to use Document.Window.Frames you need a header using "System.Collections";
btw, there is a problem. When I try to access to the information in third curly bracket, I need to do some kinds of work between frame1 and frame2 such as delaying for frame2 to have enough time to be able to access to next level after frame1.
I figured a kind of hack to get it through. Place a messagebox to pop up for short time delay, or place a delay function( not freeze ) with async code looking like,
async Task PutTaskDelay()
{
await Task.Delay(5000);//5 secs
}
I just found a temporary solution for accessing to second level. I will appreciate anyone who knows some ways to solve this problem.

Can't find this element on page even though it is exist C# selenium

I have tried finding this element for the longest time and I can't figure it out. My goal is too set the value to a number using setattribute but I can't find the element.
<input type="tel" id="cvNumber" tabindex="1" data-shortname="cvv" class="cc-input ncss-input pt2-sm pr4-sm pb2-sm pl4-sm u-align-center" "cvv"="" autocomplete="off" autocorrect="off" value="" maxlength="4">
Here is some code I used to try to find the element
driver.FindElement(By.XPath("//input[#class='cc-input ncss-input pt2-sm pr4-sm pb2-sm pl4-sm u-align-center');
driver.FindElement(By.Id("cvNumber");
driver.FindElement(By.XPath("//input[#id='cvNumber'");
driver.FindElement(By.className("cc-input ncss-input pt2-sm pr4-sm pb2-sm pl4-sm u-align-center");
driver.FindElement(By.XPath("//input[#type='tel'");
Thanks in advance
I don't think there is anything wrong with the element selector. Its likely that you are not waiting for the element long enough
var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(10));
var myElement = wait.Until(x => x.FindElement(By.Id("cvNumber")));
if(myElement.Displayed) {
//do stuff
}
Or its possible that the element is inside a frame, so you need to switch to the frame before executing code above.
driver.SwitchTo().Frame(driver.FindElement(By.id("frameId")));
try with this code :
driver.FindElement(By.XPath("//input[#id='cvNumber'][#type='tel']");
As per your shared HTML, you can use below location strategies
Xpath
.//*[#id='cvNumber']
CSS selector
#cvNumber

How to follow/debug html creation in ASP.net

I'm trying to find out where an extra div is inserted and how I would go about removing it.
In our Index.cshtml file we have this:
<div id="an-id">
#Html.DisplayFor(m => m.BottomArticleListContentArea, new { ViewName = "_ArticleListBlockNoHeader" })
</div>
And in our _ArticleListBlockNoHeader.cshtml view the code looks like this:
#if (Model != null)
{
for (int i = 0; i < Model.Items.Count; i++)
{
var article = Model.Items[i];
<div class="item" data-articleid="#article.ArticleId">
Item #article.ArticleId
</div>
}
}
BottomArticleListContentArea is a ContentArea and is handled by this DisplayTemplate:
#model ContentArea
#if (Model != null)
{
Html.RenderContentArea(Model);
}
As you can see, it doesn't really do anything except check if it's null. Oh... Maybe it does more things!
When I look at the generated html it looks like this:
<div id="an-id">
<div><div>
<div class="item" data-articleid="1">Item 1</div>
<div class="item" data-articleid="2">Item 2</div>
<div class="item" data-articleid="3">Item 3</div>
<div class="item" data-articleid="4">Item 4</div>
<div class="item" data-articleid="5">Item 5</div>
</div></div>
</div>
Notice how on row 2 and 9 there is two divs (<div><div> and </div></div>) that are not in the code I just shared above.
My hypothesis is now that these two divs might be added by some extension method somewhere or some handler or something else. I'm not familiar with the entire codebase and I'm fairly new with ASP.net so my knowledge of the insertion points in ASP.net is very limited.
Where could these two divs come from? And how can I start looking for them?
If something is missing in the question, please let me know, tried to be brief so that it would be easier to read and understand 😊
Thanks in advance!
Edit:
Made a mistake while cleaning the code, added back so that the result is what's generated by the code.
The HTML results above is what is returned and captured using fiddler. No JS has started running while the DOM is recorded.
Added the display template used.
This is the current solution that I have right now and I'm going to try out for a while:
(highly EPiServer specific)
Instead of letting it be rendered using RenderContentArea we're taking control over it and creating it the "raw" way with RenderContentData
foreach (var content in Model.FilteredItems)
{
Html.RenderContentData(content.GetContent(), false, Model.Tag);
}
This gets rid of all the extra divs and make it behave just the way we want it, just the way it seen when we read the code.
Yes, with this we're also loosing the ability to edit the page directly in epi visually. But that's something we need to look into later, for now, it works and I'm happy.
I also wrote this extended version that lets me choose if I want to skip the wrappers or not like this (notice DisableWrapper = true)
#Html.DisplayFor(m => m.ContentArea, new { DisableWrapper = true, ViewName = "_ArticleList" })
That can be done if I instead change the first code snippet to this:
var disableWrapper = Html.ViewContext.ViewData["DisableWrapper"] as bool?;
if (disableWrapper.GetValueOrDefault())
{
foreach (var content in Model.FilteredItems)
{
Html.RenderContentData(content.GetContent(), false, Model.Tag);
}
}
else
{
Html.RenderContentArea(Model);
}
This works and seems to produce the results I'm looking for. As stated previously, I haven't worked in this field for that long so if there's any suggestions or tips, I'd love to hear that and be able to improve my solution both here and in the project.
Thanks for the helpful comments that made me finally arrive at this solution!

How to grab session ID - Xpath, C#

I'm trying to read the value of a session ID which is served up to a client page (a pin that can then be given to other users who want to join the session), which according to chrome developer tools, is located within this element:
<input type="text" size="18" autocomplete="off" id="idSession" name="idSession" class="lots of stuff here" title="" ">
So far I've been using C# and Xpath to navigate around the site successfully, for testing purposes, but I just can't get hold of the pin that is generated within id="idSession", or by using any other identifier through Xpath. There's a bunch of jquery stuff going on in the background, but neither is it showing up there (again, the code knows about the on-screen locations in the .js files for the ID, but that's it).
I'm new to all of this so would really appreciate a nudge in the right direction, ie. what different tools I need for this, what am I missing etc. what I need to read up on.
Thanks a lot.
What about //input[#id='idSession']/#value to get the content
Also, including a link to a helper library for creating xpath using linq-esq syntax
var xpath = CreateXpath.Where(e => e.TargetElementName == "input" &&
e.Attribute("id").Text == "idSession").Select(e => e.Attribute("value"));
http://unit-testing.net/CurrentArticle/How-to-Create-Xpath-From-Lambda-Expressions.html

Categories