capybara-webkit 0.1.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "capybara-webkit"
3
- s.version = "0.1.7"
4
- s.authors = ["thoughtbot", "Joe Ferris", "Jason Morrison", "Tristan Dunn"]
3
+ s.version = "0.2.0"
4
+ s.authors = ["thoughtbot", "Joe Ferris", "Jason Morrison", "Tristan Dunn",
5
+ "Joshua Clayton", "Yuichi Tateno", "Aaron Gibralter"]
5
6
  s.email = "support@thoughtbot.com"
6
7
  s.files = `git ls-files`.split("\n")
7
8
  s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
@@ -52,8 +52,13 @@ class Capybara::Driver::Webkit
52
52
  raise Capybara::NotSupportedByDriverError
53
53
  end
54
54
 
55
- def within_frame(frame_id)
56
- raise Capybara::NotSupportedByDriverError
55
+ def within_frame(frame_id_or_index)
56
+ browser.frame_focus(frame_id_or_index)
57
+ begin
58
+ yield
59
+ ensure
60
+ browser.frame_focus
61
+ end
57
62
  end
58
63
 
59
64
  def within_window(handle)
@@ -30,6 +30,16 @@ class Capybara::Driver::Webkit
30
30
  command("Url")
31
31
  end
32
32
 
33
+ def frame_focus(frame_id_or_index=nil)
34
+ if frame_id_or_index.is_a? Fixnum
35
+ command("FrameFocus", "", frame_id_or_index.to_s)
36
+ elsif frame_id_or_index
37
+ command("FrameFocus", frame_id_or_index)
38
+ else
39
+ command("FrameFocus")
40
+ end
41
+ end
42
+
33
43
  def command(name, *args)
34
44
  @socket.puts name
35
45
  @socket.puts args.size
data/spec/driver_spec.rb CHANGED
@@ -6,6 +6,104 @@ describe Capybara::Driver::Webkit do
6
6
  before { subject.visit("/hello/world?success=true") }
7
7
  after { subject.reset! }
8
8
 
9
+ context "iframe app" do
10
+ before(:all) do
11
+ @app = lambda do |env|
12
+ params = ::Rack::Utils.parse_query(env['QUERY_STRING'])
13
+ if params["iframe"] == "true"
14
+ # We are in an iframe request.
15
+ p_id = "farewell"
16
+ msg = "goodbye"
17
+ iframe = nil
18
+ else
19
+ # We are not in an iframe request and need to make an iframe!
20
+ p_id = "greeting"
21
+ msg = "hello"
22
+ iframe = "<iframe id=\"f\" src=\"/?iframe=true\"></iframe>"
23
+ end
24
+ body = <<-HTML
25
+ <html>
26
+ <head>
27
+ <style type="text/css">
28
+ #display_none { display: none }
29
+ </style>
30
+ </head>
31
+ <body>
32
+ #{iframe}
33
+ <script type="text/javascript">
34
+ document.write("<p id='#{p_id}'>#{msg}</p>");
35
+ </script>
36
+ </body>
37
+ </html>
38
+ HTML
39
+ [200,
40
+ { 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s },
41
+ [body]]
42
+ end
43
+ end
44
+
45
+ it "finds frames by index" do
46
+ subject.within_frame(0) do
47
+ subject.find("//*[contains(., 'goodbye')]").should_not be_empty
48
+ end
49
+ end
50
+
51
+ it "finds frames by id" do
52
+ subject.within_frame("f") do
53
+ subject.find("//*[contains(., 'goodbye')]").should_not be_empty
54
+ end
55
+ end
56
+
57
+ it "raises error for missing frame by index" do
58
+ expect { subject.within_frame(1) { } }.
59
+ to raise_error(Capybara::Driver::Webkit::WebkitError)
60
+ end
61
+
62
+ it "raise_error for missing frame by id" do
63
+ expect { subject.within_frame("foo") { } }.
64
+ to raise_error(Capybara::Driver::Webkit::WebkitError)
65
+ end
66
+
67
+ it "returns an attribute's value" do
68
+ subject.within_frame("f") do
69
+ subject.find("//p").first["id"].should == "farewell"
70
+ end
71
+ end
72
+
73
+ it "returns a node's text" do
74
+ subject.within_frame("f") do
75
+ subject.find("//p").first.text.should == "goodbye"
76
+ end
77
+ end
78
+
79
+ it "returns the current URL" do
80
+ subject.within_frame("f") do
81
+ port = subject.instance_variable_get("@rack_server").port
82
+ subject.current_url.should == "http://127.0.0.1:#{port}/?iframe=true"
83
+ end
84
+ end
85
+
86
+ it "returns the source code for the page" do
87
+ subject.within_frame("f") do
88
+ subject.source.should =~ %r{<html>.*farewell.*}m
89
+ end
90
+ end
91
+
92
+ it "evaluates Javascript" do
93
+ subject.within_frame("f") do
94
+ result = subject.evaluate_script(%<document.getElementById('farewell').innerText>)
95
+ result.should == "goodbye"
96
+ end
97
+ end
98
+
99
+ it "executes Javascript" do
100
+ subject.within_frame("f") do
101
+ subject.execute_script(%<document.getElementById('farewell').innerHTML = 'yo'>)
102
+ subject.find("//p[contains(., 'yo')]").should_not be_empty
103
+ end
104
+ end
105
+ end
106
+
9
107
  context "hello app" do
