minibidi 0.0.0 → 0.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 607b907a85631222aca0cf29e33cdcc76af704464e8a64ee19b9e2da1b6c3b75
4
- data.tar.gz: 527e055f3473a2c08f26157d466f2759a210476e97e63d341f90e91b7053315a
3
+ metadata.gz: 74c2b07cd5b5a34c85ca23e6127e5c09b23af0814ab91339e8ffc3c18f2aaec4
4
+ data.tar.gz: 1de813a159df9930ffa27dc69b3c68426faebbe3604dc631b03fb899ea39a7ce
5
5
  SHA512:
6
- metadata.gz: 2a470c291ead662299187dff8f4cf4b3eaffa7308ad3ad15adee38ce39fa5112d93941ceabd120a7e7d47bd2153a36d449c18935364d90f346b5fac5def8ac3f
7
- data.tar.gz: 6ca0eff8038b65628ebf1e66040c5ed7d6b4ffbcd997084e018feeb8911974295e13c61d0d79652b74b20e54dd11ca60df332e992ece59c6231fe3265a4c3030
6
+ metadata.gz: 2be5e98fd4c177b4b087a3ca8af9efa5110386df709de76c61b477463b44fb6a797c13c002f270fba542a8b548a226dbae8dfa86000d26cc4b93fbd4bd486025
7
+ data.tar.gz: 185322a8c0ee29af4e7fd1a0663dc89746ab7203163c5a9f27bd17158b17a009d7f7dde2b910163f950c678a4f66e1a18133fdd69f7d40353d69df32c21f2e30
data/Gemfile CHANGED
@@ -4,3 +4,11 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in minibidi.gemspec
6
6
  gemspec
7
+
8
+ gem "bundler"
9
+ gem "minitest"
10
+ gem "pry"
11
+ gem "rack-test_server"
12
+ gem "rake"
13
+ gem "sinatra", require: false
14
+ gem 'webrick'
@@ -1,5 +1,6 @@
1
1
  require 'async'
2
2
  require 'async/variable'
3
+ require 'json'
3
4
 
4
5
  module Minibidi
5
6
  class Browser
@@ -8,10 +9,8 @@ module Minibidi
8
9
  @debug_protocol = %w[1 true].include?(ENV['DEBUG'])
9
10
 
10
11
  Async do
11
- while data = async_websocket_connection.read
12
- if message = Protocol::WebSocket::JSONMessage.wrap(data)
13
- handle_received_message_from_websocket(message.to_h)
14
- end
12
+ while message = async_websocket_connection.read
13
+ handle_received_message_from_websocket(message.to_h)
15
14
  end
16
15
  end
17
16
 
@@ -79,7 +78,7 @@ module Minibidi
79
78
 
80
79
  def send_message_to_websocket(payload)
81
80
  debug_print_send(payload)
82
- message = Protocol::WebSocket::JSONMessage.generate(payload)
81
+ message = Protocol::WebSocket::TextMessage.new(JSON.generate(payload))
83
82
  message.send(@websocket)
84
83
  @websocket.flush
85
84
  end
@@ -105,7 +104,7 @@ module Minibidi
105
104
  new(
106
105
  type: payload[:error],
107
106
  message: payload[:message],
108
- stacktrace: payload[:stacktrace].split("\n"),
107
+ stacktrace: (payload[:stacktrace] || '').split("\n"),
109
108
  )
110
109
  end
111
110
 
@@ -7,19 +7,76 @@ module Minibidi
7
7
  @context_id = context_id
8
8
  end
9
9
 
10
- def navigate(url)
11
- bidi_call_async('browsingContext.navigate', { url: url, wait: :interactive }).wait
10
+ def navigate(url, wait: :interactive)
11
+ bidi_call_async('browsingContext.navigate', {
12
+ url: url,
13
+ wait: wait,
14
+ }.compact).wait
12
15
  end
13
16
 
