Getting text of a span that is not displayed - html

The web page I'm testing has a span with inner HTML having a numeric value that I want to extract. For example:
<span class="timeout" style="display:none">5000</span>
I tried using the nightwatch command getText(), but it only returns "displayable" text, which, in this case, is a null string. What is the proper way to access this data?

Figured it out myself. You can use getAttribute on "innerHTML" to get the value, e.g.,
browser.getAttribute(spanCSS,"innerHTML",function(r)
{ console.log("span's innerHTML is " + r.value)
})
Wonder if there is a list of these "reserved" attribute names somewhere.

Related

Rendering VueJS prop within HTML array

I have an HTML array with data like so:
data-groups='["category_all", "data goes here"]'
I have a prop called "title" which contains the string I need to render in the "data goes here" area. I've tried using v-bind, but then I lose the array which I need to have in order for the original sort feature to work.
I google'd a few different ways to either escape or render quotes, and most refer to v-bind which again, won't work in this instance.
Any help would be appreciated :)
I was using Shuffle.js and for anyone else seeking an answer, it was in the documentation:
https://vestride.github.io/Shuffle/docs/getting-started
Alternatively, you can set the delimiter option to a comma (delimiter: ',') and the data-groups attribute will be split on that character.
Then changing the above line of code to:
:data-groups="item.category.title + ',all'"
works just fine :)

How to write an XPath query for text within <script> using PhantomJS

