playwright-ruby-client 1.22.0 → 1.25.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/documentation/docs/api/accessibility.md +8 -0
  3. data/documentation/docs/api/api_request_context.md +8 -8
  4. data/documentation/docs/api/browser.md +30 -5
  5. data/documentation/docs/api/browser_context.md +20 -7
  6. data/documentation/docs/api/browser_type.md +4 -0
  7. data/documentation/docs/api/download.md +1 -1
  8. data/documentation/docs/api/element_handle.md +1 -6
  9. data/documentation/docs/api/experimental/android_device.md +4 -0
  10. data/documentation/docs/api/file_chooser.md +1 -1
  11. data/documentation/docs/api/locator.md +15 -7
  12. data/documentation/docs/api/page.md +21 -4
  13. data/documentation/docs/api/request.md +3 -1
  14. data/documentation/docs/api/response.md +12 -1
  15. data/documentation/docs/api/route.md +65 -0
  16. data/documentation/docs/api/selectors.md +2 -2
  17. data/documentation/docs/api/tracing.md +1 -1
  18. data/documentation/docs/include/api_coverage.md +5 -3
  19. data/documentation/package.json +4 -4
  20. data/documentation/yarn.lock +1876 -1304
  21. data/lib/playwright/channel.rb +1 -3
  22. data/lib/playwright/channel_owner.rb +13 -1
  23. data/lib/playwright/channel_owners/browser.rb +13 -0
  24. data/lib/playwright/channel_owners/browser_context.rb +82 -14
  25. data/lib/playwright/channel_owners/browser_type.rb +4 -0
  26. data/lib/playwright/channel_owners/frame.rb +16 -2
  27. data/lib/playwright/channel_owners/local_utils.rb +29 -0
  28. data/lib/playwright/channel_owners/page.rb +43 -15
  29. data/lib/playwright/channel_owners/request.rb +31 -6
  30. data/lib/playwright/channel_owners/response.rb +6 -0
  31. data/lib/playwright/channel_owners/route.rb +104 -45
  32. data/lib/playwright/connection.rb +20 -9
  33. data/lib/playwright/har_router.rb +82 -0
  34. data/lib/playwright/http_headers.rb +1 -1
  35. data/lib/playwright/javascript/regex.rb +23 -0
  36. data/lib/playwright/javascript/value_parser.rb +4 -0
  37. data/lib/playwright/javascript/value_serializer.rb +5 -4
  38. data/lib/playwright/javascript.rb +1 -0
  39. data/lib/playwright/locator_impl.rb +3 -5
  40. data/lib/playwright/route_handler.rb +2 -6
  41. data/lib/playwright/utils.rb +31 -6
  42. data/lib/playwright/version.rb +2 -2
  43. data/lib/playwright.rb +2 -0
  44. data/lib/playwright_api/accessibility.rb +8 -0
  45. data/lib/playwright_api/android_device.rb +5 -1
  46. data/lib/playwright_api/api_request_context.rb +8 -8
  47. data/lib/playwright_api/browser.rb +28 -2
  48. data/lib/playwright_api/browser_context.rb +19 -9
  49. data/lib/playwright_api/browser_type.rb +8 -2
  50. data/lib/playwright_api/download.rb +1 -1
  51. data/lib/playwright_api/element_handle.rb +1 -12
  52. data/lib/playwright_api/file_chooser.rb +1 -1
  53. data/lib/playwright_api/locator.rb +13 -13
  54. data/lib/playwright_api/page.rb +19 -6
  55. data/lib/playwright_api/request.rb +8 -1
  56. data/lib/playwright_api/response.rb +14 -1
  57. data/lib/playwright_api/route.rb +61 -2
  58. data/lib/playwright_api/selectors.rb +1 -1
  59. data/lib/playwright_api/tracing.rb +1 -1
  60. metadata +5 -4
  61. data/lib/playwright_api/local_utils.rb +0 -9
@@ -3,13 +3,28 @@ require 'mime/types'
3
3
 
4
4
  module Playwright
5
5
  define_channel_owner :Route do
