e2e 0.3.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 803c14bd6d5868f7ae89a2af6e67da28be4fa3a8fc48249a0a60672fad495c3c
4
+ data.tar.gz: 5e51d72904f0ccb1d316f753e4fbd766957de8538ce804a8a8bf2a8ae26f911c
5
+ SHA512:
6
+ metadata.gz: 98cd206b7dc00293712b48a93d5ff732d01cf39630ebfbe2d0a105bb7f9d34a0efe59c8d16d93149774ed76709450d925e58eb376669f11cd3257723a82852e3
7
+ data.tar.gz: febfd9530d491c8c2ec6b272040833a5fc2d5c4f3fc49cd8eb3c4920294f11ef44451216222aa4d4646b388f66b2e32c9d424d921e335fbe852c99437dd46111
data/Appraisals ADDED
@@ -0,0 +1,15 @@
1
+ appraise "rails-7.0" do
2
+ gem "rails", "~> 7.0.0"
3
+ end
4
+
5
+ appraise "rails-7.1" do
6
+ gem "rails", "~> 7.1.0"
7
+ end
8
+
9
+ appraise "rails-7.2" do
10
+ gem "rails", "~> 7.2.0"
11
+ end
12
+
13
+ appraise "rails-8.0" do
14
+ gem "rails", "~> 8.0.0"
15
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,54 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.3.2] - 2026-02-05
11
+
12
+ ### Fixed
13
+
14
+ - `Playwright::TargetClosedError` on CI environments without X-server by only enabling debug console in headed mode
15
+ - `pause` now raises a clear error when called in headless mode instead of failing silently
16
+
17
+ ## [0.3.1] - 2026-02-05
18
+
19
+ ### Fixed
20
+
21
+ - `uninitialized constant RSpec::Matchers` error when loading the gem in environments where RSpec is only partially initialized (e.g., via `Bundler.require`)
22
+ - Matchers are now only defined if `RSpec::Matchers` is actually present
23
+ - Matchers are no longer automatically loaded by `require "e2e"`; they are now explicitly loaded via `require "e2e/rspec"`
24
+
25
+ ## [0.3.0] - 2026-02-05
26
+
27
+ ### Added
28
+
29
+ - Custom RSpec matchers: `have_class`, `have_text`/`have_content`, `have_value`, `have_attribute`, `be_visible`, `be_checked`, `be_disabled`/`be_enabled`
30
+ - Element API methods: `classes`, `has_class?`, `visible?`, `[]`, `value`, `checked?`, `disabled?`, `enabled?`
31
+ - Improved debugging documentation and fixed `pause` helper
32
+
33
+ ## [0.2.0] - 2026-02-05
34
+
35
+ ### Added
36
+
37
+ - Browser switching support for Chromium, Firefox, and WebKit via `E2E.config.browser_type`
38
+ - `E2E.reset_session!` for dynamic session management
39
+ - `rails g e2e:install` generator with test framework detection (RSpec/Minitest) and RuboCop config injection
40
+ - `rails g e2e:test` generator for scaffolding test files
41
+ - Minitest support via `E2E::Minitest::TestCase`
42
+ - RuboCop integration with automatic `inherit_gem` injection
43
+ - `pause` helper for Playwright Inspector
44
+
45
+ ## [0.1.0] - 2026-02-05
46
+
47
+ ### Added
48
+
49
+ - Initial release of `e2e` gem, a unified testing framework wrapper around Playwright
50
+ - Playwright driver implementation using `playwright-ruby-client` (IPC/Pipes)
51
+ - Capybara-like DSL: `visit`, `click_button`, `click_link`, `fill_in`, `check`, `uncheck`, `attach_file`, `find`, `all`
52
+ - `E2E.enable_shared_connection!` for fast transactional tests in Rails
53
+ - Rack application booting via `E2E.config.app`
54
+ - Basic RSpec integration (`type: :e2e`)
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Alexey Poimtsev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,327 @@
1
+ # E2E
2
+
3
+ **Unified, high-performance E2E testing framework for Ruby.**
4
+
5
+ `e2e` is a modern wrapper around **Playwright**, designed to bring the elegance of Capybara and the speed of raw browser automation together.
6
+
7
+ [![Gem Version](https://badge.fury.io/rb/e2e.svg)](https://badge.fury.io/rb/e2e)
8
+ [![Build Status](https://github.com/alec-c4/e2e/actions/workflows/main.yml/badge.svg)](https://github.com/alec-c4/e2e/actions)
9
+
10
+ ## Why E2E?
11
+
12
+ - **⚡️ Blazing Fast:** Uses direct IPC (Pipes) to communicate with the browser, avoiding HTTP overhead.
13
+ - **🧩 Plug & Play:** Zero configuration for most Rails apps. Includes a generator.
14
+ - **💎 Clean DSL:** Idiomatic Ruby API (`click_button`, `find`, `visit`) that feels like home.
15
+ - **🚀 Modern Engine:** Powered by Microsoft Playwright (WebKit, Firefox, Chromium).
16
+ - **🛠 Escape Hatch:** Direct access to the `native` Playwright object for **any** complex scenario.
17
+ - **🔄 Shared Connection:** Built-in support for sharing DB connections between test and app threads (transactional tests support).
18
+ - **👮‍♀️ Lint Friendly:** Includes auto-configuration for RuboCop to respect E2E testing patterns.
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's `Gemfile`:
23
+
24
+ ```ruby
25
+ group :test do
26
+ gem "e2e"
27
+ end
28
+ ```
29
+
30
+ And then execute:
31
+
32
+ ```bash
33
+ bundle install
34
+ npx playwright install # Install browser binaries
35
+ ```
36
+
37
+ ### Rails Setup
38
+
39
+ Run the generator to create the helper file:
40
+
41
+ ```bash
42
+ rails g e2e:install
43
+ ```
44
+
45
+ This will create `spec/e2e_helper.rb` (for RSpec) or `test/e2e_helper.rb` (for Minitest) and configure your `.rubocop.yml`.
46
+
47
+ ## RuboCop Integration
48
+
49
+ `e2e` comes with a built-in RuboCop configuration that relaxes strict RSpec rules (like `DescribeClass` or `ExampleLength`) which are often not suitable for high-level E2E tests.
50
+
51
+ The generator adds this to your `.rubocop.yml` automatically:
52
+
53
+ ```yaml
54
+ inherit_gem:
55
+ e2e: config/rubocop.yml
56
+ ```
57
+
58
+ This will apply the following changes to all files in `spec/e2e/` and `test/e2e/`:
59
+
60
+ - Disable `RSpec/DescribeClass` and `RSpec/DescribeMethod`.
61
+ - Disable `RSpec/ExampleLength` and `RSpec/MultipleExpectations`.
62
+ - Increase `RSpec/NestedGroups` allowance.
63
+
64
+ ## Usage
65
+
66
+ You can generate a new test using:
67
+
68
+ ```bash
69
+ rails g e2e:test UserLogin
70
+ ```
71
+
72
+ ### RSpec Example
73
+
74
+ Write your tests in `spec/e2e/`.
75
+
76
+ ```ruby
77
+ # spec/e2e/login_spec.rb
78
+ require "e2e_helper"
79
+
80
+ RSpec.describe "User Login", type: :e2e do
81
+ it "signs in successfully" do
82
+ visit "/login"
83
+
84
+ fill_in "Email", with: "user@example.com"
85
+ fill_in "Password", with: "password"
86
+ click_button "Sign In"
87
+
88
+ expect(page.body).to include("Welcome, User!")
89
+ end
90
+ end
91
+ ```
92
+
93
+ ### Minitest Example
94
+
95
+ Write your tests in `test/e2e/`.
96
+
97
+ ```ruby
98
+ # test/e2e/login_test.rb
99
+ require "e2e_helper"
100
+
101
+ class UserLoginTest < E2E::Minitest::TestCase
102
+ def test_sign_in
103
+ visit "/login"
104
+
105
+ fill_in "Email", with: "user@example.com"
106
+ fill_in "Password", with: "password"
107
+ click_button "Sign In"
108
+
109
+ assert_includes page.body, "Welcome, User!"
110
+ end
111
+ end
112
+ ```
113
+
114
+ ## Debugging & UI Mode
115
+
116
+ By default, tests run in **headless** mode (no browser window). For debugging, you can run tests in **headful** mode to see what's happening.
117
+
118
+ ### Running with a visible browser
119
+
120
+ Set the `HEADLESS` environment variable to `false`:
121
+
122
+ ```bash
123
+ HEADLESS=false bundle exec rspec spec/e2e
124
+ ```
125
+
126
+ ### Pausing for Debugging
127
+
128
+ If the browser closes too fast, you can pause the execution to inspect the page or step through the test. This will open the **Playwright Inspector**.
129
+
130
+ Add this to your test:
131
+
132
+ ```ruby
133
+ it "debugs something" do
134
+ visit "/path"
135
+ pause # The test will stop here, and a debugger UI will open
136
+ click_button "Submit"
137
+ end
138
+ ```
139
+
140
+ Alternatively, you can just use `sleep(10)` if you want the browser to stay open for a few seconds without opening the inspector.
141
+
142
+ ### Automatic Screenshots
143
+
144
+ If a test fails in RSpec, a screenshot is automatically saved to `tmp/screenshots/` for quick investigation.
145
+
146
+ ### API Reference
147
+
148
+ #### Navigation
149
+
150
+ ```ruby
151
+ visit("/path")
152
+ current_url
153
+ ```
154
+
155
+ #### Interaction
156
+
157
+ ```ruby
158
+ click_button "Submit"
159
+ click_link "Read more"
160
+ click "#nav-menu" # CSS selector
161
+
162
+ fill_in "Email", with: "test@example.com"
163
+ check "I agree"
164
+ uncheck "Subscribe"
165
+ attach_file "#upload", "path/to/file.png"
166
+ ```
167
+
168
+ #### Finding Elements
169
+
170
+ ```ruby
171
+ find(".btn") # Returns E2E::Element
172
+ all("li") # Returns Array<E2E::Element>
173
+ find("button", text: "Save") # Filter by text
174
+ ```
175
+
176
+ #### Assertions & Matchers
177
+
178
+ ```ruby
179
+ # Check for content
180
+ expect(page.body).to include("Success")
181
+ expect(find(".alert")).to have_text("Success")
182
+ expect(find(".alert")).to have_content("Success") # Alias
183
+
184
+ # Check for classes
185
+ expect(find(".alert")).to have_class("success")
186
+ expect(find(".alert")).not_to have_class("error")
187
+
188
+ # Check visibility
189
+ expect(find("#modal")).to be_visible
190
+
191
+ # Check attributes & value
192
+ expect(find("input")).to have_value("test")
193
+ expect(find("div")).to have_attribute("data-id", "123")
194
+
195
+ # Check states
196
+ expect(find("#checkbox")).to be_checked
197
+ expect(find("button")).to be_disabled
198
+ expect(find("input")).to be_enabled
199
+ ```
200
+
201
+ #### Assertions & Data
202
+
203
+ ```ruby
204
+ page.body # Full HTML
205
+ evaluate("document.title") # Execute JS
206
+ save_screenshot("tmp/screen.png")
207
+ ```
208
+
209
+ ### 🔓 Native Access (The Escape Hatch)
210
+
211
+ We believe you shouldn't be limited by the wrapper. You can access the underlying `Playwright::Page` object at any time using `.native`.
212
+
213
+ **This means you have access to 100% of Playwright's features.**
214
+
215
+ #### 1. Keyboard Shortcuts
216
+
217
+ ```ruby
218
+ find("input").click
219
+ page.native.keyboard.press("Enter")
220
+ page.native.keyboard.press("Control+C")
221
+ ```
222
+
223
+ #### 2. Network Interception (Mocking)
224
+
225
+ ```ruby
226
+ page.native.route("**/api/users") do |route|
227
+ route.fulfill(status: 200, body: '{"users": []}')
228
+ end
229
+ ```
230
+
231
+ #### 3. Handling Dialogs (Alerts/Confirms)
232
+
233
+ ```ruby
234
+ page.native.on("dialog") do |dialog|
235
+ dialog.accept
236
+ end
237
+ click_button "Delete Account"
238
+ ```
239
+
240
+ #### 4. Emulation (Mobile/Dark Mode)
241
+
242
+ ```ruby
243
+ page.native.viewport_size = { width: 375, height: 667 }
244
+ page.native.emulate_media(color_scheme: 'dark')
245
+ ```
246
+
247
+ ## Performance: Transactional Tests
248
+
249
+ By default, Rails system tests run in a separate thread, meaning they can't see data created in a database transaction.
250
+ `e2e` solves this with **Shared Connection**.
251
+
252
+ Enable it in your `spec/e2e_helper.rb`:
253
+
254
+ ```ruby
255
+ E2E.enable_shared_connection!
256
+ ```
257
+
258
+ Now you can use fast transactional tests (standard RSpec behavior) instead of slow `DatabaseCleaner` truncation strategies.
259
+
260
+ ## Configuration
261
+
262
+ ```ruby
263
+ E2E.configure do |config|
264
+ config.driver = :playwright
265
+ config.browser_type = :chromium # Options: :chromium (default), :firefox, :webkit
266
+ config.headless = ENV.fetch("HEADLESS", "true") == "true"
267
+ config.app = Rails.application # Automatic Rack booting
268
+ end
269
+ ```
270
+
271
+ ### Multiple Browsers
272
+
273
+ One of the key advantages of Playwright is true cross-browser testing. You can easily switch engines:
274
+
275
+ - **Chromium:** Google Chrome, Microsoft Edge, etc.
276
+ - **Firefox:** Mozilla Firefox.
277
+ - **WebKit:** Safari, iOS browsers.
278
+
279
+ To test in Safari (WebKit):
280
+
281
+ ```ruby
282
+ E2E.configure { |config| config.browser_type = :webkit }
283
+ ```
284
+
285
+ Don't forget to install all browser binaries:
286
+
287
+ ```bash
288
+ npx playwright install
289
+ ```
290
+
291
+ ### Switching Browsers per Test (RSpec)
292
+
293
+ You can run specific tests in different browsers using metadata (requires simple setup in your helper).
294
+
295
+ First, update your `spec/e2e_helper.rb` to respect metadata:
296
+
297
+ ```ruby
298
+ RSpec.configure do |config|
299
+ config.before(:each) do |example|
300
+ browser = example.metadata[:browser]
301
+ if browser
302
+ E2E.config.browser_type = browser
303
+ E2E.reset_session! # Force new browser launch
304
+ end
305
+ end
306
+
307
+ config.after(:each) do
308
+ if E2E.config.browser_type != :chromium
309
+ E2E.config.browser_type = :chromium
310
+ E2E.reset_session!
311
+ end
312
+ end
313
+ end
314
+ ```
315
+
316
+ Then use it in your specs:
317
+
318
+ ```ruby
319
+ it "works in Safari", browser: :webkit do
320
+ visit "/"
321
+ expect(page.body).to include("Safari specific feature")
322
+ end
323
+ ```
324
+
325
+ ## License
326
+
327
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,31 @@
1
+ # Configuration for E2E tests
2
+ # This configuration relaxes strict RSpec rules for E2E scenarios.
3
+
4
+ RSpec/DescribeClass:
5
+ Exclude:
6
+ - 'spec/e2e/**/*'
7
+ - 'test/e2e/**/*'
8
+
9
+ RSpec/DescribeMethod:
10
+ Exclude:
11
+ - 'spec/e2e/**/*'
12
+ - 'test/e2e/**/*'
13
+
14
+ RSpec/SpecFilePathFormat:
15
+ Exclude:
16
+ - 'spec/e2e/**/*'
17
+ - 'test/e2e/**/*'
18
+
19
+ # E2E tests often involve multiple steps and checks
20
+ RSpec/ExampleLength:
21
+ Exclude:
22
+ - 'spec/e2e/**/*'
23
+ - 'test/e2e/**/*'
24
+
25
+ RSpec/MultipleExpectations:
26
+ Exclude:
27
+ - 'spec/e2e/**/*'
28
+ - 'test/e2e/**/*'
29
+
30
+ RSpec/NestedGroups:
31
+ Max: 4
@@ -0,0 +1,15 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "irb"
6
+ gem "rake", "~> 13.0"
7
+ gem "rspec", "~> 3.0"
8
+ gem "appraisal"
9
+ gem "lefthook"
10
+ gem "standard"
11
+ gem "rubocop-rspec"
12
+ gem "rubocop-performance"
13
+ gem "rails", "~> 7.0.0"
14
+
15
+ gemspec path: "../"