I am trying to scrape some specific content that sits within the <script> section of a page (at the bottom of the page before the end of the tag. It is my understanding that this can't be done with regular XPath, so I will be using PhantomJs cloud via SEOTools for Excel plugin.
Please see code below:
<script> window.__INITIAL_STATE__ = {"questions":{"list":{},"status":{}},"sites":{"list":{"SEOTest":{"joined":"2016-04-17T22:00:31.000Z","threshold":[],"abn":"8724483318952",
I want to be able to scrape the text after "ABN" field, so the xpath would return "8724483318952". Does anybody know how this can be done with xpath?
To retrieve the desired target string value of "8724483318952" you can use the following XPath-1.0 expression:
substring-before(substring-after(script,'abn":'),',')
It gets the desired string from the <script> tag and its output is
"8724483318952"
The signature of XPathUrl is, according to this link:
=XPathOnUrl(
string url,
string xpath,
string attribute,
string xmlHttpSettings,
string mode
) : vector
So the whole expression could look like this:
=XPathOnUrl(A2,"substring-before(substring-after(//ul[#class='headshot']/script,'abn":'),',')")
I'm not sure that this expression really does work, but it should give you a pretty precise idea of how to handle XPath expression generally.

Not able to select a text using selenium

I have a readymade code and i'm trying to write tests for it using selenium. This is how my code looks like in element tab of chrome:
<table id="xyz">
<tbody>
<tr>...</tr>
"
I am not able to retrieve this text.
"
</tbody>
</table>
Doing this $x("//*[contains(text(),'I am not able to retrieve this text')]"); in console tab of chrome shows no results. I'm able to get text by this command if the text is defined in a div, span etc. (Also case sensitivity is not a problem).
In code that text is appended in tbody using jQuery('tbody').append( abc() ); and abc() function returns this text in this way pqr.html();
Now my questions is what xpath expression should i write to grab this text? And i am looking for a pure xpath expression i.e no java functions etc.
contains() expects singular value as the first parameter. An HTML element may have more than one text nodes children in it, in which case, your attempted XPath will evaluates only the first text node. According to the sample HTML posted, the first text node of <tbody> which will be evaluated consists of newline and some spaces, hence your XPath didn't consider <tbody> a match and returned no result.
To avoid the problem explained above, use contains() in predicate for individual text nodes like the following :
//*[text()[contains(.,'I am not able to retrieve this text')]]
or this way if you want to return the text node itself instead of the parent element :
//*/text()[contains(.,'I am not able to retrieve this text')]
That table element is probably within a frame. To access contents within a frame you need to first switch to it. You can use the "switch to" method in selenium. Refer this answer and this one.
For the same reason it is not working in the Chrome Dev Tools console. In the console tab, there is dropdown containing a list of frames. Make sure you select the correct frame in which the specific element exist and then execute your XPath.

How can you view the output XPATH functions like normalize-space()?

Say I have the following HTML:
<div class="instruction" id="scan-prompt">
<span class="long instruction">Scan </span>
<span id="slot-to-scan">A-2</span>
<span class="long instruction"> to prep</span>
</div>
And I'm trying to write an XPATH selector like this
//div[#id='scan-prompt' and normalize-space()='Scan A-2 to prep']
Is there a way to see what the normalize-space output actually is?
I know you can do $x("//div[#id='scan-prompt']) in chrome debugger but I don't know how to go from that to seeing the output of normalize-space.
Why can you not simply use the path expression
normalize-space(//div[#id='scan-prompt'])
to see what the normalized string value would look like? Other than that, what normalize-space() does exactly is:
Removing any leading or trailing whitespaces from the string argument
Collapsing any sequence of whitespace characters to just one whitespace character
If handed an element node as an argument (as is the case with your original expression), the function evaluates the string value of that element node. The string value of an element node is the concatenation of all its descendant text nodes.
The result of normalize-space(//div[#id='scan-prompt']) is, given the input you show (whitespace marked with "+"):
Scan+A-2+to+prep
Without invoking normalize-space(), for example string(//div[#id='scan-prompt']):
+
Scan+
A-2+
to+prep+
+
So, simply use path expressions that do nothing else than either giving back a string value or a normalized string value. With Google Chrome by using an XPath expression inside $x().

How to stop an html TEXTAREA from decoding html entities

I have a strange problem:
In the database, I have a literal ampersand lt semicolon:
<div
whenever its printed into a html textarea tag, the source code of the page shows the > as >.
How do I stop this decoding?
You can't stop entities being decoded in a textarea since the content of a textarea is not (unlike a script or style element) intrinsic CDATA, even though error recovery may sometimes give the impression that it is.
The definition of the textarea element is:
<!ELEMENT TEXTAREA - - (#PCDATA) -- multi-line text field -->
i.e. it contains PCDATA which is described as:
Document text (indicated by the SGML construct "#PCDATA"). Text may contain character references. Recall that these begin with & and end with a semicolon (e.g., Hergé's adventures of Tintin contains the character entity reference for the e acute character).
This means that when you type (the invalid HTML of) "start of tag" (<) the browser corrects it to "less than sign" (<) but when you type "start of entity" (&), which is allowed, no error correction takes place.
You need to write what you mean. If you want to include some HTML as data then you must convert any character with special meaning to its respective character reference.
If the data is:
<div
Then the HTML must be:
<textarea>&lt;div</textarea>
You can use the standard functions for converting this (e.g. PHP's htmlspecialchars or Perl's HTML::Entities module).
NB 1: If you were using XHTML[2] (and really using it, it doesn't count if you serve it as text/html) then you could use an explicit CDATA block:
<textarea><![CDATA[<div]]></textarea>
NB 2: Or if browsers implemented HTML 4 correctly
Ok , but the question is . why it decodes them anyway ? assuming i've added & , save the textarea , ti will be saved < , but displayed as < , saving it again will convert it back to < (but it will remain < in the database) , saving again will save it a < in the database , why the textarea decodes it ?
The server sends (to the browser) data encoded as HTML.
The browser sends (to the server) data encoded as application/x-www-form-urlencoded (or multipart/form-data).
Since the browser is not sending the data as HTML, the characters are not represented as HTML entities.
If you take the data received from the client and then put it into an HTML document, then you must encode it as HTML first.
In PHP, this can be done using htmlentities(). Example below.
<?php
$content = "This string contains the TM symbol: ™";
print "<textarea>". htmlentities($content) ."</textarea>";
?>
Without htmlentities(), the textarea would interpret and display the TM symbol (™) instead of "™".
http://php.net/manual/en/function.htmlentities.php
You have to be sure that this is rendered to the browser:
<textarea name="somename">&lt;div</textarea>
Essentially, this means that the & in < has to be html encoded to &. How to do it will depend on the technologies you're using.
UPDATE: Think about it like this. If you want to display <div> inside a textarea, you'll have to encode <> because otherwise, <div> would be a normal HTML element to the browser:
<textarea name="somename"><div></textarea>
Having said this, if you want to display <div> inside a textarea, you'll have to encode & again, because the browser decodes HTML entities when rendering HTML. It has nothing to do with your database.
You can serve your DB-content from a separate page and then place it in the textarea using a Javascript (jQuery) Ajax-call:
request = $.ajax
({
type: "GET",
url: "url-with-the-troubled-content.php",
success: function(data)
{
document.getElementById('id-of-text-area').value = data;
}
});
Explained at
http://www.endtask.net/how-to-prevent-a-textarea-element-from-decoding-html-entities/
I had the same problem and I just made two replacements on the text to show from the database before letting it into the text area:
myString = Replace(myString, "&", "&")
myString = Replace(myString, "<", "<")
Replace n:o 1 to trick the textarea to show the codes.
replace n:o 2: Without this replacement you can not show the word "" inside the textarea (it would end the textarea tag).
(Asp / vbscript code above, translate to a replace method of your language choice)
I found an alternative solution for reading and working with in-browser, simply read the element's text() using jQuery, it returns the characters as display characters and allows me to write from a textarea to a div's innerHTML using the property via html()...
With only JS and HTML...
...to answer the actual question, with a bare-minimal example:
<textarea id=myta></textarea>
<script id=mytext type=text/plain>
™
</script>
<script> myta.value = mytext.innerText; </script>
Explanation:
Script tags do not render html nor entities. By storing text in a script tag, it will remain unadultered-- problem is it will try to execute as JavaScript. So we use an empty textarea and store the text in a script tag (here, the first one).
To prevent that, we change the mime-type to text/plain instead of it's default, which is text/javascript. This will prevent it from running.
Then to populate the textarea, we copy the script tag's content to it (here done in the second script tag).
The only caveats I have found with this are you have to use JavaScript and you cannot include script tags directly in it.