Selenium doesn't recognize element by XPath - javascript

i am sorry to create a topic about this, but this little thing has been boggling my brain for the past 2 hours. Chrome returns the right element by Xpath as well as by javascript script, but Selenium tells me that in the very code, that Chrome runs perfectly fine is an error:
javascript error: missing ) after argument list
This is the code I am currently trying:
driver.execute_script('let clickable = document.evaluate("//a[contains(#onclick,\"openFbLWin\")]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; clickable.click();')
i know its a bit messy, but overall the most important thing is //a[contains(#onclick,\"openFbLWin\")]
as for the XPath selector.

I think this is because when you run this in python, it converts "//a[contains(#onclick,\"openFbLWin\")]" into "//a[contains(#onclick,"openFbLWin")]", without the slashes. Then, when this is run in javascript, it can't parse the string because there is a double-quote inside of another double-quote. To fix this, change your xPath to "//a[contains(#onclick,'openFbLWin')]".
You should use selenium's inbuilt search and click tools, though. It is much more readable and faster (use find_element_by_xpath and click)

Related

Chrome Bookmarklet to Check URL

I am creating a chrome javascript bookmarklet with reference to:
this question
My code:
javascript:(function NoOverrideAction(t){this.currentWindow=t,this.urlMatchPattern=/https:\/\/.*visual\.force\.com\/apex\/.*/,this.urlMatchPattern1=/https:\/\/.*visualforce\.com\/apex\/.*/,null!=this.currentWindow.location.toString().match(this.urlMatchPattern)||null!=this.currentWindow.location.toString().match(this.urlMatchPattern1)?this.isPageValid=!0:this.isPageValid=!1,this.recordId} NoOverrideAction.prototype={getId:function(){this.currentWindow.location.search.substr(1).split("&").forEach(function(t){var i=t.split("=");"id"==i[0]&&(this.recordId=i[1])},this)},run:function(){this.getId(),console.log(this),this.isPageValid&&void 0!==this.recordId&&(this.currentWindow.location.href="https://"+this.currentWindow.location.hostname+"/"+this.recordId+"?nooverride=1")}};var noAction=new NoOverrideAction(window);noAction.run();)();
However, I get following error:
Uncaught SyntaxError: Unexpected identifier
This works well in console but not as a bookmarklet.
I am trying to verify the URL of my current page and replace the URL
Part I.
Several reasons why js-code might work in console, but not work as a bookmarklet.
1 - You don't use the established way of making bookmarklets, i.e. IIFE-functions.
javascript:(function(){
alert('hi');
/*code here*/
})();
2 - If you do use this structure, there might be the problem with comments.
Use /*multi-line comment*/ instead of //single-line comment (because bookmarklet is a one-liner, so you cannot close your comment)
3 - Some problems with semicolons ;.
Don't confuse statements (need semicolon) and assignments (do not need them).
Console has its "automatic semicolon insertion", but it is a problem for a one-lined bookmarklet.
You should read a bit more here: https://stackoverflow.com/a/2717956/5410914
Part II
Since there is no HTML-code to test, it might be hard to check. Moreover, you could have made it easier to read by making it multi-lined (it will still work as a bookmarklet when you paste it as a bookmark). But anyway.
The main reason it might not work is that you don't use IIFE-format (Immediately Invoked Function Expression).
Your code has function NoOverrideAction(t) and, moreover, there is };var noAction=new NoOverrideAction(window);noAction.run();)(); at the end. It is not IIFE.
Read more: https://developer.mozilla.org/ru/docs/Glossary/IIFE
To debug a bookmarklet on your own, since there is no HTML provided, you might try to make your code simplier (even with alert('hi'); at first, and verify the reason it won't start) and then make it more complicated once you figure out that it works.

How can i send character sequence to a contenteditable="true" element by using selenium and python

lately, I try to use python3.6 and selenium to do a small task, I want to log in a chatting webpage and send the message automatically.
http://maimai.cn/?regfr=baidu_pc_titlethis is the webpage that I want to send the message to
In my limited experience with python, I only know that the input element can send string. However, I came across this tough question.
I google a lot and I know that I need to use JavaScript in my python code to insert the string into a div element whose attribute contenteditable is true.
when I run my code like this:
my_desired_text="lzylzylzy"
driver.execute_script("document.getElementsByClassName('inputPanel'[0].innerHTML="+ my_desired_text)
it warns me like that:
selenium.common.exceptions.WebDriverException: Message: unknown error: lzylzylzy is not defined
but I indeed define my string.
I am searching for a long time on the net. But no use, please help or try to give some ideas on how to achieve this. Thanks in advance.
In my project, there is an iframe element to be located firstly.I locate an element in the iframe but I forget to switch to the main frame.This element is in the main frame.That is why i can't locate it.If you meet the similar situation, you can check whether you switch to your main frame and use .sendkey() method to send string.

How to keep "*/" in regular expression from being interpreted as block comment?

I'm working on a bookmarklet which is using the replaceText plugin to wrap all words (and extraneous spaces/punctuation) on a page in span tags. That plugin traverses all the text nodes on a page and allows me to call a function to manipulate the contents of each one without breaking any other HTML formatting on the page. (None of this is the problem, I'm pretty sure, but I felt like the context might be useful). My call of the function looks like this, for your reference:
$("body *").replaceText(/\S+\s*/g, spanWrap);
The problem is that the best regular expression I've found for separating these words for my purposes -- /\S+\s*/g -- contains the characters for the end of a block comment ("*/"). If I add the opening of a block comment a few lines before it in the .js file in Notepad++, I can see that the syntax highlighter is reading it as that.
When I run my bookmarklet, most sites seem to have no problem with this issue and the bookmarklet works as intended. However, some sites, for reasons I can't predict, throw up an "Uncaught SyntaxError: Unexpected token <" error and the bookmarklet breaks/stops running. If I change the regular expression I'm using in the replaceText function to one I had been using in an earlier version of the bookmarklet -- /\b(\S+?)\b/g -- while changing absolutely nothing else in the bookmarklet, these sites stop giving the error and the bookmarklet works just fine, so I have to believe that it's the presence of the block comment closure that's causing it.
For the purposes of what I'm trying to do with the bookmarklet, though, the expression with that comment closure in it --/\S+\s*/g-- works much, much better than the other one, which doesn't catch punctuation and white space. However, I'd also really like it if my bookmarklet didn't break on certain sites.
So, is there either a way to fix the regular expression that I have so that it's not being read as a comment or can you suggest one that can do the same job maybe with a different syntax or something? (If it's not obvious from my question, I have the barest understanding of how regular expressions work and have gotten the ones I'm using in this example by copying them from other Stack Overflow questions/answers)
Use the long version:
var regex = new RegExp("\\S+\\s*", "g");
$("body *").replaceText(regex, spanWrap);
(EDIT: Escaped the backslashes in the string)
So, is there either a way to fix the regular expression that I have so that it's not being read as a comment
I can't think of anything sane. (You could get the effect by using the RegExp constructor and breaking the regex up into two strings and then concatenating them back together for the regex. I wouldn't call that sane though.)
I'd use a series of line comments // instead of a block comment.

