capybara-playwright-driver 0.5.9 → 0.5.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/AGENTS.md +8 -0
- data/Gemfile +1 -0
- data/lib/capybara/playwright/browser.rb +35 -5
- data/lib/capybara/playwright/node.rb +40 -7
- data/lib/capybara/playwright/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a9766817ce50a7580acf4f72c062780da5a2363ea838dea3a8f17207c359c144
|
|
4
|
+
data.tar.gz: 5b48eb5b0eb4145088457e8b0c1a26c5843f80dc3e3d9acf120c095fd2d7691a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d7b079c7c184643a16cfae94e7aaafd325460a3a13e3ece9cf453b127045a44a8ea008b29b65c326325ad3cbb7b3a8f092ff325267df512ac3f1645565ef6baa
|
|
7
|
+
data.tar.gz: 46290aabe5623d54094efa2cd30369261ca32525b99835e0f6e393ddc48de3e9d1e21011e64cd61dfd00531bf05818dab69525c1cb450f9f2d46679b9c19b0c5
|
data/AGENTS.md
CHANGED
|
@@ -105,3 +105,11 @@ end
|
|
|
105
105
|
## General Guidance
|
|
106
106
|
- Prefer concise Ruby that reads top-to-bottom without carrying unnecessary temporary state.
|
|
107
107
|
- Prefer small private helper objects only when they reduce complexity. Once extracted, give them Ruby-like method names and keep their public surface minimal.
|
|
108
|
+
|
|
109
|
+
## How to execute RSpec or Ruby
|
|
110
|
+
|
|
111
|
+
`ruby` uses macOS system ruby interpreter (typically 2.6 or older). rbenv should be used.
|
|
112
|
+
|
|
113
|
+
- Do not run the full `spec/capybara/playwright_spec.rb` or full RSpec suite locally; run broad coverage in GitHub Actions.
|
|
114
|
+
- To run a focused Playwright compatibility check locally, use an example filter, for example:
|
|
115
|
+
`RBENV_VERSION=$(cat .ruby-version) ~/.rbenv/shims/bundle exec rspec spec/capybara/playwright_spec.rb --example fill_in`
|
data/Gemfile
CHANGED
|
@@ -15,6 +15,7 @@ gem 'rack-test_server'
|
|
|
15
15
|
gem 'rake', '~> 13.0.3'
|
|
16
16
|
gem 'rspec', '~> 3.11.0'
|
|
17
17
|
gem 'rubocop-rspec'
|
|
18
|
+
gem 'selenium-webdriver', '~> 4.34.0' if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.2')
|
|
18
19
|
gem 'sinatra', '>= 1.4.0'
|
|
19
20
|
gem 'webrick'
|
|
20
21
|
gem 'websocket-driver'
|
|
@@ -89,10 +89,20 @@ module Capybara
|
|
|
89
89
|
}
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
+
private def firefox?
|
|
93
|
+
@playwright_browser.browser_type.name == 'firefox'
|
|
94
|
+
end
|
|
95
|
+
|
|
92
96
|
def refresh
|
|
93
|
-
|
|
97
|
+
if firefox?
|
|
98
|
+
# ref: https://github.com/microsoft/playwright/issues/39738
|
|
94
99
|
@playwright_page.capybara_current_frame.evaluate('() => { location.reload(true) }')
|
|
95
|
-
|
|
100
|
+
else
|
|
101
|
+
assert_page_alive {
|
|
102
|
+
response = @playwright_page.reload
|
|
103
|
+
@playwright_page.capybara_set_last_response(response)
|
|
104
|
+
}
|
|
105
|
+
end
|
|
96
106
|
end
|
|
97
107
|
|
|
98
108
|
def find_xpath(query, **options)
|
|
@@ -255,7 +265,8 @@ module Capybara
|
|
|
255
265
|
when /Element is not attached to the DOM/,
|
|
256
266
|
/Execution context was destroyed, most likely because of a navigation/,
|
|
257
267
|
/Cannot find context with specified id/,
|
|
258
|
-
/Unable to adopt element handle from a different document
|
|
268
|
+
/Unable to adopt element handle from a different document/,
|
|
269
|
+
/maybe frame was detached/
|
|
259
270
|
# ignore error for retry
|
|
260
271
|
@internal_logger.warn(err.message)
|
|
261
272
|
else
|
|
@@ -318,16 +329,35 @@ module Capybara
|
|
|
318
329
|
|
|
319
330
|
def window_size(handle)
|
|
320
331
|
on_window(handle) do |page|
|
|
321
|
-
page
|
|
332
|
+
outer_window_size(page)
|
|
322
333
|
end
|
|
323
334
|
end
|
|
324
335
|
|
|
325
336
|
def resize_window_to(handle, width, height)
|
|
326
337
|
on_window(handle) do |page|
|
|
327
|
-
page.viewport_size =
|
|
338
|
+
page.viewport_size = viewport_size_for(page, width, height)
|
|
328
339
|
end
|
|
329
340
|
end
|
|
330
341
|
|
|
342
|
+
# Capybara follows Selenium's outer window size semantics.
|
|
343
|
+
private def outer_window_size(page)
|
|
344
|
+
page.evaluate('() => [window.outerWidth || window.innerWidth, window.outerHeight || window.innerHeight]')
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
private def viewport_size_for(page, width, height)
|
|
348
|
+
inset_width, inset_height = page.evaluate(<<~JAVASCRIPT)
|
|
349
|
+
() => [
|
|
350
|
+
Math.max(0, (window.outerWidth || window.innerWidth) - window.innerWidth),
|
|
351
|
+
Math.max(0, (window.outerHeight || window.innerHeight) - window.innerHeight)
|
|
352
|
+
]
|
|
353
|
+
JAVASCRIPT
|
|
354
|
+
|
|
355
|
+
{
|
|
356
|
+
width: [width - inset_width, 0].max,
|
|
357
|
+
height: [height - inset_height, 0].max
|
|
358
|
+
}
|
|
359
|
+
end
|
|
360
|
+
|
|
331
361
|
def maximize_window(handle)
|
|
332
362
|
@internal_logger.warn("maximize_window is not supported in Playwright driver")
|
|
333
363
|
# incomplete in Playwright
|
|
@@ -258,7 +258,7 @@ module Capybara
|
|
|
258
258
|
end
|
|
259
259
|
|
|
260
260
|
private def capybara_default_wait_time
|
|
261
|
-
Capybara.default_max_wait_time * 1100 # with 10% buffer for allowing overhead.
|
|
261
|
+
Capybara.default_max_wait_time.to_f * 1100 # with 10% buffer for allowing overhead.
|
|
262
262
|
end
|
|
263
263
|
|
|
264
264
|
class NotActionableError < StandardError ; end
|
|
@@ -411,15 +411,13 @@ module Capybara
|
|
|
411
411
|
end
|
|
412
412
|
|
|
413
413
|
text = value.to_s
|
|
414
|
-
if press_enter = text.end_with?("\n")
|
|
414
|
+
if press_enter = text.end_with?("\r\n")
|
|
415
|
+
text = text[0...-2]
|
|
416
|
+
elsif press_enter = text.end_with?("\n")
|
|
415
417
|
text = text[0...-1]
|
|
416
418
|
end
|
|
417
419
|
|
|
418
|
-
|
|
419
|
-
@element.type(text, timeout: @timeout)
|
|
420
|
-
else
|
|
421
|
-
@element.fill(text, timeout: @timeout)
|
|
422
|
-
end
|
|
420
|
+
set_text(text, append: options[:clear] == :none)
|
|
423
421
|
|
|
424
422
|
if press_enter
|
|
425
423
|
@element.press('Enter', timeout: @timeout)
|
|
@@ -429,6 +427,41 @@ module Capybara
|
|
|
429
427
|
|
|
430
428
|
@internal_logger.info("Node#set: element is not editable. #{@element}")
|
|
431
429
|
end
|
|
430
|
+
|
|
431
|
+
private def set_text(text, append:)
|
|
432
|
+
# ElementHandle#type can refocus inherited contenteditable descendants and drop the input.
|
|
433
|
+
if @element.evaluate('el => el.isContentEditable') && !append
|
|
434
|
+
@element.fill(text, timeout: @timeout)
|
|
435
|
+
return
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
if text.include?("\t")
|
|
439
|
+
type_tab_separated_text(text, append: append)
|
|
440
|
+
return
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
grapheme_clusters = text.scan(/\X/)
|
|
444
|
+
fill_text = grapheme_clusters[0...-1].join
|
|
445
|
+
typed_text = grapheme_clusters[-1].to_s
|
|
446
|
+
|
|
447
|
+
if append
|
|
448
|
+
@element.type(fill_text, timeout: @timeout) unless fill_text.empty?
|
|
449
|
+
else
|
|
450
|
+
@element.fill(fill_text, timeout: @timeout)
|
|
451
|
+
end
|
|
452
|
+
@element.type(typed_text, timeout: @timeout) unless typed_text.empty?
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
private def type_tab_separated_text(text, append:)
|
|
456
|
+
head, *tail = text.split("\t", -1)
|
|
457
|
+
set_text(head, append: append)
|
|
458
|
+
keyboard = @element.owner_frame.page.keyboard
|
|
459
|
+
|
|
460
|
+
tail.each do |part|
|
|
461
|
+
keyboard.press('Tab')
|
|
462
|
+
keyboard.type(part) unless part.empty?
|
|
463
|
+
end
|
|
464
|
+
end
|
|
432
465
|
end
|
|
433
466
|
|
|
434
467
|
class FileUpload < Settable
|