puppeteer-ruby 0.0.23 → 0.29.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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +32 -22
- data/.github/ISSUE_TEMPLATE/bug_report.md +17 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +15 -0
- data/.github/workflows/docs.yml +2 -2
- data/.github/workflows/reviewdog.yml +1 -1
- data/CHANGELOG.md +88 -0
- data/Dockerfile +1 -1
- data/README.md +18 -2
- data/lib/puppeteer.rb +3 -0
- data/lib/puppeteer/aria_query_handler.rb +71 -0
- data/lib/puppeteer/browser.rb +0 -2
- data/lib/puppeteer/concurrent_ruby_utils.rb +6 -3
- data/lib/puppeteer/custom_query_handler.rb +51 -0
- data/lib/puppeteer/define_async_method.rb +15 -6
- data/lib/puppeteer/dom_world.rb +231 -74
- data/lib/puppeteer/element_handle.rb +13 -22
- data/lib/puppeteer/execution_context.rb +12 -0
- data/lib/puppeteer/launcher/chrome.rb +4 -1
- data/lib/puppeteer/page.rb +66 -52
- data/lib/puppeteer/page/screenshot_options.rb +2 -2
- data/lib/puppeteer/page/screenshot_task_queue.rb +13 -0
- data/lib/puppeteer/query_handler_manager.rb +65 -0
- data/lib/puppeteer/remote_object.rb +12 -0
- data/lib/puppeteer/target.rb +2 -4
- data/lib/puppeteer/version.rb +1 -1
- data/lib/puppeteer/wait_task.rb +16 -4
- data/puppeteer-ruby.gemspec +6 -4
- metadata +45 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b852a48cd11f269c3b4eec0a85583b120a5cd1b0bc204e27a6ec0e365aa33dd
|
4
|
+
data.tar.gz: 8864c21fe02f6e3fcbb07c6c009516e91273ecfe0636437bc41015187e9985ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd3cdb6d7b64b0b6f6e2568eb83cad62f36ea45943f0df9cd434c6e30221ccd47b161a0368cbe02cacf4a6a3c6c6ecf293bd1313829d7f02daed5d1d2c5c9f73
|
7
|
+
data.tar.gz: 541c2dffa4c6359dff6c2d9d03e70a039057d554c1ee6509d0574d194f17a6407a968c30153bae850f8c4c0e9fa7ade7beaea2dcc8d136a896e80b22831a436f
|
data/.circleci/config.yml
CHANGED
@@ -1,30 +1,41 @@
|
|
1
1
|
version: 2.1
|
2
|
-
|
3
|
-
|
2
|
+
|
3
|
+
rspec_chrome_job: &rspec_chrome_job
|
4
|
+
steps:
|
5
|
+
- checkout
|
6
|
+
- run:
|
7
|
+
command: gem install bundler:2.2.3 && bundle install
|
8
|
+
- run:
|
9
|
+
name: rspec
|
10
|
+
command: |
|
11
|
+
DEBUG=1 bundle exec rspec --profile 10 \
|
12
|
+
--format RspecJunitFormatter \
|
13
|
+
--out test_results/rspec.xml \
|
14
|
+
--format documentation
|
4
15
|
|
5
16
|
jobs:
|
6
|
-
|
17
|
+
rspec_chrome_ruby2_6:
|
7
18
|
docker:
|
8
19
|
- image: circleci/ruby:2.6.6-buster-node-browsers
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
+
<<: *rspec_chrome_job
|
21
|
+
|
22
|
+
rspec_chrome_ruby2_7:
|
23
|
+
docker:
|
24
|
+
- image: circleci/ruby:2.7.2-buster-node-browsers
|
25
|
+
<<: *rspec_chrome_job
|
26
|
+
|
27
|
+
rspec_chrome_ruby3_0:
|
28
|
+
docker:
|
29
|
+
- image: circleci/ruby:3.0.0-buster-node-browsers
|
30
|
+
<<: *rspec_chrome_job
|
20
31
|
|
21
32
|
rspec_firefox:
|
22
33
|
docker:
|
23
|
-
- image: circleci/ruby:2.
|
24
|
-
executor: ruby/default
|
34
|
+
- image: circleci/ruby:2.7.2-buster-node-browsers
|
25
35
|
steps:
|
26
36
|
- checkout
|
27
|
-
-
|
37
|
+
- run:
|
38
|
+
command: gem install bundler:2.2.3 && bundle install
|
28
39
|
- run:
|
29
40
|
name: install firefox-nightly
|
30
41
|
command: |
|
@@ -43,13 +54,10 @@ jobs:
|
|
43
54
|
deploy:
|
44
55
|
docker:
|
45
56
|
- image: circleci/ruby:2.6.3-stretch-node
|
46
|
-
executor: ruby/default
|
47
57
|
steps:
|
48
58
|
- checkout
|
49
59
|
- run:
|
50
|
-
|
51
|
-
command: bundle -v
|
52
|
-
- ruby/bundle-install
|
60
|
+
command: gem install bundler:2.2.3 && bundle install
|
53
61
|
- run:
|
54
62
|
name: rake build
|
55
63
|
command: rake build
|
@@ -70,7 +78,9 @@ jobs:
|
|
70
78
|
workflows:
|
71
79
|
ci:
|
72
80
|
jobs:
|
73
|
-
-
|
81
|
+
- rspec_chrome_ruby2_6
|
82
|
+
- rspec_chrome_ruby2_7
|
83
|
+
- rspec_chrome_ruby3_0
|
74
84
|
- rspec_firefox
|
75
85
|
rubygems-deploy:
|
76
86
|
jobs:
|
@@ -0,0 +1,17 @@
|
|
1
|
+
---
|
2
|
+
name: Bug report
|
3
|
+
about: Create a report to help us improve
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: ''
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
### Step To Reproduce / Observed behavior
|
11
|
+
|
12
|
+
|
13
|
+
### Expected behavior
|
14
|
+
|
15
|
+
### Environment
|
16
|
+
|
17
|
+
Paste the output of `ruby --version`
|
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
name: Feature request
|
3
|
+
about: Request a new feature for playwright-ruby-client
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: ''
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
### Simple description about the feature
|
11
|
+
|
12
|
+
|
13
|
+
### Usecase / Motivation
|
14
|
+
|
15
|
+
<!-- Describe why the feature helps. -->
|
data/.github/workflows/docs.yml
CHANGED
@@ -16,12 +16,12 @@ jobs:
|
|
16
16
|
- name: Set up Ruby
|
17
17
|
uses: ruby/setup-ruby@v1
|
18
18
|
with:
|
19
|
-
ruby-version: 2.
|
19
|
+
ruby-version: 2.7
|
20
20
|
|
21
21
|
- name: Install dependencies
|
22
22
|
run: |
|
23
23
|
gem uninstall bundler
|
24
|
-
gem install bundler -v
|
24
|
+
gem install bundler -v 2.2.3
|
25
25
|
bundle install
|
26
26
|
|
27
27
|
- name: Deploy Configuration
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
### master [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.29.0...master)]
|
2
|
+
|
3
|
+
* xxx
|
4
|
+
|
5
|
+
### 0.29.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.28.1...0.29.0)]
|
6
|
+
|
7
|
+
New features:
|
8
|
+
|
9
|
+
* Add `AriaQueryHandler`. Now we can use "aria/...." for selectors.
|
10
|
+
|
11
|
+
|
12
|
+
### 0.28.1 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.27...0.28.1)]
|
13
|
+
|
14
|
+
New features:
|
15
|
+
|
16
|
+
* Add `Page#emulate_idle_state`
|
17
|
+
* Change versioning rule.
|
18
|
+
|
19
|
+
### 0.0.27 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.26...0.0.27)]
|
20
|
+
|
21
|
+
New features:
|
22
|
+
|
23
|
+
* Now puppeteer-ruby is Ruby 3.0 compatible!
|
24
|
+
|
25
|
+
### 0.0.26 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.25...0.0.26)]
|
26
|
+
|
27
|
+
Bugfix:
|
28
|
+
|
29
|
+
* Fix `Page#screenshot` working correctly with `quality` parameter.
|
30
|
+
|
31
|
+
### 0.0.25 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.23...0.0.25)]
|
32
|
+
|
33
|
+
New feature:
|
34
|
+
|
35
|
+
* **Cookie** feature: `Page#set_cookie`, `Page#cookies`
|
36
|
+
|
37
|
+
### 0.0.23 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.22...0.0.23)]
|
38
|
+
|
39
|
+
New feature:
|
40
|
+
|
41
|
+
* **GeoLocation** feature
|
42
|
+
* grant/clear permission
|
43
|
+
|
44
|
+
Bugfix/Improvement:
|
45
|
+
|
46
|
+
* Refactoring for events ([#31](https://github.com/YusukeIwaki/puppeteer-ruby/pull/31))
|
47
|
+
* Improve SEND/RECV handling in CDPSession ([#34](https://github.com/YusukeIwaki/puppeteer-ruby/pull/34))
|
48
|
+
|
49
|
+
### 0.0.22 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.21...0.0.22)]
|
50
|
+
|
51
|
+
Bugfix
|
52
|
+
|
53
|
+
* Make `Puppeteer#default_args` to work
|
54
|
+
* Respect Firefox launch options
|
55
|
+
* Respect `default_viewport: nil`
|
56
|
+
|
57
|
+
### 0.0.21 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.20...0.0.21)]
|
58
|
+
|
59
|
+
Bugfix/Improvement:
|
60
|
+
|
61
|
+
* Update DeviceDescriptors (list of emulatable devices)
|
62
|
+
* Fix bug on inputing "(" ([#25](https://github.com/YusukeIwaki/puppeteer-ruby/pull/25))
|
63
|
+
|
64
|
+
### 0.0.20 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.19...0.0.20)]
|
65
|
+
|
66
|
+
New feature
|
67
|
+
|
68
|
+
* Dialog-handling feature
|
69
|
+
|
70
|
+
### 0.0.19 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.18...0.0.19)]
|
71
|
+
|
72
|
+
New feature
|
73
|
+
|
74
|
+
* **Firefox support**
|
75
|
+
|
76
|
+
Bugfix/Improvement
|
77
|
+
|
78
|
+
* Allow `Page#keyboard` with block ([#18](https://github.com/YusukeIwaki/puppeteer-ruby/pull/18))
|
79
|
+
|
80
|
+
### 0.0.18 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.17...0.0.18)]
|
81
|
+
|
82
|
+
New feature
|
83
|
+
|
84
|
+
* **Firefox support**
|
85
|
+
|
86
|
+
Bugfix/Improvement
|
87
|
+
|
88
|
+
* Allow `Page#keyboard` with block ([#18](https://github.com/YusukeIwaki/puppeteer-ruby/pull/18))
|
data/Dockerfile
CHANGED
data/README.md
CHANGED
@@ -1,15 +1,31 @@
|
|
1
1
|
[](https://badge.fury.io/rb/puppeteer-ruby)
|
2
2
|
|
3
|
-
# Puppeteer in Ruby
|
3
|
+
# Puppeteer in Ruby
|
4
4
|
|
5
5
|
A Ruby port of [puppeteer](https://pptr.dev/).
|
6
6
|
|
7
7
|

|
8
8
|
|
9
|
-
REMARK: This Gem
|
9
|
+
REMARK: This Gem covers just a part of Puppeteer APIs. Feedbacks and feature requests are welcome :)
|
10
10
|
|
11
11
|
## Getting Started
|
12
12
|
|
13
|
+
### Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'puppeteer-ruby'
|
19
|
+
```
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install puppeteer-ruby
|
28
|
+
|
13
29
|
### Capture a site
|
14
30
|
|
15
31
|
```ruby
|
data/lib/puppeteer.rb
CHANGED
@@ -19,12 +19,14 @@ require 'puppeteer/event_callbackable'
|
|
19
19
|
require 'puppeteer/if_present'
|
20
20
|
|
21
21
|
# Classes & values.
|
22
|
+
require 'puppeteer/aria_query_handler'
|
22
23
|
require 'puppeteer/browser'
|
23
24
|
require 'puppeteer/browser_context'
|
24
25
|
require 'puppeteer/browser_runner'
|
25
26
|
require 'puppeteer/cdp_session'
|
26
27
|
require 'puppeteer/connection'
|
27
28
|
require 'puppeteer/console_message'
|
29
|
+
require 'puppeteer/custom_query_handler'
|
28
30
|
require 'puppeteer/devices'
|
29
31
|
require 'puppeteer/dialog'
|
30
32
|
require 'puppeteer/dom_world'
|
@@ -41,6 +43,7 @@ require 'puppeteer/lifecycle_watcher'
|
|
41
43
|
require 'puppeteer/mouse'
|
42
44
|
require 'puppeteer/network_manager'
|
43
45
|
require 'puppeteer/page'
|
46
|
+
require 'puppeteer/query_handler_manager'
|
44
47
|
require 'puppeteer/remote_object'
|
45
48
|
require 'puppeteer/request'
|
46
49
|
require 'puppeteer/response'
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class Puppeteer::AriaQueryHandler
|
2
|
+
private def normalize(value)
|
3
|
+
value.gsub(/ +/, ' ').strip
|
4
|
+
end
|
5
|
+
|
6
|
+
# @param selector [String]
|
7
|
+
private def parse_aria_selector(selector)
|
8
|
+
known_attributes = %w(name role)
|
9
|
+
query_options = {}
|
10
|
+
attribute_regexp = /\[\s*(?<attribute>\w+)\s*=\s*"(?<value>\\.|[^"\\]*)"\s*\]/
|
11
|
+
default_name = selector.gsub(attribute_regexp) do
|
12
|
+
attribute = $1.strip
|
13
|
+
value = $2
|
14
|
+
unless known_attributes.include?(attribute)
|
15
|
+
raise ArgumentError.new("Unkown aria attribute \"#{attribute}\" in selector")
|
16
|
+
end
|
17
|
+
query_options[attribute.to_sym] = normalize(value)
|
18
|
+
''
|
19
|
+
end
|
20
|
+
|
21
|
+
if default_name.length > 0
|
22
|
+
query_options[:name] ||= normalize(default_name)
|
23
|
+
end
|
24
|
+
|
25
|
+
query_options
|
26
|
+
end
|
27
|
+
|
28
|
+
def query_one(element, selector)
|
29
|
+
context = element.execution_context
|
30
|
+
parse_result = parse_aria_selector(selector)
|
31
|
+
res = element.query_ax_tree(accessible_name: parse_result[:name], role: parse_result[:role])
|
32
|
+
if res.empty?
|
33
|
+
nil
|
34
|
+
else
|
35
|
+
context.adopt_backend_node_id(res.first['backendDOMNodeId'])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil)
|
40
|
+
binding_function = Puppeteer::DOMWorld::BindingFunction.new(
|
41
|
+
name: 'ariaQuerySelector',
|
42
|
+
proc: -> (selector) { query_one(dom_world.send(:document), selector) },
|
43
|
+
)
|
44
|
+
dom_world.send(:wait_for_selector_in_page,
|
45
|
+
'(_, selector) => globalThis.ariaQuerySelector(selector)',
|
46
|
+
selector,
|
47
|
+
visible: visible,
|
48
|
+
hidden: hidden,
|
49
|
+
timeout: timeout,
|
50
|
+
binding_function: binding_function)
|
51
|
+
end
|
52
|
+
|
53
|
+
def query_all(element, selector)
|
54
|
+
context = element.execution_context
|
55
|
+
parse_result = parse_aria_selector(selector)
|
56
|
+
res = element.query_ax_tree(accessible_name: parse_result[:name], role: parse_result[:role])
|
57
|
+
if res.empty?
|
58
|
+
nil
|
59
|
+
else
|
60
|
+
promises = res.map do |ax_node|
|
61
|
+
context.send(:async_adopt_backend_node_id, ax_node['backendDOMNodeId'])
|
62
|
+
end
|
63
|
+
await_all(*promises)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def query_all_array(element, selector)
|
68
|
+
element_handles = query_all(element, selector)
|
69
|
+
element.execution_context.evaluate_handle('(...elements) => elements', *element_handles)
|
70
|
+
end
|
71
|
+
end
|
data/lib/puppeteer/browser.rb
CHANGED
@@ -36,7 +36,6 @@ class Puppeteer::Browser
|
|
36
36
|
@ignore_https_errors = ignore_https_errors
|
37
37
|
@default_viewport = default_viewport
|
38
38
|
@process = process
|
39
|
-
# @screenshot_task_queue = TaskQueue.new
|
40
39
|
@connection = connection
|
41
40
|
@close_callback = close_callback
|
42
41
|
|
@@ -125,7 +124,6 @@ class Puppeteer::Browser
|
|
125
124
|
session_factory: -> { @connection.create_session(target_info) },
|
126
125
|
ignore_https_errors: @ignore_https_errors,
|
127
126
|
default_viewport: @default_viewport,
|
128
|
-
screenshot_task_queue: @screenshot_task_queue,
|
129
127
|
)
|
130
128
|
# assert(!this._targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated');
|
131
129
|
@targets[target_info.target_id] = target
|
@@ -39,9 +39,12 @@ module Puppeteer::ConcurrentRubyUtils
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
def future(&block)
|
43
|
-
Concurrent::Promises.future do
|
44
|
-
block.call
|
42
|
+
def future(*args, &block)
|
43
|
+
Concurrent::Promises.future(*args) do |*block_args|
|
44
|
+
block.call(*block_args)
|
45
|
+
rescue Puppeteer::TimeoutError
|
46
|
+
# suppress error logging
|
47
|
+
raise
|
45
48
|
rescue => err
|
46
49
|
Logger.new($stderr).warn(err)
|
47
50
|
raise err
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Puppeteer::CustomQueryHandler
|
2
|
+
# @param query_one [String] JS function (element: Element | Document, selector: string) => Element | null;
|
3
|
+
# @param query_all [String] JS function (element: Element | Document, selector: string) => Element[] | NodeListOf<Element>;
|
4
|
+
def initialize(query_one: nil, query_all: nil)
|
5
|
+
@query_one = query_one
|
6
|
+
@query_all = query_all
|
7
|
+
end
|
8
|
+
|
9
|
+
def query_one(element, selector)
|
10
|
+
unless @query_one
|
11
|
+
raise NotImplementedError.new("#{self.class}##{__method__} is not implemented.")
|
12
|
+
end
|
13
|
+
|
14
|
+
handle = element.evaluate_handle(@query_one, selector)
|
15
|
+
element = handle.as_element
|
16
|
+
|
17
|
+
if element
|
18
|
+
return element
|
19
|
+
end
|
20
|
+
handle.dispose
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil)
|
25
|
+
unless @query_one
|
26
|
+
raise NotImplementedError.new("#{self.class}##{__method__} is not implemented.")
|
27
|
+
end
|
28
|
+
|
29
|
+
dom_world.send(:wait_for_selector_in_page, @query_one, selector, visible: visible, hidden: hidden, timeout: timeout)
|
30
|
+
end
|
31
|
+
|
32
|
+
def query_all(element, selector)
|
33
|
+
unless @query_all
|
34
|
+
raise NotImplementedError.new("#{self.class}##{__method__} is not implemented.")
|
35
|
+
end
|
36
|
+
|
37
|
+
handles = element.evaluate_handle(@query_all, selector)
|
38
|
+
properties = handles.properties
|
39
|
+
handles.dispose
|
40
|
+
properties.values.map(&:as_element).compact
|
41
|
+
end
|
42
|
+
|
43
|
+
def query_all_array(element, selector)
|
44
|
+
unless @query_all
|
45
|
+
raise NotImplementedError.new("#{self.class}##{__method__} is not implemented.")
|
46
|
+
end
|
47
|
+
|
48
|
+
handles = element.evaluate_handle(@query_all, selector)
|
49
|
+
handles.evaluate_handle('(res) => Array.from(res)')
|
50
|
+
end
|
51
|
+
end
|