10
108
  before(:all) do
11
109
  @app = lambda do |env|
@@ -1,3 +1,5 @@
1
+ # -*- encoding: UTF-8 -*-
2
+
1
3
  require 'spec_helper'
2
4
  require 'capybara-webkit'
3
5
 
@@ -50,18 +52,32 @@ describe Capybara::Session do
50
52
  body = <<-HTML
51
53
  <html><body>
52
54
  <strong>Hello</strong>
55
+ <span>UTF8文字列</span>
56
+ <input type="button" value="ボタン" />
53
57
  </body></html>
54
58
  HTML
55
59
  [200,
56
- { 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s },
60
+ { 'Content-Type' => 'text/html; charset=UTF-8', 'Content-Length' => body.length.to_s },
57
61
  [body]]
58
62
  end
59
63
  end
60
64
 
61
- it "inspects nodes" do
65
+ before do
62
66
  subject.visit("/")
67
+ end
68
+
69
+ it "inspects nodes" do
63
70
  subject.all(:xpath, "//strong").first.inspect.should include("strong")
64
71
  end
72
+
73
+ it "can read utf8 string" do
74
+ utf8str = subject.all(:xpath, "//span").first.text
75
+ utf8str.should eq('UTF8文字列')
76
+ end
77
+
78
+ it "can click utf8 string" do
79
+ subject.click_button('ボタン')
80
+ end
65
81
  end
66
82
  end
67
83
 
data/src/Connection.cpp CHANGED
@@ -9,6 +9,7 @@
9
9
  #include "Source.h"
10
10
  #include "Evaluate.h"
11
11
  #include "Execute.h"
12
+ #include "FrameFocus.h"
12
13
 
13
14
  #include <QTcpSocket>
14
15
  #include <iostream>
@@ -69,7 +70,7 @@ void Connection::processArgument(const char *data) {
69
70
  } else if (m_expectingDataSize == -1) {
70
71
  m_expectingDataSize = QString(data).toInt();
71
72
  } else {
72
- m_arguments.append(data);
73
+ m_arguments.append(QString::fromUtf8(data));
73
74
  }
74
75
 
