playwright-ruby-client 0.7.0 → 0.9.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +26 -0
  3. data/documentation/docs/api/browser.md +18 -2
  4. data/documentation/docs/api/browser_context.md +10 -0
  5. data/documentation/docs/api/browser_type.md +1 -0
  6. data/documentation/docs/api/cdp_session.md +41 -1
  7. data/documentation/docs/api/download.md +97 -0
  8. data/documentation/docs/api/element_handle.md +38 -4
  9. data/documentation/docs/api/experimental/android_device.md +1 -0
  10. data/documentation/docs/api/frame.md +78 -17
  11. data/documentation/docs/api/keyboard.md +11 -20
  12. data/documentation/docs/api/locator.md +650 -0
  13. data/documentation/docs/api/page.md +107 -19
  14. data/documentation/docs/api/response.md +16 -0
  15. data/documentation/docs/article/guides/inspector.md +31 -0
  16. data/documentation/docs/article/guides/playwright_on_alpine_linux.md +91 -0
  17. data/documentation/docs/article/guides/rails_integration.md +1 -1
  18. data/documentation/docs/article/guides/semi_automation.md +5 -1
  19. data/documentation/docs/include/api_coverage.md +70 -7
  20. data/lib/playwright.rb +36 -4
  21. data/lib/playwright/channel_owners/artifact.rb +4 -0
  22. data/lib/playwright/channel_owners/browser.rb +5 -0
  23. data/lib/playwright/channel_owners/browser_context.rb +37 -3
  24. data/lib/playwright/channel_owners/cdp_session.rb +19 -0
  25. data/lib/playwright/channel_owners/element_handle.rb +11 -4
  26. data/lib/playwright/channel_owners/frame.rb +103 -34
  27. data/lib/playwright/channel_owners/page.rb +140 -53
  28. data/lib/playwright/channel_owners/response.rb +9 -1
  29. data/lib/playwright/connection.rb +2 -4
  30. data/lib/playwright/{download.rb → download_impl.rb} +5 -1
  31. data/lib/playwright/javascript/expression.rb +5 -4
  32. data/lib/playwright/locator_impl.rb +314 -0
  33. data/lib/playwright/route_handler_entry.rb +3 -2
  34. data/lib/playwright/timeout_settings.rb +4 -4
  35. data/lib/playwright/transport.rb +0 -1
  36. data/lib/playwright/url_matcher.rb +12 -2
  37. data/lib/playwright/version.rb +2 -2
  38. data/lib/playwright/web_socket_client.rb +164 -0
  39. data/lib/playwright/web_socket_transport.rb +104 -0
  40. data/lib/playwright_api/android.rb +6 -6
  41. data/lib/playwright_api/android_device.rb +10 -9
  42. data/lib/playwright_api/browser.rb +17 -11
  43. data/lib/playwright_api/browser_context.rb +14 -9
  44. data/lib/playwright_api/browser_type.rb +8 -7
  45. data/lib/playwright_api/cdp_session.rb +30 -8
  46. data/lib/playwright_api/console_message.rb +6 -6
  47. data/lib/playwright_api/dialog.rb +6 -6
  48. data/lib/playwright_api/download.rb +70 -0
  49. data/lib/playwright_api/element_handle.rb +44 -24
  50. data/lib/playwright_api/frame.rb +100 -49
  51. data/lib/playwright_api/js_handle.rb +6 -6
  52. data/lib/playwright_api/locator.rb +509 -0
  53. data/lib/playwright_api/page.rb +110 -57
  54. data/lib/playwright_api/playwright.rb +6 -6
  55. data/lib/playwright_api/request.rb +6 -6
  56. data/lib/playwright_api/response.rb +15 -10
  57. data/lib/playwright_api/route.rb +6 -6
  58. data/lib/playwright_api/selectors.rb +6 -6
  59. data/lib/playwright_api/web_socket.rb +6 -6
  60. data/lib/playwright_api/worker.rb +6 -6
  61. metadata +15 -5