6
+ private def set_handling_future(future)
7
+ @handling_future = future
8
+ end
9
+
10
+ private def handling_with_result(done, &block)
11
+ chain = @handling_future
12
+ raise 'Route is already handled!' unless chain
13
+ block.call
14
+ @handling_future = nil
15
+ chain.fulfill(done)
16
+ end
17
+
6
18
  def request
7
19
  ChannelOwners::Request.from(@initializer['request'])
8
20
  end
9
21
 
10
22
  def abort(errorCode: nil)
11
- params = { errorCode: errorCode }.compact
12
- @channel.async_send_message_to_server('abort', params)
23
+ handling_with_result(true) do
24
+ params = { errorCode: errorCode }.compact
25
+ # TODO _race_with_page_close
26
+ @channel.async_send_message_to_server('abort', params)
27
+ end
13
28
  end
14
29
 
15
30
  def fulfill(
@@ -19,69 +34,113 @@ module Playwright
19
34
  path: nil,
20
35
  status: nil,
21
36
  response: nil)
22
- params = {
23
- contentType: contentType,
24
- status: status,
25
- }.compact
26
- option_body = body
37
+ handling_with_result(true) do
38
+ params = {
39
+ contentType: contentType,
40
+ status: status,
41
+ }.compact
42
+ option_body = body
27
43
 
28
- if response
29
- params[:status] ||= response.status
30
- params[:headers] ||= response.headers
44
+ if response
45
+ params[:status] ||= response.status
46
+ params[:headers] ||= response.headers
31
47
 
32
- if !body && !path && response.is_a?(APIResponse)
33
- if response.send(:_request).send(:same_connection?, self)
34
- params[:fetchResponseUid] = response.send(:fetch_uid)
35
- else
36
- option_body = response.body
48
+ if !body && !path && response.is_a?(APIResponse)
49
+ if response.send(:_request).send(:same_connection?, self)
50
+ params[:fetchResponseUid] = response.send(:fetch_uid)
51
+ else
52
+ option_body = response.body
53
+ end
37
54
  end
38
55
  end
39
- end
40
56
 
41
- content =
42
- if option_body
43
- option_body
57
+ content =
58
+ if option_body
59
+ option_body
60
+ elsif path
61
+ File.read(path)
62
+ else
63
+ nil
64
+ end
65
+
66
+ param_headers = headers || {}
67
+ if contentType
68
+ param_headers['content-type'] = contentType
44
69
  elsif path
45
- File.read(path)
46
- else
47
- nil
70
+ param_headers['content-type'] = mime_type_for(path)
48
71
  end
49
72
 
50
- param_headers = headers || {}
51
- if contentType
52
- param_headers['content-type'] = contentType
53
- elsif path
54
- param_headers['content-type'] = mime_type_for(path)
55
- end
56
-
57
- if content
58
- if content.is_a?(String)
59
- params[:body] = content
60
- params[:isBase64] = false
61
- else
62
- params[:body] = Base64.strict_encode64(content)
63
- params[:isBase64] = true
73
+ if content
74
+ if content.is_a?(String)
75
+ params[:body] = content
76
+ params[:isBase64] = false
77
+ else
78
+ params[:body] = Base64.strict_encode64(content)
79
+ params[:isBase64] = true
80
+ end
81
+ param_headers['content-length'] ||= content.length.to_s
64
82
  end
65
- param_headers['content-length'] ||= content.length.to_s
83
+
84
+ params[:headers] = HttpHeaders.new(param_headers).as_serialized
85
+
86
+ @channel.async_send_message_to_server('fulfill', params)
66
87
  end
88
+ end
67
89
 
68
- params[:headers] = HttpHeaders.new(param_headers).as_serialized
90
+ def fallback(headers: nil, method: nil, postData: nil, url: nil)
91
+ overrides = {
92
+ headers: headers,
93
+ method: method,
94
+ postData: postData,
95
+ url: url,
96
+ }.compact
69
97
 
70
- @channel.async_send_message_to_server('fulfill', params)
98
+ handling_with_result(false) do
99
+ request.apply_fallback_overrides(overrides)
100
+ end
71
101
  end
72
102
 
73
103
  def continue(headers: nil, method: nil, postData: nil, url: nil)