14
- def capture_screenshot(origin:, format:)
17
+ def realms
18
+ result = bidi_call_async('script.getRealms').wait
19
+ result[:realms].map do |realm|
20
+ Realm.new(
21
+ browsing_context: self,
22
+ id: realm[:realm],
23
+ origin: realm[:origin],
24
+ type: realm[:type],
25
+ )
26
+ end
27
+ end
28
+
29
+ def default_realm
30
+ realms.find { |realm| realm.type == 'window' }
31
+ end
32
+
33
+ def input
34
+ Input.new(self)
35
+ end
36
+
37
+ def activate
38
+ bidi_call_async('browsingContext.activate').wait
39
+ end
40
+
41
+ def capture_screenshot(origin: nil, format: nil, clip: nil)
15
42
  result = bidi_call_async('browsingContext.captureScreenshot', {
16
43
  origin: origin,
17
44
  format: format,
18
- }).wait
45
+ clip: clip,
46
+ }.compact).wait
19
47
 
20
48
  Base64.strict_decode64(result[:data])
21
49
  end
22
50
 
51
+ def close(prompt_unload: nil)
52
+ bidi_call_async('browsingContext.close', {
53
+ promptUnload: prompt_unload,
54
+ }.compact).wait
55
+ end
56
+
57
+ def reload(ignore_cache: nil, wait: nil)
58
+ bidi_call_async('browsingContext.reload', {
59
+ ignoreCache: ignore_cache,
60
+ wait: wait,
61
+ }.compact).wait
62
+ end
63
+
64
+ def set_viewport(width:, height:, device_pixel_ratio: nil)
65
+ bidi_call_async('browsingContext.setViewport', {
66
+ viewport: {
67
+ width: width,
68
+ height: height,
69
+ },
70
+ devicePixelRatio: device_pixel_ratio,
71
+ }.compact).wait
72
+ end
73
+
74
+ def traverse_history(delta)
75
+ bidi_call_async('browsingContext.traverseHistory', {
76
+ delta: delta,
77
+ }).wait
78
+ end
79
+
23
80
  private
24
81
 
25
82
  def bidi_call_async(method_, params = {})
@@ -2,41 +2,72 @@ require 'async'
2
2
  require 'async/http/endpoint'
3
3
  require 'async/websocket'
4
4
  require 'open3'
5
- require 'protocol/websocket/json_message'
6
5
  require 'timeout'
7
6
  require 'tmpdir'
8
7
 
9
8
  module Minibidi
9
+ class Firefox
10
+ def self.launch(&block)
11
+ FirefoxLauncher.new.launch(&block)
12
+ end
13
+
14
+ def self.discover_binary
15
+ # check if macOS
16
+ if RUBY_PLATFORM =~ /darwin/
17
+ if File.exist?("/Applications/Firefox Developer Edition.app/Contents/MacOS/firefox")
18
+ return "/Applications/Firefox Developer Edition.app/Contents/MacOS/firefox"
19
+ end
20
+ elsif RUBY_PLATFORM =~ /linux/
21
+ if File.exist?("/usr/bin/firefox-devedition")
22
+ return "/usr/bin/firefox-devedition"
23
+ end
24
+ end
25
+
26
+ raise LaunchError, 'Firefox Developer Edition is not found. Please install it from https://www.mozilla.org/firefox/developer/'
27
+ end
28
+ end
29
+
10
30
  class FirefoxLauncher
11
31
  def launch(&block)
12
32
  raise ArgumentError, "block is required" unless block
13
33
 
14
- Dir.mktmpdir('minibidi') do |tmp|
15
- create_user_profile(tmp)
34
+ tmp = Dir.mktmpdir('minibidi')
35
+ create_user_profile(tmp)
36
+ args = [
37
+ "--remote-debugging-port=0",
38
+ "--profile",
39
+ tmp,
40
+ "--no-remote",
41
+ ]
42
+ if RUBY_PLATFORM =~ /darwin/
43
+ args << "--foreground"
44
+ end
45
+ if %w[true 1].include?(ENV['HEADLESS'])
46
+ args << "--headless"
47
+ end
16
48
 
17
- proc = BrowserProcess.new(
18
- "/Applications/Firefox Developer Edition.app/Contents/MacOS/firefox",
19
- "--remote-debugging-port=0",
20
- "--profile #{tmp}",
21
- "--no-remote",
22
- "--foreground",
23
- "about:blank",
24
- )
25
- at_exit { proc.kill }
26
- trap(:INT) { proc.kill ; exit 130 }
27
- trap(:TERM) { proc.kill ; proc.dispose }
28
- trap(:HUP) { proc.kill ; proc.dispose }
49
+ proc = BrowserProcess.new(
50
+ Firefox.discover_binary,
51
+ *args,
52
+ "about:blank",
53
+ )
54
+ at_exit do
55
+ proc.kill
56
+ FileUtils.remove_entry(tmp)
57
+ end
58
+ trap(:INT) { proc.kill ; exit 130 }
59
+ trap(:TERM) { proc.kill ; proc.dispose }
60
+ trap(:HUP) { proc.kill ; proc.dispose }
29
61
 