Avoid FF JS automatic HTML encoding?

I'm trying to make simple templating for users on a site. I have a test line like this :
<div id="test">Test</div>
It will alert the HTML properly with the following JS in all browsers except FF:
alert( document.getElementById( 'test' ).innerHTML );
In FF it will change the curly braces to their HTML encoded version. I don't want to just URL decode in case the user enters HTML with an actual URL instead of one of the templated ones. Any ideas to solve this outside of REGEXing the return value?
My fiddle is here: http://jsfiddle.net/davestein/ppWkT/
EDIT
Since it's seemingly impossible to avoid the difference in FF, and we're still early in development, we are just going to switch to using [] instead of {}. Marking #Quentin as the correct answer since it's what I'm going by,
When you get the innerHTML of something, you get a serialised representation of the DOM which will include any error recovery or replacing constructs with equivalents that the browser does.
There is no way to get the original source from the DOM.
If your code won't contain %xx elsewhere, you can just run it through unescape().

Make NSXMLParser skip an Element

I'm using NSXMLParser on an iPhone App to parse HTML Files for a RSS or Atom Feed Link.
Everything works fine until the parser find a <script> element that includes Javascript code without the CDATA Declaration, this causes a Parse Error.
Is possible to tell the parser to skip all the elements named <script>?
Why not just implement parser:parseErrorOccured: and tell it to fail gracefully? I don't believe there's a way to say 'skip this element'
It's not possible to my knowledge to just skip an element. However you may be able to use regex replacement to filter out the invalid content.
Another possibility would maybe to use Tidy to try to clean it up before parsing.

Categories

Resources