@@ -104,6 +104,7 @@ def check(
104
104
  force: nil,
105
105
  noWaitAfter: nil,
106
106
  position: nil,
107
+ strict: nil,
107
108
  timeout: nil,
108
109
  trial: nil)
109
110
  ```
@@ -136,6 +137,7 @@ def click(
136
137
  modifiers: nil,
137
138
  noWaitAfter: nil,
138
139
  position: nil,
140
+ strict: nil,
139
141
  timeout: nil,
140
142
  trial: nil)
141
143
  ```
@@ -194,6 +196,7 @@ def dblclick(
194
196
  modifiers: nil,
195
197
  noWaitAfter: nil,
196
198
  position: nil,
199
+ strict: nil,
197
200
  timeout: nil,
198
201
  trial: nil)
199
202
  ```
@@ -217,7 +220,12 @@ Shortcut for main frame's [Frame#dblclick](./frame#dblclick).
217
220
  ## dispatch_event
218
221
 
219
222
  ```
220
- def dispatch_event(selector, type, eventInit: nil, timeout: nil)
223
+ def dispatch_event(
224
+ selector,
225
+ type,
226
+ eventInit: nil,
227
+ strict: nil,
228
+ timeout: nil)
221
229
  ```
222
230
 
223
231
  The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element,
@@ -253,6 +261,21 @@ page.dispatch_event("#source", "dragstart", eventInit: { dataTransfer: data_tran
253
261
 
254
262
 
255
263
 
264
+ ## drag_and_drop
265
+
266
+ ```
267
+ def drag_and_drop(
268
+ source,
269
+ target,
270
+ force: nil,
271
+ noWaitAfter: nil,
272
+ strict: nil,
273
+ timeout: nil,
274
+ trial: nil)
275
+ ```
276
+
277
+
278
+
256
279
  ## emulate_media
257
280
 
258
281
  ```
@@ -287,7 +310,7 @@ page.evaluate("matchMedia('(prefers-color-scheme: no-preference)').matches") # =
287
310
  ## eval_on_selector
288
311
 
289
312
  ```
290
- def eval_on_selector(selector, expression, arg: nil)
313
+ def eval_on_selector(selector, expression, arg: nil, strict: nil)
291
314
  ```
292
315
 
293
316
  The method finds an element matching the specified selector within the page and passes it as a first argument to
@@ -499,7 +522,13 @@ page.click("button")
499
522
  ## fill
500
523
 
501
524
  ```
502
- def fill(selector, value, noWaitAfter: nil, timeout: nil)
525
+ def fill(
526
+ selector,
527
+ value,
528
+ force: nil,
529
+ noWaitAfter: nil,
530
+ strict: nil,
531
+ timeout: nil)
503
532
  ```
504
533
 
