From fe46eaf50dea6eedf62306464f0fd4a46f8832b3 Mon Sep 17 00:00:00 2001 From: Matthew Horan Date: Tue, 27 Mar 2012 18:49:57 -0400 Subject: [PATCH] Implement window_handles and window_handle for proper window switching --- lib/capybara/driver/webkit.rb | 11 +++++++++- lib/capybara/driver/webkit/browser.rb | 20 +++++++++++------ spec/driver_spec.rb | 6 +++--- src/Command.h | 1 + src/CommandFactory.cpp | 2 ++ src/GetWindowHandle.cpp | 9 ++++++++ src/GetWindowHandle.h | 11 ++++++++++ src/GetWindowHandles.cpp | 22 +++++++++++++++++++ src/GetWindowHandles.h | 12 +++++++++++ src/WebPage.cpp | 7 ++++++ src/WebPage.h | 2 ++ src/WebPageManager.cpp | 11 +++------- src/WebPageManager.h | 9 +++++--- src/WindowFocus.cpp | 31 ++++++++++++++++----------- src/WindowFocus.h | 7 +++--- src/find_command.h | 2 ++ src/webkit_server.pro | 4 ++++ 17 files changed, 130 insertions(+), 37 deletions(-) create mode 100644 src/GetWindowHandle.cpp create mode 100644 src/GetWindowHandle.h create mode 100644 src/GetWindowHandles.cpp create mode 100644 src/GetWindowHandles.h diff --git a/lib/capybara/driver/webkit.rb b/lib/capybara/driver/webkit.rb index c9a0150..0fc9acf 100644 --- a/lib/capybara/driver/webkit.rb +++ b/lib/capybara/driver/webkit.rb @@ -93,14 +93,23 @@ class Capybara::Driver::Webkit end def within_window(handle) + current_window = window_handle browser.window_focus(handle) begin yield ensure - browser.window_focus + browser.window_focus(current_window) end end + def window_handles + browser.get_window_handles + end + + def window_handle + browser.get_window_handle + end + def wait? true end diff --git a/lib/capybara/driver/webkit/browser.rb b/lib/capybara/driver/webkit/browser.rb index 5be287f..b7deb54 100644 --- a/lib/capybara/driver/webkit/browser.rb +++ b/lib/capybara/driver/webkit/browser.rb @@ -81,14 +81,22 @@ class Capybara::Driver::Webkit command("SetSkipImageLoading", skip_image_loading) end - def window_focus(handle=nil) - if handle - command("WindowFocus", handle) - else - command("WindowFocus") - end + def window_focus(handle) + command("WindowFocus", handle) end + def get_window_handles + JSON.parse(command('GetWindowHandles')) + end + + alias_method :window_handles, :get_window_handles + + def get_window_handle + command('GetWindowHandle') + end + + alias_method :window_handle, :get_window_handle + def command(name, *args) @connection.puts name @connection.puts args.size diff --git a/spec/driver_spec.rb b/spec/driver_spec.rb index 847d647..acb2d4f 100644 --- a/spec/driver_spec.rb +++ b/spec/driver_spec.rb @@ -1576,21 +1576,21 @@ describe Capybara::Driver::Webkit do it "has the expected text in the new window" do subject.visit("/new_window") - subject.within_window(true) do + subject.within_window(subject.window_handles.last) do subject.find("//p").first.text.should == "finished" end end it "waits for the new window to load" do subject.visit("/new_window?sleep=1") - subject.within_window(true) do + subject.within_window(subject.window_handles.last) do lambda { Timeout::timeout(1) { subject.find("//p") } }.should_not raise_error(Timeout::Error) end end it "switches back to the original window" do subject.visit("/new_window") - subject.within_window(true) { } + subject.within_window(subject.window_handles.last) { } subject.find("//p").first.text.should == "bananas" end end diff --git a/src/Command.h b/src/Command.h index 3c81295..4e3c296 100644 --- a/src/Command.h +++ b/src/Command.h @@ -16,6 +16,7 @@ class Command : public QObject { signals: void finished(Response *response); + void windowChanged(WebPage *); protected: WebPage *page(); diff --git a/src/CommandFactory.cpp b/src/CommandFactory.cpp index 59be3ff..7b01d11 100644 --- a/src/CommandFactory.cpp +++ b/src/CommandFactory.cpp @@ -26,6 +26,8 @@ #include "IgnoreSslErrors.h" #include "SetSkipImageLoading.h" #include "WindowFocus.h" +#include "GetWindowHandles.h" +#include "GetWindowHandle.h" CommandFactory::CommandFactory(WebPage *page, QObject *parent) : QObject(parent) { m_page = page; diff --git a/src/GetWindowHandle.cpp b/src/GetWindowHandle.cpp new file mode 100644 index 0000000..87113a7 --- /dev/null +++ b/src/GetWindowHandle.cpp @@ -0,0 +1,9 @@ +#include "GetWindowHandle.h" +#include + +GetWindowHandle::GetWindowHandle(WebPage *page, QStringList &arguments, QObject *parent) : Command(page, arguments, parent) { +} + +void GetWindowHandle::start() { + emit finished(new Response(true, page()->uuid())); +} diff --git a/src/GetWindowHandle.h b/src/GetWindowHandle.h new file mode 100644 index 0000000..8c3b78a --- /dev/null +++ b/src/GetWindowHandle.h @@ -0,0 +1,11 @@ +#include "Command.h" +#include "WebPage.h" + +class GetWindowHandle : public Command { + Q_OBJECT + + public: + GetWindowHandle(WebPage *page, QStringList &arguments, QObject *parent = 0); + virtual void start(); +}; + diff --git a/src/GetWindowHandles.cpp b/src/GetWindowHandles.cpp new file mode 100644 index 0000000..9b8b59a --- /dev/null +++ b/src/GetWindowHandles.cpp @@ -0,0 +1,22 @@ +#include "GetWindowHandles.h" +#include "WebPageManager.h" +#include + +GetWindowHandles::GetWindowHandles(WebPage *page, QStringList &arguments, QObject *parent) : Command(page, arguments, parent) { +} + +void GetWindowHandles::start() { + QListIterator pageIterator = + WebPageManager::getInstance()->iterator(); + + QString handles = "["; + QStringList stringList; + + while (pageIterator.hasNext()) { + stringList.append("\"" + pageIterator.next()->uuid() + "\""); + } + + handles += stringList.join(",") + "]"; + + emit finished(new Response(true, handles)); +} diff --git a/src/GetWindowHandles.h b/src/GetWindowHandles.h new file mode 100644 index 0000000..b73b4d5 --- /dev/null +++ b/src/GetWindowHandles.h @@ -0,0 +1,12 @@ +#include "Command.h" + +class WebPage; + +class GetWindowHandles : public Command { + Q_OBJECT + + public: + GetWindowHandles(WebPage *page, QStringList &arguments, QObject *parent = 0); + virtual void start(); +}; + diff --git a/src/WebPage.cpp b/src/WebPage.cpp index 5257922..62ffa3b 100644 --- a/src/WebPage.cpp +++ b/src/WebPage.cpp @@ -7,6 +7,7 @@ #include #include #include +#include WebPage::WebPage(QObject *parent) : QWebPage(parent) { setForwardUnsupportedContent(true); @@ -27,6 +28,8 @@ WebPage::WebPage(QObject *parent) : QWebPage(parent) { settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, true); WebPageManager::getInstance()->append(this); + + m_uuid = QUuid::createUuid().toString(); } void WebPage::resetWindowSize() { @@ -251,3 +254,7 @@ QWebPage *WebPage::createWindow(WebWindowType type) { Q_UNUSED(type); return new WebPage(this); } + +QString WebPage::uuid() { + return m_uuid; +} diff --git a/src/WebPage.h b/src/WebPage.h index 54e4aa8..5a88dc9 100644 --- a/src/WebPage.h +++ b/src/WebPage.h @@ -23,6 +23,7 @@ class WebPage : public QWebPage { void resetConsoleMessages(); void resetWindowSize(); QWebPage *createWindow(WebWindowType type); + QString uuid(); public slots: bool shouldInterruptJavaScript(); @@ -57,6 +58,7 @@ class WebPage : public QWebPage { QString m_pageHeaders; bool m_ignoreSslErrors; QStringList m_consoleMessages; + QString m_uuid; }; #endif //_WEBPAGE_H diff --git a/src/WebPageManager.cpp b/src/WebPageManager.cpp index e729ee9..edf679b 100644 --- a/src/WebPageManager.cpp +++ b/src/WebPageManager.cpp @@ -3,7 +3,6 @@ WebPageManager *WebPageManager::m_instance = NULL; WebPageManager::WebPageManager() { - webPages = new QList(); } WebPageManager *WebPageManager::getInstance() { @@ -14,14 +13,10 @@ WebPageManager *WebPageManager::getInstance() { } void WebPageManager::append(WebPage *value) { - webPages->append(value); + m_pages.append(value); } -WebPage *WebPageManager::first() { - return (WebPage*) webPages->first(); -} - -WebPage *WebPageManager::last() { - return (WebPage*) webPages->last(); +QListIterator WebPageManager::iterator() { + return QListIterator(m_pages); } diff --git a/src/WebPageManager.h b/src/WebPageManager.h index a1b7613..f93024f 100644 --- a/src/WebPageManager.h +++ b/src/WebPageManager.h @@ -1,3 +1,5 @@ +#ifndef _WEBPAGEMANAGER_H +#define _WEBPAGEMANAGER_H #include "WebPage.h" #include @@ -5,12 +7,13 @@ class WebPageManager { public: static WebPageManager *getInstance(); void append(WebPage *value); - WebPage *first(); - WebPage *last(); + QListIterator iterator(); private: WebPageManager(); - QList *webPages; + QList m_pages; static WebPageManager *m_instance; }; +#endif // _WEBPAGEMANAGER_H + diff --git a/src/WindowFocus.cpp b/src/WindowFocus.cpp index 3406cb1..e9acce6 100644 --- a/src/WindowFocus.cpp +++ b/src/WindowFocus.cpp @@ -7,23 +7,30 @@ WindowFocus::WindowFocus(WebPage *page, QStringList &arguments, QObject *parent) } void WindowFocus::start() { - WebPageManager *manager = WebPageManager::getInstance(); - - switch(arguments().length()) { - case 1: - emit windowChanged(manager->last()); - success(); - break; - default: - emit windowChanged(manager->first()); - success(); - } + focusWindow(arguments()[0]); } void WindowFocus::windowNotFound() { emit finished(new Response(false, QString("Unable to locate window. "))); } -void WindowFocus::success() { +void WindowFocus::success(WebPage *page) { + emit windowChanged(page); emit finished(new Response(true)); } + +void WindowFocus::focusWindow(QString selector) { + QListIterator pageIterator = + WebPageManager::getInstance()->iterator(); + + while (pageIterator.hasNext()) { + WebPage *page = pageIterator.next(); + + if (selector == page->uuid()) { + success(page); + return; + } + } + + windowNotFound(); +} diff --git a/src/WindowFocus.h b/src/WindowFocus.h index d12a184..c229f69 100644 --- a/src/WindowFocus.h +++ b/src/WindowFocus.h @@ -1,4 +1,5 @@ #include "Command.h" +#include "WebPageManager.h" class WebPage; @@ -9,11 +10,9 @@ class WindowFocus : public Command { WindowFocus(WebPage *page, QStringList &arguments, QObject *parent = 0); virtual void start(); - signals: - void windowChanged(WebPage *); - private: - void success(); + void success(WebPage *); void windowNotFound(); + void focusWindow(QString); }; diff --git a/src/find_command.h b/src/find_command.h index 316f955..bd8b993 100644 --- a/src/find_command.h +++ b/src/find_command.h @@ -29,3 +29,5 @@ CHECK_COMMAND(ResizeWindow) CHECK_COMMAND(IgnoreSslErrors) CHECK_COMMAND(SetSkipImageLoading) CHECK_COMMAND(WindowFocus) +CHECK_COMMAND(GetWindowHandles) +CHECK_COMMAND(GetWindowHandle) diff --git a/src/webkit_server.pro b/src/webkit_server.pro index e71f5fd..2cb4704 100644 --- a/src/webkit_server.pro +++ b/src/webkit_server.pro @@ -41,6 +41,8 @@ HEADERS = \ SetSkipImageLoading.h \ WebPageManager.h \ WindowFocus.h \ + GetWindowHandles.h \ + GetWindowHandle.h \ SOURCES = \ IgnoreSslErrors.cpp \ @@ -83,6 +85,8 @@ SOURCES = \ SetSkipImageLoading.cpp \ WebPageManager.cpp \ WindowFocus.cpp \ + GetWindowHandles.cpp \ + GetWindowHandle.cpp \ RESOURCES = webkit_server.qrc QT += network webkit