playwright-ruby-client 0.0.8 → 1.58.1.alpha1

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 (209) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +4 -0
  3. data/CLAUDE/api_generation.md +28 -0
  4. data/CLAUDE/ci_expectations.md +23 -0
  5. data/CLAUDE/gem_release_flow.md +39 -0
  6. data/CLAUDE/past_upgrade_pr_patterns.md +42 -0
  7. data/CLAUDE/playwright_upgrade_workflow.md +35 -0
  8. data/CLAUDE/rspec_debugging.md +30 -0
  9. data/CLAUDE/unimplemented_examples.md +18 -0
  10. data/CLAUDE.md +32 -0
  11. data/CONTRIBUTING.md +5 -0
  12. data/README.md +60 -16
  13. data/documentation/README.md +33 -0
  14. data/documentation/babel.config.js +3 -0
  15. data/documentation/docs/api/api_request.md +7 -0
  16. data/documentation/docs/api/api_request_context.md +298 -0
  17. data/documentation/docs/api/api_response.md +114 -0
  18. data/documentation/docs/api/browser.md +237 -0
  19. data/documentation/docs/api/browser_context.md +503 -0
  20. data/documentation/docs/api/browser_type.md +184 -0
  21. data/documentation/docs/api/cdp_session.md +44 -0
  22. data/documentation/docs/api/clock.md +154 -0
  23. data/documentation/docs/api/console_message.md +85 -0
  24. data/documentation/docs/api/dialog.md +84 -0
  25. data/documentation/docs/api/download.md +111 -0
  26. data/documentation/docs/api/element_handle.md +694 -0
  27. data/documentation/docs/api/experimental/_category_.yml +3 -0
  28. data/documentation/docs/api/experimental/android.md +42 -0
  29. data/documentation/docs/api/experimental/android_device.md +109 -0
  30. data/documentation/docs/api/experimental/android_input.md +43 -0
  31. data/documentation/docs/api/experimental/android_socket.md +7 -0
  32. data/documentation/docs/api/experimental/android_web_view.md +7 -0
  33. data/documentation/docs/api/file_chooser.md +53 -0
  34. data/documentation/docs/api/frame.md +1218 -0
  35. data/documentation/docs/api/frame_locator.md +348 -0
  36. data/documentation/docs/api/js_handle.md +121 -0
  37. data/documentation/docs/api/keyboard.md +170 -0
  38. data/documentation/docs/api/locator.md +1495 -0
  39. data/documentation/docs/api/locator_assertions.md +827 -0
  40. data/documentation/docs/api/mouse.md +86 -0
  41. data/documentation/docs/api/page.md +1946 -0
  42. data/documentation/docs/api/page_assertions.md +65 -0
  43. data/documentation/docs/api/playwright.md +66 -0
  44. data/documentation/docs/api/request.md +255 -0
  45. data/documentation/docs/api/response.md +176 -0
  46. data/documentation/docs/api/route.md +205 -0
  47. data/documentation/docs/api/selectors.md +63 -0
  48. data/documentation/docs/api/touchscreen.md +22 -0
  49. data/documentation/docs/api/tracing.md +129 -0
  50. data/documentation/docs/api/web_socket.md +51 -0
  51. data/documentation/docs/api/worker.md +83 -0
  52. data/documentation/docs/article/api_coverage.mdx +11 -0
  53. data/documentation/docs/article/getting_started.md +161 -0
  54. data/documentation/docs/article/guides/_category_.yml +3 -0
  55. data/documentation/docs/article/guides/download_playwright_driver.md +55 -0
  56. data/documentation/docs/article/guides/inspector.md +31 -0
  57. data/documentation/docs/article/guides/launch_browser.md +121 -0
  58. data/documentation/docs/article/guides/playwright_on_alpine_linux.md +112 -0
  59. data/documentation/docs/article/guides/rails_integration.md +278 -0
  60. data/documentation/docs/article/guides/rails_integration_with_null_driver.md +145 -0
  61. data/documentation/docs/article/guides/recording_video.md +79 -0
  62. data/documentation/docs/article/guides/rspec_integration.md +59 -0
  63. data/documentation/docs/article/guides/semi_automation.md +71 -0
  64. data/documentation/docs/article/guides/use_storage_state.md +78 -0
  65. data/documentation/docs/include/api_coverage.md +671 -0
  66. data/documentation/docusaurus.config.js +114 -0
  67. data/documentation/package.json +39 -0
  68. data/documentation/sidebars.js +15 -0
  69. data/documentation/src/components/HomepageFeatures.js +61 -0
  70. data/documentation/src/components/HomepageFeatures.module.css +13 -0
  71. data/documentation/src/css/custom.css +44 -0
  72. data/documentation/src/pages/index.js +49 -0
  73. data/documentation/src/pages/index.module.css +41 -0
  74. data/documentation/src/pages/markdown-page.md +7 -0
  75. data/documentation/static/.nojekyll +0 -0
  76. data/documentation/static/img/playwright-logo.svg +9 -0
  77. data/documentation/static/img/playwright-ruby-client.png +0 -0
  78. data/documentation/static/img/undraw_dropdown_menu.svg +1 -0
  79. data/documentation/static/img/undraw_web_development.svg +1 -0
  80. data/documentation/static/img/undraw_windows.svg +1 -0
  81. data/documentation/yarn.lock +9005 -0
  82. data/lib/playwright/{input_types/android_input.rb → android_input_impl.rb} +5 -1
  83. data/lib/playwright/api_implementation.rb +18 -0
  84. data/lib/playwright/api_response_impl.rb +77 -0
  85. data/lib/playwright/channel.rb +62 -1
  86. data/lib/playwright/channel_owner.rb +70 -7
  87. data/lib/playwright/channel_owners/android.rb +16 -3
  88. data/lib/playwright/channel_owners/android_device.rb +22 -66
  89. data/lib/playwright/channel_owners/api_request_context.rb +247 -0
  90. data/lib/playwright/channel_owners/artifact.rb +40 -0
  91. data/lib/playwright/channel_owners/binding_call.rb +70 -0
  92. data/lib/playwright/channel_owners/browser.rb +114 -22
  93. data/lib/playwright/channel_owners/browser_context.rb +589 -15
  94. data/lib/playwright/channel_owners/browser_type.rb +90 -1
  95. data/lib/playwright/channel_owners/cdp_session.rb +19 -0
  96. data/lib/playwright/channel_owners/dialog.rb +32 -0
  97. data/lib/playwright/channel_owners/element_handle.rb +107 -43
  98. data/lib/playwright/channel_owners/fetch_request.rb +8 -0
  99. data/lib/playwright/channel_owners/frame.rb +334 -104
  100. data/lib/playwright/channel_owners/js_handle.rb +9 -13
  101. data/lib/playwright/channel_owners/local_utils.rb +82 -0
  102. data/lib/playwright/channel_owners/page.rb +778 -95
  103. data/lib/playwright/channel_owners/playwright.rb +25 -30
  104. data/lib/playwright/channel_owners/request.rb +120 -18
  105. data/lib/playwright/channel_owners/response.rb +113 -0
  106. data/lib/playwright/channel_owners/route.rb +181 -0
  107. data/lib/playwright/channel_owners/stream.rb +30 -0
  108. data/lib/playwright/channel_owners/tracing.rb +117 -0
  109. data/lib/playwright/channel_owners/web_socket.rb +96 -0
  110. data/lib/playwright/channel_owners/worker.rb +46 -0
  111. data/lib/playwright/channel_owners/writable_stream.rb +14 -0
  112. data/lib/playwright/clock_impl.rb +67 -0
  113. data/lib/playwright/connection.rb +111 -63
  114. data/lib/playwright/console_message_impl.rb +29 -0
  115. data/lib/playwright/download_impl.rb +32 -0
  116. data/lib/playwright/errors.rb +42 -5
  117. data/lib/playwright/event_emitter.rb +17 -3
  118. data/lib/playwright/event_emitter_proxy.rb +49 -0
  119. data/lib/playwright/events.rb +10 -5
  120. data/lib/playwright/file_chooser_impl.rb +24 -0
  121. data/lib/playwright/frame_locator_impl.rb +66 -0
  122. data/lib/playwright/har_router.rb +89 -0
  123. data/lib/playwright/http_headers.rb +14 -0
  124. data/lib/playwright/input_files.rb +102 -15
  125. data/lib/playwright/javascript/expression.rb +7 -11
  126. data/lib/playwright/javascript/regex.rb +23 -0
  127. data/lib/playwright/javascript/source_url.rb +16 -0
  128. data/lib/playwright/javascript/value_parser.rb +108 -19
  129. data/lib/playwright/javascript/value_serializer.rb +47 -8
  130. data/lib/playwright/javascript/visitor_info.rb +26 -0
  131. data/lib/playwright/javascript.rb +2 -10
  132. data/lib/playwright/{input_types/keyboard.rb → keyboard_impl.rb} +6 -2
  133. data/lib/playwright/locator_assertions_impl.rb +571 -0
  134. data/lib/playwright/locator_impl.rb +544 -0
  135. data/lib/playwright/locator_utils.rb +136 -0
  136. data/lib/playwright/mouse_impl.rb +57 -0
  137. data/lib/playwright/page_assertions_impl.rb +154 -0
  138. data/lib/playwright/playwright_api.rb +102 -30
  139. data/lib/playwright/raw_headers.rb +61 -0
  140. data/lib/playwright/route_handler.rb +78 -0
  141. data/lib/playwright/select_option_values.rb +34 -13
  142. data/lib/playwright/selectors_impl.rb +45 -0
  143. data/lib/playwright/test.rb +102 -0
  144. data/lib/playwright/timeout_settings.rb +9 -4
  145. data/lib/playwright/touchscreen_impl.rb +14 -0
  146. data/lib/playwright/transport.rb +61 -10
  147. data/lib/playwright/url_matcher.rb +24 -2
  148. data/lib/playwright/utils.rb +48 -13
  149. data/lib/playwright/version.rb +2 -1
  150. data/lib/playwright/video.rb +54 -0
  151. data/lib/playwright/waiter.rb +166 -0
  152. data/lib/playwright/web_socket_client.rb +167 -0
  153. data/lib/playwright/web_socket_transport.rb +116 -0
  154. data/lib/playwright.rb +188 -11
  155. data/lib/playwright_api/android.rb +46 -11
  156. data/lib/playwright_api/android_device.rb +182 -31
  157. data/lib/playwright_api/android_input.rb +22 -13
  158. data/lib/playwright_api/android_socket.rb +18 -0
  159. data/lib/playwright_api/android_web_view.rb +24 -0
  160. data/lib/playwright_api/api_request.rb +26 -0
  161. data/lib/playwright_api/api_request_context.rb +311 -0
  162. data/lib/playwright_api/api_response.rb +92 -0
  163. data/lib/playwright_api/browser.rb +116 -103
  164. data/lib/playwright_api/browser_context.rb +290 -389
  165. data/lib/playwright_api/browser_type.rb +96 -118
  166. data/lib/playwright_api/cdp_session.rb +36 -39
  167. data/lib/playwright_api/clock.rb +121 -0
  168. data/lib/playwright_api/console_message.rb +35 -19
  169. data/lib/playwright_api/dialog.rb +53 -50
  170. data/lib/playwright_api/download.rb +49 -43
  171. data/lib/playwright_api/element_handle.rb +354 -402
  172. data/lib/playwright_api/file_chooser.rb +15 -18
  173. data/lib/playwright_api/frame.rb +703 -603
  174. data/lib/playwright_api/frame_locator.rb +285 -0
  175. data/lib/playwright_api/js_handle.rb +50 -76
  176. data/lib/playwright_api/keyboard.rb +67 -146
  177. data/lib/playwright_api/locator.rb +1304 -0
  178. data/lib/playwright_api/locator_assertions.rb +704 -0
  179. data/lib/playwright_api/mouse.rb +23 -29
  180. data/lib/playwright_api/page.rb +1196 -1176
  181. data/lib/playwright_api/page_assertions.rb +60 -0
  182. data/lib/playwright_api/playwright.rb +54 -122
  183. data/lib/playwright_api/request.rb +112 -74
  184. data/lib/playwright_api/response.rb +92 -20
  185. data/lib/playwright_api/route.rb +152 -62
  186. data/lib/playwright_api/selectors.rb +47 -61
  187. data/lib/playwright_api/touchscreen.rb +8 -2
  188. data/lib/playwright_api/tracing.rb +128 -0
  189. data/lib/playwright_api/web_socket.rb +43 -5
  190. data/lib/playwright_api/worker.rb +74 -34
  191. data/playwright.gemspec +14 -9
  192. data/sig/playwright.rbs +658 -0
  193. metadata +216 -50
  194. data/docs/api_coverage.md +0 -354
  195. data/lib/playwright/channel_owners/chromium_browser.rb +0 -8
  196. data/lib/playwright/channel_owners/chromium_browser_context.rb +0 -8
  197. data/lib/playwright/channel_owners/console_message.rb +0 -21
  198. data/lib/playwright/channel_owners/firefox_browser.rb +0 -8
  199. data/lib/playwright/channel_owners/selectors.rb +0 -4
  200. data/lib/playwright/channel_owners/webkit_browser.rb +0 -8
  201. data/lib/playwright/input_type.rb +0 -19
  202. data/lib/playwright/input_types/mouse.rb +0 -4
  203. data/lib/playwright/input_types/touchscreen.rb +0 -4
  204. data/lib/playwright/javascript/function.rb +0 -67
  205. data/lib/playwright/wait_helper.rb +0 -73
  206. data/lib/playwright_api/accessibility.rb +0 -93
  207. data/lib/playwright_api/binding_call.rb +0 -23
  208. data/lib/playwright_api/chromium_browser_context.rb +0 -57
  209. data/lib/playwright_api/video.rb +0 -24
