puppeteer-ruby 0.45.6 → 0.50.0.alpha5

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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -3
  3. data/AGENTS.md +169 -0
  4. data/CLAUDE/README.md +41 -0
  5. data/CLAUDE/architecture.md +253 -0
  6. data/CLAUDE/cdp_protocol.md +230 -0
  7. data/CLAUDE/concurrency.md +216 -0
  8. data/CLAUDE/porting_puppeteer.md +575 -0
  9. data/CLAUDE/rbs_type_checking.md +101 -0
  10. data/CLAUDE/spec_migration_plans.md +1041 -0
  11. data/CLAUDE/testing.md +278 -0
  12. data/CLAUDE.md +242 -0
  13. data/README.md +8 -0
  14. data/Rakefile +7 -0
  15. data/Steepfile +28 -0
  16. data/docs/api_coverage.md +105 -56
  17. data/lib/puppeteer/aria_query_handler.rb +3 -2
  18. data/lib/puppeteer/async_utils.rb +214 -0
  19. data/lib/puppeteer/browser.rb +98 -56
  20. data/lib/puppeteer/browser_connector.rb +18 -3
  21. data/lib/puppeteer/browser_context.rb +196 -3
  22. data/lib/puppeteer/browser_runner.rb +18 -10
  23. data/lib/puppeteer/cdp_session.rb +67 -23
  24. data/lib/puppeteer/chrome_target_manager.rb +65 -40
  25. data/lib/puppeteer/connection.rb +55 -36
  26. data/lib/puppeteer/console_message.rb +9 -1
  27. data/lib/puppeteer/console_patch.rb +47 -0
  28. data/lib/puppeteer/css_coverage.rb +5 -3
  29. data/lib/puppeteer/custom_query_handler.rb +80 -33
  30. data/lib/puppeteer/define_async_method.rb +31 -37
  31. data/lib/puppeteer/dialog.rb +47 -14
  32. data/lib/puppeteer/element_handle.rb +231 -62
  33. data/lib/puppeteer/emulation_manager.rb +1 -1
  34. data/lib/puppeteer/env.rb +1 -1
  35. data/lib/puppeteer/errors.rb +25 -2
  36. data/lib/puppeteer/event_callbackable.rb +15 -0
  37. data/lib/puppeteer/events.rb +4 -0
  38. data/lib/puppeteer/execution_context.rb +148 -3
  39. data/lib/puppeteer/file_chooser.rb +6 -0
  40. data/lib/puppeteer/frame.rb +162 -91
  41. data/lib/puppeteer/frame_manager.rb +69 -48
  42. data/lib/puppeteer/http_request.rb +114 -38
  43. data/lib/puppeteer/http_response.rb +24 -7
  44. data/lib/puppeteer/isolated_world.rb +64 -41
  45. data/lib/puppeteer/js_coverage.rb +5 -3
  46. data/lib/puppeteer/js_handle.rb +58 -16
  47. data/lib/puppeteer/keyboard.rb +30 -17
  48. data/lib/puppeteer/launcher/browser_options.rb +3 -1
  49. data/lib/puppeteer/launcher/chrome.rb +8 -5
  50. data/lib/puppeteer/launcher/launch_options.rb +7 -2
  51. data/lib/puppeteer/launcher.rb +4 -8
  52. data/lib/puppeteer/lifecycle_watcher.rb +38 -22
  53. data/lib/puppeteer/mouse.rb +273 -64
  54. data/lib/puppeteer/network_event_manager.rb +7 -0
  55. data/lib/puppeteer/network_manager.rb +393 -112
  56. data/lib/puppeteer/page/screenshot_task_queue.rb +14 -4
  57. data/lib/puppeteer/page.rb +568 -226
  58. data/lib/puppeteer/puppeteer.rb +171 -64
  59. data/lib/puppeteer/query_handler_manager.rb +112 -16
  60. data/lib/puppeteer/reactor_runner.rb +247 -0
  61. data/lib/puppeteer/remote_object.rb +127 -47
  62. data/lib/puppeteer/target.rb +74 -27
  63. data/lib/puppeteer/task_manager.rb +3 -1
  64. data/lib/puppeteer/timeout_helper.rb +6 -10
  65. data/lib/puppeteer/touch_handle.rb +39 -0
  66. data/lib/puppeteer/touch_screen.rb +72 -22
  67. data/lib/puppeteer/tracing.rb +3 -3
  68. data/lib/puppeteer/version.rb +1 -1
  69. data/lib/puppeteer/wait_task.rb +264 -101
  70. data/lib/puppeteer/web_socket.rb +2 -2
  71. data/lib/puppeteer/web_socket_transport.rb +91 -27
  72. data/lib/puppeteer/web_worker.rb +175 -0
  73. data/lib/puppeteer.rb +20 -4
  74. data/puppeteer-ruby.gemspec +15 -11
  75. data/sig/_external.rbs +8 -0
  76. data/sig/_supplementary.rbs +314 -0
  77. data/sig/puppeteer/browser.rbs +166 -0
  78. data/sig/puppeteer/cdp_session.rbs +64 -0
  79. data/sig/puppeteer/dialog.rbs +41 -0
  80. data/sig/puppeteer/element_handle.rbs +305 -0
  81. data/sig/puppeteer/execution_context.rbs +87 -0
  82. data/sig/puppeteer/frame.rbs +226 -0
  83. data/sig/puppeteer/http_request.rbs +214 -0
  84. data/sig/puppeteer/http_response.rbs +89 -0
  85. data/sig/puppeteer/js_handle.rbs +64 -0
  86. data/sig/puppeteer/keyboard.rbs +40 -0
  87. data/sig/puppeteer/mouse.rbs +113 -0
  88. data/sig/puppeteer/page.rbs +515 -0
  89. data/sig/puppeteer/puppeteer.rbs +98 -0
  90. data/sig/puppeteer/remote_object.rbs +78 -0
  91. data/sig/puppeteer/touch_handle.rbs +21 -0
  92. data/sig/puppeteer/touch_screen.rbs +35 -0
  93. data/sig/puppeteer/web_worker.rbs +83 -0
  94. metadata +116 -45
  95. data/CHANGELOG.md +0 -397
  96. data/lib/puppeteer/concurrent_ruby_utils.rb +0 -81
  97. data/lib/puppeteer/firefox_target_manager.rb +0 -157
  98. data/lib/puppeteer/launcher/firefox.rb +0 -453
