puppeteer-ruby 0.0.26 → 0.31.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 +4 -1
- data/.github/workflows/windows_check.yml +40 -0
- data/.gitignore +2 -0
- data/CHANGELOG.md +42 -1
- data/Dockerfile +1 -1
- data/README.md +25 -9
- data/lib/puppeteer.rb +3 -0
- data/lib/puppeteer/aria_query_handler.rb +71 -0
- data/lib/puppeteer/browser_runner.rb +1 -1
- data/lib/puppeteer/custom_query_handler.rb +51 -0
- data/lib/puppeteer/define_async_method.rb +15 -6
- data/lib/puppeteer/dom_world.rb +372 -228
- data/lib/puppeteer/element_handle.rb +28 -33
- data/lib/puppeteer/env.rb +4 -0
- data/lib/puppeteer/execution_context.rb +12 -0
- data/lib/puppeteer/frame.rb +31 -24
- data/lib/puppeteer/launcher/base.rb +8 -0
- data/lib/puppeteer/launcher/chrome.rb +4 -1
- data/lib/puppeteer/page.rb +127 -104
- data/lib/puppeteer/query_handler_manager.rb +65 -0
- data/lib/puppeteer/remote_object.rb +12 -0
- data/lib/puppeteer/version.rb +1 -1
- data/lib/puppeteer/wait_task.rb +16 -4
- data/lib/puppeteer/web_socket.rb +2 -0
- data/lib/puppeteer/web_socket_transport.rb +2 -0
- data/puppeteer-ruby.gemspec +5 -4
- metadata +30 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d7c0b6410629e9119a7f298cc3cecdd6e5640a18fdb944dc53e1b47b4c940b0
|
4
|
+
data.tar.gz: 4f9bf8f3e4a21a22cb89fcff1927e420bff86cbdec4a3084dbec32669530f03e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a13874bd8b09ea00a33516f1237e3a91fcfa6b18795af251f3568dc421f026821325c2e89d2e2ee8e8211b03ed1700d8ba15c3a2d01e733ffaa378a1f97b02bc
|
7
|
+
data.tar.gz: 3920af1f121788b36e68ee85194da1fe92335abed949610f726d90bd368d492502da10d935087bbadb386eab13f41f259263dd7777eb42d8988fecc3e1fa83da
|
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
|
@@ -7,9 +7,12 @@ jobs:
|
|
7
7
|
steps:
|
8
8
|
- name: Check out code
|
9
9
|
uses: actions/checkout@v2
|
10
|
+
- uses: ruby/setup-ruby@v1
|
11
|
+
with:
|
12
|
+
ruby-version: 3.0.0
|
10
13
|
- name: rubocop
|
11
14
|
uses: reviewdog/action-rubocop@v1
|
12
15
|
with:
|
13
16
|
github_token: ${{ secrets.github_token }}
|
14
17
|
reporter: github-pr-review
|
15
|
-
rubocop_version:
|
18
|
+
rubocop_version: 1.11.0
|
@@ -0,0 +1,40 @@
|
|
1
|
+
name: Windows check
|
2
|
+
on: [pull_request]
|
3
|
+
jobs:
|
4
|
+
windows_edge_rspec:
|
5
|
+
name: RSpec on Windows / Edge
|
6
|
+
runs-on: windows-latest
|
7
|
+
steps:
|
8
|
+
- name: Check out code
|
9
|
+
uses: actions/checkout@v2
|
10
|
+
- uses: ruby/setup-ruby@v1
|
11
|
+
with:
|
12
|
+
ruby-version: 3.0.0
|
13
|
+
- name: Install dependencies
|
14
|
+
run: |
|
15
|
+
gem uninstall bundler
|
16
|
+
gem install bundler -v 2.2.3
|
17
|
+
bundle install
|
18
|
+
- uses: browser-actions/setup-edge@latest
|
19
|
+
- name: Check example
|
20
|
+
run: bundle exec rspec spec/integration/example_spec.rb
|
21
|
+
env:
|
22
|
+
PUPPETEER_EXECUTABLE_PATH_RSPEC: 'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe'
|
23
|
+
|
24
|
+
windows_chrome_rspec:
|
25
|
+
name: RSpec on Windows / Chrome
|
26
|
+
runs-on: windows-latest
|
27
|
+
steps:
|
28
|
+
- name: Check out code
|
29
|
+
uses: actions/checkout@v2
|
30
|
+
- uses: ruby/setup-ruby@v1
|
31
|
+
with:
|
32
|
+
ruby-version: 3.0.0
|
33
|
+
- name: Install dependencies
|
34
|
+
run: |
|
35
|
+
gem uninstall bundler
|
36
|
+
gem install bundler -v 2.2.3
|
37
|
+
bundle install
|
38
|
+
- uses: browser-actions/setup-chrome@latest
|
39
|
+
- name: Check example
|
40
|
+
run: bundle exec rspec spec/integration/example_spec.rb
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,48 @@
|
|
1
|
-
### master [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0
|
1
|
+
### master [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.31.0...master)]
|
2
2
|
|
3
3
|
* xxx
|
4
4
|
|
5
|
+
### 0.31.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.30.0...0.31.0)]
|
6
|
+
|
7
|
+
New features:
|
8
|
+
|
9
|
+
* Now puppeteer-ruby is compatible with Windows
|
10
|
+
|
11
|
+
Bugfix:
|
12
|
+
|
13
|
+
* Fix `Page#add_script_tag` and `Page#add_style_tag` to work
|
14
|
+
|
15
|
+
### 0.30.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.29.0...0.30.0)]
|
16
|
+
|
17
|
+
New features:
|
18
|
+
|
19
|
+
* S, SS, Seval, SSeval is renamed to query_selector, query_selector_all, eval_on_selector, eval_on_selector_all
|
20
|
+
|
21
|
+
### 0.29.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.28.1...0.29.0)]
|
22
|
+
|
23
|
+
New features:
|
24
|
+
|
25
|
+
* Add `AriaQueryHandler`. Now we can use "aria/...." for selectors.
|
26
|
+
|
27
|
+
### 0.28.1 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.27...0.28.1)]
|
28
|
+
|
29
|
+
New features:
|
30
|
+
|
31
|
+
* Add `Page#emulate_idle_state`
|
32
|
+
* Change versioning rule.
|
33
|
+
|
34
|
+
### 0.0.27 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.26...0.0.27)]
|
35
|
+
|
36
|
+
New features:
|
37
|
+
|
38
|
+
* Now puppeteer-ruby is Ruby 3.0 compatible!
|
39
|
+
|
40
|
+
### 0.0.26 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.25...0.0.26)]
|
41
|
+
|
42
|
+
Bugfix:
|
43
|
+
|
44
|
+
* Fix `Page#screenshot` working correctly with `quality` parameter.
|
45
|
+
|
5
46
|
### 0.0.25 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.23...0.0.25)]
|
6
47
|
|
7
48
|
New feature:
|
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
|
@@ -30,18 +46,18 @@ Puppeteer.launch(headless: false, slow_mo: 50, args: ['--guest', '--window-size=
|
|
30
46
|
page.viewport = Puppeteer::Viewport.new(width: 1280, height: 800)
|
31
47
|
page.goto("https://github.com/", wait_until: 'domcontentloaded')
|
32
48
|
|
33
|
-
form = page.
|
34
|
-
searchInput = form.
|
49
|
+
form = page.query_selector("form.js-site-search-form")
|
50
|
+
searchInput = form.query_selector("input.header-search-input")
|
35
51
|
searchInput.type_text("puppeteer")
|
36
52
|
await_all(
|
37
53
|
page.async_wait_for_navigation,
|
38
54
|
searchInput.async_press("Enter"),
|
39
55
|
)
|
40
56
|
|
41
|
-
list = page.
|
42
|
-
items = list.
|
57
|
+
list = page.query_selector("ul.repo-list")
|
58
|
+
items = list.query_selector_all("div.f4")
|
43
59
|
items.each do |item|
|
44
|
-
title = item.
|
60
|
+
title = item.eval_on_selector("a", "a => a.innerText")
|
45
61
|
puts("==> #{title}")
|
46
62
|
end
|
47
63
|
end
|
@@ -114,7 +130,7 @@ RSpec.describe 'hotel.testplanisphere.dev', type: :feature do
|
|
114
130
|
puppeteer_page = @browser.pages.first
|
115
131
|
puppeteer_page.wait_for_selector('li.nav-item')
|
116
132
|
|
117
|
-
reservation_link = puppeteer_page.
|
133
|
+
reservation_link = puppeteer_page.query_selector_all('li.nav-item')[1]
|
118
134
|
|
119
135
|
await_all(
|
120
136
|
puppeteer_page.async_wait_for_navigation,
|
@@ -131,7 +147,7 @@ RSpec.describe 'hotel.testplanisphere.dev', type: :feature do
|
|
131
147
|
|
132
148
|
# expectation with puppeteer
|
133
149
|
puppeteer_page = @browser.pages.first
|
134
|
-
body_text = puppeteer_page.
|
150
|
+
body_text = puppeteer_page.eval_on_selector('body', '(el) => el.textContent')
|
135
151
|
expect(body_text).to include('宿泊プラン一覧')
|
136
152
|
end
|
137
153
|
```
|
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
|