@@ -1,10 +1,12 @@
1
- require 'date'
1
+ require 'base64'
2
+ require 'time'
2
3
 
3
4
  module Playwright
4
5
  module JavaScript
5
6
  class ValueParser
6
7
  def initialize(hash)
7
8
  @hash = hash
9
+ @refs = {}
8
10
  end
9
11
 
10
12
  # @return [Hash]
@@ -23,26 +25,52 @@ module Playwright
23
25
  return hash[key] if hash.key?(key)
24
26
  end
25
27
 
28
+ if hash.key?('ref')
29
+ return @refs[hash['ref']]
30
+ end
31
+
26
32
  if hash.key?('v')
27
- return
28
- case hash['v']
29
- when 'undefined'
30
- nil
31
- when 'null'
32
- nil
33
- when 'NaN'
34
- Float::NAN
35
- when 'Infinity'
36
- Float::INFINITY
37
- when '-Infinity'
38
- -Float::INFINITY
39
- when '-0'
40
- -0
41
- end
33
+ return case hash['v']
34
+ when 'undefined'
35
+ nil
36
+ when 'null'
37
+ nil
38
+ when 'NaN'
39
+ Float::NAN
40
+ when 'Infinity'
41
+ Float::INFINITY
42
+ when '-Infinity'
43
+ -Float::INFINITY when '-0'
44
+ -0
45
+ end
42
46
  end