505
534
  This method waits for an element matching `selector`, waits for [actionability](https://playwright.dev/python/docs/actionability) checks, focuses the
@@ -518,7 +547,7 @@ Shortcut for main frame's [Frame#fill](./frame#fill).
518
547
  ## focus
519
548
 
520
549
  ```
521
- def focus(selector, timeout: nil)
550
+ def focus(selector, strict: nil, timeout: nil)
522
551
  ```
523
552
 
524
553
  This method fetches an element with `selector` and focuses it. If there's no element matching `selector`, the method
@@ -555,7 +584,7 @@ An array of all frames attached to the page.
555
584
  ## get_attribute
556
585
 
557
586
  ```
558
- def get_attribute(selector, name, timeout: nil)
587
+ def get_attribute(selector, name, strict: nil, timeout: nil)
559
588
  ```
560
589
 
561
590
  Returns element attribute value.
@@ -617,6 +646,7 @@ def hover(
617
646
  force: nil,
618
647
  modifiers: nil,
619
648
  position: nil,
649
+ strict: nil,
620
650
  timeout: nil,
621
651
  trial: nil)
622
652
  ```
@@ -637,7 +667,7 @@ Shortcut for main frame's [Frame#hover](./frame#hover).
637
667
  ## inner_html
638
668
 
639
669
  ```
640
- def inner_html(selector, timeout: nil)
670
+ def inner_html(selector, strict: nil, timeout: nil)
641
671
  ```
642
672
 
643
673
  Returns `element.innerHTML`.
@@ -645,15 +675,23 @@ Returns `element.innerHTML`.
645
675
  ## inner_text
646
676
 
647
677
  ```
648
- def inner_text(selector, timeout: nil)
678
+ def inner_text(selector, strict: nil, timeout: nil)
649
679
  ```
650
680
 
651
681
  Returns `element.innerText`.
652
682
 
683
+ ## input_value
684
+
685
+ ```
686
+ def input_value(selector, strict: nil, timeout: nil)
687
+ ```
688
+
689
+ Returns `input.value` for the selected `<input>` or `<textarea>` element. Throws for non-input elements.
690
+
653
691
  ## checked?
654
692
 
655
693
  ```
656
- def checked?(selector, timeout: nil)
694
+ def checked?(selector, strict: nil, timeout: nil)
657
695
  ```
658
696
 
659
697
  Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
@@ -669,7 +707,7 @@ Indicates that the page has been closed.
669
707
  ## disabled?
670
708
 
671
709
  ```
672
- def disabled?(selector, timeout: nil)
710
+ def disabled?(selector, strict: nil, timeout: nil)
673
711
  ```
674
712
 
675
713
  Returns whether the element is disabled, the opposite of [enabled](https://playwright.dev/python/docs/actionability).
@@ -677,7 +715,7 @@ Returns whether the element is disabled, the opposite of [enabled](https://playw
677
715
  ## editable?
678
716
 
679
717
  ```
680
- def editable?(selector, timeout: nil)
718
+ def editable?(selector, strict: nil, timeout: nil)
681
719
  ```
682
720
 
683
721
  Returns whether the element is [editable](https://playwright.dev/python/docs/actionability).
@@ -685,7 +723,7 @@ Returns whether the element is [editable](https://playwright.dev/python/docs/act
685
723
  ## enabled?
686
724
 
687
725
  ```
688
- def enabled?(selector, timeout: nil)
726
+ def enabled?(selector, strict: nil, timeout: nil)
689
727
  ```
690
728
 
691
729
  Returns whether the element is [enabled](https://playwright.dev/python/docs/actionability).
@@ -693,7 +731,7 @@ Returns whether the element is [enabled](https://playwright.dev/python/docs/acti
693
731
  ## hidden?
694
732
 
695
733
  ```
696
- def hidden?(selector, timeout: nil)
734
+ def hidden?(selector, strict: nil, timeout: nil)
697
735
  ```
698
736
 
699
737
  Returns whether the element is hidden, the opposite of [visible](https://playwright.dev/python/docs/actionability). `selector` that does not
@@ -702,12 +740,26 @@ match any elements is considered hidden.
702
740
  ## visible?
703
741
 
704
742
  ```
705
- def visible?(selector, timeout: nil)
743
+ def visible?(selector, strict: nil, timeout: nil)
706
744
  ```
707
745
 
708
746
  Returns whether the element is [visible](https://playwright.dev/python/docs/actionability). `selector` that does not match any elements is
709
747
  considered not visible.
710
748
 
749
+ ## locator
750
+
751
+ ```
752
+ def locator(selector)
753
+ ```
754
+
755
+ The method returns an element locator that can be used to perform actions on the page. Locator is resolved to the
756
+ element immediately before performing an action, so a series of actions on the same locator can in fact be performed on
757
+ different DOM elements. That would happen if the DOM structure between those actions has changed.
758
+
759
+ Note that locator always implies visibility, so it will always be locating visible elements.
760
+
761
+ Shortcut for main frame's [Frame#locator](./frame#locator).
762
+
711
763
  ## main_frame
712
764
 
713
765
  ```
@@ -724,6 +776,21 @@ def opener
724
776
 
725
777
  Returns the opener for popup pages and `null` for others. If the opener has been closed already the returns `null`.
726
778
 
779
+ ## pause
780
+
781
+ ```
782
+ def pause
783
+ ```
784
+
785
+ Pauses script execution. Playwright will stop executing the script and wait for the user to either press 'Resume' button
786
+ in the page overlay or to call `playwright.resume()` in the DevTools console.
787
+
788
+ User can inspect selectors or perform manual steps while paused. Resume will continue running the original script from
789
+ the place it was paused.
790
+
791
+ > NOTE: This method requires Playwright to be started in a headed mode, with a falsy `headless` value in the
792
+ [BrowserType#launch](./browser_type#launch).
793
+
727
794
  ## pdf
728
795
 
729
796
  ```
@@ -797,6 +864,7 @@ def press(
797
864
  key,
798
865
  delay: nil,
799
866
  noWaitAfter: nil,
867
+ strict: nil,
800
868
  timeout: nil)
801
869
  ```
802
870
 
@@ -834,7 +902,7 @@ page.screenshot(path: "o.png")
834
902
  ## query_selector
835
903
 
836
904
  ```
837
- def query_selector(selector)
905
+ def query_selector(selector, strict: nil)
838
906
  ```
839
907
 
840
908
  The method finds an element matching the specified selector within the page. If no elements match the selector, the
@@ -934,7 +1002,9 @@ def select_option(
934
1002
  index: nil,
935
1003
  value: nil,
936
1004
  label: nil,
1005
+ force: nil,
937
1006
  noWaitAfter: nil,
1007
+ strict: nil,
938
1008
  timeout: nil)
939
1009
  ```
940
1010
 
@@ -1013,7 +1083,12 @@ The extra HTTP headers will be sent with every request the page initiates.
1013
1083
  ## set_input_files
1014
1084
 
1015
1085
  ```
1016
- def set_input_files(selector, files, noWaitAfter: nil, timeout: nil)
1086
+ def set_input_files(
1087
+ selector,
1088
+ files,
1089
+ noWaitAfter: nil,
1090
+ strict: nil,
1091
+ timeout: nil)
1017
1092
  ```
1018
1093
 
1019
1094
  This method expects `selector` to point to an
@@ -1051,6 +1126,7 @@ def tap_point(
1051
1126
  modifiers: nil,
1052
1127
  noWaitAfter: nil,
1053
1128
  position: nil,
1129
+ strict: nil,
1054
1130
  timeout: nil,
1055
1131
  trial: nil)
1056
1132
  ```
@@ -1073,7 +1149,7 @@ Shortcut for main frame's [Frame#tap_point](./frame#tap_point).
1073
1149
  ## text_content
1074
1150
 
1075
1151
  ```
1076
- def text_content(selector, timeout: nil)
1152
+ def text_content(selector, strict: nil, timeout: nil)
1077
1153
  ```
1078
1154
 
1079
1155
  Returns `element.textContent`.
@@ -1094,6 +1170,7 @@ def type(
1094
1170
  text,
1095
1171
  delay: nil,
1096
1172
  noWaitAfter: nil,
1173
+ strict: nil,
1097
1174
  timeout: nil)
1098
1175
  ```
1099
1176
 
@@ -1117,6 +1194,7 @@ def uncheck(
1117
1194
  force: nil,
1118
1195
  noWaitAfter: nil,
1119
1196
  position: nil,
1197
+ strict: nil,
1120
1198
  timeout: nil,
1121
1199
  trial: nil)
1122
1200
  ```
@@ -1185,7 +1263,7 @@ throw an error if the page is closed before the [`event: Page.console`] event is
1185
1263
  def expect_download(predicate: nil, timeout: nil, &block)
1186
1264
  ```
1187
1265
 
1188
- Performs action and waits for a new `Download`. If predicate is provided, it passes `Download` value into the
1266
+ Performs action and waits for a new [Download](./download). If predicate is provided, it passes [Download](./download) value into the
1189
1267
  `predicate` function and waits for `predicate(download)` to return a truthy value. Will throw an error if the page is
1190
1268
  closed before the download event is fired.
1191
1269
 
@@ -1306,7 +1384,7 @@ Performs action and waits for a popup [Page](./page). If predicate is provided,
1306
1384
  def expect_request(urlOrPredicate, timeout: nil, &block)
1307
1385
  ```
1308
1386
 
1309
- Waits for the matching request and returns it. See [waiting for event](https://playwright.dev/python/docs/events) for more details
1387
+ Waits for the matching request and returns it. See [waiting for event](https://playwright.dev/python/docs/events) for more details
1310
1388
  about events.
1311
1389
 
1312
1390
  ```ruby
@@ -1328,6 +1406,16 @@ puts request.headers
1328
1406
 
1329
1407
 
1330
1408
 
1409
+ ## expect_request_finished
1410
+
1411
+ ```
1412
+ def expect_request_finished(predicate: nil, timeout: nil, &block)
1413
+ ```
1414
+
1415
+ Performs action and waits for a [Request](./request) to finish loading. If predicate is provided, it passes [Request](./request) value into
1416
+ the `predicate` function and waits for `predicate(request)` to return a truthy value. Will throw an error if the page is
1417
+ closed before the [`event: Page.requestFinished`] event is fired.
1418
+
1331
1419
  ## expect_response
1332
1420
 
1333
1421
  ```
@@ -1356,7 +1444,7 @@ puts response.body
1356
1444
  ## wait_for_selector
1357
1445
 
1358
1446
  ```
1359
- def wait_for_selector(selector, state: nil, timeout: nil)
1447
+ def wait_for_selector(selector, state: nil, strict: nil, timeout: nil)
1360
1448
  ```
1361
1449
 
1362
1450
  Returns when element specified by selector satisfies `state` option. Returns `null` if waiting for `hidden` or
@@ -64,6 +64,22 @@ def request
64
64
 
65
65
  Returns the matching [Request](./request) object.
66
66
 
67
+ ## security_details
68
+
69
+ ```
70
+ def security_details
71
+ ```
72
+
73
+ Returns SSL and other security information.
74
+
75
+ ## server_addr
76
+
77
+ ```
78
+ def server_addr
79
+ ```
80
+
81
+ Returns the IP address and port of the server.
82
+
67
83
  ## status
68
84
 
69
85
  ```
@@ -0,0 +1,31 @@
1
+ ---
2
+ sidebar_position: 6
3
+ ---
4
+
5
+ # Playwright inspector
6
+
7
+ Playwright provides an useful inspector.
8
+ https://playwright.dev/docs/inspector/
9
+
10
+ ## Overview
11
+
12
+ ```ruby {4,8}
13
+ playwright.chromium.launch(headless: false) do |browser|
14
+ browser.new_context do |context|
15
+ # This method call should be put just after creating BrowserContext.
16
+ context.enable_debug_console!
17
+
18
+ page = context.new_pagè
19
+ page.goto('http://example.com/')
20
+ page.pause
21
+ end
22
+ end
23
+ ```
24
+
25
+ `page.pause` requires Playwright debug session, and it can be enabled by calling `BrowserContext#enable_debug_console!` in advance.
26
+
27
+ Note that since Ruby is not officially supported in Playwright, many limitations exist. We CANNOT
28
+
29
+ * Launch inspector via `PWDEBUG=1`
30
+ * Debug without inspector UI (`PWDEBUG=console` is not working well)
31
+ * Show Ruby code in inspector
@@ -0,0 +1,91 @@
1
+ ---
2
+ sidebar_position: 7
3
+ ---
4
+
5
+ # Playwright on Alpine Linux
6
+
7
+ **NOTE: This feature is EXPERIMENTAL.**
8
+
9
+ Playwright actually requires a permission for shell command execution, and many run-time dependencies for each browser.
10
+
11
+ ![all-in-one](https://user-images.githubusercontent.com/11763113/124934388-9c9c9100-e03f-11eb-8f13-324afac3be2a.png)
12
+
13
+ This all-in-one architecture is reasonable for browser automation in our own computers.
14
+
15
+ However we may have trouble with bringing Playwright into:
16
+
17
+ * Docker
18
+ * Alpine Linux
19
+ * Serverless computing
20
+ * AWS Lambda
21
+ * Google Cloud Functions
22
+ * PaaS
23
+ * Heroku
24
+ * Google App Engine
25
+
26
+ This article introduces a way to separate environments into client (for executing Playwright script) and server (for working with browsers). The main use-case assumes Docker (using Alpine Linux), however the way can be applied also into other use-cases.
27
+
28
+ ## Overview
29
+
30
+ Playwrignt Ruby client is running on Alpine Linux. It just sends/receives JSON messages of Playwright-protocol via WebSocket.
31
+
32
+ Playwright server is running on a container of [official Docker image](https://hub.docker.com/_/microsoft-playwright). It just operates browsers in response to the JSON messages from WebSocket.
33
+
34
+ ![overview](https://user-images.githubusercontent.com/11763113/124934448-ad4d0700-e03f-11eb-942e-b9f3282bb703.png)
35
+
36
+ ## Playwright client
37
+
38
+ Many example uses `Playwright#create`, which internally uses Pipe (stdin/stdout) transport for Playwright-protocol messaging. Instead, **just use `Playwright#connect_to_playwright_server(endpoint)`** for WebSocket transport.
39
+
40
+ ```ruby {3}
41
+ require 'playwright'
42
+
43
+ Playwright.connect_to_playwright_server('wss://example.com:8888/ws') do |playwright|
44
+ playwright.chromium.launch do |browser|
45
+ page = browser.new_page
46
+ page.goto('https://github.com/microsoft/playwright')
47
+ page.screenshot(path: 'github-microsoft-playwright.png')
48
+ end
49
+ end
50
+ ```
51
+
52
+ `wss://example.com:8888/ws` is an example of endpoint URL of the Playwright server. In local development environment, it is typically `"ws://127.0.0.1:#{port}/ws"`.
53
+
54
+ ## Playwright server
55
+
56
+ With the [official Docker image](https://hub.docker.com/_/microsoft-playwright) or in the local development environment with Node.js, just execute `npx playwright install && npx playwright run-server $PORT`. (`$PORT` is a port number of the server)
57
+
58
+ If custom Docker image is preferred, build it as follows:
59
+
60
+ ```Dockerfile
61
+ FROM mcr.microsoft.com/playwright:focal
62
+
63
+ WORKDIR /root
64
+ RUN npm install playwright@1.12.3 && ./node_modules/.bin/playwright install
65
+
66
+ ENV PORT 8888
67
+ CMD ["./node_modules/.bin/playwright", "run-server", "$PORT"]
68
+ ```
69
+
70
+ ## Debugging for connection
71
+
72
+ The client and server are really quiet. This chapter shows how to check if the communication on the WebSocket works well or not.
73
+
74
+ ### Show JSON message on client
75
+
76
+ Just set an environment variable `DEBUG=1`.
77
+
78
+ ```
79
+ DEBUG=1 bundle exec ruby some-automation-with-playwright.rb
80
+ ```
81
+
82
+
83
+ ### Enable verbose logging on server
84
+
85
+ Just set an environment variable `DEBUG=pw:*` or `DEBUG=pw:server`
86
+
87
+ ```
88
+ DEBUG=pw:* npx playwright run-server 8888
89
+ ```
90
+
91
+ See [the official documentation](https://playwright.dev/docs/debug/#verbose-api-logs) for details.