playwright-ruby-client 1.44.0 → 1.45.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/documentation/docs/api/api_request_context.md +1 -1
  3. data/documentation/docs/api/browser_context.md +5 -23
  4. data/documentation/docs/api/clock.md +142 -0
  5. data/documentation/docs/api/console_message.md +1 -1
  6. data/documentation/docs/api/element_handle.md +3 -0
  7. data/documentation/docs/api/locator.md +6 -0
  8. data/documentation/docs/api/locator_assertions.md +1 -1
  9. data/documentation/docs/api/mouse.md +1 -1
  10. data/documentation/docs/api/page.md +6 -21
  11. data/documentation/docs/api/page_assertions.md +1 -1
  12. data/documentation/docs/include/api_coverage.md +12 -0
  13. data/lib/playwright/channel_owners/api_request_context.rb +5 -1
  14. data/lib/playwright/channel_owners/browser_context.rb +62 -10
  15. data/lib/playwright/channel_owners/page.rb +4 -1
  16. data/lib/playwright/clock_impl.rb +65 -0
  17. data/lib/playwright/input_files.rb +64 -23
  18. data/lib/playwright/version.rb +2 -2
  19. data/lib/playwright_api/api_request_context.rb +2 -2
  20. data/lib/playwright_api/browser.rb +2 -2
  21. data/lib/playwright_api/browser_context.rb +6 -16
  22. data/lib/playwright_api/clock.rb +109 -0
  23. data/lib/playwright_api/console_message.rb +1 -1
  24. data/lib/playwright_api/element_handle.rb +3 -0
  25. data/lib/playwright_api/locator.rb +6 -0
  26. data/lib/playwright_api/locator_assertions.rb +2 -2
  27. data/lib/playwright_api/mouse.rb +1 -1
  28. data/lib/playwright_api/page.rb +8 -17
  29. data/lib/playwright_api/page_assertions.rb +2 -2
  30. data/lib/playwright_api/playwright.rb +4 -4
  31. data/lib/playwright_api/worker.rb +4 -4
  32. data/sig/playwright.rbs +17 -3
  33. metadata +6 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c83d71803d132d79217392a22bcbad5de47673f738badf76692ff178e4ddd27
4
- data.tar.gz: 4d25cd84f28d6028f6335b89e4c0324847b3077004e6b21ffb6ed9740cd6ec91
3
+ metadata.gz: 61d1fe5862b1d039cee887b00ac4f561c4d1158d21e582262738bcabe6c5614b
4
+ data.tar.gz: 5041a590c2d79d0b6885b140be6ef581e7d50f52ca44cb7b975999cb70c4eacb
5
5
  SHA512:
6
- metadata.gz: 899c0d792c8021c4560240d9b61ca57b300519f5b2786f58406d65fcb44eb70301d474217c85ec710036c3eeff3119388bbe7255d5f3e6bdbe3debcc0ef425a0
7
- data.tar.gz: 0ca7408e7e43818d7afb4660fb6c8df219eeb386f244c9cde5895cad7fa2c3f9ef26d90f99b86c7c937071cb7c66be6db631ecd883186c43064be6501e793fe6
6
+ metadata.gz: c4bed1453a41a06716fa4df121cdbbec291bd9a0338993c90a2961745fdebb0c3ba09a160179a4b649b8342adbd83f95193639764ac75600cf0dc7be11ff833b
7
+ data.tar.gz: f2ed6829ad907d3a9862ba0be498348e834c46fa7ab352b50da81ef29d68ce6a2ecac7f6e003b20a58abae6d69e14a2391d7825326ad17c614032f118b7a8410
@@ -81,7 +81,7 @@ context cookies from the response. The method will automatically follow redirect
81
81
  ## dispose
82
82
 
83
83
  ```
84
- def dispose
84
+ def dispose(reason: nil)
85
85
  ```
86
86
 
87
87
 
@@ -185,29 +185,6 @@ HTML
185
185
  page.get_by_role("button").click
186
186
  ```
187
187
 
188
- An example of passing an element handle:
189
-
190
- ```ruby
191
- def print_text(source, element)
192
- element.text_content
193
- end
194
-
195
- browser_context.expose_binding("clicked", method(:print_text), handle: true)
196
- page = browser_context.new_page
197
-
198
- page.content = <<~HTML
199
- <script>
200
- document.addEventListener('click', async (event) => {
201
- alert(await window.clicked(event.target));
202
- })
203
- </script>
204
- <div>Click me</div>
205
- <div>Or click me</div>
206
- HTML
207
-
208
- page.locator('div').first.click
209
- ```
210
-
211
188
  ## expose_function
212
189
 
213
190
  ```
@@ -510,6 +487,11 @@ Performs action and waits for a new [Page](./page) to be created in the context.
510
487
  [Page](./page) value into the `predicate` function and waits for `predicate(event)` to return a truthy value.
511
488
  Will throw an error if the context closes before new [Page](./page) is created.
512
489
 
490
+ ## clock
491
+
492
+
493
+ Playwright has ability to mock clock and passage of time.
494
+
513
495
  ## request
514
496
 
515
497
 