43
47
 
44
48
  if hash.key?('d')
45
- return DateTime.parse(hash['d'])
49
+ return Time.parse(hash['d'])
50
+ end
51
+
52
+ if hash.key?('u')
53
+ return URI(hash['u'])
54
+ end
55
+
56
+ if hash.key?('bi')
57
+ return hash['bi'].to_i
58
+ end
59
+
60
+ if hash.key?('e')
61
+ return ::Playwright::Error.new(
62
+ message: hash['e']['m'],
63
+ name: hash['e']['n'],
64
+ stack: hash['e']['s'].split("\n"),
65
+ )
66
+ end
67
+
68
+ if hash.key?('m')
69
+ return parse_hash(hash['m']).to_h
70
+ end
71
+
72
+ if hash.key?('se')
73
+ return Set.new(parse_hash(hash['se']))
46
74
  end
47
75
 
48
76
  if hash.key?('r')
@@ -57,17 +85,78 @@ module Playwright
57
85
  end
58
86
 
59
87
  if hash.key?('a')
60
- return hash['a'].map { |value| parse_hash(value) }
88
+ result = []
89
+ if hash['id']
90
+ @refs[hash['id']] = result
91
+ end
92
+ hash['a'].each { |value| result << parse_hash(value) }
93
+ return result
61
94
  end
