Watir Random Popup - javascript

High all, I'm testing this e-commerce and I get this random popup (it's a div)that gets in the way of my scripts, given its random appereance I can't relly predict when it's going to show, otherwise I can easily interact with it, as it is a simple div, whenever I see it. It's there a way that can I catch this popup and do as I please whenever it dares to show? Thanks in advance
<div class="fsrFloatingMid"><div class="fsrInvite">
<div class="fsrDialogs">
<div style="margin-left: 0px;" class="fsrDialog ">
<div class="fsrLogos">
<img src="/_ui/desktop/common/foresee/sitelogo.gif" alt="" class="fsrSiteLogo">
<img src="/_ui/desktop/common/foresee/fsrlogo.gif" alt="Foresee" class="fsrCorpLogo">
</div>
<h1 class="fsrHeading">We'd welcome your feedback!</h1>
<p class="fsrBlurb">Some bullshit text</p>
<p class="fsrSubBlurb">The survey is designed to measure your entire experience, please look for it at the <u>conclusion</u> of your visit.</p>
<p class="fsrAttribution">This survey is conducted by an independent company, on behalf of the site you are visiting.</p>
<div style="" class="fsrB">
<div class="fsrAcceptButtonContainer">
Yes, I'll give feedback<span class="hidden-accessible"> (this will launch a new window)</span>
</div>
<div class="fsrDeclineButtonContainer">No, thanks
</div>
</div>
<div class="fsrFooter">
<img src="/_ui/desktop/common/foresee/truste.png" alt="TRUSTe verified" class="fsrTruste">
</div>
</div>
</div>
×<span class="hidden-accessible">Click to close.</span>

