Why can't I use FindElementByXPath on this table from a website? - vba

I am currently working with webscraping on vba using selenium and chromedriver.
I log in a website (the website is, unfortunately, unreacheable due to a login necessity, but it's https://monitoring.csisolar.com/login), and within the main page, there is a general table with a bunch of info.
I used "inspect element" and identified the table object as in the image:
print of the found element, the table is highlighted
When I select "copy xpath", I get this: "//*[#id="mCSB_67_container"]/table"
Naturally, I set the command like this:
Set tabela = driver.FindElementByXPath("//*[#id="mCSB_67_container"]/table") 'Seleciona a tabela pelo java
If tabela Is Nothing Then
MsgBox "Não encontrado"
Else
tabela.AsTable().ToExcel (ActiveSheet.Cells(1, 1)) 'Cola a tabela na planilha (aba) onde está o botão
End If
but nothing is printed on excell.
I did the same thing in other similar sites (solarweb.com) and it went very well, but the table object had a id and class defined, while the one above has no attributes named (as seen on the print)
I know this question is not very clarified, but please comment below if there's something that can help you understand and I will gladly edit my question

Whatever is under the hood is creating dynamic ids. Your goal is to find selectors that don't change. Then use them to navigate down the DOM until you get to your table. In your small excerpt I don't see anything that's screaming unique id that never changes. If you only have one table visible you could just find it like this:
driver.findElement(By.cssSelector("table"));

mCSB_67_container seems to be a dynamically created id value i.e. this is not a fixed id value.
I'm not sure (need to see the actual page with dev tools), but you can try using this XPath instead:
Set tabela = driver.FindElementByXPath("//div[contains(#class,'mCustomScrollBox']//table")

Sometimes, it is hard locate the element,
if it is static table and dynamically updating values page. better right click and copy xpath given by chrome. that works efficiently. instead writing looping logic.
enter image description here

What is being tried on the question does not work because that table element is a dynamic object, so it's "id" and "class" attributes are not constant and cannot be referecend.
So, thanks to #Prophet and #David M, I discovered that I should be looking for a static reference instead, a part of the site's interface that wasnt dynamic, and then use that to reference said table.
The element I used was the division that contained the element, which had an ID of "plantList". Here's a screenshot of how I found this element:
In red, an arrow pointing to the table element, and in green, an arrow pointing to the statc element that I used to reference
From this point on, I just make my way through every other element until I reached the table. the final line is something like this:
Set canadian = driver.FindElementByXPath("//*[#id=""plantList""]/div[3]/div[1]/div[1]/div[2]/div[1]/div[1]/table") 'Seleciona a tabela pelo java
If canadian Is Nothing Then
MsgBox "Não Encontrado"
Else
canadian.AsTable().ToExcel (ActiveSheet.Cells(1, 1)) 'Cola a tabela na planilha (aba) onde está o botão
End If

Related

Unable to identify Web object in UFT for webpage?

SystemUtil.Run "iexplore.exe", "https://www.jetairways.com/EN/IN/Home.aspx"
wait (7)
Set traverse=Browser("Jet Airways: Airlines").Page("Jet Airways: Airlines")
traverse.WebEdit("placeholder:=From").Click
traverse.Link("acc_name:= This link will open Popup window for airport selection. ").WebElement("innerhtml:=All Airports","innertext:=All Airports","outerhtml:=<strong>All Airports </strong>").Click
traverse.WebTabStrip("html id:=ToC").Link("innerhtml:=Africa","innertext:=Africa").Click
Set oDesc = Description.Create
oDesc( "micclass" ).value = "Link"
oDesc( "href" ).value = "https://www.jetairways.com/EN/IN/Home.aspx#"
Set rc=Browser("creationtime:=0").Page("micClass:=page").ChildObjects(oDesc)
msgbox rc.count
UFT is not bale to identify the link, lets say, Johanesber or Port Elizabeth,etc
This is actually not working. Have tried many ways .
Can some one help me fix this?
The following code works for me, I cleaned up some of the spaces (and simplified the description a bit). I don't understand what you were trying to accomplish with the last lines of your script (counting the links).
I think the problem you were facing was probably to do with the fact that when you use descriptive programming (either inline with := or using a Description object), the values are used as regular expressions and not as plain strings. This means you have to escape regular expression characters (in this case ( and )) or else the values won't match.
Set traverse=Browser("Jet Airways: Airlines").Page("Jet Airways: Airlines")
traverse.WebEdit("placeholder:=From").Click
traverse.Link("acc_name:=This link will open Popup window for airport selection.").WebElement("html tag:=strong").Click
traverse.WebTabStrip("html id:=ToC").Link("innerhtml:=Africa","innertext:=Africa").Click
traverse.Link("innertext:=Port Elizabeth \(PLZ\)").Click ' Note \( and \)
Try to write the link object and the pop up window object in two different lines
traverse.Link("acc_name:= This link will open Popup window for airport selection. ")
traverse.WebElement("innerhtml:=All Airports","innertext:=All Airports","outerhtml:=<strong>All Airports </strong>").Click
also try to use Regex if the property values contains spaces or symbols.

Getting description using selenium xpath

I am trying to get the job description for job search page indeed.com This is how it looks like
Provide technical leadership around
QA
automation to IT teams. Work with various team to promote
QA
processes, practices and standardization....
Any idea how can I get that description? I tried the following:
//span[contains(#class,'summary')]
That does not give me the text description. Should I xpath or is there any other solution? Thanks in advance for your time.
This XPath are correct.
//span[contains(#class,'summary')]
//span[#class='summary']
I'm a Python guy, But I translated it to Java. You can do:
element = driver.findElement(By.name("summary"));
element = driver.findElement(By.className("summary"));
element = driver.findElement(By.cssSelector('span[class="summary"]');
And remember that If you want the element text, every element has the method .getText(), the find* functions only retrieve the element/s.
Double check you were not using driver.findElements(By.xpath()) in plural. In that case you should first retrieve the individual elements. Then access to the .getText() method.
description = driver.findElement(By.className("summary")).getText();
System.out.print(description);
Alternatively you could do:
description = driver.findElement(By.className("summary"));
description_text = description.getAttribute("innerHTML");
System.out.print(description_text);
If your problem is that your element is not visible or reachable (stale). Then you can use javascript.
element = driver.executeScript("return document.querySelector('span[class=\"summary\"]');");
For more reference:
https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/WebElement.html

Unable to select an element in the table

I am testing out Selenium recently to see if it can recognize my web app better than QTP. So far it seems doing quite well. I ran into a problem trying to find an element within the table element. Some how I was not able to find master table but not the rows within the table.
This is how the table looks like
The code below works fine...
WebElement BaseTable = driver.findElement(By.id("table_simpleBrowser|type=TradingInstrumentReport|!browser"));
Where as the code below does not...
BaseTable = driver.findElement(By.id("table_simpleBrowser|type=TradingInstrumentReport|!browser_tr_1"));
or
BaseTable = driver.findElement(By.className("even status_DEFAULT"));
or
WebElement BaseTable = driver.findElement(By.id("table_simpleBrowser|type=TradingInstrumentReport|!browser"));
BaseTable = BaseTable.findElement(By.className("even status_DEFAULT"));
Can someone please help to show me how I can retrieve the a certain value in the table by finding the element in certain row/column in the table?
Thanks.
even and status_DEFAULT are actually two classes of this web element. By.className() receives only one class as parameter. It should be
findElement(By.className("even"));
// or
findElement(By.className("status_DEFAULT"));
To find element by the two classes use By.cssSelector()
findElement(By.cssSelector(".even.status_DEFAULT")); // note the dot before each class name
However it seems that its not unique enough. I recommend you search by id which contains browser_tr_1
findElement(By.cssSelector("[id*=`browser_tr_1`]"));

QTP - Checking dynamic pages

I'm trying to check if a value is contained in the innertext of a webelement but I'm having a little problem: frames seem to change at every refresh of the pages.
These are the steps I've recorded:
Browser("SystemPage").Page("SystemP").Frame("dme2_header").Image("Gestione Anagrafiche").Click<br>
Browser("SystemPage").Page("SystemP").Frame("dme2_appl").WebEdit("pdrBean.pdrPod").Set parameter("POD")<br>
Browser("SystemPage").Page("SystemP").Frame("dme2_appl").WebButton("Cerca").Click
Browser("SystemPage").Page("SystemP").Frame("dme2_appl_2").Image("show_files").Click
Browser("SystemPage").Page("SystemP").Frame("dme2_appl_6").Image("Lente").Click
cctype = Browser("SystemPage").Page("SystemP").Frame("dme2_appl_7").WebElement("arrow_down").GetROProperty("innertext")<br>
DataAct = Browser("SystemPage").Page("SystemP").Frame("dme2_appl_7").WebElement("arrow_down_2").GetROProperty("innertext")<br>
Browser("SystemPage").Page("SystemP").Frame("dme2_header").Image("Gestione Anagrafiche").Click
The frames "dme2_appl6" and "dme2_appl7" changes at every refresh of the two pages.
The question is simple: how can I rewrite these two actions to make them universal?
I've tried to do something like:
Set objFrame = Frame("title:=dme2_appl_.")
and then
Browser("SystemPage").Page("SystemP").objFrame.Image("Lente").Click
But QTP gives me an error in return: "property or method not supported by the object"
Please try using the below code
Browser("SystemPage").Page("SystemP").Image("Lente").Click
Avoid using the "Frame" and if you really want to use it, put regex for name property of Frame.
Go to Object Properties--> Click on the Frame object --> Mandatory Properties--> Change name property as
like iFrame_213123123 to i.*
Hope this will solve your problem.
I don't think you can use a frame object that way. When you write Page().Frame() UFT sets the frame's parent in different way than if you first create the Frame.
Think of Frame() as a function that behaves differently when called on a Page or as a free function.
Try:
Browser("SystemPage").Page("SystemP").Frame("title:=dme2_appl_.")

Detecting Drop down with Selenium WebDriver

http://i.stack.imgur.com/L4WUv.jpg
Link to Grid
I'm trying to detect the different drop downs on this page (depicted by the filters by the text boxes). The problem i'm having is that it seems that the filters all have the same ids. I can get the webdriver to find the initial filter button but not target the options in the drop down.
Note the filters I'm talking about are the ones from the funnel buttons. For example contains, isEqual, between etc *
This is wrong but an example
it('Should filter grid to -contain Civic', function() {
browser.element(by.id('ctl00_ContentPlaceHolder1_RadGrid1_ctl00_ctl02_ctl03_FilterTextBox_Model')).sendKeys("civic");
browser.element(by.id('ctl00$ContentPlaceHolder1$RadGrid1$ctl00$ctl02$ctl03$FilterTextBox_Model')).click();
browser.element(by.xpath("//*[contains(text(), 'Contains')]")).click();
})
NOTE The answer that was being looked for is at the bottom of this answer after the word "EDIT". The rest of this answer is retained because it is still useful.
It's a challenge to test webpages that dynamically generate ids and other attributes. Sometimes you just have to figure out how to navigate the stable attributes with an xpath. Here's an xpath that finds all four dropdowns:
//tr[#class='rgFilterRow']//input
To differentiate between each one, you can do this:
(//tr[#class='rgFilterRow']//input)[1] // Brand Name
(//tr[#class='rgFilterRow']//input)[2] // Classification
(//tr[#class='rgFilterRow']//input)[3] // Transmission
(//tr[#class='rgFilterRow']//input)[4] // Fuel
Using numbers to specify elements in an xpath isn't really desirable (it will behave incorrectly if the order of columns in the table changes), but it's probably the best you can do in this case because of all the dynamic ids and general lack of reliable identifying attributes.
EDIT
I misunderstood what you were trying to get because I didn't look at the image that you linked to. Once you've opened up that menu, you should be able to use an xpath to get whichever option you want by the text. For example, if you want the "Contains" option:
//a[#class='rmLink']//span[text()='Contains']
This page is highly dynamic. You had better brush up on your XPath, as nothing else will be able to help you. You can use this: http://www.zvon.org/xxl/XPathTutorial/General/examples.html .
Here is a simple example of how to access the Brand Name "pulldown". This is written in Groovy, which looks a lot like Java. If you know Java you should be able to get the idea from this:
WebElement brandName = driver.findElement(By.id("ctl00_ContentPlaceHolder1_RadGrid1_ctl00_ctl02_ctl03_BrandNameCombo_Arrow"))
brandName.click() // to open the "pulldown"
List<WebElement> brandItems = driver.findElements(By.xpath("//ul[#class='rcbList']/li"))
brandItems.each {
if(it.text == 'BMW')
it.click()
}
Unfortunately, the above id is not very reliable. A much better strategy would be something like:
WebElement classification = driver.findElement(By.xpath("//table[#summary='combobox']//a[contains(#id, 'ClassificationCombo_Arrow')]"))
Selecting its items is done similarly.
classification.click() // to open the "pulldown"
List<WebElement> classificationItems = driver.findElements(By.xpath("//ul[#class='rcbList']/li"))
classificationItems.each {
if(it.text == 'Sedan')
it.click()
}
If you are not up to the task, you should be able to get help from your development colleagues on how to locate all the elements in this page.