62
95
 
63
96
  if hash.key?('o')
64
- return hash['o'].map { |obj| [obj['k'], parse_hash(obj['v'])] }.to_h
97
+ result = {}
98
+ if hash['id']
99
+ @refs[hash['id']] = result
100
+ end
101
+ hash['o'].each { |obj| result[obj['k']] = parse_hash(obj['v']) }
102
+ return result
65
103
  end
66
104
 
67
105
  if hash.key?('h')
68
106
  return @handles[hash['h']]
69
107
  end
70
108
 
109
+ if hash.key?('ta')
110
+ encoded_bytes = hash['ta']['b']
111
+ decoded_bytes = Base64.strict_decode64(encoded_bytes)
112
+ array_type = hash['ta']['k']
113
+
114
+ if array_type == 'i8'
115
+ word_size = 1
116
+ unpack_format = 'c*' # signed char
117
+ elsif array_type == 'ui8' || array_type == 'ui8c'
118
+ word_size = 1
119
+ unpack_format = 'C*' # unsigned char
120
+ elsif array_type == 'i16'
121
+ word_size = 2
122
+ unpack_format = 's<*' # signed short, little-endian
123
+ elsif array_type == 'ui16'
124
+ word_size = 2
125
+ unpack_format = 'S<*' # unsigned short, little-endian
126
+ elsif array_type == 'i32'
127
+ word_size = 4
128
+ unpack_format = 'l<*' # signed long, little-endian
129
+ elsif array_type == 'ui32'
130
+ word_size = 4
131
+ unpack_format = 'L<*' # unsigned long, little-endian
132
+ elsif array_type == 'f32'
133
+ word_size = 4
134
+ unpack_format = 'e*' # float, little-endian
135
+ elsif array_type == 'f64'
136
+ word_size = 8
137
+ unpack_format = 'E*' # double, little-endian
138
+ elsif array_type == 'bi64'
139
+ word_size = 8
140
+ unpack_format = 'q<*' # signed long long, little-endian
141
+ elsif array_type == 'bui64'
142
+ word_size = 8
143
+ unpack_format = 'Q<*' # unsigned long long, little-endian
144
+ else
145
+ raise ArgumentError, "Unsupported array type: #{array_type}"
146
+ end
147
+
148
+ byte_len = decoded_bytes.bytesize
149
+ if byte_len.zero?
150
+ return []
151
+ end
152
+
153
+ if byte_len % word_size != 0
154
+ raise ArgumentError, "Decoded bytes length #{byte_len} is not a multiple of word size #{word_size} for type #{array_type}"
155
+ end
156
+
157
+ return decoded_bytes.unpack(unpack_format)
158
+ end
159
+
71
160
  raise ArgumentError.new("Unexpected value: #{hash}")