30
- endpoint = wait_for_ws_endpoint(proc)
62
+ endpoint = wait_for_ws_endpoint(proc)
31
63
 
32
- Async::Reactor.run do
33
- Async::WebSocket::Client.connect(Async::HTTP::Endpoint.parse("#{endpoint}/session")) do |async_websocket_connection|
34
- browser = Browser.new(async_websocket_connection)
35
- begin
36
- block.call(browser)
37
- ensure
38
- browser.close
39
- end
64
+ Async::Reactor.run do
65
+ Async::WebSocket::Client.connect(Async::HTTP::Endpoint.parse("#{endpoint}/session")) do |async_websocket_connection|
66
+ browser = Browser.new(async_websocket_connection)
67
+ begin
68
+ block.call(browser)
69
+ ensure
70
+ browser.close
40
71
  end
41
72
  end
42
73
  end
@@ -0,0 +1,298 @@
1
+ module Minibidi
2
+ class Input
3
+ def initialize(browser_context)
4
+ @browser_context = browser_context
5
+ end
6
+
7
+ def click(x:, y:, delay: 50)
8
+ perform_mouse_actions do |q|
9
+ q.pointer_move(x: x.to_i, y: y.to_i)
10
+ q.pointer_down(button: 0)
11
+ q.pause(delay)
12
+ q.pointer_up(button: 0)
13
+ end
14
+ end
15
+
16
+ def while_pressing_key(key, &block)
17
+ value = convert_key(key)
18
+ perform_keyboard_actions do |q|
19
+ q.key_down(value)
20
+ end
21
+
22
+ begin
23
+ block.call
24
+ ensure
25
+ perform_keyboard_actions do |q|
26
+ q.key_up(value)
27
+ end
28
+ end
29
+ end
30
+
31
+ def press_key(key, delay: 50)
32
+ value = convert_key(key)
33
+ perform_keyboard_actions do |q|
34
+ q.key_down(value)
35
+ q.pause(delay)
36
+ q.key_up(value)
37
+ end
38
+ end
39
+
40
+ def type_text(text, delay: 50)
41
+ text.each_char do |char|
42
+ perform_keyboard_actions do |q|
43
+ q.key_down(char)
44
+ q.pause(delay / 2)
45
+ q.key_up(char)
46
+ q.pause(delay / 2)
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def perform_actions(actions)
54
+ @browser_context.send(:bidi_call_async, 'input.performActions', {
55
+ actions: actions,
56
+ }).wait
57
+ end
58
+
59
+ def perform_keyboard_actions(&block)
60
+ q = KeyboardActionQueue.new
61
+ block.call(q)
62
+ perform_actions([{
63
+ type: 'key',
64
+ id: '__minibidi_keyboard',
65
+ actions: q.to_a,
66
+ }])
67
+ end
68
+
69
+ def perform_mouse_actions(&block)
70
+ q = MouseActionQueue.new
71
+ block.call(q)
72
+ perform_actions([{
73
+ type: 'pointer',
74
+ id: '__minibidi_mouse',
75
+ actions: q.to_a,
76
+ }])
77
+ end
78
+
79
+ def macos?
80
+ RUBY_PLATFORM =~ /darwin/
81
+ end
82
+
83
+ # ref: https://github.com/puppeteer/puppeteer/blob/puppeteer-v23.5.3/packages/puppeteer-core/src/bidi/Input.ts#L52
84
+ # Converted using ChatGPT 4o
85
+ def convert_key(key)
86
+ return key if key.length == 1
87
+
88
+ case key
89
+ when 'Cancel'
90
+ "\uE001"
91
+ when 'Help'
92
+ "\uE002"
93
+ when 'Backspace'
94
+ "\uE003"
95
+ when 'Tab'
96
+ "\uE004"
97
+ when 'Clear'
98
+ "\uE005"
99
+ when 'Enter'
100
+ "\uE007"
101
+ when 'Shift', 'ShiftLeft'
102
+ "\uE008"
103
+ when 'Control', 'ControlLeft', 'Ctrl'
104
+ "\uE009"
105
+ when 'ControlOrMeta', 'CtrlOrMeta'
106
+ macos? ? "\uE03D" : "\uE009"
107
+ when 'Alt', 'AltLeft'
108
+ "\uE00A"
109
+ when 'Pause'
110
+ "\uE00B"
111
+ when 'Escape'
112
+ "\uE00C"
113
+ when 'PageUp'
114
+ "\uE00E"
115
+ when 'PageDown'
116
+ "\uE00F"
117
+ when 'End'
118
+ "\uE010"
119
+ when 'Home'
120
+ "\uE011"
121
+ when 'ArrowLeft'
122
+ "\uE012"
123
+ when 'ArrowUp'
124
+ "\uE013"
125
+ when 'ArrowRight'
126
+ "\uE014"
127
+ when 'ArrowDown'
128
+ "\uE015"
129
+ when 'Insert'
130
+ "\uE016"
131
+ when 'Delete'
132
+ "\uE017"
133
+ when 'NumpadEqual'
134
+ "\uE019"
135
+ when 'Numpad0'
136
+ "\uE01A"
137
+ when 'Numpad1'
138
+ "\uE01B"
139
+ when 'Numpad2'
140
+ "\uE01C"
141
+ when 'Numpad3'
142
+ "\uE01D"
143
+ when 'Numpad4'
144
+ "\uE01E"
145
+ when 'Numpad5'
146
+ "\uE01F"
147
+ when 'Numpad6'
148
+ "\uE020"
149
+ when 'Numpad7'
150
+ "\uE021"
151
+ when 'Numpad8'
152
+ "\uE022"
153
+ when 'Numpad9'
154
+ "\uE023"
155
+ when 'NumpadMultiply'
156
+ "\uE024"
157
+ when 'NumpadAdd'
158
+ "\uE025"
159
+ when 'NumpadSubtract'
160
+ "\uE027"
161
+ when 'NumpadDecimal'
162
+ "\uE028"
163
+ when 'NumpadDivide'
164
+ "\uE029"
165
+ when 'F1'
166
+ "\uE031"
167
+ when 'F2'
168
+ "\uE032"
169
+ when 'F3'
170
+ "\uE033"
171
+ when 'F4'
172
+ "\uE034"
173
+ when 'F5'
174
+ "\uE035"
175
+ when 'F6'
176
+ "\uE036"
177
+ when 'F7'
178
+ "\uE037"
179
+ when 'F8'
180
+ "\uE038"
181
+ when 'F9'
182
+ "\uE039"
183
+ when 'F10'
184
+ "\uE03A"
185
+ when 'F11'
186
+ "\uE03B"
187
+ when 'F12'
188
+ "\uE03C"
189
+ when 'Meta', 'MetaLeft'
190
+ "\uE03D"
191
+ when 'ShiftRight'
192
+ "\uE050"
193
+ when 'ControlRight'
194
+ "\uE051"
195
+ when 'AltRight'
196
+ "\uE052"
197
+ when 'MetaRight'
198
+ "\uE053"
199
+ when 'Digit0'
200
+ '0'
201
+ when 'Digit1'
202
+ '1'
203
+ when 'Digit2'
204
+ '2'
205
+ when 'Digit3'
206
+ '3'
207
+ when 'Digit4'
208
+ '4'
209
+ when 'Digit5'
210
+ '5'
211
+ when 'Digit6'
212
+ '6'
213
+ when 'Digit7'
214
+ '7'
215
+ when 'Digit8'
216
+ '8'
217
+ when 'Digit9'
218
+ '9'
219
+ when 'KeyA'
220
+ 'a'
221
+ when 'KeyB'
222
+ 'b'
223
+ when 'KeyC'
224
+ 'c'
225
+ when 'KeyD'
226
+ 'd'
227
+ when 'KeyE'
228
+ 'e'
229
+ when 'KeyF'
230
+ 'f'
231
+ when 'KeyG'
232
+ 'g'
233
+ when 'KeyH'
234
+ 'h'
235
+ when 'KeyI'
236
+ 'i'
237
+ when 'KeyJ'
238
+ 'j'
239
+ when 'KeyK'
240
+ 'k'
241
+ when 'KeyL'
242
+ 'l'
243
+ when 'KeyM'
244
+ 'm'
245
+ when 'KeyN'
246
+ 'n'
247
+ when 'KeyO'
248
+ 'o'
249
+ when 'KeyP'
250
+ 'p'
251
+ when 'KeyQ'
252
+ 'q'
253
+ when 'KeyR'
254
+ 'r'
255
+ when 'KeyS'
256
+ 's'
257
+ when 'KeyT'
258
+ 't'
259
+ when 'KeyU'
260
+ 'u'
261
+ when 'KeyV'
262
+ 'v'
263
+ when 'KeyW'
264
+ 'w'
265
+ when 'KeyX'
266
+ 'x'
267
+ when 'KeyY'
268
+ 'y'
269
+ when 'KeyZ'
270
+ 'z'
271
+ when 'Semicolon'
272
+ ';'
273
+ when 'Equal'
274
+ '='
275
+ when 'Comma'
276
+ ','
277
+ when 'Minus'
278
+ '-'
279
+ when 'Period'
280
+ '.'
281
+ when 'Slash'
282
+ '/'
283
+ when 'Backquote'
284
+ '`'
285
+ when 'BracketLeft'
286
+ '['
287
+ when 'Backslash'
288
+ '\\'
289
+ when 'BracketRight'
290
+ ']'
291
+ when 'Quote'
292
+ '"'
293
+ else
294
+ raise ArgumentError, "Unknown key: \"#{key}\""
295
+ end
296
+ end
297
+ end
298
+ end
@@ -0,0 +1,23 @@
1
+ module Minibidi
2
+ class KeyboardActionQueue
3
+ def initialize
4
+ @actions = []
5
+ end
6
+
7
+ def to_a
8
+ @actions
9
+ end
10
+
11
+ def pause(duration)
12
+ @actions << { type: 'pause', duration: duration }
13
+ end
14
+
15
+ def key_down(value)
16
+ @actions << { type: 'keyDown', value: value }
17
+ end
18
+
19
+ def key_up(value)
20
+ @actions << { type: 'keyUp', value: value }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,29 @@
1
+ module Minibidi
2
+ class MouseActionQueue
3
+ def initialize
4
+ @actions = []
5
+ end
6
+
7
+ def to_a
8
+ @actions
9
+ end
10
+
11
+ def pause(duration)
12
+ @actions << { type: 'pause', duration: duration }
13
+ end
14
+
15
+ # button: 0 for left, 1 for middle, 2 for right
16
+ def pointer_down(button:)
17
+ @actions << { type: 'pointerDown', button: button }
18
+ end
19
+
20
+ def pointer_move(x:, y:, duration: nil)
21
+ @actions << { type: 'pointerMove', x: x, y: y, duration: duration }.compact
22
+ end
23
+
24
+ # button: 0 for left, 1 for middle, 2 for right
25
+ def pointer_up(button:)
26
+ @actions << { type: 'pointerUp', button: button }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,76 @@
1
+ module Minibidi
2
+ class Realm
3
+ def initialize(browsing_context:, id:, origin:, type: nil)
4
+ @browsing_context = browsing_context
5
+ @id = id
6
+ @origin = origin
7
+ @type = type
8
+ end
9
+
10
+ class ScriptEvaluationError < StandardError ; end
11
+
12
+ def script_evaluate(expression)
13
+ result = @browsing_context.send(:bidi_call_async, 'script.evaluate', {
14
+ expression: expression,
15
+ target: { realm: @id },
16
+ awaitPromise: true,
17
+ }).wait
18
+
19
+ if result[:type] == 'exception'
20
+ raise ScriptEvaluationError.new(result[:exceptionDetails][:text])
21
+ end
22
+
23
+ deserialize(result[:result])
24
+ end
25
+
26
+ attr_reader :type
27
+
28
+ private
29
+
30
+ def deserialize(result)
31
+ # ref: https://github.com/puppeteer/puppeteer/blob/puppeteer-v23.5.3/packages/puppeteer-core/src/bidi/Deserializer.ts#L21
32
+ # Converted using ChatGPT 4o
33
+ case result[:type]
34
+ when 'array'
35
+ result[:value]&.map { |value| deserialize(value) }
36
+ when 'set'
37
+ result[:value]&.each_with_object(Set.new) do |value, acc|
38
+ acc.add(deserialize(value))
39
+ end
40
+ when 'object'
41
+ result[:value]&.each_with_object({}) do |tuple, acc|
42
+ key, value = tuple
43
+ acc[key] = deserialize(value)
44
+ end
45
+ when 'map'
46
+ result[:value]&.each_with_object({}) do |tuple, acc|
47
+ key, value = tuple
48
+ acc[key] = deserialize(value)
49
+ end
50
+ when 'promise'
51
+ {}
52
+ when 'regexp'
53
+ flags = 0
54
+ result[:value][:flags]&.each_char do |flag|
55
+ case flag
56
+ when 'm'
57
+ flags |= Regexp::MULTILINE
58
+ when 'i'
59
+ flags |= Regexp::IGNORECASE
60
+ end
61
+ end
62
+ Regexp.new(result[:value][:pattern], flags)
63
+ when 'date'
64
+ Date.parse(result[:value])
65
+ when 'undefined'
66
+ nil
67
+ when 'null'
68
+ nil
69
+ when 'number', 'bigint', 'boolean', 'string'
70
+ result[:value]
71
+ else
72
+ raise ArgumentError, "Unknown type: #{result[:type]}"
73
+ end
74
+ end
75
+ end
76
+ end
@@ -1,3 +1,3 @@
1
1
  module Minibidi