If this pop-up appears randomly then I think using the "protection proxy" design pattern would help most. The purpose of it is to execute a particular piece of code, in our example this:
if browser.div(class: 'fsrDialogs').exists?
browser.a(class: 'fsrCloseBtn').click
end
BEFORE any method on the "subject" ("subject" is the object we wrap inside the Proxy class, in our case it's the browser) is called. The Proxy design pattern is pretty straightforward to implement in Ruby, here's how we'd do it in your particular case:
class WatirProxy
attr_reader :subject
def initialize(browser)
#subject = browser
end
def method_missing(method, *args)
puts "I am executing the code below before calling #{method} with args #{args}"
if subject.div(class: 'fsrDialogs').exists?
subject.a(class: 'fsrCloseBtn').click
end
subject.send(method, *args)
end
end
You can remove the puts below method_missing in production, however, I'd recommend you keep it for now if you're not 100% clear on how the code below works.
Let's try playing with it:
browser = WatirProxy.new(Watir::Browser.new(:chrome)) # you can use ANY method on browser, although it's wrapped in a proxy
browser.goto 'https://google.com'
puts browser.text_field(name: 'q').exists?
Ruby should output:
I am executing the code below before calling goto with args ["https://google.com"]
I am executing the code below before calling text_field with args [{:name=>"q"}]
true # May change if google search box 'name' attribute changed to something other than 'q' in the future
In your specific case, this pop-up is raising errors because the browser didn't expect it, now we make sure there's a check BEFORE ANY method on browser is called. A great book for reading about the Proxy design pattern (and some other useful ones in Ruby) is Design Patterns in Ruby by Russ Olsen.

#browser.link(class: "fsrCloseBtn").click if #browser.h1(class: "hsrHeading").visible?
Something like this should be enough. Obviously, sub whatever you name your WebDriver instance for #browser. This clicks the close link if the dialog is visible and skips this step if the dialog is not there. My syntax might be a little wrong, so double check that. I'm used to wrapping all this in page-object, which would look like:
page_class.close_dialog if page_class.dialog_header_element.visible?

Had same issue with Foresee survey, I got around it by adding
while browser.text.include?("We'd welcome your feedback!") == false do
browser.refresh
sleep 1
end
browser.link(:class => /declineButton/).click
end
to the first step after going to the page. It's not the best option but it deals with the Foresee because once you close the window you get a fsr cookie that prevents the survey from popping up again during that browser session. The "sleep 1" was added so chrome would slow down and look for the Foresee survey. Hope it helps.

Related

Play a sound/notification each time a particular user messages on an existing website

I am a user on a website that has a chat widget - users can chat with an instructor.
Every time the instructor sends a message, I would like to receive an audio notification (and optionally a browser notification would be cool too). It's important that I catch these right away and they're pretty easy to miss.
Note: It is something I will be using every day. I understand it's possible to run code right in the console, but that is a bit ad hoc and relies on me to add it successfully during every chat session.
FYI - The code of each chat message from the instructor looks like this:
<ul ng-class="{'notEducator': 'xyz,shanetech' == undefined, 'notEducator': 'xyz,shanetech' == '', 'notEducator': 0 == - 1, 'educator': 0 >=0, 'me':'xyz' == 'abc', 'notMe':'xyz' != 'abc'}" class="chat ng-scope educator notMe" data-ng-repeat="k in previousMessages track by $index">
<div class="main-msg-container xyz">
<div ng-class="{'hideMsgContainer':'' == '0'}" class="msg-container_5e9871f3e6eee5732cee3a1c">
<strong class="primary-font ng-binding">xyz</strong>
<li class=" clearfix">
<div class="chat-body clearfix">
<div class="header">
<small class="pull-right text-muted ng-binding">
<span class="glyphicon glyphicon-time"></span>16-04-2020 07:55:47
</small>
</div>
<p data-ng-bind-html="k.message | to_trusted" class="edu_message_5e9871f3e6eee5732cee3a1c">msg</p>
</div>
</li>
</div>
</div>
</ul>
One unique feature I notice vs regular user chat messages is the presence of the educator class in the ul tag.
Another differentiator taken from the ng-class attribute:
'notEducator': -1 == - 1, 'educator': -1 >=0 <- Me
notEducator': 0 == - 1, 'educator': 0 >=0 <- Host
Assuming you're trying to run code on a web app that you can't modify the code of, like the Zoom we app, here's a non-intrusive approach:
If you're trying to trigger a browser notification when something changes in the DOM, you can do so using chrome code snippets. I'm guessing you have a container element and you want to trigger a notification when that container node is changed and the last child element has a specific class to signify that it is a message from educator.
To simplify this scenario so it's easier to follow, let's say the container element has a class of messageList and the messages inside of it have a class of either educator or student. So what we want to do, is watch for changes on the messageList node. When a change happens, we want to check if the last child in messageList has a class of educator. If it does, we then trigger a browser notification.
I'm not gonna go into specific codes since the question is relatively vague, but in order to run code in chrome every time you go to a specific web address you can use Chrome code snippets (saves code snippets in browser memory to be run now or at a later time) and MutationObserver (triggers an action when a DOM Node mutates), check out this GoogleDev post as well.
Cheers! 🍻

Are they any syntax highlighting plugins that will allow you to embed an ignorable html element into a snippet?

I am trying to make dynamic code examples for our api that can be constructed from from input html elements.
A paired down example looks like this, I give the user an input to name the device they would like to create.
<input class="observable-input" data-key="deviceName" type="text" value="deviceKey" />
I would then like that input to update code examples (replacing the device name in the example with the one the user inputs).
<code lang="python">
device = { "name": "<span data-observeKey="deviceName">Name</span>" }
client.createDevicewrite(device)
</code>
I have all of the code setup for observing a change in the input and updating the code examples, this works great. All of the syntax highlighters I have looked at, usually chop the snippet up and rerender the example wrapped with its own html (for styling). Is there an option/configurable way to get a syntax highlighter to not strip the these tags, or is there a different approach I should be looking at for preserving the syntax highlighting and still supporting dynamic updates without having to do a full text search of each snippet's rendered tags.
The example output of the pygment (current syntax highlighter I'm using).
<li>
<div class="line">
<span class="n">device</span>
<span class="o">=</span>
<span class="n">{</span>
<span class="s">"name"</span>
<span class="p">:</span>
<span class="s">"Name"</span>
<span class="n">}</span>
</div>
</li>
I decided to just go with a brute force approach, it ended up being decently performant, ill leave my code here if anyone is interested in what I did
https://gist.github.com/selecsosi/5d41dae843b9dea4888f
Since i use backbone, lodash, and jquery as my base app frameworks the gist uses those. I have a manager which will push updates from inputs to spans on the page which I use to dynamically update the code examples

ElasticUI - Triggering search/sort with ng-click

This was taken from a e-mail thread between me and the author. I've moved it from e-mail to SO hoping that it may benefit others. ElasticUI can be found here
My Original Question(s)
I see that search is eui-enabled by querystring.length. We would like to the search and sorting triggered by buttons, rather than the
watch functionality.
It's a bit confusing when the search returns no results. Instead of a no results found message it simply returns the deafualt (all)
results. Is it possible to make the results empty by default, rather
than return all?
Author's Answer
1+2 - this is both possible. In AngularJS, keep in mind what "model"
variable you use and connect to your UI / Directives, something along
the following lines would make sense
<div eui-query="ejs.MatchQuery('textField', querystring)" eui-enabled="querystring.length"> <input type="text" ng-model="querystring_live" />
<input type="button" ng-click="querystring=querystring_live" /> </div>
<div ng-if="!querystring.length"> No query specified </div>
Notice what happens on a click. You could also wrap an ng-if clause
around you're results to only display results when a query has been
specified.
When I include this snippet, the ng-if condition doesn't take (the "No query specified" stays at all times) and after submitting the search, results are blank, even if it's query I'm sure should return results.
Being new to angular, an obvious mistake may go over my head. Is there anything obvious that is missing?
Edit
Found the issue: Forgot to fill in the field with which to run the query against: eui-query="ejs.MatchQuery('post_title', querystring)" ('post_title' being the ES field)
Although it seems like you may have found the answer I think there's still a bug in the "author answer" (me) you posted above. Seems like I fell for the dot-problem in Angular. This should work better:
<div ng-init="qs_model={live:'', after_click:''}">
Debug: {{qs_model | json}}
<h3>Search</h3>
<div eui-query="ejs.MatchQuery('tweet.text', qs_model.after_click)" eui-enabled="qs_model.after_click.length">
<input type="text" ng-model="qs_model.live" />
<input type="button" ng-click="qs_model.after_click=qs_model.live" />
</div>
<div ng-if="!qs_model.after_click.length">No query specified </div>
</div>
It's cleaner to define qs_model in a controller as opposed to ng-init I demoed above.
Also note that even if eui-query is disabled (no querystring specified), ElasticUI will at this moment still do a MatchAll query behind the scenes (you can choose to hide the results using ng-if).

How to auto-translate a section using google translate tools?

This is more like a auto-click link problem. But my problem is this link is generate by google's script.
http://translate.google.com/translate_tools
If you choose "translate a section" , there will be a link generate inside the goog-trans-control class
Original script:
<div class="goog-trans-section">
<div class="goog-trans-control">
</div>
Original Text here.
</div>
Script code after execute (Check Component):
<div class="goog-trans-section">
<div class="goog-trans-control">
<div class="skiptranslate goog-te-sectional-gadget-link" style="">
<div id=":1.gadgetLink">
<a class="goog-te-gadget-link" href="javascript:void(0)">
<span class="goog-te-sectional-gadget-link-text">Translate</span>
</a>
</div>
</div>
</div>
Original Text here.
</div>
How would I auto-click (or execute) the Translate link after this page is totally loaded?
For some reason, jsfiddle is not working with my script, though I still post this for your convenience.
http://jsfiddle.net/Wb7tE/
Really appreciate for your time and help.
Edited:
I tried Google translate API, but there is a limitation of 5000 words at a time.
My translations include whole html with tables and scripts, so it reach the limit with no exception.
I have a similar problem, and I solved it temporally like this
google_initialized = false;
function google_auto_translate()
{
if(google_initialized)
{
$('a.goog-te-gadget-link')[0].click();
}
else if(google.translate)
{
google_initialized = true;
setTimeout(google_auto_translate, 500);
}
else
setTimeout(google_auto_translate, 100);
}
window.onload = google_auto_translate;
but on slower connection, in 50 % of time google doesn't load on time, and script already clicks before loading is done. So if anyone know any other way to do this, via some events or something similar please add it here...
P.S. Don't use Google Translation API it's Deprecated and will be removed till the end of this year.

Should I use template or return full code in jquery AJAX?

I am currently working on a project that lets users post comments with jquery and ajax. So far it is using Json and retunring several items, username, comment text, user photo url, comment ID number and stuff like that, I then need to use some sort of template to make all this data go into the correct div's before adding it all to the screen.
I am new to using javascript so this is a hard task for me. I am now considering the easy route.
Just have my PHP backend script return the whole block of code, div's and everything in place but I am wondering is this a bad idea? More importantly is it a bad idea with json?
Here is an example of a block of code that needs to be added to the screen when a comment is posted
<li class="admin" id="comment-1371">
<div class="photocolumn">
<!-- START Photo block -->
<div class="imageSub" style="width: 100px;">
<img class="male" src="http://cache2.mycrib.net/images/image_group34/0/39/T_653807517aff2b1f5662d865b40d87d527c8eb.jpg" alt="Something" width="100"/>
<div class="blackbg"></div>
<div class="label">JasonDavis</div>
</div>
<!-- END Photo block -->
</div><!-- END photocolumn -->
<div class="commenttext">
<p>02/12/3009</p>
<p>sample text for comment area!</p>
</div>
<!-- END COMMENTTEXT -->
</li>
I would say it depends on the situation/application. For instance I would use json and templating for a flight/hotel etc result screen. Why return 50k's worth of the same markup when a 4k json object will do and will allow for rapid clientside sort/filter. If you dont need quick clientside filtering/sorting then responding with dom fragments is ok. Horses for courses.
I don't see a problem with returning HTML via AJAX. A bonus of this is that you can generate most of the HTML in a view in PHP and still keep things fairly clean.
Tokenizing your data into an object is nice for re-use but can be overkill for a one-off.
Go the easy route, I can see no reasons of going with JSON array.

Categories