playwright-ruby-client 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/docs/api_coverage.md +102 -49
- data/lib/playwright.rb +1 -0
- data/lib/playwright/channel.rb +10 -10
- data/lib/playwright/channel_owners/binding_call.rb +3 -0
- data/lib/playwright/channel_owners/browser_context.rb +149 -3
- data/lib/playwright/channel_owners/dialog.rb +28 -0
- data/lib/playwright/channel_owners/page.rb +47 -10
- data/lib/playwright/channel_owners/playwright.rb +4 -0
- data/lib/playwright/channel_owners/request.rb +26 -2
- data/lib/playwright/channel_owners/response.rb +60 -0
- data/lib/playwright/channel_owners/route.rb +78 -0
- data/lib/playwright/channel_owners/selectors.rb +19 -1
- data/lib/playwright/route_handler_entry.rb +36 -0
- data/lib/playwright/utils.rb +1 -0
- data/lib/playwright/version.rb +1 -1
- data/lib/playwright_api/android.rb +80 -8
- data/lib/playwright_api/android_device.rb +145 -28
- data/lib/playwright_api/android_input.rb +17 -13
- data/lib/playwright_api/android_socket.rb +16 -0
- data/lib/playwright_api/android_web_view.rb +21 -0
- data/lib/playwright_api/binding_call.rb +11 -6
- data/lib/playwright_api/browser.rb +6 -6
- data/lib/playwright_api/browser_context.rb +33 -28
- data/lib/playwright_api/browser_type.rb +14 -14
- data/lib/playwright_api/chromium_browser_context.rb +6 -6
- data/lib/playwright_api/console_message.rb +6 -6
- data/lib/playwright_api/dialog.rb +32 -5
- data/lib/playwright_api/download.rb +6 -6
- data/lib/playwright_api/element_handle.rb +6 -6
- data/lib/playwright_api/file_chooser.rb +1 -1
- data/lib/playwright_api/frame.rb +13 -11
- data/lib/playwright_api/js_handle.rb +6 -6
- data/lib/playwright_api/page.rb +48 -46
- data/lib/playwright_api/playwright.rb +7 -7
- data/lib/playwright_api/request.rb +8 -8
- data/lib/playwright_api/response.rb +27 -17
- data/lib/playwright_api/route.rb +27 -5
- data/lib/playwright_api/selectors.rb +7 -7
- metadata +7 -2
@@ -0,0 +1,28 @@
|
|
1
|
+
module Playwright
|
2
|
+
define_channel_owner :Dialog do
|
3
|
+
def type
|
4
|
+
@initializer['type']
|
5
|
+
end
|
6
|
+
|
7
|
+
def message
|
8
|
+
@initializer['message']
|
9
|
+
end
|
10
|
+
|
11
|
+
def default_value
|
12
|
+
@initializer['defaultValue']
|
13
|
+
end
|
14
|
+
|
15
|
+
def accept(promptText: nil)
|
16
|
+
accept_async(prompt_text: promptText).value!
|
17
|
+
end
|
18
|
+
|
19
|
+
def accept_async(promptText: nil)
|
20
|
+
params = { promptText: promptText }.compact
|
21
|
+
@channel.async_send_message_to_server('accept', params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def dismiss
|
25
|
+
@channel.async_send_message_to_server('dismiss')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -14,8 +14,16 @@ module Playwright
|
|
14
14
|
@mouse = MouseImpl.new(@channel)
|
15
15
|
@touchscreen = TouchscreenImpl.new(@channel)
|
16
16
|
|
17
|
-
|
17
|
+
if @initializer['viewportSize']
|
18
|
+
@viewport_size = {
|
19
|
+
width: @initializer['viewportSize']['width'],
|
20
|
+
height: @initializer['viewportSize']['height'],
|
21
|
+
}
|
22
|
+
end
|
18
23
|
@closed = false
|
24
|
+
@bindings = {}
|
25
|
+
@routes = Set.new
|
26
|
+
|
19
27
|
@main_frame = ChannelOwners::Frame.from(@initializer['mainFrame'])
|
20
28
|
@main_frame.send(:update_page_from_page, self)
|
21
29
|
@frames = Set.new
|
@@ -96,12 +104,12 @@ module Playwright
|
|
96
104
|
private def on_request_failed(request, response_end_timing, failure_text)
|
97
105
|
request.send(:update_failure_text, failure_text)
|
98
106
|
request.send(:update_response_end_timing, response_end_timing)
|
99
|
-
emit(Events::Page::RequestFailed)
|
107
|
+
emit(Events::Page::RequestFailed, request)
|
100
108
|
end
|
101
109
|
|
102
110
|
private def on_request_finished(request, response_end_timing)
|
103
111
|
request.send(:update_response_end_timing, response_end_timing)
|
104
|
-
emit(Events::Page::RequestFinished)
|
112
|
+
emit(Events::Page::RequestFinished, request)
|
105
113
|
end
|
106
114
|
|
107
115
|
private def on_frame_attached(frame)
|
@@ -117,8 +125,15 @@ module Playwright
|
|
117
125
|
end
|
118
126
|
|
119
127
|
private def on_route(route, request)
|
120
|
-
#
|
121
|
-
|
128
|
+
# It is not desired to use PlaywrightApi.wrap directly.
|
129
|
+
# However it is a little difficult to define wrapper for `handler` parameter in generate_api.
|
130
|
+
# Just a workaround...
|
131
|
+
wrapped_route = PlaywrightApi.wrap(route)
|
132
|
+
wrapped_request = PlaywrightApi.wrap(request)
|
133
|
+
|
134
|
+
if @routes.none? { |handler_entry| handler_entry.handle(wrapped_route, wrapped_request) }
|
135
|
+
@browser_context.send(:on_route, route, request)
|
136
|
+
end
|
122
137
|
end
|
123
138
|
|
124
139
|
private def on_close
|
@@ -130,14 +145,14 @@ module Playwright
|
|
130
145
|
private def on_dialog(params)
|
131
146
|
dialog = ChannelOwners::Dialog.from(params['dialog'])
|
132
147
|
unless emit(Events::Page::Dialog, dialog)
|
133
|
-
dialog.dismiss
|
148
|
+
dialog.dismiss
|
134
149
|
end
|
135
150
|
end
|
136
151
|
|
137
152
|
# @override
|
138
153
|
def on(event, callback)
|
139
154
|
if event == Events::Page::FileChooser && listener_count(event) == 0
|
140
|
-
@channel.
|
155
|
+
@channel.async_send_message_to_server('setFileChooserInterceptedNoReply', intercepted: true)
|
141
156
|
end
|
142
157
|
super
|
143
158
|
end
|
@@ -145,7 +160,7 @@ module Playwright
|
|
145
160
|
# @override
|
146
161
|
def once(event, callback)
|
147
162
|
if event == Events::Page::FileChooser && listener_count(event) == 0
|
148
|
-
@channel.
|
163
|
+
@channel.async_send_message_to_server('setFileChooserInterceptedNoReply', intercepted: true)
|
149
164
|
end
|
150
165
|
super
|
151
166
|
end
|
@@ -154,7 +169,7 @@ module Playwright
|
|
154
169
|
def off(event, callback)
|
155
170
|
super
|
156
171
|
if event == Events::Page::FileChooser && listener_count(event) == 0
|
157
|
-
@channel.
|
172
|
+
@channel.async_send_message_to_server('setFileChooserInterceptedNoReply', intercepted: false)
|
158
173
|
end
|
159
174
|
end
|
160
175
|
|
@@ -347,7 +362,7 @@ module Playwright
|
|
347
362
|
def add_init_script(path: nil, script: nil)
|
348
363
|
source =
|
349
364
|
if path
|
350
|
-
File.read(path
|
365
|
+
File.read(path)
|
351
366
|
elsif script
|
352
367
|
script
|
353
368
|
else
|
@@ -358,6 +373,23 @@ module Playwright
|
|
358
373
|
nil
|
359
374
|
end
|
360
375
|
|
376
|
+
def route(url, handler)
|
377
|
+
entry = RouteHandlerEntry.new(url, handler)
|
378
|
+
@routes << entry
|
379
|
+
if @routes.count >= 1
|
380
|
+
@channel.send_message_to_server('setNetworkInterceptionEnabled', enabled: true)
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
def unroute(url, handler: nil)
|
385
|
+
@routes.reject! do |handler_entry|
|
386
|
+
handler_entry.same_value?(url: url, handler: handler)
|
387
|
+
end
|
388
|
+
if @routes.count == 0
|
389
|
+
@channel.send_message_to_server('setNetworkInterceptionEnabled', enabled: false)
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
361
393
|
def screenshot(
|
362
394
|
path: nil,
|
363
395
|
type: nil,
|
@@ -698,5 +730,10 @@ module Playwright
|
|
698
730
|
private def timeout_settings
|
699
731
|
@timeout_settings
|
700
732
|
end
|
733
|
+
|
734
|
+
# called from BrowserContext#expose_binding
|
735
|
+
private def has_bindings?(name)
|
736
|
+
@bindings.key?(name)
|
737
|
+
end
|
701
738
|
end
|
702
739
|
end
|
@@ -20,6 +20,10 @@ module Playwright
|
|
20
20
|
@electron ||= ::Playwright::ChannelOwners::Electron.from(@initializer['electron'])
|
21
21
|
end
|
22
22
|
|
23
|
+
def selectors
|
24
|
+
@selectors ||= ::Playwright::ChannelOwners::Selectors.from(@initializer['selectors'])
|
25
|
+
end
|
26
|
+
|
23
27
|
class DeviceDescriptor
|
24
28
|
class Viewport
|
25
29
|
def initialize(hash)
|
@@ -29,7 +29,7 @@ module Playwright
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def method
|
32
|
-
@
|
32
|
+
@initializer['method']
|
33
33
|
end
|
34
34
|
|
35
35
|
def post_data
|
@@ -69,7 +69,7 @@ module Playwright
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def frame
|
72
|
-
@initializer['frame']
|
72
|
+
ChannelOwners::Frame.from(@initializer['frame'])
|
73
73
|
end
|
74
74
|
|
75
75
|
def navigation_request?
|
@@ -90,6 +90,30 @@ module Playwright
|
|
90
90
|
@failure_text = failure_text
|
91
91
|
end
|
92
92
|
|
93
|
+
private def update_timings(
|
94
|
+
start_time:,
|
95
|
+
domain_lookup_start:,
|
96
|
+
domain_lookup_end:,
|
97
|
+
connect_start:,
|
98
|
+
secure_connection_start:,
|
99
|
+
connect_end:,
|
100
|
+
request_start:,
|
101
|
+
response_start:)
|
102
|
+
|
103
|
+
@timing["startTime"] = start_time
|
104
|
+
@timing["domainLookupStart"] = domain_lookup_start
|
105
|
+
@timing["domainLookupEnd"] = domain_lookup_end
|
106
|
+
@timing["connectStart"] = connect_start
|
107
|
+
@timing["secureConnectionStart"] = secure_connection_start
|
108
|
+
@timing["connectEnd"] = connect_end
|
109
|
+
@timing["requestStart"] = request_start
|
110
|
+
@timing["responseStart"] = response_start
|
111
|
+
end
|
112
|
+
|
113
|
+
private def update_headers(headers)
|
114
|
+
@headers = parse_headers(headers)
|
115
|
+
end
|
116
|
+
|
93
117
|
private def update_response_end_timing(response_end_timing)
|
94
118
|
@timing[:responseEnd] = response_end_timing
|
95
119
|
end
|
@@ -1,5 +1,65 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'json'
|
3
|
+
|
1
4
|
module Playwright
|
2
5
|
# @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_network.py
|
3
6
|
define_channel_owner :Response do
|
7
|
+
def after_initialize
|
8
|
+
@request = ChannelOwners::Request.from(@initializer['request'])
|
9
|
+
timing = @initializer['timing']
|
10
|
+
@request.send(:update_timings,
|
11
|
+
start_time: timing["startTime"],
|
12
|
+
domain_lookup_start: timing["domainLookupStart"],
|
13
|
+
domain_lookup_end: timing["domainLookupEnd"],
|
14
|
+
connect_start: timing["connectStart"],
|
15
|
+
secure_connection_start: timing["secureConnectionStart"],
|
16
|
+
connect_end: timing["connectEnd"],
|
17
|
+
request_start: timing["requestStart"],
|
18
|
+
response_start: timing["responseStart"],
|
19
|
+
)
|
20
|
+
@request.send(:update_headers, @initializer['requestHeaders'])
|
21
|
+
end
|
22
|
+
attr_reader :request
|
23
|
+
|
24
|
+
def url
|
25
|
+
@initializer['url']
|
26
|
+
end
|
27
|
+
|
28
|
+
def ok
|
29
|
+
status == 0 || (200...300).include?(status)
|
30
|
+
end
|
31
|
+
alias_method :ok?, :ok
|
32
|
+
|
33
|
+
def status
|
34
|
+
@initializer['status']
|
35
|
+
end
|
36
|
+
|
37
|
+
def status_text
|
38
|
+
@initializer['statusText']
|
39
|
+
end
|
40
|
+
|
41
|
+
def headers
|
42
|
+
@initializer['headers'].map do |header|
|
43
|
+
[header['name'].downcase, header['value']]
|
44
|
+
end.to_h
|
45
|
+
end
|
46
|
+
|
47
|
+
def finished
|
48
|
+
@channel.send_message_to_server('finished')
|
49
|
+
end
|
50
|
+
|
51
|
+
def body
|
52
|
+
binary = @channel.send_message_to_server("body")
|
53
|
+
Base64.strict_decode64(binary)
|
54
|
+
end
|
55
|
+
alias_method :text, :body
|
56
|
+
|
57
|
+
def json
|
58
|
+
JSON.parse(text)
|
59
|
+
end
|
60
|
+
|
61
|
+
def frame
|
62
|
+
@request.frame
|
63
|
+
end
|
4
64
|
end
|
5
65
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'mime/types'
|
3
|
+
|
4
|
+
module Playwright
|
5
|
+
define_channel_owner :Route do
|
6
|
+
def request
|
7
|
+
ChannelOwners::Request.from(@initializer['request'])
|
8
|
+
end
|
9
|
+
|
10
|
+
def abort(errorCode: nil)
|
11
|
+
params = { errorCode: errorCode }.compact
|
12
|
+
@channel.async_send_message_to_server('abort', params)
|
13
|
+
end
|
14
|
+
|
15
|
+
def fulfill(
|
16
|
+
body: nil,
|
17
|
+
contentType: nil,
|
18
|
+
headers: nil,
|
19
|
+
path: nil,
|
20
|
+
status: nil)
|
21
|
+
params = {
|
22
|
+
contentType: contentType,
|
23
|
+
status: status,
|
24
|
+
}.compact
|
25
|
+
|
26
|
+
length = 0
|
27
|
+
content =
|
28
|
+
if body
|
29
|
+
body
|
30
|
+
elsif path
|
31
|
+
File.read(path)
|
32
|
+
else
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
|
36
|
+
param_headers = headers || {}
|
37
|
+
if contentType
|
38
|
+
param_headers['content-type'] = contentType
|
39
|
+
elsif path
|
40
|
+
param_headers['content-type'] = mime_type_for(path)
|
41
|
+
end
|
42
|
+
|
43
|
+
if content
|
44
|
+
if content.is_a?(String)
|
45
|
+
params[:body] = content
|
46
|
+
params[:isBase64] = false
|
47
|
+
else
|
48
|
+
params[:body] = Base64.strict_encode64(content)
|
49
|
+
params[:isBase64] = true
|
50
|
+
end
|
51
|
+
param_headers['content-length'] ||= content.length.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
params[:headers] = HttpHeaders.new(param_headers).as_serialized
|
55
|
+
|
56
|
+
@channel.async_send_message_to_server('fulfill', params)
|
57
|
+
end
|
58
|
+
|
59
|
+
def continue(headers: nil, method: nil, postData: nil, url: nil)
|
60
|
+
overrides = { url: url, method: method }.compact
|
61
|
+
|
62
|
+
if headers
|
63
|
+
overrides[:headers] = HttpHeaders.new(headers).as_serialized
|
64
|
+
end
|
65
|
+
|
66
|
+
if postData
|
67
|
+
overrides[:postData] = Base64.strict_encode64(postData)
|
68
|
+
end
|
69
|
+
|
70
|
+
@channel.async_send_message_to_server('continue', overrides)
|
71
|
+
end
|
72
|
+
|
73
|
+
private def mime_type_for(filepath)
|
74
|
+
mime_types = MIME::Types.type_for(filepath)
|
75
|
+
mime_types.first.to_s || 'application/octet-stream'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -1,4 +1,22 @@
|
|
1
1
|
module Playwright
|
2
2
|
# https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_selectors.py
|
3
|
-
define_channel_owner :Selectors
|
3
|
+
define_channel_owner :Selectors do
|
4
|
+
def register(name, contentScript: nil, path: nil, script: nil)
|
5
|
+
source =
|
6
|
+
if path
|
7
|
+
File.read(path)
|
8
|
+
elsif script
|
9
|
+
script
|
10
|
+
else
|
11
|
+
raise ArgumentError.new('Either path or script parameter must be specified')
|
12
|
+
end
|
13
|
+
params = { name: name, source: source }
|
14
|
+
if contentScript
|
15
|
+
params[:contentScript] = true
|
16
|
+
end
|
17
|
+
@channel.send_message_to_server('register', params)
|
18
|
+
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
4
22
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Playwright
|
2
|
+
class RouteHandlerEntry
|
3
|
+
# @param url [String]
|
4
|
+
# @param handler [Proc]
|
5
|
+
def initialize(url, handler)
|
6
|
+
@url_value = url
|
7
|
+
@url_matcher = UrlMatcher.new(url)
|
8
|
+
@handler = handler
|
9
|
+
end
|
10
|
+
|
11
|
+
def handle(route, request)
|
12
|
+
if url_match?(request.url)
|
13
|
+
@handler.call(route, request)
|
14
|
+
true
|
15
|
+
else
|
16
|
+
false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def same_value?(url:, handler: nil)
|
21
|
+
if handler
|
22
|
+
@url_value == url && @handler == handler
|
23
|
+
else
|
24
|
+
@url_value == url
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private def url_match?(request_url)
|
29
|
+
if @url_value.is_a?(Regexp)
|
30
|
+
@url_matcher.match?(request_url)
|
31
|
+
else
|
32
|
+
@url_matcher.match?(request_url) || File.fnmatch?(@url_value, request_url)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/playwright/utils.rb
CHANGED
@@ -3,6 +3,7 @@ module Playwright
|
|
3
3
|
module PrepareBrowserContextOptions
|
4
4
|
# @see https://github.com/microsoft/playwright/blob/5a2cfdbd47ed3c3deff77bb73e5fac34241f649d/src/client/browserContext.ts#L265
|
5
5
|
private def prepare_browser_context_options(params)
|
6
|
+
params[:sdkLanguage] = 'ruby'
|
6
7
|
if params[:noViewport] == 0
|
7
8
|
params.delete(:noViewport)
|
8
9
|
params[:noDefaultViewport] = true
|
data/lib/playwright/version.rb
CHANGED
@@ -1,28 +1,100 @@
|
|
1
1
|
module Playwright
|
2
|
-
#
|
2
|
+
# Playwright has **experimental** support for Android automation. You can access android namespace via:
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# ```js
|
6
|
+
# const { _android } = require('playwright');
|
7
|
+
# ```
|
8
|
+
#
|
9
|
+
# An example of the Android automation script would be:
|
10
|
+
#
|
11
|
+
#
|
12
|
+
# ```js
|
13
|
+
# const { _android } = require('playwright');
|
14
|
+
#
|
15
|
+
# (async () => {
|
16
|
+
# // Connect to the device.
|
17
|
+
# const [device] = await playwright._android.devices();
|
18
|
+
# console.log(`Model: ${device.model()}`);
|
19
|
+
# console.log(`Serial: ${device.serial()}`);
|
20
|
+
# // Take screenshot of the whole device.
|
21
|
+
# await device.screenshot({ path: 'device.png' });
|
22
|
+
#
|
23
|
+
# {
|
24
|
+
# // --------------------- WebView -----------------------
|
25
|
+
#
|
26
|
+
# // Launch an application with WebView.
|
27
|
+
# await device.shell('am force-stop org.chromium.webview_shell');
|
28
|
+
# await device.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
|
29
|
+
# // Get the WebView.
|
30
|
+
# const webview = await device.webView({ pkg: 'org.chromium.webview_shell' });
|
31
|
+
#
|
32
|
+
# // Fill the input box.
|
33
|
+
# await device.fill({ res: 'org.chromium.webview_shell:id/url_field' }, 'github.com/microsoft/playwright');
|
34
|
+
# await device.press({ res: 'org.chromium.webview_shell:id/url_field' }, 'Enter');
|
35
|
+
#
|
36
|
+
# // Work with WebView's page as usual.
|
37
|
+
# const page = await webview.page();
|
38
|
+
# await page.page.waitForNavigation({ url: /.*microsoft\/playwright.*/ });
|
39
|
+
# console.log(await page.title());
|
40
|
+
# }
|
41
|
+
#
|
42
|
+
# {
|
43
|
+
# // --------------------- Browser -----------------------
|
44
|
+
#
|
45
|
+
# // Launch Chrome browser.
|
46
|
+
# await device.shell('am force-stop com.android.chrome');
|
47
|
+
# const context = await device.launchBrowser();
|
48
|
+
#
|
49
|
+
# // Use BrowserContext as usual.
|
50
|
+
# const page = await context.newPage();
|
51
|
+
# await page.goto('https://webkit.org/');
|
52
|
+
# console.log(await page.evaluate(() => window.location.href));
|
53
|
+
# await page.screenshot({ path: 'page.png' });
|
54
|
+
#
|
55
|
+
# await context.close();
|
56
|
+
# }
|
57
|
+
#
|
58
|
+
# // Close the device.
|
59
|
+
# await device.close();
|
60
|
+
# })();
|
61
|
+
# ```
|
62
|
+
#
|
63
|
+
# Note that since you don't need Playwright to install web browsers when testing Android, you can omit browser download
|
64
|
+
# via setting the following environment variable when installing Playwright:
|
65
|
+
#
|
66
|
+
# ```sh js
|
67
|
+
# $ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm i -D playwright
|
68
|
+
# ```
|
3
69
|
class Android < PlaywrightApi
|
4
70
|
|
5
|
-
#
|
71
|
+
# Returns the list of detected Android devices.
|
6
72
|
def devices
|
7
73
|
wrap_impl(@impl.devices)
|
8
74
|
end
|
9
75
|
|
76
|
+
# This setting will change the default maximum time for all the methods accepting `timeout` option.
|
77
|
+
def set_default_timeout(timeout)
|
78
|
+
raise NotImplementedError.new('set_default_timeout is not implemented yet.')
|
79
|
+
end
|
80
|
+
alias_method :default_timeout=, :set_default_timeout
|
81
|
+
|
10
82
|
# -- inherited from EventEmitter --
|
11
83
|
# @nodoc
|
12
|
-
def
|
13
|
-
event_emitter_proxy.
|
84
|
+
def off(event, callback)
|
85
|
+
event_emitter_proxy.off(event, callback)
|
14
86
|
end
|
15
87
|
|
16
88
|
# -- inherited from EventEmitter --
|
17
89
|
# @nodoc
|
18
|
-
def
|
19
|
-
event_emitter_proxy.
|
90
|
+
def once(event, callback)
|
91
|
+
event_emitter_proxy.once(event, callback)
|
20
92
|
end
|
21
93
|
|
22
94
|
# -- inherited from EventEmitter --
|
23
95
|
# @nodoc
|
24
|
-
def
|
25
|
-
event_emitter_proxy.
|
96
|
+
def on(event, callback)
|
97
|
+
event_emitter_proxy.on(event, callback)
|
26
98
|
end
|
27
99
|
|
28
100
|
private def event_emitter_proxy
|