This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-04-26
Channels
- # aleph (6)
- # announcements (1)
- # babashka (18)
- # beginners (13)
- # calva (18)
- # cider (5)
- # clojure (144)
- # clojure-europe (34)
- # clojure-nl (1)
- # clojure-norway (29)
- # clojure-uk (4)
- # emacs (9)
- # etaoin (51)
- # events (1)
- # gratitude (1)
- # hyperfiddle (9)
- # lsp (4)
- # off-topic (6)
- # pathom (61)
- # rdf (1)
- # releases (3)
- # shadow-cljs (16)
- # vrac (1)
- # yada (1)
- # yamlscript (3)
Good question @U02PR896TMG! Here's me playing in my REPL:
(require '[etaoin.api :as e])
(def driver (e/firefox))
;; I'll amble over to a page we can both play with...
(e/go driver "")
;; And do a similar query to what you specified
(def elem (e/query driver {:tag :a :fn/link "" :index 1}))
;; Let's inspect a bit (looks good)
(e/get-element-tag-el driver elem)
;; => "a"
(e/get-element-inner-html-el driver elem)
;; => "ClojureScript Cheatsheet"
;; And this is counter-intuitive, I think, but it seems you can use the child fn to ask for the parent via XPath
(def parent-elem (e/child driver elem ".."))
;; This seems to work fine!
(e/get-element-tag-el driver parent-elem)
;; => "p"
(e/get-element-inner-html-el driver parent-elem)
;; => "<a href=\" \">ClojureScript Cheatsheet</a>"
(e/quit driver)
So, in my dabbling here, I've found I can use the child
fn to get to its parent element.
Lemme know if this helps, works for you, and answers your question.sounds good @UE21H2HHD the answer is (e/child driver elem "..")
which is from your snippet 🙂
I need to get the last <tr>
element in the html inside the iframe, <#document> and again <html> and <body>
Have you read our user guide on this topic yet? https://cljdoc.org/d/etaoin/etaoin/1.0.40/doc/user-guide#_working_with_frames_and_iframes
I think maybe because you've switched inside the frame you can no longer see the frame element. Lemme try your HTML from here... just a sec.
Oh... I think you were trying to convey in your HTML example that your iframe
index.html
is the content between the #document
tags? Is that... your intent?
I've provided the screenshot as well https://clojurians.slack.com/archives/C7KDM0EKW/p1714175161211909?thread_ts=1714174911.619219&cid=C7KDM0EKW
So @U02PR896TMG, you gave me some HTML. I assumed I could use this to replicate your problem, but you just pasted it from the inspector. Now that I understand this, I can can rework your example HTML to something I can use and help you more.
Ok, I've saved your html and iframe HTML to separate files in my fiddle
directory.
fiddle/slack2024-04-26.html
<html xmlns="" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html">
<!-- CSS Tabs is licensed under Creative Commons Attribution 3.0 - -->
</head>
<body onload="init('tab1');">
<h1><a id="hudson_link" href="/job/Services/job/project-name/job/master/6121/">Back to #6121</a></h1>
<h2><a id="zip_link" href="*zip*/Cloverage_20report.zip">Zip</a></h2>
<ul id="tabnav">
<li id="tab1" class="selected" onclick="updateBody('tab1')" value="index.html">Cloverage report</li>
<script type="text/javascript">document.getElementById("hudson_link").innerHTML="Back to #6121";</script><script type="text/javascript">document.getElementById("hudson_link").href="/job/Services/job/project-name/job/master/6121/";</script><script type="text/javascript">document.getElementById("zip_link").href="*zip*/Cloverage_20report.zip";</script>
</ul>
<div>
<iframe id="myframe" height="100%" width="100%" frameborder="0" src="slack2024-04-26-iframe.html" style="height: 26px;">
</iframe>
</div>
</body>
</html>
And the iframe source fiddle/slack2024-04-26-iframe.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="./coverage.css">
<title>Coverage Summary</title>
</head>
<body>
<table>
<thead>
<tr>
<td class="ns-name"> Namespace </td>
<td class="with-bar"> Forms </td>
<td class="with-number">Forms %</td>
<td class="with-bar"> Lines </td>
<td class="with-number">Lines %</td>
<td class="with-number">Total</td>
<td class="with-number">Blank</td>
<td class="with-number">Instrumented</td>
</tr>
</thead>
<tbody>
<tr>
<tr>
<td>Totals:</td>
<td class="with-bar"></td>
<td class="with-number">84.65 %</td>
<td class="with-bar"></td>
<td class="with-number">97.08 %</td>
</tr>
</tbody>
</table>
</body>
<html>
So working with this in my REPL let's fire up a firefox session and bring up the test page:
(require '[etaoin.api :as e]
'[ :as io])
(def driver (e/firefox))
(e/go driver (-> "fiddle/slack2024-04-26.html" io/file .toURI str))
Now, notice that we can find the :myframe
element before we switch to it:
(e/exists? driver :myframe)
;; => true
But after we switch inside the iframe we can no longer see the iframe element (because we are inside it):
(e/switch-frame driver :myframe)
(e/exists? driver :myframe)
;; => false
Now that we are inside the iframe, I'll search for the last tr
in the tbody
like so:
(def elem (e/query driver {:css "tbody > tr:last-child"}))
And let's see if we go what we expected:
(e/get-element-tag-el driver elem)
;; => "tr"
(e/get-element-text-el driver elem)
;; => "Totals: 84.65 % 97.08 %"
I think that looks good.You are welcome, @U02PR896TMG; feel free to drop by if you get stuck again with Etaoin.
Hey @UE21H2HHD one more question
(let [parent-tr (e/query driver {:css "tbody > tr:last-child"})
td-els (e/child driver parent-tr {:tag :td})]
(println "parent-tr count is " (count parent-tr))
(println "row-els count is " (count td-els))
(for [row parent-tr]
(println (e/get-element-text-el driver row)))
#_(clojure.pprint/pprint (map #(e/get-element-text driver %) td-els)))
@U02PR896TMG you were close. Here's what I did below:
1. switched child
to children
to get all td
tags.
2. turfed the parent-tr count is
println, you were printing the length of the webdriver element id string
3. printed from the returned td-els
4. switched to doseq
from for
because for
is lazy and won't be realized outside of a REPL
Continuing from the REPL session I showed above:
(let [parent-tr (e/query driver {:css "tbody > tr:last-child"})
td-els (e/children driver parent-tr {:tag :td})]
(println "tds count is " (count td-els))
(doseq [td td-els]
(println "td text" (e/get-element-text-el driver td))))
Here's what this outputs for me:
tds count is 5
td text Totals:
td text
td text 84.65 %
td text
td text 97.08 %