ferrum 0.12 → 0.13
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/README.md +15 -20
- data/lib/ferrum/browser/client.rb +4 -4
- data/lib/ferrum/browser/command.rb +5 -6
- data/lib/ferrum/browser/options/base.rb +1 -4
- data/lib/ferrum/browser/options/chrome.rb +14 -9
- data/lib/ferrum/browser/options/firefox.rb +3 -6
- data/lib/ferrum/browser/options.rb +84 -0
- data/lib/ferrum/browser/process.rb +5 -6
- data/lib/ferrum/browser/version_info.rb +71 -0
- data/lib/ferrum/browser/xvfb.rb +1 -1
- data/lib/ferrum/browser.rb +176 -62
- data/lib/ferrum/context.rb +3 -2
- data/lib/ferrum/contexts.rb +2 -2
- data/lib/ferrum/cookies/cookie.rb +126 -0
- data/lib/ferrum/cookies.rb +86 -49
- data/lib/ferrum/dialog.rb +30 -0
- data/lib/ferrum/frame/dom.rb +177 -0
- data/lib/ferrum/frame/runtime.rb +41 -61
- data/lib/ferrum/frame.rb +90 -3
- data/lib/ferrum/headers.rb +28 -0
- data/lib/ferrum/keyboard.rb +45 -2
- data/lib/ferrum/mouse.rb +84 -0
- data/lib/ferrum/network/exchange.rb +86 -5
- data/lib/ferrum/network/request.rb +64 -0
- data/lib/ferrum/network/response.rb +83 -1
- data/lib/ferrum/network.rb +160 -0
- data/lib/ferrum/page/animation.rb +16 -0
- data/lib/ferrum/page/frames.rb +66 -11
- data/lib/ferrum/page/screenshot.rb +91 -0
- data/lib/ferrum/page/tracing.rb +26 -0
- data/lib/ferrum/page.rb +151 -32
- data/lib/ferrum/proxy.rb +91 -2
- data/lib/ferrum/target.rb +6 -4
- data/lib/ferrum/version.rb +1 -1
- metadata +5 -2
data/lib/ferrum/mouse.rb
CHANGED
@@ -10,10 +10,50 @@ module Ferrum
|
|
10
10
|
@x = @y = 0
|
11
11
|
end
|
12
12
|
|
13
|
+
#
|
14
|
+
# Scroll page to a given x, y coordinates.
|
15
|
+
#
|
16
|
+
# @param [Integer] top
|
17
|
+
# The pixel along the horizontal axis of the document that you want
|
18
|
+
# displayed in the upper left.
|
19
|
+
#
|
20
|
+
# @param [Integer] left
|
21
|
+
# The pixel along the vertical axis of the document that you want
|
22
|
+
# displayed in the upper left.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# browser.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara")
|
26
|
+
# browser.mouse.scroll_to(0, 400)
|
27
|
+
#
|
13
28
|
def scroll_to(top, left)
|
14
29
|
tap { @page.execute("window.scrollTo(#{top}, #{left})") }
|
15
30
|
end
|
16
31
|
|
32
|
+
#
|
33
|
+
# Click given coordinates, fires mouse move, down and up events.
|
34
|
+
#
|
35
|
+
# @param [Integer] x
|
36
|
+
#
|
37
|
+
# @param [Integer] y
|
38
|
+
#
|
39
|
+
# @param [Float] delay
|
40
|
+
# Delay between mouse down and mouse up events.
|
41
|
+
#
|
42
|
+
# @param [Float] wait
|
43
|
+
#
|
44
|
+
# @param [Hash{Symbol => Object}] options
|
45
|
+
# Additional keyword arguments.
|
46
|
+
#
|
47
|
+
# @option options [:left, :right] :button (:left)
|
48
|
+
# The mouse button to click.
|
49
|
+
#
|
50
|
+
# @option options [Integer] :count (1)
|
51
|
+
#
|
52
|
+
# @option options [Integer] :modifiers
|
53
|
+
# Bitfield for key modifiers. See`keyboard.modifiers`.
|
54
|
+
#
|
55
|
+
# @return [self]
|
56
|
+
#
|
17
57
|
def click(x:, y:, delay: 0, wait: CLICK_WAIT, **options)
|
18
58
|
move(x: x, y: y)
|
19
59
|
down(**options)
|
@@ -24,14 +64,58 @@ module Ferrum
|
|
24
64
|
self
|
25
65
|
end
|
26
66
|
|
67
|
+
#
|
68
|
+
# Mouse down for given coordinates.
|
69
|
+
#
|
70
|
+
# @param [Hash{Symbol => Object}] options
|
71
|
+
# Additional keyword arguments.
|
72
|
+
#
|
73
|
+
# @option options [:left, :right] :button (:left)
|
74
|
+
# The mouse button to click.
|
75
|
+
#
|
76
|
+
# @option options [Integer] :count (1)
|
77
|
+
#
|
78
|
+
# @option options [Integer] :modifiers
|
79
|
+
# Bitfield for key modifiers. See`keyboard.modifiers`.
|
80
|
+
#
|
81
|
+
# @return [self]
|
82
|
+
#
|
27
83
|
def down(**options)
|
28
84
|
tap { mouse_event(type: "mousePressed", **options) }
|
29
85
|
end
|
30
86
|
|
87
|
+
#
|
88
|
+
# Mouse up for given coordinates.
|
89
|
+
#
|
90
|
+
# @param [Hash{Symbol => Object}] options
|
91
|
+
# Additional keyword arguments.
|
92
|
+
#
|
93
|
+
# @option options [:left, :right] :button (:left)
|
94
|
+
# The mouse button to click.
|
95
|
+
#
|
96
|
+
# @option options [Integer] :count (1)
|
97
|
+
#
|
98
|
+
# @option options [Integer] :modifiers
|
99
|
+
# Bitfield for key modifiers. See`keyboard.modifiers`.
|
100
|
+
#
|
101
|
+
# @return [self]
|
102
|
+
#
|
31
103
|
def up(**options)
|
32
104
|
tap { mouse_event(type: "mouseReleased", **options) }
|
33
105
|
end
|
34
106
|
|
107
|
+
#
|
108
|
+
# Mouse move to given x and y.
|
109
|
+
#
|
110
|
+
# @param [Integer] x
|
111
|
+
#
|
112
|
+
# @param [Integer] y
|
113
|
+
#
|
114
|
+
# @param [Integer] steps
|
115
|
+
# Sends intermediate mousemove events.
|
116
|
+
#
|
117
|
+
# @return [self]
|
118
|
+
#
|
35
119
|
def move(x:, y:, steps: 1)
|
36
120
|
from_x = @x
|
37
121
|
from_y = @y
|
@@ -3,9 +3,38 @@
|
|
3
3
|
module Ferrum
|
4
4
|
class Network
|
5
5
|
class Exchange
|
6
|
+
# ID of the request.
|
7
|
+
#
|
8
|
+
# @return String
|
6
9
|
attr_reader :id
|
7
|
-
attr_accessor :intercepted_request, :request, :response, :error
|
8
10
|
|
11
|
+
# The intercepted request.
|
12
|
+
#
|
13
|
+
# @return [InterceptedRequest, nil]
|
14
|
+
attr_accessor :intercepted_request
|
15
|
+
|
16
|
+
# The request object.
|
17
|
+
#
|
18
|
+
# @return [Request, nil]
|
19
|
+
attr_accessor :request
|
20
|
+
|
21
|
+
# The response object.
|
22
|
+
#
|
23
|
+
# @return [Response, nil]
|
24
|
+
attr_accessor :response
|
25
|
+
|
26
|
+
# The error object.
|
27
|
+
#
|
28
|
+
# @return [Error, nil]
|
29
|
+
attr_accessor :error
|
30
|
+
|
31
|
+
#
|
32
|
+
# Initializes the network exchange.
|
33
|
+
#
|
34
|
+
# @param [Page] page
|
35
|
+
#
|
36
|
+
# @param [String] id
|
37
|
+
#
|
9
38
|
def initialize(page, id)
|
10
39
|
@id = id
|
11
40
|
@page = page
|
@@ -13,35 +42,87 @@ module Ferrum
|
|
13
42
|
@request = @response = @error = nil
|
14
43
|
end
|
15
44
|
|
45
|
+
#
|
46
|
+
# Determines if the network exchange was caused by a page navigation
|
47
|
+
# event.
|
48
|
+
#
|
49
|
+
# @param [String] frame_id
|
50
|
+
#
|
51
|
+
# @return [Boolean]
|
52
|
+
#
|
16
53
|
def navigation_request?(frame_id)
|
17
|
-
request.type?(:document) &&
|
18
|
-
request.frame_id == frame_id
|
54
|
+
request.type?(:document) && request&.frame_id == frame_id
|
19
55
|
end
|
20
56
|
|
57
|
+
#
|
58
|
+
# Determines if the network exchange has a request.
|
59
|
+
#
|
60
|
+
# @return [Boolean]
|
61
|
+
#
|
21
62
|
def blank?
|
22
63
|
!request
|
23
64
|
end
|
24
65
|
|
66
|
+
#
|
67
|
+
# Determines if the request was intercepted and blocked.
|
68
|
+
#
|
69
|
+
# @return [Boolean]
|
70
|
+
#
|
25
71
|
def blocked?
|
26
72
|
intercepted? && intercepted_request.status?(:aborted)
|
27
73
|
end
|
28
74
|
|
75
|
+
#
|
76
|
+
# Determines if the request was blocked, a response was returned, or if an
|
77
|
+
# error occurred.
|
78
|
+
#
|
79
|
+
# @return [Boolean]
|
80
|
+
#
|
29
81
|
def finished?
|
30
|
-
blocked? || response || error
|
82
|
+
blocked? || !response.nil? || !error.nil?
|
31
83
|
end
|
32
84
|
|
85
|
+
#
|
86
|
+
# Determines if the network exchange is still not finished.
|
87
|
+
#
|
88
|
+
# @return [Boolean]
|
89
|
+
#
|
33
90
|
def pending?
|
34
91
|
!finished?
|
35
92
|
end
|
36
93
|
|
94
|
+
#
|
95
|
+
# Determines if the exchange's request was intercepted.
|
96
|
+
#
|
97
|
+
# @return [Boolean]
|
98
|
+
#
|
37
99
|
def intercepted?
|
38
|
-
intercepted_request
|
100
|
+
!intercepted_request.nil?
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Returns request's URL.
|
105
|
+
#
|
106
|
+
# @return [String, nil]
|
107
|
+
#
|
108
|
+
def url
|
109
|
+
request&.url
|
39
110
|
end
|
40
111
|
|
112
|
+
#
|
113
|
+
# Converts the network exchange into a request, response, and error tuple.
|
114
|
+
#
|
115
|
+
# @return [Array]
|
116
|
+
#
|
41
117
|
def to_a
|
42
118
|
[request, response, error]
|
43
119
|
end
|
44
120
|
|
121
|
+
#
|
122
|
+
# Inspects the network exchange.
|
123
|
+
#
|
124
|
+
# @return [String]
|
125
|
+
#
|
45
126
|
def inspect
|
46
127
|
"#<#{self.class} " \
|
47
128
|
"@id=#{@id.inspect} " \
|
@@ -4,48 +4,112 @@ require "time"
|
|
4
4
|
|
5
5
|
module Ferrum
|
6
6
|
class Network
|
7
|
+
#
|
8
|
+
# Represents a [Network.Request](https://chromedevtools.github.io/devtools-protocol/1-3/Network/#type-Request)
|
9
|
+
# object.
|
10
|
+
#
|
7
11
|
class Request
|
12
|
+
#
|
13
|
+
# Initializes the request object.
|
14
|
+
#
|
15
|
+
# @param [Hash{String => Object}] params
|
16
|
+
# The parsed JSON attributes.
|
17
|
+
#
|
8
18
|
def initialize(params)
|
9
19
|
@params = params
|
10
20
|
@request = @params["request"]
|
11
21
|
end
|
12
22
|
|
23
|
+
#
|
24
|
+
# The request ID.
|
25
|
+
#
|
26
|
+
# @return [String]
|
27
|
+
#
|
13
28
|
def id
|
14
29
|
@params["requestId"]
|
15
30
|
end
|
16
31
|
|
32
|
+
#
|
33
|
+
# The request resouce type.
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
#
|
17
37
|
def type
|
18
38
|
@params["type"]
|
19
39
|
end
|
20
40
|
|
41
|
+
#
|
42
|
+
# Determines if the request is of the given type.
|
43
|
+
#
|
44
|
+
# @param [String, Symbol] value
|
45
|
+
# The type value to compare against.
|
46
|
+
#
|
47
|
+
# @return [Boolean]
|
48
|
+
#
|
21
49
|
def type?(value)
|
22
50
|
type.downcase == value.to_s.downcase
|
23
51
|
end
|
24
52
|
|
53
|
+
#
|
54
|
+
# The frame ID of the request.
|
55
|
+
#
|
56
|
+
# @return [String]
|
57
|
+
#
|
25
58
|
def frame_id
|
26
59
|
@params["frameId"]
|
27
60
|
end
|
28
61
|
|
62
|
+
#
|
63
|
+
# The URL for the request.
|
64
|
+
#
|
65
|
+
# @return [String]
|
66
|
+
#
|
29
67
|
def url
|
30
68
|
@request["url"]
|
31
69
|
end
|
32
70
|
|
71
|
+
#
|
72
|
+
# The URL fragment for the request.
|
73
|
+
#
|
74
|
+
# @return [String, nil]
|
75
|
+
#
|
33
76
|
def url_fragment
|
34
77
|
@request["urlFragment"]
|
35
78
|
end
|
36
79
|
|
80
|
+
#
|
81
|
+
# The request method.
|
82
|
+
#
|
83
|
+
# @return [String]
|
84
|
+
#
|
37
85
|
def method
|
38
86
|
@request["method"]
|
39
87
|
end
|
40
88
|
|
89
|
+
#
|
90
|
+
# The request headers.
|
91
|
+
#
|
92
|
+
# @return [Hash{String => String}]
|
93
|
+
#
|
41
94
|
def headers
|
42
95
|
@request["headers"]
|
43
96
|
end
|
44
97
|
|
98
|
+
#
|
99
|
+
# The request timestamp.
|
100
|
+
#
|
101
|
+
# @return [Time]
|
102
|
+
#
|
45
103
|
def time
|
46
104
|
@time ||= Time.strptime(@params["wallTime"].to_s, "%s")
|
47
105
|
end
|
48
106
|
|
107
|
+
#
|
108
|
+
# The optional HTTP `POST` form data.
|
109
|
+
#
|
110
|
+
# @return [String, nil]
|
111
|
+
# The HTTP `POST` form data.
|
112
|
+
#
|
49
113
|
def post_data
|
50
114
|
@request["postData"]
|
51
115
|
end
|
@@ -2,43 +2,105 @@
|
|
2
2
|
|
3
3
|
module Ferrum
|
4
4
|
class Network
|
5
|
+
#
|
6
|
+
# Represents a [Network.Response](https://chromedevtools.github.io/devtools-protocol/1-3/Network/#type-Response)
|
7
|
+
# object.
|
8
|
+
#
|
5
9
|
class Response
|
6
|
-
|
10
|
+
# The response body size.
|
11
|
+
#
|
12
|
+
# @return [Integer, nil]
|
13
|
+
attr_reader :body_size
|
7
14
|
|
15
|
+
# The parsed JSON attributes for the [Network.Response](https://chromedevtools.github.io/devtools-protocol/1-3/Network/#type-Response)
|
16
|
+
# object.
|
17
|
+
#
|
18
|
+
# @return [Hash{String => Object}]
|
19
|
+
attr_reader :params
|
20
|
+
|
21
|
+
#
|
22
|
+
# Initializes the respones object.
|
23
|
+
#
|
24
|
+
# @param [Page] page
|
25
|
+
# The page associated with the network response.
|
26
|
+
#
|
27
|
+
# @param [Hash{String => Object}] params
|
28
|
+
# The parsed JSON attributes for the [Network.Response](https://chromedevtools.github.io/devtools-protocol/1-3/Network/#type-Response)
|
29
|
+
#
|
8
30
|
def initialize(page, params)
|
9
31
|
@page = page
|
10
32
|
@params = params
|
11
33
|
@response = params["response"] || params["redirectResponse"]
|
12
34
|
end
|
13
35
|
|
36
|
+
#
|
37
|
+
# The request ID associated with the response.
|
38
|
+
#
|
39
|
+
# @return [String]
|
40
|
+
#
|
14
41
|
def id
|
15
42
|
@params["requestId"]
|
16
43
|
end
|
17
44
|
|
45
|
+
#
|
46
|
+
# The URL of the response.
|
47
|
+
#
|
48
|
+
# @return [String]
|
49
|
+
#
|
18
50
|
def url
|
19
51
|
@response["url"]
|
20
52
|
end
|
21
53
|
|
54
|
+
#
|
55
|
+
# The HTTP status of the response.
|
56
|
+
#
|
57
|
+
# @return [Integer]
|
58
|
+
#
|
22
59
|
def status
|
23
60
|
@response["status"]
|
24
61
|
end
|
25
62
|
|
63
|
+
#
|
64
|
+
# The HTTP status text.
|
65
|
+
#
|
66
|
+
# @return [String]
|
67
|
+
#
|
26
68
|
def status_text
|
27
69
|
@response["statusText"]
|
28
70
|
end
|
29
71
|
|
72
|
+
#
|
73
|
+
# The headers of the response.
|
74
|
+
#
|
75
|
+
# @return [Hash{String => String}]
|
76
|
+
#
|
30
77
|
def headers
|
31
78
|
@response["headers"]
|
32
79
|
end
|
33
80
|
|
81
|
+
#
|
82
|
+
# The total size in bytes of the response.
|
83
|
+
#
|
84
|
+
# @return [Integer]
|
85
|
+
#
|
34
86
|
def headers_size
|
35
87
|
@response["encodedDataLength"]
|
36
88
|
end
|
37
89
|
|
90
|
+
#
|
91
|
+
# The resource type of the response.
|
92
|
+
#
|
93
|
+
# @return [String]
|
94
|
+
#
|
38
95
|
def type
|
39
96
|
@params["type"]
|
40
97
|
end
|
41
98
|
|
99
|
+
#
|
100
|
+
# The `Content-Type` header value of the response.
|
101
|
+
#
|
102
|
+
# @return [String, nil]
|
103
|
+
#
|
42
104
|
def content_type
|
43
105
|
@content_type ||= headers.find { |k, _| k.downcase == "content-type" }&.last&.sub(/;.*\z/, "")
|
44
106
|
end
|
@@ -52,6 +114,11 @@ module Ferrum
|
|
52
114
|
@body_size = size - headers_size
|
53
115
|
end
|
54
116
|
|
117
|
+
#
|
118
|
+
# The response body.
|
119
|
+
#
|
120
|
+
# @return [String]
|
121
|
+
#
|
55
122
|
def body
|
56
123
|
@body ||= begin
|
57
124
|
body, encoded = @page
|
@@ -61,14 +128,29 @@ module Ferrum
|
|
61
128
|
end
|
62
129
|
end
|
63
130
|
|
131
|
+
#
|
132
|
+
# @return [Boolean]
|
133
|
+
#
|
64
134
|
def main?
|
65
135
|
@page.network.response == self
|
66
136
|
end
|
67
137
|
|
138
|
+
#
|
139
|
+
# Comapres the respones ID to another response's ID.
|
140
|
+
#
|
141
|
+
# @return [Boolean]
|
142
|
+
# Indicates whether the response has the same ID as the other response
|
143
|
+
# object.
|
144
|
+
#
|
68
145
|
def ==(other)
|
69
146
|
id == other.id
|
70
147
|
end
|
71
148
|
|
149
|
+
#
|
150
|
+
# Inspects the response object.
|
151
|
+
#
|
152
|
+
# @return [String]
|
153
|
+
#
|
72
154
|
def inspect
|
73
155
|
%(#<#{self.class} @params=#{@params.inspect} @response=#{@response.inspect}>)
|
74
156
|
end
|
data/lib/ferrum/network.rb
CHANGED
@@ -19,6 +19,16 @@ module Ferrum
|
|
19
19
|
AUTHORIZE_TYPE_WRONG = ":type should be in #{AUTHORIZE_TYPE}"
|
20
20
|
ALLOWED_CONNECTION_TYPE = %w[none cellular2g cellular3g cellular4g bluetooth ethernet wifi wimax other].freeze
|
21
21
|
|
22
|
+
# Network traffic.
|
23
|
+
#
|
24
|
+
# @return [Array<Exchange>]
|
25
|
+
# Returns all information about network traffic as {Exchange}
|
26
|
+
# instance which in general is a wrapper around `request`, `response` and
|
27
|
+
# `error`.
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# browser.go_to("https://github.com/")
|
31
|
+
# browser.network.traffic # => [#<Ferrum::Network::Exchange, ...]
|
22
32
|
attr_reader :traffic
|
23
33
|
|
24
34
|
def initialize(page)
|
@@ -29,6 +39,25 @@ module Ferrum
|
|
29
39
|
@whitelist = nil
|
30
40
|
end
|
31
41
|
|
42
|
+
#
|
43
|
+
# Waits for network idle or raises {Ferrum::TimeoutError} error.
|
44
|
+
#
|
45
|
+
# @param [Integer] connections
|
46
|
+
# how many connections are allowed for network to be idling,
|
47
|
+
#
|
48
|
+
# @param [Float] duration
|
49
|
+
# Sleep for given amount of time and check again.
|
50
|
+
#
|
51
|
+
# @param [Float] timeout
|
52
|
+
# During what time we try to check idle.
|
53
|
+
#
|
54
|
+
# @raise [Ferrum::TimeoutError]
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# browser.go_to("https://example.com/")
|
58
|
+
# browser.at_xpath("//a[text() = 'No UI changes button']").click
|
59
|
+
# browser.network.wait_for_idle
|
60
|
+
#
|
32
61
|
def wait_for_idle(connections: 0, duration: 0.05, timeout: @page.browser.timeout)
|
33
62
|
start = Utils::ElapsedTime.monotonic_time
|
34
63
|
|
@@ -55,18 +84,61 @@ module Ferrum
|
|
55
84
|
total_connections - finished_connections
|
56
85
|
end
|
57
86
|
|
87
|
+
#
|
88
|
+
# Page request of the main frame.
|
89
|
+
#
|
90
|
+
# @return [Request]
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# browser.go_to("https://github.com/")
|
94
|
+
# browser.network.request # => #<Ferrum::Network::Request...
|
95
|
+
#
|
58
96
|
def request
|
59
97
|
@exchange&.request
|
60
98
|
end
|
61
99
|
|
100
|
+
#
|
101
|
+
# Page response of the main frame.
|
102
|
+
#
|
103
|
+
# @return [Response, nil]
|
104
|
+
#
|
105
|
+
# @example
|
106
|
+
# browser.go_to("https://github.com/")
|
107
|
+
# browser.network.response # => #<Ferrum::Network::Response...
|
108
|
+
#
|
62
109
|
def response
|
63
110
|
@exchange&.response
|
64
111
|
end
|
65
112
|
|
113
|
+
#
|
114
|
+
# Contains the status code of the main page response (e.g., 200 for a
|
115
|
+
# success). This is just a shortcut for `response.status`.
|
116
|
+
#
|
117
|
+
# @return [Integer, nil]
|
118
|
+
#
|
119
|
+
# @example
|
120
|
+
# browser.go_to("https://github.com/")
|
121
|
+
# browser.network.status # => 200
|
122
|
+
#
|
66
123
|
def status
|
67
124
|
response&.status
|
68
125
|
end
|
69
126
|
|
127
|
+
#
|
128
|
+
# Clear browser's cache or collected traffic.
|
129
|
+
#
|
130
|
+
# @param [:traffic, :cache] type
|
131
|
+
# The type of traffic to clear.
|
132
|
+
#
|
133
|
+
# @return [true]
|
134
|
+
#
|
135
|
+
# @example
|
136
|
+
# traffic = browser.network.traffic # => []
|
137
|
+
# browser.go_to("https://github.com/")
|
138
|
+
# traffic.size # => 51
|
139
|
+
# browser.network.clear(:traffic)
|
140
|
+
# traffic.size # => 0
|
141
|
+
#
|
70
142
|
def clear(type)
|
71
143
|
raise ArgumentError, ":type should be in #{CLEAR_TYPE}" unless CLEAR_TYPE.include?(type)
|
72
144
|
|
@@ -91,6 +163,30 @@ module Ferrum
|
|
91
163
|
end
|
92
164
|
alias allowlist= whitelist=
|
93
165
|
|
166
|
+
#
|
167
|
+
# Set request interception for given options. This method is only sets
|
168
|
+
# request interception, you should use `on` callback to catch requests and
|
169
|
+
# abort or continue them.
|
170
|
+
#
|
171
|
+
# @param [String] pattern
|
172
|
+
#
|
173
|
+
# @param [Symbol, nil] resource_type
|
174
|
+
# One of the [resource types](https://chromedevtools.github.io/devtools-protocol/tot/Network#type-ResourceType)
|
175
|
+
#
|
176
|
+
# @example
|
177
|
+
# browser = Ferrum::Browser.new
|
178
|
+
# browser.network.intercept
|
179
|
+
# browser.on(:request) do |request|
|
180
|
+
# if request.match?(/bla-bla/)
|
181
|
+
# request.abort
|
182
|
+
# elsif request.match?(/lorem/)
|
183
|
+
# request.respond(body: "Lorem ipsum")
|
184
|
+
# else
|
185
|
+
# request.continue
|
186
|
+
# end
|
187
|
+
# end
|
188
|
+
# browser.go_to("https://google.com")
|
189
|
+
#
|
94
190
|
def intercept(pattern: "*", resource_type: nil)
|
95
191
|
pattern = { urlPattern: pattern }
|
96
192
|
pattern[:resourceType] = resource_type if resource_type && RESOURCE_TYPES.include?(resource_type.to_s)
|
@@ -98,6 +194,31 @@ module Ferrum
|
|
98
194
|
@page.command("Fetch.enable", handleAuthRequests: true, patterns: [pattern])
|
99
195
|
end
|
100
196
|
|
197
|
+
#
|
198
|
+
# Sets HTTP Basic-Auth credentials.
|
199
|
+
#
|
200
|
+
# @param [String] user
|
201
|
+
# The username to send.
|
202
|
+
#
|
203
|
+
# @param [String] password
|
204
|
+
# The password to send.
|
205
|
+
#
|
206
|
+
# @param [:server, :proxy] type
|
207
|
+
# Specifies whether the credentials are for a website or a proxy.
|
208
|
+
#
|
209
|
+
# @yield [request]
|
210
|
+
# The given block will be passed each authenticated request and can allow
|
211
|
+
# or deny the request.
|
212
|
+
#
|
213
|
+
# @yieldparam [Request] request
|
214
|
+
# An HTTP request.
|
215
|
+
#
|
216
|
+
# @example
|
217
|
+
# browser.network.authorize(user: "login", password: "pass") { |req| req.continue }
|
218
|
+
# browser.go_to("http://example.com/authenticated")
|
219
|
+
# puts browser.network.status # => 200
|
220
|
+
# puts browser.body # => Welcome, authenticated client
|
221
|
+
#
|
101
222
|
def authorize(user:, password:, type: :server, &block)
|
102
223
|
raise ArgumentError, AUTHORIZE_TYPE_WRONG unless AUTHORIZE_TYPE.include?(type)
|
103
224
|
raise ArgumentError, AUTHORIZE_BLOCK_MISSING if !block_given? && !@page.subscribed?("Fetch.requestPaused")
|
@@ -151,6 +272,37 @@ module Ferrum
|
|
151
272
|
Network::Exchange.new(@page, id).tap { |e| @traffic << e }
|
152
273
|
end
|
153
274
|
|
275
|
+
#
|
276
|
+
# Activates emulation of network conditions.
|
277
|
+
#
|
278
|
+
# @param [Boolean] offline
|
279
|
+
# Emulate internet disconnection,
|
280
|
+
#
|
281
|
+
# @param [Integer] latency
|
282
|
+
# Minimum latency from request sent to response headers received (ms).
|
283
|
+
#
|
284
|
+
# @param [Integer] download_throughput
|
285
|
+
# Maximal aggregated download throughput (bytes/sec).
|
286
|
+
#
|
287
|
+
# @param [Integer] upload_throughput
|
288
|
+
# Maximal aggregated upload throughput (bytes/sec).
|
289
|
+
#
|
290
|
+
# @param [String, nil] connection_type
|
291
|
+
# Connection type if known:
|
292
|
+
# * `"none"`
|
293
|
+
# * `"cellular2g"`
|
294
|
+
# * `"cellular3g"`
|
295
|
+
# * `"cellular4g"`
|
296
|
+
# * `"bluetooth"`
|
297
|
+
# * `"ethernet"`
|
298
|
+
# * `"wifi"`
|
299
|
+
# * `"wimax"`
|
300
|
+
# * `"other"`
|
301
|
+
#
|
302
|
+
# @example
|
303
|
+
# browser.network.emulate_network_conditions(connection_type: "cellular2g")
|
304
|
+
# browser.go_to("https://github.com/")
|
305
|
+
#
|
154
306
|
def emulate_network_conditions(offline: false, latency: 0,
|
155
307
|
download_throughput: -1, upload_throughput: -1,
|
156
308
|
connection_type: nil)
|
@@ -166,6 +318,14 @@ module Ferrum
|
|
166
318
|
true
|
167
319
|
end
|
168
320
|
|
321
|
+
#
|
322
|
+
# Activates offline mode for a page.
|
323
|
+
#
|
324
|
+
# @example
|
325
|
+
# browser.network.offline_mode
|
326
|
+
# browser.go_to("https://github.com/") # => Ferrum::StatusError (Request to https://github.com/ failed to reach
|
327
|
+
# server, check DNS and server status)
|
328
|
+
#
|
169
329
|
def offline_mode
|
170
330
|
emulate_network_conditions(offline: true, latency: 0, download_throughput: 0, upload_throughput: 0)
|
171
331
|
end
|