Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add command to retrieve URL modified by Javascript #212

Closed
wants to merge 1 commit into from

4 participants

@joefiorini

If I use pushState to change the URL Browser#current_url still returns
the URL as it was after the original request. This commit adds a command
for RequestedUrl, which is the QtWebkit method for retrieving a URL
modified by Javascript or a redirect.

@joefiorini joefiorini Add command to retrieve URL modified by Javascript
If I use pushState to change the URL Browser#current_url still returns
the URL as it was after the original request. This commit adds a command
for RequestedUrl, which is the QtWebkit method for retrieving a URL
modified by Javascript or a redirect.
89f2cf0
@tristandunn

Seems like the current_url and requested_url behavior would make more sense the other way around.

@joefiorini

Completely agree, however it's directly mirroring the QtWebkit API (http://doc.qt.nokia.com/latest/qwebframe.html#requestedUrl-prop). I prefer that transparency over changing the language set in place by the Qt authors.

@joefiorini

Although thinking more about it, maybe current_url could become requested_url and we could implement url to return QWebFrame#url (which current_url currently uses). Thoughts?

@halogenandtoast halogenandtoast commented on the diff
src/webkit_server.pro
@@ -33,6 +34,11 @@ HEADERS = \
SetProxy.h \
SOURCES = \
+<<<<<<< HEAD
+=======
+ RequestedUrl.cpp \
+ ConsoleMessages.cpp \
+>>>>>>> 3d0768c... Add command to retrieve URL modified by Javascript
@halogenandtoast Owner

You left in this merge conflict.

Agh! Thanks for catching that. I'll fix and push today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@halogenandtoast

Merged your branch without the merge conflict into master.

@marcisme

Perhaps I'm missing something, but doesn't this leave capybara-webkit inconsistent with other Capybara drivers? Personally I have some request specs that assert "current_path.should == blah" that fail with this driver because of the presence of url fragments that do not exist with say the Selenium driver.

I'm not entirely convinced this shouldn't be viewed as some kind of QtWebKit bug, as if you run history.replaceState in other WebKit-based browsers (Safari & Chrome), the URL in the address bar changes, while in QtWeb, which appears to be built with QtWebKit, it does not.

@halogenandtoast

@marcisme right now current_path will return the paths sans fragments. current_url will return the original url with fragments and requested_url will return the current url as set by javascript.

For example if I visit "/?foo=bar#baz and have a javascript call window.history.pushState('', '', '/qux') on the page: current_path == "/" and current_url == "http://myhost/?foo=bar#baz" and requested_url == "/qux". However when Selenium runs the same test it will spit out current_path == "/qux" and current_url = "http://myhost/qux" so you may be right.

For now I'm going to leave this pull request in, but I'm open to more discussion about these methods and how best to handle them.

@tristandunn

I still don't think it makes sense for current_url to return the requested URL and requested_url to return the original URL. The case for following QtWebkit API doesn't make sense to me either, since you don't need to know anything about QtWebkit to use capybara-webkit, it's a Capybara driver.

Edit: I may have confused myself here. Refer to my original comment if I mistyped.

@halogenandtoast

@tristandunn I think this discussion needs to boil down to the actual values these methods should return. For example:

If visiting "/?foo=bar#baz" that contains window.history.pushState('', '', '/qux') what should be the values for current_url,current_path, and requested_url.

If I do what selenium is currently doing then current_url and current_path will both end with "/qux"

@marcisme

@halogenandtoast I think the value of current_url is most important.

The current_path method is based on current_url and is implemented in Capybara itself, so it should "just work" if current_url is right.

The requested_url method does not appear to be part of the Capybara API, so I see it as more for internal use to access the corresponding property in QWebFrame.

Simply implementing current_url based on requested_url would do the right thing in the case of pushState/replaceState, but unfortunately it returns the wrong value (original URL) in the case of a redirect.