data/CLAUDE/testing.md ADDED
@@ -0,0 +1,278 @@
1
+ # Testing Strategy
2
+
3
+ This document describes the testing approach for puppeteer-ruby.
4
+
5
+ ## Test Organization
6
+
7
+ ```
8
+ spec/
9
+ ├── integration/ # Browser automation tests (type: :puppeteer)
10
+ │ ├── page_spec.rb
11
+ │ ├── element_handle_spec.rb
12
+ │ ├── click_spec.rb
13
+ │ └── ...
14
+ ├── puppeteer/ # Unit tests (no browser required)
15
+ │ ├── devices_spec.rb
16
+ │ ├── launcher_spec.rb
17
+ │ └── ...
18
+ ├── assets/ # Test HTML/JS/CSS files
19
+ ├── golden_matcher.rb # Screenshot comparison matcher
20
+ ├── spec_helper.rb # RSpec configuration
21
+ └── utils.rb # Test utilities
22
+ ```
23
+
24
+ ## Integration Tests
25
+
26
+ ### Basic Structure
27
+
28
+ Integration tests use `type: :puppeteer` metadata which is automatically applied to files in `spec/integration/`:
29
+
30
+ ```ruby
31
+ RSpec.describe 'Page#goto' do
32
+ # This file is in spec/integration/, so type: :puppeteer is applied
33
+
34
+ it 'navigates to a URL' do
35
+ page.goto('https://example.com')
36
+ expect(page.title).to eq('Example Domain')
37
+ end
38
+ end
39
+ ```
40
+
41
+ ### Available Helpers
42
+
43
+ The `type: :puppeteer` metadata provides these helpers:
44
+
45
+ | Helper | Description |
46
+ |--------|-------------|
47
+ | `page` | Current `Puppeteer::Page` instance |
48
+ | `browser` | Browser instance (requires `puppeteer: :browser` metadata) |
49
+ | `browser_context` | BrowserContext (requires `browser_context: :incognito`) |
50
+ | `headless?` | Whether running in headless mode |
51
+ | `default_launch_options` | Launch options used for current test |
52
+
53
+ ### Test with Sinatra Server
54
+
55
+ For tests requiring a web server, use `sinatra: true` metadata:
56
+
57
+ ```ruby
58
+ RSpec.describe 'Page#goto', sinatra: true do
59
+ it 'navigates to local server' do
60
+ sinatra.get('/hello') { 'Hello World' }
61
+
62
+ page.goto("#{server_prefix}/hello")
63
+ expect(page.content).to include('Hello World')
64
+ end
65
+ end
66
+ ```
67
+
68
+ Sinatra helpers:
69
+
70
+ | Helper | Description |
71
+ |--------|-------------|
72
+ | `sinatra` | Sinatra app instance |
73
+ | `server_prefix` | `http://localhost:4567` |
74
+ | `server_cross_process_prefix` | `http://127.0.0.1:4567` |
75
+ | `server_empty_page` | `http://localhost:4567/empty.html` |
76
+
77
+ ### Test with Browser Instance
78
+
79
+ For tests that need direct browser access:
80
+
81
+ ```ruby
82
+ RSpec.describe 'Browser', puppeteer: :browser do
83
+ it 'creates new pages' do
84
+ page1 = browser.new_page
85
+ page2 = browser.new_page
86
+ expect(browser.pages.length).to eq(2)
87
+ end
88
+ end
89
+ ```
90
+
91
+ ### Incognito Context Tests
92
+
93
+ ```ruby
94
+ RSpec.describe 'BrowserContext', browser_context: :incognito do
95
+ it 'has isolated cookies' do
96
+ browser_context.set_cookie(name: 'test', value: 'value')
97
+ # Cookies are isolated to this context
98
+ end
99
+ end
100
+ ```
101
+
102
+ ### OOPIF (Out-of-Process IFrame) Tests
103
+
104
+ For tests requiring cross-process iframes, use `enable_site_per_process_flag: true`:
105
+
106
+ ```ruby
107
+ it 'clicks button in cross-process iframe', enable_site_per_process_flag: true do
108
+ with_test_state do |page:, server:, **|
109
+ page.goto(server.empty_page)
110
+ # Use cross_process_prefix (127.0.0.1) instead of prefix (localhost)
111
+ attach_frame(page, 'frame-id', "#{server.cross_process_prefix}/input/button.html")
112
+
113
+ frame = page.frames[1]
114
+ frame.click('button')
115
+ end
116
+ end
117
+ ```
118
+
119
+ This metadata launches Chrome with `--site-per-process` and `--host-rules=MAP * 127.0.0.1` flags.
120
+
121
+ ## Running Tests
122
+
123
+ ### Basic Commands
124
+
125
+ ```bash
126
+ # Run all tests
127
+ bundle exec rspec
128
+
129
+ # Run specific file
130
+ bundle exec rspec spec/integration/page_spec.rb
131
+
132
+ # Run specific test by line number
133
+ bundle exec rspec spec/integration/page_spec.rb:42
134
+
135
+ # Run with documentation format
136
+ bundle exec rspec --format documentation
137
+ ```
138
+
139
+ ### Chrome Configuration
140
+
141
+ ```bash
142
+ # Run with custom Chrome path
143
+ PUPPETEER_EXECUTABLE_PATH_RSPEC=/path/to/chrome bundle exec rspec
144
+
145
+ # Run with Chrome channel
146
+ PUPPETEER_CHANNEL_RSPEC=chrome-beta bundle exec rspec
147
+ ```
148
+
149
+ ### Debug Mode
150
+
151
+ ```bash
152
+ # Non-headless mode (see the browser)
153
+ DEBUG=1 bundle exec rspec spec/integration/page_spec.rb
154
+
155
+ # With debug output
156
+ DEBUG=1 bundle exec rspec spec/integration/page_spec.rb 2>&1 | tee test.log
157
+ ```
158
+
159
+ ### Container/CI Mode
160
+
161
+ ```bash
162
+ # Add --no-sandbox flag
163
+ PUPPETEER_NO_SANDBOX_RSPEC=true bundle exec rspec
164
+ ```
165
+
166
+ ## Screenshot Testing
167
+
168
+ ### Golden Matcher
169
+
170
+ Use `match_golden` matcher for screenshot comparisons:
171
+
172
+ ```ruby
173
+ RSpec.describe 'Page#screenshot' do
174
+ it 'captures page screenshot' do
175
+ page.goto(server_empty_page)
176
+ screenshot = page.screenshot
177
+
178
+ expect(screenshot).to match_golden('empty-page.png')
179
+ end
180
+ end
181
+ ```
182
+
183
+ Golden images are stored in `spec/golden/`.
184
+
185
+ ### Updating Golden Images
186
+
187
+ When intentionally changing visual output:
188
+
189
+ ```bash
190
+ # Remove old golden and re-run test to generate new one
191
+ rm spec/golden/empty-page.png
192
+ bundle exec rspec spec/integration/screenshot_spec.rb
193
+ ```
194
+
195
+ ## Writing New Tests
196
+
197
+ ### Guidelines
198
+
199
+ 1. **One assertion per test when possible** - Easier to identify failures
200
+ 2. **Use descriptive test names** - Should read like documentation
201
+ 3. **Clean up resources** - Close pages, restore state in `after` blocks
202
+ 4. **Minimize flakiness** - Use explicit waits, not sleeps
203
+
204
+ ### Example Test Pattern
205
+
206
+ ```ruby
207
+ RSpec.describe 'ElementHandle#click', sinatra: true do
208
+ before do
209
+ sinatra.get('/button') do
210
+ <<~HTML
211
+ <button onclick="window.clicked = true">Click me</button>
212
+ HTML
213
+ end
214
+ page.goto("#{server_prefix}/button")
215
+ end
216
+
217
+ it 'clicks the button' do
218
+ button = page.query_selector('button')
219
+ button.click
220
+
221
+ result = page.evaluate('() => window.clicked')
222
+ expect(result).to eq(true)
223
+ end
224
+
225
+ it 'triggers click event' do
226
+ events = []
227
+ page.evaluate(<<~JS)
228
+ document.querySelector('button').addEventListener('click', () => {
229
+ window.clickEvent = true;
230
+ });
231
+ JS
232
+
233
+ page.click('button')
234
+
235
+ expect(page.evaluate('() => window.clickEvent')).to eq(true)
236
+ end
237
+ end
238
+ ```
239
+
240
+ ## CI Configuration
241
+
242
+ Tests run on GitHub Actions with matrix of:
243
+
244
+ - Ruby versions: 3.2, 3.3, 3.4
245
+ - Environments: Ubuntu with Chrome, Alpine with Chromium
246
+
247
+ See `.github/workflows/ci.yml` for details.
248
+
249
+ ## Debugging Tips
250
+
251
+ ### See What's Happening
252
+
253
+ ```bash
254
+ # Run with visible browser
255
+ DEBUG=1 bundle exec rspec spec/integration/page_spec.rb
256
+
257
+ # Add screenshots for debugging
258
+ page.screenshot(path: 'debug.png')
259
+
260
+ # Log page content
261
+ puts page.content
262
+ ```
263
+
264
+ ### Slow Down Execution
265
+
266
+ ```ruby
267
+ # In spec_helper.rb or individual test
268
+ Puppeteer.launch(slow_mo: 100) do |browser|
269
+ # Actions are slowed by 100ms each
270
+ end
271
+ ```
272
+
273
+ ### Inspect CDP Messages
274
+
275
+ ```bash
276
+ # Enable CDP debug logging
277
+ DEBUG=1 bundle exec rspec 2>&1 | grep -E "(SEND|RECV)"
278
+ ```
data/CLAUDE.md ADDED
@@ -0,0 +1,242 @@
1
+ # Puppeteer-Ruby Development Guide
2
+
3
+ > **IMPORTANT: Spec Migration Tracking**
4
+ >
5
+ > Test porting from Node.js Puppeteer to Ruby RSpec is tracked in **[CLAUDE/spec_migration_plans.md](./CLAUDE/spec_migration_plans.md)**.
6
+ >
7
+ > - Before porting tests: Check the migration plan for priorities and status
8
+ > - After porting tests: Update the migration plan to reflect progress
9
+ > - This file must be kept up-to-date with all spec migration work
10
+
11
+ This document provides essential guidance for AI agents working on the puppeteer-ruby codebase.
12
+
13
+ ## Project Overview
14
+
15
+ puppeteer-ruby is a Ruby port of [Puppeteer](https://pptr.dev/), the Node.js browser automation library. It uses the Chrome DevTools Protocol (CDP) to automate Chrome/Chromium browsers.
16
+
17
+ ### Core Principles
18
+
19
+ 1. **CDP Protocol Focus**: All browser automation is done via CDP
20
+ 2. **Chrome Specialization**: Focused on Chrome/Chromium automation
21
+ 3. **API Compatibility**: Follow Puppeteer's API design closely, but use Ruby idioms
22
+
23
+ ## Quick Reference
24
+
25
+ ### Running Tests
26
+
27
+ ```bash
28
+ # Run all tests
29
+ bundle exec rspec
30
+
31
+ # Run specific test file
32
+ bundle exec rspec spec/integration/page_spec.rb
33
+
34
+ # Run in debug mode (non-headless)
35
+ DEBUG=1 bundle exec rspec spec/integration/page_spec.rb
36
+ ```
37
+
38
+ > **Note for Codex CLI**: When executing RSpec from Codex CLI, always use `rbenv exec`:
39
+ > ```bash
40
+ > rbenv exec bundle exec rspec spec/integration/click_spec.rb
41
+ > ```
42
+
43
+ ### Key Environment Variables
44
+
45
+ | Variable | Description |
46
+ |----------|-------------|
47
+ | `PUPPETEER_EXECUTABLE_PATH_RSPEC` | Custom browser executable path |
48
+ | `PUPPETEER_CHANNEL_RSPEC` | Chrome channel (e.g., `chrome`, `chrome-beta`) |
49
+ | `DEBUG` | Set to `1` for debug output |
50
+ | `PUPPETEER_NO_SANDBOX_RSPEC` | Add `--no-sandbox` flag (for containers) |
51
+
52
+ ### Code Quality
53
+
54
+ ```bash
55
+ # Run RuboCop
56
+ bundle exec rubocop
57
+
58
+ # Auto-fix RuboCop issues
59
+ bundle exec rubocop -a
60
+
61
+ # Run Steep type check
62
+ bundle exec steep check
63
+ ```
64
+
65
+ ## Architecture
66
+
67
+ The codebase follows a straightforward architecture:
68
+
69
+ ```
70
+ lib/puppeteer/
71
+ ├── puppeteer.rb # Main entry point (Puppeteer.launch, Puppeteer.connect)
72
+ ├── browser.rb # Browser instance management
73
+ ├── browser_context.rb # Incognito/default context
74
+ ├── page.rb # Page API (main user-facing class)
75
+ ├── frame.rb # Frame handling
76
+ ├── element_handle.rb # DOM element operations
77
+ ├── js_handle.rb # JavaScript object handles
78
+ ├── connection.rb # WebSocket connection to browser
79
+ ├── cdp_session.rb # CDP session management
80
+ ├── keyboard.rb # Keyboard input simulation
81
+ ├── mouse.rb # Mouse input simulation
82
+ └── ...
83
+ ```
84
+
85
+ ### Key Components
86
+
87
+ - **Connection**: Manages WebSocket connection to the browser's DevTools
88
+ - **CDPSession**: Sends CDP commands and receives events
89
+ - **FrameManager**: Tracks frames and their execution contexts
90
+ - **NetworkManager**: Handles request interception and network events
91
+ - **LifecycleWatcher**: Waits for navigation events (load, DOMContentLoaded, etc.)
92
+
93
+ ## Code Standards
94
+
95
+ ### Ruby Version & Style
96
+
97
+ - Minimum Ruby version: 3.2
98
+ - Follow RuboCop rules defined in `.rubocop.yml`
99
+ - Use explicit keyword arguments for public APIs
100
+
101
+ ### API Naming Conventions
102
+
103
+ JavaScript Puppeteer methods use camelCase, Ruby methods use snake_case:
104
+
105
+ | Puppeteer (JS) | puppeteer-ruby |
106
+ |----------------|----------------|
107
+ | `page.waitForSelector()` | `page.wait_for_selector` |
108
+ | `page.setContent()` | `page.content=` or `page.set_content` |
109
+ | `element.boundingBox()` | `element.bounding_box` |
110
+ | `browser.newPage()` | `browser.new_page` |
111
+
112
+ ### Error Classes
113
+
114
+ All custom errors inherit from `Puppeteer::Error`:
115
+
116
+ ```ruby
117
+ module Puppeteer
118
+ class Error < StandardError; end
119
+ class TimeoutError < Error; end
120
+ class FrameNotFoundError < Error; end
121
+ # etc.
122
+ end
123
+ ```
124
+
125
+ ## Testing Strategy
126
+
127
+ ### Test Types
128
+
129
+ - **Unit tests**: `spec/puppeteer/` - Test individual classes without browser
130
+ - **Integration tests**: `spec/integration/` - Test with real browser
131
+
132
+ ### Integration Test Setup
133
+
134
+ Integration tests use RSpec metadata:
135
+
136
+ ```ruby
137
+ RSpec.describe 'Page', type: :puppeteer do
138
+ it 'navigates to a page' do
139
+ page.goto('https://example.com')
140
+ expect(page.title).to eq('Example Domain')
141
+ end
142
+ end
143
+ ```
144
+
145
+ The `type: :puppeteer` metadata automatically:
146
+ - Launches Chrome before each test
147
+ - Provides `page` helper method
148
+ - Closes browser after test
149
+
150
+ ## Porting from Puppeteer
151
+
152
+ When implementing new features, reference the TypeScript Puppeteer source:
153
+
154
+ 1. Find the corresponding TypeScript file in [puppeteer/puppeteer](https://github.com/puppeteer/puppeteer)
155
+ 2. Understand the CDP calls being made
156
+ 3. Implement in Ruby following existing patterns
157
+ 4. Port the relevant tests
158
+ 5. Update `docs/api_coverage.md`
159
+
160
+ ### CDP Command Pattern
161
+
162
+ ```ruby
163
+ # TypeScript Puppeteer
164
+ await this._client.send('Page.navigate', { url });
165
+
166
+ # Ruby equivalent
167
+ @client.send_message('Page.navigate', url: url)
168
+ ```
169
+
170
+ ## Concurrency Model
171
+
172
+ ### Current State (socketry/async)
173
+
174
+ puppeteer-ruby uses Fiber-based concurrency with `socketry/async` (version 2.35.1+):
175
+
176
+ - `Async::Promise` - For async operations that complete later
177
+ - `Async` blocks - For running operations in Fiber context
178
+ - `Puppeteer::AsyncUtils.await_promise_all` - For waiting on multiple promises
179
+ - `Puppeteer::AsyncUtils.await_promise_race` - For waiting on any of multiple promises
180
+ - `Puppeteer::ReactorRunner` - Dedicated Async reactor thread for sync API wrapping
181
+ - Standard `Hash` with `Mutex` - For thread-safe callbacks and sessions
182
+
183
+ ### Key Components
184
+
185
+ | Component | Purpose |
186
+ |-----------|---------|
187
+ | `Async::Promise` | Promise that can be resolved/rejected later |
188
+ | `AsyncUtils.await_promise_all` | Wait for multiple async operations |
189
+ | `AsyncUtils.await_promise_race` | Wait for first of multiple operations |
190
+ | `AsyncUtils.async_timeout` | Timeout wrapper for async operations |
191
+ | `ReactorRunner` | Bridges sync API calls into Async reactor |
192
+
193
+ ### Async Method Pattern
194
+
195
+ ```ruby
196
+ class Page
197
+ # Synchronous version (blocks until complete)
198
+ def wait_for_selector(selector, timeout: nil)
199
+ # ...
200
+ end
201
+
202
+ # Async version (returns Async task)
203
+ define_async_method :async_wait_for_selector
204
+ end
205
+ ```
206
+
207
+ ## Development Workflow
208
+
209
+ ### Before Submitting Changes
210
+
211
+ 1. Run tests: `bundle exec rspec`
212
+ 2. Run RuboCop: `bundle exec rubocop`
213
+ 3. Run type check: `bundle exec steep check`
214
+ 4. Update `docs/api_coverage.md` if adding new API methods
215
+
216
+ ### Pull Request Guidelines
217
+
218
+ - **Language**: All Pull Requests must be written in English (title, description, and commit messages)
219
+ - **`gh` command**: Available for exploring GitHub issues, codes, or creating pull requests
220
+ - **PR Title**: Use a clear, concise title describing the change
221
+ - **PR Description**: Include a summary of changes and testing done
222
+
223
+ ### Version Updates
224
+
225
+ When updating the version, **both files must be updated**:
226
+ - `lib/puppeteer/version.rb` - The canonical version constant
227
+ - `docs/api_coverage.md` - The version displayed in documentation
228
+
229
+ GitHub Actions automatically publishes to RubyGems when a version tag is pushed. Tag format is the version number without `v` prefix (e.g., `0.50.0.alpha3`, not `v0.50.0.alpha3`).
230
+
231
+ ## Detailed Documentation
232
+
233
+ For in-depth information on specific topics, see the [CLAUDE/](./CLAUDE/) directory:
234
+
235
+ - [README.md](./CLAUDE/README.md) - Documentation index
236
+ - [architecture.md](./CLAUDE/architecture.md) - Detailed architecture overview
237
+ - [testing.md](./CLAUDE/testing.md) - Testing strategies and patterns
238
+ - [cdp_protocol.md](./CLAUDE/cdp_protocol.md) - CDP protocol details
239
+ - [concurrency.md](./CLAUDE/concurrency.md) - Concurrency patterns
240
+ - [porting_puppeteer.md](./CLAUDE/porting_puppeteer.md) - Guide for porting from TypeScript
241
+ - [rbs_type_checking.md](./CLAUDE/rbs_type_checking.md) - RBS type annotations and Steep type checking
242
+ - [spec_migration_plans.md](./CLAUDE/spec_migration_plans.md) - Test migration tracking and progress
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/puppeteer-ruby.svg)](https://badge.fury.io/rb/puppeteer-ruby)
2
2
 
3
+ > [!IMPORTANT]
4
+ > The `main` branch is currently under **HEAVY DEVELOPMENT** for increased stability.
5
+ > If you need the latest stable release, please refer to the [ref-2025 tag](https://github.com/YusukeIwaki/puppeteer-ruby/tree/ref-2025).
6
+
3
7
  # Puppeteer in Ruby
4
8
 
5
9
  A Ruby port of [puppeteer](https://pptr.dev/).
@@ -228,6 +232,10 @@ end
228
232
 
229
233
  https://yusukeiwaki.github.io/puppeteer-ruby-docs/
230
234
 
235
+ ## Note on Firefox
236
+
237
+ This library supports **Chrome/Chromium only**. For Firefox automation, consider using [playwright-ruby-client](https://github.com/YusukeIwaki/playwright-ruby-client) or [puppeteer-bidi](https://github.com/YusukeIwaki/puppeteer-bidi).
238
+
231
239
  ## Contributing
232
240
 
233
241
  Bug reports and pull requests are welcome on GitHub at https://github.com/YusukeIwaki/puppeteer-ruby.
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
1
  require 'bundler/gem_tasks'
2
+
3
+ desc 'Generate RBS files with rbs-inline'
4
+ task :rbs do
5
+ sh 'bundle', 'exec', 'rbs-inline', '--output=sig', 'lib'
6
+ end
7
+
8
+ Rake::Task[:build].enhance([:rbs])
data/Steepfile ADDED
@@ -0,0 +1,28 @@
1
+ # Steepfile for type checking
2
+
3
+ target :lib do
4
+ signature "sig"
5
+
6
+ check "lib"
7
+
8
+ # Standard library
9
+ library "base64"
10
+ library "json"
11
+ library "net-http"
12
+ library "uri"
13
+
14
+ configure_code_diagnostics do |hash|
15
+ hash[Steep::Diagnostic::Ruby::UnannotatedEmptyCollection] = :hint
16
+ hash[Steep::Diagnostic::Ruby::UnknownConstant] = :hint
17
+ hash[Steep::Diagnostic::Ruby::NoMethod] = :hint
18
+ hash[Steep::Diagnostic::Ruby::UnresolvedOverloading] = :hint
19
+ hash[Steep::Diagnostic::Ruby::IncompatibleAssignment] = :hint
20
+ hash[Steep::Diagnostic::Ruby::ArgumentTypeMismatch] = :hint
21
+ hash[Steep::Diagnostic::Ruby::ReturnTypeMismatch] = :hint
22
+ hash[Steep::Diagnostic::Ruby::BlockTypeMismatch] = :hint
23
+ hash[Steep::Diagnostic::Ruby::BreakTypeMismatch] = :hint
24
+ hash[Steep::Diagnostic::Ruby::ImplicitBreakValueMismatch] = :hint
25
+ hash[Steep::Diagnostic::Ruby::UnexpectedBlockGiven] = :hint
26
+ hash[Steep::Diagnostic::Ruby::UnexpectedPositionalArgument] = :hint
27
+ end
28
+ end