Karate UI: Get current browser's URL - ui-automation

Is there a way to get the current URL in the browser's address bar?
Is there any replacement for the following code which does not work, perhaps as mentioned here:
And def url = function() {return window.location.href}
Then print url()

Yes driver.url is what you are looking for: https://github.com/intuit/karate/tree/master/karate-core#driverurl
* match driver.url == 'https://some/url'
Note that to avoid flaky tests, this may be better:
* waitForUrl('https://some/url')

Related

Blocking a response whose body matches some condition

In Fiddler, is there a way to block a response if its body contains a particular word?
If Fiddler is capable of this (possibly through FiddlerScript?), that'd be awesome. Otherwise, if there is another tool that would be better, I'd love to hear about it.
A similar question was asked at What is the best way to block specific URL for testing?, but in my case I don't want to block a URI entirely, but rather only block certain responses from that URI, so that answer is not applicable.
Possible Leads
In FiddlerScript, there appears to be a function called utilFindInResponse, which might be incorporated into OnBeforeResponse like this:
static function OnBeforeResponse(oSession: Session) {
...
if (oSession.utilFindInResponse("WordToBlock", false) > -1){
oSession.responseCode = "404";
}
}
Is this the right way to go about a response-blocker that searches for a particular word?
Yes, you're on the right track, but you should probably ensure that the response in question is HTML (or whatever text format you're expecting) before trying to search it.
static function OnBeforeResponse(oSession: Session) {
if (oSession.oResponse.headers.ExistsAndContains("Content-Type", "text/"))
{
oSession.utilDecodeResponse();
if (oSession.utilFindInResponse("WordToBlock", false) > -1)
{
oSession.responseCode = 404;
oSession.utilSetResponseBody("blocked");
}
}
}
Also, keep in mind that the Streaming option (see Fiddler's toolbar) must be disabled for this code to work as you expect.

Finding broken links with Selenium Remote Driver

I have a site with login and i want to test all links present in that site.
I tried with finding links and click on each to verify with Selenium Remote Driver. But one problem i have is coming back to previous URL and selecting next link. This testing should be recursive.
How can we do this with Selenium Remote Driver?
Following program i tried to check broken links
sub traverse {
my ($self) = #_;
my $links = find_links("//a");
foreach my $index (1..$#$links) {
my $url = $links->[$index]->get_attribute('href');
my $result = $links->[$index]->click();
if ($result) {
traverse();
} else {
print "url is broken $url\n";
}
}
}
I know it's possible to do in C# by checking the returned status code. So you don't actually click on the link, but you are retrieving the header of the response that link is going to give. In this header you can find the HTTP Status Code which you can check to see if the link is giving a valid response or not. Plus you're not leaving the current site!
In C#, a possible method to get the status code will look like this (The checking of the HTTP status code is not included):
private static HttpStatusCode GetStatusCode(string url)
{
var result = default(HttpStatusCode);
var request = WebRequest.Create(url);
request.Method = "HEAD";
HttpWebResponse response;
try {
response = request.GetResponse() as HttpWebResponse;
} catch (WebException) {
return HttpStatusCode.NotFound;
}
if (response != null)
{
result = response.StatusCode;
response.Close();
response.Dispose();
}
return result;
}
Altough this is no Perl code, I hope this helps
Why are you not trying to use some tool, because your site can has over 9000+ urls, it's a lot of time and job, you can use Xenu
Install
In option check use Cookie
Run IE and login thorugh it
Run Xenu
P.S. To test privete part of your site, you must login thorugh IE because Xenu uses only IE cookie
Hmm, I've crossed this bridge before and here is how I solved it. Now I should say that I crossed this bridge before WebDriver :) so this is using WWW::Selenium instead of S:R:D but the concept is the same and still applies.
One of the most tedious tasks, IMO, for a test engineer, is manually verifying links. We can automate most of the process and as long as we have the URL's for where we are expected to land after clicking the link, we can verify this functionality using Selenium and a little bit of JS.
In the below example we first navigate to our desired website and then use Selenium's getEval() function to execute JavaScript that gathers all the links on the page (anchors) and saves them in a comma separated list. This list then gets split and pushed into an array. We then iterate through the list of links in the array clicking on each one and then navigating back to the starting page using go_back.
use strict;
use warnings;
use Time::HiRes qw(sleep);
use Test::WWW::Selenium;
use Test::More "no_plan";
my $sel = Test::WWW::Selenium->new( host => "localhost",
port => 4444,
browser => "*iexplore",
browser_url => "http://www.google.com/");
$sel->open_ok("/", "true");
$sel->set_speed("1000");
my $javascript = "var allLinks = this.browserbot.getCurrentWindow().document.getElementsByTagName('a');
var separator = ',';
var all_links_texts = '';
for(var i = 0; i < allLinks.length; i++) {
all_links_texts = all_links_texts+separator+allLinks[i].href;
}
all_links_texts;";
# Get all of the links in the page and, using a comma to separate each one, add them to the all_links_texts var.
my $link_list = $sel->get_eval($javascript);
my #link_array = split /,/ , $link_list;
my $count = 0;
# Click on each link contained in the array and then go_back
# You can add other logic here like capture and store a screenshot for example
foreach my $link_name (#link_array) {
unless ($link_name =~ /^$/){
$sel->click_ok("css=a[href $= $link_name]");
$sel->wait_for_page_to_load("30000");
print "Clicked Link href: $link_name \n";
$sel->go_back();
$count++;
}
}
print "Clicked $count URL's";
pass;
This can be easily modified to do much more than just click on the links. And of course nothing beats a good pair of eyes on the intended landing pages for the links clicked. Implementing a similar solution in your organization might ease with the manual testing. Here is how I have done it in the past:
Not everything can be automated, but we can certainly make it much easier to review large amounts of links. The above logic can be easily extended to capture a screen shot and add it to a queue of "to be reviewed" images. These properly tagged [by the software] images are what you use in the final phase of the test; visual verification phase.
With this approach you'll know right away if a link is broken or not (assuming you update the logic above to also include this, again this example can be easily extended to include that functionality). As well you will have the capability of visually verifying the screen shots of the intended link landing pages.
I actually have a blog post about this very same issue here: get all links and click on each one
Hope that helps.

Soundmanager2 won't load sound from google translate

I want to speak some text; I can get the audio-file(mp3) from google translate tts if I enter a properly formatted url in the browser.
But if I try to createSound it, I only see a 404-error in firebug.
I use this, but it fails:
soundManager.createSound(
{id:'testsound',
autoLoad:true,
url:'http://translate.google.com/translate_tts?ie=UTF-8&tl=da&q=testing'}
);
I have pre-fetched the fixed voiceprompts with wget, so they are as local mp3-files on the same webserver as the page. But I would like to say a dynamic prompt.
I see this was asked long time ago, but I have come to a similar issue, and I was able to make it work for Chrome and Firefox, but with the Audio Tag.
Here is the demo page I have made
http://jsfiddle.net/royriojas/SE6ET/
here is the code that made the trick for me...
var sayIt;
function createSayIt() {
// Tiny trick to make the request to google actually work!, they deny the request if it comes from a page but somehow it works when the function is inside this iframe!
//create an iframe without setting the src attribute
var iframe = document.createElement('iframe');
// don't know if the attribute is required, but it was on the codepen page where this code worked, so I just put this here. Might be not needed.
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-pointer-lock');
// hide the iframe... cause you know, it is ugly letting iframes be visible around...
iframe.setAttribute('class', 'hidden-iframe')
// append it to the body
document.body.appendChild(iframe);
// obtain a reference to the contentWindow
var v = iframe.contentWindow;
// parse the sayIt function in this contentWindow scope
// Yeah, I know eval is evil, but its evilness fixed this issue...
v.eval("function sayIt(query, language, cb) { var audio = new Audio(); audio.src = 'http://translate.google.com/translate_tts?ie=utf-8&tl=' + language + '&q=' + encodeURIComponent(query); cb && audio.addEventListener('ended', cb); audio.play();}");
// export it under sayIt variable
sayIt = v.sayIt;
}
I guess that I was able to byPass that restriction. They could potentially fix this hack in the future I don't know. I actually hope they don't...
You can also try to use the Text2Speech HTML5 api, but it is still very young...
IE 11 is not working with this hack, some time in the future I might try to fix it
Even though you see this as a 404 error, you're actually running into a cross-domain restriction.
Some of the response headers from that 404 will also give you a clue of what's going on:
X-Content-Type-Options:nosniff
X-XSS-Protection:1; mode=block
So, you won't be able to do this client-side, as Google does not (and probably will never) allow you to do so.
In order to do this dynamic loading of audio, you need to work around this x-domain restriction by setting up a proxy on your own server, which would download whatever file requested by the end-user from Google's servers (via wget or whatever) and spitting whatever data comes from google.
Code I used to reproduce the issue:
soundManager.setup({
url: 'swf',
onready: function() {
soundManager.createSound({
id:'testsound',
autoLoad:true,
url:'http://translate.google.com/translate_tts?ie=UTF-8&tl=da&q=testing'
});
}
});
Your code should look like this:
soundManager.createSound({
id:'testsound',
autoLoad:true,
url:'/audioproxy.php?ie=UTF-8&tl=da&q=testing' // Same domain!
});
Regards and good luck!

Nothing except "None" returned for my Python web.py Facebook app when I turn on "OAuth 2.0 for Canvas"

I am a beginning Facebook app developer, but I'm an experienced developer. I'm using web.py as my web framework, and to make matters a bit worse, I'm new to Python.
I'm running into an issue, where when I try to switch over to using the newer "OAuth 2.0 for Canvas", I simply can't get anything to work. The only thing being returned in my Facebook app is "None".
My motivation for turning on OAuth 2.0 is because it sounds like Facebook is going to force it by July, and I might as well learn it now and now have to rewrite it in a few weeks.
I turned on "OAuth 2.0 for Canvas" in the Advanced Settings, and rewrote my code to look for "signed_request" that is POSTed to my server whenever my test user tries to access my app.
My code is the following (I've removed debugging statements and error checking for brevity):
#!/usr/bin/env python
import base64
import web
import minifb
import urllib
import json
FbApiKey = "AAAAAA"
FbActualSecret = "BBBBBB"
CanvasURL = "http://1.2.3.4/fb/"
RedirectURL="http://apps.facebook.com/CCCCCCCC/"
RegURL = 'https://graph.facebook.com/oauth/authorize?client_id=%s&redirect_uri=%s&type=user_agent&display=page' % (FbApiKey, RedirectURL)
urls = (
'/fb/', 'index',
)
app = web.application(urls, locals())
def authorize():
args = web.input()
signed_request = args['signed_request']
#split the signed_request via the .
strings = signed_request.split('.')
hmac = strings[0]
encoded = strings[1]
#since uslsafe_b64decode requires padding, add the proper padding
numPads = len(encoded) % 4
encoded = encoded + "=" * numPads
unencoded = base64.urlsafe_b64decode(str(encoded))
#convert signedRequest into a dictionary
signedRequest = json.loads(unencoded)
try:
#try to find the oauth_token, if it's not there, then
#redirect to the login page
access_token = signedRequest['oauth_token']
print(access_token)
except:
print("Access token not found, redirect user to login")
redirect = "<script type=\"text/javascript\">\ntop.location.href=\"" +_RegURL + "\";\n</script>"
print(redirect)
return redirect
# Do something on the canvas page
returnString = "<html><body>Hello</body></html>"
print(returnString)
class index:
def GET(self):
authorize()
def POST(self):
authorize()
if __name__ == "__main__":
app.run()
For the time being, I want to concentrate on the case where the user is already logged in, so assume that oauth_token is found.
My question is: Why is my "Hello" not being outputted, and instead all I see is "None"?
It appears that I'm missing something very fundamental, because I swear to you, I've scoured the Internet for solutions, and I've read the Facebook pages on this many times. Similarly, I've found many good blogs and stackoverflow questions that document precisely how to use OAuth 2.0 and signed_request. But the fact that I am getting a proper oauth_token, but my only output is "None" makes me think there is something fundamental that I'm doing incorrectly. I realize that "None" is a special word in python, so maybe that's the cause, but I can't pin down exactly what I'm doing wrong.
When I turn off OAuth 2.0, and revert my code to look for the older POST data, I'm able to easily print stuff to the screen.
Any help on this would be greatly appreciated!
How embarrassing!
In my authorize function, I return a string. But since class index is calling authorize, it needs to be returned from the class, not from authorize. If I return the return from authorize, it works.

zend framework urls and get method

I am developing a website using zend framework.
i have a search form with get method. when the user clicks submit button the query string appears in the url after ? mark. but i want it to be zend like url.
is it possible?
As well as the JS approach you can do a redirect back to the preferred URL you want. I.e. let the form submit via GET, then redirect to the ZF routing style.
This is, however, overkill unless you have a really good reason to want to create neat URLs for your search queries. Generally speaking a search form should send a GET query that can be bookmarked. And there's nothing wrong with ?param=val style parameters in a URL :-)
ZF URLs are a little odd in that they force URL parameters to be part of the main URL. I.e. domain.com/controller/action/param/val/param2/val rather than domain.com/controller/action?param=val&param2=val
This isn't always what you want, but seems to be the way frameworks are going with URL parameters
There is no obvious solution. The form generated by zf will be a standard html one. When submitted from the browser using GET it will result in a request like
/action/specified/in/form?var1=val1&var2=var2
Only solution to get a "zendlike url" (one with / instead of ? or &), would be to hack the form submission using javascript. For example you can listen for onSubmit, abort the submission and instead redirect browser to a translated url. I personally don't believe this solution is worth the added complexity, but it should perform what you're looking for.
After raging against this for a day-and-a-half, and doing my best to figure out the right way to do this fairly simple this, I gave up and did the following. I still can't believe there's not a better way.
The use case that necessitates this is a simple record listing, with a form up top for adding some filters (via GET), maybe some column sorting, and Zend_Paginate thrown in for good measure. I ran into issues using the Url view helper in my pagination partial, but I suspect with even just sorting and a filter-form, Zend_View_Helper_Url would still fall down.
But I digress. My solution was to add a method to my base controller class that merges any raw query-string parameters with the existing zend-style slashy-params, and redirects (but only if necessary). The method can be called in any action that doesn't have to handle POSTs.
Hopefully someone will find this useful. Or even better, find a better way:
/**
* Translate standard URL parameters (?foo=bar&baz=bork) to zend-style
* param (foo/bar/baz/bork). Query-string style
* values override existing route-params.
*/
public function mergeQueryString(){
if ($this->getRequest()->isPost()){
throw new Exception("mergeQueryString only works on GET requests.");
}
$q = $this->getRequest()->getQuery();
$p = $this->getRequest()->getParams();
if (empty($q)) {
//there's nothing to do.
return;
}
$action = $p['action'];
$controller = $p['controller'];
$module = $p['module'];
unset($p['action'],$p['controller'],$p['module']);
$params = array_merge($p,$q);
$this->_helper->getHelper('Redirector')
->setCode(301)
->gotoSimple(
$action,
$controller,
$module,
$params);
}