72
161
  end
73
162
  end
@@ -1,8 +1,13 @@
1
+ require_relative './visitor_info'
2
+ require_relative './regex'
3
+ require 'uri'
4
+
1
5
  module Playwright
2
6
  module JavaScript
3
7
  class ValueSerializer
4
8
  def initialize(ruby_value)
5
9
  @value = ruby_value
10
+ @visited = VisitorInfo.new
6
11
  end
7
12
 
8
13
  # @return [Hash]
@@ -20,31 +25,65 @@ module Playwright
20
25
  @handles << value.channel
21
26
  { h: index }
22
27
  when nil
23
- { v: 'undefined' }
28
+ { v: 'null' }
24
29
  when Float::NAN
25
30
  { v: 'NaN'}
26
31
  when Float::INFINITY
27
32
  { v: 'Infinity' }
28
33
  when -Float::INFINITY
29
34
  { v: '-Infinity' }
35
+ when ::Playwright::Error
36
+ {
37
+ e: {
38
+ n: value.name,
39
+ m: value.message,
40
+ s: value.stack.join("\n")
41
+ }
42
+ }
43
+ when StandardError
44
+ {
45
+ e: {
46
+ n: value.class.name,
47
+ m: value.message,
48
+ s: (value.backtrace || []).join("\n")
49
+ }
50
+ }
30
51
  when true, false