74
- overrides = { url: url, method: method }.compact
104
+ overrides = {
105
+ headers: headers,
106
+ method: method,
107
+ postData: postData,
108
+ url: url,
109
+ }.compact
75
110
 
76
- if headers
77
- overrides[:headers] = HttpHeaders.new(headers).as_serialized
111
+ handling_with_result(true) do
112
+ request.apply_fallback_overrides(overrides)
113
+ async_continue_route
78
114
  end
115
+ end
79
116
 
80
- if postData
81
- overrides[:postData] = Base64.strict_encode64(postData)
117
+ private def async_continue_route
118
+ post_data_for_wire =
119
+ if (post_data_from_overrides = request.send(:fallback_overrides)[:postData])
120
+ post_data_for_wire = Base64.strict_encode64(post_data_from_overrides)
121
+ else
122
+ nil
123
+ end
124
+
125
+ params = request.send(:fallback_overrides).dup
126
+
127
+ if params[:headers]
128
+ params[:headers] = HttpHeaders.new(params[:headers]).as_serialized
129
+ end
130
+
131
+ if post_data_for_wire
132
+ params[:postData] = post_data_for_wire
82
133
  end
83
134
 
84
- @channel.async_send_message_to_server('continue', overrides)
135
+ # TODO _race_with_page_close
136
+ @channel.async_send_message_to_server('continue', params)
137
+ end
138
+
139
+ def redirect_navigation_request(url)
140
+ handling_with_result(true) do
141
+ # TODO _race_with_page_close
142
+ @channel.send_message_to_server('redirectNavigationRequest', { url: url })
143
+ end
85
144
  end
86
145
 
87
146
  private def mime_type_for(filepath)
@@ -24,6 +24,8 @@ module Playwright
24
24
  @remote = false
25
25
  end
26
26
 
27
+ attr_reader :local_utils
28
+
27
29
  def mark_as_remote
28
30
  @remote = true
29
31
  end
@@ -127,28 +129,37 @@ module Playwright
127
129
  params = msg['params']
128
130
 
129
131
  if method == "__create__"