@@ -0,0 +1,142 @@
1
+ ---
2
+ sidebar_position: 10
3
+ ---
4
+
5
+ # Clock
6
+
7
+
8
+ Accurately simulating time-dependent behavior is essential for verifying the correctness of applications. Learn more about [clock emulation](https://playwright.dev/python/docs/clock).
9
+
10
+ Note that clock is installed for the entire [BrowserContext](./browser_context), so the time
11
+ in all the pages and iframes is controlled by the same clock.
12
+
13
+ ## fast_forward
14
+
15
+ ```
16
+ def fast_forward(ticks)
17
+ ```
18
+
19
+
20
+ Advance the clock by jumping forward in time. Only fires due timers at most once. This is equivalent to user closing the laptop lid for a while and
21
+ reopening it later, after given time.
22
+
23
+ **Usage**
24
+
25
+ ```ruby
26
+ page.clock.fast_forward(1000)
27
+ page.clock.fast_forward("30:00")
28
+ ```
29
+
30
+ ## install
31
+
32
+ ```
33
+ def install(time: nil)
34
+ ```
35
+
36
+
37
+ Install fake implementations for the following time-related functions:
38
+ - `Date`
39
+ - `setTimeout`
40
+ - `clearTimeout`
41
+ - `setInterval`
42
+ - `clearInterval`
43
+ - `requestAnimationFrame`
44
+ - `cancelAnimationFrame`
45
+ - `requestIdleCallback`
46
+ - `cancelIdleCallback`
47
+ - `performance`
48
+
49
+ Fake timers are used to manually control the flow of time in tests. They allow you to advance time, fire timers, and control the behavior of time-dependent functions. See [Clock#run_for](./clock#run_for) and [Clock#fast_forward](./clock#fast_forward) for more information.
50
+
51
+ ## run_for
52
+
53
+ ```
54
+ def run_for(ticks)
55
+ ```
56
+
57
+
58
+ Advance the clock, firing all the time-related callbacks.
59
+
60
+ **Usage**
61
+
62
+ ```ruby
63
+ page.clock.run_for(1000)
64
+ page.clock.run_for("30:00")
65
+ ```
66
+
67
+ ## pause_at
68
+
69
+ ```
70
+ def pause_at(time)
71
+ ```
72
+
73
+
74
+ Advance the clock by jumping forward in time and pause the time. Once this method is called, no timers
75
+ are fired unless [Clock#run_for](./clock#run_for), [Clock#fast_forward](./clock#fast_forward), [Clock#pause_at](./clock#pause_at) or [Clock#resume](./clock#resume) is called.
76
+
77
+ Only fires due timers at most once.
78
+ This is equivalent to user closing the laptop lid for a while and reopening it at the specified time and
79
+ pausing.
80
+
81
+ **Usage**
82
+
83
+ ```ruby
84
+ page.clock.pause_at(Time.parse("2020-02-02"))
85
+ page.clock.pause_at("2020-02-02")
86
+ ```
87
+
88
+ ## resume
89
+
90
+ ```
91
+ def resume
92
+ ```
93
+
94
+
95
+ Resumes timers. Once this method is called, time resumes flowing, timers are fired as usual.
96
+
97
+ ## set_fixed_time
98
+
99
+ ```
100
+ def set_fixed_time(time)
101
+ ```
102
+ alias: `fixed_time=`
103
+
104
+
105
+ Makes `Date.now` and `new Date()` return fixed fake time at all times,
106
+ keeps all the timers running.
107
+
108
+ **Usage**
109
+
110
+ ```ruby
111
+ page.clock.set_fixed_time(Time.now)
112
+ page.clock.set_fixed_time(Time.parse("2020-02-02"))
113
+ page.clock.set_fixed_time("2020-02-02")
114
+
115
+ # or we can use the alias
116
+ page.clock.fixed_time = Time.now
117
+ page.clock.fixed_time = Time.parse("2020-02-02")
118
+ page.clock.fixed_time = "2020-02-02"
119
+ ```
120
+
121
+ ## set_system_time
122
+
123
+ ```
124
+ def set_system_time(time)
125
+ ```
126
+ alias: `system_time=`
127
+
128
+
129
+ Sets current system time but does not trigger any timers.
130
+
131
+ **Usage**
132
+
133
+ ```ruby
134
+ page.clock.set_system_time(Time.now)
135
+ page.clock.set_system_time(Time.parse("2020-02-02"))
136
+ page.clock.set_system_time("2020-02-02")
137
+
138
+ # or we can use the alias
139
+ page.clock.system_time = Time.now
140
+ page.clock.system_time = Time.parse("2020-02-02")
141
+ page.clock.system_time = "2020-02-02"
142
+ ```
@@ -6,7 +6,7 @@ sidebar_position: 10
6
6
 
7
7
 
8
8
  [ConsoleMessage](./console_message) objects are dispatched by page via the [`event: Page.console`] event.
9
- For each console messages logged in the page there will be corresponding event in the Playwright
9
+ For each console message logged in the page there will be corresponding event in the Playwright
10
10
  context.
11
11
 
12
12
  ```ruby
@@ -485,6 +485,8 @@ completely visible as defined by
485
485
  Throws when `elementHandle` does not point to an element
486
486
  [connected](https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected) to a Document or a ShadowRoot.
487
487
 
488
+ See [scrolling](https://playwright.dev/python/docs/input#scrolling) for alternative ways to scroll.
489
+
488
490
  ## select_option
489
491
 
490
492
  ```
@@ -566,6 +568,7 @@ alias: `input_files=`
566
568
 
567
569
  Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then they
568
570
  are resolved relative to the current working directory. For empty array, clears the selected files.
571
+ For inputs with a `[webkitdirectory]` attribute, only a single directory path is supported.
569
572
 
570
573
  This method expects [ElementHandle](./element_handle) to point to an
571
574
  [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). However, if the element is inside the `<label>` element that has an associated [control](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control), targets the control instead.
@@ -1162,6 +1162,8 @@ This method waits for [actionability](https://playwright.dev/python/docs/actiona
1162
1162
  completely visible as defined by
1163
1163
  [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)'s `ratio`.
1164
1164
 
1165
+ See [scrolling](https://playwright.dev/python/docs/input#scrolling) for alternative ways to scroll.
1166
+
1165
1167
  ## select_option
1166
1168
 
1167
1169
  ```
@@ -1265,6 +1267,7 @@ alias: `input_files=`
1265
1267
 
1266
1268
 
1267
1269
  Upload file or multiple files into `<input type=file>`.
1270
+ For inputs with a `[webkitdirectory]` attribute, only a single directory path is supported.
1268
1271
 
1269
1272
  **Usage**
1270
1273
 
@@ -1275,6 +1278,9 @@ page.get_by_label("Upload file").set_input_files('myfile.pdf')
1275
1278
  # Select multiple files
1276
1279
  page.get_by_label("Upload files").set_input_files(['file1.txt', 'file2.txt'])
1277
1280
 
1281
+ # Select a directory
1282
+ page.get_by_label("Upload directory").set_input_files('mydir')
1283
+
1278
1284
  # Remove all the selected files
1279
1285
  page.get_by_label("Upload file").set_input_files([])
1280
1286
  ```
@@ -200,7 +200,7 @@ The opposite of [LocatorAssertions#to_have_js_property](./locator_assertions#to_
200
200
  ## not_to_have_role
201
201
 
202
202
  ```ruby
203
- expect(locator).not_to have_role(name, timeout: nil)
203
+ expect(locator).not_to have_role(role, timeout: nil)
204
204
  ```
205
205
 
206
206
 
@@ -78,7 +78,7 @@ def wheel(deltaX, deltaY)
78
78
  ```
79
79
 
80
80
 
81
- Dispatches a `wheel` event.
81
+ Dispatches a `wheel` event. This method is usually used to manually scroll the page. See [scrolling](https://playwright.dev/python/docs/input#scrolling) for alternative ways to scroll.
82
82
 
83
83
  **NOTE**: Wheel events may cause scrolling if they are not handled, and this method does not
84
84
  wait for the scrolling to finish before returning.
@@ -479,27 +479,6 @@ HTML
479
479
  page.click("button")
480
480
  ```
481
481
 
482
- An example of passing an element handle:
483
-
484
- ```ruby
485
- def print_text(source, element)
486
- element.text_content
487
- end
488
-
489
- page.expose_binding("clicked", method(:print_text), handle: true)
490
- page.content = <<~HTML
491
- <script>
492
- document.addEventListener('click', async (event) => {
493
- alert(await window.clicked(event.target));
494
- })
495
- </script>
496
- <div>Click me</div>
497
- <div>Or click me</div>
498
- HTML
499
-
500
- page.locator('div').first.click
501
- ```
502
-
503
482
  ## expose_function
504
483
 
505
484
  ```
@@ -1438,6 +1417,7 @@ def set_input_files(
1438
1417
 
1439
1418
  Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then they
1440
1419
  are resolved relative to the current working directory. For empty array, clears the selected files.
1420
+ For inputs with a `[webkitdirectory]` attribute, only a single directory path is supported.
1441
1421
 
1442
1422
  This method expects `selector` to point to an
1443
1423
  [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). However, if the element is inside the `<label>` element that has an associated [control](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control), targets the control instead.
@@ -1910,6 +1890,11 @@ associated with the page.
1910
1890
 
1911
1891
  **NOTE**: This does not contain ServiceWorkers
1912
1892
 
1893
+ ## clock
1894
+
1895
+
1896
+ Playwright has ability to mock clock and passage of time.
1897
+
1913
1898
  ## accessibility
1914
1899
 
1915
1900
  ## keyboard
@@ -28,7 +28,7 @@ The opposite of [PageAssertions#to_have_title](./page_assertions#to_have_title).
28
28
  ## not_to_have_url
29
29
 
30
30
  ```
31
- def not_to_have_url(urlOrRegExp, timeout: nil)
31
+ def not_to_have_url(urlOrRegExp, ignoreCase: nil, timeout: nil)
32
32
  ```
33
33
 
34
34
 
@@ -214,6 +214,16 @@
214
214
  * register
215
215
  * ~~set_test_id_attribute~~
216
216
 
217
+ ## Clock
218
+
219
+ * fast_forward
220
+ * install
221
+ * run_for
222
+ * pause_at
223
+ * resume
224
+ * set_fixed_time
225
+ * set_system_time
226
+
217
227
  ## ConsoleMessage
218
228
 
219
229
  * args
@@ -340,6 +350,7 @@
340
350
  * expect_worker
341
351
  * workers
342
352
  * ~~wait_for_event~~
353
+ * clock
343
354
  * accessibility
344
355
  * keyboard
345
356
  * mouse
@@ -377,6 +388,7 @@
377
388
  * expect_event
378
389
  * expect_page
379
390
  * ~~wait_for_event~~
391
+ * clock
380
392
  * request
381
393
  * tracing
382
394
 
@@ -6,7 +6,8 @@ module Playwright
6
6
  @tracing = ChannelOwners::Tracing.from(@initializer['tracing'])
7
7
  end
8
8
 
9
- def dispose
9
+ def dispose(reason: nil)
10
+ @close_reason = reason
10
11
  @channel.send_message_to_server('dispose')
11
12
  end
12
13
 
@@ -92,6 +93,9 @@ module Playwright
92
93
  multipart: nil,
93
94
  params: nil,
94
95
  timeout: nil)
96
+ if @close_reason
97
+ raise TargetClosedError.new(message: @close_reason)
98
+ end
95
99
  if [data, form, multipart].compact.count > 1
96
100
  raise ArgumentError.new("Only one of 'data', 'form' or 'multipart' can be specified")
97
101
  end
@@ -5,7 +5,7 @@ module Playwright
5
5
 
6
6
  attr_accessor :browser
7
7
  attr_writer :owner_page, :options
8
- attr_reader :tracing, :request
8
+ attr_reader :clock, :tracing, :request
9
9
 
10
10
  private def after_initialize
11
11
  if @parent.is_a?(ChannelOwners::Browser)
@@ -22,6 +22,7 @@ module Playwright
22
22
 
23
23
  @tracing = ChannelOwners::Tracing.from(@initializer['tracing'])
24
24
  @request = ChannelOwners::APIRequestContext.from(@initializer['requestContext'])
25
+ @clock = ClockImpl.new(self)
25
26
  @har_recorders = {}
26
27
 
27
28
  @channel.on('bindingCall', ->(params) { on_binding(ChannelOwners::BindingCall.from(params['binding'])) })
@@ -441,7 +442,7 @@ module Playwright
441
442
  return if @close_was_called
442
443
  @close_was_called = true
443
444
  @close_reason = reason
444
-
445
+ @request.dispose(reason: reason)
445
446
  inner_close
446
447
  @channel.send_message_to_server('close', { reason: reason }.compact)
447
448
  @closed_promise.value!
@@ -553,14 +554,65 @@ module Playwright
553
554
 
554
555
  # called from InputFiles
555
556
  # @param filepath [string]
556
- # @return [WritableStream]
557
- private def create_temp_file(filepath)
558
- result = @channel.send_message_to_server(
559
- 'createTempFile',
560
- name: File.basename(filepath),
561
- lastModifiedMs: File.mtime(filepath).to_i * 1000,
562
- )
563
- ChannelOwners::WritableStream.from(result)
557
+ # @return [WritableStream, Array<WritableStream>]
558
+ private def create_temp_files(local_directory, files)
559
+ if local_directory
560
+ params = {
561
+ rootDirName: File.basename(local_directory),
562
+ items: files.map do |filepath|
563
+ {
564
+ name: Pathname.new(filepath).relative_path_from(Pathname.new(local_directory)).to_s,
565
+ lastModifiedMs: File.mtime(filepath).to_i * 1000,
566
+ }
567
+ end
568
+ }
569
+ else
570
+ params = {
571
+ items: files.map do |filepath|
572
+ {
573
+ name: File.basename(filepath),
574
+ lastModifiedMs: File.mtime(filepath).to_i * 1000,
575
+ }
576
+ end
577
+ }
578
+ end
579
+
580
+ result = @channel.send_message_to_server_result('createTempFiles', params)
581
+
582
+ [
583
+ ChannelOwners::WritableStream.from_nullable(result['rootDir']),
584
+ result['writableStreams'].map do |s|
585
+ ChannelOwners::WritableStream.from(s)
586
+ end,
587
+ ]
588
+ end
589
+
590
+ private def clock_fast_forward(ticks_params)
591
+ @channel.send_message_to_server('clockFastForward', ticks_params)
592
+ end
593
+
594
+ private def clock_install(time_params)
595
+ @channel.send_message_to_server('clockInstall', time_params)
596
+ end
597
+
598
+ private def clock_pause_at(time_params)
599
+ @channel.send_message_to_server('clockPauseAt', time_params)
600
+ end
601
+
602
+ private def clock_resume
603
+ @channel.send_message_to_server('clockResume')
604
+ end
605
+
606
+ private def clock_run_for(ticks_params)
607
+ @channel.send_message_to_server('clockRunFor', ticks_params)
608
+ end
609
+
610
+ private def clock_set_fixed_time(time_params)
611
+ @channel.send_message_to_server('clockSetFixedTime', time_params)
612
+ end
613
+
614
+ private def clock_set_system_time(time_params)
615
+ @channel.send_message_to_server('clockSetSystemTime', time_params)
564
616
  end
565
617
  end
566
618
  end
@@ -8,7 +8,6 @@ module Playwright
8
8
  include LocatorUtils
9
9
  attr_writer :owned_context
10
10
 
11
-
12
11
  private def after_initialize
13
12
  @browser_context = @parent
14
13
  @timeout_settings = TimeoutSettings.new(@browser_context.send(:_timeout_settings))
@@ -196,6 +195,10 @@ module Playwright
196
195
  @browser_context
197
196
  end
198
197
 
198
+ def clock
199
+ @browser_context.clock
200
+ end
201
+
199
202
  def opener
200
203
  if @opener&.closed?
201
204
  nil
@@ -0,0 +1,65 @@
1
+ module Playwright
2
+ define_api_implementation :ClockImpl do
3
+ def initialize(browser_context)
4
+ @browser_context = browser_context
5
+ end
6
+
7
+ def install(time: nil)
8
+ if time
9
+ @browser_context.send(:clock_install, parse_time(time))
10
+ else
11
+ @browser_context.send(:clock_install, {})
12
+ end
13
+ end
14
+
15
+ def fast_forward(ticks)
16
+ @browser_context.send(:clock_fast_forward, parse_ticks(ticks))
17
+ end
18
+
19
+ def pause_at(time)
20
+ @browser_context.send(:clock_pause_at, parse_time(time))
21
+ end
22
+
23
+ def resume
24
+ @browser_context.send(:clock_resume)
25
+ end
26
+
27
+ def run_for(ticks)
28
+ @browser_context.send(:clock_run_for, parse_ticks(ticks))
29
+ end
30
+
31
+ def set_fixed_time(time)
32
+ @browser_context.send(:clock_set_fixed_time, parse_time(time))
33
+ end
34
+
35
+ def set_system_time(time)
36
+ @browser_context.send(:clock_set_system_time, parse_time(time))
37
+ end
38
+
39
+ private def parse_time(time)
40
+ case time
41
+ when Integer
42
+ { timeNumber: time }
43
+ when String
44
+ { timeString: time }
45
+ else
46
+ if time.respond_to?(:utc)
47
+ { timeNumber: time.utc.to_i }
48
+ else
49
+ raise ArgumentError.new('time must be either integer, string or a Time object')
50
+ end
51
+ end
52
+ end
53
+
54
+ private def parse_ticks(ticks)
55
+ case ticks
56
+ when Integer
57
+ { ticksNumber: ticks }
58
+ when String
59
+ { ticksString: ticks }
60
+ else
61
+ raise ArgumentError.new('ticks must be either integer or string')
62
+ end
63
+ end
64
+ end
65
+ end
@@ -5,16 +5,17 @@ module Playwright
5
5
  def initialize(context, files)
6
6
  @context = context
7
7
  if files.is_a?(File)
8
- @files = [files]
8
+ files_to_resolve = [files]
9
9
  elsif files.is_a?(Enumerable)
10
- @files = files
10
+ files_to_resolve = files
11
11
  else
12
- @files = [files]
12
+ files_to_resolve = [files]
13
13
  end
14
+ resolve_paths_and_directory_for_input_files(files_to_resolve)
14
15
  end
15
16
 
16
17
  def as_method_and_params
17
- if has_large_file?
18
+ if @local_directory || has_large_file?
18
19
  ['setInputFiles', params_for_set_input_file_paths]
19
20
  else
20
21
  ['setInputFiles', params_for_set_input_files]
@@ -24,44 +25,86 @@ module Playwright
24
25
  private def has_large_file?
25
26
  max_bufsize = 1024 * 1024 # 1MB
26
27
 
27
- @files.any? do |file|
28
+ @local_files.any? do |file|
28
29
  case file
29
30
  when String
30
31
  File::Stat.new(file).size > max_bufsize
31
32
  when File
32
33
  file.stat.size > max_bufsize
33
- else
34
- raise_argument_error
35
34
  end
36
35
  end
37
36
  end
38
37
 
39
- private def params_for_set_input_file_paths
40
- writable_streams = @files.map do |file|
41
- case file
38
+ private def resolve_paths_and_directory_for_input_files(files)
39
+ # filter_map is not available in Ruby < 2.7
40
+ @local_files = files.map do |item|
41
+ case item
42
42
  when String
43
- writable_stream = @context.send(:create_temp_file, file)
44
-
45
- File.open(file, 'rb') do |file|
46
- writable_stream.write(file)
43
+ if File.directory?(item)
44
+ raise ArgumentError.new('Multiple directories are not supported') if @local_directory
45
+ @local_directory = item
46
+ next
47
47
  end
48
48
 
49
- writable_stream.channel
49
+ item
50
50
  when File
51
- writable_stream = @context.send(:create_temp_file, file.path)
52
- writable_stream.write(file)
51
+ if File.directory?(item.path)
52
+ raise ArgumentError.new('Multiple directories are not supported') if @local_directory
53
+ @local_directory = item
54
+ next
55
+ end
53
56
 
54
- writable_stream.channel
57
+ item
55
58
  else
56
- raise_argument_error
59
+ raise ArgumentError.new('file must be a String or File or Directory.')
57
60
  end
61
+ end.compact
62
+
63
+ if @local_directory && !@local_files.empty?
64
+ raise ArgumentError.new('File paths must be all files or a single directory')
58
65
  end
66
+ end
67
+
68
+ private def params_for_set_input_file_paths
69
+ if @local_directory
70
+ filenames = Dir["#{@local_directory}/**/*"].reject { |file| File.directory?(file) }
71
+ directory_stream, writable_streams = @context.send(:create_temp_files, @local_directory, filenames)
72
+
73
+ filenames.zip(writable_streams).each do |filename, writable_stream|
74
+ File.open(filename, 'rb') do |file|
75
+ writable_stream.write(file)
76
+ end
77
+ end
78
+
79
+ { directoryStream: directory_stream.channel }
80
+ else
81
+ filenames = @local_files.map do |file|
82
+ case file
83
+ when String
84
+ file
85
+ when File
86
+ file.path
87
+ end
88
+ end
59
89
 
60
- { streams: writable_streams }
90
+ _, writable_streams = @context.send(:create_temp_files, nil, filenames)
91
+ @local_files.zip(writable_streams).each do |file, writable_stream|
92
+ case file
93
+ when String
94
+ File.open(file, 'rb') do |file|
95
+ writable_stream.write(file)
96
+ end
97
+ when File
98
+ writable_stream.write(file)
99
+ end
100
+ end
101
+
102
+ { streams: writable_streams.map(&:channel) }
103
+ end
61
104
  end
62
105
 
63
106
  private def params_for_set_input_files
64
- file_payloads = @files.map do |file|
107
+ file_payloads = @local_files.map do |file|
65
108
  case file
66
109
  when String
67
110
  {
@@ -73,8 +116,6 @@ module Playwright
73
116
  name: File.basename(file.path),
74
117
  buffer: Base64.strict_encode64(file.read),
75
118
  }
76
- else
77
- raise_argument_error
78
119
  end
79
120
  end
80
121
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playwright
4
- VERSION = '1.44.0'
5
- COMPATIBLE_PLAYWRIGHT_VERSION = '1.44.0'
4
+ VERSION = '1.45.0'
5
+ COMPATIBLE_PLAYWRIGHT_VERSION = '1.45.0'
6
6
  end
@@ -87,8 +87,8 @@ module Playwright
87
87
 
88
88
  #
89
89
  # All responses returned by [`method: APIRequestContext.get`] and similar methods are stored in the memory, so that you can later call [`method: APIResponse.body`].This method discards all its resources, calling any method on disposed `APIRequestContext` will throw an exception.
90
- def dispose
91
- wrap_impl(@impl.dispose)
90
+ def dispose(reason: nil)
91
+ wrap_impl(@impl.dispose(reason: unwrap_impl(reason)))
92
92
  end
93
93
 
94
94
  #
@@ -45,9 +45,9 @@ module Playwright
45
45
  #
46
46
  # ```python sync
47
47
  # browser = pw.webkit.launch()
48
- # print(len(browser.contexts())) # prints `0`
48
+ # print(len(browser.contexts)) # prints `0`
49
49
  # context = browser.new_context()
50
- # print(len(browser.contexts())) # prints `1`
50
+ # print(len(browser.contexts)) # prints `1`
51
51
  # ```
52
52
  def contexts
53
53
  wrap_impl(@impl.contexts)
@@ -20,6 +20,12 @@ module Playwright
20
20
  # ```
21
21
  class BrowserContext < PlaywrightApi
22
22
 
23
+ #
24
+ # Playwright has ability to mock clock and passage of time.
25
+ def clock # property
26
+ wrap_impl(@impl.clock)
27
+ end
28
+
23
29
  #
24
30
  # API testing helper associated with this context. Requests made with this API will use context cookies.
25
31
  def request # property
@@ -163,22 +169,6 @@ module Playwright
163
169
  # with sync_playwright() as playwright:
164
170
  # run(playwright)
165
171
  # ```
166
- #
167
- # An example of passing an element handle:
168
- #
169
- # ```python sync
170
- # def print(source, element):
171
- # print(element.text_content())
172
- #
173
- # context.expose_binding("clicked", print, handle=true)
174
- # page.set_content("""
175
- # <script>
176
- # document.addEventListener('click', event => window.clicked(event.target));
177
- # </script>
178
- # <div>Click me</div>
179
- # <div>Or click me</div>
180
- # """)
181
- # ```
182
172
  def expose_binding(name, callback, handle: nil)
183
173
  wrap_impl(@impl.expose_binding(unwrap_impl(name), unwrap_impl(callback), handle: unwrap_impl(handle)))
184
174
  end
@@ -0,0 +1,109 @@
1
+ module Playwright
2
+ #
3
+ # Accurately simulating time-dependent behavior is essential for verifying the correctness of applications. Learn more about [clock emulation](../clock.md).
4
+ #
5
+ # Note that clock is installed for the entire `BrowserContext`, so the time
6
+ # in all the pages and iframes is controlled by the same clock.
7
+ class Clock < PlaywrightApi
8
+
9
+ #
10
+ # Advance the clock by jumping forward in time. Only fires due timers at most once. This is equivalent to user closing the laptop lid for a while and
11
+ # reopening it later, after given time.
12
+ #
13
+ # **Usage**
14
+ #
15
+ # ```python sync
16
+ # page.clock.fast_forward(1000)
17
+ # page.clock.fast_forward("30:00")
18
+ # ```
19
+ def fast_forward(ticks)
20
+ wrap_impl(@impl.fast_forward(unwrap_impl(ticks)))
21
+ end
22
+
23
+ #
24
+ # Install fake implementations for the following time-related functions:
25
+ # - `Date`
26
+ # - `setTimeout`
27
+ # - `clearTimeout`
28
+ # - `setInterval`
29
+ # - `clearInterval`
30
+ # - `requestAnimationFrame`
31
+ # - `cancelAnimationFrame`
32
+ # - `requestIdleCallback`
33
+ # - `cancelIdleCallback`
34
+ # - `performance`
35
+ #
36
+ # Fake timers are used to manually control the flow of time in tests. They allow you to advance time, fire timers, and control the behavior of time-dependent functions. See [`method: Clock.runFor`] and [`method: Clock.fastForward`] for more information.
37
+ def install(time: nil)
38
+ wrap_impl(@impl.install(time: unwrap_impl(time)))
39
+ end
40
+
41
+ #
42
+ # Advance the clock, firing all the time-related callbacks.
43
+ #
44
+ # **Usage**
45
+ #
46
+ # ```python sync
47
+ # page.clock.run_for(1000);
48
+ # page.clock.run_for("30:00")
49
+ # ```
50
+ def run_for(ticks)
51
+ wrap_impl(@impl.run_for(unwrap_impl(ticks)))
52
+ end
53
+
54
+ #
55
+ # Advance the clock by jumping forward in time and pause the time. Once this method is called, no timers
56
+ # are fired unless [`method: Clock.runFor`], [`method: Clock.fastForward`], [`method: Clock.pauseAt`] or [`method: Clock.resume`] is called.
57
+ #
58
+ # Only fires due timers at most once.
59
+ # This is equivalent to user closing the laptop lid for a while and reopening it at the specified time and
60
+ # pausing.
61
+ #
62
+ # **Usage**
63
+ #
64
+ # ```python sync
65
+ # page.clock.pause_at(datetime.datetime(2020, 2, 2))
66
+ # page.clock.pause_at("2020-02-02")
67
+ # ```
68
+ def pause_at(time)
69
+ wrap_impl(@impl.pause_at(unwrap_impl(time)))
70
+ end
71
+
72
+ #
73
+ # Resumes timers. Once this method is called, time resumes flowing, timers are fired as usual.
74
+ def resume
75
+ wrap_impl(@impl.resume)
76
+ end
77
+
78
+ #
79
+ # Makes `Date.now` and `new Date()` return fixed fake time at all times,
80
+ # keeps all the timers running.
81
+ #
82
+ # **Usage**
83
+ #
84
+ # ```python sync
85
+ # page.clock.set_fixed_time(datetime.datetime.now())
86
+ # page.clock.set_fixed_time(datetime.datetime(2020, 2, 2))
87
+ # page.clock.set_fixed_time("2020-02-02")
88
+ # ```
89
+ def set_fixed_time(time)
90
+ wrap_impl(@impl.set_fixed_time(unwrap_impl(time)))
91
+ end
92
+ alias_method :fixed_time=, :set_fixed_time
93
+
94
+ #
95
+ # Sets current system time but does not trigger any timers.
96
+ #
97
+ # **Usage**
98
+ #
99
+ # ```python sync
100
+ # page.clock.set_system_time(datetime.datetime.now())
101
+ # page.clock.set_system_time(datetime.datetime(2020, 2, 2))
102
+ # page.clock.set_system_time("2020-02-02")
103
+ # ```
104
+ def set_system_time(time)
105
+ wrap_impl(@impl.set_system_time(unwrap_impl(time)))
106
+ end
107
+ alias_method :system_time=, :set_system_time
108
+ end
109
+ end
@@ -1,7 +1,7 @@
1
1
  module Playwright
2
2
  #
3
3
  # `ConsoleMessage` objects are dispatched by page via the [`event: Page.console`] event.
4
- # For each console messages logged in the page there will be corresponding event in the Playwright
4
+ # For each console message logged in the page there will be corresponding event in the Playwright
5
5
  # context.
6
6
  #
7
7
  # ```python sync
@@ -395,6 +395,8 @@ module Playwright
395
395
  #
396
396
  # Throws when `elementHandle` does not point to an element
397
397
  # [connected](https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected) to a Document or a ShadowRoot.
398
+ #
399
+ # See [scrolling](../input.md#scrolling) for alternative ways to scroll.
398
400
  def scroll_into_view_if_needed(timeout: nil)
399
401
  wrap_impl(@impl.scroll_into_view_if_needed(timeout: unwrap_impl(timeout)))
400
402
  end
@@ -464,6 +466,7 @@ module Playwright
464
466
  #
465
467
  # Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then they
466
468
  # are resolved relative to the current working directory. For empty array, clears the selected files.
469
+ # For inputs with a `[webkitdirectory]` attribute, only a single directory path is supported.
467
470
  #
468
471
  # This method expects `ElementHandle` to point to an
469
472
  # [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). However, if the element is inside the `<label>` element that has an associated [control](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control), targets the control instead.
@@ -983,6 +983,8 @@ module Playwright
983
983
  # This method waits for [actionability](../actionability.md) checks, then tries to scroll element into view, unless it is
984
984
  # completely visible as defined by
985
985
  # [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)'s `ratio`.
986
+ #
987
+ # See [scrolling](../input.md#scrolling) for alternative ways to scroll.
986
988
  def scroll_into_view_if_needed(timeout: nil)
987
989
  wrap_impl(@impl.scroll_into_view_if_needed(timeout: unwrap_impl(timeout)))
988
990
  end
@@ -1073,6 +1075,7 @@ module Playwright
1073
1075
 
1074
1076
  #
1075
1077
  # Upload file or multiple files into `<input type=file>`.
1078
+ # For inputs with a `[webkitdirectory]` attribute, only a single directory path is supported.
1076
1079
  #
1077
1080
  # **Usage**
1078
1081
  #
@@ -1083,6 +1086,9 @@ module Playwright
1083
1086
  # # Select multiple files
1084
1087
  # page.get_by_label("Upload files").set_input_files(['file1.txt', 'file2.txt'])
1085
1088
  #
1089
+ # # Select a directory
1090
+ # page.get_by_label("Upload directory").set_input_files('mydir')
1091
+ #
1086
1092
  # # Remove all the selected files
1087
1093
  # page.get_by_label("Upload file").set_input_files([])
1088
1094
  #
@@ -128,8 +128,8 @@ module Playwright
128
128
 
129
129
  #
130
130
  # The opposite of [`method: LocatorAssertions.toHaveRole`].
131
- def not_to_have_role(name, timeout: nil)
132
- wrap_impl(@impl.not_to_have_role(unwrap_impl(name), timeout: unwrap_impl(timeout)))
131
+ def not_to_have_role(role, timeout: nil)
132
+ wrap_impl(@impl.not_to_have_role(unwrap_impl(role), timeout: unwrap_impl(timeout)))
133
133
  end
134
134
 
135
135
  #
@@ -53,7 +53,7 @@ module Playwright
53
53
  end
54
54
 
55
55
  #
56
- # Dispatches a `wheel` event.
56
+ # Dispatches a `wheel` event. This method is usually used to manually scroll the page. See [scrolling](../input.md#scrolling) for alternative ways to scroll.
57
57
  #
58
58
  # **NOTE**: Wheel events may cause scrolling if they are not handled, and this method does not
59
59
  # wait for the scrolling to finish before returning.
@@ -44,6 +44,12 @@ module Playwright
44
44
  # ```
45
45
  class Page < PlaywrightApi
46
46
 
47
+ #
48
+ # Playwright has ability to mock clock and passage of time.
49
+ def clock # property
50
+ wrap_impl(@impl.clock)
51
+ end
52
+
47
53
  def accessibility # property
48
54
  wrap_impl(@impl.accessibility)
49
55
  end
@@ -463,22 +469,6 @@ module Playwright
463
469
  # with sync_playwright() as playwright:
464
470
  # run(playwright)
465
471
  # ```
466
- #
467
- # An example of passing an element handle:
468
- #
469
- # ```python sync
470
- # def print(source, element):
471
- # print(element.text_content())
472
- #
473
- # page.expose_binding("clicked", print, handle=true)
474
- # page.set_content("""
475
- # <script>
476
- # document.addEventListener('click', event => window.clicked(event.target));
477
- # </script>
478
- # <div>Click me</div>
479
- # <div>Or click me</div>
480
- # """)
481
- # ```
482
472
  def expose_binding(name, callback, handle: nil)
483
473
  wrap_impl(@impl.expose_binding(unwrap_impl(name), unwrap_impl(callback), handle: unwrap_impl(handle)))
484
474
  end
@@ -1353,6 +1343,7 @@ module Playwright
1353
1343
  #
1354
1344
  # Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then they
1355
1345
  # are resolved relative to the current working directory. For empty array, clears the selected files.
1346
+ # For inputs with a `[webkitdirectory]` attribute, only a single directory path is supported.
1356
1347
  #
1357
1348
  # This method expects `selector` to point to an
1358
1349
  # [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). However, if the element is inside the `<label>` element that has an associated [control](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control), targets the control instead.
@@ -1656,7 +1647,7 @@ module Playwright
1656
1647
  # return response.ok
1657
1648
  #
1658
1649
  # # or with a lambda
1659
- # with page.expect_response(lambda response: response.url == "https://example.com" and response.status == 200) as response_info:
1650
+ # with page.expect_response(lambda response: response.url == "https://example.com" and response.status == 200 and response.request.method == "get") as response_info:
1660
1651
  # page.get_by_text("trigger response").click()
1661
1652
  # response = response_info.value
1662
1653
  # return response.ok
@@ -21,8 +21,8 @@ module Playwright
21
21
 
22
22
  #
23
23
  # The opposite of [`method: PageAssertions.toHaveURL`].
24
- def not_to_have_url(urlOrRegExp, timeout: nil)
25
- wrap_impl(@impl.not_to_have_url(unwrap_impl(urlOrRegExp), timeout: unwrap_impl(timeout)))
24
+ def not_to_have_url(urlOrRegExp, ignoreCase: nil, timeout: nil)
25
+ wrap_impl(@impl.not_to_have_url(unwrap_impl(urlOrRegExp), ignoreCase: unwrap_impl(ignoreCase), timeout: unwrap_impl(timeout)))
26
26
  end
27
27
 
28
28
  #
@@ -94,13 +94,13 @@ module Playwright
94
94
  end
95
95
 
96
96
  # @nodoc
97
- def electron
98
- wrap_impl(@impl.electron)
97
+ def android
98
+ wrap_impl(@impl.android)
99
99
  end
100
100
 
101
101
  # @nodoc
102
- def android
103
- wrap_impl(@impl.android)
102
+ def electron
103
+ wrap_impl(@impl.electron)
104
104
  end
105
105
 
106
106
  # -- inherited from EventEmitter --
@@ -47,13 +47,13 @@ module Playwright
47
47
  end
48
48
 
49
49
  # @nodoc
50
- def page=(req)
51
- wrap_impl(@impl.page=(unwrap_impl(req)))
50
+ def context=(req)
51
+ wrap_impl(@impl.context=(unwrap_impl(req)))
52
52
  end
53
53
 
54
54
  # @nodoc
55
- def context=(req)
56
- wrap_impl(@impl.context=(unwrap_impl(req)))
55
+ def page=(req)
56
+ wrap_impl(@impl.page=(unwrap_impl(req)))
57
57
  end
58
58
 
59
59
  # -- inherited from EventEmitter --
data/sig/playwright.rbs CHANGED
@@ -220,6 +220,18 @@ module Playwright
220
220
  def register: (String name, ?script: String, ?contentScript: bool, ?path: (String | File)) -> void
221
221
  end
222
222
 
223
+ class Clock
224
+ def fast_forward: ((Integer | String) ticks) -> void
225
+ def install: (?time: (Integer | String | Time)) -> void
226
+ def run_for: ((Integer | String) ticks) -> void
227
+ def pause_at: ((Integer | String | Time) time) -> void
228
+ def resume: -> void
229
+ def set_fixed_time: ((Integer | String | Time) time) -> void
230
+ def fixed_time=: ((Integer | String | Time) time) -> void
231
+ def set_system_time: ((Integer | String | Time) time) -> void
232
+ def system_time=: ((Integer | String | Time) time) -> void
233
+ end
234
+
223
235
  class ConsoleMessage
224
236
  def args: -> Array[untyped]
225
237
  def location: -> Hash[untyped, untyped]
@@ -348,6 +360,7 @@ module Playwright
348
360
  def expect_worker: (?predicate: function, ?timeout: Float) { () -> void } -> Worker
349
361
  def workers: -> Array[untyped]
350
362
 
363
+ attr_reader clock: Clock
351
364
  attr_reader accessibility: Accessibility
352
365
  attr_reader keyboard: Keyboard
353
366
  attr_reader mouse: Mouse
@@ -390,6 +403,7 @@ module Playwright
390
403
  def expect_event: (String event, ?predicate: function, ?timeout: Float) { () -> void } -> untyped
391
404
  def expect_page: (?predicate: function, ?timeout: Float) { () -> void } -> Page
392
405
 
406
+ attr_reader clock: Clock
393
407
  attr_reader request: APIRequestContext
394
408
  attr_reader tracing: Tracing
395
409
  end
@@ -533,7 +547,7 @@ module Playwright
533
547
 
534
548
  class APIRequestContext
535
549
  def delete: (String url, ?data: (String | String | untyped), ?failOnStatusCode: bool, ?form: Hash[untyped, untyped], ?headers: Hash[untyped, untyped], ?ignoreHTTPSErrors: bool, ?maxRedirects: Integer, ?multipart: Hash[untyped, untyped], ?params: Hash[untyped, untyped], ?timeout: Float) -> APIResponse
536
- def dispose: -> void
550
+ def dispose: (?reason: String) -> void
537
551
  def fetch: ((String | Request) urlOrRequest, ?data: (String | String | untyped), ?failOnStatusCode: bool, ?form: Hash[untyped, untyped], ?headers: Hash[untyped, untyped], ?ignoreHTTPSErrors: bool, ?maxRedirects: Integer, ?method: String, ?multipart: Hash[untyped, untyped], ?params: Hash[untyped, untyped], ?timeout: Float) -> APIResponse
538
552
  def get: (String url, ?data: (String | String | untyped), ?failOnStatusCode: bool, ?form: Hash[untyped, untyped], ?headers: Hash[untyped, untyped], ?ignoreHTTPSErrors: bool, ?maxRedirects: Integer, ?multipart: Hash[untyped, untyped], ?params: Hash[untyped, untyped], ?timeout: Float) -> APIResponse
539
553
  def head: (String url, ?data: (String | String | untyped), ?failOnStatusCode: bool, ?form: Hash[untyped, untyped], ?headers: Hash[untyped, untyped], ?ignoreHTTPSErrors: bool, ?maxRedirects: Integer, ?multipart: Hash[untyped, untyped], ?params: Hash[untyped, untyped], ?timeout: Float) -> APIResponse
@@ -562,7 +576,7 @@ module Playwright
562
576
  def not_to_have_css: (String name, (String | Regexp) value, ?timeout: Float) -> void
563
577
  def not_to_have_id: ((String | Regexp) id, ?timeout: Float) -> void
564
578
  def not_to_have_js_property: (String name, untyped value, ?timeout: Float) -> void
565
- def not_to_have_role: ((String | Regexp) name, ?timeout: Float) -> void
579
+ def not_to_have_role: (("alert" | "alertdialog" | "application" | "article" | "banner" | "blockquote" | "button" | "caption" | "cell" | "checkbox" | "code" | "columnheader" | "combobox" | "complementary" | "contentinfo" | "definition" | "deletion" | "dialog" | "directory" | "document" | "emphasis" | "feed" | "figure" | "form" | "generic" | "grid" | "gridcell" | "group" | "heading" | "img" | "insertion" | "link" | "list" | "listbox" | "listitem" | "log" | "main" | "marquee" | "math" | "meter" | "menu" | "menubar" | "menuitem" | "menuitemcheckbox" | "menuitemradio" | "navigation" | "none" | "note" | "option" | "paragraph" | "presentation" | "progressbar" | "radio" | "radiogroup" | "region" | "row" | "rowgroup" | "rowheader" | "scrollbar" | "search" | "searchbox" | "separator" | "slider" | "spinbutton" | "status" | "strong" | "subscript" | "superscript" | "switch" | "tab" | "table" | "tablist" | "tabpanel" | "term" | "textbox" | "time" | "timer" | "toolbar" | "tooltip" | "tree" | "treegrid" | "treeitem") role, ?timeout: Float) -> void
566
580
  def not_to_have_text: ((String | Regexp | Array[untyped] | Array[untyped] | Array[untyped]) expected, ?ignoreCase: bool, ?timeout: Float, ?useInnerText: bool) -> void
567
581
  def not_to_have_value: ((String | Regexp) value, ?timeout: Float) -> void
568
582
  def not_to_have_values: ((Array[untyped] | Array[untyped] | Array[untyped]) values, ?timeout: Float) -> void
@@ -593,7 +607,7 @@ module Playwright
593
607
 
594
608
  class PageAssertions
595
609
  def not_to_have_title: ((String | Regexp) titleOrRegExp, ?timeout: Float) -> void
596
- def not_to_have_url: ((String | Regexp) urlOrRegExp, ?timeout: Float) -> void
610
+ def not_to_have_url: ((String | Regexp) urlOrRegExp, ?ignoreCase: bool, ?timeout: Float) -> void
597
611
  def to_have_title: ((String | Regexp) titleOrRegExp, ?timeout: Float) -> void
598
612
  def to_have_url: ((String | Regexp) urlOrRegExp, ?ignoreCase: bool, ?timeout: Float) -> void
599
613
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: playwright-ruby-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.44.0
4
+ version: 1.45.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - YusukeIwaki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-05-20 00:00:00.000000000 Z
11
+ date: 2024-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -217,6 +217,7 @@ files:
217
217
  - documentation/docs/api/browser_context.md
218
218
  - documentation/docs/api/browser_type.md
219
219
  - documentation/docs/api/cdp_session.md
220
+ - documentation/docs/api/clock.md
220
221
  - documentation/docs/api/console_message.md
221
222
  - documentation/docs/api/dialog.md
222
223
  - documentation/docs/api/download.md
@@ -310,6 +311,7 @@ files:
310
311
  - lib/playwright/channel_owners/web_socket.rb
311
312
  - lib/playwright/channel_owners/worker.rb
312
313
  - lib/playwright/channel_owners/writable_stream.rb
314
+ - lib/playwright/clock_impl.rb
313
315
  - lib/playwright/connection.rb
314
316
  - lib/playwright/console_message_impl.rb
315
317
  - lib/playwright/download_impl.rb
@@ -363,6 +365,7 @@ files:
363
365
  - lib/playwright_api/browser_context.rb
364
366
  - lib/playwright_api/browser_type.rb
365
367
  - lib/playwright_api/cdp_session.rb
368
+ - lib/playwright_api/clock.rb
366
369
  - lib/playwright_api/console_message.rb
367
370
  - lib/playwright_api/dialog.rb
368
371
  - lib/playwright_api/download.rb
@@ -410,5 +413,5 @@ requirements: []
410
413
  rubygems_version: 3.3.27
411
414
  signing_key:
412
415
  specification_version: 4
413
- summary: The Ruby binding of playwright driver 1.44.0
416
+ summary: The Ruby binding of playwright driver 1.45.0
414
417
  test_files: []