Here are the values I think current_url should return.

  • QWebFrame->requestedUrl when modified by javascript in the visited page
  • QWebFrame->requestedUrl when modified by javascript via session.execute_script
  • QWebFrame->requestedUrl when modified by javascript via session.evaluate_script
  • QWebFrame->url when not modified by javascript (requestedUrl would be wrong after a redirect)

Let me know if you would prefer an example with literal values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 16, 2011
  1. @joefiorini

    Add command to retrieve URL modified by Javascript

    joefiorini authored
    If I use pushState to change the URL Browser#current_url still returns
    the URL as it was after the original request. This commit adds a command
    for RequestedUrl, which is the QtWebkit method for retrieving a URL
    modified by Javascript or a redirect.
This page is out of date. Refresh to see the latest.
View
4 lib/capybara/driver/webkit.rb
@@ -30,6 +30,10 @@ def current_url
browser.url
end
+ def requested_url
+ browser.requested_url
+ end
+
def visit(path)
browser.visit(url(path))
end
View
4 lib/capybara/driver/webkit/browser.rb
@@ -53,6 +53,10 @@ def url
command("Url")
end
+ def requested_url
+ command("RequestedUrl")
+ end
+
def frame_focus(frame_id_or_index=nil)
if frame_id_or_index.is_a? Fixnum
command("FrameFocus", "", frame_id_or_index.to_s)
View
5 spec/browser_spec.rb
@@ -168,6 +168,11 @@
browser.url.should == @url
end
+ it 'uses URLs changed by javascript' do
+ browser.execute_script "window.history.pushState('', '', '/blah')"
+ browser.requested_url.should == 'http://example.org/blah'
+ end
+
it 'is possible to disable proxy again' do
@proxy_requests.clear
browser.clear_proxy
View
1  src/CommandFactory.cpp
@@ -18,6 +18,7 @@
#include "ClearCookies.h"
#include "GetCookies.h"
#include "SetProxy.h"
+#include "RequestedUrl.h"
CommandFactory::CommandFactory(WebPage *page, QObject *parent) : QObject(parent) {
m_page = page;
View
15 src/RequestedUrl.cpp
@@ -0,0 +1,15 @@
+#include "RequestedUrl.h"
+#include "WebPage.h"
+
+RequestedUrl::RequestedUrl(WebPage *page, QObject *parent) : Command(page, parent) {
+}
+
+void RequestedUrl::start(QStringList &arguments) {
+ Q_UNUSED(arguments);
+
+ QUrl humanUrl = page()->currentFrame()->requestedUrl();
+ QByteArray encodedBytes = humanUrl.toEncoded();
+ QString urlString = QString(encodedBytes);
+ emit finished(new Response(true, urlString));
+}
+
View
12 src/RequestedUrl.h
@@ -0,0 +1,12 @@
+#include "Command.h"
+
+class WebPage;
+
+class RequestedUrl : public Command {
+ Q_OBJECT
+
+ public:
+ RequestedUrl(WebPage *page, QObject *parent = 0);
+ virtual void start(QStringList &arguments);
+};
+
View
1  src/find_command.h
@@ -22,3 +22,4 @@ CHECK_COMMAND(ClearCookies)
CHECK_COMMAND(GetCookies)
CHECK_COMMAND(Headers)
CHECK_COMMAND(SetProxy)
+CHECK_COMMAND(RequestedUrl)
View
6 src/webkit_server.pro
@@ -2,6 +2,7 @@ TEMPLATE = app
TARGET = webkit_server
DESTDIR = .
HEADERS = \
+ RequestedUrl.h \
WebPage.h \
Server.h \
Connection.h \
@@ -33,6 +34,11 @@ HEADERS = \
SetProxy.h \
SOURCES = \
+<<<<<<< HEAD
+=======
+ RequestedUrl.cpp \
+ ConsoleMessages.cpp \
+>>>>>>> 3d0768c... Add command to retrieve URL modified by Javascript
@halogenandtoast Owner

You left in this merge conflict.

Agh! Thanks for catching that. I'll fix and push today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
main.cpp \
WebPage.cpp \
Server.cpp \
Something went wrong with that request. Please try again.