cuprite 0.2.0 → 0.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b3d43410a4b7875e111108b5ef1b53bf07589f833925ea3a9e336d725d99b95
4
- data.tar.gz: 6cea0c2abdef1b5d8f8b6468f2924dac1cbbe5b51f1a4b6ce74bb980a86278ab
3
+ metadata.gz: 2931562eb83d217b25c93d8449b3a5e3c401e2ad64689a7b60c1de9b6abb8b5b
4
+ data.tar.gz: 5701e966d47d9dc45450b47dbb51ed56cd0ba94abe904573a2fc54bc04042210
5
5
  SHA512:
6
- metadata.gz: cd77da4241673d610343e552245f5e0421ee6fe8613cc437bd53d0e8bd3d63be8b422a4abf36fcfedf35d79bbed0b7db5fe26250e5b86f737ac4479c6e02281e
7
- data.tar.gz: cd86413a1b47478e4b0545c28c5ba0ea54a592d889ef0420547d2192bfdac7bece55e9557d88d48cca0720a8d86562dbe281b0988e1234fc55a25d7fc44484c1
6
+ metadata.gz: a348c4d493896c9ba2ba729a83741fd4ff8f52a6bead2486654a6c8ad90408780fec57ea2adcdeb7bc359516e4c768fb67b15fa0bdd862cbb314af4e6c462401
7
+ data.tar.gz: 6639dc96f4da906ce8f69657043e28de6d98f28e5cf0d7a71b8e0a3af7eca2ed94f3b931c539910b46ffabc147e54c8c0a847d8499df2efef30b4863e16ec93f
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Machinio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,180 @@
1
+ # Cuprite - Headless Chrome driver for Capybara #
2
+
3
+ Cuprite is a pure Ruby driver (read as _no_ Java/Selenium/WebDriver/ChromeDriver
4
+ requirement) for [Capybara](https://github.com/teamcapybara/capybara). It allows
5
+ you to run your Capybara tests on a headless [Chrome](https://www.google.com/chrome/)
6
+ or [Chromium](https://www.chromium.org/) browser while the latter is prefered
7
+ for now because we work with tip-of-tree [protocol](https://chromedevtools.github.io/devtools-protocol/).
8
+
9
+ The emphasis was made on raw CDP protocol because Headless Chrome allows you to
10
+ do so many cool things that are barely supported by WebDriver because it should
11
+ have consistent design with other browsers. The design of the driver will be as
12
+ close to [Poltergeist](https://github.com/teampoltergeist/poltergeist) as
13
+ possible but it's not a goal.
14
+
15
+ ## Speed comparison and missing features ##
16
+
17
+ Almost all capybara tests are passing with quite good speed in comparison with
18
+ Poltergest/PhantomJS:
19
+
20
+ ```
21
+ cuprite:
22
+ Finished in 4 minutes 15 seconds (files took 1.23 seconds to load)
23
+ 1533 examples, 0 failures, 148 pending
24
+
25
+ poltergeist:
26
+ Finished in 7 minutes 6 seconds (files took 0.59349 seconds to load)
27
+ 1560 examples, 0 failures, 6 pending
28
+
29
+ selenium headless chrome:
30
+ Finished in 9 minutes 3 seconds (files took 5.98 seconds to load)
31
+ 1445 examples, 0 failures, 3 pending
32
+ ```
33
+
34
+ ## Installation ##
35
+
36
+ ``` ruby
37
+ gem "cuprite"
38
+ ```
39
+ and run `bundle install`.
40
+
41
+ In your test setup add:
42
+
43
+ ``` ruby
44
+ require "capybara/cuprite"
45
+ Capybara.javascript_driver = :cuprite
46
+ ```
47
+
48
+ If you were previously using the `:rack_test` driver, be aware that
49
+ your app will now run in a separate thread and this can have
50
+ consequences for transactional tests. [See the Capybara README for more detail](https://github.com/jnicklas/capybara/blob/master/README.md#transactions-and-database-setup).
51
+
52
+ ## Installing Chromium ##
53
+
54
+ As Chromium is stopped being built as a package for Linux don't even try to
55
+ install it this way because it will either be outdated or unofficial package.
56
+ Both are bad. Download it from official [source](https://www.chromium.org/getting-involved/download-chromium).
57
+
58
+ ## Supported features ##
59
+
60
+ All the mandatory capybara features plus optional ones:
61
+
62
+ * `page.evaluate_script` and `page.execute_script`
63
+ * `page.within_frame`
64
+ * `page.status_code`
65
+ * `page.response_headers`
66
+ * `page.save_screenshot`
67
+ * `page.driver.render_base64(format, options)`
68
+ * window API
69
+ * cookie handling
70
+
71
+ ### Clicking coordinates ###
72
+
73
+ Sometimes its desirable to click a very specific area of the screen. You can
74
+ accomplish this with `page.driver.click(x, y)`, where x and y are the screen
75
+ coordinates.
76
+
77
+ ### Manipulating request headers ###
78
+
79
+ Manipulate HTTP request headers like a boss:
80
+
81
+ ``` ruby
82
+ page.driver.headers # => {}
83
+ page.driver.headers = { "User-Agent" => "Cuprite" }
84
+ page.driver.add_headers("Referer" => "https://example.com")
85
+ page.driver.headers # => { "User-Agent" => "Cuprite", "Referer" => "https://example.com" }
86
+ ```
87
+
88
+ Notice that `headers=` will overwrite already set headers. You should use
89
+ `add_headers` if you want to add a few more. These headers will apply to all
90
+ subsequent HTTP requests (including requests for assets, AJAX, etc). They will
91
+ be automatically cleared at the end of the test.
92
+
93
+ ### Inspecting network traffic ###
94
+
95
+ You can inspect the network traffic (i.e. what resources have been loaded) on
96
+ the current page by calling `page.driver.network_traffic`. This returns an array
97
+ of request objects. A request object has a `response` method containing data
98
+ about the response.
99
+
100
+ Please note that network traffic is not cleared when you visit new page. You can
101
+ manually clear the network traffic by calling `page.driver.clear_network_traffic`
102
+ or `page.driver.reset`
103
+
104
+ ### Manipulating cookies ###
105
+
106
+ The following methods are used to inspect and manipulate cookies:
107
+
108
+ * `page.driver.cookies` - a hash of cookies accessible to the current
109
+ page. The keys are cookie names. The values are `Cookie` objects, with
110
+ the following methods: `name`, `value`, `domain`, `path`, `size`, `secure?`,
111
+ `httponly?`, `session?`, `expires`.
112
+ * `page.driver.set_cookie(name, value, options = {})` - set a cookie.
113
+ The options hash can take the following keys: `:domain`, `:path`,
114
+ `:secure`, `:httponly`, `:expires`. `:expires` should be a
115
+ `Time` object.
116
+ * `page.driver.remove_cookie(name)` - remove a cookie
117
+ * `page.driver.clear_cookies` - clear all cookies
118
+
119
+ ## Customization ##
120
+
121
+ You can customize the way that Capybara sets up Cuprite via the following code
122
+ in your test setup:
123
+
124
+ ``` ruby
125
+ Capybara.register_driver :cuprite do |app|
126
+ Capybara::Cuprite::Driver.new(app, options)
127
+ end
128
+ ```
129
+
130
+ `options` is a hash of options. The following options are supported:
131
+
132
+ * `:browser` (Hash) - Hash of options to be passed to chrome process:
133
+ * `:path` (String) - Path to chrome binary, you can also set ENV variable as
134
+ `BROWSER_PATH=some/path/chrome bundle exec rspec`
135
+ * `:window_size` (Array) - The dimensions of the browser window in which to
136
+ test, expressed as a 2-element array, e.g. [1024, 768]. Default: [1024, 768]
137
+ * `:port` (Integer) - Remote debugging port for headless Chrome
138
+ * `:host` (String) - Remote debugging address for headless Chrome
139
+
140
+ ### URL Blacklisting & Whitelisting ###
141
+ Cuprite supports URL blacklisting, which allows you to prevent scripts from
142
+ running on designated domains:
143
+
144
+ ```ruby
145
+ page.driver.browser.url_blacklist = ['http://www.example.com']
146
+ ```
147
+
148
+ and also URL whitelisting, which allows scripts to only run
149
+ on designated domains:
150
+
151
+ ```ruby
152
+ page.driver.browser.url_whitelist = ['http://www.example.com']
153
+ ```
154
+
155
+ If you are experiencing slower run times, consider creating a URL whitelist of
156
+ domains that are essential or a blacklist of domains that are not essential,
157
+ such as ad networks or analytics, to your testing environment.
158
+
159
+ ## License ##
160
+
161
+ Copyright 2018-2019 Machinio
162
+
163
+ Permission is hereby granted, free of charge, to any person obtaining
164
+ a copy of this software and associated documentation files (the
165
+ "Software"), to deal in the Software without restriction, including
166
+ without limitation the rights to use, copy, modify, merge, publish,
167
+ distribute, sublicense, and/or sell copies of the Software, and to
168
+ permit persons to whom the Software is furnished to do so, subject to
169
+ the following conditions:
170
+
171
+ The above copyright notice and this permission notice shall be
172
+ included in all copies or substantial portions of the Software.
173
+
174
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
175
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
176
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
177
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
178
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
179
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
180
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -6,11 +6,11 @@ Thread.abort_on_exception = true
6
6
  Thread.report_on_exception = true
7
7
 
8
8
  module Capybara::Cuprite
9
- require "cuprite/driver"
10
- require "cuprite/browser"
11
- require "cuprite/node"
12
- require "cuprite/errors"
13
- require "cuprite/cookie"
9
+ require "capybara/cuprite/driver"
10
+ require "capybara/cuprite/browser"
11
+ require "capybara/cuprite/node"
12
+ require "capybara/cuprite/errors"
13
+ require "capybara/cuprite/cookie"
14
14
 
15
15
  class << self
16
16
  def windows?
@@ -2,10 +2,10 @@
2
2
 
3
3
  require "base64"
4
4
  require "forwardable"
5
- require "cuprite/browser/targets"
6
- require "cuprite/browser/process"
7
- require "cuprite/browser/client"
8
- require "cuprite/browser/page"
5
+ require "capybara/cuprite/browser/targets"
6
+ require "capybara/cuprite/browser/process"
7
+ require "capybara/cuprite/browser/client"
8
+ require "capybara/cuprite/browser/page"
9
9
 
10
10
  module Capybara::Cuprite
11
11
  class Browser
@@ -91,7 +91,7 @@ module Capybara::Cuprite
91
91
  end
92
92
 
93
93
  def delete_text(node)
94
- raise NotImplementedError
94
+ evaluate_on(node: node, expr: "_cuprite.deleteText(this)")
95
95
  end
96
96
 
97
97
  def select_file(node, value)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "timeout"
4
- require "cuprite/browser/web_socket"
4
+ require "capybara/cuprite/browser/web_socket"
5
5
 
6
6
  module Capybara::Cuprite
7
7
  class Browser
@@ -59,20 +59,19 @@ module Capybara::Cuprite
59
59
  end
60
60
 
61
61
  def send_keys(node, keys)
62
- # value.each_char do |char|
63
- # # Check puppeteer Input.js and USKeyboardLayout.js
64
- # # also send_keys and modifiers from capybara API and unify all that.
65
- # if /\n/.match?(char)
66
- # command("Input.insertText", text: char)
67
- # # command("Input.dispatchKeyEvent", type: "keyDown", code: "Enter", key: "Enter", text: "\r")
68
- # # command("Input.dispatchKeyEvent", type: "keyUp", code: "Enter", key: "Enter")
69
- # else
70
- # command("Input.dispatchKeyEvent", type: "keyDown", text: char)
71
- # command("Input.dispatchKeyEvent", type: "keyUp", text: char)
72
- # end
73
- # end
74
- # command "send_keys", node, normalize_keys(keys)
75
- raise NotImplementedError
62
+ click(node) if !evaluate_on(node: node, expr: %(_cuprite.containsSelection(this)))
63
+
64
+ keys.first.each_char do |char|
65
+ # Check puppeteer Input.js and USKeyboardLayout.js also send_keys and modifiers from poltergeist.
66
+ if /\n/.match?(char)
67
+ command("Input.insertText", text: char)
68
+ # command("Input.dispatchKeyEvent", type: "keyDown", code: "Enter", key: "Enter", text: "\r")
69
+ # command("Input.dispatchKeyEvent", type: "keyUp", code: "Enter", key: "Enter")
70
+ else
71
+ command("Input.dispatchKeyEvent", type: "keyDown", text: char)
72
+ command("Input.dispatchKeyEvent", type: "keyUp", text: char)
73
+ end
74
+ end
76
75
  end
77
76
 
78
77
  private
@@ -122,8 +122,19 @@ class Cuprite {
122
122
  this.trigger(node, "focus");
123
123
  node.value = "";
124
124
 
125
- if (node.type == "number") {
126
- node.value = value
125
+ if (node.type == "number" || node.type == "date") {
126
+ node.value = value;
127
+ } else if (node.type == "time") {
128
+ node.value = new Date(value).toTimeString().split(" ")[0];
129
+ } else if (node.type == "datetime-local") {
130
+ value = new Date(value);
131
+ let year = value.getFullYear();
132
+ let month = ("0" + (value.getMonth() + 1)).slice(-2);
133
+ let date = ("0" + value.getDate()).slice(-2);
134
+ let hour = ("0" + value.getHours()).slice(-2);
135
+ let min = ("0" + value.getMinutes()).slice(-2);
136
+ let sec = ("0" + value.getSeconds()).slice(-2);
137
+ node.value = `${year}-${month}-${date}T${hour}:${min}:${sec}`;
127
138
  } else {
128
139
  for (let i = 0; i < value.length; i++) {
129
140
  let char = value[i];
@@ -402,6 +413,28 @@ class Cuprite {
402
413
  return node.value;
403
414
  }
404
415
  }
416
+
417
+ deleteText(node) {
418
+ let range = document.createRange();
419
+ range.selectNodeContents(node);
420
+ window.getSelection().removeAllRanges();
421
+ window.getSelection().addRange(range);
422
+ window.getSelection().deleteFromDocument();
423
+ }
424
+
425
+ containsSelection(node) {
426
+ let selectedNode = document.getSelection().focusNode;
427
+
428
+ if (!selectedNode) {
429
+ return false;
430
+ }
431
+
432
+ if (selectedNode.nodeType == 3) {
433
+ selectedNode = selectedNode.parentNode;
434
+ }
435
+
436
+ return node.contains(selectedNode);
437
+ }
405
438
  }
406
439
 
407
440
  window._cuprite = new Cuprite;
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cuprite/browser/dom"
4
- require "cuprite/browser/input"
5
- require "cuprite/browser/runtime"
6
- require "cuprite/browser/frame"
7
- require "cuprite/browser/client"
8
- require "cuprite/network/error"
9
- require "cuprite/network/request"
10
- require "cuprite/network/response"
3
+ require "capybara/cuprite/browser/dom"
4
+ require "capybara/cuprite/browser/input"
5
+ require "capybara/cuprite/browser/runtime"
6
+ require "capybara/cuprite/browser/frame"
7
+ require "capybara/cuprite/browser/client"
8
+ require "capybara/cuprite/network/error"
9
+ require "capybara/cuprite/network/request"
10
+ require "capybara/cuprite/network/response"
11
11
 
12
12
  # RemoteObjectId is from a JavaScript world, and corresponds to any JavaScript
13
13
  # object, including JS wrappers for DOM nodes. There is a way to convert between
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Capybara
4
4
  module Cuprite
5
- VERSION = "0.2.0"
5
+ VERSION = "0.2.1"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cuprite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Vorotilin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-15 00:00:00.000000000 Z
11
+ date: 2019-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
@@ -184,6 +184,8 @@ executables: []
184
184
  extensions: []
185
185
  extra_rdoc_files: []
186
186
  files:
187
+ - LICENSE
188
+ - README.md
187
189
  - lib/capybara/cuprite.rb
188
190
  - lib/capybara/cuprite/browser.rb
189
191
  - lib/capybara/cuprite/browser/client.rb
@@ -211,12 +213,12 @@ metadata: {}
211
213
  post_install_message:
212
214
  rdoc_options: []
213
215
  require_paths:
214
- - lib/capybara
216
+ - lib
215
217
  required_ruby_version: !ruby/object:Gem::Requirement
216
218
  requirements:
217
219
  - - ">="
218
220
  - !ruby/object:Gem::Version
219
- version: '0'
221
+ version: 2.3.0
220
222
  required_rubygems_version: !ruby/object:Gem::Requirement
221
223
  requirements:
222
224
  - - ">="