31
52
  { b: value }
32
53
  when Numeric
33
- { n: value }
54
+ if !value.is_a?(Integer) || (-9007199254740992..9007199254740991).include?(value)
55
+ { n: value }
56
+ else
57
+ { bi: value.to_s }
58
+ end
34
59
  when String
35
60
  { s: value }
36
61
  when Time
37
62
  require 'time'
38
63
  { d: value.utc.iso8601 }
64
+ when ::URI
65
+ { u: value.to_s }
39
66
  when Regexp
40
- flags = []
41
- flags << 'ms' if (value.options & Regexp::MULTILINE) != 0
42
- flags << 'i' if (value.options & Regexp::IGNORECASE) != 0
43
- { r: { p: value.source, f: flags.join('') } }
67
+ regex_value = Regex.new(value)
68
+ { r: { p: regex_value.source, f: regex_value.flag } }
69
+ when -> (value) { @visited.ref(value) }
70
+ { ref: @visited.ref(value) }
44
71
  when Array
45
- { a: value.map { |v| serialize_value(v) } }
72
+ id = @visited.log(value)
73
+ result = []
74
+ value.each { |v| result << serialize_value(v) }
75
+ { a: result, id: id }
76
+ when Set
77
+ { se: serialize_value(value.to_a) }
46
78
  when Hash
47
- { o: value.map { |key, v| { k: key, v: serialize_value(v) } } }
79
+ if value.any? { |k, v| !k.is_a?(String) && !k.is_a?(Symbol) } # Map
80
+ { m: serialize_value(value.to_a) }
81
+ else
82
+ id = @visited.log(value)
83
+ result = []
84
+ value.each { |key, v| result << { k: key, v: serialize_value(v) } }
85
+ { o: result, id: id }
86
+ end
48
87
  else
49
88
  raise ArgumentError.new("Unexpected value: #{value}")
50
89
  end
@@ -0,0 +1,26 @@
1
+ module Playwright
2
+ module JavaScript
3
+ class VisitorInfo
4
+ def initialize
5
+ @data = {}
6
+ @last_id = 0
7
+ end
8
+
9
+ # returns [Integer|nil]
10
+ def ref(object)
11
+ @data[object]
12
+ end
13
+
14
+ def log(object)
15
+ if @data[object]
16
+ raise ArgumentError.new("Already visited")
17
+ end
18
+
19
+ id = @last_id + 1
20
+ @last_id = id # FIXME: should thread-safe
21
+
22
+ @data[object] = id
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,13 +1,5 @@
1
1
  require_relative './javascript/expression'
2
- require_relative './javascript/function'
3
2
  require_relative './javascript/value_parser'
4
3
  require_relative './javascript/value_serializer'
5
-
6
- module Playwright
7
- module JavaScript
8
- # Detect if str is likely to be a function
9
- module_function def function?(str)
10
- ['async', 'function'].any? { |key| str.strip.start_with?(key) } || str.include?('=>')
11
- end
12
- end
13
- end
4
+ require_relative './javascript/regex'
5
+ require_relative './javascript/source_url'
@@ -1,12 +1,16 @@
1
1
  module Playwright
2
- define_input_type :Keyboard do
2
+ define_api_implementation :KeyboardImpl do
3
+ def initialize(channel)
4
+ @channel = channel
5
+ end
6
+
3
7
  def down(key)
4
8
  @channel.send_message_to_server('keyboardDown', key: key)
5
9
  nil
6
10
  end
7
11
 
8
12
  def up(key)
9
- @channel.send_message_to_server('keyboardDown', key: key)
13
+ @channel.send_message_to_server('keyboardUp', key: key)
10
14
  end
11
15
 
12
16
  def insert_text(text)