2
- VERSION = '0.0.0'
2
+ VERSION = '0.1.0'
3
3
  end
data/lib/minibidi.rb CHANGED
@@ -3,8 +3,11 @@ require "minibidi/version"
3
3
  require 'minibidi/browser'
4
4
  require 'minibidi/browsing_context'
5
5
  require 'minibidi/browser_process'
6
- require 'minibidi/firefox'
7
6
  require 'minibidi/firefox_launcher'
7
+ require 'minibidi/input'
8
+ require 'minibidi/keyboard_action_queue'
9
+ require 'minibidi/mouse_action_queue'
10
+ require 'minibidi/realm'
8
11
 
9
12
  module Minibidi
10
13
  class LaunchError < StandardError ; end
data/minibidi.gemspec CHANGED
@@ -25,8 +25,4 @@ Gem::Specification.new do |spec|
25
25
  spec.required_ruby_version = ">= 3.2" # Dependency for socketry/async and Data.define
26
26
  spec.add_dependency "async"
27
27
  spec.add_dependency "async-websocket"
28
- spec.add_development_dependency "bundler"
29
- spec.add_development_dependency "minitest"
30
- spec.add_development_dependency "pry"
31
- spec.add_development_dependency "rake"
32
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minibidi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.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-04-08 00:00:00.000000000 Z
11
+ date: 2024-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -38,62 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: bundler
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: minitest
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: pry
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: rake
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
41
  description:
