playwright-ruby-client 0.7.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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.