130
- create_remote_object(
132
+ remote_object = create_remote_object(
131
133
  parent_guid: guid,
132
134
  type: params["type"],
133
135
  guid: params["guid"],
134
136
  initializer: params["initializer"],
135
137
  )
138
+ if remote_object.is_a?(ChannelOwners::LocalUtils)
139
+ @local_utils = remote_object
140
+ end
136
141
  return
137
142
  end
138
143
 
139
- if method == "__dispose__"
140
- object = @objects[guid]
141
- unless object
142
- raise "Cannot find object to dispose: #{guid}"
144
+ object = @objects[guid]
145
+ unless object
146
+ raise "Cannot find object to \"#{method}\": #{guid}"
147
+ end
148
+
149
+ if method == "__adopt__"
150
+ child = @objects[params["guid"]]
151
+ unless child
152
+ raise "Unknown new child: #{params['guid']}"
143
153
  end
144
- object.send(:dispose!)
154
+ object.send(:adopt!, child)
145
155
  return
146
156
  end
147
157
 
148
- object = @objects[guid]
149
- unless object
150
- raise "Cannot find object to emit \"#{method}\": #{guid}"
158
+ if method == "__dispose__"
159
+ object.send(:dispose!)
160
+ return
151
161
  end
162
+
152
163
  object.channel.emit(method, replace_guids_with_channels(params))
153
164
  end
154
165
 
@@ -0,0 +1,82 @@
1
+ module Playwright
2
+ class HarRouter
3
+ # @param local_utils [LocalUtils]
4
+ # @param file [String]
5
+ # @param not_found_action [String] 'abort' or 'fallback'
6
+ # @param url_match [String||Regexp|nil]
7
+ def self.create(local_utils, file, not_found_action, url_match: nil)
8
+ har_id = local_utils.har_open(file)
9
+
10
+ new(
11
+ local_utils: local_utils,
12
+ har_id: har_id,
13
+ not_found_action: not_found_action,
14
+ url_match: url_match,
15
+ )
16
+ end
17
+
18
+ # @param local_utils [LocalUtils]
19
+ # @param har_id [String]
20
+ # @param not_found_action [String] 'abort' or 'fallback'
21
+ # @param url_match [String||Regexp|nil]
22
+ def initialize(local_utils:, har_id:, not_found_action:, url_match: nil)
23
+ unless ['abort', 'fallback'].include?(not_found_action)
24
+ raise ArgumentError.new("not_found_action must be either 'abort' or 'fallback'. '#{not_found_action}' is specified.")
25
+ end
26
+
27
+ @local_utils = local_utils
28
+ @har_id = har_id
29
+ @not_found_action = not_found_action
30
+ @url_match = url_match || '**/*'
31
+ @debug = ENV['DEBUG'].to_s == 'true' || ENV['DEBUG'].to_s == '1'
32
+ end
33
+
34
+ private def handle(route, request)
35
+ response = @local_utils.har_lookup(
36
+ har_id: @har_id,
37
+ url: request.url,
38
+ method: request.method,
39
+ headers: request.headers_array,
40
+ post_data: request.post_data_buffer,
41
+ is_navigation_request: request.navigation_request?,
42
+ )
43
+ case response['action']
44
+ when 'redirect'
45
+ redirect_url = response['redirectURL']
46
+ puts "pw:api HAR: #{request.url} redirected to #{redirect_url}" if @debug
47
+ route.redirect_navigation_request(redirect_url)
48
+ when 'fulfill'
49
+ route.fulfill(
50
+ status: response['status'],
51
+ headers: response['headers'].map { |header| [header['name'], header['value']] }.to_h,
52
+ body: Base64.strict_decode64(response['body']),
53
+ )
54
+ else
55
+ # Report the error, but fall through to the default handler.
56
+ if response['action'] == 'error'
57
+ puts "pw:api HAR: #{response['message']} redirected to #{redirect_url}" if @debug
58
+ end
59
+
60
+ if @not_found_action == 'abort'
61
+ route.abort
62
+ else
63
+ route.fallback
64
+ end
65
+ end
66
+ end
67
+
68
+ def add_context_route(context)
69
+ context.route(@url_match, method(:handle))
70
+ context.once(Events::BrowserContext::Close, method(:dispose))
71
+ end
72
+
73
+ def add_page_route(page)
74
+ page.route(@url_match, method(:handle))
75
+ page.once(Events::Page::Close, method(:dispose))
76
+ end
77
+
78
+ def dispose
79
+ @local_utils.async_har_close(@har_id)
80
+ end
81
+ end
82
+ end
@@ -7,7 +7,7 @@ module Playwright
7
7
 
8
8
  def as_serialized
9
9
  @headers.map do |key, value|
10
- { name: key, value: value }
10
+ { 'name' => key, 'value' => value }
11
11
  end
12
12
  end
13
13
  end
@@ -0,0 +1,23 @@
1
+ module Playwright
2
+ module JavaScript
3
+ class Regex
4
+ def initialize(regexp)
5
+ unless regexp.is_a?(Regexp)
6
+ raise ArgumentError("Argument must be a Regexp: #{regexp} (#{regexp.class})")
7
+ end
8
+
9
+ @source = regexp.source
10
+ @flag = flag_for(regexp)
11
+ end
12
+
13
+ attr_reader :source, :flag
14
+
15
+ private def flag_for(regexp)
16
+ flags = []
17
+ flags << 'ms' if (regexp.options & Regexp::MULTILINE) != 0
18
+ flags << 'i' if (regexp.options & Regexp::IGNORECASE) != 0
19
+ flags.join('')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -48,6 +48,10 @@ module Playwright
48
48
  return DateTime.parse(hash['d'])
49
49
  end
50
50
 
51
+ if hash.key?('u')
52
+ return URI(hash['u'])
53
+ end
54
+
51
55
  if hash.key?('r')
52
56
  # @see https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp
53
57
  # @see https://docs.ruby-lang.org/ja/latest/class/Regexp.html
@@ -1,4 +1,5 @@
1
1
  require_relative './visitor_info'
2
+ require_relative './regex'
2
3
 
3
4
  module Playwright
4
5
  module JavaScript
@@ -39,11 +40,11 @@ module Playwright
39
40
  when Time
40
41
  require 'time'
41
42
  { d: value.utc.iso8601 }
43
+ when URI
44
+ { u: value.to_s }
42
45
  when Regexp
43
- flags = []
44
- flags << 'ms' if (value.options & Regexp::MULTILINE) != 0
45
- flags << 'i' if (value.options & Regexp::IGNORECASE) != 0
46
- { r: { p: value.source, f: flags.join('') } }
46
+ regex_value = Regex.new(value)
47
+ { r: { p: regex_value.source, f: regex_value.flag } }
47
48
  when -> (value) { @visited.ref(value) }
48
49
  { ref: @visited.ref(value) }
49
50
  when Array
@@ -1,3 +1,4 @@
1
1
  require_relative './javascript/expression'
2
2
  require_relative './javascript/value_parser'
3
3
  require_relative './javascript/value_serializer'
4
+ require_relative './javascript/regex'
@@ -31,11 +31,9 @@ module Playwright
31
31
 
32
32
  case hasText
33
33
  when Regexp
34
- source = EscapeWithQuotes.new(hasText.source, '"')
35
- flags = []
36
- flags << 'ms' if (hasText.options & Regexp::MULTILINE) != 0
37
- flags << 'i' if (hasText.options & Regexp::IGNORECASE) != 0
38
- selector_scopes << ":scope:text-matches(#{source}, \"#{flags.join('')}\")"
34
+ regex = JavaScript::Regex.new(hasText)
35
+ source = EscapeWithQuotes.new(regex.source, '"')
36
+ selector_scopes << "has=#{"text=/#{regex.source}/#{regex.flag}".to_json}"
39
37
  when String
40
38
  text = EscapeWithQuotes.new(hasText, '"')
41
39
  selector_scopes << ":scope:has-text(#{text})"
@@ -50,12 +50,8 @@ module Playwright
50
50
  def async_handle(route, request)
51
51
  @counter.increment
52
52
 
53
- Concurrent::Promises.future do
54
- begin
55
- @handler.call(route, request)
56
- rescue => err
57
- puts err, err.backtrace
58
- end
53
+ Concurrent::Promises.future { @handler.call(route, request) }.rescue do |err|
54
+ puts err, err.backtrace
59
55
  end
60
56
  end
61
57
 
@@ -1,6 +1,36 @@
1
1
  module Playwright
2
2
  module Utils
3
3
  module PrepareBrowserContextOptions
4
+ private def prepare_record_har_options(params)
5
+ out_params = {
6
+ path: params.delete(:record_har_path)
7
+ }
8
+ if params[:record_har_url_filter]
9
+ opt = params.delete(:record_har_url_filter)
10
+ if opt.is_a?(Regexp)
11
+ regex = ::Playwright::JavaScript::Regex.new(opt)
12
+ out_params[:urlRegexSource] = regex.source
13
+ out_params[:urlRegexFlags] = regex.flag
14
+ elsif opt.is_a?(String)
15
+ out_params[:urlGlob] = opt
16
+ end
17
+ end
18
+ if params[:record_har_mode]
19
+ out_params[:mode] = params.delete(:record_har_mode)
20
+ end
21
+ if params[:record_har_content]
22
+ out_params[:content] = params.delete(:record_har_content)
23
+ end
24
+ if params[:record_har_omit_content]
25
+ old_api_omit_content = params.delete(:record_har_omit_content)
26
+ if old_api_omit_content
27
+ out_params[:content] ||= 'omit'
28
+ end
29
+ end
30
+
31
+ out_params
32
+ end
33
+
4
34
  # @see https://github.com/microsoft/playwright/blob/5a2cfdbd47ed3c3deff77bb73e5fac34241f649d/src/client/browserContext.ts#L265
5
35
  private def prepare_browser_context_options(params)
6
36
  if params[:noViewport] == 0
@@ -11,12 +41,7 @@ module Playwright
11
41
  params[:extraHTTPHeaders] = ::Playwright::HttpHeaders.new(params[:extraHTTPHeaders]).as_serialized
12
42
  end
13
43
  if params[:record_har_path]
14
- params[:recordHar] = {
15
- path: params.delete(:record_har_path)
16
- }
17
- if params[:record_har_omit_content]
18
- params[:recordHar][:omitContent] = params.delete(:record_har_omit_content)
19
- end
44
+ params[:recordHar] = prepare_record_har_options(params)
20
45
  end
21
46
  if params[:record_video_dir]
22
47
  params[:recordVideo] = {
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playwright
4
- VERSION = '1.22.0'
5
- COMPATIBLE_PLAYWRIGHT_VERSION = '1.22.1'
4
+ VERSION = '1.25.0'
5
+ COMPATIBLE_PLAYWRIGHT_VERSION = '1.25.0'
6
6
  end
data/lib/playwright.rb CHANGED
@@ -20,6 +20,7 @@ require 'playwright/channel_owner'
20
20
  require 'playwright/http_headers'
21
21
  require 'playwright/input_files'
22
22
  require 'playwright/connection'
23
+ require 'playwright/har_router'
23
24
  require 'playwright/raw_headers'
24
25
  require 'playwright/route_handler'
25
26
  require 'playwright/select_option_values'
@@ -143,6 +144,7 @@ module Playwright
143
144
  playwright = connection.initialize_playwright
144
145
  browser = playwright.send(:pre_launched_browser)
145
146
  browser.should_close_connection_on_close!
147
+ browser.send(:update_browser_type, browser.browser_type)
146
148
  Execution.new(connection, PlaywrightApi.wrap(playwright), PlaywrightApi.wrap(browser))
147
149
  rescue
148
150
  connection.stop
@@ -1,4 +1,8 @@
1
1
  module Playwright
2
+ # **DEPRECATED** This class is deprecated. Please use other libraries such as [Axe](https://www.deque.com/axe/) if you
3
+ # need to test page accessibility. See our Node.js [guide](https://playwright.dev/docs/accessibility-testing) for
4
+ # integration with Axe.
5
+ #
2
6
  # The Accessibility class provides methods for inspecting Chromium's accessibility tree. The accessibility tree is used by
3
7
  # assistive technology such as [screen readers](https://en.wikipedia.org/wiki/Screen_reader) or
4
8
  # [switches](https://en.wikipedia.org/wiki/Switch_access).
@@ -14,6 +18,10 @@ module Playwright
14
18
  # only the "interesting" nodes of the tree.
15
19
  class Accessibility < PlaywrightApi
16
20
 
21
+ # **DEPRECATED** This method is deprecated. Please use other libraries such as [Axe](https://www.deque.com/axe/) if you
22
+ # need to test page accessibility. See our Node.js [guide](https://playwright.dev/docs/accessibility-testing) for
23
+ # integration with Axe.
24
+ #
17
25
  # Captures the current state of the accessibility tree. The returned object represents the root accessible node of the
18
26
  # page.
19
27
  #
@@ -57,18 +57,22 @@ module Playwright
57
57
  noViewport: nil,
58
58
  offline: nil,
59
59
  permissions: nil,
60
+ record_har_content: nil,
61
+ record_har_mode: nil,
60
62
  record_har_omit_content: nil,
61
63
  record_har_path: nil,
64
+ record_har_url_filter: nil,
62
65
  record_video_dir: nil,
63
66
  record_video_size: nil,
64
67
  reducedMotion: nil,
65
68
  screen: nil,
69
+ serviceWorkers: nil,
66
70
  strictSelectors: nil,
67
71
  timezoneId: nil,
68
72
  userAgent: nil,
69
73
  viewport: nil,
70
74
  &block)
71
- wrap_impl(@impl.launch_browser(acceptDownloads: unwrap_impl(acceptDownloads), baseURL: unwrap_impl(baseURL), bypassCSP: unwrap_impl(bypassCSP), colorScheme: unwrap_impl(colorScheme), command: unwrap_impl(command), deviceScaleFactor: unwrap_impl(deviceScaleFactor), extraHTTPHeaders: unwrap_impl(extraHTTPHeaders), forcedColors: unwrap_impl(forcedColors), geolocation: unwrap_impl(geolocation), hasTouch: unwrap_impl(hasTouch), httpCredentials: unwrap_impl(httpCredentials), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), isMobile: unwrap_impl(isMobile), javaScriptEnabled: unwrap_impl(javaScriptEnabled), locale: unwrap_impl(locale), noViewport: unwrap_impl(noViewport), offline: unwrap_impl(offline), permissions: unwrap_impl(permissions), record_har_omit_content: unwrap_impl(record_har_omit_content), record_har_path: unwrap_impl(record_har_path), record_video_dir: unwrap_impl(record_video_dir), record_video_size: unwrap_impl(record_video_size), reducedMotion: unwrap_impl(reducedMotion), screen: unwrap_impl(screen), strictSelectors: unwrap_impl(strictSelectors), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
75
+ wrap_impl(@impl.launch_browser(acceptDownloads: unwrap_impl(acceptDownloads), baseURL: unwrap_impl(baseURL), bypassCSP: unwrap_impl(bypassCSP), colorScheme: unwrap_impl(colorScheme), command: unwrap_impl(command), deviceScaleFactor: unwrap_impl(deviceScaleFactor), extraHTTPHeaders: unwrap_impl(extraHTTPHeaders), forcedColors: unwrap_impl(forcedColors), geolocation: unwrap_impl(geolocation), hasTouch: unwrap_impl(hasTouch), httpCredentials: unwrap_impl(httpCredentials), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), isMobile: unwrap_impl(isMobile), javaScriptEnabled: unwrap_impl(javaScriptEnabled), locale: unwrap_impl(locale), noViewport: unwrap_impl(noViewport), offline: unwrap_impl(offline), permissions: unwrap_impl(permissions), record_har_content: unwrap_impl(record_har_content), record_har_mode: unwrap_impl(record_har_mode), record_har_omit_content: unwrap_impl(record_har_omit_content), record_har_path: unwrap_impl(record_har_path), record_har_url_filter: unwrap_impl(record_har_url_filter), record_video_dir: unwrap_impl(record_video_dir), record_video_size: unwrap_impl(record_video_size), reducedMotion: unwrap_impl(reducedMotion), screen: unwrap_impl(screen), serviceWorkers: unwrap_impl(serviceWorkers), strictSelectors: unwrap_impl(strictSelectors), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
72
76
  end
73
77
 
74
78
  # Performs a long tap on the widget defined by `selector`.
@@ -8,14 +8,14 @@ module Playwright
8
8
  #
9
9
  # **Cookie management**
10
10
  #
11
- # `APIRequestContext` retuned by [`property: BrowserContext.request`] and [`property: Page.request`] shares cookie storage
12
- # with the corresponding `BrowserContext`. Each API request will have `Cookie` header populated with the values from the
13
- # browser context. If the API response contains `Set-Cookie` header it will automatically update `BrowserContext` cookies
14
- # and requests made from the page will pick them up. This means that if you log in using this API, your e2e test will be
15
- # logged in and vice versa.
11
+ # `APIRequestContext` returned by [`property: BrowserContext.request`] and [`property: Page.request`] shares cookie
12
+ # storage with the corresponding `BrowserContext`. Each API request will have `Cookie` header populated with the values
13
+ # from the browser context. If the API response contains `Set-Cookie` header it will automatically update `BrowserContext`
14
+ # cookies and requests made from the page will pick them up. This means that if you log in using this API, your e2e test
15
+ # will be logged in and vice versa.
16
16
  #
17
- # If you want API requests to not interfere with the browser cookies you shoud create a new `APIRequestContext` by calling
18
- # [`method: APIRequest.newContext`]. Such `APIRequestContext` object will have its own isolated cookie storage.
17
+ # If you want API requests to not interfere with the browser cookies you should create a new `APIRequestContext` by
18
+ # calling [`method: APIRequest.newContext`]. Such `APIRequestContext` object will have its own isolated cookie storage.
19
19
  #
20
20
  # ```python sync
21
21
  # import os
@@ -28,7 +28,7 @@ module Playwright
28
28
  # with sync_playwright() as p:
29
29
  # # This will launch a new browser, create a context and page. When making HTTP
30
30
  # # requests with the internal APIRequestContext (e.g. `context.request` or `page.request`)
31
- # # it will automatically set the cookies to the browser page and vise versa.
31
+ # # it will automatically set the cookies to the browser page and vice versa.
32
32
  # browser = p.chromium.launch()
33
33
  # context = browser.new_context(base_url="https://api.github.com")
34
34
  # api_request_context = context.request