98
42
  email:
99
43
  - q7w8e9w8q7w8e9@yahoo.co.jp
@@ -110,8 +54,11 @@ files:
110
54
  - lib/minibidi/browser.rb
111
55
  - lib/minibidi/browser_process.rb
112
56
  - lib/minibidi/browsing_context.rb
113
- - lib/minibidi/firefox.rb
114
57
  - lib/minibidi/firefox_launcher.rb
58
+ - lib/minibidi/input.rb
59
+ - lib/minibidi/keyboard_action_queue.rb
60
+ - lib/minibidi/mouse_action_queue.rb
61
+ - lib/minibidi/realm.rb
115
62
  - lib/minibidi/version.rb
116
63
  - minibidi.gemspec
117
64
  homepage: https://github.com/YusukeIwaki/minibidi
@@ -133,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
80
  - !ruby/object:Gem::Version
134
81
  version: '0'
135
82
  requirements: []
136
- rubygems_version: 3.5.3
83
+ rubygems_version: 3.5.22
137
84
  signing_key:
138
85
  specification_version: 4
139
86
  summary: Mini WebDriver BiDi binding for Ruby
@@ -1,7 +0,0 @@
1
- module Minibidi
2
- class Firefox
3
- def self.launch(&block)
4
- FirefoxLauncher.new.launch(&block)
5
- end
6
- end
7
- end