I'm new to Selenium and have searched for a solution for this, but cannot find one.
I am trying to drill down into a nav containing a collapsable directory tree. The folder nodes' content starts as an empty div that is populated when their "+" icon is clicked. The problem is that I cannot find anything within the newly populated div. I am using find_element_by_link_text() and have tried find_element_by_partial_link_text() with a fragment. I've even done a find_elements_by_tag_name() and the new elements (anchors) are not listed with those that exist outside of the new div.
The entire nav is contained within an iframe - is there a switch_to method that would apply?
Here is a sanitized example of what the HTML looks like:
<iframe id="KnownID" ...> <html ...> <body ...> <div id="unknown_id_first_subtree"> ... </div> <div id="unknown_id_nth_subtree"> <div id="unknown_a"> <table> <tbody> <tr> <td width="however wide the indent"></td> <td> <!-- Child nodes begin here --> <div> <table> <tbody> <tr> <td class="treeCell"> <a id="unknown_id"> this toggles the tree node display </a> <a id="unknown_id">This is the text I know</a> </td> </tr> </tbody> </table> </div> <div id="subtreeContainer_unknown_id"> <!-- Empty place holder to hold expanded content --> </div> <!-- Repeat above pattern for each tree entry --> </td> </tr> </tbody> </table> </div> </div> ... closes out the nth_subtree repeats
The empty place holder is populated when the node is expanded. I do not know any of the ID's when my script runs, all that I know is the text of the link ("This is the text I know").
The IDs of the elements are, of course, available at run time, and I can construct the ID of the various elements I need to use by replacing the prefix.
I was able to find_element_by_xpath the first entry:
with both FirePath and Seleninum. I can find "B" in "A/B" using FirePath with:
However, that string does not work when I issue it from Selenium using find_elements_by_xpath(). (I use the plural version because several entries match ("A", "A1", "A2") a single left fragment, just look for the one that I want in that list.)
The code that I wrote is basically:
xpath = "//" segments = [ "A", "B", "C", ...] for segment in segments: xpath += "a[contains(text(),'%s')]" % segment anchors = driver.find_elements_by_xpath(xpath) subTreeId = None for anchor in anchors: if anchor.text == segment: id = anchor.get_attribute("id") openId = "open" + id find_element_by_id(openId).click() subTreeId = "subTreeId" + id WebDriverWait(driver, 60).until(EC.presence_of_element_located((By.ID, subTreeId))) xpath += "/../../../../../..//div[@id='%s']//" % subTreeId break if subTreeId is None: fail()
The first iteration works and opens the first level of sub-tree, however, the second pass fails with this string:
which is the same as the one above and I can cut-n-paste this string into FirePath and it finds the node (nodes, actually, "B", "B1", "B2", ...) - sorry to repeat myself.
My thinking is that when I "click" the "openId" element, Selenium's concept of the "current node" changes and so should the xpath, however, I was not able to get that concept to work by not carrying the prior xpath forward (I changed the "+=" to just "=" for the xpath assignment just before the "break".
Thanks (again), I appreciate the help