75
76
  if (m_arguments.length() == m_argumentsExpected) {
@@ -123,8 +124,9 @@ void Connection::writeResponse(bool success, QString &response) {
123
124
  else
124
125
  m_socket->write("failure\n");
125
126
 
126
- QString responseLength = QString::number(response.size()) + "\n";
127
+ QByteArray response_utf8 = response.toUtf8();
128
+ QString responseLength = QString::number(response_utf8.size()) + "\n";
127
129
  m_socket->write(responseLength.toAscii());
128
- m_socket->write(response.toAscii());
130
+ m_socket->write(response_utf8);
129
131
  }
130
132
 
data/src/Evaluate.cpp CHANGED
@@ -7,7 +7,7 @@ Evaluate::Evaluate(WebPage *page, QObject *parent) : Command(page, parent) {
7
7
  }
8
8
 
9
9
  void Evaluate::start(QStringList &arguments) {
10
- QVariant result = page()->mainFrame()->evaluateJavaScript(arguments[0]);
10
+ QVariant result = page()->currentFrame()->evaluateJavaScript(arguments[0]);
11
11
  addVariant(result);
12
12
  emit finished(true, m_buffer);
13
13
  }
data/src/Execute.cpp CHANGED
@@ -6,7 +6,7 @@ Execute::Execute(WebPage *page, QObject *parent) : Command(page, parent) {
6
6
 
7
7
  void Execute::start(QStringList &arguments) {
8
8
  QString script = arguments[0] + QString("; 'success'");
9
- QVariant result = page()->mainFrame()->evaluateJavaScript(script);
9
+ QVariant result = page()->currentFrame()->evaluateJavaScript(script);
10
10
  QString response;
11
11
  if (result.isValid()) {
12
12
  emit finished(true, response);
@@ -0,0 +1,69 @@
1
+ #include "FrameFocus.h"
2
+ #include "Command.h"
3
+ #include "WebPage.h"
4
+
5
+ FrameFocus::FrameFocus(WebPage *page, QObject *parent) : Command(page, parent) {
6
+ }
7
+
8
+ void FrameFocus::start(QStringList &arguments) {
9
+ findFrames();
10
+ switch(arguments.length()) {
11
+ case 1:
12
+ focusId(arguments[0]);
13
+ break;
14
+ case 2:
15
+ focusIndex(arguments[1].toInt());
16
+ break;
17
+ default:
18
+ focusParent();
19
+ }
20
+ }
21
+
22
+ void FrameFocus::findFrames() {
23
+ frames = page()->currentFrame()->childFrames();
24
+ }
25
+
26
+ void FrameFocus::focusIndex(int index) {
27
+ if (isFrameAtIndex(index)) {
28
+ frames[index]->setFocus();
29
+ success();
30
+ } else {
31
+ frameNotFound();
32
+ }
33
+ }
34
+
35
+ bool FrameFocus::isFrameAtIndex(int index) {
36
+ return 0 <= index && index < frames.length();
37
+ }
38
+
39
+ void FrameFocus::focusId(QString name) {
40
+ for (int i = 0; i < frames.length(); i++) {
41
+ if (frames[i]->frameName().compare(name) == 0) {
42
+ frames[i]->setFocus();
43
+ success();
44
+ return;
45
+ }
46
+ }
47
+
48
+ frameNotFound();
49
+ }
50
+
51
+ void FrameFocus::focusParent() {
52
+ if (page()->currentFrame()->parentFrame() == 0) {
53
+ QString response = "Already at parent frame.";
54
+ emit finished(false, response);
55
+ } else {
56
+ page()->currentFrame()->parentFrame()->setFocus();
57
+ success();
58
+ }
59
+ }
60
+
61
+ void FrameFocus::frameNotFound() {
62
+ QString response = "Unable to locate frame. ";
63
+ emit finished(false, response);
64
+ }
65
+
66
+ void FrameFocus::success() {
67
+ QString response;
68
+ emit finished(true, response);
69
+ }
data/src/FrameFocus.h ADDED
@@ -0,0 +1,28 @@
1
+ #include "Command.h"
2
+
3
+ class WebPage;
4
+ class QWebFrame;
5
+
6
+ class FrameFocus : public Command {
7
+ Q_OBJECT
8
+
9
+ public:
10
+ FrameFocus(WebPage *page, QObject *parent = 0);
11
+ virtual void start(QStringList &arguments);
12
+
13
+ private:
14
+ void findFrames();
15
+
16
+ void focusParent();
17
+
18
+ void focusIndex(int index);
19
+ bool isFrameAtIndex(int index);
20
+
21
+ void focusId(QString id);
22
+
23
+ void success();
24
+ void frameNotFound();
25
+
26
+ QList<QWebFrame *> frames;
27
+ };
28
+
data/src/Reset.cpp CHANGED
@@ -8,7 +8,7 @@ void Reset::start(QStringList &arguments) {
8
8
  Q_UNUSED(arguments);
9
9
 
10
10
  page()->triggerAction(QWebPage::Stop);
11
- page()->mainFrame()->setHtml("<html><body></body></html>");
11
+ page()->currentFrame()->setHtml("<html><body></body></html>");
12
12
  page()->networkAccessManager()->setCookieJar(new QNetworkCookieJar());
13
13
  QString response = "";
14
14
  emit finished(true, response);
data/src/Source.cpp CHANGED
@@ -7,7 +7,7 @@ Source::Source(WebPage *page, QObject *parent) : Command(page, parent) {
7
7
  void Source::start(QStringList &arguments) {
8
8
  Q_UNUSED(arguments)
9
9
 
10
- QString response = page()->mainFrame()->toHtml();
10
+ QString response = page()->currentFrame()->toHtml();
11
11
 
12
12
  emit finished(true, response);
13
13
  }
data/src/Url.cpp CHANGED
@@ -7,7 +7,7 @@ Url::Url(WebPage *page, QObject *parent) : Command(page, parent) {
7
7
  void Url::start(QStringList &argments) {
8
8
  Q_UNUSED(argments);
9
9
 
10
- QUrl humanUrl = page()->mainFrame()->url();
10
+ QUrl humanUrl = page()->currentFrame()->url();
11
11
  QByteArray encodedBytes = humanUrl.toEncoded();
12
12
  QString response = QString(encodedBytes);
13
13
 
data/src/Visit.cpp CHANGED
@@ -7,7 +7,7 @@ Visit::Visit(WebPage *page, QObject *parent) : Command(page, parent) {
7
7
  }
8
8
 
9
9
  void Visit::start(QStringList &arguments) {
10
- page()->mainFrame()->setUrl(QUrl(arguments[0]));
10
+ page()->currentFrame()->setUrl(QUrl(arguments[0]));
11
11
  }
12
12
 
13
13
  void Visit::loadFinished(bool success) {
data/src/WebPage.cpp CHANGED
@@ -4,8 +4,6 @@
4
4
  #include <iostream>
5
5
 
6
6
  WebPage::WebPage(QObject *parent) : QWebPage(parent) {
7
- connect(mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
8
- this, SLOT(injectJavascriptHelpers()));
9
7
  QResource javascript(":/capybara.js");
10
8
  char * javascriptString = new char[javascript.size() + 1];
11
9
  strcpy(javascriptString, (const char *)javascript.data());
@@ -14,10 +12,18 @@ WebPage::WebPage(QObject *parent) : QWebPage(parent) {
14
12
  m_loading = false;
15
13
  connect(this, SIGNAL(loadStarted()), this, SLOT(loadStarted()));
16
14
  connect(this, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
15
+ connect(this, SIGNAL(frameCreated(QWebFrame *)),
16
+ this, SLOT(frameCreated(QWebFrame *)));
17
+ }
18
+
19
+ void WebPage::frameCreated(QWebFrame * frame) {
20
+ connect(frame, SIGNAL(javaScriptWindowObjectCleared()),
21
+ this, SLOT(injectJavascriptHelpers()));
17
22
  }
18
23
 
19
24
  void WebPage::injectJavascriptHelpers() {
20
- mainFrame()->evaluateJavaScript(m_capybaraJavascript);
25
+ QWebFrame* frame = qobject_cast<QWebFrame *>(QObject::sender());
26
+ frame->evaluateJavaScript(m_capybaraJavascript);
21
27
  }
22
28
 
23
29
  bool WebPage::shouldInterruptJavaScript() {
@@ -28,9 +34,9 @@ QVariant WebPage::invokeCapybaraFunction(const char *name, QStringList &argument
28
34
  QString qname(name);
29
35
  QString objectName("CapybaraInvocation");
30
36
  JavascriptInvocation invocation(qname, arguments);
31
- mainFrame()->addToJavaScriptWindowObject(objectName, &invocation);
37
+ currentFrame()->addToJavaScriptWindowObject(objectName, &invocation);
32
38
  QString javascript = QString("Capybara.invoke()");
33
- return mainFrame()->evaluateJavaScript(javascript);
39
+ return currentFrame()->evaluateJavaScript(javascript);
34
40
  }
35
41
 
36
42
  QVariant WebPage::invokeCapybaraFunction(QString &name, QStringList &arguments) {
@@ -76,6 +82,6 @@ bool WebPage::isLoading() const {
76
82
  }
77
83
 
78
84
  QString WebPage::failureString() {
79
- return QString("Unable to load URL: ") + mainFrame()->url().toString();
85
+ return QString("Unable to load URL: ") + currentFrame()->url().toString();
80
86
  }
81
87
 
data/src/WebPage.h CHANGED
@@ -15,6 +15,7 @@ class WebPage : public QWebPage {
15
15
  void loadStarted();
16
16
  void loadFinished(bool);
17
17
  bool isLoading() const;
18
+ void frameCreated(QWebFrame *);
18
19
 
19
20
  protected:
20
21
  virtual void javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID);
data/src/find_command.h CHANGED
@@ -11,3 +11,4 @@ CHECK_COMMAND(Url)
11
11
  CHECK_COMMAND(Source)
12
12
  CHECK_COMMAND(Evaluate)
13
13
  CHECK_COMMAND(Execute)
14
+ CHECK_COMMAND(FrameFocus)
@@ -1,8 +1,8 @@
1
1
  TEMPLATE = app
2
2
  TARGET = webkit_server
3
3
  DESTDIR = .
4
- HEADERS = WebPage.h Server.h Connection.h Command.h Visit.h Find.h Reset.h Node.h JavascriptInvocation.h Url.h Source.h Evaluate.h Execute.h
5
- SOURCES = main.cpp WebPage.cpp Server.cpp Connection.cpp Command.cpp Visit.cpp Find.cpp Reset.cpp Node.cpp JavascriptInvocation.cpp Url.cpp Source.cpp Evaluate.cpp Execute.cpp
4
+ HEADERS = WebPage.h Server.h Connection.h Command.h Visit.h Find.h Reset.h Node.h JavascriptInvocation.h Url.h Source.h Evaluate.h Execute.h FrameFocus.h
5
+ SOURCES = main.cpp WebPage.cpp Server.cpp Connection.cpp Command.cpp Visit.cpp Find.cpp Reset.cpp Node.cpp JavascriptInvocation.cpp Url.cpp Source.cpp Evaluate.cpp Execute.cpp FrameFocus.cpp
6
6
  RESOURCES = webkit_server.qrc
7
7
  QT += network webkit
8
8
  CONFIG += console
metadata CHANGED
@@ -1,32 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capybara-webkit
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 23
4
5
  prerelease:
5
- version: 0.1.7
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
6
11
  platform: ruby
7
12
  authors:
8
13
  - thoughtbot
9
14
  - Joe Ferris
10
15
  - Jason Morrison
11
16
  - Tristan Dunn
17
+ - Joshua Clayton
18
+ - Yuichi Tateno
19
+ - Aaron Gibralter
12
20
  autorequire:
13
21
  bindir: bin
14
22
  cert_chain: []
15
23
 
16
- date: 2011-04-15 00:00:00 -04:00
24
+ date: 2011-04-20 00:00:00 -04:00
17
25
  default_executable:
18
26
  dependencies:
19
27
  - !ruby/object:Gem::Dependency
20
- name: capybara
28
+ type: :runtime
21
29
  requirement: &id001 !ruby/object:Gem::Requirement
22
30
  none: false
23
31
  requirements:
24
32
  - - ~>
25
33
  - !ruby/object:Gem::Version
34
+ hash: 13
35
+ segments:
36
+ - 0
37
+ - 4
38
+ - 1
26
39
  version: 0.4.1
27
- type: :runtime
28
- prerelease: false
29
40
  version_requirements: *id001
41
+ name: capybara
42
+ prerelease: false
30
43
  description:
31
44
  email: support@thoughtbot.com
32
45
  executables: []
@@ -65,6 +78,8 @@ files:
65
78
  - src/Execute.h
66
79
  - src/Find.cpp
67
80
  - src/Find.h
81
+ - src/FrameFocus.cpp
82
+ - src/FrameFocus.h
68
83
  - src/JavascriptInvocation.cpp
69
84
  - src/JavascriptInvocation.h
70
85
  - src/Node.cpp
@@ -103,7 +118,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
103
118
  requirements:
104
119
  - - ">="
105
120
  - !ruby/object:Gem::Version
106
- hash: 2573501153324218535
121
+ hash: 3
107
122
  segments:
108
123
  - 0
109
124
  version: "0"
@@ -112,11 +127,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
127
  requirements:
113
128
  - - ">="
114
129
  - !ruby/object:Gem::Version
130
+ hash: 3
131
+ segments:
132
+ - 0
115
133
  version: "0"
116
134
  requirements: []
117
135
 
118
136
  rubyforge_project:
119
- rubygems_version: 1.6.2
137
+ rubygems_version: 1.6.1
120
138
  signing_key:
121
139
  specification_version: 3
122
140
  summary: Headless Webkit driver for Capybara